]> source.dussan.org Git - archiva.git/blob
9e316a7fe9a9180f05e2616031c9592960ba93d8
[archiva.git] /
1 package org.apache.archiva.repository.base;
2 /*
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied.  See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19
20 import org.apache.archiva.components.registry.RegistryException;
21 import org.apache.archiva.configuration.AbstractRepositoryConfiguration;
22 import org.apache.archiva.configuration.Configuration;
23 import org.apache.archiva.configuration.IndeterminateConfigurationException;
24 import org.apache.archiva.event.Event;
25 import org.apache.archiva.event.EventManager;
26 import org.apache.archiva.event.EventType;
27 import org.apache.archiva.repository.EditableRepository;
28 import org.apache.archiva.repository.Repository;
29 import org.apache.archiva.repository.RepositoryException;
30 import org.apache.archiva.repository.RepositoryHandler;
31 import org.apache.archiva.repository.RepositoryProvider;
32 import org.apache.archiva.repository.RepositoryState;
33 import org.apache.archiva.repository.RepositoryType;
34 import org.apache.archiva.repository.event.LifecycleEvent;
35 import org.apache.archiva.repository.validation.CheckedResult;
36 import org.apache.archiva.repository.validation.CombinedValidator;
37 import org.apache.archiva.repository.validation.RepositoryChecker;
38 import org.apache.archiva.repository.validation.RepositoryValidator;
39 import org.apache.archiva.repository.validation.ValidationError;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
42
43 import java.util.Collection;
44 import java.util.Collections;
45 import java.util.HashMap;
46 import java.util.List;
47 import java.util.Map;
48 import java.util.stream.Collectors;
49
50 /**
51  * Base abstract class for repository handlers.
52  *
53  * @author Martin Stockhammer <martin_s@apache.org>
54  */
55 public abstract class AbstractRepositoryHandler<R extends Repository, C extends AbstractRepositoryConfiguration> implements RepositoryHandler<R, C>
56 {
57
58     private static final Logger log = LoggerFactory.getLogger( AbstractRepositoryHandler.class );
59
60     protected final Map<RepositoryType, RepositoryProvider> providerMap = new HashMap<>( );
61     private CombinedValidator<R> combinedValidator;
62     private final Class<R> repositoryClazz;
63     private final Class<C> configurationClazz;
64     private final EventManager eventManager;
65     private final Map<String, R> repositoryMap  = new HashMap<>(  );
66     private final ConfigurationHandler configurationHandler;
67
68     public AbstractRepositoryHandler(Class<R> repositoryClazz, Class<C> configurationClazz, ConfigurationHandler configurationHandler) {
69         this.repositoryClazz = repositoryClazz;
70         this.configurationClazz = configurationClazz;
71         this.eventManager = new EventManager( this );
72         this.configurationHandler = configurationHandler;
73     }
74
75     protected List<RepositoryValidator<R>> initValidators( Class<R> clazz, List<RepositoryValidator<? extends Repository>> repositoryGroupValidatorList )
76     {
77         if ( repositoryGroupValidatorList != null && repositoryGroupValidatorList.size( ) > 0 )
78         {
79             return repositoryGroupValidatorList.stream( ).filter(
80                 v -> v.isFlavour( clazz )
81             ).map( v -> v.narrowTo( clazz ) ).collect( Collectors.toList( ) );
82         }
83         else
84         {
85             return Collections.emptyList( );
86         }
87     }
88
89     protected CombinedValidator<R> getCombinedValidator( Class<R> clazz, List<RepositoryValidator<? extends Repository>> repositoryGroupValidatorList )
90     {
91         return new CombinedValidator<>( clazz, initValidators( clazz, repositoryGroupValidatorList ) );
92     }
93
94     protected void setLastState( R repo, RepositoryState state )
95     {
96         RepositoryState currentState = repo.getLastState( );
97         if ( repo instanceof EditableRepository )
98         {
99             if ( state.getOrderNumber( ) > repo.getLastState( ).getOrderNumber( ) )
100             {
101                 ( (EditableRepository) repo ).setLastState( state );
102             }
103         }
104         else
105         {
106             log.error( "Found a not editable repository instance: {}, {}", repo.getId( ), repo.getClass( ).getName( ) );
107         }
108         if (state == RepositoryState.REGISTERED && state != currentState ) {
109             pushEvent( LifecycleEvent.REGISTERED,  repo );
110         } else if (state == RepositoryState.UNREGISTERED && state != currentState) {
111             pushEvent( LifecycleEvent.UNREGISTERED, repo );
112         }
113     }
114
115     @Override
116     public void setRepositoryProviders( List<RepositoryProvider> providers )
117     {
118         if ( providers != null )
119         {
120             for ( RepositoryProvider provider : providers )
121             {
122                 for ( RepositoryType type : provider.provides( ) )
123                 {
124                     providerMap.put( type, provider );
125                 }
126             }
127         }
128     }
129
130     protected RepositoryProvider getProvider(RepositoryType type) {
131         return providerMap.get( type );
132     }
133
134     @Override
135     public void setRepositoryValidator( List<RepositoryValidator<? extends Repository>> repositoryValidatorList )
136     {
137         this.combinedValidator = getCombinedValidator( repositoryClazz, repositoryValidatorList );
138     }
139
140     protected CombinedValidator<R> getCombinedValidator() {
141         return this.combinedValidator;
142     }
143
144     @Override
145     public Class<R> getVariant( )
146     {
147         return this.repositoryClazz;
148     }
149
150     @Override
151     public Class<C> getConfigurationVariant( )
152     {
153         return this.configurationClazz;
154     }
155
156     @Override
157     public void processOtherVariantRemoval( Repository repository )
158     {
159         // Default: do nothing
160     }
161
162     protected void pushEvent( Event event )
163     {
164         eventManager.fireEvent( event );
165     }
166
167     protected void pushEvent(EventType<? extends LifecycleEvent> event, R repo) {
168         pushEvent( new LifecycleEvent( event, this, repo ) );
169     }
170
171     protected Map<String, R> getRepositories() {
172         return repositoryMap;
173     }
174
175     protected ConfigurationHandler getConfigurationHandler() {
176         return configurationHandler;
177     }
178
179     @Override
180     public void activateRepository( R repository )
181     {
182         //
183     }
184
185     @Override
186     public void deactivateRepository( R repository )
187     {
188         repository.close();
189     }
190
191     @Override
192     public abstract R newInstance( C repositoryConfiguration ) throws RepositoryException;
193
194     @Override
195     public <D> CheckedResult<R, D> putWithCheck( C repositoryConfiguration, RepositoryChecker<R, D> checker ) throws RepositoryException
196     {
197         final String id = repositoryConfiguration.getId( );
198         R currentRepository = getRepositories().get( id );
199         R managedRepository = newInstance( repositoryConfiguration );
200         CheckedResult<R, D> result;
201         if ( currentRepository == null )
202         {
203             result = checker.apply( managedRepository );
204         }
205         else
206         {
207             result = checker.applyForUpdate( managedRepository );
208         }
209         if ( result.isValid( ) )
210         {
211             put( result.getRepository() );
212         }
213         return result;
214
215     }
216
217     protected abstract C findRepositoryConfiguration(Configuration configuration, String id);
218
219     protected abstract void removeRepositoryConfiguration(Configuration configuration, C repoConfiguration );
220
221     protected abstract void addRepositoryConfiguration( Configuration configuration, C repoConfiguration );
222
223     /**
224      * Removes a repository group from the registry and configuration, if it exists.
225      * The change is saved to the configuration immediately.
226      *
227      * @param id the id of the repository group to remove
228      * @throws RepositoryException if an error occurs during configuration save
229      */
230     @Override
231     public void remove( String id ) throws RepositoryException
232     {
233         R repo = get( id );
234         if ( repo != null )
235         {
236             try
237             {
238                 repo = getRepositories().remove( id );
239                 if ( repo != null )
240                 {
241                     deactivateRepository( repo );
242                     Configuration configuration = this.configurationHandler.getBaseConfiguration( );
243                     C cfg = findRepositoryConfiguration( configuration, id );
244                     if ( cfg != null )
245                     {
246                         removeRepositoryConfiguration( configuration, cfg );
247                     }
248                     this.configurationHandler.save( configuration, ConfigurationHandler.REGISTRY_EVENT_TAG );
249                     setLastState( repo, RepositoryState.UNREGISTERED );
250                 }
251
252             }
253             catch ( RegistryException | IndeterminateConfigurationException e )
254             {
255                 // Rollback
256                 log.error( "Could not save config after repository removal: {}", e.getMessage( ), e );
257                 getRepositories().put( repo.getId( ), repo );
258                 throw new RepositoryException( "Could not save configuration after repository removal: " + e.getMessage( ) );
259             }
260         }
261     }
262
263     @Override
264     public void remove( String id, Configuration configuration ) throws RepositoryException
265     {
266         R repo = getRepositories().get( id );
267         if ( repo != null )
268         {
269             repo = getRepositories().remove( id );
270             if ( repo != null )
271             {
272                 deactivateRepository( repo );
273             }
274             setLastState( repo, RepositoryState.UNREGISTERED );
275         }
276         C cfg = findRepositoryConfiguration(configuration, id );
277         if ( cfg != null )
278         {
279             removeRepositoryConfiguration(configuration, cfg );
280         }
281     }
282
283     @Override
284     public R get( String groupId )
285     {
286         return getRepositories().get( groupId );
287     }
288
289     @Override
290     public Collection<R> getAll( )
291     {
292         return Collections.unmodifiableCollection( getRepositories( ).values( ) );
293     }
294
295     @Override
296     public RepositoryValidator<R> getValidator( )
297     {
298         return getCombinedValidator();
299     }
300
301     @Override
302     public CheckedResult<R, Map<String, List<ValidationError>>> validateRepository( R repository )
303     {
304         return getCombinedValidator(  ).apply( repository );
305
306     }
307
308     @Override
309     public CheckedResult<R,Map<String, List<ValidationError>>> validateRepositoryForUpdate( R repository )
310     {
311         return getCombinedValidator().applyForUpdate( repository );
312     }
313     @Override
314     public boolean hasRepository( String id )
315     {
316         return getRepositories().containsKey( id );
317     }
318
319
320     @Override
321     public void close( )
322     {
323         for ( R repository : getRepositories().values( ) )
324         {
325             try
326             {
327                 deactivateRepository( repository );
328             }
329             catch ( Throwable e )
330             {
331                 log.error( "Could not close repository {}: {}", repository.getId( ), e.getMessage( ) );
332             }
333         }
334         getRepositories().clear( );
335     }
336
337     protected void registerNewRepository( C repositoryGroupConfiguration, R currentRepository, Configuration configuration, boolean updated ) throws IndeterminateConfigurationException, RegistryException, RepositoryException
338     {
339         final String id = repositoryGroupConfiguration.getId( );
340         getConfigurationHandler().save( configuration, ConfigurationHandler.REGISTRY_EVENT_TAG );
341         updateReferences( currentRepository, repositoryGroupConfiguration );
342         if (!updated )
343         {
344             setLastState( currentRepository, RepositoryState.REFERENCES_SET );
345         }
346         activateRepository( currentRepository );
347         getRepositories().put( id, currentRepository );
348         setLastState( currentRepository, RepositoryState.REGISTERED );
349     }
350
351
352
353     protected void rollback( Configuration configuration, R oldRepository, Exception e, C oldCfg ) throws RepositoryException
354     {
355         final String id = oldRepository.getId( );
356         replaceOrAddRepositoryConfig( oldCfg, configuration );
357         try
358         {
359             getConfigurationHandler().save( configuration, ConfigurationHandler.REGISTRY_EVENT_TAG );
360         }
361         catch ( IndeterminateConfigurationException | RegistryException indeterminateConfigurationException )
362         {
363             log.error( "Fatal error, config save during rollback failed: {}", e.getMessage( ), e );
364         }
365         updateReferences( oldRepository, oldCfg );
366         setLastState( oldRepository, RepositoryState.REFERENCES_SET );
367         activateRepository( oldRepository );
368         getRepositories().put( id, oldRepository );
369         setLastState( oldRepository, RepositoryState.REGISTERED );
370     }
371
372     protected void replaceOrAddRepositoryConfig( C repositoryGroupConfiguration, Configuration configuration )
373     {
374         C oldCfg = findRepositoryConfiguration( configuration, repositoryGroupConfiguration.getId( ) );
375         if ( oldCfg != null )
376         {
377             removeRepositoryConfiguration(configuration, oldCfg );
378         }
379         addRepositoryConfiguration( configuration, repositoryGroupConfiguration );
380     }
381
382
383
384 }