1 package org.apache.archiva.repository.base;
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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
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.event.Event;
27 import org.apache.archiva.event.EventHandler;
28 import org.apache.archiva.event.EventManager;
29 import org.apache.archiva.event.EventType;
30 import org.apache.archiva.indexer.ArchivaIndexingContext;
31 import org.apache.archiva.repository.EditableRepository;
32 import org.apache.archiva.repository.RepositoryCapabilities;
33 import org.apache.archiva.repository.RepositoryState;
34 import org.apache.archiva.repository.RepositoryType;
35 import org.apache.archiva.repository.UnsupportedFeatureException;
36 import org.apache.archiva.repository.event.*;
37 import org.apache.archiva.repository.storage.RepositoryStorage;
38 import org.apache.archiva.repository.storage.StorageAsset;
39 import org.apache.archiva.repository.features.RepositoryFeature;
40 import org.apache.archiva.repository.features.StagingRepositoryFeature;
41 import org.apache.commons.lang3.StringUtils;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
45 import java.io.IOException;
46 import java.io.InputStream;
47 import java.io.OutputStream;
49 import java.nio.channels.ReadableByteChannel;
50 import java.nio.channels.WritableByteChannel;
51 import java.nio.file.CopyOption;
52 import java.util.Collections;
53 import java.util.HashMap;
54 import java.util.HashSet;
55 import java.util.Locale;
58 import java.util.concurrent.atomic.AtomicBoolean;
59 import java.util.function.Consumer;
62 * Implementation of a repository with the necessary fields for a bare repository.
63 * No features are provided. Capabilities and features must be implemented by concrete classes.
66 public abstract class AbstractRepository implements EditableRepository, EventHandler<RepositoryEvent>
70 Logger log = LoggerFactory.getLogger(AbstractRepository.class);
72 private final AtomicBoolean openStatus = new AtomicBoolean(false);
75 private final RepositoryType type;
76 private final String id;
77 private Map<Locale, String> names = new HashMap<>( );
78 private Map<Locale, String> descriptions = new HashMap<>( );
80 private Locale primaryLocale = new Locale("en_US");
81 protected URI location;
83 private Set<URI> failoverLocations = new HashSet<>( );
84 private Set<URI> uFailoverLocations = Collections.unmodifiableSet( failoverLocations );
85 private boolean scanned = true;
86 String schedulingDefinition = "0 0 02 * * ?";
87 private String layout = "default";
88 public static final CronDefinition CRON_DEFINITION = CronDefinitionBuilder.instanceDefinitionFor(CronType.QUARTZ);
89 private RepositoryState state;
91 private final EventManager eventManager;
93 Map<Class<? extends RepositoryFeature<?>>, RepositoryFeature<?>> featureMap = new HashMap<>( );
95 private ArchivaIndexingContext indexingContext;
96 private RepositoryStorage storage;
98 public AbstractRepository(RepositoryType type, String id, String name, RepositoryStorage repositoryStorage) {
100 this.names.put( primaryLocale, name);
102 this.storage = repositoryStorage;
103 this.location = repositoryStorage.getLocation();
104 this.openStatus.compareAndSet(false, true);
105 this.eventManager = new EventManager(this);
108 public AbstractRepository(Locale primaryLocale, RepositoryType type, String id, String name, RepositoryStorage repositoryStorage) {
109 setPrimaryLocale( primaryLocale );
111 this.names.put( primaryLocale, name);
113 this.storage = repositoryStorage;
114 this.location = repositoryStorage.getLocation();
115 this.openStatus.compareAndSet(false, true);
116 this.eventManager = new EventManager(this);
119 protected void setPrimaryLocale(Locale locale) {
120 this.primaryLocale = locale;
124 public String getId( )
130 public String getName( )
132 return getName( primaryLocale );
136 public String getName( Locale locale )
138 return names.get(locale);
142 public String getDescription( )
144 return getDescription( primaryLocale );
148 public String getDescription( Locale locale )
150 return descriptions.get(primaryLocale);
154 public RepositoryType getType( )
160 public URI getLocation( )
166 public StorageAsset getRoot( )
168 return storage.getRoot( );
172 public Set<URI> getFailoverLocations( )
174 return uFailoverLocations;
178 public boolean isScanned( )
184 public String getSchedulingDefinition( )
186 return schedulingDefinition;
190 public abstract boolean hasIndex( );
193 public String getLayout( )
199 public abstract RepositoryCapabilities getCapabilities( );
201 @SuppressWarnings( "unchecked" )
203 public <T extends RepositoryFeature<T>> RepositoryFeature<T> getFeature( Class<T> clazz ) throws UnsupportedFeatureException
205 if (featureMap.containsKey( clazz )) {
206 return (RepositoryFeature<T>) featureMap.get(clazz);
209 throw new UnsupportedFeatureException( "Feature " + clazz + " not supported" );
214 public <T extends RepositoryFeature<T>> boolean supportsFeature( Class<T> clazz )
216 return featureMap.containsKey( clazz );
220 public Locale getPrimaryLocale( )
222 return primaryLocale;
226 public void setName( Locale locale, String name )
228 names.put(locale, name);
232 public void setDescription( Locale locale, String description )
234 descriptions.put(locale, description);
238 public void setLocation( final URI location )
240 if (location!=null && ( this.location == null || !this.location.equals(location))) {
242 updateLocation(location);
243 } catch (IOException e) {
244 log.error("Could not update location of repository {} to {}", getId(), location, e);
250 public void updateLocation(URI newLocation) throws IOException {
251 storage.updateLocation(newLocation);
252 this.location = newLocation;
256 public void addFailoverLocation( URI location )
258 this.failoverLocations.add(location);
262 public void removeFailoverLocation( URI location )
264 this.failoverLocations.remove( location );
268 public void clearFailoverLocations( )
270 this.failoverLocations.clear();
274 public void setScanned( boolean scanned )
276 this.scanned = scanned;
280 public void setLayout( String layout )
282 this.layout = layout;
286 public void setBaseUri(URI baseUri) {
287 this.baseUri = baseUri;
291 public void setSchedulingDefinition(String cronExpression) {
292 this.schedulingDefinition = cronExpression;
295 @SuppressWarnings( "unchecked" )
296 protected <T extends RepositoryFeature<T>> void addFeature(RepositoryFeature<T> feature) {
297 featureMap.put( (Class<? extends RepositoryFeature<?>>) feature.getClass(), feature);
301 public void setIndexingContext(ArchivaIndexingContext context) {
302 this.indexingContext = context;
306 public ArchivaIndexingContext getIndexingContext() {
307 return indexingContext;
311 public void close() {
312 if (this.openStatus.compareAndSet(true, false)) {
313 ArchivaIndexingContext ctx = getIndexingContext();
317 } catch (IOException e) {
318 log.warn("Error during index context close.", e);
320 this.indexingContext = null;
323 if (supportsFeature(StagingRepositoryFeature.class)) {
324 StagingRepositoryFeature sf = getFeature(StagingRepositoryFeature.class).get();
325 if (sf.getStagingRepository() != null) {
326 sf.getStagingRepository().close();
329 setLastState( RepositoryState.CLOSED );
335 public boolean isOpen() {
336 return openStatus.get();
340 public void handle(RepositoryEvent event) {
341 // We just rethrow the events
342 eventManager.fireEvent(event);
346 public <T extends Event> void registerEventHandler( EventType<T> eventType, EventHandler<? super T> eventHandler) {
347 if (!EventType.isInstanceOf(eventType, RepositoryEvent.ANY)) {
348 throw new IllegalArgumentException("Can only register RepositoryEvent Handlers");
350 eventManager.registerEventHandler(eventType, eventHandler);
354 public <T extends Event> void unregisterEventHandler(EventType<T> type, EventHandler<? super T> eventHandler) {
355 eventManager.unregisterEventHandler(type, eventHandler);
359 public StorageAsset getAsset(String path )
361 return storage.getAsset(path);
365 public StorageAsset addAsset( String path, boolean container )
367 return storage.addAsset(path, container);
371 public void removeAsset( StorageAsset asset ) throws IOException
373 storage.removeAsset(asset);
377 public StorageAsset moveAsset( StorageAsset origin, String destination, CopyOption... copyOptions ) throws IOException
379 return storage.moveAsset(origin, destination);
383 public void moveAsset( StorageAsset origin, StorageAsset destination, CopyOption... copyOptions ) throws IOException
385 storage.moveAsset( origin, destination, copyOptions );
389 public StorageAsset copyAsset( StorageAsset origin, String destination, CopyOption... copyOptions ) throws IOException
391 return storage.copyAsset(origin, destination);
395 public void copyAsset( StorageAsset origin, StorageAsset destination, CopyOption... copyOptions ) throws IOException
397 storage.copyAsset( origin, destination, copyOptions);
401 public void consumeData(StorageAsset asset, Consumer<InputStream> consumerFunction, boolean readLock ) throws IOException
403 storage.consumeData(asset, consumerFunction, readLock);
407 public void consumeDataFromChannel( StorageAsset asset, Consumer<ReadableByteChannel> consumerFunction, boolean readLock ) throws IOException
409 storage.consumeDataFromChannel( asset, consumerFunction, readLock );
413 public void writeData( StorageAsset asset, Consumer<OutputStream> consumerFunction, boolean writeLock ) throws IOException
415 storage.writeData( asset, consumerFunction, writeLock );
419 public void writeDataToChannel( StorageAsset asset, Consumer<WritableByteChannel> consumerFunction, boolean writeLock ) throws IOException
421 storage.writeDataToChannel( asset, consumerFunction, writeLock );
424 protected void setStorage( RepositoryStorage storage) {
425 this.storage = storage;
428 protected RepositoryStorage getStorage() {
434 public RepositoryState getLastState( )
440 public void setLastState( RepositoryState state )