]> source.dussan.org Git - archiva.git/blob
b9c721c01ad8f6d0f1339c16f5f791be2c81fbf8
[archiva.git] /
1 package org.apache.maven.repository.discovery;
2
3 /*
4  * Copyright 2005-2006 The Apache Software Foundation.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * 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, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18
19 import org.apache.maven.artifact.factory.ArtifactFactory;
20 import org.apache.maven.artifact.repository.ArtifactRepository;
21 import org.codehaus.plexus.logging.AbstractLogEnabled;
22 import org.codehaus.plexus.util.DirectoryScanner;
23 import org.codehaus.plexus.util.FileUtils;
24 import org.codehaus.plexus.util.IOUtil;
25 import org.codehaus.plexus.util.StringUtils;
26 import org.codehaus.plexus.util.xml.Xpp3Dom;
27 import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
28 import org.codehaus.plexus.util.xml.Xpp3DomWriter;
29 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
30
31 import java.io.File;
32 import java.io.FileNotFoundException;
33 import java.io.FileReader;
34 import java.io.FileWriter;
35 import java.io.IOException;
36 import java.text.ParseException;
37 import java.text.SimpleDateFormat;
38 import java.util.ArrayList;
39 import java.util.Arrays;
40 import java.util.Iterator;
41 import java.util.List;
42 import java.util.Locale;
43
44 /**
45  * Base class for the artifact and metadata discoverers.
46  *
47  * @author <a href="mailto:brett@apache.org">Brett Porter</a>
48  */
49 public abstract class AbstractDiscoverer
50     extends AbstractLogEnabled
51     implements Discoverer
52 {
53     private List kickedOutPaths = new ArrayList();
54
55     /**
56      * @plexus.requirement
57      */
58     protected ArtifactFactory artifactFactory;
59
60     private static final String[] EMPTY_STRING_ARRAY = new String[0];
61
62     private List excludedPaths = new ArrayList();
63
64     /**
65      * @plexus.configuration default-value="60000"
66      */
67     private int blackoutPeriod;
68
69     protected static final String DATE_FMT = "yyyyMMddHHmmss";
70
71     /**
72      * Add a path to the list of files that were kicked out due to being invalid.
73      *
74      * @param path   the path to add
75      * @param reason the reason why the path is being kicked out
76      */
77     protected void addKickedOutPath( String path, String reason )
78     {
79         kickedOutPaths.add( new DiscovererPath( path, reason ) );
80     }
81
82     /**
83      * Returns an iterator for the list if DiscovererPaths that were found to not represent a searched object
84      *
85      * @return Iterator for the DiscovererPath List
86      */
87     public Iterator getKickedOutPathsIterator()
88     {
89         return kickedOutPaths.iterator();
90     }
91
92     protected List scanForArtifactPaths( File repositoryBase, String blacklistedPatterns, String[] includes,
93                                          String[] excludes, long comparisonTimestamp )
94     {
95         List allExcludes = new ArrayList();
96         allExcludes.addAll( FileUtils.getDefaultExcludesAsList() );
97         if ( excludes != null )
98         {
99             allExcludes.addAll( Arrays.asList( excludes ) );
100         }
101
102         if ( !StringUtils.isEmpty( blacklistedPatterns ) )
103         {
104             allExcludes.addAll( Arrays.asList( blacklistedPatterns.split( "," ) ) );
105         }
106
107         DirectoryScanner scanner = new DirectoryScanner();
108         scanner.setBasedir( repositoryBase );
109         if ( includes != null )
110         {
111             scanner.setIncludes( includes );
112         }
113         scanner.setExcludes( (String[]) allExcludes.toArray( EMPTY_STRING_ARRAY ) );
114
115         scanner.scan();
116
117         for ( Iterator files = Arrays.asList( scanner.getExcludedFiles() ).iterator(); files.hasNext(); )
118         {
119             String path = files.next().toString();
120
121             excludedPaths.add( new DiscovererPath( path, "Artifact was in the specified list of exclusions" ) );
122         }
123
124         // TODO: this could be a part of the scanner
125         List includedPaths = new ArrayList();
126         for ( Iterator files = Arrays.asList( scanner.getIncludedFiles() ).iterator(); files.hasNext(); )
127         {
128             String path = files.next().toString();
129
130             long modTime = new File( repositoryBase, path ).lastModified();
131             if ( modTime < System.currentTimeMillis() - blackoutPeriod )
132             {
133                 if ( modTime > comparisonTimestamp )
134                 {
135                     includedPaths.add( path );
136                 }
137             }
138         }
139
140         return includedPaths;
141     }
142
143     /**
144      * Returns an iterator for the list if DiscovererPaths that were not processed because they are explicitly excluded
145      *
146      * @return Iterator for the DiscovererPath List
147      */
148     public Iterator getExcludedPathsIterator()
149     {
150         return excludedPaths.iterator();
151     }
152
153     protected long readComparisonTimestamp( ArtifactRepository repository, String operation, Xpp3Dom dom )
154     {
155         Xpp3Dom entry = dom.getChild( operation );
156         long comparisonTimestamp = 0;
157         if ( entry != null )
158         {
159             try
160             {
161                 comparisonTimestamp = new SimpleDateFormat( DATE_FMT, Locale.US ).parse( entry.getValue() ).getTime();
162             }
163             catch ( ParseException e )
164             {
165                 getLogger().error( "Timestamp was invalid: " + entry.getValue() + "; ignoring" );
166             }
167         }
168         return comparisonTimestamp;
169     }
170
171     protected Xpp3Dom readDom( File file )
172     {
173         Xpp3Dom dom;
174         FileReader fileReader = null;
175         try
176         {
177             fileReader = new FileReader( file );
178             dom = Xpp3DomBuilder.build( fileReader );
179         }
180         catch ( FileNotFoundException e )
181         {
182             // Safe to ignore
183             dom = new Xpp3Dom( "metadata" );
184         }
185         catch ( XmlPullParserException e )
186         {
187             getLogger().error( "Error reading metadata (ignoring and recreating): " + e.getMessage() );
188             dom = new Xpp3Dom( "metadata" );
189         }
190         catch ( IOException e )
191         {
192             getLogger().error( "Error reading metadata (ignoring and recreating): " + e.getMessage() );
193             dom = new Xpp3Dom( "metadata" );
194         }
195         finally
196         {
197             IOUtil.close( fileReader );
198         }
199         return dom;
200     }
201
202     protected Xpp3Dom getLastArtifactDiscoveryDom( Xpp3Dom dom )
203     {
204         Xpp3Dom lastDiscoveryDom = dom.getChild( "lastArtifactDiscovery" );
205         if ( lastDiscoveryDom == null )
206         {
207             dom.addChild( new Xpp3Dom( "lastArtifactDiscovery" ) );
208             lastDiscoveryDom = dom.getChild( "lastArtifactDiscovery" );
209         }
210         return lastDiscoveryDom;
211     }
212
213     protected Xpp3Dom getLastMetadataDiscoveryDom( Xpp3Dom dom )
214     {
215         Xpp3Dom lastDiscoveryDom = dom.getChild( "lastMetadataDiscovery" );
216         if ( lastDiscoveryDom == null )
217         {
218             dom.addChild( new Xpp3Dom( "lastMetadataDiscovery" ) );
219             lastDiscoveryDom = dom.getChild( "lastMetadataDiscovery" );
220         }
221         return lastDiscoveryDom;
222     }
223
224     public void resetLastCheckedTime( ArtifactRepository repository, String operation )
225         throws IOException
226     {
227         // TODO: get these changes into maven-metadata.xml and migrate towards that. The model is further diverging to a different layout at each level so submodels might be a good idea.
228         // TODO: maven-artifact probably needs an improved pathOfMetadata to cope with top level metadata
229         // TODO: might we need to write this as maven-metadata-local in some circumstances? merge others? Probably best to keep it simple and just use this format at the root. No need to merge anything that I can see
230         // TODO: since this metadata isn't meant to be shared, perhaps another file is called for after all.
231         // Format is: <repository><lastDiscovery><KEY>yyyyMMddHHmmss</KEY></lastDiscovery></repository> (ie, flat properties)
232
233         File file = new File( repository.getBasedir(), "maven-metadata.xml" );
234
235         Xpp3Dom dom = readDom( file );
236
237         boolean changed = false;
238
239         if ( removeEntry( getLastArtifactDiscoveryDom( dom ), operation ) )
240         {
241             changed = true;
242         }
243
244         if ( removeEntry( getLastMetadataDiscoveryDom( dom ), operation ) )
245         {
246             changed = true;
247         }
248
249         if ( changed )
250         {
251             saveDom( file, dom );
252         }
253     }
254
255     private boolean removeEntry( Xpp3Dom lastDiscoveryDom, String operation )
256     {
257         boolean changed = false;
258
259         // do this in reverse so that removing doesn't affect counter
260         Xpp3Dom[] children = lastDiscoveryDom.getChildren();
261         for ( int i = lastDiscoveryDom.getChildCount() - 1; i >= 0; i-- )
262         {
263             if ( children[i].getName().equals( operation ) )
264             {
265                 changed = true;
266                 lastDiscoveryDom.removeChild( i );
267             }
268         }
269         return changed;
270     }
271
272     protected void saveDom( File file, Xpp3Dom dom )
273         throws IOException
274     {
275         FileWriter writer = new FileWriter( file );
276
277         // save metadata
278         try
279         {
280             Xpp3DomWriter.write( writer, dom );
281         }
282         finally
283         {
284             IOUtil.close( writer );
285         }
286     }
287
288     protected void setEntry( Xpp3Dom lastDiscoveryDom, String operation, String dateString )
289     {
290         Xpp3Dom entry = lastDiscoveryDom.getChild( operation );
291         if ( entry == null )
292         {
293             entry = new Xpp3Dom( operation );
294             lastDiscoveryDom.addChild( entry );
295         }
296         entry.setValue( dateString );
297     }
298
299     protected Xpp3Dom readRepositoryMetadataDom( ArtifactRepository repository )
300     {
301         return readDom( new File( repository.getBasedir(), "maven-metadata.xml" ) );
302     }
303 }