import org.apache.archiva.consumers.InvalidRepositoryContentConsumer;
import org.apache.archiva.consumers.KnownRepositoryContentConsumer;
import org.apache.archiva.consumers.RepositoryContentConsumer;
-import org.apache.archiva.repository.base.BasicManagedRepository;
+import org.apache.archiva.repository.base.managed.BasicManagedRepository;
import org.apache.archiva.repository.scanner.RepositoryScanStatistics;
import org.apache.archiva.repository.scanner.RepositoryScanner;
import org.apache.archiva.repository.scanner.RepositoryScannerException;
import java.io.IOException;
import java.io.InputStream;
-import java.nio.file.Files;
-import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
* under the License.
*/
+import org.apache.archiva.components.registry.Registry;
import org.apache.archiva.components.registry.RegistryException;
import org.apache.archiva.components.registry.RegistryListener;
* @return
*/
public Path getDataDirectory();
+
+ /**
+ * Return the used configuration registry
+ * @return
+ */
+ Registry getRegistry( );
}
import org.apache.archiva.configuration.RemoteRepositoryConfiguration;
import org.apache.archiva.configuration.RepositoryGroupConfiguration;
import org.apache.archiva.event.EventHandler;
-import org.apache.archiva.event.EventType;
-import org.apache.archiva.repository.base.BasicManagedRepository;
-import org.apache.archiva.repository.base.BasicRemoteRepository;
+import org.apache.archiva.repository.base.managed.BasicManagedRepository;
+import org.apache.archiva.repository.base.remote.BasicRemoteRepository;
import org.apache.archiva.repository.EditableManagedRepository;
import org.apache.archiva.repository.EditableRemoteRepository;
import org.apache.archiva.repository.RepositoryGroup;
import org.apache.archiva.metadata.repository.MetadataRepository;
import org.apache.archiva.metadata.repository.RepositorySessionFactory;
-import org.apache.archiva.repository.base.BasicManagedRepository;
+import org.apache.archiva.repository.base.managed.BasicManagedRepository;
import org.apache.archiva.repository.RepositoryException;
import org.apache.archiva.repository.RepositoryRegistry;
import org.junit.Before;
import org.apache.archiva.checksum.ChecksummedFile;
import org.apache.archiva.common.utils.PathUtil;
import org.apache.archiva.consumers.KnownRepositoryContentConsumer;
-import org.apache.archiva.repository.base.BasicManagedRepository;
+import org.apache.archiva.repository.base.managed.BasicManagedRepository;
import org.apache.archiva.repository.EditableManagedRepository;
import org.apache.commons.io.FileUtils;
import org.assertj.core.api.Assertions;
import org.apache.archiva.metadata.repository.RepositorySession;
import org.apache.archiva.metadata.repository.RepositorySessionFactory;
import org.apache.archiva.repository.ManagedRepositoryContent;
-import org.apache.archiva.repository.RepositoryRegistry;
-import org.apache.archiva.repository.base.ArchivaRepositoryRegistry;
-import org.apache.archiva.repository.base.RepositoryGroupHandler;
+import org.apache.archiva.repository.base.group.RepositoryGroupHandler;
import org.apache.archiva.repository.maven.metadata.storage.Maven2RepositoryPathTranslator;
-import org.apache.archiva.repository.base.BasicManagedRepository;
+import org.apache.archiva.repository.base.managed.BasicManagedRepository;
import org.apache.archiva.repository.ReleaseScheme;
import org.apache.archiva.repository.RepositoryContentProvider;
import org.apache.archiva.metadata.audit.RepositoryListener;
import org.junit.runner.RunWith;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
-import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import javax.inject.Inject;
import org.apache.archiva.configuration.RemoteRepositoryConfiguration;
import org.apache.archiva.configuration.RepositoryGroupConfiguration;
import org.apache.archiva.event.EventHandler;
-import org.apache.archiva.repository.base.BasicManagedRepository;
-import org.apache.archiva.repository.base.BasicRemoteRepository;
+import org.apache.archiva.repository.base.managed.BasicManagedRepository;
+import org.apache.archiva.repository.base.remote.BasicRemoteRepository;
import org.apache.archiva.repository.EditableManagedRepository;
import org.apache.archiva.repository.EditableRemoteRepository;
import org.apache.archiva.repository.EditableRepositoryGroup;
import org.apache.archiva.configuration.FileTypes;
import org.apache.archiva.components.taskqueue.TaskQueueException;
import org.apache.archiva.repository.base.ArchivaRepositoryRegistry;
-import org.apache.archiva.repository.base.BasicManagedRepository;
+import org.apache.archiva.repository.base.managed.BasicManagedRepository;
import org.apache.archiva.repository.ReleaseScheme;
-import org.apache.archiva.repository.base.RepositoryGroupHandler;
+import org.apache.archiva.repository.base.group.RepositoryGroupHandler;
import org.apache.archiva.scheduler.ArchivaTaskScheduler;
import org.apache.archiva.scheduler.indexing.ArtifactIndexingTask;
import org.apache.archiva.test.utils.ArchivaSpringJUnit4ClassRunner;
import org.apache.archiva.redback.role.RoleManager;
import org.apache.archiva.redback.users.User;
import org.apache.archiva.redback.users.memory.SimpleUser;
-import org.apache.archiva.repository.base.RepositoryGroupHandler;
+import org.apache.archiva.repository.base.group.RepositoryGroupHandler;
import org.apache.archiva.test.utils.ArchivaSpringJUnit4ClassRunner;
import org.apache.commons.lang3.StringUtils;
import org.junit.Before;
-import org.junit.BeforeClass;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.archiva.metadata.model.facets.AuditEvent;
import org.apache.archiva.repository.Repository;
import org.apache.archiva.repository.RepositoryRegistry;
-import org.apache.archiva.repository.base.RepositoryGroupHandler;
+import org.apache.archiva.repository.base.group.RepositoryGroupHandler;
import org.junit.Test;
import javax.inject.Inject;
+++ /dev/null
-package org.apache.archiva.repository;
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-/**
- * @author Martin Stockhammer <martin_s@apache.org>
- */
-public interface CheckedResult<R extends Repository, D>
-{
- R getRepository();
-
- boolean isValid();
-
- D getResult();
-
-}
*/
import org.apache.archiva.configuration.Configuration;
+import org.apache.archiva.repository.validation.CheckedResult;
import org.apache.archiva.repository.validation.RepositoryChecker;
import org.apache.archiva.repository.validation.RepositoryValidator;
+import org.apache.archiva.repository.validation.ValidationResponse;
import java.util.Collection;
import java.util.Map;
*/
RepositoryValidator<R> getValidator( );
+ /**
+ * Validates the set attributes of the given repository instance and returns the validation result.
+ * The repository registry uses all available validators and applies their validateRepository method to the given
+ * repository. Validation results will be merged per field.
+ *
+ * @param repository the repository to validate against
+ * @return the result of the validation.
+ */
+ ValidationResponse<R> validateRepository( R repository);
+
+ /**
+ * Validates the set attributes of the given repository instance for a repository update and returns the validation result.
+ * The repository registry uses all available validators and applies their validateRepositoryForUpdate method to the given
+ * repository. Validation results will be merged per field.
+ *
+ * @param repository the repository to validate against
+ * @return the result of the validation.
+ */
+ ValidationResponse<R> validateRepositoryForUpdate( R repository);
+
+
+
/**
* Returns <code>true</code>, if the repository is registered with the given id, otherwise <code>false</code>
* @param id the repository identifier
import org.apache.archiva.indexer.IndexUpdateFailedException;
import org.apache.archiva.repository.metadata.MetadataReader;
import org.apache.archiva.repository.storage.StorageAsset;
+import org.apache.archiva.repository.validation.CheckedResult;
import org.apache.archiva.repository.validation.ValidationError;
import org.apache.archiva.repository.validation.ValidationResponse;
* under the License.
*/
-import org.apache.archiva.repository.CheckedResult;
import org.apache.archiva.repository.Repository;
import org.apache.archiva.repository.RepositoryRegistry;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
/**
* @author Martin Stockhammer <martin_s@apache.org>
*/
public abstract class AbstractRepositoryValidator<R extends Repository> implements RepositoryValidator<R>
{
protected RepositoryRegistry repositoryRegistry;
+ private final String category;
+
+ public AbstractRepositoryValidator( String category )
+ {
+ this.category = category;
+ }
@Override
public void setRepositoryRegistry( RepositoryRegistry repositoryRegistry )
this.repositoryRegistry = repositoryRegistry;
}
+ protected String getCategory() {
+ return this.category;
+ }
+
+
+
+ protected Map<String, List<ValidationError>> appendError( Map<String, List<ValidationError>> errorMap, String attribute, String type, Object... parameter )
+ {
+ String errorKey = getCategory( ) + "." + attribute + "." + type;
+ Map<String, List<ValidationError>> result;
+ result = errorMap == null ? new HashMap<>( ) : errorMap;
+ ValidationError error = ValidationError.ofKey( errorKey, parameter );
+ List<ValidationError> errList = result.computeIfAbsent( error.getAttribute( ), k -> new ArrayList<>( ) );
+ errList.add( error );
+ return result;
+ }
+
protected abstract ValidationResponse<R> apply( R repo, boolean update );
@Override
--- /dev/null
+package org.apache.archiva.repository.validation;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.archiva.repository.Repository;
+
+/**
+ * @author Martin Stockhammer <martin_s@apache.org>
+ */
+public interface CheckedResult<R extends Repository, D>
+{
+ R getRepository();
+
+ boolean isValid();
+
+ D getResult();
+
+}
--- /dev/null
+package org.apache.archiva.repository.validation;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.archiva.repository.Repository;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Martin Stockhammer <martin_s@apache.org>
+ */
+public class CombinedValidationResponse<R extends Repository> implements CheckedResult<R, Map<String, List<ValidationError>>>
+{
+
+ private final Map<String, List<ValidationError>> errorMap = new HashMap<>( );
+ private final R repository;
+
+ public CombinedValidationResponse( R repository )
+ {
+ this.repository = repository;
+ }
+
+ @Override
+ public R getRepository( )
+ {
+ return repository;
+ }
+
+ @Override
+ public boolean isValid( )
+ {
+ return errorMap.size()==0;
+ }
+
+ @Override
+ public Map<String, List<ValidationError>> getResult( )
+ {
+ return errorMap;
+ }
+
+ public void addErrors(String key, List<ValidationError> errorList) {
+ if ( StringUtils.isNotEmpty( key ) && errorList!=null && errorList.size()>0) {
+ this.errorMap.put( key, errorList );
+ }
+ }
+
+ public void addErrors(Map<String, List<ValidationError>> errorMap) {
+ if (errorMap!=null) {
+ errorMap.entrySet( ).stream( ).forEach( e -> addErrors( e.getKey( ), e.getValue( ) ) );
+ }
+ }
+
+ public void addResult(CheckedResult<R, Map<String, List<ValidationError>>> result) {
+ this.addErrors( result.getResult( ) );
+ }
+}
--- /dev/null
+package org.apache.archiva.repository.validation;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.archiva.repository.Repository;
+import org.apache.archiva.repository.RepositoryRegistry;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A combined validator cumulates the validation results of multiple validators
+ *
+ * @author Martin Stockhammer <martin_s@apache.org>
+ */
+public class CombinedValidator<R extends Repository>
+implements RepositoryValidator<R> {
+
+ private final List<RepositoryValidator<R>> validatorList;
+ private final Class<R> flavourClazz;
+
+ public CombinedValidator( Class<R> flavourClazz, List<RepositoryValidator<R>> validatorList )
+ {
+ if (flavourClazz==null) {
+ throw new IllegalArgumentException( "The flavour class may not be null" );
+ }
+ this.flavourClazz = flavourClazz;
+ if (validatorList==null) {
+ throw new IllegalArgumentException( "The validator list may not be null" );
+ }
+ this.validatorList = validatorList;
+ }
+
+ @Override
+ public CheckedResult<R, Map<String, List<ValidationError>>> apply( R r )
+ {
+ CombinedValidationResponse<R> response = new CombinedValidationResponse<>( r );
+ validatorList.stream( ).forEach(
+ v -> response.addResult( v.apply( r ) )
+ );
+ return response;
+ }
+
+ @Override
+ public CheckedResult<R, Map<String, List<ValidationError>>> applyForUpdate( R repo )
+ {
+ CombinedValidationResponse<R> response = new CombinedValidationResponse<>( repo );
+ validatorList.stream( ).forEach(
+ v -> response.addResult( v.applyForUpdate( repo ) )
+ );
+ return response;
+
+ }
+
+ @Override
+ public void setRepositoryRegistry( RepositoryRegistry repositoryRegistry )
+ {
+ // Not used
+ }
+
+ @Override
+ public Class<R> getFlavour( )
+ {
+ return flavourClazz;
+ }
+
+ @Override
+ public boolean isFlavour( Class<?> clazz )
+ {
+ return flavourClazz.isAssignableFrom( clazz );
+ }
+}
--- /dev/null
+package org.apache.archiva.repository.validation;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.archiva.components.registry.Registry;
+
+/**
+ * @author Martin Stockhammer <martin_s@apache.org>
+ */
+public interface ErrorKeys
+{
+ String ISNULL = "isnull";
+ String ISEMPTY = "empty";
+ String EXISTS = "exists";
+ String MANAGED_REPOSITORY_EXISTS = "managed_repo_exists";
+ String REMOTE_REPOSITORY_EXISTS = "remote_repo_exists";
+ String REPOSITORY_GROUP_EXISTS = "group_exists";
+ String MAX_LENGTH_EXCEEDED = "max_length";
+ String INVALID_CHARS = "invalid_chars";
+ String BELOW_MIN = "min";
+ String INVALID_SCHEDULING_EXPRESSION = "scheduling_exp_invalid";
+ String INVALID_LOCATION = "location_invalid";
+}
* under the License.
*/
-import org.apache.archiva.repository.CheckedResult;
import org.apache.archiva.repository.Repository;
import java.util.function.Function;
-import java.util.function.Predicate;
/**
* @author Martin Stockhammer <martin_s@apache.org>
public interface RepositoryValidator<R extends Repository> extends RepositoryChecker<R, Map<String, List<ValidationError>>>, Comparable<RepositoryValidator<R>>
{
+ String REPOSITORY_ID_VALID_EXPRESSION = "^[a-zA-Z0-9._-]+$";
+ String REPOSITORY_NAME_VALID_EXPRESSION = "^([a-zA-Z0-9.)/_(-]|\\s)+$";
+ String REPOSITORY_LOCATION_VALID_EXPRESSION = "^[-a-zA-Z0-9._/~:?!&=\\\\]+$";
+
+
int DEFAULT_PRIORITY=1000;
/**
Class<R> getFlavour();
- boolean isFlavour(Class<?> clazz);
+ default boolean isFlavour(Class<?> clazz) {
+ return getFlavour( ).isAssignableFrom( clazz );
+ }
+
+ @SuppressWarnings( "unchecked" )
+ default <RR extends Repository> RepositoryValidator<RR> narrowTo( Class<RR> clazz ) {
+ if (isFlavour( clazz )) {
+ return (RepositoryValidator<RR>) this;
+ } else {
+ throw new IllegalArgumentException( "Could not narrow to " + clazz );
+ }
+ }
}
* under the License.
*/
-import org.apache.archiva.repository.CheckedResult;
import org.apache.archiva.repository.Repository;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.function.Function;
/**
* A validation response gives information about the validation status for certain attributes.
<groupId>org.apache.archiva.components.registry</groupId>
<artifactId>archiva-components-spring-registry-api</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.apache.archiva.components</groupId>
+ <artifactId>archiva-components-spring-quartz</artifactId>
+ </dependency>
<dependency>
<groupId>com.cronutils</groupId>
<artifactId>cron-utils</artifactId>
+++ /dev/null
-package org.apache.archiva.repository.base;
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-
-import org.apache.archiva.repository.EditableManagedRepository;
-import org.apache.archiva.repository.ManagedRepositoryContent;
-import org.apache.archiva.repository.ReleaseScheme;
-import org.apache.archiva.repository.RepositoryType;
-import org.apache.archiva.repository.storage.RepositoryStorage;
-
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Locale;
-import java.util.Set;
-
-/**
- * Simple implementation of a managed repository.
- */
-public abstract class AbstractManagedRepository extends AbstractRepository implements EditableManagedRepository
-{
- private boolean blocksRedeployment = false;
- private ManagedRepositoryContent content;
- private Set<ReleaseScheme> activeReleaseSchemes = new HashSet<>( );
- private Set<ReleaseScheme> uActiveReleaseSchemes = Collections.unmodifiableSet( activeReleaseSchemes );
-
- public AbstractManagedRepository( RepositoryType type, String id, String name, RepositoryStorage storage)
- {
- super( type, id, name, storage );
- }
-
- public AbstractManagedRepository( Locale primaryLocale, RepositoryType type, String id, String name, RepositoryStorage storage )
- {
- super( primaryLocale, type, id, name, storage );
- }
-
- @Override
- public ManagedRepositoryContent getContent( )
- {
- return content;
- }
-
- @Override
- public void setContent( ManagedRepositoryContent content) {
- this.content = content;
- }
-
- @Override
- public void setBlocksRedeployment( boolean blocksRedeployment )
- {
- this.blocksRedeployment = blocksRedeployment;
- }
-
- @Override
- public boolean blocksRedeployments( )
- {
- return blocksRedeployment;
- }
-
- @Override
- public Set<ReleaseScheme> getActiveReleaseSchemes( )
- {
- return uActiveReleaseSchemes;
- }
-
- @Override
- public void addActiveReleaseScheme( ReleaseScheme scheme )
- {
- this.activeReleaseSchemes.add(scheme);
- }
-
- @Override
- public void removeActiveReleaseScheme( ReleaseScheme scheme )
- {
- this.activeReleaseSchemes.remove(scheme);
- }
-
- @Override
- public void clearActiveReleaseSchemes( )
- {
- this.activeReleaseSchemes.clear();
- }
-
-
-}
+++ /dev/null
-package org.apache.archiva.repository.base;
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-
-import org.apache.archiva.repository.EditableRemoteRepository;
-import org.apache.archiva.repository.RemoteRepositoryContent;
-import org.apache.archiva.repository.RepositoryCredentials;
-import org.apache.archiva.repository.RepositoryType;
-import org.apache.archiva.repository.storage.RepositoryStorage;
-
-import java.net.URI;
-import java.time.Duration;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Locale;
-import java.util.Map;
-
-/**
- * Abstract implementation of a remote repository. Abstract classes must implement the
- * features and capabilities by themselves.
- */
-public abstract class AbstractRemoteRepository extends AbstractRepository implements EditableRemoteRepository
-{
-
- private RepositoryCredentials credentials;
- private String checkPath;
- private Map<String,String> extraParameters = new HashMap<>( );
- private Map<String,String> uExtraParameters = Collections.unmodifiableMap( extraParameters );
- private Map<String,String> extraHeaders = new HashMap<>( );
- private Map<String,String> uExtraHeaders = Collections.unmodifiableMap( extraHeaders );
- private Duration timeout = Duration.ofSeconds( 60 );
- private String proxyId;
- private RemoteRepositoryContent content;
-
- public AbstractRemoteRepository( RepositoryType type, String id, String name , RepositoryStorage storage)
- {
- super( type, id, name, storage );
- }
-
- public AbstractRemoteRepository( Locale primaryLocale, RepositoryType type, String id, String name, RepositoryStorage storage )
- {
- super( primaryLocale, type, id, name, storage );
- }
-
- @Override
- public void setCredentials( RepositoryCredentials credentials )
- {
- this.credentials = credentials;
- }
-
- @Override
- public void setCheckPath( String path )
- {
- this.checkPath = path;
- }
-
- @Override
- public void setExtraParameters( Map<String, String> params )
- {
- this.extraParameters.clear();
- this.extraParameters.putAll(params);
- }
-
- @Override
- public void addExtraParameter( String key, String value )
- {
- this.extraParameters.put(key, value);
- }
-
- @Override
- public void setExtraHeaders( Map<String, String> headers )
- {
- this.extraHeaders.clear();
- this.extraHeaders.putAll(headers);
- }
-
- @Override
- public void addExtraHeader( String header, String value )
- {
- this.extraHeaders.put(header, value);
- }
-
- @Override
- public void setTimeout( Duration duration )
- {
- this.timeout = duration;
- }
-
- @Override
- public RemoteRepositoryContent getContent( )
- {
- return content;
- }
-
- @Override
- public void setContent(RemoteRepositoryContent content) {
- this.content = content;
- }
-
- @Override
- public RepositoryCredentials getLoginCredentials( )
- {
- return credentials;
- }
-
- @Override
- public String getCheckPath( )
- {
- return checkPath;
- }
-
- @Override
- public Map<String, String> getExtraParameters( )
- {
- return uExtraParameters;
- }
-
- @Override
- public Map<String, String> getExtraHeaders( )
- {
- return uExtraHeaders;
- }
-
- @Override
- public Duration getTimeout( )
- {
- return timeout;
- }
-
- @Override
- public String toString() {
- StringBuilder str = new StringBuilder();
- return str.append("checkPath=").append(checkPath)
- .append(",creds:").append(credentials).toString();
- }
-
- @Override
- public void setLocation(URI location) {
- // Location of remote repositories is not for the local filestore
- super.location = location;
- }
-}
+++ /dev/null
-package org.apache.archiva.repository.base;
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import org.apache.archiva.repository.EditableRepositoryGroup;
-import org.apache.archiva.repository.ManagedRepository;
-import org.apache.archiva.repository.RepositoryCapabilities;
-import org.apache.archiva.repository.RepositoryType;
-import org.apache.archiva.repository.storage.RepositoryStorage;
-import org.apache.commons.collections4.map.ListOrderedMap;
-
-import java.util.List;
-import java.util.Locale;
-import java.util.concurrent.locks.ReadWriteLock;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
-
-/**
- * Abstract repository group implementation.
- *
- */
-public class AbstractRepositoryGroup extends AbstractRepository implements EditableRepositoryGroup
-{
-
- private ListOrderedMap<String, ManagedRepository> repositories = new ListOrderedMap<>();
-
- private int mergedIndexTTL;
-
- private final ReadWriteLock rwl = new ReentrantReadWriteLock();
-
- private RepositoryCapabilities capabilities;
-
- public AbstractRepositoryGroup( RepositoryType type, String id, String name, RepositoryStorage storage) {
- super(type, id, name, storage);
- }
-
- public AbstractRepositoryGroup(Locale primaryLocale, RepositoryType type, String id, String name, RepositoryStorage storage) {
- super(primaryLocale, type, id, name, storage);
- }
-
- @Override
- public boolean hasIndex() {
- return true;
- }
-
- @Override
- public RepositoryCapabilities getCapabilities() {
- return capabilities;
- }
-
-
- @Override
- public void clearRepositories() {
- rwl.writeLock().lock();
- try {
- repositories.clear();
- } finally {
- rwl.writeLock().unlock();
- }
- }
-
- @Override
- public void setRepositories(List<ManagedRepository> newRepositories) {
- rwl.writeLock().lock();
- try {
- repositories.clear();
- for(ManagedRepository repo : newRepositories) {
- if (repo!=null)
- repositories.put(repo.getId(), repo);
- }
- } finally {
- rwl.writeLock().unlock();
- }
- }
-
- @Override
- public void addRepository(ManagedRepository repository) {
- rwl.writeLock().lock();
- try {
- if (repository!=null)
- repositories.put(repository.getId(), repository);
- } finally {
- rwl.writeLock().unlock();
- }
- }
-
- @Override
- public void addRepository(int index, ManagedRepository repository) {
- rwl.writeLock().lock();
- try {
- if (repository!=null)
- repositories.put(index, repository.getId(), repository);
- } finally {
- rwl.writeLock().unlock();
- }
- }
-
- @Override
- public boolean removeRepository(ManagedRepository repository) {
- rwl.writeLock().lock();
- try {
- return repositories.remove(repository.getId(), repository);
- } finally {
- rwl.writeLock().unlock();
- }
- }
-
- @Override
- public ManagedRepository removeRepository(String repoId) {
- rwl.writeLock().lock();
- try {
- return repositories.remove(repoId);
- } finally {
- rwl.writeLock().unlock();
- }
- }
-
- @Override
- public void setMergedIndexTTL(int timeInSeconds) {
- this.mergedIndexTTL = timeInSeconds;
- }
-
- @Override
- public List<ManagedRepository> getRepositories() {
- rwl.readLock().lock();
- try {
- return repositories.valueList();
- } finally {
- rwl.readLock().unlock();
- }
- }
-
- @Override
- public boolean contains(ManagedRepository repository) {
- rwl.readLock().lock();
- try {
- return repositories.containsValue(repository);
- } finally {
- rwl.readLock().unlock();
- }
- }
-
- @Override
- public boolean contains(String id) {
- rwl.readLock().lock();
- try {
- return repositories.containsKey(id);
- } finally {
- rwl.readLock().unlock();
- }
- }
-
- @Override
- public int getMergedIndexTTL() {
- return mergedIndexTTL;
- }
-
- protected void setCapabilities(RepositoryCapabilities capabilities) {
- this.capabilities = capabilities;
- }
-}
import org.apache.archiva.indexer.IndexCreationFailedException;
import org.apache.archiva.indexer.IndexManagerFactory;
import org.apache.archiva.indexer.IndexUpdateFailedException;
-import org.apache.archiva.repository.CheckedResult;
+import org.apache.archiva.repository.base.group.RepositoryGroupHandler;
+import org.apache.archiva.repository.validation.CheckedResult;
import org.apache.archiva.repository.EditableManagedRepository;
import org.apache.archiva.repository.EditableRemoteRepository;
import org.apache.archiva.repository.EditableRepository;
import org.apache.archiva.repository.RepositoryRegistry;
import org.apache.archiva.repository.RepositoryType;
import org.apache.archiva.repository.UnsupportedRepositoryTypeException;
-import org.apache.archiva.repository.base.validation.CommonGroupValidator;
import org.apache.archiva.repository.event.LifecycleEvent;
import org.apache.archiva.repository.event.RepositoryEvent;
import org.apache.archiva.repository.event.RepositoryIndexEvent;
import org.apache.archiva.repository.features.StagingRepositoryFeature;
import org.apache.archiva.repository.metadata.MetadataReader;
import org.apache.archiva.repository.storage.StorageAsset;
-import org.apache.archiva.repository.validation.RepositoryChecker;
import org.apache.archiva.repository.validation.RepositoryValidator;
import org.apache.archiva.repository.validation.ValidationError;
import org.apache.archiva.repository.validation.ValidationResponse;
}
- protected Map<RepositoryType, RepositoryProvider> getRepositoryProviderMap( )
+ public Map<RepositoryType, RepositoryProvider> getRepositoryProviderMap( )
{
Map<RepositoryType, RepositoryProvider> map = new HashMap<>( );
if ( repositoryProviders != null )
return map;
}
- protected RepositoryProvider getProvider( RepositoryType type ) throws RepositoryException
+ public RepositoryProvider getProvider( RepositoryType type ) throws RepositoryException
{
return repositoryProviders.stream( ).filter( repositoryProvider -> repositoryProvider.provides( ).contains( type ) ).findFirst( ).orElseThrow( ( ) -> new RepositoryException( "Repository type cannot be handled: " + type ) );
}
+++ /dev/null
-package org.apache.archiva.repository.base;
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import org.apache.archiva.common.filelock.DefaultFileLockManager;
-import org.apache.archiva.common.filelock.FileLockManager;
-import org.apache.archiva.repository.ReleaseScheme;
-import org.apache.archiva.repository.RepositoryCapabilities;
-import org.apache.archiva.repository.RepositoryRequestInfo;
-import org.apache.archiva.repository.RepositoryType;
-import org.apache.archiva.repository.StandardCapabilities;
-import org.apache.archiva.repository.storage.StorageAsset;
-import org.apache.archiva.repository.storage.fs.FilesystemStorage;
-import org.apache.archiva.repository.storage.RepositoryStorage;
-import org.apache.archiva.repository.features.ArtifactCleanupFeature;
-import org.apache.archiva.repository.features.IndexCreationFeature;
-import org.apache.archiva.repository.features.StagingRepositoryFeature;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.IOException;
-import java.nio.file.Path;
-import java.util.Locale;
-
-/**
- *
- * Just a helper class, mainly used for unit tests.
- *
- *
- */
-public class BasicManagedRepository extends AbstractManagedRepository
-
-{
- Logger log = LoggerFactory.getLogger(BasicManagedRepository.class);
- ArtifactCleanupFeature artifactCleanupFeature = new ArtifactCleanupFeature( );
- StagingRepositoryFeature stagingRepositoryFeature = new StagingRepositoryFeature( );
-
- static final StandardCapabilities CAPABILITIES = new StandardCapabilities( new ReleaseScheme[] {
- ReleaseScheme.RELEASE, ReleaseScheme.SNAPSHOT
- }, new String[] {"default"}, new String[0], new String[] {
- ArtifactCleanupFeature.class.toString(), IndexCreationFeature.class.toString(),
- StagingRepositoryFeature.class.toString()
- }, true, true, true, true, true );
-
- public BasicManagedRepository( String id, String name, RepositoryStorage repositoryStorage )
- {
- super( RepositoryType.MAVEN, id, name, repositoryStorage );
- initFeatures();
- }
-
- public BasicManagedRepository( Locale primaryLocale, RepositoryType type, String id, String name, RepositoryStorage repositoryStorage )
- {
- super( primaryLocale, type, id, name, repositoryStorage);
- initFeatures();
- }
-
- private void initFeatures() {
- IndexCreationFeature indexCreationFeature = new IndexCreationFeature(this, this);
- addFeature( artifactCleanupFeature );
- addFeature( indexCreationFeature );
- addFeature( stagingRepositoryFeature );
- }
-
- @Override
- public boolean hasIndex( )
- {
- return true;
- }
-
- @Override
- public RepositoryCapabilities getCapabilities( )
- {
- return CAPABILITIES;
- }
-
-
- @Override
- public RepositoryRequestInfo getRequestInfo() {
- return null;
- }
-
- /**
- * Creates a filesystem based repository instance. The path is built by basePath/repository-id
- *
- * @param id The repository id
- * @param name The name of the repository
- * @param repositoryPath The path to the repository
- * @return The repository instance
- * @throws IOException
- */
- public static BasicManagedRepository newFilesystemInstance(String id, String name, Path repositoryPath) throws IOException {
- FileLockManager lockManager = new DefaultFileLockManager();
- FilesystemStorage storage = new FilesystemStorage(repositoryPath, lockManager);
- return new BasicManagedRepository(id, name, storage);
- }
-
-}
+++ /dev/null
-package org.apache.archiva.repository.base;
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import org.apache.archiva.common.filelock.DefaultFileLockManager;
-import org.apache.archiva.common.filelock.FileLockManager;
-import org.apache.archiva.repository.ReleaseScheme;
-import org.apache.archiva.repository.RepositoryCapabilities;
-import org.apache.archiva.repository.RepositoryType;
-import org.apache.archiva.repository.StandardCapabilities;
-import org.apache.archiva.repository.storage.fs.FilesystemStorage;
-import org.apache.archiva.repository.storage.RepositoryStorage;
-import org.apache.archiva.repository.features.IndexCreationFeature;
-import org.apache.archiva.repository.features.RemoteIndexFeature;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.IOException;
-import java.nio.file.Path;
-import java.util.Locale;
-
-/**
- *
- * Just a helper class, mainly used for unit tests.
- *
- *
- */
-public class BasicRemoteRepository extends AbstractRemoteRepository
-
-{
- Logger log = LoggerFactory.getLogger(BasicRemoteRepository.class);
-
- RemoteIndexFeature remoteIndexFeature = new RemoteIndexFeature();
- IndexCreationFeature indexCreationFeature = new IndexCreationFeature(true);
-
-
- static final StandardCapabilities CAPABILITIES = new StandardCapabilities( new ReleaseScheme[] {
- ReleaseScheme.RELEASE, ReleaseScheme.SNAPSHOT
- }, new String[] {"default"}, new String[0], new String[] {
- RemoteIndexFeature.class.toString(),
- IndexCreationFeature.class.toString()
- }, true, true, true, true, true );
-
- public BasicRemoteRepository( String id, String name, RepositoryStorage storage)
- {
- super( RepositoryType.MAVEN, id, name, storage);
- initFeatures();
- }
-
- public BasicRemoteRepository( Locale primaryLocale, RepositoryType type, String id, String name, RepositoryStorage storage )
- {
- super( primaryLocale, type, id, name, storage );
- initFeatures();
- }
-
- private void initFeatures() {
- addFeature( remoteIndexFeature );
- addFeature( indexCreationFeature );
- }
-
- @Override
- public boolean hasIndex( )
- {
- return true;
- }
-
- @Override
- public RepositoryCapabilities getCapabilities( )
- {
- return CAPABILITIES;
- }
-
-
- public static BasicRemoteRepository newFilesystemInstance(String id, String name, Path basePath) throws IOException {
- FileLockManager lockManager = new DefaultFileLockManager();
- FilesystemStorage storage = new FilesystemStorage(basePath.resolve(id), lockManager);
- return new BasicRemoteRepository(id, name, storage);
- }
-}
archivaConfiguration.save( configuration, "" );
}
- ReentrantReadWriteLock getLock() {
+ public ReentrantReadWriteLock getLock() {
return lock;
}
}
+++ /dev/null
-package org.apache.archiva.repository.base;
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import org.apache.archiva.components.registry.RegistryException;
-import org.apache.archiva.configuration.Configuration;
-import org.apache.archiva.configuration.IndeterminateConfigurationException;
-import org.apache.archiva.configuration.ManagedRepositoryConfiguration;
-import org.apache.archiva.configuration.RepositoryGroupConfiguration;
-import org.apache.archiva.indexer.merger.MergedRemoteIndexesScheduler;
-import org.apache.archiva.repository.CheckedResult;
-import org.apache.archiva.repository.EditableRepository;
-import org.apache.archiva.repository.EditableRepositoryGroup;
-import org.apache.archiva.repository.ManagedRepository;
-import org.apache.archiva.repository.RepositoryException;
-import org.apache.archiva.repository.RepositoryGroup;
-import org.apache.archiva.repository.RepositoryHandler;
-import org.apache.archiva.repository.RepositoryProvider;
-import org.apache.archiva.repository.RepositoryType;
-import org.apache.archiva.repository.event.RepositoryEvent;
-import org.apache.archiva.repository.features.IndexCreationFeature;
-import org.apache.archiva.repository.storage.StorageAsset;
-import org.apache.archiva.repository.validation.RepositoryChecker;
-import org.apache.archiva.repository.validation.RepositoryValidator;
-import org.apache.commons.lang3.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.stereotype.Service;
-
-import javax.annotation.PostConstruct;
-import javax.annotation.PreDestroy;
-import javax.inject.Named;
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
-import java.util.stream.Collectors;
-
-import static org.apache.archiva.indexer.ArchivaIndexManager.DEFAULT_INDEX_PATH;
-
-/**
- * This class manages repository groups for the RepositoryRegistry.
- * It is tightly coupled with the {@link ArchivaRepositoryRegistry}.
- *
- * @author Martin Stockhammer <martin_s@apache.org>
- */
-@Service( "repositoryGroupHandler#default" )
-public class RepositoryGroupHandler implements RepositoryHandler<RepositoryGroup, RepositoryGroupConfiguration>
-{
- private static final Logger log = LoggerFactory.getLogger( RepositoryGroupHandler.class );
-
- private final ArchivaRepositoryRegistry repositoryRegistry;
- private final ConfigurationHandler configurationHandler;
- private final MergedRemoteIndexesScheduler mergedRemoteIndexesScheduler;
-
- private final Map<String, RepositoryGroup> repositoryGroups = new HashMap<>( );
- private final RepositoryValidator<RepositoryGroup> validator;
-
- private Path groupsDirectory;
-
-
- /**
- * Creates a new instance. All dependencies are injected on the constructor.
- *
- * @param repositoryRegistry the registry. To avoid circular dependencies via DI, this class registers itself on the registry.
- * @param configurationHandler the configuration handler is used to retrieve and save configuration.
- * @param mergedRemoteIndexesScheduler the index scheduler is used for merging the indexes from all group members
- */
- public RepositoryGroupHandler( ArchivaRepositoryRegistry repositoryRegistry,
- ConfigurationHandler configurationHandler,
- @Named( "mergedRemoteIndexesScheduler#default" ) MergedRemoteIndexesScheduler mergedRemoteIndexesScheduler,
- @Named( "repositoryValidator#common#group") RepositoryValidator<RepositoryGroup> repositoryGroupValidator
- )
- {
- this.configurationHandler = configurationHandler;
- this.mergedRemoteIndexesScheduler = mergedRemoteIndexesScheduler;
- this.repositoryRegistry = repositoryRegistry;
- this.validator = repositoryGroupValidator;
- }
-
- @Override
- @PostConstruct
- public void init( )
- {
- log.debug( "Initializing repository group handler " + repositoryRegistry.toString( ) );
- initializeStorage( );
- // We are registering this class on the registry. This is necessary to avoid circular dependencies via injection.
- this.repositoryRegistry.registerGroupHandler( this );
- }
-
- public void initializeFromConfig( )
- {
- this.repositoryGroups.clear( );
- this.repositoryGroups.putAll( newInstancesFromConfig( ) );
- for ( RepositoryGroup group : this.repositoryGroups.values( ) )
- {
- initializeGroup( group );
- }
- }
-
- private void initializeStorage( )
- {
- Path baseDir = this.configurationHandler.getArchivaConfiguration( ).getRepositoryGroupBaseDir( );
- if ( !Files.exists( baseDir ) )
- {
- try
- {
- Files.createDirectories( baseDir );
- }
- catch ( IOException e )
- {
- log.error( "Could not create group base directory: {}", e.getMessage( ), e );
- }
- }
- this.groupsDirectory = baseDir;
- }
-
- private void initializeGroup( RepositoryGroup repositoryGroup )
- {
- StorageAsset indexDirectory = getMergedIndexDirectory( repositoryGroup );
- if ( !indexDirectory.exists( ) )
- {
- try
- {
- indexDirectory.create( );
- }
- catch ( IOException e )
- {
- log.error( "Could not create index directory {} for group {}: {}", indexDirectory, repositoryGroup.getId( ), e.getMessage( ) );
- }
- }
- Path groupPath = groupsDirectory.resolve( repositoryGroup.getId( ) );
- if ( !Files.exists( groupPath ) )
- {
- try
- {
- Files.createDirectories( groupPath );
- }
- catch ( IOException e )
- {
- log.error( "Could not create repository group directory {}", groupPath );
- }
- }
- mergedRemoteIndexesScheduler.schedule( repositoryGroup,
- indexDirectory );
- }
-
- public StorageAsset getMergedIndexDirectory( RepositoryGroup group )
- {
- if ( group != null )
- {
- return group.getFeature( IndexCreationFeature.class ).get( ).getLocalIndexPath( );
- }
- else
- {
- return null;
- }
- }
-
-
- @Override
- public Map<String, RepositoryGroup> newInstancesFromConfig( )
- {
- try
- {
- List<RepositoryGroupConfiguration> repositoryGroupConfigurations =
- this.configurationHandler.getBaseConfiguration( ).getRepositoryGroups( );
-
- if ( repositoryGroupConfigurations == null )
- {
- return Collections.emptyMap( );
- }
-
- Map<String, RepositoryGroup> repositoryGroupMap = new LinkedHashMap<>( repositoryGroupConfigurations.size( ) );
-
- Map<RepositoryType, RepositoryProvider> providerMap = repositoryRegistry.getRepositoryProviderMap( );
- for ( RepositoryGroupConfiguration repoConfig : repositoryGroupConfigurations )
- {
- RepositoryType repositoryType = RepositoryType.valueOf( repoConfig.getType( ) );
- if ( providerMap.containsKey( repositoryType ) )
- {
- try
- {
- RepositoryGroup repo = createNewRepositoryGroup( providerMap.get( repositoryType ), repoConfig );
- repositoryGroupMap.put( repo.getId( ), repo );
- }
- catch ( Exception e )
- {
- log.error( "Could not create repository group {}: {}", repoConfig.getId( ), e.getMessage( ), e );
- }
- }
- }
- return repositoryGroupMap;
- }
- catch ( Throwable e )
- {
- log.error( "Could not initialize repositories from config: {}", e.getMessage( ), e );
- return Collections.emptyMap( );
- }
- }
-
- @Override
- public RepositoryGroup newInstance( final RepositoryType type, String id ) throws RepositoryException
- {
- RepositoryProvider provider = repositoryRegistry.getProvider( type );
- RepositoryGroupConfiguration config = new RepositoryGroupConfiguration( );
- config.setId( id );
- return createNewRepositoryGroup( provider, config );
- }
-
- @Override
- public RepositoryGroup newInstance( final RepositoryGroupConfiguration repositoryConfiguration ) throws RepositoryException
- {
- RepositoryType type = RepositoryType.valueOf( repositoryConfiguration.getType( ) );
- RepositoryProvider provider = repositoryRegistry.getProvider( type );
- return createNewRepositoryGroup( provider, repositoryConfiguration );
- }
-
- private RepositoryGroup createNewRepositoryGroup( RepositoryProvider provider, RepositoryGroupConfiguration config ) throws RepositoryException
- {
- RepositoryGroup repositoryGroup = provider.createRepositoryGroup( config );
- updateReferences( repositoryGroup, config );
- return repositoryGroup;
- }
-
-
- /**
- * Adds a new repository group to the current list, or replaces the repository group definition with
- * the same id, if it exists already.
- * The change is saved to the configuration immediately.
- *
- * @param repositoryGroup the new repository group.
- * @throws RepositoryException if the new repository group could not be saved to the configuration.
- */
- @Override
- public RepositoryGroup put( final RepositoryGroup repositoryGroup ) throws RepositoryException
- {
- final String id = repositoryGroup.getId( );
- RepositoryGroup originRepoGroup = repositoryGroups.remove( id );
- try
- {
- if ( originRepoGroup != null && originRepoGroup != repositoryGroup )
- {
- this.mergedRemoteIndexesScheduler.unschedule( originRepoGroup );
- originRepoGroup.close( );
- }
- RepositoryProvider provider = repositoryRegistry.getProvider( repositoryGroup.getType( ) );
- RepositoryGroupConfiguration newCfg = provider.getRepositoryGroupConfiguration( repositoryGroup );
- ReentrantReadWriteLock.WriteLock configLock = this.configurationHandler.getLock( ).writeLock( );
- configLock.lock( );
- try
- {
- Configuration configuration = this.configurationHandler.getBaseConfiguration( );
- updateReferences( repositoryGroup, newCfg );
- RepositoryGroupConfiguration oldCfg = configuration.findRepositoryGroupById( id );
- if ( oldCfg != null )
- {
- configuration.removeRepositoryGroup( oldCfg );
- }
- configuration.addRepositoryGroup( newCfg );
- configurationHandler.save( configuration, ConfigurationHandler.REGISTRY_EVENT_TAG );
- initializeGroup( repositoryGroup );
- }
- finally
- {
- configLock.unlock( );
- }
- repositoryGroups.put( id, repositoryGroup );
- return repositoryGroup;
- }
- catch ( Exception e )
- {
- // Rollback
- if ( originRepoGroup != null )
- {
- repositoryGroups.put( id, originRepoGroup );
- }
- else
- {
- repositoryGroups.remove( id );
- }
- log.error( "Exception during configuration update {}", e.getMessage( ), e );
- throw new RepositoryException( "Could not save the configuration" + ( e.getMessage( ) == null ? "" : ": " + e.getMessage( ) ), e);
- }
- }
-
- /**
- * Adds a new repository group or updates the repository with the same id, if it exists already.
- * The configuration is saved immediately.
- *
- * @param repositoryGroupConfiguration the repository configuration
- * @return the updated or created repository
- * @throws RepositoryException if an error occurs, or the configuration is not valid.
- */
- @Override
- public RepositoryGroup put( RepositoryGroupConfiguration repositoryGroupConfiguration ) throws RepositoryException
- {
- final String id = repositoryGroupConfiguration.getId( );
- final RepositoryType repositoryType = RepositoryType.valueOf( repositoryGroupConfiguration.getType( ) );
- final RepositoryProvider provider = repositoryRegistry.getProvider( repositoryType );
- RepositoryGroup currentRepository;
- ReentrantReadWriteLock.WriteLock configLock = this.configurationHandler.getLock( ).writeLock( );
- configLock.lock( );
- try
- {
- Configuration configuration = this.configurationHandler.getBaseConfiguration( );
- currentRepository = repositoryRegistry.getRepositoryGroup( id );
- RepositoryGroup oldRepository = currentRepository == null ? null : clone( currentRepository );
- try
- {
-
- if (currentRepository==null) {
- currentRepository = put( repositoryGroupConfiguration, configuration );
- } else
- {
- setRepositoryGroupDefaults( repositoryGroupConfiguration );
- provider.updateRepositoryGroupInstance( (EditableRepositoryGroup) currentRepository, repositoryGroupConfiguration );
- }
- configurationHandler.save( configuration, ConfigurationHandler.REGISTRY_EVENT_TAG );
- updateReferences( currentRepository, repositoryGroupConfiguration );
- initializeGroup( currentRepository );
- this.repositoryGroups.put( id, currentRepository );
- }
- catch ( IndeterminateConfigurationException | RegistryException | RepositoryException e )
- {
- // Trying a rollback
- if ( oldRepository != null )
- {
- RepositoryGroupConfiguration oldCfg = provider.getRepositoryGroupConfiguration( oldRepository );
- provider.updateRepositoryGroupInstance( (EditableRepositoryGroup) currentRepository, oldCfg);
- replaceOrAddRepositoryConfig( oldCfg, configuration );
- try
- {
- configurationHandler.save( configuration, ConfigurationHandler.REGISTRY_EVENT_TAG );
- }
- catch ( IndeterminateConfigurationException | RegistryException indeterminateConfigurationException )
- {
- log.error( "Fatal error, config save during rollback failed: {}", e.getMessage( ), e );
- }
- updateReferences( oldRepository, oldCfg );
- initializeGroup( oldRepository );
- }
- log.error( "Could not save the configuration for repository group {}: {}", id, e.getMessage( ), e );
- if (e instanceof RepositoryException) {
- throw (RepositoryException) e;
- } else
- {
- throw new RepositoryException( "Could not save the configuration for repository group " + id + ": " + e.getMessage( ) );
- }
- }
- }
- finally
- {
- configLock.unlock( );
- }
- return currentRepository;
- }
-
- @Override
- public RepositoryGroup put( RepositoryGroupConfiguration repositoryGroupConfiguration, Configuration configuration ) throws RepositoryException
- {
- final String id = repositoryGroupConfiguration.getId( );
- final RepositoryType repoType = RepositoryType.valueOf( repositoryGroupConfiguration.getType( ) );
- RepositoryGroup repo;
- setRepositoryGroupDefaults( repositoryGroupConfiguration );
- if ( repositoryGroups.containsKey( id ) )
- {
- repo = clone( repositoryGroups.get( id ) );
- if ( repo instanceof EditableRepositoryGroup )
- {
- repositoryRegistry.getProvider( repoType ).updateRepositoryGroupInstance( (EditableRepositoryGroup) repo, repositoryGroupConfiguration );
- }
- else
- {
- throw new RepositoryException( "The repository is not editable " + id );
- }
- }
- else
- {
- repo = repositoryRegistry.getProvider( repoType ).createRepositoryGroup( repositoryGroupConfiguration );
- }
- replaceOrAddRepositoryConfig( repositoryGroupConfiguration, configuration );
- updateReferences( repo, repositoryGroupConfiguration );
- return repo;
- }
-
- @Override
- public <D> CheckedResult<RepositoryGroup, D> putWithCheck( RepositoryGroupConfiguration repositoryConfiguration, RepositoryChecker<RepositoryGroup, D> checker ) throws RepositoryException
- {
- final String id = repositoryConfiguration.getId( );
- RepositoryGroup currentGroup = repositoryGroups.get( id );
- Configuration configuration = configurationHandler.getBaseConfiguration( );
- RepositoryGroup repositoryGroup = put( repositoryConfiguration, configuration );
- CheckedResult<RepositoryGroup, D> result;
- if ( currentGroup == null )
- {
- result = checker.apply( repositoryGroup );
- }
- else
- {
- result = checker.applyForUpdate( repositoryGroup );
- }
- if ( result.isValid( ) )
- {
- put( result.getRepository() );
- }
- return result;
- }
-
-
- private void setRepositoryGroupDefaults( RepositoryGroupConfiguration repositoryGroupConfiguration )
- {
- if ( StringUtils.isEmpty( repositoryGroupConfiguration.getMergedIndexPath( ) ) )
- {
- repositoryGroupConfiguration.setMergedIndexPath( DEFAULT_INDEX_PATH );
- }
- if ( repositoryGroupConfiguration.getMergedIndexTtl( ) <= 0 )
- {
- repositoryGroupConfiguration.setMergedIndexTtl( 300 );
- }
- if ( StringUtils.isEmpty( repositoryGroupConfiguration.getCronExpression( ) ) )
- {
- repositoryGroupConfiguration.setCronExpression( "0 0 03 ? * MON" );
- }
- }
-
- private void replaceOrAddRepositoryConfig( RepositoryGroupConfiguration repositoryGroupConfiguration, Configuration configuration )
- {
- RepositoryGroupConfiguration oldCfg = configuration.findRepositoryGroupById( repositoryGroupConfiguration.getId( ) );
- if ( oldCfg != null )
- {
- configuration.removeRepositoryGroup( oldCfg );
- }
- configuration.addRepositoryGroup( repositoryGroupConfiguration );
- }
-
- public void removeRepositoryFromGroups( ManagedRepository repo )
- {
- if ( repo != null )
- {
- repositoryGroups.values( ).stream( ).filter( repoGroup -> repoGroup instanceof EditableRepository ).
- map( repoGroup -> (EditableRepositoryGroup) repoGroup ).forEach( repoGroup -> repoGroup.removeRepository( repo ) );
- }
- }
-
- /**
- * Removes a repository group from the registry and configuration, if it exists.
- * The change is saved to the configuration immediately.
- *
- * @param id the id of the repository group to remove
- * @throws RepositoryException if a error occurs during configuration save
- */
- @Override
- public void remove( final String id ) throws RepositoryException
- {
- RepositoryGroup repo = get( id );
- if ( repo != null )
- {
- try
- {
- repo = repositoryGroups.remove( id );
- if ( repo != null )
- {
- this.mergedRemoteIndexesScheduler.unschedule( repo );
- repo.close( );
- Configuration configuration = this.configurationHandler.getBaseConfiguration( );
- RepositoryGroupConfiguration cfg = configuration.findRepositoryGroupById( id );
- if ( cfg != null )
- {
- configuration.removeRepositoryGroup( cfg );
- }
- this.configurationHandler.save( configuration, ConfigurationHandler.REGISTRY_EVENT_TAG );
- }
-
- }
- catch ( RegistryException | IndeterminateConfigurationException e )
- {
- // Rollback
- log.error( "Could not save config after repository removal: {}", e.getMessage( ), e );
- repositoryGroups.put( repo.getId( ), repo );
- throw new RepositoryException( "Could not save configuration after repository removal: " + e.getMessage( ) );
- }
- }
- }
-
- @Override
- public void remove( String id, Configuration configuration ) throws RepositoryException
- {
- RepositoryGroup repo = repositoryGroups.get( id );
- if ( repo != null )
- {
- repo = repositoryGroups.remove( id );
- if ( repo != null )
- {
- this.mergedRemoteIndexesScheduler.unschedule( repo );
- repo.close( );
- RepositoryGroupConfiguration cfg = configuration.findRepositoryGroupById( id );
- if ( cfg != null )
- {
- configuration.removeRepositoryGroup( cfg );
- }
- }
- }
-
- }
-
- @Override
- public RepositoryGroup get( String groupId )
- {
- return repositoryGroups.get( groupId );
- }
-
- @Override
- public RepositoryGroup clone( RepositoryGroup repo ) throws RepositoryException
- {
- RepositoryProvider provider = repositoryRegistry.getProvider( repo.getType( ) );
- RepositoryGroupConfiguration cfg = provider.getRepositoryGroupConfiguration( repo );
- RepositoryGroup cloned = provider.createRepositoryGroup( cfg );
- cloned.registerEventHandler( RepositoryEvent.ANY, repositoryRegistry );
- return cloned;
- }
-
- @Override
- public void updateReferences( RepositoryGroup repo, RepositoryGroupConfiguration repositoryConfiguration ) throws RepositoryException
- {
- if ( repo instanceof EditableRepositoryGroup )
- {
- EditableRepositoryGroup eGroup = (EditableRepositoryGroup) repo;
- eGroup.setRepositories( repositoryConfiguration.getRepositories( ).stream( )
- .map( repositoryRegistry::getManagedRepository ).collect( Collectors.toList( ) ) );
- }
-
- }
-
- @Override
- public Collection<RepositoryGroup> getAll( )
- {
- return repositoryGroups.values( );
- }
-
- @Override
- public RepositoryValidator<RepositoryGroup> getValidator( )
- {
- return this.validator;
- }
-
- @Override
- public boolean has( String id )
- {
- return repositoryGroups.containsKey( id );
- }
-
- @PreDestroy
- private void destroy( )
- {
- this.close( );
- }
-
- @Override
- public void close( )
- {
- for ( RepositoryGroup group : repositoryGroups.values( ) )
- {
- try
- {
- mergedRemoteIndexesScheduler.unschedule( group );
- group.close( );
- }
- catch ( Throwable e )
- {
- log.error( "Could not close repository group {}: {}", group.getId( ), e.getMessage( ) );
- }
- }
- this.repositoryGroups.clear( );
- }
-
-}
--- /dev/null
+package org.apache.archiva.repository.base.group;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.archiva.repository.EditableRepositoryGroup;
+import org.apache.archiva.repository.ManagedRepository;
+import org.apache.archiva.repository.RepositoryCapabilities;
+import org.apache.archiva.repository.RepositoryType;
+import org.apache.archiva.repository.base.AbstractRepository;
+import org.apache.archiva.repository.storage.RepositoryStorage;
+import org.apache.commons.collections4.map.ListOrderedMap;
+
+import java.util.List;
+import java.util.Locale;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+/**
+ * Abstract repository group implementation.
+ *
+ */
+public class AbstractRepositoryGroup extends AbstractRepository implements EditableRepositoryGroup
+{
+
+ private final ListOrderedMap<String, ManagedRepository> repositories = new ListOrderedMap<>();
+
+ private int mergedIndexTTL;
+
+ private final ReadWriteLock rwl = new ReentrantReadWriteLock();
+
+ private RepositoryCapabilities capabilities;
+
+ public AbstractRepositoryGroup( RepositoryType type, String id, String name, RepositoryStorage storage) {
+ super(type, id, name, storage);
+ }
+
+ public AbstractRepositoryGroup(Locale primaryLocale, RepositoryType type, String id, String name, RepositoryStorage storage) {
+ super(primaryLocale, type, id, name, storage);
+ }
+
+ @Override
+ public boolean hasIndex() {
+ return true;
+ }
+
+ @Override
+ public RepositoryCapabilities getCapabilities() {
+ return capabilities;
+ }
+
+
+ @Override
+ public void clearRepositories() {
+ rwl.writeLock().lock();
+ try {
+ repositories.clear();
+ } finally {
+ rwl.writeLock().unlock();
+ }
+ }
+
+ @Override
+ public void setRepositories(List<ManagedRepository> newRepositories) {
+ rwl.writeLock().lock();
+ try {
+ repositories.clear();
+ for(ManagedRepository repo : newRepositories) {
+ if (repo!=null)
+ repositories.put(repo.getId(), repo);
+ }
+ } finally {
+ rwl.writeLock().unlock();
+ }
+ }
+
+ @Override
+ public void addRepository(ManagedRepository repository) {
+ rwl.writeLock().lock();
+ try {
+ if (repository!=null)
+ repositories.put(repository.getId(), repository);
+ } finally {
+ rwl.writeLock().unlock();
+ }
+ }
+
+ @Override
+ public void addRepository(int index, ManagedRepository repository) {
+ rwl.writeLock().lock();
+ try {
+ if (repository!=null)
+ repositories.put(index, repository.getId(), repository);
+ } finally {
+ rwl.writeLock().unlock();
+ }
+ }
+
+ @Override
+ public boolean removeRepository(ManagedRepository repository) {
+ rwl.writeLock().lock();
+ try {
+ return repositories.remove(repository.getId(), repository);
+ } finally {
+ rwl.writeLock().unlock();
+ }
+ }
+
+ @Override
+ public ManagedRepository removeRepository(String repoId) {
+ rwl.writeLock().lock();
+ try {
+ return repositories.remove(repoId);
+ } finally {
+ rwl.writeLock().unlock();
+ }
+ }
+
+ @Override
+ public void setMergedIndexTTL(int timeInSeconds) {
+ this.mergedIndexTTL = timeInSeconds;
+ }
+
+ @Override
+ public List<ManagedRepository> getRepositories() {
+ rwl.readLock().lock();
+ try {
+ return repositories.valueList();
+ } finally {
+ rwl.readLock().unlock();
+ }
+ }
+
+ @Override
+ public boolean contains(ManagedRepository repository) {
+ rwl.readLock().lock();
+ try {
+ return repositories.containsValue(repository);
+ } finally {
+ rwl.readLock().unlock();
+ }
+ }
+
+ @Override
+ public boolean contains(String id) {
+ rwl.readLock().lock();
+ try {
+ return repositories.containsKey(id);
+ } finally {
+ rwl.readLock().unlock();
+ }
+ }
+
+ @Override
+ public int getMergedIndexTTL() {
+ return mergedIndexTTL;
+ }
+
+ protected void setCapabilities(RepositoryCapabilities capabilities) {
+ this.capabilities = capabilities;
+ }
+}
--- /dev/null
+package org.apache.archiva.repository.base.group;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.archiva.repository.RepositoryGroup;
+import org.apache.archiva.repository.RepositoryRegistry;
+import org.apache.archiva.repository.base.ConfigurationHandler;
+import org.apache.archiva.repository.validation.AbstractRepositoryValidator;
+import org.apache.archiva.repository.validation.RepositoryValidator;
+import org.apache.archiva.repository.validation.ValidationError;
+import org.apache.archiva.repository.validation.ValidationResponse;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import static org.apache.archiva.repository.validation.ErrorKeys.*;
+
+/**
+ *
+ * A validator for repository groups. All validation errors are prefixed with category 'repository_group'.
+ *
+ * @author Martin Stockhammer <martin_s@apache.org>
+ */
+@Service( "repositoryValidator#common#group" )
+public class BasicRepositoryGroupValidator extends AbstractRepositoryValidator<RepositoryGroup> implements RepositoryValidator<RepositoryGroup>
+{
+
+ private static final String CATEGORY = "repository_group";
+ private static final Pattern REPO_GROUP_ID_PATTERN = Pattern.compile( "[A-Za-z0-9._\\-]+" );
+ private final ConfigurationHandler configurationHandler;
+
+ private RepositoryRegistry repositoryRegistry;
+
+ public BasicRepositoryGroupValidator( ConfigurationHandler configurationHandler )
+ {
+ super( CATEGORY );
+ this.configurationHandler = configurationHandler;
+ }
+
+
+ @Override
+ public ValidationResponse<RepositoryGroup> apply( RepositoryGroup repositoryGroup, boolean updateMode ) throws IllegalArgumentException
+ {
+ final String repoGroupId = repositoryGroup.getId( );
+ Map<String, List<ValidationError>> errors = null;
+ if ( StringUtils.isBlank( repoGroupId ) )
+ {
+ errors = appendError( null, "id", ISEMPTY );
+ }
+
+ if ( repoGroupId.length( ) > 100 )
+ {
+ errors = appendError( errors, "id", MAX_LENGTH_EXCEEDED, repoGroupId, Integer.toString( 100 ) );
+
+ }
+
+ Matcher matcher = REPO_GROUP_ID_PATTERN.matcher( repoGroupId );
+ if ( !matcher.matches( ) )
+ {
+ errors = appendError( errors, "id", INVALID_CHARS, repoGroupId, new String[]{"alphanumeric, '.', '-','_'"} );
+ }
+
+ if ( repositoryGroup.getMergedIndexTTL( ) <= 0 )
+ {
+ errors = appendError( errors, "merged_index_ttl",BELOW_MIN, "0" );
+ }
+
+
+ if ( repositoryRegistry != null && !updateMode )
+ {
+ if ( repositoryRegistry.hasRepositoryGroup( repoGroupId ) )
+ {
+ errors = appendError( errors, "id", REPOSITORY_GROUP_EXISTS, repoGroupId );
+ }
+ else if ( repositoryRegistry.hasManagedRepository( repoGroupId ) )
+ {
+ errors = appendError( errors, "id", MANAGED_REPOSITORY_EXISTS );
+ }
+ else if ( repositoryRegistry.hasRemoteRepository( repoGroupId ) )
+ {
+ errors = appendError( errors, "id", REMOTE_REPOSITORY_EXISTS );
+ }
+ }
+ return new ValidationResponse<>(repositoryGroup, errors );
+ }
+
+
+
+
+ public ConfigurationHandler getConfigurationHandler( )
+ {
+ return configurationHandler;
+ }
+
+ public RepositoryRegistry getRepositoryRegistry( )
+ {
+ return repositoryRegistry;
+ }
+
+ @Override
+ public void setRepositoryRegistry( RepositoryRegistry repositoryRegistry )
+ {
+ this.repositoryRegistry = repositoryRegistry;
+ }
+
+ @Override
+ public Class<RepositoryGroup> getFlavour( )
+ {
+ return RepositoryGroup.class;
+ }
+
+}
--- /dev/null
+package org.apache.archiva.repository.base.group;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.archiva.components.registry.RegistryException;
+import org.apache.archiva.configuration.Configuration;
+import org.apache.archiva.configuration.IndeterminateConfigurationException;
+import org.apache.archiva.configuration.RepositoryGroupConfiguration;
+import org.apache.archiva.indexer.merger.MergedRemoteIndexesScheduler;
+import org.apache.archiva.repository.base.ArchivaRepositoryRegistry;
+import org.apache.archiva.repository.base.ConfigurationHandler;
+import org.apache.archiva.repository.validation.CheckedResult;
+import org.apache.archiva.repository.EditableRepository;
+import org.apache.archiva.repository.EditableRepositoryGroup;
+import org.apache.archiva.repository.ManagedRepository;
+import org.apache.archiva.repository.Repository;
+import org.apache.archiva.repository.RepositoryException;
+import org.apache.archiva.repository.RepositoryGroup;
+import org.apache.archiva.repository.RepositoryHandler;
+import org.apache.archiva.repository.RepositoryProvider;
+import org.apache.archiva.repository.RepositoryType;
+import org.apache.archiva.repository.event.RepositoryEvent;
+import org.apache.archiva.repository.features.IndexCreationFeature;
+import org.apache.archiva.repository.storage.StorageAsset;
+import org.apache.archiva.repository.validation.CombinedValidator;
+import org.apache.archiva.repository.validation.RepositoryChecker;
+import org.apache.archiva.repository.validation.RepositoryValidator;
+import org.apache.archiva.repository.validation.ValidationResponse;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.inject.Named;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.stream.Collectors;
+
+import static org.apache.archiva.indexer.ArchivaIndexManager.DEFAULT_INDEX_PATH;
+
+/**
+ * This class manages repository groups for the RepositoryRegistry.
+ * It is tightly coupled with the {@link ArchivaRepositoryRegistry}.
+ *
+ * @author Martin Stockhammer <martin_s@apache.org>
+ */
+@Service( "repositoryGroupHandler#default" )
+public class RepositoryGroupHandler implements RepositoryHandler<RepositoryGroup, RepositoryGroupConfiguration>
+{
+ private static final Logger log = LoggerFactory.getLogger( RepositoryGroupHandler.class );
+
+ private final ArchivaRepositoryRegistry repositoryRegistry;
+ private final ConfigurationHandler configurationHandler;
+ private final MergedRemoteIndexesScheduler mergedRemoteIndexesScheduler;
+
+ private final Map<String, RepositoryGroup> repositoryGroups = new HashMap<>( );
+ private final RepositoryValidator<RepositoryGroup> validator;
+
+ private Path groupsDirectory;
+
+
+ /**
+ * Creates a new instance. All dependencies are injected on the constructor.
+ *
+ * @param repositoryRegistry the registry. To avoid circular dependencies via DI, this class registers itself on the registry.
+ * @param configurationHandler the configuration handler is used to retrieve and save configuration.
+ * @param mergedRemoteIndexesScheduler the index scheduler is used for merging the indexes from all group members
+ */
+ public RepositoryGroupHandler( ArchivaRepositoryRegistry repositoryRegistry,
+ ConfigurationHandler configurationHandler,
+ @Named( "mergedRemoteIndexesScheduler#default" ) MergedRemoteIndexesScheduler mergedRemoteIndexesScheduler,
+ List<RepositoryValidator<? extends Repository>> repositoryGroupValidatorList
+ )
+ {
+ this.configurationHandler = configurationHandler;
+ this.mergedRemoteIndexesScheduler = mergedRemoteIndexesScheduler;
+ this.repositoryRegistry = repositoryRegistry;
+ List<RepositoryValidator<RepositoryGroup>> validatorList = initValidators( repositoryGroupValidatorList );
+ this.validator = new CombinedValidator<>( RepositoryGroup.class, validatorList );
+ }
+
+ private List<RepositoryValidator<RepositoryGroup>> initValidators(List<RepositoryValidator<? extends Repository>> repositoryGroupValidatorList) {
+ if (repositoryGroupValidatorList!=null && repositoryGroupValidatorList.size()>0) {
+ return repositoryGroupValidatorList.stream( ).filter(
+ v -> v.isFlavour( RepositoryGroup.class )
+ ).map( v -> v.narrowTo( RepositoryGroup.class ) ).collect( Collectors.toList( ) );
+ } else {
+ return Collections.emptyList( );
+ }
+ }
+
+ @Override
+ @PostConstruct
+ public void init( )
+ {
+ log.debug( "Initializing repository group handler " + repositoryRegistry.toString( ) );
+ initializeStorage( );
+ // We are registering this class on the registry. This is necessary to avoid circular dependencies via injection.
+ this.repositoryRegistry.registerGroupHandler( this );
+ }
+
+ public void initializeFromConfig( )
+ {
+ this.repositoryGroups.clear( );
+ this.repositoryGroups.putAll( newInstancesFromConfig( ) );
+ for ( RepositoryGroup group : this.repositoryGroups.values( ) )
+ {
+ initializeGroup( group );
+ }
+ }
+
+ private void initializeStorage( )
+ {
+ Path baseDir = this.configurationHandler.getArchivaConfiguration( ).getRepositoryGroupBaseDir( );
+ if ( !Files.exists( baseDir ) )
+ {
+ try
+ {
+ Files.createDirectories( baseDir );
+ }
+ catch ( IOException e )
+ {
+ log.error( "Could not create group base directory: {}", e.getMessage( ), e );
+ }
+ }
+ this.groupsDirectory = baseDir;
+ }
+
+ private void initializeGroup( RepositoryGroup repositoryGroup )
+ {
+ StorageAsset indexDirectory = getMergedIndexDirectory( repositoryGroup );
+ if ( !indexDirectory.exists( ) )
+ {
+ try
+ {
+ indexDirectory.create( );
+ }
+ catch ( IOException e )
+ {
+ log.error( "Could not create index directory {} for group {}: {}", indexDirectory, repositoryGroup.getId( ), e.getMessage( ) );
+ }
+ }
+ Path groupPath = groupsDirectory.resolve( repositoryGroup.getId( ) );
+ if ( !Files.exists( groupPath ) )
+ {
+ try
+ {
+ Files.createDirectories( groupPath );
+ }
+ catch ( IOException e )
+ {
+ log.error( "Could not create repository group directory {}", groupPath );
+ }
+ }
+ mergedRemoteIndexesScheduler.schedule( repositoryGroup,
+ indexDirectory );
+ }
+
+ public StorageAsset getMergedIndexDirectory( RepositoryGroup group )
+ {
+ if ( group != null )
+ {
+ return group.getFeature( IndexCreationFeature.class ).get( ).getLocalIndexPath( );
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+
+ @Override
+ public Map<String, RepositoryGroup> newInstancesFromConfig( )
+ {
+ try
+ {
+ List<RepositoryGroupConfiguration> repositoryGroupConfigurations =
+ this.configurationHandler.getBaseConfiguration( ).getRepositoryGroups( );
+
+ if ( repositoryGroupConfigurations == null )
+ {
+ return Collections.emptyMap( );
+ }
+
+ Map<String, RepositoryGroup> repositoryGroupMap = new LinkedHashMap<>( repositoryGroupConfigurations.size( ) );
+
+ Map<RepositoryType, RepositoryProvider> providerMap = repositoryRegistry.getRepositoryProviderMap( );
+ for ( RepositoryGroupConfiguration repoConfig : repositoryGroupConfigurations )
+ {
+ RepositoryType repositoryType = RepositoryType.valueOf( repoConfig.getType( ) );
+ if ( providerMap.containsKey( repositoryType ) )
+ {
+ try
+ {
+ RepositoryGroup repo = createNewRepositoryGroup( providerMap.get( repositoryType ), repoConfig );
+ repositoryGroupMap.put( repo.getId( ), repo );
+ }
+ catch ( Exception e )
+ {
+ log.error( "Could not create repository group {}: {}", repoConfig.getId( ), e.getMessage( ), e );
+ }
+ }
+ }
+ return repositoryGroupMap;
+ }
+ catch ( Throwable e )
+ {
+ log.error( "Could not initialize repositories from config: {}", e.getMessage( ), e );
+ return Collections.emptyMap( );
+ }
+ }
+
+ @Override
+ public RepositoryGroup newInstance( final RepositoryType type, String id ) throws RepositoryException
+ {
+ RepositoryProvider provider = repositoryRegistry.getProvider( type );
+ RepositoryGroupConfiguration config = new RepositoryGroupConfiguration( );
+ config.setId( id );
+ return createNewRepositoryGroup( provider, config );
+ }
+
+ @Override
+ public RepositoryGroup newInstance( final RepositoryGroupConfiguration repositoryConfiguration ) throws RepositoryException
+ {
+ RepositoryType type = RepositoryType.valueOf( repositoryConfiguration.getType( ) );
+ RepositoryProvider provider = repositoryRegistry.getProvider( type );
+ return createNewRepositoryGroup( provider, repositoryConfiguration );
+ }
+
+ private RepositoryGroup createNewRepositoryGroup( RepositoryProvider provider, RepositoryGroupConfiguration config ) throws RepositoryException
+ {
+ RepositoryGroup repositoryGroup = provider.createRepositoryGroup( config );
+ updateReferences( repositoryGroup, config );
+ return repositoryGroup;
+ }
+
+
+ /**
+ * Adds a new repository group to the current list, or replaces the repository group definition with
+ * the same id, if it exists already.
+ * The change is saved to the configuration immediately.
+ *
+ * @param repositoryGroup the new repository group.
+ * @throws RepositoryException if the new repository group could not be saved to the configuration.
+ */
+ @Override
+ public RepositoryGroup put( final RepositoryGroup repositoryGroup ) throws RepositoryException
+ {
+ final String id = repositoryGroup.getId( );
+ RepositoryGroup originRepoGroup = repositoryGroups.remove( id );
+ try
+ {
+ if ( originRepoGroup != null && originRepoGroup != repositoryGroup )
+ {
+ this.mergedRemoteIndexesScheduler.unschedule( originRepoGroup );
+ originRepoGroup.close( );
+ }
+ RepositoryProvider provider = repositoryRegistry.getProvider( repositoryGroup.getType( ) );
+ RepositoryGroupConfiguration newCfg = provider.getRepositoryGroupConfiguration( repositoryGroup );
+ ReentrantReadWriteLock.WriteLock configLock = this.configurationHandler.getLock( ).writeLock( );
+ configLock.lock( );
+ try
+ {
+ Configuration configuration = this.configurationHandler.getBaseConfiguration( );
+ updateReferences( repositoryGroup, newCfg );
+ RepositoryGroupConfiguration oldCfg = configuration.findRepositoryGroupById( id );
+ if ( oldCfg != null )
+ {
+ configuration.removeRepositoryGroup( oldCfg );
+ }
+ configuration.addRepositoryGroup( newCfg );
+ configurationHandler.save( configuration, ConfigurationHandler.REGISTRY_EVENT_TAG );
+ initializeGroup( repositoryGroup );
+ }
+ finally
+ {
+ configLock.unlock( );
+ }
+ repositoryGroups.put( id, repositoryGroup );
+ return repositoryGroup;
+ }
+ catch ( Exception e )
+ {
+ // Rollback
+ if ( originRepoGroup != null )
+ {
+ repositoryGroups.put( id, originRepoGroup );
+ }
+ else
+ {
+ repositoryGroups.remove( id );
+ }
+ log.error( "Exception during configuration update {}", e.getMessage( ), e );
+ throw new RepositoryException( "Could not save the configuration" + ( e.getMessage( ) == null ? "" : ": " + e.getMessage( ) ), e);
+ }
+ }
+
+ /**
+ * Adds a new repository group or updates the repository with the same id, if it exists already.
+ * The configuration is saved immediately.
+ *
+ * @param repositoryGroupConfiguration the repository configuration
+ * @return the updated or created repository
+ * @throws RepositoryException if an error occurs, or the configuration is not valid.
+ */
+ @Override
+ public RepositoryGroup put( RepositoryGroupConfiguration repositoryGroupConfiguration ) throws RepositoryException
+ {
+ final String id = repositoryGroupConfiguration.getId( );
+ final RepositoryType repositoryType = RepositoryType.valueOf( repositoryGroupConfiguration.getType( ) );
+ final RepositoryProvider provider = repositoryRegistry.getProvider( repositoryType );
+ RepositoryGroup currentRepository;
+ ReentrantReadWriteLock.WriteLock configLock = this.configurationHandler.getLock( ).writeLock( );
+ configLock.lock( );
+ try
+ {
+ Configuration configuration = this.configurationHandler.getBaseConfiguration( );
+ currentRepository = repositoryRegistry.getRepositoryGroup( id );
+ RepositoryGroup oldRepository = currentRepository == null ? null : clone( currentRepository );
+ try
+ {
+
+ if (currentRepository==null) {
+ currentRepository = put( repositoryGroupConfiguration, configuration );
+ } else
+ {
+ setRepositoryGroupDefaults( repositoryGroupConfiguration );
+ provider.updateRepositoryGroupInstance( (EditableRepositoryGroup) currentRepository, repositoryGroupConfiguration );
+ }
+ configurationHandler.save( configuration, ConfigurationHandler.REGISTRY_EVENT_TAG );
+ updateReferences( currentRepository, repositoryGroupConfiguration );
+ initializeGroup( currentRepository );
+ this.repositoryGroups.put( id, currentRepository );
+ }
+ catch ( IndeterminateConfigurationException | RegistryException | RepositoryException e )
+ {
+ // Trying a rollback
+ if ( oldRepository != null )
+ {
+ RepositoryGroupConfiguration oldCfg = provider.getRepositoryGroupConfiguration( oldRepository );
+ provider.updateRepositoryGroupInstance( (EditableRepositoryGroup) currentRepository, oldCfg);
+ replaceOrAddRepositoryConfig( oldCfg, configuration );
+ try
+ {
+ configurationHandler.save( configuration, ConfigurationHandler.REGISTRY_EVENT_TAG );
+ }
+ catch ( IndeterminateConfigurationException | RegistryException indeterminateConfigurationException )
+ {
+ log.error( "Fatal error, config save during rollback failed: {}", e.getMessage( ), e );
+ }
+ updateReferences( oldRepository, oldCfg );
+ initializeGroup( oldRepository );
+ }
+ log.error( "Could not save the configuration for repository group {}: {}", id, e.getMessage( ), e );
+ if (e instanceof RepositoryException) {
+ throw (RepositoryException) e;
+ } else
+ {
+ throw new RepositoryException( "Could not save the configuration for repository group " + id + ": " + e.getMessage( ) );
+ }
+ }
+ }
+ finally
+ {
+ configLock.unlock( );
+ }
+ return currentRepository;
+ }
+
+ @Override
+ public RepositoryGroup put( RepositoryGroupConfiguration repositoryGroupConfiguration, Configuration configuration ) throws RepositoryException
+ {
+ final String id = repositoryGroupConfiguration.getId( );
+ final RepositoryType repoType = RepositoryType.valueOf( repositoryGroupConfiguration.getType( ) );
+ RepositoryGroup repo;
+ setRepositoryGroupDefaults( repositoryGroupConfiguration );
+ if ( repositoryGroups.containsKey( id ) )
+ {
+ repo = clone( repositoryGroups.get( id ) );
+ if ( repo instanceof EditableRepositoryGroup )
+ {
+ repositoryRegistry.getProvider( repoType ).updateRepositoryGroupInstance( (EditableRepositoryGroup) repo, repositoryGroupConfiguration );
+ }
+ else
+ {
+ throw new RepositoryException( "The repository is not editable " + id );
+ }
+ }
+ else
+ {
+ repo = repositoryRegistry.getProvider( repoType ).createRepositoryGroup( repositoryGroupConfiguration );
+ }
+ replaceOrAddRepositoryConfig( repositoryGroupConfiguration, configuration );
+ updateReferences( repo, repositoryGroupConfiguration );
+ return repo;
+ }
+
+ @Override
+ public <D> CheckedResult<RepositoryGroup, D> putWithCheck( RepositoryGroupConfiguration repositoryConfiguration, RepositoryChecker<RepositoryGroup, D> checker ) throws RepositoryException
+ {
+ final String id = repositoryConfiguration.getId( );
+ RepositoryGroup currentGroup = repositoryGroups.get( id );
+ Configuration configuration = configurationHandler.getBaseConfiguration( );
+ RepositoryGroup repositoryGroup = put( repositoryConfiguration, configuration );
+ CheckedResult<RepositoryGroup, D> result;
+ if ( currentGroup == null )
+ {
+ result = checker.apply( repositoryGroup );
+ }
+ else
+ {
+ result = checker.applyForUpdate( repositoryGroup );
+ }
+ if ( result.isValid( ) )
+ {
+ put( result.getRepository() );
+ }
+ return result;
+ }
+
+
+ private void setRepositoryGroupDefaults( RepositoryGroupConfiguration repositoryGroupConfiguration )
+ {
+ if ( StringUtils.isEmpty( repositoryGroupConfiguration.getMergedIndexPath( ) ) )
+ {
+ repositoryGroupConfiguration.setMergedIndexPath( DEFAULT_INDEX_PATH );
+ }
+ if ( repositoryGroupConfiguration.getMergedIndexTtl( ) <= 0 )
+ {
+ repositoryGroupConfiguration.setMergedIndexTtl( 300 );
+ }
+ if ( StringUtils.isEmpty( repositoryGroupConfiguration.getCronExpression( ) ) )
+ {
+ repositoryGroupConfiguration.setCronExpression( "0 0 03 ? * MON" );
+ }
+ }
+
+ private void replaceOrAddRepositoryConfig( RepositoryGroupConfiguration repositoryGroupConfiguration, Configuration configuration )
+ {
+ RepositoryGroupConfiguration oldCfg = configuration.findRepositoryGroupById( repositoryGroupConfiguration.getId( ) );
+ if ( oldCfg != null )
+ {
+ configuration.removeRepositoryGroup( oldCfg );
+ }
+ configuration.addRepositoryGroup( repositoryGroupConfiguration );
+ }
+
+ public void removeRepositoryFromGroups( ManagedRepository repo )
+ {
+ if ( repo != null )
+ {
+ repositoryGroups.values( ).stream( ).filter( repoGroup -> repoGroup instanceof EditableRepository ).
+ map( repoGroup -> (EditableRepositoryGroup) repoGroup ).forEach( repoGroup -> repoGroup.removeRepository( repo ) );
+ }
+ }
+
+ /**
+ * Removes a repository group from the registry and configuration, if it exists.
+ * The change is saved to the configuration immediately.
+ *
+ * @param id the id of the repository group to remove
+ * @throws RepositoryException if a error occurs during configuration save
+ */
+ @Override
+ public void remove( final String id ) throws RepositoryException
+ {
+ RepositoryGroup repo = get( id );
+ if ( repo != null )
+ {
+ try
+ {
+ repo = repositoryGroups.remove( id );
+ if ( repo != null )
+ {
+ this.mergedRemoteIndexesScheduler.unschedule( repo );
+ repo.close( );
+ Configuration configuration = this.configurationHandler.getBaseConfiguration( );
+ RepositoryGroupConfiguration cfg = configuration.findRepositoryGroupById( id );
+ if ( cfg != null )
+ {
+ configuration.removeRepositoryGroup( cfg );
+ }
+ this.configurationHandler.save( configuration, ConfigurationHandler.REGISTRY_EVENT_TAG );
+ }
+
+ }
+ catch ( RegistryException | IndeterminateConfigurationException e )
+ {
+ // Rollback
+ log.error( "Could not save config after repository removal: {}", e.getMessage( ), e );
+ repositoryGroups.put( repo.getId( ), repo );
+ throw new RepositoryException( "Could not save configuration after repository removal: " + e.getMessage( ) );
+ }
+ }
+ }
+
+ @Override
+ public void remove( String id, Configuration configuration ) throws RepositoryException
+ {
+ RepositoryGroup repo = repositoryGroups.get( id );
+ if ( repo != null )
+ {
+ repo = repositoryGroups.remove( id );
+ if ( repo != null )
+ {
+ this.mergedRemoteIndexesScheduler.unschedule( repo );
+ repo.close( );
+ RepositoryGroupConfiguration cfg = configuration.findRepositoryGroupById( id );
+ if ( cfg != null )
+ {
+ configuration.removeRepositoryGroup( cfg );
+ }
+ }
+ }
+
+ }
+
+ @Override
+ public RepositoryGroup get( String groupId )
+ {
+ return repositoryGroups.get( groupId );
+ }
+
+ @Override
+ public RepositoryGroup clone( RepositoryGroup repo ) throws RepositoryException
+ {
+ RepositoryProvider provider = repositoryRegistry.getProvider( repo.getType( ) );
+ RepositoryGroupConfiguration cfg = provider.getRepositoryGroupConfiguration( repo );
+ RepositoryGroup cloned = provider.createRepositoryGroup( cfg );
+ cloned.registerEventHandler( RepositoryEvent.ANY, repositoryRegistry );
+ return cloned;
+ }
+
+ @Override
+ public void updateReferences( RepositoryGroup repo, RepositoryGroupConfiguration repositoryConfiguration ) throws RepositoryException
+ {
+ if ( repo instanceof EditableRepositoryGroup )
+ {
+ EditableRepositoryGroup eGroup = (EditableRepositoryGroup) repo;
+ eGroup.setRepositories( repositoryConfiguration.getRepositories( ).stream( )
+ .map( repositoryRegistry::getManagedRepository ).collect( Collectors.toList( ) ) );
+ }
+
+ }
+
+ @Override
+ public Collection<RepositoryGroup> getAll( )
+ {
+ return repositoryGroups.values( );
+ }
+
+ @Override
+ public RepositoryValidator<RepositoryGroup> getValidator( )
+ {
+ return this.validator;
+ }
+
+ @Override
+ public ValidationResponse<RepositoryGroup> validateRepository( RepositoryGroup repository )
+ {
+ return null;
+ }
+
+ @Override
+ public ValidationResponse<RepositoryGroup> validateRepositoryForUpdate( RepositoryGroup repository )
+ {
+ return null;
+ }
+
+ @Override
+ public boolean has( String id )
+ {
+ return repositoryGroups.containsKey( id );
+ }
+
+ @PreDestroy
+ private void destroy( )
+ {
+ this.close( );
+ }
+
+ @Override
+ public void close( )
+ {
+ for ( RepositoryGroup group : repositoryGroups.values( ) )
+ {
+ try
+ {
+ mergedRemoteIndexesScheduler.unschedule( group );
+ group.close( );
+ }
+ catch ( Throwable e )
+ {
+ log.error( "Could not close repository group {}: {}", group.getId( ), e.getMessage( ) );
+ }
+ }
+ this.repositoryGroups.clear( );
+ }
+
+}
--- /dev/null
+package org.apache.archiva.repository.base.managed;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+import org.apache.archiva.repository.EditableManagedRepository;
+import org.apache.archiva.repository.ManagedRepositoryContent;
+import org.apache.archiva.repository.ReleaseScheme;
+import org.apache.archiva.repository.RepositoryType;
+import org.apache.archiva.repository.base.AbstractRepository;
+import org.apache.archiva.repository.storage.RepositoryStorage;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.Set;
+
+/**
+ * Simple implementation of a managed repository.
+ */
+public abstract class AbstractManagedRepository extends AbstractRepository implements EditableManagedRepository
+{
+ private boolean blocksRedeployment = false;
+ private ManagedRepositoryContent content;
+ private Set<ReleaseScheme> activeReleaseSchemes = new HashSet<>( );
+ private Set<ReleaseScheme> uActiveReleaseSchemes = Collections.unmodifiableSet( activeReleaseSchemes );
+
+ public AbstractManagedRepository( RepositoryType type, String id, String name, RepositoryStorage storage)
+ {
+ super( type, id, name, storage );
+ }
+
+ public AbstractManagedRepository( Locale primaryLocale, RepositoryType type, String id, String name, RepositoryStorage storage )
+ {
+ super( primaryLocale, type, id, name, storage );
+ }
+
+ @Override
+ public ManagedRepositoryContent getContent( )
+ {
+ return content;
+ }
+
+ @Override
+ public void setContent( ManagedRepositoryContent content) {
+ this.content = content;
+ }
+
+ @Override
+ public void setBlocksRedeployment( boolean blocksRedeployment )
+ {
+ this.blocksRedeployment = blocksRedeployment;
+ }
+
+ @Override
+ public boolean blocksRedeployments( )
+ {
+ return blocksRedeployment;
+ }
+
+ @Override
+ public Set<ReleaseScheme> getActiveReleaseSchemes( )
+ {
+ return uActiveReleaseSchemes;
+ }
+
+ @Override
+ public void addActiveReleaseScheme( ReleaseScheme scheme )
+ {
+ this.activeReleaseSchemes.add(scheme);
+ }
+
+ @Override
+ public void removeActiveReleaseScheme( ReleaseScheme scheme )
+ {
+ this.activeReleaseSchemes.remove(scheme);
+ }
+
+ @Override
+ public void clearActiveReleaseSchemes( )
+ {
+ this.activeReleaseSchemes.clear();
+ }
+
+
+}
--- /dev/null
+package org.apache.archiva.repository.base.managed;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.archiva.common.filelock.DefaultFileLockManager;
+import org.apache.archiva.common.filelock.FileLockManager;
+import org.apache.archiva.repository.ReleaseScheme;
+import org.apache.archiva.repository.RepositoryCapabilities;
+import org.apache.archiva.repository.RepositoryRequestInfo;
+import org.apache.archiva.repository.RepositoryType;
+import org.apache.archiva.repository.StandardCapabilities;
+import org.apache.archiva.repository.storage.fs.FilesystemStorage;
+import org.apache.archiva.repository.storage.RepositoryStorage;
+import org.apache.archiva.repository.features.ArtifactCleanupFeature;
+import org.apache.archiva.repository.features.IndexCreationFeature;
+import org.apache.archiva.repository.features.StagingRepositoryFeature;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.Locale;
+
+/**
+ *
+ * Just a helper class, mainly used for unit tests.
+ *
+ *
+ */
+public class BasicManagedRepository extends AbstractManagedRepository
+
+{
+ Logger log = LoggerFactory.getLogger(BasicManagedRepository.class);
+ ArtifactCleanupFeature artifactCleanupFeature = new ArtifactCleanupFeature( );
+ StagingRepositoryFeature stagingRepositoryFeature = new StagingRepositoryFeature( );
+
+ static final StandardCapabilities CAPABILITIES = new StandardCapabilities( new ReleaseScheme[] {
+ ReleaseScheme.RELEASE, ReleaseScheme.SNAPSHOT
+ }, new String[] {"default"}, new String[0], new String[] {
+ ArtifactCleanupFeature.class.toString(), IndexCreationFeature.class.toString(),
+ StagingRepositoryFeature.class.toString()
+ }, true, true, true, true, true );
+
+ public BasicManagedRepository( String id, String name, RepositoryStorage repositoryStorage )
+ {
+ super( RepositoryType.MAVEN, id, name, repositoryStorage );
+ initFeatures();
+ }
+
+ public BasicManagedRepository( Locale primaryLocale, RepositoryType type, String id, String name, RepositoryStorage repositoryStorage )
+ {
+ super( primaryLocale, type, id, name, repositoryStorage);
+ initFeatures();
+ }
+
+ private void initFeatures() {
+ IndexCreationFeature indexCreationFeature = new IndexCreationFeature(this, this);
+ addFeature( artifactCleanupFeature );
+ addFeature( indexCreationFeature );
+ addFeature( stagingRepositoryFeature );
+ }
+
+ @Override
+ public boolean hasIndex( )
+ {
+ return true;
+ }
+
+ @Override
+ public RepositoryCapabilities getCapabilities( )
+ {
+ return CAPABILITIES;
+ }
+
+
+ @Override
+ public RepositoryRequestInfo getRequestInfo() {
+ return null;
+ }
+
+ /**
+ * Creates a filesystem based repository instance. The path is built by basePath/repository-id
+ *
+ * @param id The repository id
+ * @param name The name of the repository
+ * @param repositoryPath The path to the repository
+ * @return The repository instance
+ * @throws IOException
+ */
+ public static BasicManagedRepository newFilesystemInstance(String id, String name, Path repositoryPath) throws IOException {
+ FileLockManager lockManager = new DefaultFileLockManager();
+ FilesystemStorage storage = new FilesystemStorage(repositoryPath, lockManager);
+ return new BasicManagedRepository(id, name, storage);
+ }
+
+}
--- /dev/null
+package org.apache.archiva.repository.base.managed;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.archiva.components.registry.Registry;
+import org.apache.archiva.repository.base.ConfigurationHandler;
+import org.apache.archiva.repository.validation.AbstractRepositoryValidator;
+import org.apache.archiva.repository.ManagedRepository;
+import org.apache.archiva.repository.RepositoryRegistry;
+import org.apache.archiva.repository.validation.RepositoryValidator;
+import org.apache.archiva.repository.validation.ValidationError;
+import org.apache.archiva.repository.validation.ValidationResponse;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Service;
+import org.apache.archiva.components.scheduler.CronExpressionValidator;
+
+
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+import static org.apache.archiva.repository.validation.ErrorKeys.*;
+
+/**
+ * Validator for managed repository data.
+ *
+ * @author Martin Stockhammer <martin_s@apache.org>
+ */
+@Service( "repositoryValidator#common#managed" )
+public class BasicManagedRepositoryValidator extends AbstractRepositoryValidator<ManagedRepository> implements RepositoryValidator<ManagedRepository>
+{
+ RepositoryRegistry repositoryRegistry;
+ private static final String CATEGORY = "managed_repository";
+ private static final Pattern REPOSITORY_ID_VALID_EXPRESSION_PATTERN = Pattern.compile( REPOSITORY_ID_VALID_EXPRESSION );
+ private static final Pattern REPOSITORY_NAME_VALID_EXPRESSION_PATTERN = Pattern.compile( REPOSITORY_NAME_VALID_EXPRESSION );
+ private static final Pattern REPOSITORY_LOCATION_VALID_EXPRESSION_PATTERN = Pattern.compile( REPOSITORY_LOCATION_VALID_EXPRESSION );
+
+ private final ConfigurationHandler configurationHandler;
+
+
+ public BasicManagedRepositoryValidator( ConfigurationHandler configurationHandler)
+ {
+ super( CATEGORY );
+ this.configurationHandler = configurationHandler;
+ }
+
+ @Override
+ public ValidationResponse<ManagedRepository> apply( ManagedRepository managedRepository, boolean update )
+ {
+ Map<String, List<ValidationError>> errors = null;
+ if (managedRepository==null) {
+ errors = appendError( errors, "id", ISNULL );
+ }
+ final String repoId = managedRepository.getId( );
+ if ( StringUtils.isBlank( repoId ) ) {
+ errors = appendError( errors, "id", ISEMPTY );
+ }
+
+ if (!update)
+ {
+ if ( repositoryRegistry.hasManagedRepository( managedRepository.getId( ) ) )
+ {
+ errors = appendError( errors, "id", MANAGED_REPOSITORY_EXISTS, repoId );
+ }
+ else if ( repositoryRegistry.hasRemoteRepository( repoId ) )
+ {
+ errors = appendError( errors, "id", REMOTE_REPOSITORY_EXISTS, repoId );
+ }
+ else if ( repositoryRegistry.hasRepositoryGroup( repoId ) )
+ {
+ errors = appendError( errors, "id", REPOSITORY_GROUP_EXISTS, repoId );
+ }
+ }
+
+ if ( !REPOSITORY_ID_VALID_EXPRESSION_PATTERN.matcher( repoId ).matches( ) )
+ {
+ errors = appendError( errors, "id", INVALID_CHARS, repoId, new String[]{"alphanumeric", "_", ".", "-"} );
+ }
+ if ( StringUtils.isBlank( managedRepository.getName() ) )
+ {
+ errors = appendError( errors, "name", ISEMPTY );
+ }
+
+ if ( !REPOSITORY_NAME_VALID_EXPRESSION_PATTERN.matcher( managedRepository.getName() ).matches( ) )
+ {
+ errors = appendError( errors, "name", INVALID_CHARS, managedRepository.getName( ), new String[]{"alphanumeric", "whitespace", "/", "(", ")", "_", ".", "-"} );
+ }
+
+ String cronExpression = managedRepository.getSchedulingDefinition( );
+ if ( StringUtils.isNotBlank( cronExpression ) )
+ {
+ CronExpressionValidator validator = new CronExpressionValidator( );
+
+ if ( !validator.validate( cronExpression ) )
+ {
+ errors = appendError( errors, "scheduling_definition", INVALID_SCHEDULING_EXPRESSION, cronExpression );
+ }
+ }
+ // Cron expression may be empty
+
+ String repoLocation = interpolateVars( managedRepository.getLocation( ).toString() );
+
+ if ( !REPOSITORY_LOCATION_VALID_EXPRESSION_PATTERN.matcher( repoLocation ).matches() )
+ {
+ errors = appendError( errors, "location", INVALID_LOCATION, repoLocation, new String[]{"alphanumeric", "=", "?", "!", "&", "/", "\\", "_", ".", ":", "~", "-"} );
+ }
+
+ return new ValidationResponse<>( managedRepository, errors );
+ }
+
+ public String interpolateVars( String directory )
+ {
+ Registry registry = configurationHandler.getArchivaConfiguration( ).getRegistry( );
+ String value = StringUtils.replace( directory, "${appserver.base}",
+ registry.getString( "appserver.base", "${appserver.base}" ) );
+ value = StringUtils.replace( value, "${appserver.home}",
+ registry.getString( "appserver.home", "${appserver.home}" ) );
+ return value;
+ }
+
+
+ @Override
+ public void setRepositoryRegistry( RepositoryRegistry repositoryRegistry )
+ {
+ this.repositoryRegistry = repositoryRegistry;
+ }
+
+ @Override
+ public Class<ManagedRepository> getFlavour( )
+ {
+ return ManagedRepository.class;
+ }
+
+}
--- /dev/null
+package org.apache.archiva.repository.base.managed;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.archiva.configuration.Configuration;
+import org.apache.archiva.configuration.ManagedRepositoryConfiguration;
+import org.apache.archiva.repository.base.ArchivaRepositoryRegistry;
+import org.apache.archiva.repository.base.ConfigurationHandler;
+import org.apache.archiva.repository.validation.CheckedResult;
+import org.apache.archiva.repository.ManagedRepository;
+import org.apache.archiva.repository.RepositoryException;
+import org.apache.archiva.repository.RepositoryHandler;
+import org.apache.archiva.repository.RepositoryType;
+import org.apache.archiva.repository.validation.RepositoryChecker;
+import org.apache.archiva.repository.validation.RepositoryValidator;
+import org.apache.archiva.repository.validation.ValidationResponse;
+
+import javax.inject.Named;
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * Handler implementation for managed repositories.
+ *
+ * @author Martin Stockhammer <martin_s@apache.org>
+ */
+public class ManagedRepositoryHandler
+implements RepositoryHandler<ManagedRepository, ManagedRepositoryConfiguration>
+{
+
+ public ManagedRepositoryHandler( ArchivaRepositoryRegistry repositoryRegistry,
+ ConfigurationHandler configurationHandler,
+ @Named( "repositoryValidator#common#managed") RepositoryValidator<ManagedRepository> managedRepositoryValidator )
+ {
+ }
+
+ @Override
+ public Map<String, ManagedRepository> newInstancesFromConfig( )
+ {
+ return null;
+ }
+
+ @Override
+ public ManagedRepository newInstance( RepositoryType type, String id ) throws RepositoryException
+ {
+ return null;
+ }
+
+ @Override
+ public ManagedRepository newInstance( ManagedRepositoryConfiguration repositoryConfiguration ) throws RepositoryException
+ {
+ return null;
+ }
+
+ @Override
+ public ManagedRepository put( ManagedRepository repository ) throws RepositoryException
+ {
+ return null;
+ }
+
+ @Override
+ public ManagedRepository put( ManagedRepositoryConfiguration repositoryConfiguration ) throws RepositoryException
+ {
+ return null;
+ }
+
+ @Override
+ public ManagedRepository put( ManagedRepositoryConfiguration repositoryConfiguration, Configuration configuration ) throws RepositoryException
+ {
+ return null;
+ }
+
+ @Override
+ public <D> CheckedResult<ManagedRepository, D> putWithCheck( ManagedRepositoryConfiguration repositoryConfiguration, RepositoryChecker<ManagedRepository, D> checker ) throws RepositoryException
+ {
+ return null;
+ }
+
+ @Override
+ public void remove( String id ) throws RepositoryException
+ {
+
+ }
+
+ @Override
+ public void remove( String id, Configuration configuration ) throws RepositoryException
+ {
+
+ }
+
+ @Override
+ public ManagedRepository get( String id )
+ {
+ return null;
+ }
+
+ @Override
+ public ManagedRepository clone( ManagedRepository repo ) throws RepositoryException
+ {
+ return null;
+ }
+
+ @Override
+ public void updateReferences( ManagedRepository repo, ManagedRepositoryConfiguration repositoryConfiguration ) throws RepositoryException
+ {
+
+ }
+
+ @Override
+ public Collection<ManagedRepository> getAll( )
+ {
+ return null;
+ }
+
+ @Override
+ public RepositoryValidator<ManagedRepository> getValidator( )
+ {
+ return null;
+ }
+
+ @Override
+ public ValidationResponse<ManagedRepository> validateRepository( ManagedRepository repository )
+ {
+ return null;
+ }
+
+ @Override
+ public ValidationResponse<ManagedRepository> validateRepositoryForUpdate( ManagedRepository repository )
+ {
+ return null;
+ }
+
+ @Override
+ public boolean has( String id )
+ {
+ return false;
+ }
+
+ @Override
+ public void init( )
+ {
+
+ }
+
+ @Override
+ public void close( )
+ {
+
+ }
+}
--- /dev/null
+package org.apache.archiva.repository.base.remote;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+import org.apache.archiva.repository.EditableRemoteRepository;
+import org.apache.archiva.repository.RemoteRepositoryContent;
+import org.apache.archiva.repository.RepositoryCredentials;
+import org.apache.archiva.repository.RepositoryType;
+import org.apache.archiva.repository.base.AbstractRepository;
+import org.apache.archiva.repository.storage.RepositoryStorage;
+
+import java.net.URI;
+import java.time.Duration;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+/**
+ * Abstract implementation of a remote repository. Abstract classes must implement the
+ * features and capabilities by themselves.
+ */
+public abstract class AbstractRemoteRepository extends AbstractRepository implements EditableRemoteRepository
+{
+
+ private RepositoryCredentials credentials;
+ private String checkPath;
+ private Map<String,String> extraParameters = new HashMap<>( );
+ private Map<String,String> uExtraParameters = Collections.unmodifiableMap( extraParameters );
+ private Map<String,String> extraHeaders = new HashMap<>( );
+ private Map<String,String> uExtraHeaders = Collections.unmodifiableMap( extraHeaders );
+ private Duration timeout = Duration.ofSeconds( 60 );
+ private String proxyId;
+ private RemoteRepositoryContent content;
+
+ public AbstractRemoteRepository( RepositoryType type, String id, String name , RepositoryStorage storage)
+ {
+ super( type, id, name, storage );
+ }
+
+ public AbstractRemoteRepository( Locale primaryLocale, RepositoryType type, String id, String name, RepositoryStorage storage )
+ {
+ super( primaryLocale, type, id, name, storage );
+ }
+
+ @Override
+ public void setCredentials( RepositoryCredentials credentials )
+ {
+ this.credentials = credentials;
+ }
+
+ @Override
+ public void setCheckPath( String path )
+ {
+ this.checkPath = path;
+ }
+
+ @Override
+ public void setExtraParameters( Map<String, String> params )
+ {
+ this.extraParameters.clear();
+ this.extraParameters.putAll(params);
+ }
+
+ @Override
+ public void addExtraParameter( String key, String value )
+ {
+ this.extraParameters.put(key, value);
+ }
+
+ @Override
+ public void setExtraHeaders( Map<String, String> headers )
+ {
+ this.extraHeaders.clear();
+ this.extraHeaders.putAll(headers);
+ }
+
+ @Override
+ public void addExtraHeader( String header, String value )
+ {
+ this.extraHeaders.put(header, value);
+ }
+
+ @Override
+ public void setTimeout( Duration duration )
+ {
+ this.timeout = duration;
+ }
+
+ @Override
+ public RemoteRepositoryContent getContent( )
+ {
+ return content;
+ }
+
+ @Override
+ public void setContent(RemoteRepositoryContent content) {
+ this.content = content;
+ }
+
+ @Override
+ public RepositoryCredentials getLoginCredentials( )
+ {
+ return credentials;
+ }
+
+ @Override
+ public String getCheckPath( )
+ {
+ return checkPath;
+ }
+
+ @Override
+ public Map<String, String> getExtraParameters( )
+ {
+ return uExtraParameters;
+ }
+
+ @Override
+ public Map<String, String> getExtraHeaders( )
+ {
+ return uExtraHeaders;
+ }
+
+ @Override
+ public Duration getTimeout( )
+ {
+ return timeout;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder str = new StringBuilder();
+ return str.append("checkPath=").append(checkPath)
+ .append(",creds:").append(credentials).toString();
+ }
+
+ @Override
+ public void setLocation(URI location) {
+ // Location of remote repositories is not for the local filestore
+ super.location = location;
+ }
+}
--- /dev/null
+package org.apache.archiva.repository.base.remote;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.archiva.common.filelock.DefaultFileLockManager;
+import org.apache.archiva.common.filelock.FileLockManager;
+import org.apache.archiva.repository.ReleaseScheme;
+import org.apache.archiva.repository.RepositoryCapabilities;
+import org.apache.archiva.repository.RepositoryType;
+import org.apache.archiva.repository.StandardCapabilities;
+import org.apache.archiva.repository.storage.fs.FilesystemStorage;
+import org.apache.archiva.repository.storage.RepositoryStorage;
+import org.apache.archiva.repository.features.IndexCreationFeature;
+import org.apache.archiva.repository.features.RemoteIndexFeature;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.Locale;
+
+/**
+ *
+ * Just a helper class, mainly used for unit tests.
+ *
+ *
+ */
+public class BasicRemoteRepository extends AbstractRemoteRepository
+
+{
+ Logger log = LoggerFactory.getLogger(BasicRemoteRepository.class);
+
+ RemoteIndexFeature remoteIndexFeature = new RemoteIndexFeature();
+ IndexCreationFeature indexCreationFeature = new IndexCreationFeature(true);
+
+
+ static final StandardCapabilities CAPABILITIES = new StandardCapabilities( new ReleaseScheme[] {
+ ReleaseScheme.RELEASE, ReleaseScheme.SNAPSHOT
+ }, new String[] {"default"}, new String[0], new String[] {
+ RemoteIndexFeature.class.toString(),
+ IndexCreationFeature.class.toString()
+ }, true, true, true, true, true );
+
+ public BasicRemoteRepository( String id, String name, RepositoryStorage storage)
+ {
+ super( RepositoryType.MAVEN, id, name, storage);
+ initFeatures();
+ }
+
+ public BasicRemoteRepository( Locale primaryLocale, RepositoryType type, String id, String name, RepositoryStorage storage )
+ {
+ super( primaryLocale, type, id, name, storage );
+ initFeatures();
+ }
+
+ private void initFeatures() {
+ addFeature( remoteIndexFeature );
+ addFeature( indexCreationFeature );
+ }
+
+ @Override
+ public boolean hasIndex( )
+ {
+ return true;
+ }
+
+ @Override
+ public RepositoryCapabilities getCapabilities( )
+ {
+ return CAPABILITIES;
+ }
+
+
+ public static BasicRemoteRepository newFilesystemInstance(String id, String name, Path basePath) throws IOException {
+ FileLockManager lockManager = new DefaultFileLockManager();
+ FilesystemStorage storage = new FilesystemStorage(basePath.resolve(id), lockManager);
+ return new BasicRemoteRepository(id, name, storage);
+ }
+}
+++ /dev/null
-package org.apache.archiva.repository.base.validation;
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import org.apache.archiva.repository.Repository;
-import org.apache.archiva.repository.RepositoryGroup;
-import org.apache.archiva.repository.RepositoryRegistry;
-import org.apache.archiva.repository.base.ConfigurationHandler;
-import org.apache.archiva.repository.validation.AbstractRepositoryValidator;
-import org.apache.archiva.repository.validation.RepositoryValidator;
-import org.apache.archiva.repository.validation.ValidationError;
-import org.apache.archiva.repository.validation.ValidationResponse;
-import org.apache.commons.lang3.StringUtils;
-import org.springframework.stereotype.Service;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- *
- * A validator for repository groups. All validation errors are prefixed with category 'repository_group'.
- *
- * @author Martin Stockhammer <martin_s@apache.org>
- */
-@Service( "repositoryValidator#common#group" )
-public class CommonGroupValidator extends AbstractRepositoryValidator<RepositoryGroup> implements RepositoryValidator<RepositoryGroup>
-{
-
- private static final Pattern REPO_GROUP_ID_PATTERN = Pattern.compile( "[A-Za-z0-9\\._\\-]+" );
- private final ConfigurationHandler configurationHandler;
-
- private RepositoryRegistry repositoryRegistry;
-
- public CommonGroupValidator( ConfigurationHandler configurationHandler )
- {
- this.configurationHandler = configurationHandler;
- }
-
-
- private Map<String, List<ValidationError>> appendError( Map<String, List<ValidationError>> errorMap, String errorKey, Object... parameter )
- {
- Map<String, List<ValidationError>> result;
- result = errorMap == null ? new HashMap<>( ) : errorMap;
- ValidationError error = ValidationError.ofKey( errorKey, parameter );
- List<ValidationError> errList = result.computeIfAbsent( error.getAttribute( ), k -> new ArrayList<ValidationError>( ) );
- errList.add( error );
- return result;
- }
-
- public ValidationResponse apply( RepositoryGroup repositoryGroup, boolean updateMode ) throws IllegalArgumentException
- {
- final String repoGroupId = repositoryGroup.getId( );
- Map<String, List<ValidationError>> errors = null;
- if ( StringUtils.isBlank( repoGroupId ) )
- {
- errors = appendError( errors, "repository_group.id.empty" );
- }
-
- if ( repoGroupId.length( ) > 100 )
- {
- errors = appendError( errors, "repository_group.id.max_length", repoGroupId, Integer.toString( 100 ) );
-
- }
-
- Matcher matcher = REPO_GROUP_ID_PATTERN.matcher( repoGroupId );
- if ( !matcher.matches( ) )
- {
- errors = appendError( errors, "repository_group.id.invalid_chars", "alphanumeric, '.', '-','_'" );
- }
-
- if ( repositoryGroup.getMergedIndexTTL( ) <= 0 )
- {
- errors = appendError( errors, "repository_group.merged_index_ttl.min", "0" );
- }
-
-
- if ( repositoryRegistry != null && !updateMode )
- {
- if ( repositoryRegistry.hasRepositoryGroup( repoGroupId ) )
- {
- errors = appendError( errors, "repository_group.id.group_exists", repoGroupId );
- }
- else if ( repositoryRegistry.hasManagedRepository( repoGroupId ) )
- {
- errors = appendError( errors, "repository_group.id.managed_exists" );
- }
- else if ( repositoryRegistry.hasRemoteRepository( repoGroupId ) )
- {
- errors = appendError( errors, "repository_group.id.remote_exists" );
- }
- }
- return new ValidationResponse(repositoryGroup, errors );
- }
-
-
-
-
- public ConfigurationHandler getConfigurationHandler( )
- {
- return configurationHandler;
- }
-
- public RepositoryRegistry getRepositoryRegistry( )
- {
- return repositoryRegistry;
- }
-
- @Override
- public void setRepositoryRegistry( RepositoryRegistry repositoryRegistry )
- {
- this.repositoryRegistry = repositoryRegistry;
- }
-
- @Override
- public Class<RepositoryGroup> getFlavour( )
- {
- return RepositoryGroup.class;
- }
-
- @Override
- public boolean isFlavour( Class<?> clazz )
- {
- return RepositoryGroup.class.isAssignableFrom( clazz );
- }
-}
import org.apache.archiva.repository.RepositoryException;
import org.apache.archiva.repository.RepositoryRegistry;
import org.apache.archiva.repository.RepositoryType;
+import org.apache.archiva.repository.base.group.RepositoryGroupHandler;
+import org.apache.archiva.repository.base.managed.BasicManagedRepository;
+import org.apache.archiva.repository.base.remote.BasicRemoteRepository;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
--- /dev/null
+package org.apache.archiva.repository.base.group;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.junit.jupiter.api.Test;
+
+/**
+ * @author Martin Stockhammer <martin_s@apache.org>
+ */
+class BasicManagedRepositoryValidatorTest
+{
+
+ @Test
+ void apply( )
+ {
+ }
+
+ @Test
+ void applyForUpdate( )
+ {
+ }
+
+ @Test
+ void getFlavour( )
+ {
+ }
+
+ @Test
+ void isFlavour( )
+ {
+ }
+}
\ No newline at end of file
import org.apache.archiva.repository.features.IndexCreationFeature;
import org.apache.archiva.repository.features.RemoteIndexFeature;
import org.apache.archiva.repository.features.StagingRepositoryFeature;
-import org.apache.archiva.repository.base.BasicManagedRepository;
-import org.apache.archiva.repository.base.BasicRemoteRepository;
+import org.apache.archiva.repository.base.managed.BasicManagedRepository;
+import org.apache.archiva.repository.base.remote.BasicRemoteRepository;
import org.apache.archiva.repository.base.PasswordCredentials;
import org.springframework.stereotype.Service;
import org.apache.archiva.configuration.ArchivaConfiguration;
import org.apache.archiva.consumers.InvalidRepositoryContentConsumer;
import org.apache.archiva.consumers.KnownRepositoryContentConsumer;
-import org.apache.archiva.repository.base.BasicManagedRepository;
-import org.apache.archiva.repository.base.BasicRemoteRepository;
+import org.apache.archiva.repository.base.managed.BasicManagedRepository;
+import org.apache.archiva.repository.base.remote.BasicRemoteRepository;
import org.apache.archiva.repository.ManagedRepository;
import org.apache.archiva.repository.RemoteRepository;
import org.apache.archiva.test.utils.ArchivaSpringJUnit4ClassRunner;
import org.apache.archiva.common.filelock.FileLockManager;
import org.apache.archiva.consumers.InvalidRepositoryContentConsumer;
import org.apache.archiva.consumers.KnownRepositoryContentConsumer;
-import org.apache.archiva.repository.base.BasicManagedRepository;
-import org.apache.archiva.repository.base.BasicRemoteRepository;
+import org.apache.archiva.repository.base.managed.BasicManagedRepository;
+import org.apache.archiva.repository.base.remote.BasicRemoteRepository;
import org.apache.archiva.repository.EditableManagedRepository;
import org.apache.archiva.repository.EditableRemoteRepository;
import org.apache.archiva.repository.ManagedRepository;
import org.apache.archiva.indexer.IndexCreationFailedException;
import org.apache.archiva.repository.base.ArchivaRepositoryRegistry;
import org.apache.archiva.repository.RepositoryType;
-import org.apache.archiva.repository.base.RepositoryGroupHandler;
+import org.apache.archiva.repository.base.group.RepositoryGroupHandler;
import org.apache.archiva.repository.features.IndexCreationFeature;
import org.apache.archiva.repository.features.RemoteIndexFeature;
import org.apache.archiva.repository.maven.MavenManagedRepository;
import org.apache.archiva.proxy.ProxyRegistry;
import org.apache.archiva.repository.base.ArchivaRepositoryRegistry;
import org.apache.archiva.repository.Repository;
-import org.apache.archiva.repository.base.ConfigurationHandler;
-import org.apache.archiva.repository.base.RepositoryGroupHandler;
+import org.apache.archiva.repository.base.group.RepositoryGroupHandler;
import org.apache.archiva.repository.features.IndexCreationFeature;
import org.apache.archiva.test.utils.ArchivaSpringJUnit4ClassRunner;
import org.apache.commons.lang3.SystemUtils;
import org.apache.archiva.indexer.search.SearchResultHit;
import org.apache.archiva.indexer.search.SearchResults;
import org.apache.archiva.repository.base.ArchivaRepositoryRegistry;
-import org.apache.archiva.repository.base.RepositoryGroupHandler;
+import org.apache.archiva.repository.base.group.RepositoryGroupHandler;
import org.easymock.EasyMock;
import org.junit.After;
import org.junit.Test;
import org.apache.archiva.indexer.search.SearchResults;
import org.apache.archiva.indexer.util.SearchUtil;
import org.apache.archiva.repository.base.ArchivaRepositoryRegistry;
-import org.apache.archiva.repository.base.RepositoryGroupHandler;
+import org.apache.archiva.repository.base.group.RepositoryGroupHandler;
import org.apache.archiva.test.utils.ArchivaSpringJUnit4ClassRunner;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import javax.inject.Inject;
import org.apache.archiva.policies.*;
import org.apache.archiva.proxy.model.RepositoryProxyHandler;
import org.apache.archiva.repository.*;
-import org.apache.archiva.repository.base.BasicManagedRepository;
+import org.apache.archiva.repository.base.managed.BasicManagedRepository;
import org.apache.archiva.repository.storage.StorageAsset;
import org.apache.archiva.test.utils.ArchivaSpringJUnit4ClassRunner;
import org.apache.maven.wagon.Wagon;
import org.apache.archiva.repository.ManagedRepository;
import org.apache.archiva.repository.ManagedRepositoryContent;
import org.apache.archiva.repository.RepositoryRegistry;
-import org.apache.archiva.repository.base.BasicManagedRepository;
+import org.apache.archiva.repository.base.managed.BasicManagedRepository;
import org.apache.archiva.repository.content.Artifact;
import org.apache.archiva.repository.storage.StorageAsset;
import org.apache.archiva.test.utils.ArchivaSpringJUnit4ClassRunner;
return getAppServerBaseDir().resolve("data");
}
}
+
+ @Override
+ public Registry getRegistry( )
+ {
+ return null;
+ }
}
import org.apache.archiva.configuration.RemoteRepositoryConfiguration;
import org.apache.archiva.configuration.RepositoryGroupConfiguration;
import org.apache.archiva.event.EventHandler;
-import org.apache.archiva.repository.base.BasicManagedRepository;
-import org.apache.archiva.repository.base.BasicRemoteRepository;
+import org.apache.archiva.repository.base.managed.BasicManagedRepository;
+import org.apache.archiva.repository.base.remote.BasicRemoteRepository;
import org.apache.archiva.repository.EditableManagedRepository;
import org.apache.archiva.repository.EditableRemoteRepository;
import org.apache.archiva.repository.EditableRepositoryGroup;
import org.apache.archiva.repository.RepositoryType;
import org.apache.archiva.repository.StandardCapabilities;
import org.apache.archiva.repository.UnsupportedFeatureException;
-import org.apache.archiva.repository.base.AbstractManagedRepository;
+import org.apache.archiva.repository.base.managed.AbstractManagedRepository;
import org.apache.archiva.repository.features.ArtifactCleanupFeature;
import org.apache.archiva.repository.features.IndexCreationFeature;
import org.apache.archiva.repository.features.RepositoryFeature;
import org.apache.archiva.repository.RepositoryType;
import org.apache.archiva.repository.StandardCapabilities;
import org.apache.archiva.repository.UnsupportedFeatureException;
-import org.apache.archiva.repository.base.AbstractRemoteRepository;
+import org.apache.archiva.repository.base.remote.AbstractRemoteRepository;
import org.apache.archiva.repository.features.IndexCreationFeature;
import org.apache.archiva.repository.features.RemoteIndexFeature;
import org.apache.archiva.repository.features.RepositoryFeature;
import org.apache.archiva.repository.RepositoryCapabilities;
import org.apache.archiva.repository.RepositoryType;
import org.apache.archiva.repository.StandardCapabilities;
-import org.apache.archiva.repository.base.AbstractRepositoryGroup;
+import org.apache.archiva.repository.base.group.AbstractRepositoryGroup;
import org.apache.archiva.repository.features.IndexCreationFeature;
import org.apache.archiva.repository.storage.fs.FilesystemStorage;
import org.slf4j.Logger;
import org.apache.archiva.repository.RepositoryProvider;
import org.apache.archiva.repository.RepositoryType;
import org.apache.archiva.repository.UnsupportedURIException;
-import org.apache.archiva.repository.base.BasicManagedRepository;
+import org.apache.archiva.repository.base.managed.BasicManagedRepository;
import org.apache.archiva.repository.base.PasswordCredentials;
import org.apache.archiva.repository.event.RepositoryEvent;
import org.apache.archiva.repository.features.ArtifactCleanupFeature;
}
}
-
+ @Override
+ public Registry getRegistry( )
+ {
+ return null;
+ }
}
* under the License.
*/
+import org.apache.archiva.components.registry.Registry;
import org.apache.archiva.components.registry.RegistryException;
import org.apache.archiva.components.registry.RegistryListener;
import org.apache.archiva.configuration.ArchivaConfiguration;
}
}
+
+ @Override
+ public Registry getRegistry( )
+ {
+ return null;
+ }
}
package org.apache.archiva.repository.maven.mock.configuration;
+import org.apache.archiva.components.registry.Registry;
import org.apache.archiva.components.registry.RegistryException;
import org.apache.archiva.components.registry.RegistryListener;
import org.apache.archiva.configuration.ArchivaConfiguration;
return getAppServerBaseDir().resolve("data");
}
}
+
+ @Override
+ public Registry getRegistry( )
+ {
+ return null;
+ }
}
import org.apache.archiva.indexer.ArchivaIndexingContext;
import org.apache.archiva.indexer.UnsupportedBaseContextException;
import org.apache.archiva.repository.base.ArchivaRepositoryRegistry;
-import org.apache.archiva.repository.base.BasicManagedRepository;
+import org.apache.archiva.repository.base.managed.BasicManagedRepository;
import org.apache.archiva.repository.ManagedRepository;
import org.apache.archiva.repository.ReleaseScheme;
-import org.apache.archiva.repository.base.RepositoryGroupHandler;
+import org.apache.archiva.repository.base.group.RepositoryGroupHandler;
import org.apache.archiva.repository.storage.StorageAsset;
import org.apache.archiva.repository.features.IndexCreationFeature;
import org.apache.archiva.scheduler.indexing.ArtifactIndexingTask;
import org.apache.archiva.components.taskqueue.execution.TaskExecutor;
import org.apache.archiva.repository.ManagedRepository;
import org.apache.archiva.repository.RepositoryRegistry;
-import org.apache.archiva.repository.base.RepositoryGroupHandler;
+import org.apache.archiva.repository.base.group.RepositoryGroupHandler;
import org.apache.archiva.scheduler.repository.model.RepositoryTask;
import org.apache.archiva.test.utils.ArchivaSpringJUnit4ClassRunner;
import org.junit.After;
import org.apache.archiva.redback.users.User;
import org.apache.archiva.redback.users.UserManagerException;
import org.apache.archiva.redback.users.UserNotFoundException;
-import org.apache.archiva.repository.base.RepositoryGroupHandler;
+import org.apache.archiva.repository.base.group.RepositoryGroupHandler;
import org.apache.archiva.repository.content.BaseRepositoryContentLayout;
import org.apache.archiva.repository.content.ContentNotFoundException;
import org.apache.archiva.repository.content.LayoutException;
* under the License.
*/
-import org.apache.archiva.components.registry.RegistryException;
import org.apache.archiva.components.rest.model.PagedResult;
import org.apache.archiva.components.rest.util.QueryHelper;
-import org.apache.archiva.configuration.Configuration;
-import org.apache.archiva.configuration.IndeterminateConfigurationException;
import org.apache.archiva.configuration.RepositoryGroupConfiguration;
-import org.apache.archiva.repository.CheckedResult;
+import org.apache.archiva.repository.validation.CheckedResult;
import org.apache.archiva.repository.EditableRepositoryGroup;
import org.apache.archiva.repository.RepositoryException;
import org.apache.archiva.repository.RepositoryRegistry;
import org.apache.archiva.repository.base.ConfigurationHandler;
import org.apache.archiva.repository.validation.ValidationError;
-import org.apache.archiva.repository.validation.ValidationResponse;
import org.apache.archiva.rest.api.model.v2.MergeConfiguration;
import org.apache.archiva.rest.api.model.v2.RepositoryGroup;
import org.apache.archiva.rest.api.services.v2.ArchivaRestServiceException;
import org.apache.archiva.metadata.repository.RepositorySession;
import org.apache.archiva.metadata.repository.RepositorySessionFactory;
import org.apache.archiva.repository.base.ArchivaRepositoryRegistry;
-import org.apache.archiva.repository.base.BasicManagedRepository;
+import org.apache.archiva.repository.base.managed.BasicManagedRepository;
import org.apache.archiva.repository.Repository;
import org.apache.archiva.repository.RepositoryRegistry;
import org.apache.archiva.repository.storage.fs.FilesystemStorage;
import junit.framework.TestCase;
import org.apache.archiva.common.filelock.DefaultFileLockManager;
import org.apache.archiva.configuration.ArchivaConfiguration;
-import org.apache.archiva.repository.base.BasicManagedRepository;
+import org.apache.archiva.repository.base.managed.BasicManagedRepository;
import org.apache.archiva.repository.RepositoryRegistry;
import org.apache.archiva.repository.storage.fs.FilesystemStorage;
import org.apache.archiva.test.utils.ArchivaSpringJUnit4ClassRunner;
import org.apache.archiva.repository.base.ArchivaRepositoryRegistry;
import org.apache.archiva.repository.ManagedRepository;
import org.apache.archiva.repository.RepositoryType;
-import org.apache.archiva.repository.base.RepositoryGroupHandler;
+import org.apache.archiva.repository.base.group.RepositoryGroupHandler;
import org.apache.archiva.test.utils.ArchivaSpringJUnit4ClassRunner;
import org.apache.archiva.webdav.httpunit.MkColMethodWebRequest;
import org.apache.commons.io.FileUtils;
import org.apache.archiva.configuration.RepositoryGroupConfiguration;
import org.apache.archiva.metadata.repository.storage.RepositoryPathTranslator;
import org.apache.archiva.repository.ManagedRepositoryContent;
-import org.apache.archiva.repository.base.RepositoryGroupHandler;
+import org.apache.archiva.repository.base.group.RepositoryGroupHandler;
import org.apache.archiva.repository.maven.content.MavenContentHelper;
import org.apache.archiva.repository.maven.metadata.storage.ArtifactMappingProvider;
import org.apache.archiva.proxy.ProxyRegistry;
import org.apache.archiva.redback.users.memory.SimpleUser;
import org.apache.archiva.repository.RepositoryRegistry;
import org.apache.archiva.metadata.audit.TestAuditListener;
-import org.apache.archiva.repository.base.RepositoryGroupHandler;
+import org.apache.archiva.repository.base.group.RepositoryGroupHandler;
import org.apache.archiva.security.ServletAuthenticator;
import org.apache.archiva.security.common.ArchivaRoleConstants;
import org.apache.archiva.test.utils.ArchivaSpringJUnit4ClassRunner;
import org.apache.archiva.metadata.repository.RepositorySession;
import org.apache.archiva.metadata.repository.RepositorySessionFactory;
import org.apache.archiva.metadata.repository.storage.RepositoryPathTranslator;
-import org.apache.archiva.repository.base.BasicManagedRepository;
+import org.apache.archiva.repository.base.managed.BasicManagedRepository;
import org.apache.archiva.test.utils.ArchivaSpringJUnit4ClassRunner;
import org.junit.Before;
import org.junit.Test;