1 package org.apache.maven.repository.discovery;
4 * Copyright 2005-2006 The Apache Software Foundation.
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
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;
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;
45 * Base class for the artifact and metadata discoverers.
47 * @author <a href="mailto:brett@apache.org">Brett Porter</a>
49 public abstract class AbstractDiscoverer
50 extends AbstractLogEnabled
53 private List kickedOutPaths = new ArrayList();
58 protected ArtifactFactory artifactFactory;
60 private static final String[] EMPTY_STRING_ARRAY = new String[0];
62 private List excludedPaths = new ArrayList();
65 * @plexus.configuration default-value="60000"
67 private int blackoutPeriod;
69 protected static final String DATE_FMT = "yyyyMMddHHmmss";
72 * Add a path to the list of files that were kicked out due to being invalid.
74 * @param path the path to add
75 * @param reason the reason why the path is being kicked out
77 protected void addKickedOutPath( String path, String reason )
79 kickedOutPaths.add( new DiscovererPath( path, reason ) );
83 * Returns an iterator for the list if DiscovererPaths that were found to not represent a searched object
85 * @return Iterator for the DiscovererPath List
87 public Iterator getKickedOutPathsIterator()
89 return kickedOutPaths.iterator();
92 protected List scanForArtifactPaths( File repositoryBase, String blacklistedPatterns, String[] includes,
93 String[] excludes, long comparisonTimestamp )
95 List allExcludes = new ArrayList();
96 allExcludes.addAll( FileUtils.getDefaultExcludesAsList() );
97 if ( excludes != null )
99 allExcludes.addAll( Arrays.asList( excludes ) );
102 if ( !StringUtils.isEmpty( blacklistedPatterns ) )
104 allExcludes.addAll( Arrays.asList( blacklistedPatterns.split( "," ) ) );
107 DirectoryScanner scanner = new DirectoryScanner();
108 scanner.setBasedir( repositoryBase );
109 if ( includes != null )
111 scanner.setIncludes( includes );
113 scanner.setExcludes( (String[]) allExcludes.toArray( EMPTY_STRING_ARRAY ) );
117 for ( Iterator files = Arrays.asList( scanner.getExcludedFiles() ).iterator(); files.hasNext(); )
119 String path = files.next().toString();
121 excludedPaths.add( new DiscovererPath( path, "Artifact was in the specified list of exclusions" ) );
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(); )
128 String path = files.next().toString();
130 long modTime = new File( repositoryBase, path ).lastModified();
131 if ( modTime < System.currentTimeMillis() - blackoutPeriod )
133 if ( modTime > comparisonTimestamp )
135 includedPaths.add( path );
140 return includedPaths;
144 * Returns an iterator for the list if DiscovererPaths that were not processed because they are explicitly excluded
146 * @return Iterator for the DiscovererPath List
148 public Iterator getExcludedPathsIterator()
150 return excludedPaths.iterator();
153 protected long readComparisonTimestamp( ArtifactRepository repository, String operation, Xpp3Dom dom )
155 Xpp3Dom entry = dom.getChild( operation );
156 long comparisonTimestamp = 0;
161 comparisonTimestamp = new SimpleDateFormat( DATE_FMT, Locale.US ).parse( entry.getValue() ).getTime();
163 catch ( ParseException e )
165 getLogger().error( "Timestamp was invalid: " + entry.getValue() + "; ignoring" );
168 return comparisonTimestamp;
171 protected Xpp3Dom readDom( File file )
174 FileReader fileReader = null;
177 fileReader = new FileReader( file );
178 dom = Xpp3DomBuilder.build( fileReader );
180 catch ( FileNotFoundException e )
183 dom = new Xpp3Dom( "metadata" );
185 catch ( XmlPullParserException e )
187 getLogger().error( "Error reading metadata (ignoring and recreating): " + e.getMessage() );
188 dom = new Xpp3Dom( "metadata" );
190 catch ( IOException e )
192 getLogger().error( "Error reading metadata (ignoring and recreating): " + e.getMessage() );
193 dom = new Xpp3Dom( "metadata" );
197 IOUtil.close( fileReader );
202 protected Xpp3Dom getLastArtifactDiscoveryDom( Xpp3Dom dom )
204 Xpp3Dom lastDiscoveryDom = dom.getChild( "lastArtifactDiscovery" );
205 if ( lastDiscoveryDom == null )
207 dom.addChild( new Xpp3Dom( "lastArtifactDiscovery" ) );
208 lastDiscoveryDom = dom.getChild( "lastArtifactDiscovery" );
210 return lastDiscoveryDom;
213 protected Xpp3Dom getLastMetadataDiscoveryDom( Xpp3Dom dom )
215 Xpp3Dom lastDiscoveryDom = dom.getChild( "lastMetadataDiscovery" );
216 if ( lastDiscoveryDom == null )
218 dom.addChild( new Xpp3Dom( "lastMetadataDiscovery" ) );
219 lastDiscoveryDom = dom.getChild( "lastMetadataDiscovery" );
221 return lastDiscoveryDom;
224 public void resetLastCheckedTime( ArtifactRepository repository, String operation )
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)
233 File file = new File( repository.getBasedir(), "maven-metadata.xml" );
235 Xpp3Dom dom = readDom( file );
237 boolean changed = false;
239 if ( removeEntry( getLastArtifactDiscoveryDom( dom ), operation ) )
244 if ( removeEntry( getLastMetadataDiscoveryDom( dom ), operation ) )
251 saveDom( file, dom );
255 private boolean removeEntry( Xpp3Dom lastDiscoveryDom, String operation )
257 boolean changed = false;
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-- )
263 if ( children[i].getName().equals( operation ) )
266 lastDiscoveryDom.removeChild( i );
272 protected void saveDom( File file, Xpp3Dom dom )
275 FileWriter writer = new FileWriter( file );
280 Xpp3DomWriter.write( writer, dom );
284 IOUtil.close( writer );
288 protected void setEntry( Xpp3Dom lastDiscoveryDom, String operation, String dateString )
290 Xpp3Dom entry = lastDiscoveryDom.getChild( operation );
293 entry = new Xpp3Dom( operation );
294 lastDiscoveryDom.addChild( entry );
296 entry.setValue( dateString );
299 protected Xpp3Dom readRepositoryMetadataDom( ArtifactRepository repository )
301 return readDom( new File( repository.getBasedir(), "maven-metadata.xml" ) );