📄 componenthelper.java
字号:
/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */package org.apache.tools.ant;import java.lang.reflect.Modifier;import java.lang.reflect.InvocationTargetException;import java.io.InputStream;import java.io.IOException;import java.io.File;import java.io.StringWriter;import java.io.PrintWriter;import java.util.Enumeration;import java.util.Hashtable;import java.util.HashSet;import java.util.Iterator;import java.util.Properties;import java.util.Set;import java.util.Stack;import java.util.List;import java.util.ArrayList;import org.apache.tools.ant.taskdefs.Typedef;import org.apache.tools.ant.taskdefs.Definer;import org.apache.tools.ant.launch.Launcher;import org.apache.tools.ant.util.FileUtils;/** * Component creation and configuration. * * The class is based around handing component * definitions in an AntTypeTable. * * The old task/type methods have been kept * for backward compatibly. * Project will just delegate its calls to this class. * * A very simple hook mechanism is provided that allows users to plug * in custom code. It is also possible to replace the default behavior * ( for example in an app embedding ant ) * * @since Ant1.6 */public class ComponentHelper { /** Map from component name to anttypedefinition */ private AntTypeTable antTypeTable; /** Map of tasks generated from antTypeTable */ private Hashtable taskClassDefinitions = new Hashtable(); /** flag to rebuild taskClassDefinitions */ private boolean rebuildTaskClassDefinitions = true; /** Map of types generated from antTypeTable */ private Hashtable typeClassDefinitions = new Hashtable(); /** flag to rebuild typeClassDefinitions */ private boolean rebuildTypeClassDefinitions = true; /** Set of namespaces that have been checked for antlibs */ private Set checkedNamespaces = new HashSet(); /** * Stack of antlib contexts used to resolve definitions while * processing antlib */ private Stack antLibStack = new Stack(); /** current antlib uri */ private String antLibCurrentUri = null; /** * this does not appear to be used anywhere in the Ant codebase * even via its accessors */ private ComponentHelper next; /** * Project that owns a component helper */ private Project project; /** * Error string when the file taskdefs/defaults.properties cannot be found */ private static final String ERROR_NO_TASK_LIST_LOAD = "Can't load default task list"; /** * Error string when the typedefs/defaults.properties cannot be found */ private static final String ERROR_NO_TYPE_LIST_LOAD = "Can't load default type list"; /** * reference under which we register ourselves with a project -{@value} */ public static final String COMPONENT_HELPER_REFERENCE = "ant.ComponentHelper"; /** * string used to control build.syspath policy {@value} */ private static final String BUILD_SYSCLASSPATH_ONLY = "only"; /** * special name of ant's property task -{@value}. There is some * contrived work here to enable this early. */ private static final String ANT_PROPERTY_TASK = "property"; // {tasks, types} private static Properties[] defaultDefinitions = new Properties[2]; /** * Find a project component for a specific project, creating * it if it does not exist. * @param project the project. * @return the project component for a specific project. */ public static ComponentHelper getComponentHelper(Project project) { if (project == null) { return null; } // Singleton for now, it may change ( per/classloader ) ComponentHelper ph = (ComponentHelper) project.getReference( COMPONENT_HELPER_REFERENCE); if (ph != null) { return ph; } ph = new ComponentHelper(); ph.setProject(project); project.addReference(COMPONENT_HELPER_REFERENCE, ph); return ph; } /** * Creates a new ComponentHelper instance. */ protected ComponentHelper() { } /** * Set the next chained component helper. * * @param next the next chained component helper. */ public void setNext(ComponentHelper next) { this.next = next; } /** * Get the next chained component helper. * * @return the next chained component helper. */ public ComponentHelper getNext() { return next; } /** * Sets the project for this component helper. * * @param project the project for this helper. */ public void setProject(Project project) { this.project = project; antTypeTable = new AntTypeTable(project); } /** * Used with creating child projects. Each child * project inherits the component definitions * from its parent. * @param helper the component helper of the parent project. */ public void initSubProject(ComponentHelper helper) { // add the types of the parent project AntTypeTable typeTable = helper.antTypeTable; for (Iterator i = typeTable.values().iterator(); i.hasNext();) { AntTypeDefinition def = (AntTypeDefinition) i.next(); antTypeTable.put(def.getName(), def); } // add the parsed namespaces of the parent project for (Iterator i = helper.checkedNamespaces.iterator(); i.hasNext();) { checkedNamespaces.add(i.next()); } } /** * Factory method to create the components. * * This should be called by UnknownElement. * * @param ue The Unknown Element creating this component. * @param ns Namespace URI. Also available as ue.getNamespace(). * @param componentType The component type, * Also available as ue.getComponentName(). * @return the created component. * @throws BuildException if an error occurs. */ public Object createComponent(UnknownElement ue, String ns, String componentType) throws BuildException { Object component = createComponent(componentType); if (component instanceof Task) { Task task = (Task) component; task.setLocation(ue.getLocation()); task.setTaskType(componentType); task.setTaskName(ue.getTaskName()); task.setOwningTarget(ue.getOwningTarget()); task.init(); } return component; } /** * Create an object for a component. * * @param componentName the name of the component, if * the component is in a namespace, the * name is prefixed with the namespace uri and ":". * @return the class if found or null if not. */ public Object createComponent(String componentName) { AntTypeDefinition def = getDefinition(componentName); return (def == null) ? null : def.create(project); } /** * Return the class of the component name. * * @param componentName the name of the component, if * the component is in a namespace, the * name is prefixed with the namespace uri and ":". * @return the class if found or null if not. */ public Class getComponentClass(String componentName) { AntTypeDefinition def = getDefinition(componentName); return (def == null) ? null : def.getExposedClass(project); } /** * Return the antTypeDefinition for a componentName. * @param componentName the name of the component. * @return the ant definition or null if not present. */ public AntTypeDefinition getDefinition(String componentName) { checkNamespace(componentName); return antTypeTable.getDefinition(componentName); } /** * This method is initialization code implementing the original ant component * loading from /org/apache/tools/ant/taskdefs/default.properties * and /org/apache/tools/ant/types/default.properties. */ public void initDefaultDefinitions() { initTasks(); initTypes(); } /** * Adds a new task definition to the project. * Attempting to override an existing definition with an * equivalent one (i.e. with the same classname) results in * a verbose log message. Attempting to override an existing definition * with a different one results in a warning log message. * * @param taskName The name of the task to add. * Must not be <code>null</code>. * @param taskClass The full name of the class implementing the task. * Must not be <code>null</code>. * * @exception BuildException if the class is unsuitable for being an Ant * task. An error level message is logged before * this exception is thrown. * * @see #checkTaskClass(Class) */ public void addTaskDefinition(String taskName, Class taskClass) { checkTaskClass(taskClass); AntTypeDefinition def = new AntTypeDefinition(); def.setName(taskName); def.setClassLoader(taskClass.getClassLoader()); def.setClass(taskClass); def.setAdapterClass(TaskAdapter.class); def.setClassName(taskClass.getName()); def.setAdaptToClass(Task.class); updateDataTypeDefinition(def); } /** * Checks whether or not a class is suitable for serving as Ant task. * Ant task implementation classes must be public, concrete, and have * a no-arg constructor. * * @param taskClass The class to be checked. * Must not be <code>null</code>. * * @exception BuildException if the class is unsuitable for being an Ant * task. An error level message is logged before * this exception is thrown. */ public void checkTaskClass(final Class taskClass) throws BuildException { if (!Modifier.isPublic(taskClass.getModifiers())) { final String message = taskClass + " is not public"; project.log(message, Project.MSG_ERR); throw new BuildException(message); } if (Modifier.isAbstract(taskClass.getModifiers())) { final String message = taskClass + " is abstract"; project.log(message, Project.MSG_ERR); throw new BuildException(message); } try { taskClass.getConstructor((Class[]) null); // don't have to check for public, since // getConstructor finds public constructors only. } catch (NoSuchMethodException e) { final String message = "No public no-arg constructor in " + taskClass; project.log(message, Project.MSG_ERR); throw new BuildException(message); } if (!Task.class.isAssignableFrom(taskClass)) { TaskAdapter.checkTaskClass(taskClass, project); } } /** * Returns the current task definition hashtable. The returned hashtable is * "live" and so should not be modified. * * @return a map of from task name to implementing class * (String to Class). */ public Hashtable getTaskDefinitions() { synchronized (taskClassDefinitions) { synchronized (antTypeTable) { if (rebuildTaskClassDefinitions) { taskClassDefinitions.clear(); for (Iterator i = antTypeTable.keySet().iterator(); i.hasNext();) { String name = (String) i.next(); Class clazz = antTypeTable.getExposedClass(name); if (clazz == null) { continue;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -