This project has retired. For details please refer to its Attic page.
Source code
001package org.apache.archiva.consumers.metadata;
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.common.utils.VersionUtil;
023import org.apache.archiva.configuration.ArchivaConfiguration;
024import org.apache.archiva.configuration.ConfigurationNames;
025import org.apache.archiva.configuration.FileTypes;
026import org.apache.archiva.consumers.AbstractMonitoredConsumer;
027import org.apache.archiva.consumers.ConsumerException;
028import org.apache.archiva.consumers.KnownRepositoryContentConsumer;
029import org.apache.archiva.metadata.model.ArtifactMetadata;
030import org.apache.archiva.metadata.model.ProjectMetadata;
031import org.apache.archiva.metadata.model.ProjectVersionMetadata;
032import org.apache.archiva.metadata.repository.*;
033import org.apache.archiva.metadata.repository.storage.ReadMetadataRequest;
034import org.apache.archiva.metadata.repository.storage.RepositoryStorage;
035import org.apache.archiva.metadata.repository.storage.RepositoryStorageMetadataInvalidException;
036import org.apache.archiva.metadata.repository.storage.RepositoryStorageMetadataNotFoundException;
037import org.apache.archiva.metadata.repository.storage.RepositoryStorageRuntimeException;
038import org.apache.archiva.components.registry.Registry;
039import org.apache.archiva.components.registry.RegistryListener;
040import org.apache.archiva.repository.ManagedRepository;
041import org.slf4j.Logger;
042import org.slf4j.LoggerFactory;
043import org.springframework.context.annotation.Scope;
044import org.springframework.stereotype.Service;
045
046import javax.annotation.PostConstruct;
047import javax.inject.Inject;
048import javax.inject.Named;
049import java.time.ZoneId;
050import java.time.ZonedDateTime;
051import java.util.ArrayList;
052import java.util.Date;
053import java.util.List;
054
055/**
056 * Take an artifact off of disk and put it into the metadata repository.
057 */
058@Service ("knownRepositoryContentConsumer#create-archiva-metadata")
059@Scope ("prototype")
060public class ArchivaMetadataCreationConsumer
061    extends AbstractMonitoredConsumer
062    implements KnownRepositoryContentConsumer, RegistryListener
063{
064    private String id = "create-archiva-metadata";
065
066    private String description = "Create basic metadata for Archiva to be able to reference the artifact";
067
068    @Inject
069    private ArchivaConfiguration configuration;
070
071    @Inject
072    private FileTypes filetypes;
073
074    private ZonedDateTime whenGathered;
075
076    private List<String> includes = new ArrayList<>( 0 );
077
078    /**
079     * FIXME: this could be multiple implementations and needs to be configured.
080     */
081    @Inject
082    private RepositorySessionFactory repositorySessionFactory;
083
084    /**
085     * FIXME: this needs to be configurable based on storage type - and could also be instantiated per repo. Change to a
086     * factory.
087     */
088    @Inject
089    @Named (value = "repositoryStorage#maven2")
090    private RepositoryStorage repositoryStorage;
091
092    private static final Logger log = LoggerFactory.getLogger( ArchivaMetadataCreationConsumer.class );
093
094    private String repoId;
095
096    @Override
097    public String getId()
098    {
099        return this.id;
100    }
101
102    @Override
103    public String getDescription()
104    {
105        return this.description;
106    }
107
108    @Override
109    public List<String> getExcludes()
110    {
111        return getDefaultArtifactExclusions();
112    }
113
114    @Override
115    public List<String> getIncludes()
116    {
117        return this.includes;
118    }
119
120    @Override
121    public void beginScan( ManagedRepository repo, Date whenGathered )
122        throws ConsumerException
123    {
124        repoId = repo.getId();
125        this.whenGathered = ZonedDateTime.ofInstant(whenGathered.toInstant(), ZoneId.of("GMT"));
126    }
127
128    @Override
129    public void beginScan( ManagedRepository repository, Date whenGathered, boolean executeOnEntireRepo )
130        throws ConsumerException
131    {
132        beginScan( repository, whenGathered );
133    }
134
135    @Override
136    public void processFile( String path )
137        throws ConsumerException
138    {
139
140        RepositorySession repositorySession = null;
141        try
142        {
143            repositorySession = repositorySessionFactory.createSession();
144        }
145        catch ( MetadataRepositoryException e )
146        {
147            e.printStackTrace( );
148        }
149        try
150        {
151            // note that we do minimal processing including checksums and POM information for performance of
152            // the initial scan. Any request for this information will be intercepted and populated on-demand
153            // or picked up by subsequent scans
154
155            ArtifactMetadata artifact = repositoryStorage.readArtifactMetadataFromPath( repoId, path );
156
157            ProjectMetadata project = new ProjectMetadata();
158            project.setNamespace( artifact.getNamespace() );
159            project.setId( artifact.getProject() );
160
161            String projectVersion = VersionUtil.getBaseVersion( artifact.getVersion() );
162
163            MetadataRepository metadataRepository = repositorySession.getRepository();
164
165            boolean createVersionMetadata = false;
166
167            // FIXME: maybe not too efficient since it may have already been read and stored for this artifact
168            ProjectVersionMetadata versionMetadata = null;
169            try
170            {
171                ReadMetadataRequest readMetadataRequest =
172                    new ReadMetadataRequest().repositoryId( repoId ).namespace( artifact.getNamespace() ).projectId(
173                        artifact.getProject() ).projectVersion( projectVersion );
174                versionMetadata = repositoryStorage.readProjectVersionMetadata( readMetadataRequest );
175                createVersionMetadata = true;
176            }
177            catch ( RepositoryStorageMetadataNotFoundException e )
178            {
179                log.warn( "Missing or invalid POM for artifact:{} (repository:{}); creating empty metadata", path,
180                          repoId );
181
182                versionMetadata = new ProjectVersionMetadata();
183                versionMetadata.setId( projectVersion );
184                versionMetadata.setIncomplete( true );
185                createVersionMetadata = true;
186            }
187            catch ( RepositoryStorageMetadataInvalidException e )
188            {
189                log.warn( "Error occurred resolving POM for artifact:{} (repository:{}); message: {}",
190                          new Object[]{ path, repoId, e.getMessage() } );
191            }
192
193            // read the metadata and update it if it is newer or doesn't exist
194            artifact.setWhenGathered( whenGathered );
195            metadataRepository.updateArtifact(repositorySession , repoId, project.getNamespace(), project.getId(),
196                projectVersion, artifact );
197            if ( createVersionMetadata )
198            {
199                metadataRepository.updateProjectVersion(repositorySession , repoId, project.getNamespace(),
200                    project.getId(), versionMetadata );
201            }
202            metadataRepository.updateProject(repositorySession , repoId, project );
203            repositorySession.save();
204        }
205        catch ( MetadataRepositoryException e )
206        {
207            log.warn(
208                "Error occurred persisting metadata for artifact:{} (repository:{}); message: {}" ,
209                path, repoId, e.getMessage(), e );
210            try {
211                repositorySession.revert();
212            } catch (MetadataSessionException ex) {
213                log.error("Reverting failed {}", ex.getMessage());
214            }
215        }
216        catch ( RepositoryStorageRuntimeException e )
217        {
218            log.warn(
219                "Error occurred persisting metadata for artifact:{} (repository:{}); message: {}",
220                path, repoId, e.getMessage(), e );
221            try {
222                repositorySession.revert();
223            } catch (MetadataSessionException ex) {
224                log.error("Reverting failed {}", ex.getMessage());
225            }
226        } catch (MetadataSessionException e) {
227            throw new ConsumerException(e.getMessage(), e);
228        } finally
229        {
230            repositorySession.close();
231        }
232    }
233
234    @Override
235    public void processFile( String path, boolean executeOnEntireRepo )
236        throws ConsumerException
237    {
238        processFile( path );
239    }
240
241    @Override
242    public void completeScan()
243    {
244        /* do nothing */
245    }
246
247    @Override
248    public void completeScan( boolean executeOnEntireRepo )
249    {
250        completeScan();
251    }
252
253    @Override
254    public void afterConfigurationChange( Registry registry, String propertyName, Object propertyValue )
255    {
256        if ( ConfigurationNames.isRepositoryScanning( propertyName ) )
257        {
258            initIncludes();
259        }
260    }
261
262    @Override
263    public void beforeConfigurationChange( Registry registry, String propertyName, Object propertyValue )
264    {
265        /* do nothing */
266    }
267
268    private void initIncludes()
269    {
270        includes = new ArrayList<String>( filetypes.getFileTypePatterns( FileTypes.ARTIFACTS ) );
271    }
272
273    @PostConstruct
274    public void initialize()
275    {
276        configuration.addChangeListener( this );
277
278        initIncludes();
279    }
280}