View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.index.context;
20  
21  import java.io.File;
22  import java.io.FileNotFoundException;
23  import java.io.IOException;
24  import java.io.InputStream;
25  import java.io.OutputStream;
26  import java.nio.file.NoSuchFileException;
27  import java.util.Date;
28  
29  import org.apache.lucene.document.Document;
30  import org.apache.lucene.document.Field;
31  import org.apache.lucene.document.StoredField;
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.apache.maven.index.IndexerField;
40  import org.codehaus.plexus.util.FileUtils;
41  
42  public class IndexUtils {
43      public static final String TIMESTAMP_FILE = "timestamp";
44  
45      // Directory
46  
47      public static void copyDirectory(Directory source, Directory target) throws IOException {
48          // FIXME: check if this copies too much, Lucene 4 has no filter for lucene files
49          // Directory.copy( source, target, false );
50  
51          for (String file : source.listAll()) {
52              target.copyFrom(source, file, file, IOContext.DEFAULT);
53          }
54  
55          copyFile(source, target, IndexingContext.INDEX_UPDATER_PROPERTIES_FILE);
56          copyFile(source, target, IndexingContext.INDEX_PACKER_PROPERTIES_FILE);
57  
58          Date ts = getTimestamp(source);
59          updateTimestamp(target, ts);
60      }
61  
62      public static boolean copyFile(Directory source, Directory target, String name) throws IOException {
63          return copyFile(source, target, name, name);
64      }
65  
66      public static boolean copyFile(Directory source, Directory target, String srcName, String targetName)
67              throws IOException {
68          try {
69              source.fileLength(srcName); // instead of fileExists
70          } catch (FileNotFoundException | NoSuchFileException e) {
71              return false;
72          }
73          target.copyFrom(source, srcName, targetName, IOContext.DEFAULT);
74          return true;
75      }
76  
77      // timestamp
78  
79      public static ArtifactInfo constructArtifactInfo(Document doc, IndexingContext context) {
80          // if no UINFO can't create, must be a different type of record
81          if (doc.get(ArtifactInfo.UINFO) == null) {
82              return null;
83          }
84  
85          boolean res = false;
86  
87          ArtifactInfo artifactInfo = new ArtifactInfo();
88  
89          // Add minimal information to the artifact info linking it to the context it belongs to.
90          try {
91              artifactInfo.setRepository(context.getRepositoryId());
92          } catch (UnsupportedOperationException e) {
93              // we ignore that as PartialImplementation can generate this UnsupportedOperationException
94          }
95          try {
96              artifactInfo.setContext(context.getId());
97          } catch (Exception e) {
98              // we ignore that as PartialImplementation can generate this UnsupportedOperationException
99          }
100 
101         for (IndexCreator ic : context.getIndexCreators()) {
102             res |= ic.updateArtifactInfo(doc, artifactInfo);
103         }
104 
105         return res ? artifactInfo : null;
106     }
107 
108     public static Document updateDocument(Document doc, IndexingContext context) {
109         return updateDocument(doc, context, true);
110     }
111 
112     public static Document updateDocument(Document doc, IndexingContext context, boolean updateLastModified) {
113         return updateDocument(doc, context, updateLastModified, null);
114     }
115 
116     public static Document updateDocument(
117             Document doc, IndexingContext context, boolean updateLastModified, ArtifactInfo ai) {
118         if (ai == null) {
119             ai = constructArtifactInfo(doc, context);
120             if (ai == null) {
121                 return doc;
122             }
123         }
124         Document document = new Document();
125 
126         // unique key
127         document.add(new Field(ArtifactInfo.UINFO, ai.getUinfo(), IndexerField.KEYWORD_STORED));
128 
129         if (updateLastModified || doc.getField(ArtifactInfo.LAST_MODIFIED) == null) {
130             document.add(new StoredField(
131                     ArtifactInfo.LAST_MODIFIED, //
132                     Long.toString(System.currentTimeMillis())));
133         } else {
134             document.add(doc.getField(ArtifactInfo.LAST_MODIFIED));
135         }
136 
137         for (IndexCreator ic : context.getIndexCreators()) {
138             ic.updateDocument(ai, document);
139         }
140 
141         return document;
142     }
143 
144     public static void deleteTimestamp(Directory directory) throws IOException {
145         try {
146             directory.deleteFile(TIMESTAMP_FILE);
147         } catch (FileNotFoundException | NoSuchFileException e) {
148             // Does not exist
149         }
150     }
151 
152     public static void updateTimestamp(Directory directory, Date timestamp) throws IOException {
153         synchronized (directory) {
154             Date currentTimestamp = getTimestamp(directory);
155 
156             if (timestamp != null && (currentTimestamp == null || !currentTimestamp.equals(timestamp))) {
157                 deleteTimestamp(directory);
158 
159                 IndexOutput io = directory.createOutput(TIMESTAMP_FILE, IOContext.DEFAULT);
160 
161                 try {
162                     io.writeLong(timestamp.getTime());
163                 } finally {
164                     close(io);
165                 }
166             }
167         }
168     }
169 
170     public static Date getTimestamp(Directory directory) {
171         synchronized (directory) {
172             Date result = null;
173             try (IndexInput ii = directory.openInput(TIMESTAMP_FILE, IOContext.DEFAULT)) {
174                 result = new Date(ii.readLong());
175             } catch (FileNotFoundException | NoSuchFileException e) {
176                 // Does not exist
177             } catch (IOException ex) {
178                 // IO failure
179             }
180 
181             return result;
182         }
183     }
184 
185     // close helpers
186 
187     public static void close(OutputStream os) {
188         if (os != null) {
189             try {
190                 os.close();
191             } catch (IOException e) {
192                 // ignore
193             }
194         }
195     }
196 
197     public static void close(InputStream is) {
198         if (is != null) {
199             try {
200                 is.close();
201             } catch (IOException e) {
202                 // ignore
203             }
204         }
205     }
206 
207     public static void close(IndexOutput io) {
208         if (io != null) {
209             try {
210                 io.close();
211             } catch (IOException e) {
212                 // ignore
213             }
214         }
215     }
216 
217     public static void close(IndexInput in) {
218         if (in != null) {
219             try {
220                 in.close();
221             } catch (IOException e) {
222                 // ignore
223             }
224         }
225     }
226 
227     public static void close(IndexReader r) {
228         if (r != null) {
229             try {
230                 r.close();
231             } catch (IOException e) {
232                 // ignore
233             }
234         }
235     }
236 
237     public static void close(IndexWriter w) {
238         if (w != null) {
239             try {
240                 w.close();
241             } catch (IOException e) {
242                 // ignore
243             }
244         }
245     }
246 
247     public static void close(Directory d) {
248         if (d != null) {
249             try {
250                 d.close();
251             } catch (IOException e) {
252                 // ignore
253             }
254         }
255     }
256 
257     public static void delete(File indexDir) {
258         try {
259             FileUtils.deleteDirectory(indexDir);
260         } catch (IOException ex) {
261             // ignore
262         }
263     }
264 }