]> source.dussan.org Git - archiva.git/blob
0e17aacd6428c55c08453fb8c421c0d354d0830c
[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.model.AbstractRepositoryConfiguration;
22 import org.apache.archiva.configuration.model.Configuration;
23 import org.apache.archiva.configuration.provider.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     @Override
218     public CheckedResult<R, Map<String, List<ValidationError>>> putWithCheck( C repositoryConfiguration ) throws RepositoryException
219     {
220         return putWithCheck( repositoryConfiguration, getValidator( ) );
221     }
222
223     protected abstract C findRepositoryConfiguration( Configuration configuration, String id);
224
225     protected abstract void removeRepositoryConfiguration(Configuration configuration, C repoConfiguration );
226
227     protected abstract void addRepositoryConfiguration( Configuration configuration, C repoConfiguration );
228
229     /**
230      * Removes a repository group from the registry and configuration, if it exists.
231      * The change is saved to the configuration immediately.
232      *
233      * @param id the id of the repository group to remove
234      * @throws RepositoryException if an error occurs during configuration save
235      */
236     @Override
237     public void remove( String id ) throws RepositoryException
238     {
239         R repo = get( id );
240         if ( repo != null )
241         {
242             try
243             {
244                 repo = getRepositories().remove( id );
245                 if ( repo != null )
246                 {
247                     deactivateRepository( repo );
248                     Configuration configuration = this.configurationHandler.getBaseConfiguration( );
249                     C cfg = findRepositoryConfiguration( configuration, id );
250                     if ( cfg != null )
251                     {
252                         removeRepositoryConfiguration( configuration, cfg );
253                     }
254                     this.configurationHandler.save( configuration, ConfigurationHandler.REGISTRY_EVENT_TAG );
255                     setLastState( repo, RepositoryState.UNREGISTERED );
256                 }
257
258             }
259             catch ( RegistryException | IndeterminateConfigurationException e )
260             {
261                 // Rollback
262                 log.error( "Could not save config after repository removal: {}", e.getMessage( ), e );
263                 getRepositories().put( repo.getId( ), repo );
264                 throw new RepositoryException( "Could not save configuration after repository removal: " + e.getMessage( ) );
265             }
266         }
267     }
268
269     @Override
270     public void remove( String id, Configuration configuration ) throws RepositoryException
271     {
272         R repo = getRepositories().get( id );
273         if ( repo != null )
274         {
275             repo = getRepositories().remove( id );
276             if ( repo != null )
277             {
278                 deactivateRepository( repo );
279             }
280             setLastState( repo, RepositoryState.UNREGISTERED );
281         }
282         C cfg = findRepositoryConfiguration(configuration, id );
283         if ( cfg != null )
284         {
285             removeRepositoryConfiguration(configuration, cfg );
286         }
287     }
288
289     @Override
290     public R get( String groupId )
291     {
292         return getRepositories().get( groupId );
293     }
294
295     @Override
296     public Collection<R> getAll( )
297     {
298         return Collections.unmodifiableCollection( getRepositories( ).values( ) );
299     }
300
301     @Override
302     public RepositoryValidator<R> getValidator( )
303     {
304         return getCombinedValidator();
305     }
306
307     @Override
308     public CheckedResult<R, Map<String, List<ValidationError>>> validateRepository( R repository )
309     {
310         return getCombinedValidator(  ).apply( repository );
311
312     }
313
314     @Override
315     public CheckedResult<R,Map<String, List<ValidationError>>> validateRepositoryForUpdate( R repository )
316     {
317         return getCombinedValidator().applyForUpdate( repository );
318     }
319     @Override
320     public boolean hasRepository( String id )
321     {
322         return getRepositories().containsKey( id );
323     }
324
325
326     @Override
327     public void close( )
328     {
329         for ( R repository : getRepositories().values( ) )
330         {
331             try
332             {
333                 deactivateRepository( repository );
334             }
335             catch ( Throwable e )
336             {
337                 log.error( "Could not close repository {}: {}", repository.getId( ), e.getMessage( ) );
338             }
339         }
340         getRepositories().clear( );
341     }
342
343     protected void registerNewRepository( C repositoryGroupConfiguration, R currentRepository, Configuration configuration, boolean updated ) throws IndeterminateConfigurationException, RegistryException, RepositoryException
344     {
345         final String id = repositoryGroupConfiguration.getId( );
346         getConfigurationHandler().save( configuration, ConfigurationHandler.REGISTRY_EVENT_TAG );
347         updateReferences( currentRepository, repositoryGroupConfiguration );
348         if (!updated )
349         {
350             setLastState( currentRepository, RepositoryState.REFERENCES_SET );
351         }
352         activateRepository( currentRepository );
353         getRepositories().put( id, currentRepository );
354         setLastState( currentRepository, RepositoryState.REGISTERED );
355     }
356
357
358
359     protected void rollback( Configuration configuration, R oldRepository, Exception e, C oldCfg ) throws RepositoryException
360     {
361         final String id = oldRepository.getId( );
362         replaceOrAddRepositoryConfig( oldCfg, configuration );
363         try
364         {
365             getConfigurationHandler().save( configuration, ConfigurationHandler.REGISTRY_EVENT_TAG );
366         }
367         catch ( IndeterminateConfigurationException | RegistryException indeterminateConfigurationException )
368         {
369             log.error( "Fatal error, config save during rollback failed: {}", e.getMessage( ), e );
370         }
371         updateReferences( oldRepository, oldCfg );
372         setLastState( oldRepository, RepositoryState.REFERENCES_SET );
373         activateRepository( oldRepository );
374         getRepositories().put( id, oldRepository );
375         setLastState( oldRepository, RepositoryState.REGISTERED );
376     }
377
378     protected void replaceOrAddRepositoryConfig( C repositoryGroupConfiguration, Configuration configuration )
379     {
380         C oldCfg = findRepositoryConfiguration( configuration, repositoryGroupConfiguration.getId( ) );
381         if ( oldCfg != null )
382         {
383             removeRepositoryConfiguration(configuration, oldCfg );
384         }
385         addRepositoryConfiguration( configuration, repositoryGroupConfiguration );
386     }
387
388
389
390 }