1 package org.apache.archiva.repository;
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.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;
36 import java.io.IOException;
37 import java.io.InputStream;
38 import java.io.OutputStream;
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;
51 import java.util.concurrent.atomic.AtomicBoolean;
52 import java.util.function.Consumer;
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.
59 public abstract class AbstractRepository implements EditableRepository, EventHandler<RepositoryEvent>
63 Logger log = LoggerFactory.getLogger(AbstractRepository.class);
65 private final AtomicBoolean openStatus = new AtomicBoolean(false);
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<>( );
73 private Locale primaryLocale = new Locale("en_US");
74 protected URI location;
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);
83 private final EventManager eventManager;
85 Map<Class<? extends RepositoryFeature<?>>, RepositoryFeature<?>> featureMap = new HashMap<>( );
87 private ArchivaIndexingContext indexingContext;
88 private RepositoryStorage storage;
90 public AbstractRepository(RepositoryType type, String id, String name, RepositoryStorage repositoryStorage) {
92 this.names.put( primaryLocale, name);
94 this.storage = repositoryStorage;
95 this.location = repositoryStorage.getLocation();
96 this.openStatus.compareAndSet(false, true);
97 this.eventManager = new EventManager(this);
100 public AbstractRepository(Locale primaryLocale, RepositoryType type, String id, String name, RepositoryStorage repositoryStorage) {
101 setPrimaryLocale( primaryLocale );
103 this.names.put( primaryLocale, name);
105 this.storage = repositoryStorage;
106 this.location = repositoryStorage.getLocation();
107 this.openStatus.compareAndSet(false, true);
108 this.eventManager = new EventManager(this);
111 protected void setPrimaryLocale(Locale locale) {
112 this.primaryLocale = locale;
116 public String getId( )
122 public String getName( )
124 return getName( primaryLocale );
128 public String getName( Locale locale )
130 return names.get(locale);
134 public String getDescription( )
136 return getDescription( primaryLocale );
140 public String getDescription( Locale locale )
142 return descriptions.get(primaryLocale);
146 public RepositoryType getType( )
152 public URI getLocation( )
158 public StorageAsset getLocalPath() {
159 return storage.getAsset("");
163 public Set<URI> getFailoverLocations( )
165 return uFailoverLocations;
169 public boolean isScanned( )
175 public String getSchedulingDefinition( )
177 return schedulingDefinition;
181 public abstract boolean hasIndex( );
184 public String getLayout( )
190 public abstract RepositoryCapabilities getCapabilities( );
192 @SuppressWarnings( "unchecked" )
194 public <T extends RepositoryFeature<T>> RepositoryFeature<T> getFeature( Class<T> clazz ) throws UnsupportedFeatureException
196 if (featureMap.containsKey( clazz )) {
197 return (RepositoryFeature<T>) featureMap.get(clazz);
200 throw new UnsupportedFeatureException( "Feature " + clazz + " not supported" );
205 public <T extends RepositoryFeature<T>> boolean supportsFeature( Class<T> clazz )
207 return featureMap.containsKey( clazz );
211 public Locale getPrimaryLocale( )
213 return primaryLocale;
217 public void setName( Locale locale, String name )
219 names.put(locale, name);
223 public void setDescription( Locale locale, String description )
225 descriptions.put(locale, description);
229 public void setLocation( final URI location )
231 if (location!=null && ( this.location == null || !this.location.equals(location))) {
233 updateLocation(location);
234 } catch (IOException e) {
235 log.error("Could not update location of repository {} to {}", getId(), location, e);
241 public void updateLocation(URI newLocation) throws IOException {
242 storage.updateLocation(newLocation);
243 this.location = newLocation;
247 public void addFailoverLocation( URI location )
249 this.failoverLocations.add(location);
253 public void removeFailoverLocation( URI location )
255 this.failoverLocations.remove( location );
259 public void clearFailoverLocations( )
261 this.failoverLocations.clear();
265 public void setScanned( boolean scanned )
267 this.scanned = scanned;
271 public void setLayout( String layout )
273 this.layout = layout;
277 public void setBaseUri(URI baseUri) {
278 this.baseUri = baseUri;
282 public void setSchedulingDefinition(String cronExpression) {
283 if (StringUtils.isNotEmpty( cronExpression ))
285 CronParser parser = new CronParser( CRON_DEFINITION );
286 parser.parse( cronExpression ).validate( );
288 this.schedulingDefinition = cronExpression;
291 @SuppressWarnings( "unchecked" )
292 protected <T extends RepositoryFeature<T>> void addFeature(RepositoryFeature<T> feature) {
293 featureMap.put( (Class<? extends RepositoryFeature<?>>) feature.getClass(), feature);
297 public void setIndexingContext(ArchivaIndexingContext context) {
298 if (this.indexingContext!=null) {
301 this.indexingContext = context;
305 public ArchivaIndexingContext getIndexingContext() {
306 return indexingContext;
310 public void close() {
311 if (this.openStatus.compareAndSet(true, false)) {
312 ArchivaIndexingContext ctx = getIndexingContext();
316 } catch (IOException e) {
317 log.warn("Error during index context close.", e);
319 this.indexingContext = null;
322 if (supportsFeature(StagingRepositoryFeature.class)) {
323 StagingRepositoryFeature sf = getFeature(StagingRepositoryFeature.class).get();
324 if (sf.getStagingRepository() != null) {
325 sf.getStagingRepository().close();
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() {