]> source.dussan.org Git - archiva.git/blob
3966de0358e7c9b42bb0eb3d2c1ff17ed23013e8
[archiva.git] /
1 package org.apache.maven.archiva.consumers.lucene;
2
3 /*
4  * Licensed to the Apache Software Foundation (ASF) under one
5  * or more contributor license agreements.  See the NOTICE file
6  * distributed with this work for additional information
7  * regarding copyright ownership.  The ASF licenses this file
8  * to you under the Apache License, Version 2.0 (the
9  * "License"); you may not use this file except in compliance
10  * with the License.  You may obtain a copy of the License at
11  *
12  *  http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing,
15  * software distributed under the License is distributed on an
16  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17  * KIND, either express or implied.  See the License for the
18  * specific language governing permissions and limitations
19  * under the License.
20  */
21
22 import org.apache.maven.archiva.consumers.AbstractMonitoredConsumer;
23 import org.apache.maven.archiva.consumers.ConsumerException;
24 import org.apache.maven.archiva.consumers.DatabaseUnprocessedArtifactConsumer;
25 import org.apache.maven.archiva.indexer.RepositoryContentIndex;
26 import org.apache.maven.archiva.indexer.RepositoryContentIndexFactory;
27 import org.apache.maven.archiva.indexer.RepositoryIndexException;
28 import org.apache.maven.archiva.indexer.bytecode.BytecodeRecord;
29 import org.apache.maven.archiva.model.ArchivaArtifact;
30 import org.apache.maven.archiva.repository.ManagedRepositoryContent;
31 import org.apache.maven.archiva.repository.RepositoryContentFactory;
32 import org.apache.maven.archiva.repository.RepositoryException;
33
34 import com.sun.org.apache.bcel.internal.classfile.ClassParser;
35 import com.sun.org.apache.bcel.internal.classfile.JavaClass;
36 import com.sun.org.apache.bcel.internal.classfile.Method;
37
38 import java.io.File;
39 import java.io.IOException;
40 import java.util.ArrayList;
41 import java.util.Enumeration;
42 import java.util.HashMap;
43 import java.util.List;
44 import java.util.Map;
45 import java.util.zip.ZipEntry;
46 import java.util.zip.ZipFile;
47
48 /**
49  * IndexJavaPublicMethodsConsumer 
50  *
51  *         <a href="mailto:oching@apache.org">Maria Odea Ching</a>
52  * @version $Id$
53  * 
54  * @plexus.component role="org.apache.maven.archiva.consumers.DatabaseUnprocessedArtifactConsumer"
55  *                   role-hint="index-public-methods"
56  *                   instantiation-strategy="per-lookup"
57  */
58 public class IndexJavaPublicMethodsConsumer
59     extends AbstractMonitoredConsumer
60     implements DatabaseUnprocessedArtifactConsumer
61 {
62     /**
63      * @plexus.configuration default-value="index-public-methods"
64      */
65     private String id;
66
67     /**
68      * @plexus.configuration default-value="Index the java public methods for Full Text Search."
69      */
70     private String description;
71     
72     /**
73      * @plexus.requirement role-hint="lucene"
74      */
75     private RepositoryContentIndexFactory repoIndexFactory;
76
77     /**
78      * @plexus.requirement
79      */
80     private RepositoryContentFactory repoFactory;
81     
82     private static final String CLASSES = "classes";
83     
84     private static final String METHODS = "methods";
85     
86     private List<String> includes = new ArrayList<String>();
87
88     public IndexJavaPublicMethodsConsumer()
89     {
90         includes.add( "jar" );
91         includes.add( "war" );
92         includes.add( "ear" );
93         includes.add( "zip" );
94         includes.add( "tar.gz" );
95         includes.add( "tar.bz2" );
96         includes.add( "car" );
97         includes.add( "sar" );
98         includes.add( "mar" );
99         includes.add( "rar" );
100     }
101     
102     public void beginScan()
103     {
104         // TODO Auto-generated method stubx        
105     }
106
107     public void completeScan()
108     {
109         // TODO Auto-generated method stub
110
111     }
112
113     public List<String> getIncludedTypes()
114     {   
115         return includes;
116     }
117
118     public void processArchivaArtifact( ArchivaArtifact artifact )
119         throws ConsumerException
120     {   
121         try
122         {
123             ManagedRepositoryContent repoContent =
124                 repoFactory.getManagedRepositoryContent( artifact.getModel().getRepositoryId() );    
125             File file = new File( repoContent.getRepoRoot(), repoContent.toPath( artifact ) );
126             
127             if( file.getAbsolutePath().endsWith( ".jar" ) || file.getAbsolutePath().endsWith( ".war" ) || 
128                     file.getAbsolutePath().endsWith( ".ear" ) || file.getAbsolutePath().endsWith( ".zip" ) || 
129                     file.getAbsolutePath().endsWith( ".tar.gz" ) || file.getAbsolutePath().endsWith( ".tar.bz2" ) ||
130                     file.getAbsolutePath().endsWith( ".car" ) || file.getAbsolutePath().endsWith( ".sar" ) ||
131                     file.getAbsolutePath().endsWith( ".mar" ) || file.getAbsolutePath().endsWith( ".rar" ) )
132             {            
133                 if( file.exists() )
134                 {
135                     List<String> files = readFilesInArchive( file );
136                     Map<String, List<String>> mapOfClassesAndMethods =
137                         getPublicClassesAndMethodsFromFiles( file.getAbsolutePath(), files );
138                     
139                     // NOTE: what about public variables? should these be indexed too?
140                     RepositoryContentIndex bytecodeIndex = repoIndexFactory.createBytecodeIndex( repoContent.getRepository() );
141                     
142                     artifact.getModel().setRepositoryId( repoContent.getId() );
143                     
144                     BytecodeRecord bytecodeRecord = new BytecodeRecord();
145                     bytecodeRecord.setFilename( file.getName() );
146                     bytecodeRecord.setClasses( mapOfClassesAndMethods.get( CLASSES ) );
147                     bytecodeRecord.setFiles( files );
148                     bytecodeRecord.setMethods( mapOfClassesAndMethods.get( METHODS ) );
149                     bytecodeRecord.setArtifact( artifact );
150                     bytecodeRecord.setRepositoryId( repoContent.getId() );
151                     bytecodeIndex.modifyRecord( bytecodeRecord );
152                 }
153             }
154         } 
155         catch ( RepositoryException e )
156         {
157             throw new ConsumerException( "Can't run index cleanup consumer: " + e.getMessage() );
158         }
159         catch ( RepositoryIndexException e )
160         {
161             throw new ConsumerException( "Error encountered while adding artifact to index: " + e.getMessage() );
162         }
163         catch ( IOException e )
164         {
165             throw new ConsumerException( "Error encountered while getting file contents: " + e.getMessage() );
166         }
167     }
168
169     public String getDescription()
170     {
171         return description;
172     }
173
174     public String getId()
175     {
176         return id;
177     }
178
179     public boolean isPermanent()
180     {
181         return false;
182     }
183     
184     private List<String> readFilesInArchive( File file )
185         throws IOException
186     {
187         ZipFile zipFile = new ZipFile( file );
188         List<String> files;
189         
190         try
191         {
192             files = new ArrayList<String>( zipFile.size() );    
193             for ( Enumeration entries = zipFile.entries(); entries.hasMoreElements(); )
194             {
195                 ZipEntry entry = (ZipEntry) entries.nextElement();                
196                 files.add( entry.getName() );
197             }
198         }
199         finally
200         {
201             closeQuietly( zipFile );
202         }
203         return files;
204     }
205     
206     private void closeQuietly( ZipFile zipFile )
207     {
208         try
209         {
210             if ( zipFile != null )
211             {
212                 zipFile.close();
213             }
214         }
215         catch ( IOException e )
216         {
217             // ignored
218         }
219     }
220     
221     private static boolean isClass( String name )
222     {   
223         return name.endsWith( ".class" ) && name.lastIndexOf( "$" ) < 0;
224     }
225     
226     private Map<String, List<String>> getPublicClassesAndMethodsFromFiles( String zipFile, List<String> files )
227     {
228         Map<String, List<String>> map = new HashMap<String, List<String>>(); 
229         List<String> methods = new ArrayList<String>();
230         List<String> classes = new ArrayList<String>();
231                 
232         for( String file : files )
233         {               
234             if( isClass( file ) )
235             {
236                 try
237                 {
238                     ClassParser parser = new ClassParser( zipFile, file );
239                     JavaClass javaClass = parser.parse();
240                     
241                     if( javaClass.isPublic() )
242                     {
243                         classes.add( javaClass.getClassName() );
244                     }                    
245                     
246                     Method[] methodsArr = javaClass.getMethods();
247                     for( Method method : methodsArr )
248                     {   
249                         if( method.isPublic() )
250                         {                            
251                             methods.add( method.getName() );
252                         }
253                     }
254                 }
255                 catch ( IOException e )
256                 {   
257                     // ignore
258                 }
259             }
260         }
261         
262         map.put( CLASSES, classes );
263         map.put( METHODS, methods );
264         
265         return map;
266     }
267
268 }