View Javadoc
1   package org.apache.maven.index.context;
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 java.io.File;
23  import java.io.FileNotFoundException;
24  import java.io.IOException;
25  import java.io.InputStream;
26  import java.io.OutputStream;
27  import java.nio.file.NoSuchFileException;
28  import java.util.Date;
29  
30  import org.apache.lucene.document.Document;
31  import org.apache.lucene.document.Field;
32  import org.apache.lucene.index.IndexReader;
33  import org.apache.lucene.index.IndexWriter;
34  import org.apache.lucene.store.Directory;
35  import org.apache.lucene.store.IOContext;
36  import org.apache.lucene.store.IndexInput;
37  import org.apache.lucene.store.IndexOutput;
38  import org.apache.maven.index.ArtifactInfo;
39  import org.codehaus.plexus.util.FileUtils;
40  
41  public class IndexUtils
42  {
43      public static final String TIMESTAMP_FILE = "timestamp";
44  
45      private static final int BUFFER_SIZE = 16384;
46  
47      // Directory
48  
49      public static void copyDirectory( Directory source, Directory target )
50          throws IOException
51      {
52          //FIXME: check if this copies too much, Lucene 4 has no filter for lucene files
53          //Directory.copy( source, target, false );
54          
55          for ( String file : source.listAll() )
56          {
57              target.copyFrom( source, file, file, IOContext.DEFAULT );
58          }
59  
60          copyFile( source, target, IndexingContext.INDEX_UPDATER_PROPERTIES_FILE );
61          copyFile( source, target, IndexingContext.INDEX_PACKER_PROPERTIES_FILE );
62  
63          Date ts = getTimestamp( source );
64          updateTimestamp( target, ts );
65      }
66  
67      public static boolean copyFile( Directory source, Directory target, String name )
68          throws IOException
69      {
70          return copyFile( source, target, name, name );
71      }
72  
73      public static boolean copyFile( Directory source, Directory target, String srcName, String targetName )
74          throws IOException
75      {
76          try
77          {
78              source.fileLength( srcName ); // instead of fileExists
79          }
80          catch ( FileNotFoundException | NoSuchFileException e )
81          {
82              return false;
83          }
84          target.copyFrom( source, srcName, targetName, IOContext.DEFAULT );
85          return true;
86      }
87  
88      // timestamp
89  
90      public static ArtifactInfo constructArtifactInfo( Document doc, IndexingContext context )
91      {
92          // if no UINFO can't create, must be a different type of record
93          if ( doc.get( ArtifactInfo.UINFO ) == null )
94          {
95              return null;
96          }
97  
98          boolean res = false;
99  
100         ArtifactInfo artifactInfo = new ArtifactInfo();
101 
102         // Add minimal information to the artifact info linking it to the context it belongs to.
103         try
104         {
105             artifactInfo.setRepository( context.getRepositoryId() );
106         }
107         catch ( UnsupportedOperationException e )
108         {
109             // we ignore that as PartialImplementation can generate this UnsupportedOperationException
110         }
111         try
112         {
113             artifactInfo.setContext( context.getId() );
114         }
115         catch ( Exception e )
116         {
117             // we ignore that as PartialImplementation can generate this UnsupportedOperationException
118         }
119 
120         for ( IndexCreator ic : context.getIndexCreators() )
121         {
122             res |= ic.updateArtifactInfo( doc, artifactInfo );
123         }
124 
125         return res ? artifactInfo : null;
126     }
127 
128     public static Document updateDocument( Document doc, IndexingContext context )
129     {
130         return updateDocument( doc, context, true );
131     }
132 
133     public static Document updateDocument( Document doc, IndexingContext context, boolean updateLastModified )
134     {
135         return updateDocument( doc, context, updateLastModified, null );
136     }
137 
138     public static Document updateDocument( Document doc, IndexingContext context, boolean updateLastModified,
139                                            ArtifactInfo ai )
140     {
141         if ( ai == null )
142         {
143             ai = constructArtifactInfo( doc, context );
144             if ( ai == null )
145             {
146                 return doc;
147             }
148         }
149         Document document = new Document();
150 
151         // unique key
152         document.add( new Field( ArtifactInfo.UINFO, ai.getUinfo(), Field.Store.YES, Field.Index.NOT_ANALYZED ) );
153 
154         if ( updateLastModified || doc.getField( ArtifactInfo.LAST_MODIFIED ) == null )
155         {
156             document.add( new Field( ArtifactInfo.LAST_MODIFIED, //
157                 Long.toString( System.currentTimeMillis() ), Field.Store.YES, Field.Index.NO ) );
158         }
159         else
160         {
161             document.add( doc.getField( ArtifactInfo.LAST_MODIFIED ) );
162         }
163 
164         for ( IndexCreator ic : context.getIndexCreators() )
165         {
166             ic.updateDocument( ai, document );
167         }
168 
169         return document;
170     }
171 
172     public static void deleteTimestamp( Directory directory )
173         throws IOException
174     {
175         try
176         {
177             directory.deleteFile( TIMESTAMP_FILE );
178         }
179         catch ( FileNotFoundException | NoSuchFileException e )
180         {
181             //Does not exist
182         }
183     }
184 
185     public static void updateTimestamp( Directory directory, Date timestamp )
186         throws IOException
187     {
188         synchronized ( directory )
189         {
190             Date currentTimestamp = getTimestamp( directory );
191 
192             if ( timestamp != null && ( currentTimestamp == null || !currentTimestamp.equals( timestamp ) ) )
193             {
194                 deleteTimestamp( directory );
195 
196                 IndexOutput io = directory.createOutput( TIMESTAMP_FILE, IOContext.DEFAULT );
197 
198                 try
199                 {
200                     io.writeLong( timestamp.getTime() );
201                 }
202                 finally
203                 {
204                     close( io );
205                 }
206             }
207         }
208     }
209 
210     public static Date getTimestamp( Directory directory )
211     {
212         synchronized ( directory )
213         {
214             Date result = null;
215             try ( IndexInput ii = directory.openInput( TIMESTAMP_FILE, IOContext.DEFAULT ) )
216             {
217                 result = new Date( ii.readLong() );
218             }
219             catch ( FileNotFoundException | NoSuchFileException e )
220             {
221                 // Does not exist
222             }
223             catch ( IOException ex )
224             {
225                 // IO failure
226             }
227 
228             return result;
229         }
230     }
231 
232     // close helpers
233 
234     public static void close( OutputStream os )
235     {
236         if ( os != null )
237         {
238             try
239             {
240                 os.close();
241             }
242             catch ( IOException e )
243             {
244                 // ignore
245             }
246         }
247     }
248 
249     public static void close( InputStream is )
250     {
251         if ( is != null )
252         {
253             try
254             {
255                 is.close();
256             }
257             catch ( IOException e )
258             {
259                 // ignore
260             }
261         }
262     }
263 
264     public static void close( IndexOutput io )
265     {
266         if ( io != null )
267         {
268             try
269             {
270                 io.close();
271             }
272             catch ( IOException e )
273             {
274                 // ignore
275             }
276         }
277     }
278 
279     public static void close( IndexInput in )
280     {
281         if ( in != null )
282         {
283             try
284             {
285                 in.close();
286             }
287             catch ( IOException e )
288             {
289                 // ignore
290             }
291         }
292     }
293 
294     public static void close( IndexReader r )
295     {
296         if ( r != null )
297         {
298             try
299             {
300                 r.close();
301             }
302             catch ( IOException e )
303             {
304                 // ignore
305             }
306         }
307     }
308 
309     public static void close( IndexWriter w )
310     {
311         if ( w != null )
312         {
313             try
314             {
315                 w.close();
316             }
317             catch ( IOException e )
318             {
319                 // ignore
320             }
321         }
322     }
323 
324     public static void close( Directory d )
325     {
326         if ( d != null )
327         {
328             try
329             {
330                 d.close();
331             }
332             catch ( IOException e )
333             {
334                 // ignore
335             }
336         }
337     }
338 
339     public static void delete( File indexDir )
340     {
341         try
342         {
343             FileUtils.deleteDirectory( indexDir );
344         }
345         catch ( IOException ex )
346         {
347             // ignore
348         }
349     }
350 
351 }