This project has retired. For details please refer to its Attic page.
Source code
001package org.apache.archiva.consumers.core;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 *  http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import org.apache.archiva.configuration.ArchivaConfiguration;
023import org.apache.archiva.configuration.FileTypes;
024import org.apache.archiva.consumers.AbstractMonitoredConsumer;
025import org.apache.archiva.consumers.ConsumerException;
026import org.apache.archiva.consumers.KnownRepositoryContentConsumer;
027import org.apache.archiva.model.ArtifactReference;
028import org.apache.archiva.model.ProjectReference;
029import org.apache.archiva.model.VersionedReference;
030import org.apache.archiva.repository.LayoutException;
031import org.apache.archiva.repository.ManagedRepository;
032import org.apache.archiva.repository.ManagedRepositoryContent;
033import org.apache.archiva.repository.RepositoryException;
034import org.apache.archiva.repository.RepositoryNotFoundException;
035import org.apache.archiva.repository.RepositoryRegistry;
036import org.apache.archiva.repository.metadata.base.MetadataTools;
037import org.apache.archiva.repository.metadata.RepositoryMetadataException;
038import org.slf4j.Logger;
039import org.slf4j.LoggerFactory;
040import org.springframework.context.annotation.Scope;
041import org.springframework.stereotype.Service;
042
043import javax.annotation.PostConstruct;
044import javax.inject.Inject;
045import java.io.IOException;
046import java.nio.file.Files;
047import java.nio.file.Path;
048import java.nio.file.Paths;
049import java.util.ArrayList;
050import java.util.Date;
051import java.util.List;
052
053/**
054 * MetadataUpdaterConsumer will create and update the metadata present within the repository.
055 */
056@Service( "knownRepositoryContentConsumer#metadata-updater" )
057@Scope( "prototype" )
058public class MetadataUpdaterConsumer
059    extends AbstractMonitoredConsumer
060    implements KnownRepositoryContentConsumer
061    // it's prototype bean so we assume configuration won't change during a run
062    //, RegistryListener
063{
064    private Logger log = LoggerFactory.getLogger( MetadataUpdaterConsumer.class );
065
066    /**
067     * default-value="metadata-updater"
068     */
069    private String id = "metadata-updater";
070
071    private String description = "Update / Create maven-metadata.xml files";
072
073    @Inject
074    private RepositoryRegistry repositoryRegistry;
075
076    @Inject
077    private MetadataTools metadataTools;
078
079    @Inject
080    private ArchivaConfiguration configuration;
081
082    @Inject
083    private FileTypes filetypes;
084
085    private static final String TYPE_METADATA_BAD_INTERNAL_REF = "metadata-bad-internal-ref";
086
087    private static final String TYPE_METADATA_WRITE_FAILURE = "metadata-write-failure";
088
089    private static final String TYPE_METADATA_IO = "metadata-io-warning";
090
091    private ManagedRepositoryContent repository;
092
093    private Path repositoryDir;
094
095    private List<String> includes = new ArrayList<>( 0 );
096
097    private long scanStartTimestamp = 0;
098
099    @Override
100    public String getDescription( )
101    {
102        return description;
103    }
104
105    @Override
106    public String getId( )
107    {
108        return id;
109    }
110
111    public void setIncludes( List<String> includes )
112    {
113        this.includes = includes;
114    }
115
116    @Override
117    public void beginScan( ManagedRepository repoConfig, Date whenGathered )
118        throws ConsumerException
119    {
120        try
121        {
122            ManagedRepository repo = repositoryRegistry.getManagedRepository( repoConfig.getId( ) );
123            if (repo==null) {
124                throw new RepositoryNotFoundException( "Repository not found: "+repoConfig.getId() );
125            }
126            this.repository = repo.getContent();
127            if (this.repository==null) {
128                throw new RepositoryNotFoundException( "Repository content not found: "+repoConfig.getId() );
129            }
130            this.repositoryDir = Paths.get( repository.getRepoRoot( ) );
131            this.scanStartTimestamp = System.currentTimeMillis( );
132        }
133        catch ( RepositoryException e )
134        {
135            throw new ConsumerException( e.getMessage( ), e );
136        }
137    }
138
139    @Override
140    public void beginScan( ManagedRepository repository, Date whenGathered, boolean executeOnEntireRepo )
141        throws ConsumerException
142    {
143        beginScan( repository, whenGathered );
144    }
145
146    @Override
147    public void completeScan( )
148    {
149        /* do nothing here */
150    }
151
152    @Override
153    public void completeScan( boolean executeOnEntireRepo )
154    {
155        completeScan( );
156    }
157
158    @Override
159    public List<String> getExcludes( )
160    {
161        return getDefaultArtifactExclusions( );
162    }
163
164    @Override
165    public List<String> getIncludes( )
166    {
167        return this.includes;
168    }
169
170    @Override
171    public void processFile( String path )
172        throws ConsumerException
173    {
174        // Ignore paths like .index etc
175        if ( !path.startsWith( "." ) )
176        {
177            try
178            {
179                ArtifactReference artifact = repository.toArtifactReference( path );
180                updateVersionMetadata( artifact, path );
181                updateProjectMetadata( artifact, path );
182            }
183            catch ( LayoutException e )
184            {
185                log.info( "Not processing path that is not an artifact: {} ({})", path, e.getMessage( ) );
186            }
187        }
188    }
189
190    @Override
191    public void processFile( String path, boolean executeOnEntireRepo )
192        throws Exception
193    {
194        processFile( path );
195    }
196
197    private void updateProjectMetadata( ArtifactReference artifact, String path )
198    {
199        ProjectReference projectRef = new ProjectReference( );
200        projectRef.setGroupId( artifact.getGroupId( ) );
201        projectRef.setArtifactId( artifact.getArtifactId( ) );
202
203        try
204        {
205            String metadataPath = this.metadataTools.toPath( projectRef );
206
207            Path projectMetadata = this.repositoryDir.resolve( metadataPath );
208
209            if ( Files.exists(projectMetadata) && ( Files.getLastModifiedTime( projectMetadata).toMillis() >= this.scanStartTimestamp ) )
210            {
211                // This metadata is up to date. skip it.
212                log.debug( "Skipping uptodate metadata: {}", this.metadataTools.toPath( projectRef ) );
213                return;
214            }
215            metadataTools.updateMetadata( this.repository, metadataPath );
216            log.debug( "Updated metadata: {}", this.metadataTools.toPath( projectRef ) );
217        }
218        catch ( RepositoryMetadataException e )
219        {
220            log.error( "Unable to write project metadat for artifact [{}]:", path, e );
221            triggerConsumerError( TYPE_METADATA_WRITE_FAILURE,
222                "Unable to write project metadata for artifact [" + path + "]: " + e.getMessage( ) );
223        }
224        catch ( IOException e )
225        {
226            log.warn( "Project metadata not written due to IO warning: ", e );
227            triggerConsumerWarning( TYPE_METADATA_IO,
228                "Project metadata not written due to IO warning: " + e.getMessage( ) );
229        }
230    }
231
232    private void updateVersionMetadata( ArtifactReference artifact, String path )
233    {
234        VersionedReference versionRef = new VersionedReference( );
235        versionRef.setGroupId( artifact.getGroupId( ) );
236        versionRef.setArtifactId( artifact.getArtifactId( ) );
237        versionRef.setVersion( artifact.getVersion( ) );
238
239        try
240        {
241            String metadataPath = this.metadataTools.toPath( versionRef );
242
243            Path projectMetadata = this.repositoryDir.resolve( metadataPath );
244
245            if ( Files.exists(projectMetadata) && ( Files.getLastModifiedTime( projectMetadata ).toMillis() >= this.scanStartTimestamp ) )
246            {
247                // This metadata is up to date. skip it.
248                log.debug( "Skipping uptodate metadata: {}", this.metadataTools.toPath( versionRef ) );
249                return;
250            }
251
252            metadataTools.updateMetadata( this.repository, metadataPath );
253            log.debug( "Updated metadata: {}", this.metadataTools.toPath( versionRef ) );
254        }
255        catch ( RepositoryMetadataException e )
256        {
257            log.error( "Unable to write version metadata for artifact [{}]: ", path, e );
258            triggerConsumerError( TYPE_METADATA_WRITE_FAILURE,
259                "Unable to write version metadata for artifact [" + path + "]: " + e.getMessage( ) );
260        }
261        catch ( IOException e )
262        {
263            log.warn( "Version metadata not written due to IO warning: ", e );
264            triggerConsumerWarning( TYPE_METADATA_IO,
265                "Version metadata not written due to IO warning: " + e.getMessage( ) );
266        }
267    }
268
269    /*
270    @Override
271    public void afterConfigurationChange( Registry registry, String propertyName, Object propertyValue )
272    {
273        if ( ConfigurationNames.isRepositoryScanning( propertyName ) )
274        {
275            initIncludes();
276        }
277    }
278
279    @Override
280    public void beforeConfigurationChange( Registry registry, String propertyName, Object propertyValue )
281    {
282        // do nothing here
283    }
284    */
285
286    private void initIncludes( )
287    {
288        includes = new ArrayList<>( filetypes.getFileTypePatterns( FileTypes.ARTIFACTS ) );
289    }
290
291    @PostConstruct
292    public void initialize( )
293    {
294        //configuration.addChangeListener( this );
295
296        initIncludes( );
297    }
298}