]> source.dussan.org Git - archiva.git/blob
54def2bfba31e448c6884b28d52f2358feee9641
[archiva.git] /
1 package org.apache.maven.repository.indexing;\r
2 \r
3 /*\r
4  * Copyright 2005-2006 The Apache Software Foundation.\r
5  *\r
6  * Licensed under the Apache License, Version 2.0 (the "License");\r
7  * you may not use this file except in compliance with the License.\r
8  * You may obtain a copy of the License at\r
9  *\r
10  *      http://www.apache.org/licenses/LICENSE-2.0\r
11  *\r
12  * Unless required by applicable law or agreed to in writing, software\r
13  * distributed under the License is distributed on an "AS IS" BASIS,\r
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
15  * See the License for the specific language governing permissions and\r
16  * limitations under the License.\r
17  */\r
18 \r
19 import org.apache.lucene.document.Document;\r
20 import org.apache.lucene.queryParser.ParseException;\r
21 import org.apache.lucene.search.Hits;\r
22 import org.apache.lucene.search.IndexSearcher;\r
23 import org.apache.maven.artifact.Artifact;\r
24 import org.apache.maven.artifact.factory.ArtifactFactory;\r
25 import org.apache.maven.artifact.repository.metadata.ArtifactRepositoryMetadata;\r
26 import org.apache.maven.artifact.repository.metadata.GroupRepositoryMetadata;\r
27 import org.apache.maven.artifact.repository.metadata.RepositoryMetadata;\r
28 import org.apache.maven.artifact.repository.metadata.SnapshotArtifactRepositoryMetadata;\r
29 import org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Reader;\r
30 import org.apache.maven.model.io.xpp3.MavenXpp3Reader;\r
31 import org.apache.maven.repository.indexing.query.Query;\r
32 import org.codehaus.plexus.logging.AbstractLogEnabled;\r
33 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;\r
34 \r
35 import java.io.File;\r
36 import java.io.FileInputStream;\r
37 import java.io.IOException;\r
38 import java.io.InputStream;\r
39 import java.io.InputStreamReader;\r
40 import java.net.MalformedURLException;\r
41 import java.util.ArrayList;\r
42 import java.util.Collections;\r
43 import java.util.HashMap;\r
44 import java.util.Iterator;\r
45 import java.util.List;\r
46 import java.util.Map;\r
47 import java.util.StringTokenizer;\r
48 \r
49 /**\r
50  * Implementation Class for searching through the index.\r
51  *\r
52  * @todo this is not a component, but extends ALE, meaning logging will throw an exception! -- should be a component\r
53  */\r
54 public class DefaultRepositoryIndexSearcher\r
55     extends AbstractLogEnabled\r
56     implements RepositoryIndexSearcher\r
57 {\r
58     protected RepositoryIndex index;\r
59 \r
60     private ArtifactFactory factory;\r
61 \r
62     private List artifactList;\r
63 \r
64     /**\r
65      * Constructor\r
66      *\r
67      * @param index the index object\r
68      */\r
69     protected DefaultRepositoryIndexSearcher( RepositoryIndex index, ArtifactFactory factory )\r
70     {\r
71         this.index = index;\r
72         this.factory = factory;\r
73     }\r
74 \r
75     /**\r
76      * @see RepositoryIndexSearcher#search(org.apache.maven.repository.indexing.query.Query)\r
77      */\r
78     public List search( Query query )\r
79         throws RepositoryIndexSearchException\r
80     {\r
81         artifactList = new ArrayList();\r
82         org.apache.lucene.search.Query luceneQuery;\r
83         try\r
84         {\r
85             luceneQuery = createLuceneQuery( query );\r
86         }\r
87         catch ( ParseException e )\r
88         {\r
89             throw new RepositoryIndexSearchException( "Unable to construct query: " + e.getMessage(), e );\r
90         }\r
91 \r
92         IndexSearcher searcher;\r
93         try\r
94         {\r
95             searcher = new IndexSearcher( index.getIndexPath() );\r
96         }\r
97         catch ( IOException e )\r
98         {\r
99             throw new RepositoryIndexSearchException( "Unable to open index: " + e.getMessage(), e );\r
100         }\r
101 \r
102         List docs;\r
103         try\r
104         {\r
105             Hits hits = searcher.search( luceneQuery );\r
106             docs = buildList( hits );\r
107         }\r
108         catch ( MalformedURLException e )\r
109         {\r
110             throw new RepositoryIndexSearchException( "Unable to search index: " + e.getMessage(), e );\r
111         }\r
112         catch ( IOException e )\r
113         {\r
114             throw new RepositoryIndexSearchException( "Unable to search index: " + e.getMessage(), e );\r
115         }\r
116         catch ( XmlPullParserException xe )\r
117         {\r
118             throw new RepositoryIndexSearchException( "Unable to parse metadata file: " + xe.getMessage(), xe );\r
119         }\r
120 \r
121         finally\r
122         {\r
123             try\r
124             {\r
125                 searcher.close();\r
126             }\r
127             catch ( IOException e )\r
128             {\r
129                 getLogger().error( "Unable to close index searcher", e );\r
130             }\r
131         }\r
132 \r
133         return docs;\r
134     }\r
135 \r
136     /**\r
137      * Method to create a lucene Query object by converting a prepared Query object\r
138      *\r
139      * @param query the prepared Query object to be converted into a lucene Query object\r
140      * @return a lucene Query object to represent the passed Query object\r
141      * @throws ParseException\r
142      */\r
143     private org.apache.lucene.search.Query createLuceneQuery( Query query )\r
144         throws ParseException\r
145     {\r
146         return query.createLuceneQuery( index );\r
147     }\r
148 \r
149     /**\r
150      * Create a list of artifact objects from the result set.\r
151      *\r
152      * @param hits the search result set\r
153      * @return List\r
154      * @throws IOException\r
155      */\r
156     private List buildList( Hits hits )\r
157         throws MalformedURLException, IOException, XmlPullParserException\r
158     {\r
159         for ( int i = 0; i < hits.length(); i++ )\r
160         {\r
161             Document doc = hits.doc( i );\r
162             artifactList.add( createSearchedObjectFromIndexDocument( doc ) );\r
163         }\r
164 \r
165         return artifactList;\r
166     }\r
167 \r
168     /**\r
169      * Method for creating the object to be returned for the search\r
170      *\r
171      * @param doc the index document where the object field values will be retrieved from\r
172      * @return Object\r
173      */\r
174     protected RepositoryIndexSearchHit createSearchedObjectFromIndexDocument( Document doc )\r
175         throws MalformedURLException, IOException, XmlPullParserException\r
176     {\r
177         RepositoryIndexSearchHit searchHit = null;\r
178 \r
179         // the document is of type artifact\r
180         if ( doc.get( RepositoryIndex.FLD_DOCTYPE ).equals( RepositoryIndex.ARTIFACT ) )\r
181         {\r
182             String groupId = doc.get( RepositoryIndex.FLD_GROUPID );\r
183             String artifactId = doc.get( RepositoryIndex.FLD_ARTIFACTID );\r
184             String version = doc.get( RepositoryIndex.FLD_VERSION );\r
185             String packaging = doc.get( RepositoryIndex.FLD_PACKAGING );\r
186             Artifact artifact = factory.createBuildArtifact( groupId, artifactId, version, packaging );\r
187 \r
188             artifact.setFile(\r
189                 new File( index.getRepository().getBasedir(), index.getRepository().pathOf( artifact ) ) );\r
190 \r
191             Map map = new HashMap();\r
192             map.put( RepositoryIndex.ARTIFACT, artifact );\r
193             map.put( RepositoryIndex.FLD_CLASSES, doc.get( RepositoryIndex.FLD_CLASSES ) );\r
194             map.put( RepositoryIndex.FLD_PACKAGES, doc.get( RepositoryIndex.FLD_PACKAGES ) );\r
195             map.put( RepositoryIndex.FLD_FILES, doc.get( RepositoryIndex.FLD_FILES ) );\r
196             map.put( RepositoryIndex.FLD_MD5, doc.get( RepositoryIndex.FLD_MD5 ) );\r
197             map.put( RepositoryIndex.FLD_SHA1, doc.get( RepositoryIndex.FLD_SHA1 ) );\r
198             map.put( RepositoryIndex.FLD_PACKAGING, doc.get( RepositoryIndex.FLD_PACKAGING ) );\r
199 \r
200             searchHit = new RepositoryIndexSearchHit( true, false, false );\r
201             searchHit.setObject( map );\r
202         }\r
203         // the document is of type model\r
204         else if ( doc.get( RepositoryIndex.FLD_DOCTYPE ).equals( RepositoryIndex.POM ) )\r
205         {\r
206             InputStream is = new FileInputStream( new File( index.getRepository().getBasedir() +\r
207                 doc.get( RepositoryIndex.FLD_GROUPID ).replace( '.', '/' ) + "/" +\r
208                 doc.get( RepositoryIndex.FLD_ARTIFACTID ) + "/" + doc.get( RepositoryIndex.FLD_VERSION ) + "/" +\r
209                 doc.get( RepositoryIndex.FLD_ARTIFACTID ) + "-" + doc.get( RepositoryIndex.FLD_VERSION ) + ".pom" ) );\r
210             MavenXpp3Reader reader = new MavenXpp3Reader();\r
211 \r
212             searchHit = new RepositoryIndexSearchHit( false, false, true );\r
213             searchHit.setObject( reader.read( new InputStreamReader( is ) ) );\r
214 \r
215         }\r
216         // the document is of type metadata\r
217         else if ( doc.get( RepositoryIndex.FLD_DOCTYPE ).equals( RepositoryIndex.METADATA ) )\r
218         {\r
219             List pathParts = new ArrayList();\r
220             StringTokenizer st = new StringTokenizer( doc.get( RepositoryIndex.FLD_NAME ), "/\\" );\r
221             while ( st.hasMoreTokens() )\r
222             {\r
223                 pathParts.add( st.nextToken() );\r
224             }\r
225 \r
226             Collections.reverse( pathParts );\r
227             Iterator it = pathParts.iterator();\r
228             String metadataFile = (String) it.next();\r
229             String tmpDir = (String) it.next();\r
230 \r
231             String metadataType;\r
232             if ( tmpDir.equals( doc.get( RepositoryIndex.FLD_VERSION ) ) )\r
233             {\r
234                 metadataType = MetadataRepositoryIndex.SNAPSHOT_METADATA;\r
235             }\r
236             else if ( tmpDir.equals( doc.get( RepositoryIndex.FLD_ARTIFACTID ) ) )\r
237             {\r
238                 metadataType = MetadataRepositoryIndex.ARTIFACT_METADATA;\r
239             }\r
240             else\r
241             {\r
242                 metadataType = MetadataRepositoryIndex.GROUP_METADATA;\r
243             }\r
244 \r
245             RepositoryMetadata repoMetadata = getMetadata( doc.get( RepositoryIndex.FLD_GROUPID ),\r
246                                                            doc.get( RepositoryIndex.FLD_ARTIFACTID ),\r
247                                                            doc.get( RepositoryIndex.FLD_VERSION ), metadataFile,\r
248                                                            metadataType );\r
249             searchHit = new RepositoryIndexSearchHit( false, true, false );\r
250             searchHit.setObject( repoMetadata );\r
251         }\r
252 \r
253         return searchHit;\r
254     }\r
255 \r
256     /**\r
257      * Create RepositoryMetadata object.\r
258      *\r
259      * @param groupId      the groupId to be set\r
260      * @param artifactId   the artifactId to be set\r
261      * @param version      the version to be set\r
262      * @param filename     the name of the metadata file\r
263      * @param metadataType the type of RepositoryMetadata object to be created (GROUP, ARTIFACT or SNAPSHOT)\r
264      * @return RepositoryMetadata\r
265      * @throws IOException\r
266      * @throws XmlPullParserException\r
267      */\r
268     private RepositoryMetadata getMetadata( String groupId, String artifactId, String version, String filename,\r
269                                             String metadataType )\r
270         throws IOException, XmlPullParserException\r
271     {\r
272         RepositoryMetadata repoMetadata = null;\r
273 \r
274         // TODO! file handles left open\r
275         InputStream is;\r
276         MetadataXpp3Reader metadataReader = new MetadataXpp3Reader();\r
277 \r
278         //group metadata\r
279         if ( metadataType.equals( MetadataRepositoryIndex.GROUP_METADATA ) )\r
280         {\r
281             // TODO! use pathOfMetadata\r
282             is = new FileInputStream(\r
283                 new File( index.getRepository().getBasedir() + groupId.replace( '.', '/' ) + "/" + filename ) );\r
284             repoMetadata = new GroupRepositoryMetadata( groupId );\r
285             repoMetadata.setMetadata( metadataReader.read( new InputStreamReader( is ) ) );\r
286         }\r
287         //artifact metadata\r
288         else if ( metadataType.equals( MetadataRepositoryIndex.ARTIFACT_METADATA ) )\r
289         {\r
290             // TODO! use pathOfMetadata\r
291             is = new FileInputStream( new File( index.getRepository().getBasedir() + groupId.replace( '.', '/' ) + "/" +\r
292                 artifactId + "/" + filename ) );\r
293             repoMetadata =\r
294                 new ArtifactRepositoryMetadata( factory.createBuildArtifact( groupId, artifactId, version, "jar" ) );\r
295             repoMetadata.setMetadata( metadataReader.read( new InputStreamReader( is ) ) );\r
296         }\r
297         //snapshot/version metadata\r
298         else if ( metadataType.equals( MetadataRepositoryIndex.SNAPSHOT_METADATA ) )\r
299         {\r
300             // TODO! use pathOfMetadata\r
301             is = new FileInputStream( new File( index.getRepository().getBasedir() + groupId.replace( '.', '/' ) + "/" +\r
302                 artifactId + "/" + version + "/" + filename ) );\r
303             repoMetadata = new SnapshotArtifactRepositoryMetadata(\r
304                 factory.createBuildArtifact( groupId, artifactId, version, "jar" ) );\r
305             repoMetadata.setMetadata( metadataReader.read( new InputStreamReader( is ) ) );\r
306         }\r
307 \r
308         return repoMetadata;\r
309     }\r
310 \r
311 }\r