View Javadoc

1   package xjavadoc.tags;
2   
3   import java.util.List;
4   import java.util.ArrayList;
5   import java.util.Iterator;
6   import java.util.StringTokenizer;
7   import java.util.jar.Manifest;
8   import java.util.jar.JarFile;
9   import java.util.jar.Attributes;
10  import java.io.File;
11  import java.io.FileInputStream;
12  import java.io.IOException;
13  import java.net.URLClassLoader;
14  import java.net.URL;
15  import java.net.MalformedURLException;
16  import java.beans.BeanInfo;
17  import java.beans.Introspector;
18  import java.beans.IntrospectionException;
19  
20  import xjavadoc.XTagFactory;
21  import xjavadoc.XTag;
22  
23  /***
24   * This class introspects the classpath and registers tags.
25   *
26   * @author Aslak Hellesøy
27   * @version $Revision: 1.3 $
28   */
29  public final class TagIntrospector {
30  
31      public void registerTags(String classpath, XTagFactory tagFactory ) {
32          for( StringTokenizer st = new StringTokenizer(classpath, System.getProperty("path.separator") ); st.hasMoreTokens(); ) {
33              File classpathElement = new File( st.nextToken() );
34              if( classpathElement.exists() ) {
35                  List javaBeans = findJavaBeans( classpathElement );
36                  registerTags( javaBeans, tagFactory );
37              } else {
38                  System.out.println( classpathElement.getAbsolutePath() + " was on classpath, but doesn't exist." );
39              }
40          }
41      }
42  
43      private void registerTags(List javaBeans, XTagFactory tagFactory ) {
44          for( Iterator i = javaBeans.iterator(); i.hasNext(); ) {
45              Class javaBean = (Class) i.next();
46              if( XTag.class.isAssignableFrom( javaBean ) ) {
47                  try {
48                      BeanInfo beanInfo = Introspector.getBeanInfo( javaBean );
49  
50                      String tagName = beanInfo.getBeanDescriptor().getName();
51                      tagFactory.registerTagClass( tagName, javaBean );
52                  } catch( IntrospectionException e ) {
53                      System.out.println("No BeanInfo for " + javaBean.getName() );
54                  }
55              } else {
56                  // System.out.println( javaBean.getName() + " isn't a xjavadoc.XTag class. Ignoring" );
57              }
58          }
59      }
60  
61  
62      /***
63       * Returns a collection of classes that are Java Beans. The Java Bean
64       * classes are found by looking at the MANIFEST.MF file.
65       *
66       * @param dirOrJar the directory of jar file containing the classes.
67       * @return a Collection of {@link Class}.
68       */
69      private List findJavaBeans( File dirOrJar ) {
70          List result = new ArrayList();
71  
72          try {
73              ClassLoader classLoader = new URLClassLoader( new URL[] {dirOrJar.toURL()}, getClass().getClassLoader() );
74  
75              Manifest manifest = null;
76              if (dirOrJar.isDirectory()) {
77                  try {
78                      manifest = new Manifest(new FileInputStream(new File(dirOrJar, "META-INF/MANIFEST.MF")));
79                  } catch (IOException e) {
80                      // Ignore. There was no Manifest here.
81                  }
82              } else {
83                  try {
84                      JarFile jarFile = new JarFile(dirOrJar);
85  
86                      manifest = jarFile.getManifest();
87                  } catch (IOException e) {
88                      // Ignore. Wasn't a jar file.
89                  }
90              }
91  
92              if (manifest != null) {
93                  // Now loop over all entries in the Manifest.
94                  for (Iterator entryNames = manifest.getEntries().keySet().iterator(); entryNames.hasNext();) {
95                      String entryName = (String) entryNames.next();
96                      // Is it a class?
97                      if (entryName.endsWith(".class")) {
98                          Attributes attributes = manifest.getAttributes(entryName);
99                          // See if it's a java bean.
100                         String javaBean = attributes.getValue("Java-Bean");
101 
102                         if ("true".equalsIgnoreCase(javaBean)) {
103                             // OK. Get the BeanInfo.
104                             String className = entryName.substring(0, entryName.length() - 6);
105 
106                             className = className.replace('/', '.');
107 
108                             // Load the class
109                             try {
110                                 Class beanClass = classLoader.loadClass(className);
111                                 result.add( beanClass );
112                             } catch (ClassNotFoundException e) {
113                                 String errorMessage = className
114                                     + " was declared as a Java-Bean in the manifest, but the class was not found.";
115 
116                                 e.printStackTrace();
117                                 throw new IllegalStateException(errorMessage);
118                             }
119                         }
120                     }
121                 }
122             }
123             return result;
124         } catch( MalformedURLException e ) {
125             throw new IllegalStateException(e.getMessage());
126         }
127     }
128 }