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.common.utils.PathUtil;
27 import org.apache.archiva.indexer.ArchivaIndexingContext;
28 import org.apache.archiva.repository.content.RepositoryStorage;
29 import org.apache.archiva.repository.content.StorageAsset;
30 import org.apache.archiva.repository.features.RepositoryFeature;
31 import org.apache.archiva.repository.features.StagingRepositoryFeature;
32 import org.apache.commons.lang.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.nio.file.Path;
44 import java.util.ArrayList;
45 import java.util.Collections;
46 import java.util.HashMap;
47 import java.util.HashSet;
48 import java.util.List;
49 import java.util.Locale;
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, RepositoryEventListener
63 Logger log = LoggerFactory.getLogger(AbstractRepository.class);
65 private final RepositoryType type;
66 private final String id;
67 private Map<Locale, String> names = new HashMap<>( );
68 private Map<Locale, String> descriptions = new HashMap<>( );
70 private Locale primaryLocale = new Locale("en_US");
73 private Set<URI> failoverLocations = new HashSet<>( );
74 private Set<URI> uFailoverLocations = Collections.unmodifiableSet( failoverLocations );
75 private boolean scanned = true;
76 String schedulingDefinition = "0 0 02 * * ?";
77 private String layout = "default";
78 public static final CronDefinition CRON_DEFINITION = CronDefinitionBuilder.instanceDefinitionFor(CronType.QUARTZ);
79 private List<RepositoryEventListener> listeners = new ArrayList<>();
82 Map<Class<? extends RepositoryFeature<?>>, RepositoryFeature<?>> featureMap = new HashMap<>( );
84 private ArchivaIndexingContext indexingContext;
85 private RepositoryStorage storage;
87 public AbstractRepository(RepositoryType type, String id, String name, RepositoryStorage repositoryStorage) {
89 this.names.put( primaryLocale, name);
91 this.storage = repositoryStorage;
94 public AbstractRepository(Locale primaryLocale, RepositoryType type, String id, String name, RepositoryStorage repositoryStorage) {
95 setPrimaryLocale( primaryLocale );
97 this.names.put( primaryLocale, name);
99 this.storage = repositoryStorage;
102 protected void setPrimaryLocale(Locale locale) {
103 this.primaryLocale = locale;
107 public String getId( )
113 public String getName( )
115 return getName( primaryLocale );
119 public String getName( Locale locale )
121 return names.get(locale);
125 public String getDescription( )
127 return getDescription( primaryLocale );
131 public String getDescription( Locale locale )
133 return descriptions.get(primaryLocale);
137 public RepositoryType getType( )
143 public URI getLocation( )
149 public Path getLocalPath() {
150 return storage.getAsset("").getFilePath();
152 // if (StringUtils.isEmpty(getLocation().getScheme()) || "file".equals(getLocation().getScheme()) ) {
153 // localPath = PathUtil.getPathFromUri(getLocation());
154 // if (localPath.isAbsolute()) {
157 // return repositoryBase.resolve(localPath);
160 // return repositoryBase.resolve(getId());
165 public Set<URI> getFailoverLocations( )
167 return uFailoverLocations;
171 public boolean isScanned( )
177 public String getSchedulingDefinition( )
179 return schedulingDefinition;
183 public abstract boolean hasIndex( );
186 public String getLayout( )
192 public abstract RepositoryCapabilities getCapabilities( );
194 @SuppressWarnings( "unchecked" )
196 public <T extends RepositoryFeature<T>> RepositoryFeature<T> getFeature( Class<T> clazz ) throws UnsupportedFeatureException
198 if (featureMap.containsKey( clazz )) {
199 return (RepositoryFeature<T>) featureMap.get(clazz);
202 throw new UnsupportedFeatureException( "Feature " + clazz + " not supported" );
207 public <T extends RepositoryFeature<T>> boolean supportsFeature( Class<T> clazz )
209 return featureMap.containsKey( clazz );
213 public Locale getPrimaryLocale( )
215 return primaryLocale;
219 public void setName( Locale locale, String name )
221 names.put(locale, name);
225 public void setDescription( Locale locale, String description )
227 descriptions.put(locale, description);
231 public void setLocation( URI location )
233 this.location = location;
237 public void addFailoverLocation( URI location )
239 this.failoverLocations.add(location);
243 public void removeFailoverLocation( URI location )
245 this.failoverLocations.remove( location );
249 public void clearFailoverLocations( )
251 this.failoverLocations.clear();
255 public void setScanned( boolean scanned )
257 this.scanned = scanned;
261 public void setLayout( String layout )
263 this.layout = layout;
267 public void setBaseUri(URI baseUri) {
268 this.baseUri = baseUri;
272 public void setSchedulingDefinition(String cronExpression) {
273 if (StringUtils.isNotEmpty( cronExpression ))
275 CronParser parser = new CronParser( CRON_DEFINITION );
276 parser.parse( cronExpression ).validate( );
278 this.schedulingDefinition = cronExpression;
281 @SuppressWarnings( "unchecked" )
282 protected <T extends RepositoryFeature<T>> void addFeature(RepositoryFeature<T> feature) {
283 featureMap.put( (Class<? extends RepositoryFeature<?>>) feature.getClass(), feature);
287 public void setIndexingContext(ArchivaIndexingContext context) {
288 this.indexingContext = context;
292 public ArchivaIndexingContext getIndexingContext() {
293 return indexingContext;
297 public void close() {
298 ArchivaIndexingContext ctx = getIndexingContext();
302 } catch (IOException e) {
303 log.warn("Error during index context close.",e);
306 if (supportsFeature(StagingRepositoryFeature.class)) {
307 StagingRepositoryFeature sf = getFeature(StagingRepositoryFeature.class).get();
308 if (sf.getStagingRepository()!=null) {
309 sf.getStagingRepository().close();
316 public <T> void raise(RepositoryEvent<T> event) {
317 for(RepositoryEventListener listener : listeners) {
318 listener.raise(event);
322 public void addListener(RepositoryEventListener listener) {
323 if (!this.listeners.contains(listener)) {
324 this.listeners.add(listener);
328 public void removeListener(RepositoryEventListener listener) {
329 this.removeListener(listener);
332 public void clearListeners() {
333 this.listeners.clear();
337 public StorageAsset getAsset(String path )
339 return storage.getAsset(path);
343 public StorageAsset addAsset( String path, boolean container )
345 return storage.addAsset(path, container);
349 public void removeAsset( StorageAsset asset ) throws IOException
351 storage.removeAsset(asset);
355 public StorageAsset moveAsset( StorageAsset origin, String destination, CopyOption... copyOptions ) throws IOException
357 return storage.moveAsset(origin, destination);
361 public void moveAsset( StorageAsset origin, StorageAsset destination, CopyOption... copyOptions ) throws IOException
363 storage.moveAsset( origin, destination, copyOptions );
367 public StorageAsset copyAsset( StorageAsset origin, String destination, CopyOption... copyOptions ) throws IOException
369 return storage.copyAsset(origin, destination);
373 public void copyAsset( StorageAsset origin, StorageAsset destination, CopyOption... copyOptions ) throws IOException
375 storage.copyAsset( origin, destination, copyOptions);
379 public void consumeData(StorageAsset asset, Consumer<InputStream> consumerFunction, boolean readLock ) throws IOException
381 storage.consumeData(asset, consumerFunction, readLock);
385 public void consumeDataFromChannel( StorageAsset asset, Consumer<ReadableByteChannel> consumerFunction, boolean readLock ) throws IOException
387 storage.consumeDataFromChannel( asset, consumerFunction, readLock );
391 public void writeData( StorageAsset asset, Consumer<OutputStream> consumerFunction, boolean writeLock ) throws IOException
393 storage.writeData( asset, consumerFunction, writeLock );
397 public void writeDataToChannel( StorageAsset asset, Consumer<WritableByteChannel> consumerFunction, boolean writeLock ) throws IOException
399 storage.writeDataToChannel( asset, consumerFunction, writeLock );
402 protected void setStorage( RepositoryStorage storage) {
403 this.storage = storage;
406 protected RepositoryStorage getStorage() {