You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

ProjectHelperRepository.java 9.0 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. package org.apache.tools.ant;
  2. import java.io.BufferedReader;
  3. import java.io.File;
  4. import java.io.InputStream;
  5. import java.io.InputStreamReader;
  6. import java.lang.reflect.Constructor;
  7. import java.net.URL;
  8. import java.util.ArrayList;
  9. import java.util.Enumeration;
  10. import java.util.Iterator;
  11. import java.util.List;
  12. import org.apache.tools.ant.helper.ProjectHelper2;
  13. import org.apache.tools.ant.util.LoaderUtils;
  14. /**
  15. * Repository of {@link ProjectHelper} found in the classpath or via
  16. * some System properties.
  17. * <p>See the ProjectHelper documentation in the manual.</p>
  18. *
  19. * @since Ant 1.8.0
  20. */
  21. public class ProjectHelperRepository {
  22. private static final String DEBUG_PROJECT_HELPER_REPOSITORY =
  23. "ant.project-helper-repo.debug";
  24. // The message log level is not accessible here because everything
  25. // is instanciated statically
  26. private static final boolean DEBUG =
  27. "true".equals(System.getProperty(DEBUG_PROJECT_HELPER_REPOSITORY));
  28. private static ProjectHelperRepository instance =
  29. new ProjectHelperRepository();
  30. private List/* <Constructor> */ helpers = new ArrayList();
  31. private static final Class[] NO_CLASS = new Class[0];
  32. private static final Object[] NO_OBJECT = new Object[0];
  33. public static ProjectHelperRepository getInstance() {
  34. return instance;
  35. }
  36. private ProjectHelperRepository() {
  37. collectProjectHelpers();
  38. }
  39. private void collectProjectHelpers() {
  40. // First, try the system property
  41. ProjectHelper projectHelper = getProjectHelperBySystemProperty();
  42. registerProjectHelper(projectHelper);
  43. // A JDK1.3 'service' ( like in JAXP ). That will plug a helper
  44. // automatically if in CLASSPATH, with the right META-INF/services.
  45. try {
  46. ClassLoader classLoader = LoaderUtils.getContextClassLoader();
  47. if (classLoader != null) {
  48. Enumeration resources =
  49. classLoader.getResources(ProjectHelper.SERVICE_ID);
  50. while (resources.hasMoreElements()) {
  51. URL resource = (URL) resources.nextElement();
  52. projectHelper =
  53. getProjectHelperByService(resource.openStream());
  54. registerProjectHelper(projectHelper);
  55. }
  56. }
  57. InputStream systemResource =
  58. ClassLoader.getSystemResourceAsStream(ProjectHelper.SERVICE_ID);
  59. if (systemResource != null) {
  60. projectHelper = getProjectHelperByService(systemResource);
  61. registerProjectHelper(projectHelper);
  62. }
  63. } catch (Exception e) {
  64. System.err.println("Unable to load ProjectHelper from service "
  65. + ProjectHelper.SERVICE_ID + " ("
  66. + e.getClass().getName()
  67. + ": " + e.getMessage() + ")");
  68. if (DEBUG) {
  69. e.printStackTrace(System.err);
  70. }
  71. }
  72. // last but not least, ant default project helper
  73. projectHelper = new ProjectHelper2();
  74. registerProjectHelper(projectHelper);
  75. }
  76. private void registerProjectHelper(ProjectHelper projectHelper) {
  77. if (projectHelper == null) {
  78. return;
  79. }
  80. if (DEBUG) {
  81. System.out.println("ProjectHelper " +
  82. projectHelper.getClass().getName()
  83. + " registered.");
  84. }
  85. try {
  86. helpers.add(projectHelper.getClass().getConstructor(NO_CLASS));
  87. } catch (NoSuchMethodException nse) {
  88. // impossible to get here
  89. throw new BuildException("Couldn't find no-arg constructor in "
  90. + projectHelper.getClass().getName());
  91. }
  92. }
  93. private ProjectHelper getProjectHelperBySystemProperty() {
  94. String helperClass = System.getProperty(ProjectHelper.HELPER_PROPERTY);
  95. try {
  96. if (helperClass != null) {
  97. return newHelper(helperClass);
  98. }
  99. } catch (SecurityException e) {
  100. System.err.println("Unable to load ProjectHelper class \""
  101. + helperClass + " specified in system property "
  102. + ProjectHelper.HELPER_PROPERTY + " ("
  103. + e.getMessage() + ")");
  104. if (DEBUG) {
  105. e.printStackTrace(System.err);
  106. }
  107. }
  108. return null;
  109. }
  110. private ProjectHelper getProjectHelperByService(InputStream is) {
  111. try {
  112. // This code is needed by EBCDIC and other strange systems.
  113. // It's a fix for bugs reported in xerces
  114. InputStreamReader isr;
  115. try {
  116. isr = new InputStreamReader(is, "UTF-8");
  117. } catch (java.io.UnsupportedEncodingException e) {
  118. isr = new InputStreamReader(is);
  119. }
  120. BufferedReader rd = new BufferedReader(isr);
  121. String helperClassName = rd.readLine();
  122. rd.close();
  123. if (helperClassName != null && !"".equals(helperClassName)) {
  124. return newHelper(helperClassName);
  125. }
  126. } catch (Exception e) {
  127. System.out.println("Unable to load ProjectHelper from service "
  128. + ProjectHelper.SERVICE_ID + " (" + e.getMessage() + ")");
  129. if (DEBUG) {
  130. e.printStackTrace(System.err);
  131. }
  132. }
  133. return null;
  134. }
  135. /**
  136. * Creates a new helper instance from the name of the class. It'll
  137. * first try the thread class loader, then Class.forName() will
  138. * load from the same loader that loaded this class.
  139. *
  140. * @param helperClass
  141. * The name of the class to create an instance of. Must not be
  142. * <code>null</code>.
  143. *
  144. * @return a new instance of the specified class.
  145. *
  146. * @exception BuildException
  147. * if the class cannot be found or cannot be appropriate
  148. * instantiated.
  149. */
  150. private ProjectHelper newHelper(String helperClass) throws BuildException {
  151. ClassLoader classLoader = LoaderUtils.getContextClassLoader();
  152. try {
  153. Class clazz = null;
  154. if (classLoader != null) {
  155. try {
  156. clazz = classLoader.loadClass(helperClass);
  157. } catch (ClassNotFoundException ex) {
  158. // try next method
  159. }
  160. }
  161. if (clazz == null) {
  162. clazz = Class.forName(helperClass);
  163. }
  164. return ((ProjectHelper) clazz.newInstance());
  165. } catch (Exception e) {
  166. throw new BuildException(e);
  167. }
  168. }
  169. /**
  170. * Get the helper that will be able to parse the specified file. The helper
  171. * will be chosen among the ones found in the classpath
  172. *
  173. * @return the first ProjectHelper that fit the requirement (never <code>null</code>).
  174. */
  175. public ProjectHelper getProjectHelper(File buildFile) throws BuildException {
  176. Iterator it = getHelpers();
  177. while (it.hasNext()) {
  178. ProjectHelper helper = (ProjectHelper) it.next();
  179. if (helper.supportsBuildFile(buildFile)) {
  180. if (DEBUG) {
  181. System.out.println("ProjectHelper "
  182. + helper.getClass().getName()
  183. + " selected for the file "
  184. + buildFile);
  185. }
  186. return helper;
  187. }
  188. }
  189. throw new RuntimeException("BUG: at least the ProjectHelper2 should "
  190. + "have supported the file " + buildFile);
  191. }
  192. /**
  193. * Get an iterator on the list of project helpers configured. The iterator
  194. * will always return at least one element as there will always be the
  195. * default project helper configured.
  196. *
  197. * @return an iterator of {@link ProjectHelper}
  198. */
  199. public Iterator getHelpers() {
  200. return new ConstructingIterator(helpers.iterator());
  201. }
  202. private static class ConstructingIterator implements Iterator {
  203. private final Iterator nested;
  204. ConstructingIterator(Iterator nested) {
  205. this.nested = nested;
  206. }
  207. public boolean hasNext() {
  208. return nested.hasNext();
  209. }
  210. public Object next() {
  211. Constructor c = (Constructor) nested.next();
  212. try {
  213. return c.newInstance(NO_OBJECT);
  214. } catch (Exception e) {
  215. throw new BuildException("Failed to invoke no-arg constructor"
  216. + " on " + c.getName());
  217. }
  218. }
  219. public void remove() {
  220. throw new UnsupportedOperationException("remove is not supported");
  221. }
  222. }
  223. }