001package org.apache.archiva.repository; 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.common.utils.PathUtil; 027import org.apache.archiva.indexer.ArchivaIndexingContext; 028import org.apache.archiva.repository.features.RepositoryFeature; 029import org.apache.archiva.repository.features.StagingRepositoryFeature; 030import org.apache.commons.lang.StringUtils; 031import org.slf4j.Logger; 032import org.slf4j.LoggerFactory; 033 034import java.io.IOException; 035import java.net.URI; 036import java.nio.file.Path; 037import java.util.ArrayList; 038import java.util.Collections; 039import java.util.HashMap; 040import java.util.HashSet; 041import java.util.List; 042import java.util.Locale; 043import java.util.Map; 044import java.util.Set; 045 046/** 047 * Implementation of a repository with the necessary fields for a bare repository. 048 * No features are provided. Capabilities and features must be implemented by concrete classes. 049 * 050 */ 051public abstract class AbstractRepository implements EditableRepository, RepositoryEventListener 052{ 053 054 055 Logger log = LoggerFactory.getLogger(AbstractRepository.class); 056 057 private final RepositoryType type; 058 private final String id; 059 private Map<Locale, String> names = new HashMap<>( ); 060 private Map<Locale, String> descriptions = new HashMap<>( ); 061 062 private Locale primaryLocale = new Locale("en_US"); 063 private URI location; 064 private URI baseUri; 065 private Set<URI> failoverLocations = new HashSet<>( ); 066 private Set<URI> uFailoverLocations = Collections.unmodifiableSet( failoverLocations ); 067 private boolean scanned = true; 068 String schedulingDefinition = "0 0 02 * * ?"; 069 private String layout = "default"; 070 public static final CronDefinition CRON_DEFINITION = CronDefinitionBuilder.instanceDefinitionFor(CronType.QUARTZ); 071 private List<RepositoryEventListener> listeners = new ArrayList<>(); 072 073 074 Map<Class<? extends RepositoryFeature<?>>, RepositoryFeature<?>> featureMap = new HashMap<>( ); 075 076 protected Path repositoryBase; 077 private ArchivaIndexingContext indexingContext; 078 079 public AbstractRepository(RepositoryType type, String id, String name, Path repositoryBase) { 080 this.id = id; 081 this.names.put( primaryLocale, name); 082 this.type = type; 083 this.repositoryBase=repositoryBase; 084 } 085 086 public AbstractRepository(Locale primaryLocale, RepositoryType type, String id, String name, Path repositoryBase) { 087 setPrimaryLocale( primaryLocale ); 088 this.id = id; 089 this.names.put( primaryLocale, name); 090 this.type = type; 091 this.repositoryBase=repositoryBase; 092 } 093 094 protected void setPrimaryLocale(Locale locale) { 095 this.primaryLocale = locale; 096 } 097 098 @Override 099 public String getId( ) 100 { 101 return id; 102 } 103 104 @Override 105 public String getName( ) 106 { 107 return getName( primaryLocale ); 108 } 109 110 @Override 111 public String getName( Locale locale ) 112 { 113 return names.get(locale); 114 } 115 116 @Override 117 public String getDescription( ) 118 { 119 return getDescription( primaryLocale ); 120 } 121 122 @Override 123 public String getDescription( Locale locale ) 124 { 125 return descriptions.get(primaryLocale); 126 } 127 128 @Override 129 public RepositoryType getType( ) 130 { 131 return type; 132 } 133 134 @Override 135 public URI getLocation( ) 136 { 137 return location; 138 } 139 140 @Override 141 public Path getLocalPath() { 142 Path localPath; 143 if (StringUtils.isEmpty(getLocation().getScheme()) || "file".equals(getLocation().getScheme()) ) { 144 localPath = PathUtil.getPathFromUri(getLocation()); 145 if (localPath.isAbsolute()) { 146 return localPath; 147 } else { 148 return repositoryBase.resolve(localPath); 149 } 150 } else { 151 return repositoryBase.resolve(getId()); 152 } 153 } 154 155 @Override 156 public Set<URI> getFailoverLocations( ) 157 { 158 return uFailoverLocations; 159 } 160 161 @Override 162 public boolean isScanned( ) 163 { 164 return scanned; 165 } 166 167 @Override 168 public String getSchedulingDefinition( ) 169 { 170 return schedulingDefinition; 171 } 172 173 @Override 174 public abstract boolean hasIndex( ); 175 176 @Override 177 public String getLayout( ) 178 { 179 return layout; 180 } 181 182 @Override 183 public abstract RepositoryCapabilities getCapabilities( ); 184 185 @SuppressWarnings( "unchecked" ) 186 @Override 187 public <T extends RepositoryFeature<T>> RepositoryFeature<T> getFeature( Class<T> clazz ) throws UnsupportedFeatureException 188 { 189 if (featureMap.containsKey( clazz )) { 190 return (RepositoryFeature<T>) featureMap.get(clazz); 191 } else 192 { 193 throw new UnsupportedFeatureException( "Feature " + clazz + " not supported" ); 194 } 195 } 196 197 @Override 198 public <T extends RepositoryFeature<T>> boolean supportsFeature( Class<T> clazz ) 199 { 200 return featureMap.containsKey( clazz ); 201 } 202 203 @Override 204 public Locale getPrimaryLocale( ) 205 { 206 return primaryLocale; 207 } 208 209 @Override 210 public void setName( Locale locale, String name ) 211 { 212 names.put(locale, name); 213 } 214 215 @Override 216 public void setDescription( Locale locale, String description ) 217 { 218 descriptions.put(locale, description); 219 } 220 221 @Override 222 public void setLocation( URI location ) 223 { 224 this.location = location; 225 } 226 227 @Override 228 public void addFailoverLocation( URI location ) 229 { 230 this.failoverLocations.add(location); 231 } 232 233 @Override 234 public void removeFailoverLocation( URI location ) 235 { 236 this.failoverLocations.remove( location ); 237 } 238 239 @Override 240 public void clearFailoverLocations( ) 241 { 242 this.failoverLocations.clear(); 243 } 244 245 @Override 246 public void setScanned( boolean scanned ) 247 { 248 this.scanned = scanned; 249 } 250 251 @Override 252 public void setLayout( String layout ) 253 { 254 this.layout = layout; 255 } 256 257 @Override 258 public void setBaseUri(URI baseUri) { 259 this.baseUri = baseUri; 260 } 261 262 @Override 263 public void setSchedulingDefinition(String cronExpression) { 264 CronParser parser = new CronParser(CRON_DEFINITION); 265 parser.parse(cronExpression).validate(); 266 this.schedulingDefinition = cronExpression; 267 } 268 269 @SuppressWarnings( "unchecked" ) 270 protected <T extends RepositoryFeature<T>> void addFeature(RepositoryFeature<T> feature) { 271 featureMap.put( (Class<? extends RepositoryFeature<?>>) feature.getClass(), feature); 272 } 273 274 @Override 275 public void setIndexingContext(ArchivaIndexingContext context) { 276 this.indexingContext = context; 277 } 278 279 @Override 280 public ArchivaIndexingContext getIndexingContext() { 281 return indexingContext; 282 } 283 284 @Override 285 public void close() { 286 ArchivaIndexingContext ctx = getIndexingContext(); 287 if (ctx!=null) { 288 try { 289 ctx.close(); 290 } catch (IOException e) { 291 log.warn("Error during index context close.",e); 292 } 293 } 294 if (supportsFeature(StagingRepositoryFeature.class)) { 295 StagingRepositoryFeature sf = getFeature(StagingRepositoryFeature.class).get(); 296 if (sf.getStagingRepository()!=null) { 297 sf.getStagingRepository().close(); 298 } 299 } 300 clearListeners(); 301 } 302 303 @Override 304 public <T> void raise(RepositoryEvent<T> event) { 305 for(RepositoryEventListener listener : listeners) { 306 listener.raise(event); 307 } 308 } 309 310 public void addListener(RepositoryEventListener listener) { 311 if (!this.listeners.contains(listener)) { 312 this.listeners.add(listener); 313 } 314 } 315 316 public void removeListener(RepositoryEventListener listener) { 317 this.removeListener(listener); 318 } 319 320 public void clearListeners() { 321 this.listeners.clear(); 322 } 323 324}