View Javadoc
1   /*
2    * Copyright (C) 2007 the original author or authors.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5    * in compliance with the License. You may obtain a copy of the License at
6    * 
7    * http://www.apache.org/licenses/LICENSE-2.0
8    * 
9    * Unless required by applicable law or agreed to in writing, software distributed under the License
10   * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11   * or implied. See the License for the specific language governing permissions and limitations under
12   * the License.
13   */
14  
15  package org.codehaus.plexus.metadata;
16  
17  import java.io.File;
18  import java.net.MalformedURLException;
19  import java.net.URL;
20  import java.net.URLClassLoader;
21  import java.util.ArrayList;
22  import java.util.Collections;
23  import java.util.List;
24  import java.util.Map;
25  
26  import org.apache.maven.plugin.MojoExecutionException;
27  import org.codehaus.plexus.component.repository.ComponentDescriptor;
28  import org.codehaus.plexus.metadata.gleaner.AnnotationComponentGleaner;
29  import org.codehaus.plexus.metadata.gleaner.ClassComponentGleaner;
30  import org.codehaus.plexus.util.DirectoryScanner;
31  
32  /**
33   * Extracts {@link ComponentDescriptor} from class files.
34   * 
35   * @version $Id$
36   */
37  public class ClassComponentDescriptorExtractor
38      extends ComponentDescriptorExtractorSupport
39  {
40      private ClassComponentGleaner gleaner;
41  
42      public ClassComponentDescriptorExtractor( final ClassComponentGleaner gleaner )
43      {
44          this.gleaner = gleaner;
45      }
46  
47      public ClassComponentDescriptorExtractor()
48      {
49          this.gleaner = new AnnotationComponentGleaner();
50      }
51  
52      public List<ComponentDescriptor<?>> extract( MetadataGenerationRequest configuration, final ComponentDescriptor<?>[] roleDefaults )
53          throws Exception
54      {
55          // We don't have a reasonable default to use, so just puke up
56          if ( gleaner == null )
57          {
58              throw new IllegalStateException( "Gleaner is not bound" );
59          }
60  
61          if ( !configuration.classesDirectory.exists() )
62          {
63              return Collections.emptyList();
64          }
65  
66          if ( configuration.useContextClassLoader )
67          {
68              return extract( configuration.classesDirectory, Thread.currentThread().getContextClassLoader(), getDefaultsByRole( roleDefaults ) );
69          }
70          else
71          {
72              ClassLoader prev = Thread.currentThread().getContextClassLoader();
73              ClassLoader cl = createClassLoader( configuration.classpath );
74  
75              Thread.currentThread().setContextClassLoader( cl );
76  
77              try
78              {
79                  return extract( configuration.classesDirectory, cl, getDefaultsByRole( roleDefaults ) );
80              }
81              finally
82              {
83                  Thread.currentThread().setContextClassLoader( prev );
84              }
85          }
86      }
87  
88      private ClassLoader createClassLoader( final List<String> elements )
89          throws Exception
90      {
91          List<URL> list = new ArrayList<URL>();
92  
93          // Add the projects dependencies
94          for ( String filename : elements )
95          {
96              try
97              {
98                  list.add( new File( filename ).toURI().toURL() );
99              }
100             catch ( MalformedURLException e )
101             {
102                 throw new MojoExecutionException( "Invalid classpath entry: " + filename, e );
103             }
104         }
105 
106         URL[] urls = list.toArray( new URL[list.size()] );
107 
108         //getLogger().debug( "Classpath:" );
109         for (URL url : urls) {
110             //getLogger().debug( "    " + urls[i] );
111         }
112 
113         return new URLClassLoader( urls, null );
114     }
115 
116     private List<ComponentDescriptor<?>> extract( File classesDir, ClassLoader cl, Map<String, ComponentDescriptor<?>> defaultsByRole )
117         throws Exception
118     {
119         assert classesDir != null;
120         assert cl != null;
121         assert defaultsByRole != null;
122 
123         List<ComponentDescriptor<?>> descriptors = new ArrayList<ComponentDescriptor<?>>();
124 
125         DirectoryScanner scanner = new DirectoryScanner();
126         scanner.setBasedir( classesDir );
127         scanner.addDefaultExcludes();
128         scanner.setIncludes( new String[] { "**/*.class" } );
129 
130         //getLogger().debug( "Scanning for classes in: " + classesDir );
131 
132         scanner.scan();
133 
134         String[] includes = scanner.getIncludedFiles();
135 
136         for ( String include : includes )
137         {
138             String className = include.substring( 0, include.lastIndexOf( ".class" ) ).replace( '\\', '.' ).replace( '/', '.' );
139 
140             try
141             {
142                 // Class type = cl.loadClass( className );
143 
144                 ComponentDescriptor<?> descriptor = gleaner.glean( className, cl );
145 
146                 if ( descriptor != null )
147                 {
148                     applyDefaults( descriptor, defaultsByRole );
149 
150                     descriptors.add( descriptor );
151                 }
152             }
153             catch ( VerifyError e )
154             {
155                 // getLogger().error( "Failed to load class: " + className + "; cause: " + e );
156             }
157         }
158 
159         return descriptors;
160     }
161 }