From 152cf7cd787bac253dd7a418d2bc9125c442e12f Mon Sep 17 00:00:00 2001 From: Olivier Lamy Date: Mon, 10 Jun 2013 10:59:20 +0000 Subject: [PATCH] all tests pass so move out metadata-store-cassandra from sandbox git-svn-id: https://svn.apache.org/repos/asf/archiva/trunk@1491410 13f79535-47bb-0310-9956-ffa450edef68 --- .../plugins/metadata-store-cassandra/pom.xml | 305 +++ .../CassandraEntityManagerFactory.java | 31 + .../CassandraMetadataRepository.java | 1889 +++++++++++++++++ .../CassandraRepositorySessionFactory.java | 87 + .../DefaultCassandraEntityManagerFactory.java | 95 + .../model/ArtifactMetadataModel.java | 331 +++ .../cassandra/model/MetadataFacetModel.java | 229 ++ .../repository/cassandra/model/Namespace.java | 190 ++ .../repository/cassandra/model/Project.java | 163 ++ .../model/ProjectVersionMetadataModel.java | 354 +++ .../cassandra/model/Repository.java | 136 ++ .../resources/META-INF/spring-context.xml | 33 + .../META-INF/spring-context.xml | 25 + .../CassandraMetadataRepositoryTest.java | 113 + .../cassandra/RepositoriesNamespaceTest.java | 133 ++ .../src/test/resources/log4j2-test.xml | 44 + 16 files changed, 4158 insertions(+) create mode 100644 archiva-modules/plugins/metadata-store-cassandra/pom.xml create mode 100644 archiva-modules/plugins/metadata-store-cassandra/src/main/java/org/apache/archiva/metadata/repository/cassandra/CassandraEntityManagerFactory.java create mode 100644 archiva-modules/plugins/metadata-store-cassandra/src/main/java/org/apache/archiva/metadata/repository/cassandra/CassandraMetadataRepository.java create mode 100644 archiva-modules/plugins/metadata-store-cassandra/src/main/java/org/apache/archiva/metadata/repository/cassandra/CassandraRepositorySessionFactory.java create mode 100644 archiva-modules/plugins/metadata-store-cassandra/src/main/java/org/apache/archiva/metadata/repository/cassandra/DefaultCassandraEntityManagerFactory.java create mode 100644 archiva-modules/plugins/metadata-store-cassandra/src/main/java/org/apache/archiva/metadata/repository/cassandra/model/ArtifactMetadataModel.java create mode 100644 archiva-modules/plugins/metadata-store-cassandra/src/main/java/org/apache/archiva/metadata/repository/cassandra/model/MetadataFacetModel.java create mode 100644 archiva-modules/plugins/metadata-store-cassandra/src/main/java/org/apache/archiva/metadata/repository/cassandra/model/Namespace.java create mode 100644 archiva-modules/plugins/metadata-store-cassandra/src/main/java/org/apache/archiva/metadata/repository/cassandra/model/Project.java create mode 100644 archiva-modules/plugins/metadata-store-cassandra/src/main/java/org/apache/archiva/metadata/repository/cassandra/model/ProjectVersionMetadataModel.java create mode 100644 archiva-modules/plugins/metadata-store-cassandra/src/main/java/org/apache/archiva/metadata/repository/cassandra/model/Repository.java create mode 100644 archiva-modules/plugins/metadata-store-cassandra/src/main/resources/META-INF/spring-context.xml create mode 100644 archiva-modules/plugins/metadata-store-cassandra/src/test/filtered-resources/META-INF/spring-context.xml create mode 100644 archiva-modules/plugins/metadata-store-cassandra/src/test/java/org/apache/archiva/metadata/repository/cassandra/CassandraMetadataRepositoryTest.java create mode 100644 archiva-modules/plugins/metadata-store-cassandra/src/test/java/org/apache/archiva/metadata/repository/cassandra/RepositoriesNamespaceTest.java create mode 100644 archiva-modules/plugins/metadata-store-cassandra/src/test/resources/log4j2-test.xml diff --git a/archiva-modules/plugins/metadata-store-cassandra/pom.xml b/archiva-modules/plugins/metadata-store-cassandra/pom.xml new file mode 100644 index 000000000..80028d529 --- /dev/null +++ b/archiva-modules/plugins/metadata-store-cassandra/pom.xml @@ -0,0 +1,305 @@ + + + + + 4.0.0 + + plugins + org.apache.archiva + 1.4.0-SNAPSHOT + + metadata-store-cassandra + bundle + Archiva Core Plugins :: Cassandra JPA Storage for Metadata + + + 1.2.5 + + + + + commons-lang + commons-lang + + + org.apache.archiva + metadata-repository-api + + + org.apache.archiva + metadata-repository-api + tests + test + + + org.apache.archiva + archiva-test-utils + ${project.version} + test + + + org.slf4j + slf4j-simple + + + + + + net.sf.beanlib + beanlib + + + cglib + cglib + + + aopalliance + aopalliance + + + log4j + log4j + + + + + + org.apache.geronimo.specs + geronimo-jpa_2.0_spec + + + + com.netflix.astyanax + astyanax-entity-mapper + 1.56.37 + + + stax + stax-api + + + log4j + log4j + + + org.slf4j + slf4j-log4j12 + + + org.apache.cassandra + cassandra-thrift + + + javax.persistence + persistence-api + + + org.jboss.netty + netty + + + + + + com.netflix.astyanax + astyanax-core + 1.56.37 + + + + com.netflix.astyanax + astyanax-thrift + 1.56.37 + + + org.apache.cassandra + cassandra-thrift + + + + + + org.apache.cassandra + cassandra-all + ${cassandraVersion} + + + log4j + log4j + + + org.slf4j + slf4j-log4j12 + + + org.mortbay.jetty + jetty + + + + + + org.apache.logging.log4j + log4j-jcl + + + org.springframework + spring-test + test + + + org.easytesting + fest-assert-core + test + + + org.apache.logging.log4j + log4j-slf4j-impl + test + + + org.apache.logging.log4j + log4j-1.2-api + ${log4j.version} + test + + + com.lmax + disruptor + test + + + org.codehaus.jackson + jackson-core-asl + test + + + org.codehaus.jackson + jackson-mapper-asl + test + + + + + + + src/test/filtered-resources + true + + + + + org.apache.felix + maven-bundle-plugin + + + org.apache.archiva.metadata.repository.cassandra + ${project.version} + + org.apache.archiva.metadata.repository.cassandra;version=${project.version};-split-package:=merge-first + + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + reserve-ports + process-test-resources + + reserve-network-port + + + + cassandraPort + + + + + + + + + org.codehaus.mojo + cassandra-maven-plugin + 1.2.1-1 + + + start-cassandra + test-compile + + start + + + ${cassandraPort} + + + + stop-cassandra + test + + stop + + + + + + org.apache.cassandra + cassandra-all + ${cassandraVersion} + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + ${cassandraPort} + + + + + + + + + + archiva.snapshots + https://archiva-repository.apache.org/archiva/repository/snapshots/ + + false + + + true + + + + + diff --git a/archiva-modules/plugins/metadata-store-cassandra/src/main/java/org/apache/archiva/metadata/repository/cassandra/CassandraEntityManagerFactory.java b/archiva-modules/plugins/metadata-store-cassandra/src/main/java/org/apache/archiva/metadata/repository/cassandra/CassandraEntityManagerFactory.java new file mode 100644 index 000000000..da5a8b613 --- /dev/null +++ b/archiva-modules/plugins/metadata-store-cassandra/src/main/java/org/apache/archiva/metadata/repository/cassandra/CassandraEntityManagerFactory.java @@ -0,0 +1,31 @@ +package org.apache.archiva.metadata.repository.cassandra; + +/* + * 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 com.netflix.astyanax.Keyspace; + +/** + * @author Olivier Lamy + */ +public interface CassandraEntityManagerFactory +{ + Keyspace getKeyspace(); + +} diff --git a/archiva-modules/plugins/metadata-store-cassandra/src/main/java/org/apache/archiva/metadata/repository/cassandra/CassandraMetadataRepository.java b/archiva-modules/plugins/metadata-store-cassandra/src/main/java/org/apache/archiva/metadata/repository/cassandra/CassandraMetadataRepository.java new file mode 100644 index 000000000..33d73783a --- /dev/null +++ b/archiva-modules/plugins/metadata-store-cassandra/src/main/java/org/apache/archiva/metadata/repository/cassandra/CassandraMetadataRepository.java @@ -0,0 +1,1889 @@ +package org.apache.archiva.metadata.repository.cassandra; + +/* + * 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 com.google.common.base.Function; +import com.google.common.base.Predicate; +import com.google.common.collect.Iterables; +import com.netflix.astyanax.Keyspace; +import com.netflix.astyanax.connectionpool.exceptions.ConnectionException; +import com.netflix.astyanax.connectionpool.exceptions.NotFoundException; +import com.netflix.astyanax.entitystore.DefaultEntityManager; +import com.netflix.astyanax.entitystore.EntityManager; +import net.sf.beanlib.provider.replicator.BeanReplicator; +import org.apache.archiva.configuration.ArchivaConfiguration; +import org.apache.archiva.metadata.model.ArtifactMetadata; +import org.apache.archiva.metadata.model.FacetedMetadata; +import org.apache.archiva.metadata.model.MetadataFacet; +import org.apache.archiva.metadata.model.MetadataFacetFactory; +import org.apache.archiva.metadata.model.ProjectMetadata; +import org.apache.archiva.metadata.model.ProjectVersionMetadata; +import org.apache.archiva.metadata.model.ProjectVersionReference; +import org.apache.archiva.metadata.repository.MetadataRepository; +import org.apache.archiva.metadata.repository.MetadataRepositoryException; +import org.apache.archiva.metadata.repository.MetadataResolutionException; +import org.apache.archiva.metadata.repository.cassandra.model.ArtifactMetadataModel; +import org.apache.archiva.metadata.repository.cassandra.model.MetadataFacetModel; +import org.apache.archiva.metadata.repository.cassandra.model.Namespace; +import org.apache.archiva.metadata.repository.cassandra.model.Project; +import org.apache.archiva.metadata.repository.cassandra.model.ProjectVersionMetadataModel; +import org.apache.archiva.metadata.repository.cassandra.model.Repository; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.persistence.PersistenceException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; + +/** + * @author Olivier Lamy + */ +public class CassandraMetadataRepository + implements MetadataRepository +{ + + private Logger logger = LoggerFactory.getLogger( getClass() ); + + private ArchivaConfiguration configuration; + + private final Map metadataFacetFactories; + + private Keyspace keyspace; + + private EntityManager repositoryEntityManager; + + private EntityManager namespaceEntityManager; + + private EntityManager projectEntityManager; + + private EntityManager artifactMetadataModelEntityManager; + + private EntityManager metadataFacetModelEntityManager; + + private EntityManager projectVersionMetadataModelEntityManager; + + public CassandraMetadataRepository( Map metadataFacetFactories, + ArchivaConfiguration configuration, Keyspace keyspace ) + { + this.metadataFacetFactories = metadataFacetFactories; + this.configuration = configuration; + + this.keyspace = keyspace; + + try + { + Properties properties = keyspace.getKeyspaceProperties(); + logger.info( "keyspace properties: {}", properties ); + } + catch ( ConnectionException e ) + { + // FIXME better logging ! + logger.warn( e.getMessage(), e ); + } + + try + { + repositoryEntityManager = + new DefaultEntityManager.Builder().withEntityType( Repository.class ).withKeyspace( + keyspace ).build(); + boolean exists = columnFamilyExists( "repository" ); + // TODO very basic test we must test model change too + if ( !exists ) + { + repositoryEntityManager.createStorage( null ); + } + + namespaceEntityManager = + new DefaultEntityManager.Builder().withEntityType( Namespace.class ).withKeyspace( + keyspace ).build(); + + exists = columnFamilyExists( "namespace" ); + if ( !exists ) + { + namespaceEntityManager.createStorage( null ); + } + + projectEntityManager = + new DefaultEntityManager.Builder().withEntityType( Project.class ).withKeyspace( + keyspace ).build(); + + exists = columnFamilyExists( "project" ); + if ( !exists ) + { + projectEntityManager.createStorage( null ); + } + + artifactMetadataModelEntityManager = + new DefaultEntityManager.Builder().withEntityType( + ArtifactMetadataModel.class ).withKeyspace( keyspace ).build(); + + exists = columnFamilyExists( "artifactmetadatamodel" ); + if ( !exists ) + { + artifactMetadataModelEntityManager.createStorage( null ); + } + + metadataFacetModelEntityManager = + new DefaultEntityManager.Builder().withEntityType( + MetadataFacetModel.class ).withKeyspace( keyspace ).build(); + + exists = columnFamilyExists( "metadatafacetmodel" ); + if ( !exists ) + { + metadataFacetModelEntityManager.createStorage( null ); + } + + projectVersionMetadataModelEntityManager = + new DefaultEntityManager.Builder().withEntityType( + ProjectVersionMetadataModel.class ).withKeyspace( keyspace ).build(); + + exists = columnFamilyExists( "projectversionmetadatamodel" ); + if ( !exists ) + { + projectVersionMetadataModelEntityManager.createStorage( null ); + } + + } + catch ( PersistenceException e ) + { + // FIXME report exception + logger.error( e.getMessage(), e ); + } + catch ( ConnectionException e ) + { + // FIXME report exception + logger.error( e.getMessage(), e ); + } + } + + private boolean columnFamilyExists( String columnFamilyName ) + throws ConnectionException + { + try + { + Properties properties = keyspace.getColumnFamilyProperties( columnFamilyName ); + logger.debug( "getColumnFamilyProperties for {}: {}", columnFamilyName, properties ); + return true; + } + catch ( NotFoundException e ) + { + return false; + } + } + + public EntityManager getRepositoryEntityManager() + { + return repositoryEntityManager; + } + + public EntityManager getNamespaceEntityManager() + { + return namespaceEntityManager; + } + + public void setRepositoryEntityManager( EntityManager repositoryEntityManager ) + { + this.repositoryEntityManager = repositoryEntityManager; + } + + public void setNamespaceEntityManager( EntityManager namespaceEntityManager ) + { + this.namespaceEntityManager = namespaceEntityManager; + } + + public EntityManager getProjectEntityManager() + { + return projectEntityManager; + } + + public void setProjectEntityManager( EntityManager projectEntityManager ) + { + this.projectEntityManager = projectEntityManager; + } + + public EntityManager getArtifactMetadataModelEntityManager() + { + return artifactMetadataModelEntityManager; + } + + public void setArtifactMetadataModelEntityManager( + EntityManager artifactMetadataModelEntityManager ) + { + this.artifactMetadataModelEntityManager = artifactMetadataModelEntityManager; + } + + public EntityManager getMetadataFacetModelEntityManager() + { + return metadataFacetModelEntityManager; + } + + public void setMetadataFacetModelEntityManager( + EntityManager metadataFacetModelEntityManager ) + { + this.metadataFacetModelEntityManager = metadataFacetModelEntityManager; + } + + public EntityManager getProjectVersionMetadataModelEntityManager() + { + return projectVersionMetadataModelEntityManager; + } + + public void setProjectVersionMetadataModelEntityManager( + EntityManager projectVersionMetadataModelEntityManager ) + { + this.projectVersionMetadataModelEntityManager = projectVersionMetadataModelEntityManager; + } + + @Override + public void updateNamespace( String repositoryId, String namespaceId ) + throws MetadataRepositoryException + { + updateOrAddNamespace( repositoryId, namespaceId ); + + } + + public Namespace updateOrAddNamespace( String repositoryId, String namespaceId ) + throws MetadataRepositoryException + { + try + { + Repository repository = this.repositoryEntityManager.get( repositoryId ); + + if ( repository == null ) + { + repository = new Repository( repositoryId ); + + Namespace namespace = new Namespace( namespaceId, repository ); + this.repositoryEntityManager.put( repository ); + + this.namespaceEntityManager.put( namespace ); + } + // FIXME add a Namespace id builder + Namespace namespace = namespaceEntityManager.get( + new Namespace.KeyBuilder().withNamespace( namespaceId ).withRepositoryId( repositoryId ).build() ); + if ( namespace == null ) + { + namespace = new Namespace( namespaceId, repository ); + namespaceEntityManager.put( namespace ); + } + return namespace; + } + catch ( PersistenceException e ) + { + throw new MetadataRepositoryException( e.getMessage(), e ); + } + + } + + + @Override + public void removeNamespace( String repositoryId, String namespaceId ) + throws MetadataRepositoryException + { + try + { + Namespace namespace = namespaceEntityManager.get( + new Namespace.KeyBuilder().withNamespace( namespaceId ).withRepositoryId( repositoryId ).build() ); + if ( namespace != null ) + { + namespaceEntityManager.remove( namespace ); + } + } + catch ( PersistenceException e ) + { + throw new MetadataRepositoryException( e.getMessage(), e ); + } + } + + + @Override + public void removeRepository( final String repositoryId ) + throws MetadataRepositoryException + { + try + { + final List artifactMetadataModels = new ArrayList(); + + // remove data related to the repository + this.artifactMetadataModelEntityManager.visitAll( new Function() + { + @Override + public Boolean apply( ArtifactMetadataModel artifactMetadataModel ) + { + if ( artifactMetadataModel != null ) + { + if ( StringUtils.equals( artifactMetadataModel.getRepositoryId(), repositoryId ) ) + { + artifactMetadataModels.add( artifactMetadataModel ); + } + } + return Boolean.TRUE; + } + } ); + + artifactMetadataModelEntityManager.remove( artifactMetadataModels ); + + final List namespaces = new ArrayList(); + + namespaceEntityManager.visitAll( new Function() + { + @Override + public Boolean apply( Namespace namespace ) + { + if ( namespace != null ) + { + if ( StringUtils.equals( namespace.getRepository().getId(), repositoryId ) ) + { + namespaces.add( namespace ); + } + } + return Boolean.TRUE; + } + } ); + + namespaceEntityManager.remove( namespaces ); + + final List projects = new ArrayList(); + projectEntityManager.visitAll( new Function() + { + @Override + public Boolean apply( Project project ) + { + if ( project != null ) + { + if ( StringUtils.equals( project.getNamespace().getRepository().getId(), repositoryId ) ) + { + projects.add( project ); + } + } + return Boolean.TRUE; + } + } ); + + projectEntityManager.remove( projects ); + + // TODO cleanup or not + //final List metadataFacetModels = new ArrayList( ); + //metadataFacetModelEntityManager.visitAll( new Function() + + final List projectVersionMetadataModels = + new ArrayList(); + + projectVersionMetadataModelEntityManager.visitAll( new Function() + { + @Override + public Boolean apply( ProjectVersionMetadataModel projectVersionMetadataModel ) + { + if ( projectVersionMetadataModel != null ) + { + if ( StringUtils.equals( projectVersionMetadataModel.getNamespace().getRepository().getId(), + repositoryId ) ) + { + projectVersionMetadataModels.add( projectVersionMetadataModel ); + } + } + return Boolean.TRUE; + } + } ); + + projectVersionMetadataModelEntityManager.remove( projectVersionMetadataModels ); + + Repository repository = repositoryEntityManager.get( repositoryId ); + if ( repository != null ) + { + repositoryEntityManager.remove( repository ); + } + + } + catch ( PersistenceException e ) + { + throw new MetadataRepositoryException( e.getMessage(), e ); + } + } + + @Override + public Collection getRepositories() + throws MetadataRepositoryException + { + try + { + logger.debug( "getRepositories" ); + + List repositories = repositoryEntityManager.getAll(); + if ( repositories == null ) + { + return Collections.emptyList(); + } + List repoIds = new ArrayList( repositories.size() ); + for ( Repository repository : repositories ) + { + repoIds.add( repository.getName() ); + } + logger.debug( "getRepositories found: {}", repoIds ); + return repoIds; + } + catch ( PersistenceException e ) + { + throw new MetadataRepositoryException( e.getMessage(), e ); + } + + } + + + @Override + public Collection getRootNamespaces( final String repoId ) + throws MetadataResolutionException + { + try + { + final Set namespaces = new HashSet(); + + namespaceEntityManager.visitAll( new Function() + { + // @Nullable add dependency ? + @Override + public Boolean apply( Namespace namespace ) + { + if ( namespace != null && namespace.getRepository() != null && StringUtils.equalsIgnoreCase( repoId, + namespace.getRepository().getId() ) ) + { + String name = namespace.getName(); + if ( StringUtils.isNotEmpty( name ) ) + { + namespaces.add( StringUtils.substringBefore( name, "." ) ); + } + } + return Boolean.TRUE; + } + } ); + + return namespaces; + } + catch ( PersistenceException e ) + { + throw new MetadataResolutionException( e.getMessage(), e ); + } + } + + @Override + public Collection getNamespaces( final String repoId, final String namespaceId ) + throws MetadataResolutionException + { + try + { + final Set namespaces = new HashSet(); + + namespaceEntityManager.visitAll( new Function() + { + // @Nullable add dependency ? + @Override + public Boolean apply( Namespace namespace ) + { + if ( namespace != null && namespace.getRepository() != null && StringUtils.equalsIgnoreCase( repoId, + namespace.getRepository().getId() ) ) + { + String currentNamespace = namespace.getName(); + // we only return childs + if ( StringUtils.startsWith( currentNamespace, namespaceId ) && ( + StringUtils.length( currentNamespace ) > StringUtils.length( namespaceId ) ) ) + { + // store after namespaceId '.' but before next '.' + // call org namespace org.apache.maven.shared -> stored apache + + String calledNamespace = + StringUtils.endsWith( namespaceId, "." ) ? namespaceId : namespaceId + "."; + String storedNamespace = StringUtils.substringAfter( currentNamespace, calledNamespace ); + + storedNamespace = StringUtils.substringBefore( storedNamespace, "." ); + + namespaces.add( storedNamespace ); + } + } + return Boolean.TRUE; + } + } ); + + return namespaces; + } + catch ( PersistenceException e ) + { + throw new MetadataResolutionException( e.getMessage(), e ); + } + + } + + public List getNamespaces( final String repoId ) + throws MetadataResolutionException + { + try + { + logger.debug( "getNamespaces for repository '{}'", repoId ); + //TypedQuery typedQuery = + // entityManager.createQuery( "select n from Namespace n where n.repository_id=:id", Namespace.class ); + + //List namespaces = typedQuery.setParameter( "id", repoId ).getResultList(); + + Repository repository = repositoryEntityManager.get( repoId ); + + if ( repository == null ) + { + return Collections.emptyList(); + } + + // FIXME find correct cql query + //String query = "select * from namespace where repository.id = '" + repoId + "';"; + + //List namespaces = namespaceEntityManager.find( query ); + + final Set namespaces = new HashSet(); + + namespaceEntityManager.visitAll( new Function() + { + // @Nullable add dependency ? + @Override + public Boolean apply( Namespace namespace ) + { + if ( namespace != null && namespace.getRepository() != null && StringUtils.equalsIgnoreCase( repoId, + namespace.getRepository().getId() ) ) + { + namespaces.add( namespace ); + } + return Boolean.TRUE; + } + } ); + + repository.setNamespaces( new ArrayList( namespaces ) ); + + if ( repository == null || repository.getNamespaces().isEmpty() ) + { + return Collections.emptyList(); + } + List namespaceIds = new ArrayList( repository.getNamespaces().size() ); + + for ( Namespace n : repository.getNamespaces() ) + { + namespaceIds.add( n.getName() ); + } + + logger.debug( "getNamespaces for repository '{}' found {}", repoId, namespaceIds.size() ); + return namespaceIds; + } + catch ( PersistenceException e ) + { + throw new MetadataResolutionException( e.getMessage(), e ); + } + } + + + @Override + public void updateProject( String repositoryId, ProjectMetadata projectMetadata ) + throws MetadataRepositoryException + { + + // project exists ? if yes return + String projectKey = new Project.KeyBuilder().withProjectId( projectMetadata.getId() ).withNamespace( + new Namespace( projectMetadata.getNamespace(), new Repository( repositoryId ) ) ).build(); + + Project project = projectEntityManager.get( projectKey ); + if ( project != null ) + { + return; + } + + String namespaceKey = new Namespace.KeyBuilder().withRepositoryId( repositoryId ).withNamespace( + projectMetadata.getNamespace() ).build(); + Namespace namespace = namespaceEntityManager.get( namespaceKey ); + if ( namespace == null ) + { + namespace = updateOrAddNamespace( repositoryId, projectMetadata.getNamespace() ); + } + + project = new Project( projectKey, projectMetadata.getId(), namespace ); + + try + { + projectEntityManager.put( project ); + } + catch ( PersistenceException e ) + { + throw new MetadataRepositoryException( e.getMessage(), e ); + } + + } + + @Override + public void removeProject( final String repositoryId, final String namespaceId, final String projectId ) + throws MetadataRepositoryException + { + + // cleanup ArtifactMetadataModel + final List artifactMetadataModels = new ArrayList(); + + artifactMetadataModelEntityManager.visitAll( new Function() + { + @Override + public Boolean apply( ArtifactMetadataModel artifactMetadataModel ) + { + if ( artifactMetadataModel != null ) + { + if ( StringUtils.equals( artifactMetadataModel.getRepositoryId(), repositoryId ) + && StringUtils.equals( artifactMetadataModel.getNamespace(), namespaceId ) + && StringUtils.equals( artifactMetadataModel.getProject(), projectId ) ) + { + artifactMetadataModels.add( artifactMetadataModel ); + } + } + return Boolean.TRUE; + } + } ); + + artifactMetadataModelEntityManager.remove( artifactMetadataModels ); + + Namespace namespace = new Namespace( namespaceId, new Repository( repositoryId ) ); + + final List projectVersionMetadataModels = + new ArrayList(); + + projectVersionMetadataModelEntityManager.visitAll( new Function() + { + @Override + public Boolean apply( ProjectVersionMetadataModel projectVersionMetadataModel ) + { + if ( projectVersionMetadataModel != null ) + { + if ( StringUtils.equals( repositoryId, + projectVersionMetadataModel.getNamespace().getRepository().getName() ) + && StringUtils.equals( namespaceId, projectVersionMetadataModel.getNamespace().getName() ) + && StringUtils.equals( projectId, projectVersionMetadataModel.getProjectId() ) ) + { + projectVersionMetadataModels.add( projectVersionMetadataModel ); + } + } + return Boolean.TRUE; + } + } ); + + if ( !projectVersionMetadataModels.isEmpty() ) + { + projectVersionMetadataModelEntityManager.remove( projectVersionMetadataModels ); + } + + String key = new Project.KeyBuilder().withNamespace( namespace ).withProjectId( projectId ).build(); + + Project project = projectEntityManager.get( key ); + if ( project == null ) + { + logger.debug( "removeProject notfound" ); + return; + } + logger.debug( "removeProject {}", project ); + + projectEntityManager.remove( project ); + } + + @Override + public Collection getProjectVersions( final String repoId, final String namespace, final String projectId ) + throws MetadataResolutionException + { + final Set versions = new HashSet(); + projectVersionMetadataModelEntityManager.visitAll( new Function() + { + @Override + public Boolean apply( ProjectVersionMetadataModel projectVersionMetadataModel ) + { + if ( projectVersionMetadataModel != null ) + { + if ( StringUtils.equals( repoId, + projectVersionMetadataModel.getNamespace().getRepository().getName() ) + && StringUtils.startsWith( projectVersionMetadataModel.getNamespace().getName(), namespace ) + && StringUtils.equals( projectId, projectVersionMetadataModel.getProjectId() ) ) + { + versions.add( projectVersionMetadataModel.getId() ); + } + } + return Boolean.TRUE; + } + } ); + // FIXME use cql query + artifactMetadataModelEntityManager.visitAll( new Function() + { + @Override + public Boolean apply( ArtifactMetadataModel artifactMetadataModel ) + { + if ( artifactMetadataModel != null ) + { + if ( StringUtils.equals( repoId, artifactMetadataModel.getRepositoryId() ) && StringUtils.equals( + namespace, artifactMetadataModel.getNamespace() ) && StringUtils.equals( projectId, + artifactMetadataModel.getProject() ) ) + { + versions.add( artifactMetadataModel.getProjectVersion() ); + } + } + return Boolean.TRUE; + } + } ); + + return versions; + } + + @Override + public void updateArtifact( String repositoryId, String namespaceId, String projectId, String projectVersion, + ArtifactMetadata artifactMeta ) + throws MetadataRepositoryException + { + String namespaceKey = + new Namespace.KeyBuilder().withRepositoryId( repositoryId ).withNamespace( namespaceId ).build(); + // create the namespace if not exists + Namespace namespace = namespaceEntityManager.get( namespaceKey ); + if ( namespace == null ) + { + namespace = updateOrAddNamespace( repositoryId, namespaceId ); + } + + // create the project if not exist + String projectKey = new Project.KeyBuilder().withNamespace( namespace ).withProjectId( projectId ).build(); + + Project project = projectEntityManager.get( projectKey ); + if ( project == null ) + { + project = new Project( projectKey, projectId, namespace ); + try + { + projectEntityManager.put( project ); + } + catch ( PersistenceException e ) + { + throw new MetadataRepositoryException( e.getMessage(), e ); + } + } + + String key = new ArtifactMetadataModel.KeyBuilder().withNamespace( namespace ).withProject( projectId ).withId( + artifactMeta.getId() ).withProjectVersion( projectVersion ).build(); + + ArtifactMetadataModel artifactMetadataModel = artifactMetadataModelEntityManager.get( key ); + if ( artifactMetadataModel == null ) + { + artifactMetadataModel = new ArtifactMetadataModel( key, artifactMeta.getId(), repositoryId, namespaceId, + artifactMeta.getProject(), projectVersion, + artifactMeta.getVersion(), + artifactMeta.getFileLastModified(), + artifactMeta.getSize(), artifactMeta.getMd5(), + artifactMeta.getSha1(), artifactMeta.getWhenGathered() ); + + } + else + { + artifactMetadataModel.setFileLastModified( artifactMeta.getFileLastModified().getTime() ); + artifactMetadataModel.setWhenGathered( artifactMeta.getWhenGathered().getTime() ); + artifactMetadataModel.setSize( artifactMeta.getSize() ); + artifactMetadataModel.setMd5( artifactMeta.getMd5() ); + artifactMetadataModel.setSha1( artifactMeta.getSha1() ); + artifactMetadataModel.setVersion( artifactMeta.getVersion() ); + } + + try + { + artifactMetadataModelEntityManager.put( artifactMetadataModel ); + } + catch ( PersistenceException e ) + { + throw new MetadataRepositoryException( e.getMessage(), e ); + } + + key = new ProjectVersionMetadataModel.KeyBuilder().withRepository( repositoryId ).withNamespace( + namespace ).withProjectId( projectId ).withId( projectVersion ).build(); + + ProjectVersionMetadataModel projectVersionMetadataModel = projectVersionMetadataModelEntityManager.get( key ); + + if ( projectVersionMetadataModel == null ) + { + projectVersionMetadataModel = new ProjectVersionMetadataModel(); + projectVersionMetadataModel.setRowId( key ); + projectVersionMetadataModel.setProjectId( projectId ); + projectVersionMetadataModel.setId( projectVersion ); + projectVersionMetadataModel.setNamespace( namespace ); + + projectVersionMetadataModelEntityManager.put( projectVersionMetadataModel ); + + } + + // now facets + updateFacets( artifactMeta, artifactMetadataModel ); + + } + + @Override + public Collection getArtifactVersions( final String repoId, final String namespace, final String projectId, + final String projectVersion ) + throws MetadataResolutionException + { + final Set versions = new HashSet(); + // FIXME use cql query + artifactMetadataModelEntityManager.visitAll( new Function() + { + @Override + public Boolean apply( ArtifactMetadataModel artifactMetadataModel ) + { + if ( artifactMetadataModel != null ) + { + if ( StringUtils.equals( repoId, artifactMetadataModel.getRepositoryId() ) && StringUtils.equals( + namespace, artifactMetadataModel.getNamespace() ) && StringUtils.equals( projectId, + artifactMetadataModel.getProject() ) + && StringUtils.equals( projectVersion, artifactMetadataModel.getProjectVersion() ) ) + { + versions.add( artifactMetadataModel.getVersion() ); + } + } + return Boolean.TRUE; + } + } ); + + return versions; + } + + /** + * iterate over available facets to remove/add from the artifactMetadata + * + * @param facetedMetadata + * @param artifactMetadataModel only use for the key + */ + private void updateFacets( final FacetedMetadata facetedMetadata, + final ArtifactMetadataModel artifactMetadataModel ) + { + + for ( final String facetId : metadataFacetFactories.keySet() ) + { + MetadataFacet metadataFacet = facetedMetadata.getFacet( facetId ); + if ( metadataFacet == null ) + { + continue; + } + // clean first + + final List metadataFacetModels = new ArrayList(); + + metadataFacetModelEntityManager.visitAll( new Function() + { + @Override + public Boolean apply( MetadataFacetModel metadataFacetModel ) + { + ArtifactMetadataModel tmp = metadataFacetModel.getArtifactMetadataModel(); + if ( StringUtils.equals( metadataFacetModel.getFacetId(), facetId ) && StringUtils.equals( + tmp.getRepositoryId(), artifactMetadataModel.getRepositoryId() ) && StringUtils.equals( + tmp.getNamespace(), artifactMetadataModel.getNamespace() ) && StringUtils.equals( + tmp.getProject(), artifactMetadataModel.getProject() ) ) + { + metadataFacetModels.add( metadataFacetModel ); + } + return Boolean.TRUE; + } + } ); + + metadataFacetModelEntityManager.remove( metadataFacetModels ); + + Map properties = metadataFacet.toProperties(); + + final List metadataFacetModelsToAdd = + new ArrayList( properties.size() ); + + for ( Map.Entry entry : properties.entrySet() ) + { + String key = new MetadataFacetModel.KeyBuilder().withKey( entry.getKey() ).withArtifactMetadataModel( + artifactMetadataModel ).withFacetId( facetId ).withName( metadataFacet.getName() ).build(); + MetadataFacetModel metadataFacetModel = + new MetadataFacetModel( key, artifactMetadataModel, facetId, entry.getKey(), entry.getValue(), + metadataFacet.getName() ); + metadataFacetModelsToAdd.add( metadataFacetModel ); + } + + metadataFacetModelEntityManager.put( metadataFacetModelsToAdd ); + + } + } + + @Override + public void updateProjectVersion( String repositoryId, String namespaceId, String projectId, + ProjectVersionMetadata versionMetadata ) + throws MetadataRepositoryException + { + String namespaceKey = + new Namespace.KeyBuilder().withRepositoryId( repositoryId ).withNamespace( namespaceId ).build(); + Namespace namespace = namespaceEntityManager.get( namespaceKey ); + if ( namespace == null ) + { + namespace = updateOrAddNamespace( repositoryId, namespaceId ); + } + + String key = new Project.KeyBuilder().withNamespace( namespace ).withProjectId( projectId ).build(); + + Project project = projectEntityManager.get( key ); + if ( project == null ) + { + project = new Project( key, projectId, namespace ); + projectEntityManager.put( project ); + } + + // we don't test of repository and namespace really exist ! + key = new ProjectVersionMetadataModel.KeyBuilder().withRepository( repositoryId ).withNamespace( + namespaceId ).withProjectId( projectId ).withId( versionMetadata.getId() ).build(); + + ProjectVersionMetadataModel projectVersionMetadataModel = projectVersionMetadataModelEntityManager.get( key ); + + if ( projectVersionMetadataModel == null ) + { + projectVersionMetadataModel = + new BeanReplicator().replicateBean( versionMetadata, ProjectVersionMetadataModel.class ); + projectVersionMetadataModel.setRowId( key ); + } + projectVersionMetadataModel.setProjectId( projectId ); + projectVersionMetadataModel.setNamespace( new Namespace( namespaceId, new Repository( repositoryId ) ) ); + projectVersionMetadataModel.setCiManagement( versionMetadata.getCiManagement() ); + projectVersionMetadataModel.setIssueManagement( versionMetadata.getIssueManagement() ); + projectVersionMetadataModel.setOrganization( versionMetadata.getOrganization() ); + projectVersionMetadataModel.setScm( versionMetadata.getScm() ); + + projectVersionMetadataModel.setMailingLists( versionMetadata.getMailingLists() ); + projectVersionMetadataModel.setDependencies( versionMetadata.getDependencies() ); + projectVersionMetadataModel.setLicenses( versionMetadata.getLicenses() ); + + + try + { + projectVersionMetadataModelEntityManager.put( projectVersionMetadataModel ); + + ArtifactMetadataModel artifactMetadataModel = new ArtifactMetadataModel(); + artifactMetadataModel.setArtifactMetadataModelId( + new ArtifactMetadataModel.KeyBuilder().withId( versionMetadata.getId() ).withRepositoryId( + repositoryId ).withNamespace( namespaceId ).withProjectVersion( + versionMetadata.getVersion() ).build() ); + artifactMetadataModel.setRepositoryId( repositoryId ); + artifactMetadataModel.setNamespace( namespaceId ); + artifactMetadataModel.setProject( projectId ); + artifactMetadataModel.setProjectVersion( versionMetadata.getVersion() ); + artifactMetadataModel.setVersion( versionMetadata.getVersion() ); + // facets etc... + updateFacets( versionMetadata, artifactMetadataModel ); + } + catch ( PersistenceException e ) + { + throw new MetadataRepositoryException( e.getMessage(), e ); + } + } + + + private static class BooleanHolder + { + private boolean value = false; + } + + @Override + public List getMetadataFacets( final String repositoryId, final String facetId ) + throws MetadataRepositoryException + { + // FIXME use cql query !! + final List facets = new ArrayList(); + this.metadataFacetModelEntityManager.visitAll( new Function() + { + @Override + public Boolean apply( MetadataFacetModel metadataFacetModel ) + { + if ( metadataFacetModel != null ) + { + if ( StringUtils.equals( metadataFacetModel.getArtifactMetadataModel().getRepositoryId(), + repositoryId ) && StringUtils.equals( metadataFacetModel.getFacetId(), + facetId ) ) + { + facets.add( metadataFacetModel.getName() ); + } + } + return Boolean.TRUE; + } + } ); + + return facets; + + } + + @Override + public boolean hasMetadataFacet( String repositoryId, String facetId ) + throws MetadataRepositoryException + { + return !getMetadataFacets( repositoryId, facetId ).isEmpty(); + } + + @Override + public MetadataFacet getMetadataFacet( final String repositoryId, final String facetId, final String name ) + throws MetadataRepositoryException + { + // FIXME use cql query !! + final List facets = new ArrayList(); + this.metadataFacetModelEntityManager.visitAll( new Function() + { + @Override + public Boolean apply( MetadataFacetModel metadataFacetModel ) + { + if ( metadataFacetModel != null ) + { + if ( StringUtils.equals( metadataFacetModel.getArtifactMetadataModel().getRepositoryId(), + repositoryId ) && StringUtils.equals( metadataFacetModel.getFacetId(), + facetId ) && StringUtils.equals( + metadataFacetModel.getName(), name ) ) + { + facets.add( metadataFacetModel ); + } + } + return Boolean.TRUE; + } + } ); + + if ( facets.isEmpty() ) + { + return null; + } + + MetadataFacetFactory metadataFacetFactory = metadataFacetFactories.get( facetId ); + if ( metadataFacetFactory == null ) + { + return null; + } + MetadataFacet metadataFacet = metadataFacetFactory.createMetadataFacet( repositoryId, name ); + Map map = new HashMap( facets.size() ); + for ( MetadataFacetModel metadataFacetModel : facets ) + { + map.put( metadataFacetModel.getKey(), metadataFacetModel.getValue() ); + } + metadataFacet.fromProperties( map ); + return metadataFacet; + } + + @Override + public void addMetadataFacet( String repositoryId, MetadataFacet metadataFacet ) + throws MetadataRepositoryException + { + + if ( metadataFacet == null ) + { + return; + } + + if ( metadataFacet.toProperties().isEmpty() ) + { + String key = new MetadataFacetModel.KeyBuilder().withRepositoryId( repositoryId ).withFacetId( + metadataFacet.getFacetId() ).withName( metadataFacet.getName() ).build(); + MetadataFacetModel metadataFacetModel = metadataFacetModelEntityManager.get( key ); + if ( metadataFacetModel == null ) + { + metadataFacetModel = new MetadataFacetModel(); + } + // we need to store the repositoryId + ArtifactMetadataModel artifactMetadataModel = new ArtifactMetadataModel(); + artifactMetadataModel.setRepositoryId( repositoryId ); + metadataFacetModel.setArtifactMetadataModel( artifactMetadataModel ); + metadataFacetModel.setId( key ); + metadataFacetModel.setFacetId( metadataFacet.getFacetId() ); + metadataFacetModel.setName( metadataFacet.getName() ); + + try + { + metadataFacetModelEntityManager.put( metadataFacetModel ); + } + catch ( PersistenceException e ) + { + throw new MetadataRepositoryException( e.getMessage(), e ); + } + } + else + { + for ( Map.Entry entry : metadataFacet.toProperties().entrySet() ) + { + + String key = new MetadataFacetModel.KeyBuilder().withRepositoryId( repositoryId ).withFacetId( + metadataFacet.getFacetId() ).withName( metadataFacet.getName() ).withKey( entry.getKey() ).build(); + + MetadataFacetModel metadataFacetModel = metadataFacetModelEntityManager.get( key ); + if ( metadataFacetModel == null ) + { + metadataFacetModel = new MetadataFacetModel(); + // we need to store the repositoryId + ArtifactMetadataModel artifactMetadataModel = new ArtifactMetadataModel(); + artifactMetadataModel.setRepositoryId( repositoryId ); + metadataFacetModel.setArtifactMetadataModel( artifactMetadataModel ); + metadataFacetModel.setId( key ); + metadataFacetModel.setKey( entry.getKey() ); + metadataFacetModel.setFacetId( metadataFacet.getFacetId() ); + metadataFacetModel.setName( metadataFacet.getName() ); + } + metadataFacetModel.setValue( entry.getValue() ); + try + { + metadataFacetModelEntityManager.put( metadataFacetModel ); + } + catch ( PersistenceException e ) + { + throw new MetadataRepositoryException( e.getMessage(), e ); + } + + } + } + } + + @Override + public void removeMetadataFacets( final String repositoryId, final String facetId ) + throws MetadataRepositoryException + { + logger.debug( "removeMetadataFacets repositoryId: '{}', facetId: '{}'", repositoryId, facetId ); + final List toRemove = new ArrayList(); + + // FIXME cql query + metadataFacetModelEntityManager.visitAll( new Function() + { + @Override + public Boolean apply( MetadataFacetModel metadataFacetModel ) + { + if ( metadataFacetModel != null ) + { + if ( StringUtils.equals( metadataFacetModel.getArtifactMetadataModel().getRepositoryId(), + repositoryId ) && StringUtils.equals( metadataFacetModel.getFacetId(), + facetId ) ) + { + toRemove.add( metadataFacetModel ); + } + } + return Boolean.TRUE; + } + } ); + logger.debug( "removeMetadataFacets repositoryId: '{}', facetId: '{}', toRemove: {}", repositoryId, facetId, + toRemove ); + metadataFacetModelEntityManager.remove( toRemove ); + } + + @Override + public void removeMetadataFacet( final String repositoryId, final String facetId, final String name ) + throws MetadataRepositoryException + { + logger.debug( "removeMetadataFacets repositoryId: '{}', facetId: '{}'", repositoryId, facetId ); + final List toRemove = new ArrayList(); + + // FIXME cql query + metadataFacetModelEntityManager.visitAll( new Function() + { + @Override + public Boolean apply( MetadataFacetModel metadataFacetModel ) + { + if ( metadataFacetModel != null ) + { + if ( StringUtils.equals( metadataFacetModel.getArtifactMetadataModel().getRepositoryId(), + repositoryId ) && StringUtils.equals( metadataFacetModel.getFacetId(), + facetId ) && StringUtils.equals( + metadataFacetModel.getName(), name ) ) + { + toRemove.add( metadataFacetModel ); + } + } + return Boolean.TRUE; + } + } ); + logger.debug( "removeMetadataFacets repositoryId: '{}', facetId: '{}', toRemove: {}", repositoryId, facetId, + toRemove ); + metadataFacetModelEntityManager.remove( toRemove ); + } + + @Override + public List getArtifactsByDateRange( final String repositoryId, final Date startTime, + final Date endTime ) + throws MetadataRepositoryException + { + + final List artifactMetadataModels = new ArrayList(); + + // FIXME cql query + artifactMetadataModelEntityManager.visitAll( new Function() + { + @Override + public Boolean apply( ArtifactMetadataModel artifactMetadataModel ) + { + if ( artifactMetadataModel != null ) + { + if ( StringUtils.equals( artifactMetadataModel.getRepositoryId(), repositoryId ) + && artifactMetadataModel.getNamespace() != null && + artifactMetadataModel.getProject() != null && artifactMetadataModel.getId() != null ) + { + + Date when = artifactMetadataModel.getWhenGathered(); + if ( ( startTime != null ? when.getTime() >= startTime.getTime() : true ) && ( endTime != null ? + when.getTime() <= endTime.getTime() : true ) ) + { + logger.debug( "getArtifactsByDateRange visitAll found: {}", artifactMetadataModel ); + artifactMetadataModels.add( artifactMetadataModel ); + } + } + } + return Boolean.TRUE; + } + } ); + List artifactMetadatas = new ArrayList( artifactMetadataModels.size() ); + + for ( ArtifactMetadataModel model : artifactMetadataModels ) + { + ArtifactMetadata artifactMetadata = new BeanReplicator().replicateBean( model, ArtifactMetadata.class ); + populateFacets( artifactMetadata ); + artifactMetadatas.add( artifactMetadata ); + } + + // FIXME facets ? + + logger.debug( "getArtifactsByDateRange repositoryId: {}, startTime: {}, endTime: {}, artifactMetadatas: {}", + repositoryId, startTime, endTime, artifactMetadatas ); + + return artifactMetadatas; + } + + protected void populateFacets( final ArtifactMetadata artifactMetadata ) + { + final List metadataFacetModels = new ArrayList(); + + metadataFacetModelEntityManager.visitAll( new Function() + { + @Override + public Boolean apply( MetadataFacetModel metadataFacetModel ) + { + if ( metadataFacetModel != null ) + { + ArtifactMetadataModel artifactMetadataModel = metadataFacetModel.getArtifactMetadataModel(); + if ( artifactMetadataModel != null ) + { + if ( StringUtils.equals( artifactMetadata.getRepositoryId(), + artifactMetadataModel.getRepositoryId() ) && StringUtils.equals( + artifactMetadata.getNamespace(), artifactMetadataModel.getNamespace() ) + && StringUtils.equals( artifactMetadata.getRepositoryId(), + artifactMetadataModel.getRepositoryId() ) && StringUtils.equals( + artifactMetadata.getProject(), artifactMetadataModel.getProject() ) && StringUtils.equals( + artifactMetadata.getId(), artifactMetadataModel.getId() ) ) + { + metadataFacetModels.add( metadataFacetModel ); + } + } + } + return Boolean.TRUE; + } + } ); + Map> facetValuesPerFacet = new HashMap>(); + + for ( MetadataFacetModel model : metadataFacetModels ) + { + Map values = facetValuesPerFacet.get( model.getName() ); + if ( values == null ) + { + values = new HashMap(); + } + values.put( model.getKey(), model.getValue() ); + facetValuesPerFacet.put( model.getName(), values ); + } + + for ( Map.Entry> entry : facetValuesPerFacet.entrySet() ) + { + MetadataFacetFactory factory = metadataFacetFactories.get( entry.getKey() ); + if ( factory == null ) + { + continue; + } + MetadataFacet metadataFacet = + factory.createMetadataFacet( artifactMetadata.getRepositoryId(), entry.getKey() ); + metadataFacet.fromProperties( entry.getValue() ); + artifactMetadata.addFacet( metadataFacet ); + } + } + + @Override + public List getArtifactsByChecksum( final String repositoryId, final String checksum ) + throws MetadataRepositoryException + { + final List artifactMetadataModels = new ArrayList(); + + if ( logger.isDebugEnabled() ) + { + logger.debug( "all ArtifactMetadataModel: {}", artifactMetadataModelEntityManager.getAll() ); + } + + // FIXME cql query + artifactMetadataModelEntityManager.visitAll( new Function() + { + @Override + public Boolean apply( ArtifactMetadataModel artifactMetadataModel ) + { + if ( artifactMetadataModel != null ) + { + if ( StringUtils.equals( artifactMetadataModel.getRepositoryId(), repositoryId ) + && artifactMetadataModel.getNamespace() != null && + artifactMetadataModel.getProject() != null && artifactMetadataModel.getId() != null ) + { + + if ( StringUtils.equals( checksum, artifactMetadataModel.getMd5() ) || StringUtils.equals( + checksum, artifactMetadataModel.getSha1() ) ) + { + artifactMetadataModels.add( artifactMetadataModel ); + } + } + } + return Boolean.TRUE; + } + } ); + List artifactMetadatas = new ArrayList( artifactMetadataModels.size() ); + + for ( ArtifactMetadataModel model : artifactMetadataModels ) + { + ArtifactMetadata artifactMetadata = new BeanReplicator().replicateBean( model, ArtifactMetadata.class ); + populateFacets( artifactMetadata ); + artifactMetadatas.add( artifactMetadata ); + } + + logger.debug( "getArtifactsByChecksum repositoryId: {}, checksum: {}, artifactMetadatas: {}", repositoryId, + checksum, artifactMetadatas ); + + return artifactMetadatas; + } + + @Override + public void removeArtifact( final String repositoryId, final String namespace, final String project, + final String version, final String id ) + throws MetadataRepositoryException + { + logger.debug( "removeArtifact repositoryId: '{}', namespace: '{}', project: '{}', version: '{}', id: '{}'", + repositoryId, namespace, project, version, id ); + String key = + new ArtifactMetadataModel.KeyBuilder().withRepositoryId( repositoryId ).withNamespace( namespace ).withId( + id ).withProjectVersion( version ).withProject( project ).build(); + + ArtifactMetadataModel artifactMetadataModel = new ArtifactMetadataModel(); + artifactMetadataModel.setArtifactMetadataModelId( key ); + + artifactMetadataModelEntityManager.remove( artifactMetadataModel ); + + key = + new ProjectVersionMetadataModel.KeyBuilder().withId( version ).withRepository( repositoryId ).withNamespace( + namespace ).withProjectId( project ).build(); + + ProjectVersionMetadataModel projectVersionMetadataModel = new ProjectVersionMetadataModel(); + projectVersionMetadataModel.setRowId( key ); + + projectVersionMetadataModelEntityManager.remove( projectVersionMetadataModel ); + } + + @Override + public void removeArtifact( ArtifactMetadata artifactMetadata, String baseVersion ) + throws MetadataRepositoryException + { + logger.debug( "removeArtifact repositoryId: '{}', namespace: '{}', project: '{}', version: '{}', id: '{}'", + artifactMetadata.getRepositoryId(), artifactMetadata.getNamespace(), + artifactMetadata.getProject(), baseVersion, artifactMetadata.getId() ); + String key = + new ArtifactMetadataModel.KeyBuilder().withRepositoryId( artifactMetadata.getRepositoryId() ).withNamespace( + artifactMetadata.getNamespace() ).withId( artifactMetadata.getId() ).withProjectVersion( + baseVersion ).withProject( artifactMetadata.getProject() ).build(); + + ArtifactMetadataModel artifactMetadataModel = new ArtifactMetadataModel(); + artifactMetadataModel.setArtifactMetadataModelId( key ); + + artifactMetadataModelEntityManager.remove( artifactMetadataModel ); + } + + @Override + public void removeArtifact( final String repositoryId, final String namespace, final String project, + final String version, final MetadataFacet metadataFacet ) + throws MetadataRepositoryException + { + final List artifactMetadataModels = new ArrayList(); + artifactMetadataModelEntityManager.visitAll( new Function() + { + @Override + public Boolean apply( ArtifactMetadataModel artifactMetadataModel ) + { + if ( artifactMetadataModel != null ) + { + if ( StringUtils.equals( repositoryId, artifactMetadataModel.getRepositoryId() ) + && StringUtils.equals( namespace, artifactMetadataModel.getNamespace() ) && StringUtils.equals( + project, artifactMetadataModel.getProject() ) && StringUtils.equals( project, + artifactMetadataModel.getVersion() ) ) + { + artifactMetadataModels.add( artifactMetadataModel ); + } + } + return Boolean.TRUE; + } + } ); + artifactMetadataModelEntityManager.remove( artifactMetadataModels ); + /* + metadataFacetModelEntityManager.visitAll( new Function() + { + @Override + public Boolean apply( MetadataFacetModel metadataFacetModel ) + { + if ( metadataFacetModel != null ) + { + ArtifactMetadataModel artifactMetadataModel = metadataFacetModel.getArtifactMetadataModel(); + if ( artifactMetadataModel != null ) + { + if ( StringUtils.equals( repositoryId, artifactMetadataModel.getRepositoryId() ) + && StringUtils.equals( namespace, artifactMetadataModel.getNamespace() ) + && StringUtils.equals( project, artifactMetadataModel.getProject() ) && StringUtils.equals( + version, artifactMetadataModel.getVersion() ) ) + { + if ( StringUtils.equals( metadataFacetModel.getFacetId(), metadataFacet.getFacetId() ) + && StringUtils.equals( metadataFacetModel.getName(), metadataFacet.getName() ) ) + { + metadataFacetModels.add( metadataFacetModel ); + } + } + } + } + return Boolean.TRUE; + } + } ); + metadataFacetModelEntityManager.remove( metadataFacetModels ); + */ + } + + + @Override + public List getArtifacts( final String repositoryId ) + throws MetadataRepositoryException + { + final List artifactMetadataModels = new ArrayList(); + // FIXME use cql query ! + artifactMetadataModelEntityManager.visitAll( new Function() + { + @Override + public Boolean apply( ArtifactMetadataModel artifactMetadataModel ) + { + if ( artifactMetadataModel != null ) + { + if ( StringUtils.equals( repositoryId, artifactMetadataModel.getRepositoryId() ) ) + { + artifactMetadataModels.add( artifactMetadataModel ); + } + } + + return Boolean.TRUE; + } + } ); + + List artifactMetadatas = new ArrayList( artifactMetadataModels.size() ); + + for ( ArtifactMetadataModel model : artifactMetadataModels ) + { + ArtifactMetadata artifactMetadata = new BeanReplicator().replicateBean( model, ArtifactMetadata.class ); + populateFacets( artifactMetadata ); + artifactMetadatas.add( artifactMetadata ); + } + + return artifactMetadatas; + } + + @Override + public ProjectMetadata getProject( final String repoId, final String namespace, final String id ) + throws MetadataResolutionException + { + //basically just checking it exists + // FIXME use cql query + + final BooleanHolder booleanHolder = new BooleanHolder(); + + projectEntityManager.visitAll( new Function() + { + @Override + public Boolean apply( Project project ) + { + if ( project != null ) + { + if ( StringUtils.equals( repoId, project.getNamespace().getRepository().getName() ) + && StringUtils.equals( namespace, project.getNamespace().getName() ) && StringUtils.equals( id, + project.getProjectId() ) ) + { + booleanHolder.value = true; + } + } + return Boolean.TRUE; + } + } ); + + if ( !booleanHolder.value ) + { + return null; + } + + ProjectMetadata projectMetadata = new ProjectMetadata(); + projectMetadata.setId( id ); + projectMetadata.setNamespace( namespace ); + + logger.debug( "getProject repoId: {}, namespace: {}, projectId: {} -> {}", repoId, namespace, id, + projectMetadata ); + + return projectMetadata; + } + + @Override + public ProjectVersionMetadata getProjectVersion( final String repoId, final String namespace, + final String projectId, final String projectVersion ) + throws MetadataResolutionException + { + String key = new ProjectVersionMetadataModel.KeyBuilder().withRepository( repoId ).withNamespace( + namespace ).withProjectId( projectId ).withId( projectVersion ).build(); + + ProjectVersionMetadataModel projectVersionMetadataModel = projectVersionMetadataModelEntityManager.get( key ); + + if ( projectVersionMetadataModel == null ) + { + logger.debug( + "getProjectVersion repoId: '{}', namespace: '{}', projectId: '{}', projectVersion: {} -> not found", + repoId, namespace, projectId, projectVersion ); + return null; + } + + ProjectVersionMetadata projectVersionMetadata = + new BeanReplicator().replicateBean( projectVersionMetadataModel, ProjectVersionMetadata.class ); + + logger.debug( "getProjectVersion repoId: '{}', namespace: '{}', projectId: '{}', projectVersion: {} -> {}", + repoId, namespace, projectId, projectVersion, projectVersionMetadata ); + + projectVersionMetadata.setCiManagement( projectVersionMetadataModel.getCiManagement() ); + projectVersionMetadata.setIssueManagement( projectVersionMetadataModel.getIssueManagement() ); + projectVersionMetadata.setOrganization( projectVersionMetadataModel.getOrganization() ); + projectVersionMetadata.setScm( projectVersionMetadataModel.getScm() ); + + // FIXME complete collections !! + + // facets + final List metadataFacetModels = new ArrayList(); + // FIXME use cql query + metadataFacetModelEntityManager.visitAll( new Function() + { + @Override + public Boolean apply( MetadataFacetModel metadataFacetModel ) + { + if ( metadataFacetModel != null ) + { + if ( StringUtils.equals( repoId, metadataFacetModel.getArtifactMetadataModel().getRepositoryId() ) + && StringUtils.equals( namespace, metadataFacetModel.getArtifactMetadataModel().getNamespace() ) + && StringUtils.equals( projectId, metadataFacetModel.getArtifactMetadataModel().getProject() ) + && StringUtils.equals( projectVersion, + metadataFacetModel.getArtifactMetadataModel().getProjectVersion() ) ) + { + metadataFacetModels.add( metadataFacetModel ); + } + } + return Boolean.TRUE; + } + } ); + Map> metadataFacetsPerFacetIds = new HashMap>(); + for ( MetadataFacetModel metadataFacetModel : metadataFacetModels ) + { + + Map metaValues = metadataFacetsPerFacetIds.get( metadataFacetModel.getFacetId() ); + if ( metaValues == null ) + { + metaValues = new HashMap(); + metadataFacetsPerFacetIds.put( metadataFacetModel.getFacetId(), metaValues ); + } + metaValues.put( metadataFacetModel.getKey(), metadataFacetModel.getValue() ); + + } + + if ( !metadataFacetsPerFacetIds.isEmpty() ) + { + for ( Map.Entry> entry : metadataFacetsPerFacetIds.entrySet() ) + { + MetadataFacetFactory metadataFacetFactory = metadataFacetFactories.get( entry.getKey() ); + if ( metadataFacetFactory != null ) + { + MetadataFacet metadataFacet = metadataFacetFactory.createMetadataFacet( repoId, entry.getKey() ); + metadataFacet.fromProperties( entry.getValue() ); + projectVersionMetadata.addFacet( metadataFacet ); + } + } + } + + return projectVersionMetadata; + } + + + @Override + public Collection getProjectReferences( String repoId, String namespace, String projectId, + String projectVersion ) + throws MetadataResolutionException + { + // FIXME implement this + return Collections.emptyList(); + } + + @Override + public Collection getProjects( final String repoId, final String namespace ) + throws MetadataResolutionException + { + final Set projects = new HashSet(); + + // FIXME use cql query + projectEntityManager.visitAll( new Function() + { + @Override + public Boolean apply( Project project ) + { + if ( project != null ) + { + if ( StringUtils.equals( repoId, project.getNamespace().getRepository().getName() ) + && StringUtils.startsWith( project.getNamespace().getName(), namespace ) ) + { + projects.add( project.getProjectId() ); + } + } + return Boolean.TRUE; + } + } ); + /* + + artifactMetadataModelEntityManager.visitAll( new Function() + { + @Override + public Boolean apply( ArtifactMetadataModel artifactMetadataModel ) + { + if ( artifactMetadataModel != null ) + { + if ( StringUtils.equals( repoId, artifactMetadataModel.getRepositoryId() ) && StringUtils.equals( + namespace, artifactMetadataModel.getNamespace() ) ) + { + projects.add( artifactMetadataModel.getProject() ); + } + } + return Boolean.TRUE; + } + } ); + */ + return projects; + } + + + @Override + public void removeProjectVersion( final String repoId, final String namespace, final String projectId, + final String projectVersion ) + throws MetadataRepositoryException + { + + final List artifactMetadataModels = new ArrayList(); + + // FIXME use cql query + + artifactMetadataModelEntityManager.visitAll( new Function() + { + @Override + public Boolean apply( ArtifactMetadataModel artifactMetadataModel ) + { + if ( artifactMetadataModel != null ) + { + if ( StringUtils.equals( repoId, artifactMetadataModel.getRepositoryId() ) && StringUtils.equals( + namespace, artifactMetadataModel.getNamespace() ) && StringUtils.equals( projectId, + artifactMetadataModel.getProject() ) + && StringUtils.equals( projectVersion, artifactMetadataModel.getProjectVersion() ) ) + { + artifactMetadataModels.add( artifactMetadataModel ); + } + } + return Boolean.TRUE; + } + } ); + + logger.debug( "removeProjectVersions:{}", artifactMetadataModels ); + if ( artifactMetadataModels.isEmpty() ) + { + return; + } + + artifactMetadataModelEntityManager.remove( artifactMetadataModels ); + + String key = new ProjectVersionMetadataModel.KeyBuilder().withProjectId( projectId ).withId( + projectVersion ).withRepository( repoId ).withNamespace( namespace ).build(); + + ProjectVersionMetadataModel projectVersionMetadataModel = new ProjectVersionMetadataModel(); + projectVersionMetadataModel.setRowId( key ); + + projectVersionMetadataModelEntityManager.remove( projectVersionMetadataModel ); + } + + @Override + public Collection getArtifacts( final String repoId, final String namespace, + final String projectId, final String projectVersion ) + throws MetadataResolutionException + { + final List artifactMetadataModels = new ArrayList(); + // FIXME use cql query ! + artifactMetadataModelEntityManager.visitAll( new Function() + { + @Override + public Boolean apply( ArtifactMetadataModel artifactMetadataModel ) + { + if ( artifactMetadataModel != null ) + { + if ( StringUtils.equals( repoId, artifactMetadataModel.getRepositoryId() ) && StringUtils.equals( + namespace, artifactMetadataModel.getNamespace() ) && StringUtils.equals( projectId, + artifactMetadataModel.getProject() ) + && StringUtils.equals( projectVersion, artifactMetadataModel.getProjectVersion() ) ) + { + artifactMetadataModels.add( artifactMetadataModel ); + } + } + + return Boolean.TRUE; + } + } ); + + List artifactMetadatas = new ArrayList( artifactMetadataModels.size() ); + + for ( ArtifactMetadataModel model : artifactMetadataModels ) + { + ArtifactMetadata artifactMetadata = new BeanReplicator().replicateBean( model, ArtifactMetadata.class ); + populateFacets( artifactMetadata ); + artifactMetadatas.add( artifactMetadata ); + } + + // retrieve facets + final List metadataFacetModels = new ArrayList(); + metadataFacetModelEntityManager.visitAll( new Function() + { + @Override + public Boolean apply( MetadataFacetModel metadataFacetModel ) + { + if ( metadataFacetModel != null ) + { + if ( StringUtils.equals( repoId, metadataFacetModel.getArtifactMetadataModel().getRepositoryId() ) + && StringUtils.equals( namespace, metadataFacetModel.getArtifactMetadataModel().getNamespace() ) + && StringUtils.equals( projectId, metadataFacetModel.getArtifactMetadataModel().getProject() ) + && StringUtils.equals( projectVersion, + metadataFacetModel.getArtifactMetadataModel().getProjectVersion() ) ) + { + metadataFacetModels.add( metadataFacetModel ); + } + + } + return Boolean.TRUE; + } + } ); + + // rebuild MetadataFacet for artifacts + + for ( final ArtifactMetadata artifactMetadata : artifactMetadatas ) + { + Iterable metadataFacetModelIterable = + Iterables.filter( metadataFacetModels, new Predicate() + { + @Override + public boolean apply( MetadataFacetModel metadataFacetModel ) + { + if ( metadataFacetModel != null ) + { + return StringUtils.equals( artifactMetadata.getVersion(), + metadataFacetModel.getArtifactMetadataModel().getVersion() ); + } + return false; + } + } ); + Iterator iterator = metadataFacetModelIterable.iterator(); + Map> metadataFacetValuesPerFacetId = + new HashMap>(); + while ( iterator.hasNext() ) + { + MetadataFacetModel metadataFacetModel = iterator.next(); + List values = metadataFacetValuesPerFacetId.get( metadataFacetModel.getName() ); + if ( values == null ) + { + values = new ArrayList(); + metadataFacetValuesPerFacetId.put( metadataFacetModel.getFacetId(), values ); + } + values.add( metadataFacetModel ); + + } + + for ( Map.Entry> entry : metadataFacetValuesPerFacetId.entrySet() ) + { + MetadataFacetFactory metadataFacetFactory = metadataFacetFactories.get( entry.getKey() ); + if ( metadataFacetFactory != null ) + { + List facetModels = entry.getValue(); + if ( !facetModels.isEmpty() ) + { + MetadataFacet metadataFacet = + metadataFacetFactory.createMetadataFacet( repoId, facetModels.get( 0 ).getName() ); + Map props = new HashMap( facetModels.size() ); + for ( MetadataFacetModel metadataFacetModel : facetModels ) + { + props.put( metadataFacetModel.getKey(), metadataFacetModel.getValue() ); + } + metadataFacet.fromProperties( props ); + artifactMetadata.addFacet( metadataFacet ); + } + } + } + + + } + + return artifactMetadatas; + } + + @Override + public void save() + { + logger.trace( "save" ); + } + + @Override + public void close() + throws MetadataRepositoryException + { + logger.trace( "close" ); + } + + @Override + public void revert() + { + logger.warn( "CassandraMetadataRepository cannot revert" ); + } + + @Override + public boolean canObtainAccess( Class aClass ) + { + return false; + } + + @Override + public T obtainAccess( Class aClass ) + throws MetadataRepositoryException + { + throw new IllegalArgumentException( + "Access using " + aClass + " is not supported on the cassandra metadata storage" ); + } +} diff --git a/archiva-modules/plugins/metadata-store-cassandra/src/main/java/org/apache/archiva/metadata/repository/cassandra/CassandraRepositorySessionFactory.java b/archiva-modules/plugins/metadata-store-cassandra/src/main/java/org/apache/archiva/metadata/repository/cassandra/CassandraRepositorySessionFactory.java new file mode 100644 index 000000000..2e7f621e5 --- /dev/null +++ b/archiva-modules/plugins/metadata-store-cassandra/src/main/java/org/apache/archiva/metadata/repository/cassandra/CassandraRepositorySessionFactory.java @@ -0,0 +1,87 @@ +package org.apache.archiva.metadata.repository.cassandra; + +/* + * 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.ArchivaConfiguration; +import org.apache.archiva.metadata.model.MetadataFacetFactory; +import org.apache.archiva.metadata.repository.MetadataResolver; +import org.apache.archiva.metadata.repository.RepositorySession; +import org.apache.archiva.metadata.repository.RepositorySessionFactory; +import org.apache.commons.lang.StringUtils; +import org.springframework.context.ApplicationContext; +import org.springframework.stereotype.Service; + +import javax.annotation.PostConstruct; +import javax.inject.Inject; +import javax.inject.Named; +import java.util.HashMap; +import java.util.Map; + +/** + * @author Olivier Lamy + */ +@Service( "repositorySessionFactory#cassandra" ) +public class CassandraRepositorySessionFactory + implements RepositorySessionFactory +{ + + private Map metadataFacetFactories; + + @Inject + @Named( value = "archivaConfiguration#default" ) + private ArchivaConfiguration configuration; + + @Inject + private MetadataResolver metadataResolver; + + @Inject + private ApplicationContext applicationContext; + + @Inject + private CassandraEntityManagerFactory cassandraEntityManagerFactory; + + @PostConstruct + public void initialize() + { + Map tmpMetadataFacetFactories = + applicationContext.getBeansOfType( MetadataFacetFactory.class ); + // olamy with spring the "id" is now "metadataFacetFactory#hint" + // whereas was only hint with plexus so let remove metadataFacetFactory# + metadataFacetFactories = new HashMap( tmpMetadataFacetFactories.size() ); + + for ( Map.Entry entry : tmpMetadataFacetFactories.entrySet() ) + { + metadataFacetFactories.put( StringUtils.substringAfterLast( entry.getKey(), "#" ), entry.getValue() ); + } + + + } + + + @Override + public RepositorySession createSession() + { + CassandraMetadataRepository metadataRepository = + new CassandraMetadataRepository( metadataFacetFactories, configuration, + cassandraEntityManagerFactory.getKeyspace() ); + return new RepositorySession( metadataRepository, metadataResolver ); + } + +} diff --git a/archiva-modules/plugins/metadata-store-cassandra/src/main/java/org/apache/archiva/metadata/repository/cassandra/DefaultCassandraEntityManagerFactory.java b/archiva-modules/plugins/metadata-store-cassandra/src/main/java/org/apache/archiva/metadata/repository/cassandra/DefaultCassandraEntityManagerFactory.java new file mode 100644 index 000000000..da24f178c --- /dev/null +++ b/archiva-modules/plugins/metadata-store-cassandra/src/main/java/org/apache/archiva/metadata/repository/cassandra/DefaultCassandraEntityManagerFactory.java @@ -0,0 +1,95 @@ +package org.apache.archiva.metadata.repository.cassandra; + +/* + * 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 com.google.common.collect.ImmutableMap; +import com.netflix.astyanax.AstyanaxContext; +import com.netflix.astyanax.Keyspace; +import com.netflix.astyanax.connectionpool.NodeDiscoveryType; +import com.netflix.astyanax.connectionpool.exceptions.ConnectionException; +import com.netflix.astyanax.connectionpool.impl.ConnectionPoolConfigurationImpl; +import com.netflix.astyanax.connectionpool.impl.ConnectionPoolType; +import com.netflix.astyanax.connectionpool.impl.CountingConnectionPoolMonitor; +import com.netflix.astyanax.impl.AstyanaxConfigurationImpl; +import com.netflix.astyanax.thrift.ThriftFamilyFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.stereotype.Service; + +import javax.annotation.PostConstruct; +import javax.inject.Inject; + +/** + * FIXME make all configuration not hardcoded :-) + * + * @author Olivier Lamy + */ +@Service("archivaEntityManagerFactory#cassandra") +public class DefaultCassandraEntityManagerFactory + implements CassandraEntityManagerFactory +{ + + @Inject + private ApplicationContext applicationContext; + + private static final String CLUSTER_NAME = "archiva"; + + private static final String KEYSPACE_NAME = "ArchivaKeySpace"; + + private Keyspace keyspace; + + private AstyanaxContext keyspaceContext; + + + @PostConstruct + public void initialize() + throws ConnectionException + { + String cassandraHost = System.getProperty( "cassandraHost", "localhost" ); + String cassandraPort = System.getProperty( "cassandraPort" ); + keyspaceContext = new AstyanaxContext.Builder().forCluster( CLUSTER_NAME ).forKeyspace( + KEYSPACE_NAME ).withAstyanaxConfiguration( + new AstyanaxConfigurationImpl().setDiscoveryType( NodeDiscoveryType.RING_DESCRIBE ).setConnectionPoolType( + ConnectionPoolType.TOKEN_AWARE ) ).withConnectionPoolConfiguration( + new ConnectionPoolConfigurationImpl( CLUSTER_NAME + "_" + KEYSPACE_NAME ).setSocketTimeout( + 30000 ).setMaxTimeoutWhenExhausted( 2000 ).setMaxConnsPerHost( 20 ).setInitConnsPerHost( 10 ).setSeeds( + cassandraHost + ":" + cassandraPort ) ).withConnectionPoolMonitor( + new CountingConnectionPoolMonitor() ).buildKeyspace( ThriftFamilyFactory.getInstance() ); + + keyspaceContext.start(); + + keyspace = keyspaceContext.getClient(); + + ImmutableMap options = ImmutableMap.builder().put( "strategy_options", + ImmutableMap.builder().put( + "replication_factor", + "1" ).build() ).put( + "strategy_class", "SimpleStrategy" ).build(); + + keyspace.createKeyspace( options ); + + } + + + @Override + public Keyspace getKeyspace() + { + return keyspace; + } +} diff --git a/archiva-modules/plugins/metadata-store-cassandra/src/main/java/org/apache/archiva/metadata/repository/cassandra/model/ArtifactMetadataModel.java b/archiva-modules/plugins/metadata-store-cassandra/src/main/java/org/apache/archiva/metadata/repository/cassandra/model/ArtifactMetadataModel.java new file mode 100644 index 000000000..aa635e9ff --- /dev/null +++ b/archiva-modules/plugins/metadata-store-cassandra/src/main/java/org/apache/archiva/metadata/repository/cassandra/model/ArtifactMetadataModel.java @@ -0,0 +1,331 @@ +package org.apache.archiva.metadata.repository.cassandra.model; + +/* + * 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 javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import java.io.Serializable; +import java.util.Date; + +/** + * Cassandra storage model for {@link org.apache.archiva.metadata.model.ArtifactMetadata} + * + * @author Olivier Lamy + */ +@Entity +public class ArtifactMetadataModel + implements Serializable +{ + + // repositoryId + namespaceId + project + projectVersion + id + @Id + private String artifactMetadataModelId; + + @Column(name = "id") + private String id; + + @Column(name = "repositoryId") + private String repositoryId; + + @Column(name = "namespace") + private String namespace; + + @Column(name = "project") + private String project; + + @Column(name = "projectVersion") + private String projectVersion; + + @Column(name = "version") + private String version; + + @Column(name = "fileLastModified") + private long fileLastModified; + + @Column(name = "size") + private long size; + + @Column(name = "md5") + private String md5; + + @Column(name = "sha1") + private String sha1; + + @Column(name = "whenGathered") + private long whenGathered; + + public ArtifactMetadataModel() + { + // no op + } + + public ArtifactMetadataModel( String artifactMetadataModelId, String id, String repositoryId, String namespace, + String project, String projectVersion, String version, Date fileLastModified, + long size, String md5, String sha1, Date whenGathered ) + { + this.artifactMetadataModelId = artifactMetadataModelId; + this.id = id; + this.repositoryId = repositoryId; + this.namespace = namespace; + this.project = project; + this.projectVersion = projectVersion; + this.version = version; + this.fileLastModified = ( fileLastModified != null ? fileLastModified.getTime() : 0 ); + this.size = size; + this.md5 = md5; + this.sha1 = sha1; + this.whenGathered = whenGathered != null ? whenGathered.getTime() : new Date().getTime(); + } + + public String getArtifactMetadataModelId() + { + return artifactMetadataModelId; + } + + public void setArtifactMetadataModelId( String artifactMetadataModelId ) + { + this.artifactMetadataModelId = artifactMetadataModelId; + } + + public String getId() + { + return id; + } + + public void setId( String id ) + { + this.id = id; + } + + public String getRepositoryId() + { + return repositoryId; + } + + public void setRepositoryId( String repositoryId ) + { + this.repositoryId = repositoryId; + } + + public String getNamespace() + { + return namespace; + } + + public void setNamespace( String namespace ) + { + this.namespace = namespace; + } + + public String getProject() + { + return project; + } + + public void setProject( String project ) + { + this.project = project; + } + + public String getProjectVersion() + { + return projectVersion; + } + + public void setProjectVersion( String projectVersion ) + { + this.projectVersion = projectVersion; + } + + public String getVersion() + { + return version; + } + + public void setVersion( String version ) + { + this.version = version; + } + + public long getFileLastModified() + { + return fileLastModified; + } + + public void setFileLastModified( long fileLastModified ) + { + this.fileLastModified = fileLastModified; + } + + public long getSize() + { + return size; + } + + public void setSize( long size ) + { + this.size = size; + } + + public String getMd5() + { + return md5; + } + + public void setMd5( String md5 ) + { + this.md5 = md5; + } + + public String getSha1() + { + return sha1; + } + + public void setSha1( String sha1 ) + { + this.sha1 = sha1; + } + + public Date getWhenGathered() + { + return new Date( whenGathered ); + } + + public void setWhenGathered( long whenGathered ) + { + this.whenGathered = whenGathered; + } + + @Override + public boolean equals( Object o ) + { + if ( this == o ) + { + return true; + } + if ( o == null || getClass() != o.getClass() ) + { + return false; + } + + ArtifactMetadataModel that = (ArtifactMetadataModel) o; + + if ( !artifactMetadataModelId.equals( that.artifactMetadataModelId ) ) + { + return false; + } + + return true; + } + + @Override + public int hashCode() + { + return artifactMetadataModelId.hashCode(); + } + + @Override + public String toString() + { + final StringBuilder sb = new StringBuilder( "ArtifactMetadataModel{" ); + sb.append( "artifactMetadataModelId='" ).append( artifactMetadataModelId ).append( '\'' ); + sb.append( ", id='" ).append( id ).append( '\'' ); + sb.append( ", repositoryId='" ).append( repositoryId ).append( '\'' ); + sb.append( ", namespace='" ).append( namespace ).append( '\'' ); + sb.append( ", project='" ).append( project ).append( '\'' ); + sb.append( ", projectVersion='" ).append( projectVersion ).append( '\'' ); + sb.append( ", version='" ).append( version ).append( '\'' ); + sb.append( ", fileLastModified=" ).append( fileLastModified ); + sb.append( ", size=" ).append( size ); + sb.append( ", md5='" ).append( md5 ).append( '\'' ); + sb.append( ", sha1='" ).append( sha1 ).append( '\'' ); + sb.append( ", whenGathered=" ).append( whenGathered ); + sb.append( '}' ); + return sb.toString(); + } + + public static class KeyBuilder + { + + private String project; + + private String id; + + private String namespaceId; + + private String repositoryId; + + private String projectVersion; + + public KeyBuilder() + { + + } + + public KeyBuilder withId( String id ) + { + this.id = id; + return this; + } + + + public KeyBuilder withNamespace( Namespace namespace ) + { + this.namespaceId = namespace.getName(); + this.repositoryId = namespace.getRepository().getId(); + return this; + } + + public KeyBuilder withNamespace( String namespaceId ) + { + this.namespaceId = namespaceId; + return this; + } + + public KeyBuilder withProject( String project ) + { + this.project = project; + return this; + } + + public KeyBuilder withProjectVersion( String projectVersion ) + { + this.projectVersion = projectVersion; + return this; + } + + public KeyBuilder withRepositoryId( String repositoryId ) + { + this.repositoryId = repositoryId; + return this; + } + + public String build() + { + //repositoryId + namespaceId + project + projectVersion + id + // FIXME add some controls + return this.repositoryId + "-" + this.namespaceId + "-" + this.project + "-" + this.projectVersion + "-" + + this.id; + } + } + +} diff --git a/archiva-modules/plugins/metadata-store-cassandra/src/main/java/org/apache/archiva/metadata/repository/cassandra/model/MetadataFacetModel.java b/archiva-modules/plugins/metadata-store-cassandra/src/main/java/org/apache/archiva/metadata/repository/cassandra/model/MetadataFacetModel.java new file mode 100644 index 000000000..545787fba --- /dev/null +++ b/archiva-modules/plugins/metadata-store-cassandra/src/main/java/org/apache/archiva/metadata/repository/cassandra/model/MetadataFacetModel.java @@ -0,0 +1,229 @@ +package org.apache.archiva.metadata.repository.cassandra.model; + +/* + * 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 javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; + +/** + * Cassandra storage model for {@link org.apache.archiva.metadata.model.MetadataFacet} + * + * @author Olivier Lamy + */ +@Entity +public class MetadataFacetModel +{ + // id is repositoryId + namespaceId + projectId + facetId + name + mapKey + @Id + @Column( name = "id" ) + private String id; + + @Column( name = "artifactMetadataModel" ) + private ArtifactMetadataModel artifactMetadataModel; + + @Column( name = "facetId" ) + private String facetId; + + @Column( name = "name" ) + private String name; + + @Column( name = "key" ) + private String key; + + @Column( name = "value" ) + private String value; + + public MetadataFacetModel() + { + // no op + } + + public MetadataFacetModel( String id, ArtifactMetadataModel artifactMetadataModel, String facetId, String key, + String value, String name ) + { + this.id = id; + this.artifactMetadataModel = artifactMetadataModel; + this.key = key; + this.value = value; + this.name = name; + this.facetId = facetId; + } + + public String getFacetId() + { + return facetId; + } + + public void setFacetId( String facetId ) + { + this.facetId = facetId; + } + + public String getId() + { + return id; + } + + public void setId( String id ) + { + this.id = id; + } + + public ArtifactMetadataModel getArtifactMetadataModel() + { + return artifactMetadataModel; + } + + public void setArtifactMetadataModel( ArtifactMetadataModel artifactMetadataModel ) + { + this.artifactMetadataModel = artifactMetadataModel; + } + + public String getName() + { + return name; + } + + public void setName( String name ) + { + this.name = name; + } + + public String getKey() + { + return key; + } + + public void setKey( String key ) + { + this.key = key; + } + + public String getValue() + { + return value; + } + + public void setValue( String value ) + { + this.value = value; + } + + @Override + public boolean equals( Object o ) + { + if ( this == o ) + { + return true; + } + if ( o == null || getClass() != o.getClass() ) + { + return false; + } + + MetadataFacetModel that = (MetadataFacetModel) o; + + if ( !id.equals( that.id ) ) + { + return false; + } + + return true; + } + + @Override + public int hashCode() + { + return id.hashCode(); + } + + @Override + public String toString() + { + final StringBuilder sb = new StringBuilder( "MetadataFacetModel{" ); + sb.append( "id='" ).append( id ).append( '\'' ); + sb.append( ", artifactMetadataModel=" ).append( artifactMetadataModel ); + sb.append( ", key='" ).append( key ).append( '\'' ); + sb.append( ", value='" ).append( value ).append( '\'' ); + sb.append( '}' ); + return sb.toString(); + } + + public static class KeyBuilder + { + + private ArtifactMetadataModel artifactMetadataModel; + + private String key; + + private String name; + + private String facetId; + + private String repositoryId; + + public KeyBuilder() + { + + } + + public KeyBuilder withArtifactMetadataModel( ArtifactMetadataModel artifactMetadataModel ) + { + this.artifactMetadataModel = artifactMetadataModel; + return this; + } + + public KeyBuilder withKey( String key ) + { + this.key = key; + return this; + } + + public KeyBuilder withName( String name ) + { + this.name = name; + return this; + } + + public KeyBuilder withFacetId( String facetId ) + { + this.facetId = facetId; + return this; + } + + public KeyBuilder withRepositoryId( String repositoryId ) + { + this.repositoryId = repositoryId; + return this; + } + + public String build() + { + // FIXME add some controls + // getArtifactMetadataModelId can have no namespace, no project and no projectid for statistics + // only repositoryId with artifactMetadataModel + return ( this.artifactMetadataModel == null + ? this.repositoryId + : this.artifactMetadataModel.getArtifactMetadataModelId() ) + "-" + this.facetId + "-" + this.name + "-" + + this.key; + } + } +} diff --git a/archiva-modules/plugins/metadata-store-cassandra/src/main/java/org/apache/archiva/metadata/repository/cassandra/model/Namespace.java b/archiva-modules/plugins/metadata-store-cassandra/src/main/java/org/apache/archiva/metadata/repository/cassandra/model/Namespace.java new file mode 100644 index 000000000..fb42b0b8d --- /dev/null +++ b/archiva-modules/plugins/metadata-store-cassandra/src/main/java/org/apache/archiva/metadata/repository/cassandra/model/Namespace.java @@ -0,0 +1,190 @@ +package org.apache.archiva.metadata.repository.cassandra.model; + +/* + * 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 javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import java.io.Serializable; + + +/** + * @author Olivier Lamy + */ +@Entity +//@Table( name = "namespace", schema = "ArchivaKeySpace@archiva") +public class Namespace + implements Serializable +{ + + private static final long serialVersionUID = 1L; + + @Id + @Column(name = "id") + private String id; + + @Column(name = "name") + private String name; + + @Column(name = "repository") + private Repository repository; + + //@ManyToOne(cascade = { CascadeType.ALL }, fetch = FetchType.EAGER) + //@JoinColumn(name = "repository_id") + //private transient Repository repository; + + + public Namespace() + { + // no op + } + + + public Namespace( String id, Repository repository ) + { + this.id = new KeyBuilder().withNamespace( id ).withRepositoryId( repository.getId() ).build(); + this.name = id; + this.repository = repository; + } + + public String getId() + { + return id; + } + + public void setId( String id ) + { + this.id = id; + } + + public String getName() + { + return name; + } + + public void setName( String name ) + { + this.name = name; + } + + public Repository getRepository() + { + return repository; + } + + public void setRepository( Repository repository ) + { + this.repository = repository; + } + + /* + public String getRepositoryId() + { + return repositoryId; + } + + public void setRepositoryId( String repositoryId ) + { + this.repositoryId = repositoryId; + }*/ + + @Override + public boolean equals( Object o ) + { + if ( this == o ) + { + return true; + } + if ( o == null || getClass() != o.getClass() ) + { + return false; + } + + Namespace namespace = (Namespace) o; + + if ( !id.equals( namespace.id ) ) + { + return false; + } + if ( !repository.getId().equals( namespace.repository.getId() ) ) + { + return false; + } + + return true; + } + + @Override + public int hashCode() + { + int result = id.hashCode(); + result = 31 * result + repository.getId().hashCode(); + return result; + } + + @Override + public String toString() + { + final StringBuilder sb = new StringBuilder( "Namespace{" ); + sb.append( "id='" ).append( id ).append( '\'' ); + sb.append( ", name='" ).append( name ).append( '\'' ); + sb.append( ", repository='" ).append( repository ).append( '\'' ); + sb.append( '}' ); + return sb.toString(); + } + + public static class KeyBuilder + { + + private String namespace; + + private String repositoryId; + + public KeyBuilder() + { + + } + + public KeyBuilder withNamespace( Namespace namespace ) + { + this.namespace = namespace.getName(); + this.repositoryId = namespace.getRepository().getId(); + return this; + } + + public KeyBuilder withNamespace( String namespace ) + { + this.namespace = namespace; + return this; + } + + public KeyBuilder withRepositoryId( String repositoryId ) + { + this.repositoryId = repositoryId; + return this; + } + + public String build() + { + // FIXME add some controls + return this.repositoryId + "-" + this.namespace; + } + } +} diff --git a/archiva-modules/plugins/metadata-store-cassandra/src/main/java/org/apache/archiva/metadata/repository/cassandra/model/Project.java b/archiva-modules/plugins/metadata-store-cassandra/src/main/java/org/apache/archiva/metadata/repository/cassandra/model/Project.java new file mode 100644 index 000000000..4a167a420 --- /dev/null +++ b/archiva-modules/plugins/metadata-store-cassandra/src/main/java/org/apache/archiva/metadata/repository/cassandra/model/Project.java @@ -0,0 +1,163 @@ +package org.apache.archiva.metadata.repository.cassandra.model; + +/* + * 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 javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import java.io.Serializable; + +/** + * @author Olivier Lamy + */ +@Entity +public class Project + implements Serializable +{ + @Id + @Column( name = "projectKey" ) + private String projectKey; + + @Column( name = "projectId" ) + private String projectId; + + + @Column( name = "repository" ) + private Namespace namespace; + + public Project() + { + // no op + } + + public Project( String projectKey, String projectId, Namespace namespace ) + { + this.projectId = projectId; + this.projectKey = projectKey; + this.namespace = namespace; + } + + public String getProjectKey() + { + return projectKey; + } + + public void setProjectKey( String projectKey ) + { + this.projectKey = projectKey; + } + + public Namespace getNamespace() + { + return namespace; + } + + public void setNamespace( Namespace namespace ) + { + this.namespace = namespace; + } + + public String getProjectId() + { + return projectId; + } + + public void setProjectId( String projectId ) + { + this.projectId = projectId; + } + + @Override + public boolean equals( Object o ) + { + if ( this == o ) + { + return true; + } + if ( o == null || getClass() != o.getClass() ) + { + return false; + } + + Project project = (Project) o; + + if ( !projectKey.equals( project.projectKey ) ) + { + return false; + } + if ( !namespace.equals( project.namespace ) ) + { + return false; + } + + return true; + } + + @Override + public int hashCode() + { + int result = projectKey.hashCode(); + result = 31 * result + namespace.hashCode(); + return result; + } + + @Override + public String toString() + { + final StringBuilder sb = new StringBuilder( "Project{" ); + sb.append( "projectKey='" ).append( projectKey ).append( '\'' ); + sb.append( ", projectId='" ).append( projectId ).append( '\'' ); + sb.append( ", namespace=" ).append( namespace ); + sb.append( '}' ); + return sb.toString(); + } + + public static class KeyBuilder + { + + private Namespace namespace; + + private String projectId; + + public KeyBuilder() + { + // no op + } + + public KeyBuilder withNamespace( Namespace namespace ) + { + this.namespace = namespace; + return this; + } + + public KeyBuilder withProjectId( String projectId ) + { + this.projectId = projectId; + return this; + } + + + public String build() + { + // FIXME add some controls + return new Namespace.KeyBuilder().withNamespace( this.namespace ).build() + "-" + this.projectId; + } + } +} diff --git a/archiva-modules/plugins/metadata-store-cassandra/src/main/java/org/apache/archiva/metadata/repository/cassandra/model/ProjectVersionMetadataModel.java b/archiva-modules/plugins/metadata-store-cassandra/src/main/java/org/apache/archiva/metadata/repository/cassandra/model/ProjectVersionMetadataModel.java new file mode 100644 index 000000000..aaa9fc41e --- /dev/null +++ b/archiva-modules/plugins/metadata-store-cassandra/src/main/java/org/apache/archiva/metadata/repository/cassandra/model/ProjectVersionMetadataModel.java @@ -0,0 +1,354 @@ +package org.apache.archiva.metadata.repository.cassandra.model; + +/* + * 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.metadata.model.CiManagement; +import org.apache.archiva.metadata.model.Dependency; +import org.apache.archiva.metadata.model.IssueManagement; +import org.apache.archiva.metadata.model.License; +import org.apache.archiva.metadata.model.MailingList; +import org.apache.archiva.metadata.model.Organization; +import org.apache.archiva.metadata.model.Scm; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import java.util.ArrayList; +import java.util.List; + +/** + * @author Olivier Lamy + */ +@Entity +public class ProjectVersionMetadataModel +{ + // repositoryId + namespace + projectId + id (version) + @Id + private String rowId; + + @Column( name = "namespace" ) + private Namespace namespace; + + /** + * id is the version + */ + @Column( name = "id" ) + private String id; + + @Column( name = "projectId" ) + private String projectId; + + @Column(name = "url") + private String url; + + @Column(name = "name") + private String name; + + @Column(name = "description") + private String description; + + @Column(name = "organization") + private Organization organization; + + @Column(name = "issueManagement") + private IssueManagement issueManagement; + + @Column(name = "scm") + private Scm scm; + + @Column(name = "ciManagement") + private CiManagement ciManagement; + + // FIXME store those values in a separate table + @Column(name = "licenses") + private List licenses = new ArrayList(); + + @Column(name = "mailingLists") + private List mailingLists = new ArrayList(); + + @Column(name = "dependencies") + private List dependencies = new ArrayList(); + + @Column(name = "incomplete") + private boolean incomplete; + + public String getProjectId() + { + return projectId; + } + + public void setProjectId( String projectId ) + { + this.projectId = projectId; + } + + public String getRowId() + { + return rowId; + } + + public void setRowId( String rowId ) + { + this.rowId = rowId; + } + + // FIXME must be renamed getVersion !!! + public String getId() + { + return id; + } + + public void setId( String id ) + { + this.id = id; + } + + public String getUrl() + { + return url; + } + + public void setUrl( String url ) + { + this.url = url; + } + + public String getName() + { + return name; + } + + public void setName( String name ) + { + this.name = name; + } + + public String getDescription() + { + return description; + } + + public void setDescription( String description ) + { + this.description = description; + } + + public Organization getOrganization() + { + return organization; + } + + public void setOrganization( Organization organization ) + { + this.organization = organization; + } + + public IssueManagement getIssueManagement() + { + return issueManagement; + } + + public void setIssueManagement( IssueManagement issueManagement ) + { + this.issueManagement = issueManagement; + } + + public Scm getScm() + { + return scm; + } + + public void setScm( Scm scm ) + { + this.scm = scm; + } + + public CiManagement getCiManagement() + { + return ciManagement; + } + + public void setCiManagement( CiManagement ciManagement ) + { + this.ciManagement = ciManagement; + } + + public boolean isIncomplete() + { + return incomplete; + } + + public void setIncomplete( boolean incomplete ) + { + this.incomplete = incomplete; + } + + public Namespace getNamespace() + { + return namespace; + } + + public void setNamespace( Namespace namespace ) + { + this.namespace = namespace; + } + + public List getLicenses() + { + return licenses; + } + + public void setLicenses( List licenses ) + { + this.licenses = licenses; + } + + public List getMailingLists() + { + return mailingLists; + } + + public void setMailingLists( List mailingLists ) + { + this.mailingLists = mailingLists; + } + + public List getDependencies() + { + return dependencies; + } + + public void setDependencies( List dependencies ) + { + this.dependencies = dependencies; + } + + + @Override + public String toString() + { + final StringBuilder sb = new StringBuilder( "ProjectVersionMetadataModel{" ); + sb.append( "rowId='" ).append( rowId ).append( '\'' ); + sb.append( ", namespace=" ).append( namespace ); + sb.append( ", id='" ).append( id ).append( '\'' ); + sb.append( ", projectId='" ).append( projectId ).append( '\'' ); + sb.append( ", url='" ).append( url ).append( '\'' ); + sb.append( ", name='" ).append( name ).append( '\'' ); + sb.append( ", description='" ).append( description ).append( '\'' ); + sb.append( ", organization=" ).append( organization ); + sb.append( ", issueManagement=" ).append( issueManagement ); + sb.append( ", scm=" ).append( scm ); + sb.append( ", ciManagement=" ).append( ciManagement ); + sb.append( ", incomplete=" ).append( incomplete ); + sb.append( '}' ); + return sb.toString(); + } + + @Override + public boolean equals( Object o ) + { + if ( this == o ) + { + return true; + } + if ( o == null || getClass() != o.getClass() ) + { + return false; + } + + ProjectVersionMetadataModel that = (ProjectVersionMetadataModel) o; + + if ( !rowId.equals( that.rowId ) ) + { + return false; + } + + return true; + } + + + @Override + public int hashCode() + { + return rowId.hashCode(); + } + + public static class KeyBuilder + { + + private String namespace; + + private String repositoryId; + + private String projectId; + + private String id; + + public KeyBuilder() + { + + } + + public KeyBuilder withNamespace( Namespace namespace ) + { + this.namespace = namespace.getName(); + this.repositoryId = namespace.getRepository().getId(); + return this; + } + + public KeyBuilder withNamespace( String namespace ) + { + this.namespace = namespace; + return this; + } + + public KeyBuilder withRepository( String repositoryId ) + { + this.repositoryId = repositoryId; + return this; + } + + public KeyBuilder withRepository( Repository repository ) + { + this.repositoryId = repository.getId(); + return this; + } + + public KeyBuilder withProjectId( String projectId ) + { + this.projectId = projectId; + return this; + } + + public KeyBuilder withId( String id ) + { + this.id = id; + return this; + } + + public String build() + { + // FIXME add some controls + return this.repositoryId + "-" + this.namespace + "-" + this.projectId + ( this.id == null + ? "" + : "-" + this.id ); + } + } +} diff --git a/archiva-modules/plugins/metadata-store-cassandra/src/main/java/org/apache/archiva/metadata/repository/cassandra/model/Repository.java b/archiva-modules/plugins/metadata-store-cassandra/src/main/java/org/apache/archiva/metadata/repository/cassandra/model/Repository.java new file mode 100644 index 000000000..25f8281da --- /dev/null +++ b/archiva-modules/plugins/metadata-store-cassandra/src/main/java/org/apache/archiva/metadata/repository/cassandra/model/Repository.java @@ -0,0 +1,136 @@ +package org.apache.archiva.metadata.repository.cassandra.model; + +/* + * 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 javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + + +/** + * @author Olivier Lamy + */ +@Entity +@Table(name = "repository", schema = "ArchivaKeySpace@archiva") +public class Repository + implements Serializable +{ + + private static final long serialVersionUID = 1L; + + @Id + @Column( name = "id" ) + private String id; + + @Column(name = "name") + private String name; + + private transient List namespaces = new ArrayList(); + + public Repository() + { + // no op + } + + public Repository( String id ) + { + this.id = id; + this.name = id; + } + + public String getId() + { + return id; + } + + public void setId( String id ) + { + this.id = id; + } + + public String getName() + { + return name; + } + + public void setName( String name ) + { + this.name = name; + } + + + public List getNamespaces() + { + if ( this.namespaces == null ) + { + this.namespaces = new ArrayList(); + } + return namespaces; + } + + public void setNamespaces( List namespaces ) + { + this.namespaces = namespaces; + } + + @Override + public boolean equals( Object o ) + { + if ( this == o ) + { + return true; + } + if ( o == null || getClass() != o.getClass() ) + { + return false; + } + + Repository that = (Repository) o; + + if ( !id.equals( that.id ) ) + { + return false; + } + + return true; + } + + @Override + public int hashCode() + { + return id.hashCode(); + } + + + @Override + public String toString() + { + final StringBuilder sb = new StringBuilder( "Repository{" ); + sb.append( "id='" ).append( id ).append( '\'' ); + sb.append( ", name='" ).append( name ).append( '\'' ); + sb.append( ", namespaces=" ).append( namespaces ); + sb.append( '}' ); + return sb.toString(); + } +} diff --git a/archiva-modules/plugins/metadata-store-cassandra/src/main/resources/META-INF/spring-context.xml b/archiva-modules/plugins/metadata-store-cassandra/src/main/resources/META-INF/spring-context.xml new file mode 100644 index 000000000..e1c2c24bb --- /dev/null +++ b/archiva-modules/plugins/metadata-store-cassandra/src/main/resources/META-INF/spring-context.xml @@ -0,0 +1,33 @@ + + + + + + + + + \ No newline at end of file diff --git a/archiva-modules/plugins/metadata-store-cassandra/src/test/filtered-resources/META-INF/spring-context.xml b/archiva-modules/plugins/metadata-store-cassandra/src/test/filtered-resources/META-INF/spring-context.xml new file mode 100644 index 000000000..74bb0240f --- /dev/null +++ b/archiva-modules/plugins/metadata-store-cassandra/src/test/filtered-resources/META-INF/spring-context.xml @@ -0,0 +1,25 @@ + + + + + + \ No newline at end of file diff --git a/archiva-modules/plugins/metadata-store-cassandra/src/test/java/org/apache/archiva/metadata/repository/cassandra/CassandraMetadataRepositoryTest.java b/archiva-modules/plugins/metadata-store-cassandra/src/test/java/org/apache/archiva/metadata/repository/cassandra/CassandraMetadataRepositoryTest.java new file mode 100644 index 000000000..bdf303fe5 --- /dev/null +++ b/archiva-modules/plugins/metadata-store-cassandra/src/test/java/org/apache/archiva/metadata/repository/cassandra/CassandraMetadataRepositoryTest.java @@ -0,0 +1,113 @@ +package org.apache.archiva.metadata.repository.cassandra; + +/* + * 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.metadata.model.MetadataFacetFactory; +import org.apache.archiva.metadata.repository.AbstractMetadataRepositoryTest; +import org.apache.archiva.metadata.repository.cassandra.model.ArtifactMetadataModel; +import org.apache.archiva.metadata.repository.cassandra.model.MetadataFacetModel; +import org.apache.archiva.metadata.repository.cassandra.model.Namespace; +import org.apache.archiva.metadata.repository.cassandra.model.Project; +import org.apache.archiva.metadata.repository.cassandra.model.ProjectVersionMetadataModel; +import org.apache.archiva.metadata.repository.cassandra.model.Repository; +import org.apache.commons.io.FileUtils; +import org.junit.After; +import org.junit.Before; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.inject.Inject; +import javax.inject.Named; +import java.io.File; +import java.util.List; +import java.util.Map; + +/** + * @author Olivier Lamy + */ +public class CassandraMetadataRepositoryTest + extends AbstractMetadataRepositoryTest +{ + private Logger logger = LoggerFactory.getLogger( getClass() ); + + @Inject + @Named( value = "archivaEntityManagerFactory#cassandra" ) + CassandraEntityManagerFactory cassandraEntityManagerFactory; + + CassandraMetadataRepository cmr; + + @Before + public void setUp() + throws Exception + { + super.setUp(); + + File directory = new File( "target/test-repositories" ); + if ( directory.exists() ) + { + FileUtils.deleteDirectory( directory ); + } + + Map factories = createTestMetadataFacetFactories(); + + this.cmr = new CassandraMetadataRepository( factories, null, cassandraEntityManagerFactory.getKeyspace() ); + this.repository = this.cmr; + + clearReposAndNamespace(); + } + + + @After + public void shutdown() + throws Exception + { + clearReposAndNamespace(); + super.tearDown(); + } + + protected void clearReposAndNamespace() + throws Exception + { + List projects = cmr.getProjectEntityManager().getAll(); + + cmr.getProjectEntityManager().remove( projects ); + + List namespaces = cmr.getNamespaceEntityManager().getAll(); + + cmr.getNamespaceEntityManager().remove( namespaces ); + + List repositories = cmr.getRepositoryEntityManager().getAll(); + + cmr.getRepositoryEntityManager().remove( repositories ); + + List artifactMetadataModels = cmr.getArtifactMetadataModelEntityManager().getAll(); + cmr.getArtifactMetadataModelEntityManager().remove( artifactMetadataModels ); + + List metadataFacetModels = cmr.getMetadataFacetModelEntityManager().getAll(); + cmr.getMetadataFacetModelEntityManager().remove( metadataFacetModels ); + + List projectVersionMetadataModels = + cmr.getProjectVersionMetadataModelEntityManager().getAll(); + cmr.getProjectVersionMetadataModelEntityManager().remove( projectVersionMetadataModels ); + + + } + +} diff --git a/archiva-modules/plugins/metadata-store-cassandra/src/test/java/org/apache/archiva/metadata/repository/cassandra/RepositoriesNamespaceTest.java b/archiva-modules/plugins/metadata-store-cassandra/src/test/java/org/apache/archiva/metadata/repository/cassandra/RepositoriesNamespaceTest.java new file mode 100644 index 000000000..2edffd9c5 --- /dev/null +++ b/archiva-modules/plugins/metadata-store-cassandra/src/test/java/org/apache/archiva/metadata/repository/cassandra/RepositoriesNamespaceTest.java @@ -0,0 +1,133 @@ +package org.apache.archiva.metadata.repository.cassandra; + +/* + * 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.metadata.repository.cassandra.model.Namespace; +import org.apache.archiva.metadata.repository.cassandra.model.Project; +import org.apache.archiva.metadata.repository.cassandra.model.Repository; +import org.apache.archiva.test.utils.ArchivaSpringJUnit4ClassRunner; +import org.fest.assertions.api.Assertions; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.test.context.ContextConfiguration; + +import javax.inject.Inject; +import javax.inject.Named; +import java.util.List; + +/** + * @author Olivier Lamy + */ +@RunWith(ArchivaSpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = { "classpath*:/META-INF/spring-context.xml", "classpath*:/spring-context.xml" }) +public class RepositoriesNamespaceTest +{ + + private Logger logger = LoggerFactory.getLogger( getClass() ); + + @Inject + @Named(value = "archivaEntityManagerFactory#cassandra") + CassandraEntityManagerFactory cassandraEntityManagerFactory; + + + CassandraMetadataRepository cmr; + + @Before + public void setup() + throws Exception + { + + cmr = new CassandraMetadataRepository( null, null, cassandraEntityManagerFactory.getKeyspace() ); + clearReposAndNamespace(); + + } + + @After + public void shutdown() + throws Exception + { + clearReposAndNamespace(); + } + + + @Test + public void testMetadataRepo() + throws Exception + { + + Repository r = null; + Namespace n = null; + + try + { + + cmr.updateNamespace( "release", "org" ); + + r = cmr.getRepositoryEntityManager().get( "release" ); + + Assertions.assertThat( r ).isNotNull(); + + Assertions.assertThat( cmr.getRepositories() ).isNotEmpty().hasSize( 1 ); + Assertions.assertThat( cmr.getNamespaces( "release" ) ).isNotEmpty().hasSize( 1 ); + + n = cmr.getNamespaceEntityManager().get( "release" + "-" + "org" ); + + Assertions.assertThat( n ).isNotNull(); + Assertions.assertThat( n.getRepository() ).isNotNull(); + + cmr.updateNamespace( "release", "org.apache" ); + + r = cmr.getRepositoryEntityManager().get( "release" ); + + Assertions.assertThat( r ).isNotNull(); + Assertions.assertThat( cmr.getNamespaces( "release" ) ).isNotEmpty().hasSize( 2 ); + } + catch ( Exception e ) + { + logger.error( e.getMessage(), e ); + throw e; + } + finally + { + clearReposAndNamespace(); + } + } + + protected void clearReposAndNamespace() + throws Exception + { + List projects = cmr.getProjectEntityManager().getAll(); + + cmr.getProjectEntityManager().remove( projects ); + + List namespaces = cmr.getNamespaceEntityManager().getAll(); + + cmr.getNamespaceEntityManager().remove( namespaces ); + + List repositories = cmr.getRepositoryEntityManager().getAll(); + + cmr.getRepositoryEntityManager().remove( repositories ); + + } +} diff --git a/archiva-modules/plugins/metadata-store-cassandra/src/test/resources/log4j2-test.xml b/archiva-modules/plugins/metadata-store-cassandra/src/test/resources/log4j2-test.xml new file mode 100644 index 000000000..eda946883 --- /dev/null +++ b/archiva-modules/plugins/metadata-store-cassandra/src/test/resources/log4j2-test.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 2.39.5