1 package org.apache.archiva.metadata.repository.cassandra;
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
22 import com.google.common.collect.ImmutableMap;
23 import com.netflix.astyanax.AstyanaxContext;
24 import com.netflix.astyanax.Keyspace;
25 import com.netflix.astyanax.connectionpool.NodeDiscoveryType;
26 import com.netflix.astyanax.connectionpool.exceptions.ConnectionException;
27 import com.netflix.astyanax.connectionpool.exceptions.NotFoundException;
28 import com.netflix.astyanax.connectionpool.impl.ConnectionPoolConfigurationImpl;
29 import com.netflix.astyanax.connectionpool.impl.ConnectionPoolType;
30 import com.netflix.astyanax.connectionpool.impl.Slf4jConnectionPoolMonitorImpl;
31 import com.netflix.astyanax.ddl.KeyspaceDefinition;
32 import com.netflix.astyanax.entitystore.DefaultEntityManager;
33 import com.netflix.astyanax.entitystore.EntityManager;
34 import com.netflix.astyanax.impl.AstyanaxConfigurationImpl;
35 import com.netflix.astyanax.thrift.ThriftFamilyFactory;
36 import org.apache.archiva.metadata.repository.cassandra.model.ArtifactMetadataModel;
37 import org.apache.archiva.metadata.repository.cassandra.model.MetadataFacetModel;
38 import org.apache.archiva.metadata.repository.cassandra.model.Namespace;
39 import org.apache.archiva.metadata.repository.cassandra.model.Project;
40 import org.apache.archiva.metadata.repository.cassandra.model.ProjectVersionMetadataModel;
41 import org.apache.archiva.metadata.repository.cassandra.model.Repository;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44 import org.springframework.context.ApplicationContext;
45 import org.springframework.stereotype.Service;
47 import javax.annotation.PostConstruct;
48 import javax.annotation.PreDestroy;
49 import javax.inject.Inject;
50 import javax.persistence.PersistenceException;
51 import java.util.Properties;
54 * FIXME make all configuration not hardcoded :-)
56 * @author Olivier Lamy
59 @Service( "archivaEntityManagerFactory#cassandra" )
60 public class DefaultCassandraEntityManagerFactory
61 implements CassandraEntityManagerFactory
64 private Logger logger = LoggerFactory.getLogger( getClass() );
67 private ApplicationContext applicationContext;
69 private static final String CLUSTER_NAME = "archiva";
71 private static final String KEYSPACE_NAME = "ArchivaKeySpace";
73 private AstyanaxContext<Keyspace> keyspaceContext;
75 private Keyspace keyspace;
77 private boolean started = false;
79 private EntityManager<Repository, String> repositoryEntityManager;
81 private EntityManager<Namespace, String> namespaceEntityManager;
83 private EntityManager<Project, String> projectEntityManager;
85 private EntityManager<ArtifactMetadataModel, String> artifactMetadataModelEntityManager;
87 private EntityManager<MetadataFacetModel, String> metadataFacetModelEntityManager;
89 private EntityManager<ProjectVersionMetadataModel, String> projectVersionMetadataModelEntityManager;
93 public void initialize()
94 throws ConnectionException
96 String cassandraHost = System.getProperty( "cassandraHost", "localhost" );
97 String cassandraPort = System.getProperty( "cassandraPort" );
98 keyspaceContext = new AstyanaxContext.Builder().forCluster( CLUSTER_NAME ).forKeyspace(
99 KEYSPACE_NAME ).withAstyanaxConfiguration(
100 new AstyanaxConfigurationImpl().setDiscoveryType( NodeDiscoveryType.RING_DESCRIBE ).setConnectionPoolType(
101 ConnectionPoolType.TOKEN_AWARE ) ).withConnectionPoolConfiguration(
102 new ConnectionPoolConfigurationImpl( CLUSTER_NAME + "_" + KEYSPACE_NAME ).setSocketTimeout(
103 30000 ).setMaxTimeoutWhenExhausted( 2000 ).setMaxConnsPerHost( 20 ).setInitConnsPerHost( 10 ).setSeeds(
104 cassandraHost + ":" + cassandraPort ) ).withConnectionPoolMonitor(
105 new Slf4jConnectionPoolMonitorImpl() ).buildKeyspace( ThriftFamilyFactory.getInstance() );
109 keyspace = keyspaceContext.getClient();
110 //Partitioner partitioner = keyspace.getPartitioner();
112 ImmutableMap<String, Object> options = ImmutableMap.<String, Object>builder().put( "strategy_options",
113 ImmutableMap.<String, Object>builder().put(
114 "replication_factor",
116 "strategy_class", "SimpleStrategy" ).build();
118 // test if the namespace already exists if exception or null create it
119 boolean keyspaceExists = false;
122 KeyspaceDefinition keyspaceDefinition = keyspace.describeKeyspace();
123 if ( keyspaceDefinition != null )
125 keyspaceExists = true;
129 catch ( ConnectionException e )
133 if ( !keyspaceExists )
135 keyspace.createKeyspace( options );
140 Properties properties = keyspace.getKeyspaceProperties();
141 logger.info( "keyspace properties: {}", properties );
143 catch ( ConnectionException e )
145 // FIXME better logging !
146 logger.warn( e.getMessage(), e );
151 repositoryEntityManager =
152 new DefaultEntityManager.Builder<Repository, String>().withEntityType( Repository.class ).withKeyspace(
153 keyspace ).withAutoCommit( true ).build();
154 boolean exists = columnFamilyExists( "repository" );
155 // TODO very basic test we must test model change too
158 repositoryEntityManager.createStorage( null );
161 namespaceEntityManager =
162 new DefaultEntityManager.Builder<Namespace, String>().withEntityType( Namespace.class ).withKeyspace(
163 keyspace ).withAutoCommit( true ).build();
165 exists = columnFamilyExists( "namespace" );
168 namespaceEntityManager.createStorage( null );
171 projectEntityManager =
172 new DefaultEntityManager.Builder<Project, String>().withEntityType( Project.class ).withKeyspace(
173 keyspace ).withAutoCommit( true ).build();
175 exists = columnFamilyExists( "project" );
178 projectEntityManager.createStorage( null );
181 artifactMetadataModelEntityManager =
182 new DefaultEntityManager.Builder<ArtifactMetadataModel, String>().withEntityType(
183 ArtifactMetadataModel.class ).withAutoCommit( true ).withKeyspace( keyspace ).build();
185 exists = columnFamilyExists( "artifactmetadatamodel" );
188 artifactMetadataModelEntityManager.createStorage( null );
191 metadataFacetModelEntityManager =
192 new DefaultEntityManager.Builder<MetadataFacetModel, String>().withEntityType(
193 MetadataFacetModel.class ).withAutoCommit( true ).withKeyspace( keyspace ).build();
195 exists = columnFamilyExists( "metadatafacetmodel" );
198 metadataFacetModelEntityManager.createStorage( null );
201 projectVersionMetadataModelEntityManager =
202 new DefaultEntityManager.Builder<ProjectVersionMetadataModel, String>().withEntityType(
203 ProjectVersionMetadataModel.class ).withAutoCommit( true ).withKeyspace( keyspace ).build();
205 exists = columnFamilyExists( "projectversionmetadatamodel" );
208 projectVersionMetadataModelEntityManager.createStorage( null );
212 catch ( PersistenceException e )
214 // FIXME report exception
215 logger.error( e.getMessage(), e );
217 catch ( ConnectionException e )
219 // FIXME report exception
220 logger.error( e.getMessage(), e );
226 keyspaceContext.start();
231 public void shutdown()
233 if ( keyspaceContext != null )
235 keyspaceContext.shutdown();
242 public boolean started()
247 private boolean columnFamilyExists( String columnFamilyName )
248 throws ConnectionException
252 Properties properties = keyspace.getColumnFamilyProperties( columnFamilyName );
253 logger.debug( "getColumnFamilyProperties for {}: {}", columnFamilyName, properties );
256 catch ( NotFoundException e )
264 public Keyspace getKeyspace()
269 public EntityManager<Repository, String> getRepositoryEntityManager()
271 return repositoryEntityManager;
274 public void setRepositoryEntityManager( EntityManager<Repository, String> repositoryEntityManager )
276 this.repositoryEntityManager = repositoryEntityManager;
279 public EntityManager<Namespace, String> getNamespaceEntityManager()
281 return namespaceEntityManager;
284 public void setNamespaceEntityManager( EntityManager<Namespace, String> namespaceEntityManager )
286 this.namespaceEntityManager = namespaceEntityManager;
289 public EntityManager<Project, String> getProjectEntityManager()
291 return projectEntityManager;
294 public void setProjectEntityManager( EntityManager<Project, String> projectEntityManager )
296 this.projectEntityManager = projectEntityManager;
299 public EntityManager<ArtifactMetadataModel, String> getArtifactMetadataModelEntityManager()
301 return artifactMetadataModelEntityManager;
304 public void setArtifactMetadataModelEntityManager(
305 EntityManager<ArtifactMetadataModel, String> artifactMetadataModelEntityManager )
307 this.artifactMetadataModelEntityManager = artifactMetadataModelEntityManager;
310 public EntityManager<MetadataFacetModel, String> getMetadataFacetModelEntityManager()
312 return metadataFacetModelEntityManager;
315 public void setMetadataFacetModelEntityManager(
316 EntityManager<MetadataFacetModel, String> metadataFacetModelEntityManager )
318 this.metadataFacetModelEntityManager = metadataFacetModelEntityManager;
321 public EntityManager<ProjectVersionMetadataModel, String> getProjectVersionMetadataModelEntityManager()
323 return projectVersionMetadataModelEntityManager;
326 public void setProjectVersionMetadataModelEntityManager(
327 EntityManager<ProjectVersionMetadataModel, String> projectVersionMetadataModelEntityManager )
329 this.projectVersionMetadataModelEntityManager = projectVersionMetadataModelEntityManager;