]> source.dussan.org Git - archiva.git/blob
0f71880c8fa6ba26174448219e8b7f4a4d158288
[archiva.git] /
1 package org.apache.archiva.repository;
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 com.cronutils.model.CronType;
23 import com.cronutils.model.definition.CronDefinition;
24 import com.cronutils.model.definition.CronDefinitionBuilder;
25 import com.cronutils.parser.CronParser;
26 import org.apache.archiva.indexer.ArchivaIndexingContext;
27 import org.apache.archiva.repository.events.*;
28 import org.apache.archiva.repository.storage.RepositoryStorage;
29 import org.apache.archiva.repository.storage.StorageAsset;
30 import org.apache.archiva.repository.features.RepositoryFeature;
31 import org.apache.archiva.repository.features.StagingRepositoryFeature;
32 import org.apache.commons.lang3.StringUtils;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
35
36 import java.io.IOException;
37 import java.io.InputStream;
38 import java.io.OutputStream;
39 import java.net.URI;
40 import java.nio.channels.ReadableByteChannel;
41 import java.nio.channels.WritableByteChannel;
42 import java.nio.file.CopyOption;
43 import java.util.ArrayList;
44 import java.util.Collections;
45 import java.util.HashMap;
46 import java.util.HashSet;
47 import java.util.List;
48 import java.util.Locale;
49 import java.util.Map;
50 import java.util.Set;
51 import java.util.concurrent.atomic.AtomicBoolean;
52 import java.util.function.Consumer;
53
54 /**
55  * Implementation of a repository with the necessary fields for a bare repository.
56  * No features are provided. Capabilities and features must be implemented by concrete classes.
57  *
58  */
59 public abstract class AbstractRepository implements EditableRepository, RepositoryEventListener
60 {
61
62
63     Logger log = LoggerFactory.getLogger(AbstractRepository.class);
64
65     private final AtomicBoolean openStatus = new AtomicBoolean(false);
66
67
68     private final RepositoryType type;
69     private final String id;
70     private Map<Locale, String> names = new HashMap<>(  );
71     private Map<Locale, String> descriptions = new HashMap<>(  );
72
73     private Locale primaryLocale = new Locale("en_US");
74     protected URI location;
75     private URI baseUri;
76     private Set<URI> failoverLocations = new HashSet<>(  );
77     private Set<URI> uFailoverLocations = Collections.unmodifiableSet( failoverLocations );
78     private boolean scanned = true;
79     String schedulingDefinition = "0 0 02 * * ?";
80     private String layout = "default";
81     public static final CronDefinition CRON_DEFINITION = CronDefinitionBuilder.instanceDefinitionFor(CronType.QUARTZ);
82     private List<RepositoryEventListener> listeners = new ArrayList<>();
83     private Map<EventType, List<RepositoryEventListener>> listenerTypeMap = new HashMap<>();
84
85
86     Map<Class<? extends RepositoryFeature<?>>, RepositoryFeature<?>> featureMap = new HashMap<>(  );
87
88     private ArchivaIndexingContext indexingContext;
89     private RepositoryStorage storage;
90
91     public AbstractRepository(RepositoryType type, String id, String name, RepositoryStorage repositoryStorage) {
92         this.id = id;
93         this.names.put( primaryLocale, name);
94         this.type = type;
95         this.storage = repositoryStorage;
96         this.location = repositoryStorage.getLocation();
97         this.openStatus.compareAndSet(false, true);
98     }
99
100     public AbstractRepository(Locale primaryLocale, RepositoryType type, String id, String name, RepositoryStorage repositoryStorage) {
101         setPrimaryLocale( primaryLocale );
102         this.id = id;
103         this.names.put( primaryLocale, name);
104         this.type = type;
105         this.storage = repositoryStorage;
106         this.location = repositoryStorage.getLocation();
107         this.openStatus.compareAndSet(false, true);
108     }
109
110     protected void setPrimaryLocale(Locale locale) {
111         this.primaryLocale = locale;
112     }
113
114     @Override
115     public String getId( )
116     {
117         return id;
118     }
119
120     @Override
121     public String getName( )
122     {
123         return getName( primaryLocale );
124     }
125
126     @Override
127     public String getName( Locale locale )
128     {
129         return names.get(locale);
130     }
131
132     @Override
133     public String getDescription( )
134     {
135         return getDescription( primaryLocale );
136     }
137
138     @Override
139     public String getDescription( Locale locale )
140     {
141         return descriptions.get(primaryLocale);
142     }
143
144     @Override
145     public RepositoryType getType( )
146     {
147         return type;
148     }
149
150     @Override
151     public URI getLocation( )
152     {
153         return location;
154     }
155
156     @Override
157     public StorageAsset getLocalPath() {
158         return storage.getAsset("");
159     }
160
161     @Override
162     public Set<URI> getFailoverLocations( )
163     {
164         return uFailoverLocations;
165     }
166
167     @Override
168     public boolean isScanned( )
169     {
170         return scanned;
171     }
172
173     @Override
174     public String getSchedulingDefinition( )
175     {
176         return schedulingDefinition;
177     }
178
179     @Override
180     public abstract boolean hasIndex( );
181
182     @Override
183     public String getLayout( )
184     {
185         return layout;
186     }
187
188     @Override
189     public abstract RepositoryCapabilities getCapabilities( );
190
191     @SuppressWarnings( "unchecked" )
192     @Override
193     public <T extends RepositoryFeature<T>> RepositoryFeature<T> getFeature( Class<T> clazz ) throws UnsupportedFeatureException
194     {
195         if (featureMap.containsKey( clazz )) {
196             return (RepositoryFeature<T>) featureMap.get(clazz);
197         } else
198         {
199             throw new UnsupportedFeatureException( "Feature " + clazz + " not supported" );
200         }
201     }
202
203     @Override
204     public <T extends RepositoryFeature<T>> boolean supportsFeature( Class<T> clazz )
205     {
206         return featureMap.containsKey( clazz );
207     }
208
209     @Override
210     public Locale getPrimaryLocale( )
211     {
212         return primaryLocale;
213     }
214
215     @Override
216     public void setName( Locale locale, String name )
217     {
218         names.put(locale, name);
219     }
220
221     @Override
222     public void setDescription( Locale locale, String description )
223     {
224         descriptions.put(locale, description);
225     }
226
227     @Override
228     public void setLocation( final URI location )
229     {
230         if (location!=null && ( this.location == null || !this.location.equals(location))) {
231             try {
232                 updateLocation(location);
233             } catch (IOException e) {
234                 log.error("Could not update location of repository {} to {}", getId(), location, e);
235             }
236         }
237     }
238
239     @Override
240     public void updateLocation(URI newLocation) throws IOException {
241         storage.updateLocation(newLocation);
242         this.location = newLocation;
243     }
244
245     @Override
246     public void addFailoverLocation( URI location )
247     {
248         this.failoverLocations.add(location);
249     }
250
251     @Override
252     public void removeFailoverLocation( URI location )
253     {
254         this.failoverLocations.remove( location );
255     }
256
257     @Override
258     public void clearFailoverLocations( )
259     {
260         this.failoverLocations.clear();
261     }
262
263     @Override
264     public void setScanned( boolean scanned )
265     {
266         this.scanned = scanned;
267     }
268
269     @Override
270     public void setLayout( String layout )
271     {
272         this.layout = layout;
273     }
274
275     @Override
276     public void setBaseUri(URI baseUri) {
277         this.baseUri = baseUri;
278     }
279
280     @Override
281     public void setSchedulingDefinition(String cronExpression) {
282         if (StringUtils.isNotEmpty( cronExpression ))
283         {
284             CronParser parser = new CronParser( CRON_DEFINITION );
285             parser.parse( cronExpression ).validate( );
286         }
287         this.schedulingDefinition = cronExpression;
288     }
289
290     @SuppressWarnings( "unchecked" )
291     protected <T extends RepositoryFeature<T>> void addFeature(RepositoryFeature<T> feature) {
292        featureMap.put( (Class<? extends RepositoryFeature<?>>) feature.getClass(), feature);
293     }
294
295     @Override
296     public void setIndexingContext(ArchivaIndexingContext context) {
297         if (this.indexingContext!=null) {
298
299         }
300         this.indexingContext = context;
301     }
302
303     @Override
304     public ArchivaIndexingContext getIndexingContext() {
305         return indexingContext;
306     }
307
308     @Override
309     public void close() {
310         if (this.openStatus.compareAndSet(true, false)) {
311             ArchivaIndexingContext ctx = getIndexingContext();
312             if (ctx != null) {
313                 try {
314                     ctx.close();
315                 } catch (IOException e) {
316                     log.warn("Error during index context close.", e);
317                 }
318                 this.indexingContext = null;
319
320             }
321             if (supportsFeature(StagingRepositoryFeature.class)) {
322                 StagingRepositoryFeature sf = getFeature(StagingRepositoryFeature.class).get();
323                 if (sf.getStagingRepository() != null) {
324                     sf.getStagingRepository().close();
325                 }
326             }
327             clearListeners();
328         }
329     }
330
331     @Override
332     public boolean isOpen() {
333         return openStatus.get();
334     }
335
336     @Override
337     public void raise(Event event) {
338         callListeners(event, listeners);
339         if (listenerTypeMap.containsKey(event.getType())) {
340             callListeners(event, listenerTypeMap.get(event.getType()));
341         }
342     }
343
344     private void callListeners(Event event, List<RepositoryEventListener> evtListeners) {
345         for(RepositoryEventListener listener : evtListeners) {
346             try {
347                 listener.raise(event.recreate(this));
348             } catch (Throwable e) {
349                 log.error("Could not raise event {} on listener {}: {}", event, listener, e.getMessage());
350             }
351         }
352
353     }
354
355     @Override
356     public void register(RepositoryEventListener listener) {
357         if (!this.listeners.contains(listener)) {
358             this.listeners.add(listener);
359         }
360     }
361
362     @Override
363     public void register(RepositoryEventListener listener, EventType type) {
364         List<RepositoryEventListener> listeners;
365         if (listenerTypeMap.containsKey(type)) {
366             listeners = listenerTypeMap.get(type);
367         } else {
368             listeners = new ArrayList<>();
369             listenerTypeMap.put(type, listeners);
370         }
371         if (!listeners.contains(listener)) {
372             listeners.add(listener);
373         }
374
375     }
376
377     @Override
378     public void register(RepositoryEventListener listener, Set<? extends EventType> types) {
379         for (EventType type : types) {
380             register(listener, type);
381         }
382     }
383
384     @Override
385     public void unregister(RepositoryEventListener listener) {
386         listeners.remove(listener);
387         for (List<RepositoryEventListener> listeners : listenerTypeMap.values()) {
388             listeners.remove(listener);
389         }
390     }
391
392     @Override
393     public void clearListeners() {
394         this.listeners.clear();
395         this.listenerTypeMap.clear();
396     }
397
398     @Override
399     public StorageAsset getAsset(String path )
400     {
401         return storage.getAsset(path);
402     }
403
404     @Override
405     public StorageAsset addAsset( String path, boolean container )
406     {
407         return storage.addAsset(path, container);
408     }
409
410     @Override
411     public void removeAsset( StorageAsset asset ) throws IOException
412     {
413         storage.removeAsset(asset);
414     }
415
416     @Override
417     public StorageAsset moveAsset( StorageAsset origin, String destination, CopyOption... copyOptions ) throws IOException
418     {
419         return storage.moveAsset(origin, destination);
420     }
421
422     @Override
423     public void moveAsset( StorageAsset origin, StorageAsset destination, CopyOption... copyOptions ) throws IOException
424     {
425         storage.moveAsset( origin, destination, copyOptions );
426     }
427
428     @Override
429     public StorageAsset copyAsset( StorageAsset origin, String destination, CopyOption... copyOptions ) throws IOException
430     {
431         return storage.copyAsset(origin, destination);
432     }
433
434     @Override
435     public void copyAsset( StorageAsset origin, StorageAsset destination, CopyOption... copyOptions ) throws IOException
436     {
437         storage.copyAsset( origin, destination, copyOptions);
438     }
439
440     @Override
441     public void consumeData(StorageAsset asset, Consumer<InputStream> consumerFunction, boolean readLock ) throws IOException
442     {
443         storage.consumeData(asset, consumerFunction, readLock);
444     }
445
446     @Override
447     public void consumeDataFromChannel( StorageAsset asset, Consumer<ReadableByteChannel> consumerFunction, boolean readLock ) throws IOException
448     {
449         storage.consumeDataFromChannel( asset, consumerFunction, readLock );
450     }
451
452     @Override
453     public void writeData( StorageAsset asset, Consumer<OutputStream> consumerFunction, boolean writeLock ) throws IOException
454     {
455         storage.writeData( asset, consumerFunction, writeLock );
456     }
457
458     @Override
459     public void writeDataToChannel( StorageAsset asset, Consumer<WritableByteChannel> consumerFunction, boolean writeLock ) throws IOException
460     {
461         storage.writeDataToChannel( asset, consumerFunction, writeLock );
462     }
463
464     protected void setStorage( RepositoryStorage storage) {
465         this.storage = storage;
466     }
467
468     protected RepositoryStorage getStorage() {
469         return storage;
470     }
471 }