1. /*
  2. * Copyright 2003-2004 The Apache Software Foundation
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package org.apache.commons.attributes.validation;
  17. import java.io.BufferedInputStream;
  18. import java.io.BufferedOutputStream;
  19. import java.io.File;
  20. import java.io.FileOutputStream;
  21. import java.io.InputStream;
  22. import java.io.PrintWriter;
  23. import java.io.PrintStream;
  24. import java.net.URL;
  25. import java.net.URLClassLoader;
  26. import java.util.ArrayList;
  27. import java.util.Collection;
  28. import java.util.Enumeration;
  29. import java.util.HashMap;
  30. import java.util.HashSet;
  31. import java.util.Iterator;
  32. import java.util.List;
  33. import java.util.jar.JarFile;
  34. import java.util.jar.JarEntry;
  35. import java.util.jar.JarOutputStream;
  36. import org.apache.commons.attributes.AttributeRepositoryClass;
  37. import org.apache.commons.attributes.Attributes;
  38. import org.apache.commons.attributes.AttributeUtil;
  39. import org.apache.commons.attributes.Indexed;
  40. import org.apache.tools.ant.AntClassLoader;
  41. import org.apache.tools.ant.BuildException;
  42. import org.apache.tools.ant.Task;
  43. import org.apache.tools.ant.types.FileSet;
  44. import org.apache.tools.ant.types.Path;
  45. /**
  46. * Ant task that validates attributes. Usage:
  47. *
  48. * <pre><code>
  49. * <taskdef resource="org/apache/commons/attributes/anttasks.properties"/>
  50. *
  51. * <attribute-validator jarFile="myclasses.jar">
  52. * <classpath>
  53. * ...
  54. * </classpath>
  55. * <validator class="my.Validator"/>
  56. * <validator class="my.other.Validator"/>
  57. * </attribute-validator>
  58. * </code></pre>
  59. *
  60. * The task will run the validator(s) with the classes the given jar file.
  61. */
  62. public class AttributeValidatorTask extends Task {
  63. private File jarFile;
  64. private List classes = new ArrayList ();
  65. private List validators = new ArrayList ();
  66. private Path classPath;
  67. private File baseName;
  68. private boolean inMaven = false;
  69. public static class Validator {
  70. private String className;
  71. public void setClass (String className) {
  72. this.className = className;
  73. }
  74. public String getClassName () {
  75. return className;
  76. }
  77. }
  78. public void setJarfile (File jarFile) {
  79. this.jarFile = jarFile;
  80. }
  81. public void setBaseName (File baseName) {
  82. inMaven = true;
  83. this.baseName = baseName;
  84. }
  85. public Path createClasspath () {
  86. this.classPath = new Path(project);
  87. return classPath;
  88. }
  89. public Validator createValidator () {
  90. Validator validator = new Validator ();
  91. validators.add (validator);
  92. return validator;
  93. }
  94. private static final String SUFFIX = "$__attributeRepository.class";
  95. protected void findJarFile () throws BuildException {
  96. File[] allFiles = baseName.getParentFile ().listFiles ();
  97. if (allFiles == null) {
  98. throw new BuildException ("Unable to find any file with base name " + baseName.getName ()
  99. + " in " + baseName.getParentFile ().getPath ());
  100. }
  101. long newestDate = 0;
  102. for (int i = 0; i < allFiles.length; i++) {
  103. String name = allFiles[i].getName ();
  104. if (name.startsWith (baseName.getName ()) && name.endsWith (".jar") &&
  105. allFiles[i].lastModified () > newestDate) {
  106. jarFile = allFiles[i];
  107. newestDate = allFiles[i].lastModified ();
  108. }
  109. }
  110. if (jarFile == null) {
  111. throw new BuildException ("Unable to find any file with base name " + baseName.getName ()
  112. + " in " + baseName.getParentFile ().getPath ());
  113. }
  114. }
  115. public void execute () throws BuildException {
  116. if (inMaven) {
  117. findJarFile ();
  118. }
  119. if (!jarFile.exists ()) {
  120. log ("Can't find " + jarFile.getPath ());
  121. return;
  122. }
  123. try {
  124. log ("Validating attributes in " + jarFile.getPath ());
  125. JarFile jar = new JarFile (jarFile);
  126. try {
  127. Enumeration enum = jar.entries ();
  128. while (enum.hasMoreElements ()) {
  129. JarEntry entry = (JarEntry) enum.nextElement ();
  130. if (!entry.isDirectory ()) {
  131. String className = entry.getName ();
  132. if (className.endsWith (SUFFIX)) {
  133. className = className.replace ('/', '.').replace ('\\', '.').substring (0, className.length () - SUFFIX.length ());
  134. classes.add (className);
  135. }
  136. }
  137. }
  138. } finally {
  139. jar.close ();
  140. }
  141. AntClassLoader cl = new AntClassLoader (this.getClass ().getClassLoader (), project, classPath, true);
  142. try {
  143. cl.addPathElement (jarFile.getPath ());
  144. HashSet classesToValidate = new HashSet ();
  145. Iterator attrs = classes.iterator ();
  146. while (attrs.hasNext ()) {
  147. String className = (String) attrs.next ();
  148. Class clazz = cl.loadClass (className);
  149. classesToValidate.add (clazz);
  150. }
  151. Iterator iter = validators.iterator ();
  152. while (iter.hasNext ()) {
  153. Validator validator = (Validator) iter.next ();
  154. Class validatorClass = cl.loadClass (validator.getClassName ());
  155. AttributeValidator attrValidator = (AttributeValidator) validatorClass.newInstance ();
  156. try {
  157. attrValidator.validate (classesToValidate);
  158. } catch (ValidationException ve) {
  159. throw new BuildException (ve.getInvalidClass () + " failed to validate: " + ve.getMessage ());
  160. }
  161. }
  162. } finally {
  163. cl.cleanup ();
  164. }
  165. } catch (BuildException be) {
  166. throw be;
  167. } catch (Exception e) {
  168. e.printStackTrace ();
  169. throw new BuildException (e.toString ());
  170. }
  171. }
  172. }