aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/ProjectHelperRepository.java
diff options
context:
space:
mode:
Diffstat (limited to 'framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/ProjectHelperRepository.java')
-rw-r--r--framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/ProjectHelperRepository.java337
1 files changed, 337 insertions, 0 deletions
diff --git a/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/ProjectHelperRepository.java b/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/ProjectHelperRepository.java
new file mode 100644
index 00000000..1dd44124
--- /dev/null
+++ b/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/ProjectHelperRepository.java
@@ -0,0 +1,337 @@
+/*
+ * 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.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.lang.reflect.Constructor;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.tools.ant.helper.ProjectHelper2;
+import org.apache.tools.ant.types.Resource;
+import org.apache.tools.ant.util.LoaderUtils;
+
+/**
+ * Repository of {@link ProjectHelper} found in the classpath or via
+ * some System properties.
+ *
+ * <p>See the ProjectHelper documentation in the manual.</p>
+ *
+ * @since Ant 1.8.0
+ */
+public class ProjectHelperRepository {
+
+ private static final String DEBUG_PROJECT_HELPER_REPOSITORY =
+ "ant.project-helper-repo.debug";
+
+ // The message log level is not accessible here because everything
+ // is instanciated statically
+ private static final boolean DEBUG =
+ "true".equals(System.getProperty(DEBUG_PROJECT_HELPER_REPOSITORY));
+
+ private static ProjectHelperRepository instance =
+ new ProjectHelperRepository();
+
+ private List<Constructor<? extends ProjectHelper>> helpers = new ArrayList<Constructor<? extends ProjectHelper>>();
+
+ private static Constructor<ProjectHelper2> PROJECTHELPER2_CONSTRUCTOR;
+
+ static {
+ try {
+ PROJECTHELPER2_CONSTRUCTOR = ProjectHelper2.class.getConstructor();
+ } catch (Exception e) {
+ // ProjectHelper2 must be available
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static ProjectHelperRepository getInstance() {
+ return instance;
+ }
+
+ private ProjectHelperRepository() {
+ collectProjectHelpers();
+ }
+
+ private void collectProjectHelpers() {
+ // First, try the system property
+ Constructor<? extends ProjectHelper> projectHelper = getProjectHelperBySystemProperty();
+ registerProjectHelper(projectHelper);
+
+ // A JDK1.3 'service' ( like in JAXP ). That will plug a helper
+ // automatically if in CLASSPATH, with the right META-INF/services.
+ try {
+ ClassLoader classLoader = LoaderUtils.getContextClassLoader();
+ if (classLoader != null) {
+ Enumeration<URL> resources =
+ classLoader.getResources(ProjectHelper.SERVICE_ID);
+ while (resources.hasMoreElements()) {
+ URL resource = resources.nextElement();
+ URLConnection conn = resource.openConnection();
+ conn.setUseCaches(false);
+ projectHelper =
+ getProjectHelperByService(conn.getInputStream());
+ registerProjectHelper(projectHelper);
+ }
+ }
+
+ InputStream systemResource =
+ ClassLoader.getSystemResourceAsStream(ProjectHelper.SERVICE_ID);
+ if (systemResource != null) {
+ projectHelper = getProjectHelperByService(systemResource);
+ registerProjectHelper(projectHelper);
+ }
+ } catch (Exception e) {
+ System.err.println("Unable to load ProjectHelper from service "
+ + ProjectHelper.SERVICE_ID + " ("
+ + e.getClass().getName()
+ + ": " + e.getMessage() + ")");
+ if (DEBUG) {
+ e.printStackTrace(System.err);
+ }
+ }
+ }
+
+ /**
+ * Register the specified project helper into the repository.
+ * <p>
+ * The helper will be added after all the already registered helpers, but
+ * before the default one (ProjectHelper2)
+ *
+ * @param helperClassName
+ * the fully qualified name of the helper
+ * @throws BuildException
+ * if the class cannot be loaded or if there is no constructor
+ * with no argument
+ * @since Ant 1.8.2
+ */
+ public void registerProjectHelper(String helperClassName)
+ throws BuildException {
+ registerProjectHelper(getHelperConstructor(helperClassName));
+ }
+
+ /**
+ * Register the specified project helper into the repository.
+ * <p>
+ * The helper will be added after all the already registered helpers, but
+ * before the default one (ProjectHelper2)
+ *
+ * @param helperClass
+ * the class of the helper
+ * @throws BuildException
+ * if there is no constructor with no argument
+ * @since Ant 1.8.2
+ */
+ public void registerProjectHelper(Class<? extends ProjectHelper> helperClass) throws BuildException {
+ try {
+ registerProjectHelper(helperClass.getConstructor());
+ } catch (NoSuchMethodException e) {
+ throw new BuildException("Couldn't find no-arg constructor in "
+ + helperClass.getName());
+ }
+ }
+
+ private void registerProjectHelper(Constructor<? extends ProjectHelper> helperConstructor) {
+ if (helperConstructor == null) {
+ return;
+ }
+ if (DEBUG) {
+ System.out.println("ProjectHelper "
+ + helperConstructor.getClass().getName() + " registered.");
+ }
+ helpers.add(helperConstructor);
+ }
+
+ private Constructor<? extends ProjectHelper> getProjectHelperBySystemProperty() {
+ String helperClass = System.getProperty(ProjectHelper.HELPER_PROPERTY);
+ try {
+ if (helperClass != null) {
+ return getHelperConstructor(helperClass);
+ }
+ } catch (SecurityException e) {
+ System.err.println("Unable to load ProjectHelper class \""
+ + helperClass + " specified in system property "
+ + ProjectHelper.HELPER_PROPERTY + " ("
+ + e.getMessage() + ")");
+ if (DEBUG) {
+ e.printStackTrace(System.err);
+ }
+ }
+ return null;
+ }
+
+ private Constructor<? extends ProjectHelper> getProjectHelperByService(InputStream is) {
+ try {
+ // This code is needed by EBCDIC and other strange systems.
+ // It's a fix for bugs reported in xerces
+ InputStreamReader isr;
+ try {
+ isr = new InputStreamReader(is, "UTF-8");
+ } catch (java.io.UnsupportedEncodingException e) {
+ isr = new InputStreamReader(is);
+ }
+ BufferedReader rd = new BufferedReader(isr);
+
+ String helperClassName = rd.readLine();
+ rd.close();
+
+ if (helperClassName != null && !"".equals(helperClassName)) {
+ return getHelperConstructor(helperClassName);
+ }
+ } catch (Exception e) {
+ System.out.println("Unable to load ProjectHelper from service "
+ + ProjectHelper.SERVICE_ID + " (" + e.getMessage() + ")");
+ if (DEBUG) {
+ e.printStackTrace(System.err);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Get the constructor with not argument of an helper from its class name.
+ * It'll first try the thread class loader, then Class.forName() will load
+ * from the same loader that loaded this class.
+ *
+ * @param helperClass
+ * The name of the class to create an instance of. Must not be
+ * <code>null</code>.
+ *
+ * @return the constructor of the specified class.
+ *
+ * @exception BuildException
+ * if the class cannot be found or if a constructor with no
+ * argument cannot be found.
+ */
+ private Constructor<? extends ProjectHelper> getHelperConstructor(String helperClass) throws BuildException {
+ ClassLoader classLoader = LoaderUtils.getContextClassLoader();
+ try {
+ Class<?> clazz = null;
+ if (classLoader != null) {
+ try {
+ clazz = classLoader.loadClass(helperClass);
+ } catch (ClassNotFoundException ex) {
+ // try next method
+ }
+ }
+ if (clazz == null) {
+ clazz = Class.forName(helperClass);
+ }
+ return clazz.asSubclass(ProjectHelper.class).getConstructor();
+ } catch (Exception e) {
+ throw new BuildException(e);
+ }
+ }
+
+ /**
+ * Get the helper that will be able to parse the specified build file. The helper
+ * will be chosen among the ones found in the classpath
+ *
+ * @return the first ProjectHelper that fit the requirement (never <code>null</code>).
+ */
+ public ProjectHelper getProjectHelperForBuildFile(Resource buildFile) throws BuildException {
+ for (Iterator<ProjectHelper> it = getHelpers(); it.hasNext();) {
+ ProjectHelper helper = it.next();
+ if (helper.canParseBuildFile(buildFile)) {
+ if (DEBUG) {
+ System.out.println("ProjectHelper "
+ + helper.getClass().getName()
+ + " selected for the build file "
+ + buildFile);
+ }
+ return helper;
+ }
+ }
+ throw new RuntimeException("BUG: at least the ProjectHelper2 should "
+ + "have supported the file " + buildFile);
+ }
+
+ /**
+ * Get the helper that will be able to parse the specified antlib. The helper
+ * will be chosen among the ones found in the classpath
+ *
+ * @return the first ProjectHelper that fit the requirement (never <code>null</code>).
+ */
+ public ProjectHelper getProjectHelperForAntlib(Resource antlib) throws BuildException {
+ for (Iterator<ProjectHelper> it = getHelpers(); it.hasNext();) {
+ ProjectHelper helper = it.next();
+ if (helper.canParseAntlibDescriptor(antlib)) {
+ if (DEBUG) {
+ System.out.println("ProjectHelper "
+ + helper.getClass().getName()
+ + " selected for the antlib "
+ + antlib);
+ }
+ return helper;
+ }
+ }
+ throw new RuntimeException("BUG: at least the ProjectHelper2 should "
+ + "have supported the file " + antlib);
+ }
+
+ /**
+ * Get an iterator on the list of project helpers configured. The iterator
+ * will always return at least one element as there will always be the
+ * default project helper configured.
+ *
+ * @return an iterator of {@link ProjectHelper}
+ */
+ public Iterator<ProjectHelper> getHelpers() {
+ return new ConstructingIterator(helpers.iterator());
+ }
+
+ private static class ConstructingIterator implements Iterator<ProjectHelper> {
+ private final Iterator<Constructor<? extends ProjectHelper>> nested;
+ private boolean empty = false;
+
+ ConstructingIterator(Iterator<Constructor<? extends ProjectHelper>> nested) {
+ this.nested = nested;
+ }
+
+ public boolean hasNext() {
+ return nested.hasNext() || !empty;
+ }
+
+ public ProjectHelper next() {
+ Constructor<? extends ProjectHelper> c;
+ if (nested.hasNext()) {
+ c = nested.next();
+ } else {
+ // last but not least, ant default project helper
+ empty = true;
+ c = PROJECTHELPER2_CONSTRUCTOR;
+ }
+ try {
+ return c.newInstance();
+ } catch (Exception e) {
+ throw new BuildException("Failed to invoke no-arg constructor"
+ + " on " + c.getName());
+ }
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException("remove is not supported");
+ }
+ }
+}