1 package org.apache.maven.repository.indexing;
\r
4 * Copyright 2005-2006 The Apache Software Foundation.
\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
10 * http://www.apache.org/licenses/LICENSE-2.0
\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
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
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
50 * Implementation Class for searching through the index.
\r
52 * @todo this is not a component, but extends ALE, meaning logging will throw an exception! -- should be a component
\r
54 public class DefaultRepositoryIndexSearcher
\r
55 extends AbstractLogEnabled
\r
56 implements RepositoryIndexSearcher
\r
58 protected RepositoryIndex index;
\r
60 private ArtifactFactory factory;
\r
62 private List artifactList;
\r
67 * @param index the index object
\r
69 protected DefaultRepositoryIndexSearcher( RepositoryIndex index, ArtifactFactory factory )
\r
72 this.factory = factory;
\r
76 * @see RepositoryIndexSearcher#search(org.apache.maven.repository.indexing.query.Query)
\r
78 public List search( Query query )
\r
79 throws RepositoryIndexSearchException
\r
81 artifactList = new ArrayList();
\r
82 org.apache.lucene.search.Query luceneQuery;
\r
85 luceneQuery = createLuceneQuery( query );
\r
87 catch ( ParseException e )
\r
89 throw new RepositoryIndexSearchException( "Unable to construct query: " + e.getMessage(), e );
\r
92 IndexSearcher searcher;
\r
95 searcher = new IndexSearcher( index.getIndexPath() );
\r
97 catch ( IOException e )
\r
99 throw new RepositoryIndexSearchException( "Unable to open index: " + e.getMessage(), e );
\r
105 Hits hits = searcher.search( luceneQuery );
\r
106 docs = buildList( hits );
\r
108 catch ( MalformedURLException e )
\r
110 throw new RepositoryIndexSearchException( "Unable to search index: " + e.getMessage(), e );
\r
112 catch ( IOException e )
\r
114 throw new RepositoryIndexSearchException( "Unable to search index: " + e.getMessage(), e );
\r
116 catch ( XmlPullParserException xe )
\r
118 throw new RepositoryIndexSearchException( "Unable to parse metadata file: " + xe.getMessage(), xe );
\r
127 catch ( IOException e )
\r
129 getLogger().error( "Unable to close index searcher", e );
\r
137 * Method to create a lucene Query object by converting a prepared Query object
\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
143 private org.apache.lucene.search.Query createLuceneQuery( Query query )
\r
144 throws ParseException
\r
146 return query.createLuceneQuery( index );
\r
150 * Create a list of artifact objects from the result set.
\r
152 * @param hits the search result set
\r
154 * @throws IOException
\r
156 private List buildList( Hits hits )
\r
157 throws MalformedURLException, IOException, XmlPullParserException
\r
159 for ( int i = 0; i < hits.length(); i++ )
\r
161 Document doc = hits.doc( i );
\r
162 artifactList.add( createSearchedObjectFromIndexDocument( doc ) );
\r
165 return artifactList;
\r
169 * Method for creating the object to be returned for the search
\r
171 * @param doc the index document where the object field values will be retrieved from
\r
174 protected RepositoryIndexSearchHit createSearchedObjectFromIndexDocument( Document doc )
\r
175 throws MalformedURLException, IOException, XmlPullParserException
\r
177 RepositoryIndexSearchHit searchHit = null;
\r
179 // the document is of type artifact
\r
180 if ( doc.get( RepositoryIndex.FLD_DOCTYPE ).equals( RepositoryIndex.ARTIFACT ) )
\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
189 new File( index.getRepository().getBasedir(), index.getRepository().pathOf( artifact ) ) );
\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
200 searchHit = new RepositoryIndexSearchHit( true, false, false );
\r
201 searchHit.setObject( map );
\r
203 // the document is of type model
\r
204 else if ( doc.get( RepositoryIndex.FLD_DOCTYPE ).equals( RepositoryIndex.POM ) )
\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
212 searchHit = new RepositoryIndexSearchHit( false, false, true );
\r
213 searchHit.setObject( reader.read( new InputStreamReader( is ) ) );
\r
216 // the document is of type metadata
\r
217 else if ( doc.get( RepositoryIndex.FLD_DOCTYPE ).equals( RepositoryIndex.METADATA ) )
\r
219 List pathParts = new ArrayList();
\r
220 StringTokenizer st = new StringTokenizer( doc.get( RepositoryIndex.FLD_NAME ), "/\\" );
\r
221 while ( st.hasMoreTokens() )
\r
223 pathParts.add( st.nextToken() );
\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
231 String metadataType;
\r
232 if ( tmpDir.equals( doc.get( RepositoryIndex.FLD_VERSION ) ) )
\r
234 metadataType = MetadataRepositoryIndex.SNAPSHOT_METADATA;
\r
236 else if ( tmpDir.equals( doc.get( RepositoryIndex.FLD_ARTIFACTID ) ) )
\r
238 metadataType = MetadataRepositoryIndex.ARTIFACT_METADATA;
\r
242 metadataType = MetadataRepositoryIndex.GROUP_METADATA;
\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
249 searchHit = new RepositoryIndexSearchHit( false, true, false );
\r
250 searchHit.setObject( repoMetadata );
\r
257 * Create RepositoryMetadata object.
\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
268 private RepositoryMetadata getMetadata( String groupId, String artifactId, String version, String filename,
\r
269 String metadataType )
\r
270 throws IOException, XmlPullParserException
\r
272 RepositoryMetadata repoMetadata = null;
\r
274 // TODO! file handles left open
\r
276 MetadataXpp3Reader metadataReader = new MetadataXpp3Reader();
\r
279 if ( metadataType.equals( MetadataRepositoryIndex.GROUP_METADATA ) )
\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
287 //artifact metadata
\r
288 else if ( metadataType.equals( MetadataRepositoryIndex.ARTIFACT_METADATA ) )
\r
290 // TODO! use pathOfMetadata
\r
291 is = new FileInputStream( new File( index.getRepository().getBasedir() + groupId.replace( '.', '/' ) + "/" +
\r
292 artifactId + "/" + filename ) );
\r
294 new ArtifactRepositoryMetadata( factory.createBuildArtifact( groupId, artifactId, version, "jar" ) );
\r
295 repoMetadata.setMetadata( metadataReader.read( new InputStreamReader( is ) ) );
\r
297 //snapshot/version metadata
\r
298 else if ( metadataType.equals( MetadataRepositoryIndex.SNAPSHOT_METADATA ) )
\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
308 return repoMetadata;
\r