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.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.apache.commons.lang3.StringUtils;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
44 import java.io.IOException;
45 import java.io.InputStream;
46 import java.io.OutputStream;
48 import java.nio.channels.ReadableByteChannel;
49 import java.nio.channels.WritableByteChannel;
50 import java.nio.file.CopyOption;
51 import java.util.Collections;
52 import java.util.HashMap;
53 import java.util.HashSet;
54 import java.util.Locale;
57 import java.util.concurrent.atomic.AtomicBoolean;
58 import java.util.function.Consumer;
61 * Implementation of a repository with the necessary fields for a bare repository.
62 * No features are provided. Capabilities and features must be implemented by concrete classes.
65 public abstract class AbstractRepository implements EditableRepository, EventHandler<RepositoryEvent>
69 Logger log = LoggerFactory.getLogger(AbstractRepository.class);
71 private final AtomicBoolean openStatus = new AtomicBoolean(false);
74 private final RepositoryType type;
75 private final String id;
76 private Map<Locale, String> names = new HashMap<>( );
77 private Map<Locale, String> descriptions = new HashMap<>( );
79 private Locale primaryLocale = new Locale("en_US");
80 protected URI location;
82 private Set<URI> failoverLocations = new HashSet<>( );
83 private Set<URI> uFailoverLocations = Collections.unmodifiableSet( failoverLocations );
84 private boolean scanned = true;
85 String schedulingDefinition = "0 0 02 * * ?";
86 private String layout = "default";
87 public static final CronDefinition CRON_DEFINITION = CronDefinitionBuilder.instanceDefinitionFor(CronType.QUARTZ);
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 getLocalPath() {
165 return storage.getRoot( );
169 public StorageAsset getRoot( )
171 return storage.getRoot( );
175 public Set<URI> getFailoverLocations( )
177 return uFailoverLocations;
181 public boolean isScanned( )
187 public String getSchedulingDefinition( )
189 return schedulingDefinition;
193 public abstract boolean hasIndex( );
196 public String getLayout( )
202 public abstract RepositoryCapabilities getCapabilities( );
204 @SuppressWarnings( "unchecked" )
206 public <T extends RepositoryFeature<T>> RepositoryFeature<T> getFeature( Class<T> clazz ) throws UnsupportedFeatureException
208 if (featureMap.containsKey( clazz )) {
209 return (RepositoryFeature<T>) featureMap.get(clazz);
212 throw new UnsupportedFeatureException( "Feature " + clazz + " not supported" );
217 public <T extends RepositoryFeature<T>> boolean supportsFeature( Class<T> clazz )
219 return featureMap.containsKey( clazz );
223 public Locale getPrimaryLocale( )
225 return primaryLocale;
229 public void setName( Locale locale, String name )
231 names.put(locale, name);
235 public void setDescription( Locale locale, String description )
237 descriptions.put(locale, description);
241 public void setLocation( final URI location )
243 if (location!=null && ( this.location == null || !this.location.equals(location))) {
245 updateLocation(location);
246 } catch (IOException e) {
247 log.error("Could not update location of repository {} to {}", getId(), location, e);
253 public void updateLocation(URI newLocation) throws IOException {
254 storage.updateLocation(newLocation);
255 this.location = newLocation;
259 public void addFailoverLocation( URI location )
261 this.failoverLocations.add(location);
265 public void removeFailoverLocation( URI location )
267 this.failoverLocations.remove( location );
271 public void clearFailoverLocations( )
273 this.failoverLocations.clear();
277 public void setScanned( boolean scanned )
279 this.scanned = scanned;
283 public void setLayout( String layout )
285 this.layout = layout;
289 public void setBaseUri(URI baseUri) {
290 this.baseUri = baseUri;
294 public void setSchedulingDefinition(String cronExpression) {
295 if (StringUtils.isNotEmpty( cronExpression ))
297 CronParser parser = new CronParser( CRON_DEFINITION );
298 parser.parse( cronExpression ).validate( );
300 this.schedulingDefinition = cronExpression;
303 @SuppressWarnings( "unchecked" )
304 protected <T extends RepositoryFeature<T>> void addFeature(RepositoryFeature<T> feature) {
305 featureMap.put( (Class<? extends RepositoryFeature<?>>) feature.getClass(), feature);
309 public void setIndexingContext(ArchivaIndexingContext context) {
310 if (this.indexingContext!=null) {
313 this.indexingContext = context;
317 public ArchivaIndexingContext getIndexingContext() {
318 return indexingContext;
322 public void close() {
323 if (this.openStatus.compareAndSet(true, false)) {
324 ArchivaIndexingContext ctx = getIndexingContext();
328 } catch (IOException e) {
329 log.warn("Error during index context close.", e);
331 this.indexingContext = null;
334 if (supportsFeature(StagingRepositoryFeature.class)) {
335 StagingRepositoryFeature sf = getFeature(StagingRepositoryFeature.class).get();
336 if (sf.getStagingRepository() != null) {
337 sf.getStagingRepository().close();
345 public boolean isOpen() {
346 return openStatus.get();
350 public void handle(RepositoryEvent event) {
351 // We just rethrow the events
352 eventManager.fireEvent(event);
356 public <T extends Event> void registerEventHandler( EventType<T> eventType, EventHandler<? super T> eventHandler) {
357 if (!EventType.isInstanceOf(eventType, RepositoryEvent.ANY)) {
358 throw new IllegalArgumentException("Can only register RepositoryEvent Handlers");
360 eventManager.registerEventHandler(eventType, eventHandler);
364 public <T extends Event> void unregisterEventHandler(EventType<T> type, EventHandler<? super T> eventHandler) {
365 eventManager.unregisterEventHandler(type, eventHandler);
369 public StorageAsset getAsset(String path )
371 return storage.getAsset(path);
375 public StorageAsset addAsset( String path, boolean container )
377 return storage.addAsset(path, container);
381 public void removeAsset( StorageAsset asset ) throws IOException
383 storage.removeAsset(asset);
387 public StorageAsset moveAsset( StorageAsset origin, String destination, CopyOption... copyOptions ) throws IOException
389 return storage.moveAsset(origin, destination);
393 public void moveAsset( StorageAsset origin, StorageAsset destination, CopyOption... copyOptions ) throws IOException
395 storage.moveAsset( origin, destination, copyOptions );
399 public StorageAsset copyAsset( StorageAsset origin, String destination, CopyOption... copyOptions ) throws IOException
401 return storage.copyAsset(origin, destination);
405 public void copyAsset( StorageAsset origin, StorageAsset destination, CopyOption... copyOptions ) throws IOException
407 storage.copyAsset( origin, destination, copyOptions);
411 public void consumeData(StorageAsset asset, Consumer<InputStream> consumerFunction, boolean readLock ) throws IOException
413 storage.consumeData(asset, consumerFunction, readLock);
417 public void consumeDataFromChannel( StorageAsset asset, Consumer<ReadableByteChannel> consumerFunction, boolean readLock ) throws IOException
419 storage.consumeDataFromChannel( asset, consumerFunction, readLock );
423 public void writeData( StorageAsset asset, Consumer<OutputStream> consumerFunction, boolean writeLock ) throws IOException
425 storage.writeData( asset, consumerFunction, writeLock );
429 public void writeDataToChannel( StorageAsset asset, Consumer<WritableByteChannel> consumerFunction, boolean writeLock ) throws IOException
431 storage.writeDataToChannel( asset, consumerFunction, writeLock );
434 protected void setStorage( RepositoryStorage storage) {
435 this.storage = storage;
438 protected RepositoryStorage getStorage() {