001    package org.apache.archiva.consumers.core.repository;
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    
022    import org.apache.archiva.admin.model.beans.ManagedRepository;
023    import org.apache.archiva.admin.model.managed.ManagedRepositoryAdmin;
024    import org.apache.archiva.configuration.ArchivaConfiguration;
025    import org.apache.archiva.configuration.ConfigurationNames;
026    import org.apache.archiva.configuration.FileTypes;
027    import org.apache.archiva.consumers.AbstractMonitoredConsumer;
028    import org.apache.archiva.consumers.ConsumerException;
029    import org.apache.archiva.consumers.KnownRepositoryContentConsumer;
030    import org.apache.archiva.metadata.repository.RepositorySession;
031    import org.apache.archiva.metadata.repository.RepositorySessionFactory;
032    import org.apache.archiva.redback.components.registry.Registry;
033    import org.apache.archiva.repository.ManagedRepositoryContent;
034    import org.apache.archiva.repository.RepositoryContentFactory;
035    import org.apache.archiva.repository.RepositoryException;
036    import org.apache.archiva.repository.RepositoryNotFoundException;
037    import org.apache.archiva.repository.events.RepositoryListener;
038    import org.apache.archiva.repository.metadata.MetadataTools;
039    import org.apache.archiva.redback.components.registry.RegistryListener;
040    import org.springframework.context.annotation.Scope;
041    import org.springframework.stereotype.Service;
042    
043    import javax.annotation.PostConstruct;
044    import javax.inject.Inject;
045    import javax.inject.Named;
046    import java.util.ArrayList;
047    import java.util.Collections;
048    import java.util.Date;
049    import java.util.List;
050    
051    /**
052     * Consumer for removing old snapshots in the repository based on the criteria
053     * specified by the user.
054     */
055    @Service( "knownRepositoryContentConsumer#repository-purge" )
056    @Scope( "prototype" )
057    public class RepositoryPurgeConsumer
058        extends AbstractMonitoredConsumer
059        implements KnownRepositoryContentConsumer, RegistryListener
060    {
061        /**
062         * default-value="repository-purge"
063         */
064        private String id = "repository-purge";
065    
066        /**
067         * default-value="Purge repository of old snapshots"
068         */
069        private String description = "Purge repository of old snapshots";
070    
071        /**
072         *
073         */
074        @Inject
075        @Named( value = "archivaConfiguration#default" )
076        private ArchivaConfiguration configuration;
077    
078        @Inject
079        private ManagedRepositoryAdmin managedRepositoryAdmin;
080    
081        /**
082         *
083         */
084        @Inject
085        @Named( value = "repositoryContentFactory#default" )
086        private RepositoryContentFactory repositoryContentFactory;
087    
088        /**
089         *
090         */
091        @Inject
092        private MetadataTools metadataTools;
093    
094        /**
095         *
096         */
097        @Inject
098        @Named( value = "fileTypes" )
099        private FileTypes filetypes;
100    
101        private List<String> includes = new ArrayList<String>();
102    
103        private RepositoryPurge repoPurge;
104    
105        private RepositoryPurge cleanUp;
106    
107        private boolean deleteReleasedSnapshots;
108    
109        /**
110         *
111         */
112        @Inject
113        private List<RepositoryListener> listeners = Collections.emptyList();
114    
115        /**
116         * FIXME: this could be multiple implementations and needs to be configured.
117         */
118        @Inject
119        private RepositorySessionFactory repositorySessionFactory;
120    
121        private RepositorySession repositorySession;
122    
123        public String getId()
124        {
125            return this.id;
126        }
127    
128        public String getDescription()
129        {
130            return this.description;
131        }
132    
133        public boolean isPermanent()
134        {
135            return false;
136        }
137    
138        public List<String> getExcludes()
139        {
140            return getDefaultArtifactExclusions();
141        }
142    
143        public List<String> getIncludes()
144        {
145            return this.includes;
146        }
147    
148        public void beginScan( ManagedRepository repository, Date whenGathered )
149            throws ConsumerException
150        {
151            ManagedRepositoryContent repositoryContent;
152            try
153            {
154                repositoryContent = repositoryContentFactory.getManagedRepositoryContent( repository.getId() );
155            }
156            catch ( RepositoryNotFoundException e )
157            {
158                throw new ConsumerException( "Can't run repository purge: " + e.getMessage(), e );
159            }
160            catch ( RepositoryException e )
161            {
162                throw new ConsumerException( "Can't run repository purge: " + e.getMessage(), e );
163            }
164    
165            repositorySession = repositorySessionFactory.createSession();
166    
167            if ( repository.getDaysOlder() != 0 )
168            {
169                repoPurge = new DaysOldRepositoryPurge( repositoryContent, repository.getDaysOlder(),
170                                                        repository.getRetentionCount(), repositorySession, listeners );
171            }
172            else
173            {
174                repoPurge =
175                    new RetentionCountRepositoryPurge( repositoryContent, repository.getRetentionCount(), repositorySession,
176                                                       listeners );
177            }
178    
179            cleanUp = new CleanupReleasedSnapshotsRepositoryPurge( repositoryContent, metadataTools, managedRepositoryAdmin,
180                                                                   repositoryContentFactory, repositorySession, listeners );
181    
182            deleteReleasedSnapshots = repository.isDeleteReleasedSnapshots();
183        }
184    
185        public void beginScan( ManagedRepository repository, Date whenGathered, boolean executeOnEntireRepo )
186            throws ConsumerException
187        {
188            beginScan( repository, whenGathered );
189        }
190    
191        public void processFile( String path )
192            throws ConsumerException
193        {
194            try
195            {
196                if ( deleteReleasedSnapshots )
197                {
198                    cleanUp.process( path );
199                }
200    
201                repoPurge.process( path );
202            }
203            catch ( RepositoryPurgeException rpe )
204            {
205                throw new ConsumerException( rpe.getMessage(), rpe );
206            }
207        }
208    
209        public void processFile( String path, boolean executeOnEntireRepo )
210            throws Exception
211        {
212            processFile( path );
213        }
214    
215        public void completeScan()
216        {
217            repositorySession.close();
218        }
219    
220        public void completeScan( boolean executeOnEntireRepo )
221        {
222            completeScan();
223        }
224    
225        public void afterConfigurationChange( Registry registry, String propertyName, Object propertyValue )
226        {
227            if ( ConfigurationNames.isRepositoryScanning( propertyName ) )
228            {
229                initIncludes();
230            }
231        }
232    
233        public void beforeConfigurationChange( Registry registry, String propertyName, Object propertyValue )
234        {
235            /* do nothing */
236        }
237    
238        private void initIncludes()
239        {
240            includes = new ArrayList<String>( filetypes.getFileTypePatterns( FileTypes.ARTIFACTS ) );
241        }
242    
243        @PostConstruct
244        public void initialize()
245        {
246            configuration.addChangeListener( this );
247    
248            initIncludes();
249        }
250    
251        public boolean isProcessUnmodified()
252        {
253            // we need to check all files for deletion, especially if not modified
254            return true;
255        }
256    
257        public ArchivaConfiguration getConfiguration()
258        {
259            return configuration;
260        }
261    
262        public void setConfiguration( ArchivaConfiguration configuration )
263        {
264            this.configuration = configuration;
265        }
266    
267        public RepositoryContentFactory getRepositoryContentFactory()
268        {
269            return repositoryContentFactory;
270        }
271    
272        public void setRepositoryContentFactory( RepositoryContentFactory repositoryContentFactory )
273        {
274            this.repositoryContentFactory = repositoryContentFactory;
275        }
276    
277        public MetadataTools getMetadataTools()
278        {
279            return metadataTools;
280        }
281    
282        public void setMetadataTools( MetadataTools metadataTools )
283        {
284            this.metadataTools = metadataTools;
285        }
286    
287        public FileTypes getFiletypes()
288        {
289            return filetypes;
290        }
291    
292        public void setFiletypes( FileTypes filetypes )
293        {
294            this.filetypes = filetypes;
295        }
296    
297        public RepositoryPurge getRepoPurge()
298        {
299            return repoPurge;
300        }
301    
302        public void setRepoPurge( RepositoryPurge repoPurge )
303        {
304            this.repoPurge = repoPurge;
305        }
306    
307        public RepositoryPurge getCleanUp()
308        {
309            return cleanUp;
310        }
311    
312        public void setCleanUp( RepositoryPurge cleanUp )
313        {
314            this.cleanUp = cleanUp;
315        }
316    
317        public boolean isDeleteReleasedSnapshots()
318        {
319            return deleteReleasedSnapshots;
320        }
321    
322        public void setDeleteReleasedSnapshots( boolean deleteReleasedSnapshots )
323        {
324            this.deleteReleasedSnapshots = deleteReleasedSnapshots;
325        }
326    
327        public RepositorySessionFactory getRepositorySessionFactory()
328        {
329            return repositorySessionFactory;
330        }
331    
332        public void setRepositorySessionFactory( RepositorySessionFactory repositorySessionFactory )
333        {
334            this.repositorySessionFactory = repositorySessionFactory;
335        }
336    
337        public RepositorySession getRepositorySession()
338        {
339            return repositorySession;
340        }
341    
342        public void setRepositorySession( RepositorySession repositorySession )
343        {
344            this.repositorySession = repositorySession;
345        }
346    }