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 org.apache.archiva.event.Event;
26 import org.apache.archiva.event.EventHandler;
27 import org.apache.archiva.event.EventManager;
28 import org.apache.archiva.event.EventType;
29 import org.apache.archiva.indexer.ArchivaIndexingContext;
30 import org.apache.archiva.repository.EditableRepository;
31 import org.apache.archiva.repository.RepositoryCapabilities;
32 import org.apache.archiva.repository.RepositoryState;
33 import org.apache.archiva.repository.RepositoryType;
34 import org.apache.archiva.repository.UnsupportedFeatureException;
35 import org.apache.archiva.repository.event.*;
36 import org.apache.archiva.repository.storage.RepositoryStorage;
37 import org.apache.archiva.repository.storage.StorageAsset;
38 import org.apache.archiva.repository.features.RepositoryFeature;
39 import org.apache.archiva.repository.features.StagingRepositoryFeature;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
43 import java.io.IOException;
44 import java.io.InputStream;
45 import java.io.OutputStream;
47 import java.nio.channels.ReadableByteChannel;
48 import java.nio.channels.WritableByteChannel;
49 import java.nio.file.CopyOption;
50 import java.util.Collections;
51 import java.util.HashMap;
52 import java.util.HashSet;
53 import java.util.Locale;
56 import java.util.concurrent.atomic.AtomicBoolean;
57 import java.util.function.Consumer;
60 * Implementation of a repository with the necessary fields for a bare repository.
61 * No features are provided. Capabilities and features must be implemented by concrete classes.
64 public abstract class AbstractRepository implements EditableRepository, EventHandler<RepositoryEvent>
68 Logger log = LoggerFactory.getLogger(AbstractRepository.class);
70 private final AtomicBoolean openStatus = new AtomicBoolean(false);
73 private final RepositoryType type;
74 private final String id;
75 private Map<Locale, String> names = new HashMap<>( );
76 private Map<Locale, String> descriptions = new HashMap<>( );
78 private Locale primaryLocale = new Locale("en_US");
79 protected URI location;
81 private Set<URI> failoverLocations = new HashSet<>( );
82 private Set<URI> uFailoverLocations = Collections.unmodifiableSet( failoverLocations );
83 private boolean scanned = true;
84 String schedulingDefinition = "0 0 02 * * ?";
85 private String layout = "default";
86 public static final CronDefinition CRON_DEFINITION = CronDefinitionBuilder.instanceDefinitionFor(CronType.QUARTZ);
87 private RepositoryState state;
89 private final EventManager eventManager;
91 Map<Class<? extends RepositoryFeature<?>>, RepositoryFeature<?>> featureMap = new HashMap<>( );
93 private ArchivaIndexingContext indexingContext;
94 private RepositoryStorage storage;
96 public AbstractRepository(RepositoryType type, String id, String name, RepositoryStorage repositoryStorage) {
98 this.names.put( primaryLocale, name);
100 this.storage = repositoryStorage;
101 this.location = repositoryStorage.getLocation();
102 this.openStatus.compareAndSet(false, true);
103 this.eventManager = new EventManager(this);
106 public AbstractRepository(Locale primaryLocale, RepositoryType type, String id, String name, RepositoryStorage repositoryStorage) {
107 setPrimaryLocale( primaryLocale );
109 this.names.put( primaryLocale, name);
111 this.storage = repositoryStorage;
112 this.location = repositoryStorage.getLocation();
113 this.openStatus.compareAndSet(false, true);
114 this.eventManager = new EventManager(this);
117 protected void setPrimaryLocale(Locale locale) {
118 this.primaryLocale = locale;
122 public String getId( )
128 public String getName( )
130 return getName( primaryLocale );
134 public String getName( Locale locale )
136 return names.get(locale);
140 public String getDescription( )
142 return getDescription( primaryLocale );
146 public String getDescription( Locale locale )
148 return descriptions.get(primaryLocale);
152 public RepositoryType getType( )
158 public URI getLocation( )
164 public StorageAsset getRoot( )
166 return storage.getRoot( );
170 public Set<URI> getFailoverLocations( )
172 return uFailoverLocations;
176 public boolean isScanned( )
182 public String getSchedulingDefinition( )
184 return schedulingDefinition;
188 public abstract boolean hasIndex( );
191 public String getLayout( )
197 public abstract RepositoryCapabilities getCapabilities( );
199 @SuppressWarnings( "unchecked" )
201 public <T extends RepositoryFeature<T>> T getFeature( Class<T> clazz ) throws UnsupportedFeatureException
203 if (featureMap.containsKey( clazz )) {
204 return (T) featureMap.get(clazz);
207 throw new UnsupportedFeatureException( "Feature " + clazz + " not supported" );
212 public <T extends RepositoryFeature<T>> boolean supportsFeature( Class<T> clazz )
214 return featureMap.containsKey( clazz );
218 public Locale getPrimaryLocale( )
220 return primaryLocale;
224 public void setName( Locale locale, String name )
226 names.put(locale, name);
230 public void setDescription( Locale locale, String description )
232 descriptions.put(locale, description);
236 public void setLocation( final URI location )
238 if (location!=null && ( this.location == null || !this.location.equals(location))) {
240 updateLocation(location);
241 } catch (IOException e) {
242 log.error("Could not update location of repository {} to {}", getId(), location, e);
248 public void updateLocation(URI newLocation) throws IOException {
249 storage.updateLocation(newLocation);
250 this.location = newLocation;
254 public void addFailoverLocation( URI location )
256 this.failoverLocations.add(location);
260 public void removeFailoverLocation( URI location )
262 this.failoverLocations.remove( location );
266 public void clearFailoverLocations( )
268 this.failoverLocations.clear();
272 public void setScanned( boolean scanned )
274 this.scanned = scanned;
278 public void setLayout( String layout )
280 this.layout = layout;
284 public void setBaseUri(URI baseUri) {
285 this.baseUri = baseUri;
289 public void setSchedulingDefinition(String cronExpression) {
290 this.schedulingDefinition = cronExpression;
293 @SuppressWarnings( "unchecked" )
294 protected <T extends RepositoryFeature<T>> void addFeature(RepositoryFeature<T> feature) {
295 featureMap.put( (Class<? extends RepositoryFeature<?>>) feature.getClass(), feature);
299 public void setIndexingContext(ArchivaIndexingContext context) {
300 this.indexingContext = context;
304 public ArchivaIndexingContext getIndexingContext() {
305 return indexingContext;
309 public void close() {
310 if (this.openStatus.compareAndSet(true, false)) {
311 ArchivaIndexingContext ctx = getIndexingContext();
315 } catch (IOException e) {
316 log.warn("Error during index context close.", e);
318 this.indexingContext = null;
321 if (supportsFeature(StagingRepositoryFeature.class)) {
322 StagingRepositoryFeature sf = getFeature( StagingRepositoryFeature.class );
323 if (sf.getStagingRepository() != null) {
324 sf.getStagingRepository().close();
327 setLastState( RepositoryState.CLOSED );
333 public boolean isOpen() {
334 return openStatus.get();
338 public void handle(RepositoryEvent event) {
339 // We just rethrow the events
340 eventManager.fireEvent(event);
344 public <T extends Event> void registerEventHandler( EventType<T> eventType, EventHandler<? super T> eventHandler) {
345 if (!EventType.isInstanceOf(eventType, RepositoryEvent.ANY)) {
346 throw new IllegalArgumentException("Can only register RepositoryEvent Handlers");
348 eventManager.registerEventHandler(eventType, eventHandler);
352 public <T extends Event> void unregisterEventHandler(EventType<T> type, EventHandler<? super T> eventHandler) {
353 eventManager.unregisterEventHandler(type, eventHandler);
357 public StorageAsset getAsset(String path )
359 return storage.getAsset(path);
363 public StorageAsset addAsset( String path, boolean container )
365 return storage.addAsset(path, container);
369 public void removeAsset( StorageAsset asset ) throws IOException
371 storage.removeAsset(asset);
375 public StorageAsset moveAsset( StorageAsset origin, String destination, CopyOption... copyOptions ) throws IOException
377 return storage.moveAsset(origin, destination);
381 public void moveAsset( StorageAsset origin, StorageAsset destination, CopyOption... copyOptions ) throws IOException
383 storage.moveAsset( origin, destination, copyOptions );
387 public StorageAsset copyAsset( StorageAsset origin, String destination, CopyOption... copyOptions ) throws IOException
389 return storage.copyAsset(origin, destination);
393 public void copyAsset( StorageAsset origin, StorageAsset destination, CopyOption... copyOptions ) throws IOException
395 storage.copyAsset( origin, destination, copyOptions);
399 public void consumeData(StorageAsset asset, Consumer<InputStream> consumerFunction, boolean readLock ) throws IOException
401 storage.consumeData(asset, consumerFunction, readLock);
405 public void consumeDataFromChannel( StorageAsset asset, Consumer<ReadableByteChannel> consumerFunction, boolean readLock ) throws IOException
407 storage.consumeDataFromChannel( asset, consumerFunction, readLock );
411 public void writeData( StorageAsset asset, Consumer<OutputStream> consumerFunction, boolean writeLock ) throws IOException
413 storage.writeData( asset, consumerFunction, writeLock );
417 public void writeDataToChannel( StorageAsset asset, Consumer<WritableByteChannel> consumerFunction, boolean writeLock ) throws IOException
419 storage.writeDataToChannel( asset, consumerFunction, writeLock );
422 protected void setStorage( RepositoryStorage storage) {
423 this.storage = storage;
426 protected RepositoryStorage getStorage() {
432 public RepositoryState getLastState( )
438 public void setLastState( RepositoryState state )