This project has retired. For details please refer to its Attic page.
Source code
001package org.apache.archiva.repository.base;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 *  http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import com.cronutils.model.CronType;
023import com.cronutils.model.definition.CronDefinition;
024import com.cronutils.model.definition.CronDefinitionBuilder;
025import com.cronutils.parser.CronParser;
026import org.apache.archiva.event.Event;
027import org.apache.archiva.event.EventHandler;
028import org.apache.archiva.event.EventManager;
029import org.apache.archiva.event.EventType;
030import org.apache.archiva.indexer.ArchivaIndexingContext;
031import org.apache.archiva.repository.EditableRepository;
032import org.apache.archiva.repository.RepositoryCapabilities;
033import org.apache.archiva.repository.RepositoryType;
034import org.apache.archiva.repository.UnsupportedFeatureException;
035import org.apache.archiva.repository.event.*;
036import org.apache.archiva.repository.storage.RepositoryStorage;
037import org.apache.archiva.repository.storage.StorageAsset;
038import org.apache.archiva.repository.features.RepositoryFeature;
039import org.apache.archiva.repository.features.StagingRepositoryFeature;
040import org.apache.commons.lang3.StringUtils;
041import org.slf4j.Logger;
042import org.slf4j.LoggerFactory;
043
044import java.io.IOException;
045import java.io.InputStream;
046import java.io.OutputStream;
047import java.net.URI;
048import java.nio.channels.ReadableByteChannel;
049import java.nio.channels.WritableByteChannel;
050import java.nio.file.CopyOption;
051import java.util.Collections;
052import java.util.HashMap;
053import java.util.HashSet;
054import java.util.Locale;
055import java.util.Map;
056import java.util.Set;
057import java.util.concurrent.atomic.AtomicBoolean;
058import java.util.function.Consumer;
059
060/**
061 * Implementation of a repository with the necessary fields for a bare repository.
062 * No features are provided. Capabilities and features must be implemented by concrete classes.
063 *
064 */
065public abstract class AbstractRepository implements EditableRepository, EventHandler<RepositoryEvent>
066{
067
068
069    Logger log = LoggerFactory.getLogger(AbstractRepository.class);
070
071    private final AtomicBoolean openStatus = new AtomicBoolean(false);
072
073
074    private final RepositoryType type;
075    private final String id;
076    private Map<Locale, String> names = new HashMap<>(  );
077    private Map<Locale, String> descriptions = new HashMap<>(  );
078
079    private Locale primaryLocale = new Locale("en_US");
080    protected URI location;
081    private URI baseUri;
082    private Set<URI> failoverLocations = new HashSet<>(  );
083    private Set<URI> uFailoverLocations = Collections.unmodifiableSet( failoverLocations );
084    private boolean scanned = true;
085    String schedulingDefinition = "0 0 02 * * ?";
086    private String layout = "default";
087    public static final CronDefinition CRON_DEFINITION = CronDefinitionBuilder.instanceDefinitionFor(CronType.QUARTZ);
088
089    private final EventManager eventManager;
090
091    Map<Class<? extends RepositoryFeature<?>>, RepositoryFeature<?>> featureMap = new HashMap<>(  );
092
093    private ArchivaIndexingContext indexingContext;
094    private RepositoryStorage storage;
095
096    public AbstractRepository(RepositoryType type, String id, String name, RepositoryStorage repositoryStorage) {
097        this.id = id;
098        this.names.put( primaryLocale, name);
099        this.type = type;
100        this.storage = repositoryStorage;
101        this.location = repositoryStorage.getLocation();
102        this.openStatus.compareAndSet(false, true);
103        this.eventManager = new EventManager(this);
104    }
105
106    public AbstractRepository(Locale primaryLocale, RepositoryType type, String id, String name, RepositoryStorage repositoryStorage) {
107        setPrimaryLocale( primaryLocale );
108        this.id = id;
109        this.names.put( primaryLocale, name);
110        this.type = type;
111        this.storage = repositoryStorage;
112        this.location = repositoryStorage.getLocation();
113        this.openStatus.compareAndSet(false, true);
114        this.eventManager = new EventManager(this);
115    }
116
117    protected void setPrimaryLocale(Locale locale) {
118        this.primaryLocale = locale;
119    }
120
121    @Override
122    public String getId( )
123    {
124        return id;
125    }
126
127    @Override
128    public String getName( )
129    {
130        return getName( primaryLocale );
131    }
132
133    @Override
134    public String getName( Locale locale )
135    {
136        return names.get(locale);
137    }
138
139    @Override
140    public String getDescription( )
141    {
142        return getDescription( primaryLocale );
143    }
144
145    @Override
146    public String getDescription( Locale locale )
147    {
148        return descriptions.get(primaryLocale);
149    }
150
151    @Override
152    public RepositoryType getType( )
153    {
154        return type;
155    }
156
157    @Override
158    public URI getLocation( )
159    {
160        return location;
161    }
162
163    @Override
164    public StorageAsset getLocalPath() {
165        return storage.getAsset("");
166    }
167
168    @Override
169    public Set<URI> getFailoverLocations( )
170    {
171        return uFailoverLocations;
172    }
173
174    @Override
175    public boolean isScanned( )
176    {
177        return scanned;
178    }
179
180    @Override
181    public String getSchedulingDefinition( )
182    {
183        return schedulingDefinition;
184    }
185
186    @Override
187    public abstract boolean hasIndex( );
188
189    @Override
190    public String getLayout( )
191    {
192        return layout;
193    }
194
195    @Override
196    public abstract RepositoryCapabilities getCapabilities( );
197
198    @SuppressWarnings( "unchecked" )
199    @Override
200    public <T extends RepositoryFeature<T>> RepositoryFeature<T> getFeature( Class<T> clazz ) throws UnsupportedFeatureException
201    {
202        if (featureMap.containsKey( clazz )) {
203            return (RepositoryFeature<T>) featureMap.get(clazz);
204        } else
205        {
206            throw new UnsupportedFeatureException( "Feature " + clazz + " not supported" );
207        }
208    }
209
210    @Override
211    public <T extends RepositoryFeature<T>> boolean supportsFeature( Class<T> clazz )
212    {
213        return featureMap.containsKey( clazz );
214    }
215
216    @Override
217    public Locale getPrimaryLocale( )
218    {
219        return primaryLocale;
220    }
221
222    @Override
223    public void setName( Locale locale, String name )
224    {
225        names.put(locale, name);
226    }
227
228    @Override
229    public void setDescription( Locale locale, String description )
230    {
231        descriptions.put(locale, description);
232    }
233
234    @Override
235    public void setLocation( final URI location )
236    {
237        if (location!=null && ( this.location == null || !this.location.equals(location))) {
238            try {
239                updateLocation(location);
240            } catch (IOException e) {
241                log.error("Could not update location of repository {} to {}", getId(), location, e);
242            }
243        }
244    }
245
246    @Override
247    public void updateLocation(URI newLocation) throws IOException {
248        storage.updateLocation(newLocation);
249        this.location = newLocation;
250    }
251
252    @Override
253    public void addFailoverLocation( URI location )
254    {
255        this.failoverLocations.add(location);
256    }
257
258    @Override
259    public void removeFailoverLocation( URI location )
260    {
261        this.failoverLocations.remove( location );
262    }
263
264    @Override
265    public void clearFailoverLocations( )
266    {
267        this.failoverLocations.clear();
268    }
269
270    @Override
271    public void setScanned( boolean scanned )
272    {
273        this.scanned = scanned;
274    }
275
276    @Override
277    public void setLayout( String layout )
278    {
279        this.layout = layout;
280    }
281
282    @Override
283    public void setBaseUri(URI baseUri) {
284        this.baseUri = baseUri;
285    }
286
287    @Override
288    public void setSchedulingDefinition(String cronExpression) {
289        if (StringUtils.isNotEmpty( cronExpression ))
290        {
291            CronParser parser = new CronParser( CRON_DEFINITION );
292            parser.parse( cronExpression ).validate( );
293        }
294        this.schedulingDefinition = cronExpression;
295    }
296
297    @SuppressWarnings( "unchecked" )
298    protected <T extends RepositoryFeature<T>> void addFeature(RepositoryFeature<T> feature) {
299       featureMap.put( (Class<? extends RepositoryFeature<?>>) feature.getClass(), feature);
300    }
301
302    @Override
303    public void setIndexingContext(ArchivaIndexingContext context) {
304        if (this.indexingContext!=null) {
305
306        }
307        this.indexingContext = context;
308    }
309
310    @Override
311    public ArchivaIndexingContext getIndexingContext() {
312        return indexingContext;
313    }
314
315    @Override
316    public void close() {
317        if (this.openStatus.compareAndSet(true, false)) {
318            ArchivaIndexingContext ctx = getIndexingContext();
319            if (ctx != null) {
320                try {
321                    ctx.close();
322                } catch (IOException e) {
323                    log.warn("Error during index context close.", e);
324                }
325                this.indexingContext = null;
326
327            }
328            if (supportsFeature(StagingRepositoryFeature.class)) {
329                StagingRepositoryFeature sf = getFeature(StagingRepositoryFeature.class).get();
330                if (sf.getStagingRepository() != null) {
331                    sf.getStagingRepository().close();
332                }
333            }
334        }
335
336    }
337
338    @Override
339    public boolean isOpen() {
340        return openStatus.get();
341    }
342
343    @Override
344    public void handle(RepositoryEvent event) {
345        // We just rethrow the events
346        eventManager.fireEvent(event);
347    }
348
349    @Override
350    public <T extends Event> void registerEventHandler( EventType<T> eventType, EventHandler<? super T> eventHandler) {
351        if (!EventType.isInstanceOf(eventType, RepositoryEvent.ANY)) {
352            throw new IllegalArgumentException("Can only register RepositoryEvent Handlers");
353        }
354        eventManager.registerEventHandler(eventType, eventHandler);
355    }
356
357    @Override
358    public <T extends Event> void unregisterEventHandler(EventType<T> type, EventHandler<? super T> eventHandler) {
359        eventManager.unregisterEventHandler(type, eventHandler);
360    }
361
362    @Override
363    public StorageAsset getAsset(String path )
364    {
365        return storage.getAsset(path);
366    }
367
368    @Override
369    public StorageAsset addAsset( String path, boolean container )
370    {
371        return storage.addAsset(path, container);
372    }
373
374    @Override
375    public void removeAsset( StorageAsset asset ) throws IOException
376    {
377        storage.removeAsset(asset);
378    }
379
380    @Override
381    public StorageAsset moveAsset( StorageAsset origin, String destination, CopyOption... copyOptions ) throws IOException
382    {
383        return storage.moveAsset(origin, destination);
384    }
385
386    @Override
387    public void moveAsset( StorageAsset origin, StorageAsset destination, CopyOption... copyOptions ) throws IOException
388    {
389        storage.moveAsset( origin, destination, copyOptions );
390    }
391
392    @Override
393    public StorageAsset copyAsset( StorageAsset origin, String destination, CopyOption... copyOptions ) throws IOException
394    {
395        return storage.copyAsset(origin, destination);
396    }
397
398    @Override
399    public void copyAsset( StorageAsset origin, StorageAsset destination, CopyOption... copyOptions ) throws IOException
400    {
401        storage.copyAsset( origin, destination, copyOptions);
402    }
403
404    @Override
405    public void consumeData(StorageAsset asset, Consumer<InputStream> consumerFunction, boolean readLock ) throws IOException
406    {
407        storage.consumeData(asset, consumerFunction, readLock);
408    }
409
410    @Override
411    public void consumeDataFromChannel( StorageAsset asset, Consumer<ReadableByteChannel> consumerFunction, boolean readLock ) throws IOException
412    {
413        storage.consumeDataFromChannel( asset, consumerFunction, readLock );
414    }
415
416    @Override
417    public void writeData( StorageAsset asset, Consumer<OutputStream> consumerFunction, boolean writeLock ) throws IOException
418    {
419        storage.writeData( asset, consumerFunction, writeLock );
420    }
421
422    @Override
423    public void writeDataToChannel( StorageAsset asset, Consumer<WritableByteChannel> consumerFunction, boolean writeLock ) throws IOException
424    {
425        storage.writeDataToChannel( asset, consumerFunction, writeLock );
426    }
427
428    protected void setStorage( RepositoryStorage storage) {
429        this.storage = storage;
430    }
431
432    protected RepositoryStorage getStorage() {
433        return storage;
434    }
435}