]> source.dussan.org Git - archiva.git/blob
f694d5af4a09c432d322e220b24e52c6e8600eab
[archiva.git] /
1 package org.apache.archiva.consumers.metadata;
2
3 /*
4  * Licensed to the Apache Software Foundation (ASF) under one
5  * or more contributor license agreements.  See the NOTICE file
6  * distributed with this work for additional information
7  * regarding copyright ownership.  The ASF licenses this file
8  * to you under the Apache License, Version 2.0 (the
9  * "License"); you may not use this file except in compliance
10  * with the License.  You may obtain a copy of the License at
11  *
12  *  http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing,
15  * software distributed under the License is distributed on an
16  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17  * KIND, either express or implied.  See the License for the
18  * specific language governing permissions and limitations
19  * under the License.
20  */
21
22 import org.apache.archiva.common.utils.VersionUtil;
23 import org.apache.archiva.configuration.ArchivaConfiguration;
24 import org.apache.archiva.configuration.ConfigurationNames;
25 import org.apache.archiva.configuration.FileTypes;
26 import org.apache.archiva.consumers.AbstractMonitoredConsumer;
27 import org.apache.archiva.consumers.ConsumerException;
28 import org.apache.archiva.consumers.KnownRepositoryContentConsumer;
29 import org.apache.archiva.metadata.model.ArtifactMetadata;
30 import org.apache.archiva.metadata.model.ProjectMetadata;
31 import org.apache.archiva.metadata.model.ProjectVersionMetadata;
32 import org.apache.archiva.metadata.repository.*;
33 import org.apache.archiva.metadata.repository.storage.ReadMetadataRequest;
34 import org.apache.archiva.metadata.repository.storage.RepositoryStorage;
35 import org.apache.archiva.metadata.repository.storage.RepositoryStorageMetadataInvalidException;
36 import org.apache.archiva.metadata.repository.storage.RepositoryStorageMetadataNotFoundException;
37 import org.apache.archiva.metadata.repository.storage.RepositoryStorageRuntimeException;
38 import org.apache.archiva.components.registry.Registry;
39 import org.apache.archiva.components.registry.RegistryListener;
40 import org.apache.archiva.repository.ManagedRepository;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
43 import org.springframework.context.annotation.Scope;
44 import org.springframework.stereotype.Service;
45
46 import javax.annotation.PostConstruct;
47 import javax.inject.Inject;
48 import javax.inject.Named;
49 import java.time.ZoneId;
50 import java.time.ZonedDateTime;
51 import java.util.ArrayList;
52 import java.util.Date;
53 import java.util.List;
54
55 /**
56  * Take an artifact off of disk and put it into the metadata repository.
57  */
58 @Service ("knownRepositoryContentConsumer#create-archiva-metadata")
59 @Scope ("prototype")
60 public class ArchivaMetadataCreationConsumer
61     extends AbstractMonitoredConsumer
62     implements KnownRepositoryContentConsumer, RegistryListener
63 {
64     private String id = "create-archiva-metadata";
65
66     private String description = "Create basic metadata for Archiva to be able to reference the artifact";
67
68     @Inject
69     private ArchivaConfiguration configuration;
70
71     @Inject
72     private FileTypes filetypes;
73
74     private ZonedDateTime whenGathered;
75
76     private List<String> includes = new ArrayList<>( 0 );
77
78     /**
79      * FIXME: this could be multiple implementations and needs to be configured.
80      */
81     @Inject
82     private RepositorySessionFactory repositorySessionFactory;
83
84     /**
85      * FIXME: this needs to be configurable based on storage type - and could also be instantiated per repo. Change to a
86      * factory.
87      */
88     @Inject
89     @Named (value = "repositoryStorage#maven2")
90     private RepositoryStorage repositoryStorage;
91
92     private static final Logger log = LoggerFactory.getLogger( ArchivaMetadataCreationConsumer.class );
93
94     private String repoId;
95
96     @Override
97     public String getId()
98     {
99         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 }