POLYGENE-225 - Cassandra entitystore implemented.
Project: http://git-wip-us.apache.org/repos/asf/polygene-java/repo Commit: http://git-wip-us.apache.org/repos/asf/polygene-java/commit/c86b1154 Tree: http://git-wip-us.apache.org/repos/asf/polygene-java/tree/c86b1154 Diff: http://git-wip-us.apache.org/repos/asf/polygene-java/diff/c86b1154 Branch: refs/heads/develop Commit: c86b1154e820d197516ace8da63d077d2f79f5b8 Parents: 96d03df Author: niclas <[email protected]> Authored: Tue Feb 14 12:44:48 2017 +0800 Committer: niclas <[email protected]> Committed: Tue Feb 14 12:44:48 2017 +0800 ---------------------------------------------------------------------- dependencies.gradle | 3 + extensions/entitystore-cassandra/build.gradle | 38 ++ extensions/entitystore-cassandra/dev-status.xml | 38 ++ .../entitystore/cassandra/CassandraCluster.java | 213 ++++++++++ .../CassandraEntityStoreConfiguration.java | 50 +++ .../cassandra/CassandraEntityStoreMixin.java | 425 +++++++++++++++++++ .../cassandra/CassandraEntityStoreService.java | 48 +++ .../cassandra/CassandraMigration.java | 28 ++ .../CassandraDBEntityStoreAssembler.java | 46 ++ .../polygene/entitystore/cassandra/package.html | 43 ++ .../cassandra/CassandraMapEntityStoreTest.java | 89 ++++ .../cassandra/EmptyCassandraTableMixin.java | 20 + .../src/main/docker/cassandra/Dockerfile | 16 + settings.gradle | 4 +- tools/shell/build.gradle | 39 -- tools/shell/dev-status.xml | 38 -- .../create/project/NullProjectCreator.java | 37 -- 17 files changed, 1059 insertions(+), 116 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/polygene-java/blob/c86b1154/dependencies.gradle ---------------------------------------------------------------------- diff --git a/dependencies.gradle b/dependencies.gradle index 6f6f0b9..4a00547 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -41,6 +41,7 @@ dependencies.libraries << [ // Extensions, Libraries and Tools dependencies def bonecpVersion = '0.8.0.RELEASE' def bouncyVersion = '1.55' +def cassandraClientVersion = '3.1.3' def codahaleMetricsVersion = '3.1.2' def commonsDbcpVersion = '2.1.1' def commonsLangVersion = '3.5' @@ -77,6 +78,8 @@ def velocityVersion = '1.7' dependencies.libraries << [ bonecp : "com.jolbox:bonecp:$bonecpVersion", bouncy_castle : "org.bouncycastle:bcprov-jdk15on:$bouncyVersion", + cassandra_client : [ "com.datastax.cassandra:cassandra-driver-core:$cassandraClientVersion", + ], codahale_metrics : [ "io.dropwizard.metrics:metrics-core:$codahaleMetricsVersion", "io.dropwizard.metrics:metrics-healthchecks:$codahaleMetricsVersion" ], commons_dbcp : "org.apache.commons:commons-dbcp2:$commonsDbcpVersion", http://git-wip-us.apache.org/repos/asf/polygene-java/blob/c86b1154/extensions/entitystore-cassandra/build.gradle ---------------------------------------------------------------------- diff --git a/extensions/entitystore-cassandra/build.gradle b/extensions/entitystore-cassandra/build.gradle new file mode 100644 index 0000000..2fb41a2 --- /dev/null +++ b/extensions/entitystore-cassandra/build.gradle @@ -0,0 +1,38 @@ +/* + * 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. + * + * + */ + +apply plugin: 'polygene-extension' + +description = "Apache Polygene⢠Cassandra EntityStore Extension" + +jar { manifest { name = "Apache Polygene⢠Extension - EntityStore - Cassandra" } } + +dependencies { + compile polygene.core.bootstrap + compile polygene.library( 'locking' ) + compile libraries.cassandra_client + + runtime polygene.core.runtime + + testCompile polygene.internals.testsupport + testCompile polygene.extension( 'valueserialization-orgjson' ) + + testRuntime libraries.logback +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/c86b1154/extensions/entitystore-cassandra/dev-status.xml ---------------------------------------------------------------------- diff --git a/extensions/entitystore-cassandra/dev-status.xml b/extensions/entitystore-cassandra/dev-status.xml new file mode 100644 index 0000000..fcc2930 --- /dev/null +++ b/extensions/entitystore-cassandra/dev-status.xml @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!-- + ~ 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. + ~ + ~ + --> +<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1 + http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd"> + <status> + <!--none,early,beta,stable,mature--> + <codebase>beta</codebase> + + <!-- none, brief, good, complete --> + <documentation>none</documentation> + + <!-- none, some, good, complete --> + <unittests>good</unittests> + </status> + <licenses> + <license>ALv2</license> + </licenses> +</module> http://git-wip-us.apache.org/repos/asf/polygene-java/blob/c86b1154/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/CassandraCluster.java ---------------------------------------------------------------------- diff --git a/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/CassandraCluster.java b/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/CassandraCluster.java new file mode 100644 index 0000000..c5bcf72 --- /dev/null +++ b/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/CassandraCluster.java @@ -0,0 +1,213 @@ +/* + * 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. + * + * + */ +package org.apache.polygene.entitystore.cassandra; + +import com.datastax.driver.core.Cluster; +import com.datastax.driver.core.KeyspaceMetadata; +import com.datastax.driver.core.PreparedStatement; +import com.datastax.driver.core.Session; +import org.apache.polygene.api.configuration.Configuration; +import org.apache.polygene.api.injection.scope.This; +import org.apache.polygene.api.mixin.Mixins; +import org.apache.polygene.api.service.ServiceActivation; + +@Mixins( CassandraCluster.Mixin.class ) +public interface CassandraCluster +{ + String CURRENT_STORAGE_VERSION = "1"; + String DEFAULT_KEYSPACE_NAME = "polygene:entitystore"; + String DEFAULT_TABLE_NAME = "polygene:entitystore:entities"; + String IDENTITY_COLUMN = "_id"; + String VERSION_COLUMN = "_version"; + String USECASE_COLUMN = "_usecase"; + String LASTMODIFIED_COLUMN = "_modified"; + String APP_VERSION_COLUMN = "_appversion"; + String STORE_VERSION_COLUMN = "_storeversion"; + String TYPE_COLUMN = "_type"; + String PROPERTIES_COLUMN = "_props"; + String ASSOCIATIONS_COLUMN = "_assocs"; + String MANYASSOCIATIONS_COLUMN = "_manyassocs"; + String NAMEDASSOCIATIONS_COLUMN = "_namedassocs"; + + Session session(); + + String tableName(); + + PreparedStatement entityRetrieveStatement(); + PreparedStatement versionRetrieveStatement(); + PreparedStatement entityUpdateStatement(); + + String keyspaceName(); + + class Mixin + implements ServiceActivation, CassandraCluster + { + @This + private Configuration<CassandraEntityStoreConfiguration> configuration; + + private Cluster cluster; + private Session session; + private String keyspaceName; + private PreparedStatement getEntityStatement; + private PreparedStatement updateEntityStatement; + private PreparedStatement getVersionStatement; + + @Override + public Session session() + { + return session; + } + + @Override + public PreparedStatement entityRetrieveStatement() + { + return getEntityStatement; + } + + @Override + public PreparedStatement versionRetrieveStatement() + { + return getVersionStatement; + } + + @Override + public PreparedStatement entityUpdateStatement() + { + return updateEntityStatement; + } + + @Override + public String keyspaceName() + { + return keyspaceName; + } + + public String tableName( ) + { + CassandraEntityStoreConfiguration config = configuration.get(); + String tableName = config.table().get(); + if( tableName == null ) + { + tableName = DEFAULT_TABLE_NAME; + } + return tableName; + } + + @Override + public void activateService() + throws Exception + { + configuration.refresh(); + CassandraEntityStoreConfiguration config = configuration.get(); + + String[] hostNames = config.hostnames().get().split( "," ); + Cluster.Builder builder = + Cluster.builder() + .withClusterName( "myCluster" ) + .addContactPoints( hostNames ) + .withCredentials( config.username().get(), config.password().get() ); + cluster = builder.build(); + keyspaceName = config.keySpace().get(); + if( keyspaceName == null ) + { + keyspaceName = DEFAULT_KEYSPACE_NAME; + } + String tableName = tableName(); + KeyspaceMetadata keyspace = cluster.getMetadata().getKeyspace( keyspaceName ); + if( keyspace == null ) + { + createKeyspace( keyspaceName, config.replicationFactor().get() ); + session = cluster.connect( keyspaceName ); + createPolygeneStateTable( tableName ); + } + else + { + session = cluster.connect( keyspaceName ); + } + session.init(); + + getEntityStatement = session.prepare( "SELECT " + + IDENTITY_COLUMN + ", " + + VERSION_COLUMN + ", " + + APP_VERSION_COLUMN + ", " + + STORE_VERSION_COLUMN + ", " + + LASTMODIFIED_COLUMN + ", " + + USECASE_COLUMN + ", " + + PROPERTIES_COLUMN + ", " + + ASSOCIATIONS_COLUMN + ", " + + MANYASSOCIATIONS_COLUMN + ", " + + NAMEDASSOCIATIONS_COLUMN + + " FROM " + tableName + + " WHERE " + + IDENTITY_COLUMN + " = ?" ); + + getVersionStatement = session.prepare( "SELECT " + + VERSION_COLUMN + ", " + + " FROM " + tableName + + " WHERE " + + IDENTITY_COLUMN + " = ?" ); + + updateEntityStatement = session.prepare( "INSERT INTO " + tableName + "( " + + IDENTITY_COLUMN + ", " + + VERSION_COLUMN + ", " + + APP_VERSION_COLUMN + ", " + + STORE_VERSION_COLUMN + ", " + + LASTMODIFIED_COLUMN + ", " + + USECASE_COLUMN + ", " + + PROPERTIES_COLUMN + ", " + + ASSOCIATIONS_COLUMN + ", " + + MANYASSOCIATIONS_COLUMN + ", " + + NAMEDASSOCIATIONS_COLUMN + + " ) VALUES (?,?,?," + CURRENT_STORAGE_VERSION + "?,?,?,?,?,?)" ); + } + + private void createPolygeneStateTable( String tableName ) + { + session.execute( "CREATE TABLE " + tableName + "(\n" + + " " + IDENTITY_COLUMN + " text PRIMARYKEY,\n" + + " " + VERSION_COLUMN + " text,\n" + + " " + APP_VERSION_COLUMN + " text,\n" + + " " + STORE_VERSION_COLUMN + " text,\n" + + " " + LASTMODIFIED_COLUMN + " timestamp,\n" + + " " + USECASE_COLUMN + " text,\n" + + " " + PROPERTIES_COLUMN + " map,\n" + + " " + ASSOCIATIONS_COLUMN + " map,\n" + + " " + MANYASSOCIATIONS_COLUMN + " map,\n" + + " " + NAMEDASSOCIATIONS_COLUMN + " map,\n" + + " )" ); + } + + private void createKeyspace( String keyspaceName, int replication ) + { + try( Session defaultSession = cluster.connect() ) + { + String query = "CREATE KEYSPACE " + keyspaceName + "WITH replication = {'class':'SimpleStrategy', 'replication_factor' : " + replication + "};"; + defaultSession.execute( query ); + } + } + + @Override + public void passivateService() + throws Exception + { + cluster.close(); + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/polygene-java/blob/c86b1154/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/CassandraEntityStoreConfiguration.java ---------------------------------------------------------------------- diff --git a/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/CassandraEntityStoreConfiguration.java b/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/CassandraEntityStoreConfiguration.java new file mode 100644 index 0000000..4a5e512 --- /dev/null +++ b/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/CassandraEntityStoreConfiguration.java @@ -0,0 +1,50 @@ +/* + * 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. + * + * + */ +package org.apache.polygene.entitystore.cassandra; + +import org.apache.polygene.api.common.Optional; +import org.apache.polygene.api.common.UseDefaults; +import org.apache.polygene.api.configuration.ConfigurationComposite; +import org.apache.polygene.api.property.Property; + +// START SNIPPET: config +public interface CassandraEntityStoreConfiguration + extends ConfigurationComposite +{ + + @Optional + Property<String> hostnames(); + + @Optional + Property<Integer> replicationFactor(); + + @UseDefaults + Property<String> username(); + + @UseDefaults + Property<String> password(); + + @Optional + Property<String> keySpace(); + + @Optional + Property<String> table(); +} +// END SNIPPET: config \ No newline at end of file http://git-wip-us.apache.org/repos/asf/polygene-java/blob/c86b1154/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/CassandraEntityStoreMixin.java ---------------------------------------------------------------------- diff --git a/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/CassandraEntityStoreMixin.java b/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/CassandraEntityStoreMixin.java new file mode 100644 index 0000000..159bc9c --- /dev/null +++ b/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/CassandraEntityStoreMixin.java @@ -0,0 +1,425 @@ +/* + * 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. + * + * + */ +package org.apache.polygene.entitystore.cassandra; + +import com.datastax.driver.core.BoundStatement; +import com.datastax.driver.core.ResultSet; +import com.datastax.driver.core.Row; +import com.datastax.driver.core.TypeTokens; +import com.google.common.reflect.TypeToken; +import java.time.Instant; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.apache.polygene.api.association.AssociationDescriptor; +import org.apache.polygene.api.common.Optional; +import org.apache.polygene.api.common.QualifiedName; +import org.apache.polygene.api.entity.EntityDescriptor; +import org.apache.polygene.api.entity.EntityReference; +import org.apache.polygene.api.identity.HasIdentity; +import org.apache.polygene.api.identity.Identity; +import org.apache.polygene.api.identity.IdentityGenerator; +import org.apache.polygene.api.identity.StringIdentity; +import org.apache.polygene.api.injection.scope.Service; +import org.apache.polygene.api.injection.scope.Structure; +import org.apache.polygene.api.injection.scope.This; +import org.apache.polygene.api.property.PropertyDescriptor; +import org.apache.polygene.api.service.ServiceActivation; +import org.apache.polygene.api.service.qualifier.Tagged; +import org.apache.polygene.api.structure.Application; +import org.apache.polygene.api.structure.ModuleDescriptor; +import org.apache.polygene.api.unitofwork.NoSuchEntityTypeException; +import org.apache.polygene.api.unitofwork.UnitOfWork; +import org.apache.polygene.api.usecase.Usecase; +import org.apache.polygene.api.value.ValueSerialization; +import org.apache.polygene.spi.entity.EntityState; +import org.apache.polygene.spi.entity.EntityStatus; +import org.apache.polygene.spi.entity.ManyAssociationState; +import org.apache.polygene.spi.entity.NamedAssociationState; +import org.apache.polygene.spi.entitystore.DefaultEntityStoreUnitOfWork; +import org.apache.polygene.spi.entitystore.EntityStore; +import org.apache.polygene.spi.entitystore.EntityStoreSPI; +import org.apache.polygene.spi.entitystore.EntityStoreUnitOfWork; +import org.apache.polygene.spi.entitystore.StateCommitter; +import org.apache.polygene.spi.entitystore.helpers.DefaultEntityState; + +import static java.util.stream.StreamSupport.stream; +import static org.apache.polygene.entitystore.cassandra.CassandraCluster.APP_VERSION_COLUMN; +import static org.apache.polygene.entitystore.cassandra.CassandraCluster.ASSOCIATIONS_COLUMN; +import static org.apache.polygene.entitystore.cassandra.CassandraCluster.IDENTITY_COLUMN; +import static org.apache.polygene.entitystore.cassandra.CassandraCluster.LASTMODIFIED_COLUMN; +import static org.apache.polygene.entitystore.cassandra.CassandraCluster.MANYASSOCIATIONS_COLUMN; +import static org.apache.polygene.entitystore.cassandra.CassandraCluster.NAMEDASSOCIATIONS_COLUMN; +import static org.apache.polygene.entitystore.cassandra.CassandraCluster.PROPERTIES_COLUMN; +import static org.apache.polygene.entitystore.cassandra.CassandraCluster.STORE_VERSION_COLUMN; +import static org.apache.polygene.entitystore.cassandra.CassandraCluster.TYPE_COLUMN; +import static org.apache.polygene.entitystore.cassandra.CassandraCluster.USECASE_COLUMN; +import static org.apache.polygene.entitystore.cassandra.CassandraCluster.VERSION_COLUMN; + +/** + * MongoDB implementation of MapEntityStore. + */ +public class CassandraEntityStoreMixin + implements EntityStore, EntityStoreSPI +{ + + @This + private CassandraCluster cluster; + + @Structure + private Application application; + + @Optional + @Service + private CassandraMigration migration; + + @Service + @Tagged( ValueSerialization.Formats.JSON ) + private ValueSerialization valueSerialization; + + + @Optional + @Service + private IdentityGenerator idGenerator; + + @Override + public EntityState newEntityState( EntityStoreUnitOfWork unitOfWork, EntityReference reference, EntityDescriptor entityDescriptor ) + { + return new DefaultEntityState( unitOfWork.currentTime(), reference, entityDescriptor ); + } + + @Override + public EntityState entityStateOf( EntityStoreUnitOfWork unitOfWork, ModuleDescriptor module, EntityReference reference ) + { + return queryFor( cluster.entityRetrieveStatement().bind( reference.toURI() ), module, reference ); + } + + private EntityState queryFor( BoundStatement statement, ModuleDescriptor module, EntityReference reference ) + { + ResultSet result = cluster.session().execute( statement ); + Row row = result.one(); + return deserialize( row, module); + } + + private EntityState deserialize( Row row, ModuleDescriptor module ) + { + String version = row.getString( VERSION_COLUMN ); + Instant lastModifed = row.getTimestamp( LASTMODIFIED_COLUMN ).toInstant(); + EntityStatus[] status = new EntityStatus[ 1 ]; + status[ 0 ] = EntityStatus.LOADED; + + // Check if version is correct + String currentAppVersion = row.getString( APP_VERSION_COLUMN ); + if( !currentAppVersion.equals( application.version() ) ) + { + if( migration != null ) + { + migration.migrate( row, application.version(), cluster.session() ); + // State may have changed + status[ 0 ] = EntityStatus.UPDATED; + } +// else +// { + // Do nothing ?? Should we update to newer version? Probably not... +// } + } + String type = row.getString( TYPE_COLUMN ); + + EntityDescriptor entityDescriptor = module.entityDescriptor( type ); + if( entityDescriptor == null ) + { + throw new NoSuchEntityTypeException( type, module.name(), module.typeLookup() ); + } + Map<String, String> storedProperties = row.getMap( PROPERTIES_COLUMN, String.class, String.class ); + Map<String, String> storedAssociations = row.getMap( ASSOCIATIONS_COLUMN, String.class, String.class ); + + TypeToken<String> stringToken = TypeToken.of( String.class ); + TypeToken<List<String>> listOfStringsToken = TypeTokens.listOf( String.class ); + TypeToken<Map<String, String>> mapOfStringsToken = TypeTokens.mapOf( String.class, String.class ); + Map<String, List<String>> storedManyassociation = row.getMap( MANYASSOCIATIONS_COLUMN, stringToken, listOfStringsToken ); + Map<String, Map<String, String>> storedNamedassociation = row.getMap( NAMEDASSOCIATIONS_COLUMN, stringToken, mapOfStringsToken ); + + Map<QualifiedName, Object> properties = new HashMap<>(); + entityDescriptor + .state() + .properties() + .forEach( + propertyDescriptor -> + { + String storedValue; + try + { + storedValue = storedProperties.get( propertyDescriptor.qualifiedName().name() ); + if( storedValue == null ) + { + properties.put( propertyDescriptor.qualifiedName(), null ); + } + else + { + Object deserialized = valueSerialization.deserialize( module, propertyDescriptor.valueType(), storedValue ); + properties.put( propertyDescriptor.qualifiedName(), deserialized ); + } + } + catch( RuntimeException e ) + { + // Value not found, or value is corrupt, default it. Is this correct behavior? + Object initialValue = propertyDescriptor.resolveInitialValue( module ); + properties.put( propertyDescriptor.qualifiedName(), initialValue ); + status[ 0 ] = EntityStatus.UPDATED; + } + } ); + + Map<QualifiedName, EntityReference> associations = new HashMap<>(); + entityDescriptor + .state() + .associations() + .forEach( + associationType -> + { + try + { + String storedValue = storedAssociations.get( associationType.qualifiedName().name() ); + EntityReference value = storedValue == null + ? null + : EntityReference.parseEntityReference( storedValue ); + associations.put( associationType.qualifiedName(), value ); + } + catch( RuntimeException e ) + { + // Association not found, default it to null + associations.put( associationType.qualifiedName(), null ); + status[ 0 ] = EntityStatus.UPDATED; + } + } ); + + Map<QualifiedName, List<EntityReference>> manyAssociations = new HashMap<>(); + entityDescriptor + .state() + .manyAssociations() + .forEach( + manyAssociationType -> + { + List<EntityReference> references = new ArrayList<>(); + try + { + List<String> storedValue = storedManyassociation.get( manyAssociationType.qualifiedName().name() ); + if( storedValue != null ) + { + for( String value : storedValue ) + { + EntityReference ref = value == null + ? null + : EntityReference.parseEntityReference( value ); + references.add( ref ); + } + manyAssociations.put( manyAssociationType.qualifiedName(), references ); + } + } + catch( RuntimeException e ) + { + // ManyAssociation not found, default to empty one + manyAssociations.put( manyAssociationType.qualifiedName(), references ); + } + } ); + + Map<QualifiedName, Map<String, EntityReference>> namedAssociations = new HashMap<>(); + entityDescriptor + .state() + .namedAssociations() + .forEach( + namedAssociationType -> + { + Map<String, EntityReference> references = new LinkedHashMap<>(); + try + { + Map<String, String> storedValues = storedNamedassociation.get( namedAssociationType.qualifiedName().name() ); + if( storedValues != null ) + { + for( Map.Entry<String, String> entry : storedValues.entrySet() ) + { + String name = entry.getKey(); + String value = entry.getValue(); + EntityReference ref = value == null + ? null + : EntityReference.parseEntityReference( value ); + references.put( name, ref ); + } + namedAssociations.put( namedAssociationType.qualifiedName(), references ); + } + } + catch( RuntimeException e ) + { + // NamedAssociation not found, default to empty one + namedAssociations.put( namedAssociationType.qualifiedName(), references ); + } + } ); + + EntityReference reference = EntityReference.parseEntityReference( storedProperties.get( "identity" ) ); + return new DefaultEntityState( version, + lastModifed, + reference, + status[ 0 ], + entityDescriptor, + properties, + associations, + manyAssociations, + namedAssociations + ); + } + + @Override + public String versionOf( EntityStoreUnitOfWork unitOfWork, EntityReference reference ) + { + ResultSet result = cluster.session().execute( cluster.entityRetrieveStatement().bind( reference.toURI() ) ); + Row row = result.one(); + return row.getString( VERSION_COLUMN ); + } + + @Override + public StateCommitter applyChanges( EntityStoreUnitOfWork unitOfWork, Iterable<EntityState> state ) + { + return new StateCommitter() + { + @Override + public void commit() + { + + stream( state.spliterator(), false ) + .filter( entity -> entity.status() == EntityStatus.UPDATED || entity.status() == EntityStatus.NEW ) + .forEach( + entityState -> + { + Map<String, String> props = new HashMap<>(); + Map<String, String> assocs = new HashMap<>(); + Map<String, List<String>> many = new HashMap<>(); + Map<String, Map<String, String>> named = new HashMap<>(); + serializeProperties( entityState, props ); + serializeAssociations( entityState, assocs ); + serializeManyAssociations( entityState, many ); + serializeNamedAssociations( entityState, named ); + Identity identity = (Identity) entityState.propertyValueOf( HasIdentity.IDENTITY_STATE_NAME ); + String ver = entityState.version(); + String appVersion = application.version(); + Date lastModified = new Date( entityState.lastModified().toEpochMilli() ); + String usecase = unitOfWork.usecase().name(); + BoundStatement statement = cluster.entityUpdateStatement().bind( identity.toString(), ver, appVersion, lastModified, usecase, props, assocs, many, named ); + ResultSet result = cluster.session().execute( statement ); + System.out.println( result ); + } ); + } + + private void serializeProperties( EntityState entityState, Map<String, String> props ) + { + Stream<? extends PropertyDescriptor> properties = entityState.entityDescriptor().state().properties(); + properties.forEach( + descriptor -> + { + Object value = entityState.propertyValueOf( descriptor.qualifiedName() ); + String serialized = valueSerialization.serialize( value ); + props.put( descriptor.qualifiedName().name(), serialized ); + } ); + } + + private void serializeAssociations( EntityState entityState, Map<String, String> assocs ) + { + Stream<? extends AssociationDescriptor> associations = entityState.entityDescriptor().state().associations(); + associations.forEach( + descriptor -> + { + EntityReference ref = entityState.associationValueOf( descriptor.qualifiedName() ); + assocs.put( descriptor.qualifiedName().name(), ref.toString() ); + } ); + } + + private void serializeManyAssociations( EntityState entityState, Map<String, List<String>> many ) + { + Stream<? extends AssociationDescriptor> associations = entityState.entityDescriptor().state().associations(); + associations.forEach( + descriptor -> + { + ManyAssociationState references = entityState.manyAssociationValueOf( descriptor.qualifiedName() ); + List<String> refs = references.stream().map( EntityReference::toString ).collect( Collectors.toList() ); + many.put( descriptor.qualifiedName().name(), refs ); + } ); + } + + private void serializeNamedAssociations( EntityState entityState, Map<String, Map<String, String>> named ) + { + Stream<? extends AssociationDescriptor> associations = entityState.entityDescriptor().state().associations(); + associations.forEach( + descriptor -> + { + NamedAssociationState references = entityState.namedAssociationValueOf( descriptor.qualifiedName() ); + Map<String, String> refs = + references.stream() + .collect( + Collectors.toMap( Map.Entry::getKey, + entry -> entry.getValue().toString() ) ); + named.put( descriptor.qualifiedName().name(), refs ); + } ); + } + + @Override + public void cancel() + { + } + }; + } + + @Override + public EntityStoreUnitOfWork newUnitOfWork( ModuleDescriptor module, Usecase usecase, Instant currentTime ) + { + Identity newIdentity; + if( idGenerator == null ) + { + newIdentity = new StringIdentity( UUID.randomUUID().toString() ); + } + else + { + newIdentity= idGenerator.generate( UnitOfWork.class ); + } + return new DefaultEntityStoreUnitOfWork( module, this, newIdentity, usecase, currentTime ); + } + + @Override + public Stream<EntityState> entityStates( ModuleDescriptor module ) + { + ResultSet resultSet = cluster.session().execute( "SELECT " + + IDENTITY_COLUMN + ", " + + VERSION_COLUMN + ", " + + APP_VERSION_COLUMN + ", " + + STORE_VERSION_COLUMN + ", " + + LASTMODIFIED_COLUMN + ", " + + USECASE_COLUMN + ", " + + PROPERTIES_COLUMN + ", " + + ASSOCIATIONS_COLUMN + ", " + + MANYASSOCIATIONS_COLUMN + ", " + + NAMEDASSOCIATIONS_COLUMN + + " FROM " + cluster.tableName() ); + return stream(resultSet.spliterator(), false).map( row -> deserialize( row, module )); + } + +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/c86b1154/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/CassandraEntityStoreService.java ---------------------------------------------------------------------- diff --git a/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/CassandraEntityStoreService.java b/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/CassandraEntityStoreService.java new file mode 100644 index 0000000..e7531ce --- /dev/null +++ b/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/CassandraEntityStoreService.java @@ -0,0 +1,48 @@ +/* + * 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. + * + * + */ +package org.apache.polygene.entitystore.cassandra; + +import org.apache.polygene.api.concern.Concerns; +import org.apache.polygene.api.configuration.Configuration; +import org.apache.polygene.api.mixin.Mixins; +import org.apache.polygene.api.service.ServiceActivation; +import org.apache.polygene.api.service.ServiceComposite; +import org.apache.polygene.library.locking.LockingAbstractComposite; +import org.apache.polygene.spi.entitystore.ConcurrentModificationCheckConcern; +import org.apache.polygene.spi.entitystore.EntityStateVersions; +import org.apache.polygene.spi.entitystore.EntityStore; +import org.apache.polygene.spi.entitystore.StateChangeNotificationConcern; +import org.apache.polygene.spi.entitystore.helpers.JSONMapEntityStoreActivation; +import org.apache.polygene.spi.entitystore.helpers.JSONMapEntityStoreMixin; + +/** + * Cassandra EntityStore service. + */ +@Concerns( { StateChangeNotificationConcern.class, ConcurrentModificationCheckConcern.class } ) +@Mixins( { CassandraEntityStoreMixin.class } ) +public interface CassandraEntityStoreService + extends EntityStore, + EntityStateVersions, + ServiceComposite, + ServiceActivation, + LockingAbstractComposite, + Configuration +{ +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/c86b1154/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/CassandraMigration.java ---------------------------------------------------------------------- diff --git a/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/CassandraMigration.java b/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/CassandraMigration.java new file mode 100644 index 0000000..72b4060 --- /dev/null +++ b/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/CassandraMigration.java @@ -0,0 +1,28 @@ +/* + * 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. + * + * + */ +package org.apache.polygene.entitystore.cassandra; + +import com.datastax.driver.core.Row; +import com.datastax.driver.core.Session; + +public interface CassandraMigration +{ + Row migrate( Row existingRow, String toVersion, Session session ); +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/c86b1154/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/assembly/CassandraDBEntityStoreAssembler.java ---------------------------------------------------------------------- diff --git a/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/assembly/CassandraDBEntityStoreAssembler.java b/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/assembly/CassandraDBEntityStoreAssembler.java new file mode 100644 index 0000000..15b3c60 --- /dev/null +++ b/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/assembly/CassandraDBEntityStoreAssembler.java @@ -0,0 +1,46 @@ +/* + * 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. + * + * + */ +package org.apache.polygene.entitystore.cassandra.assembly; + +import org.apache.polygene.bootstrap.Assemblers; +import org.apache.polygene.bootstrap.AssemblyException; +import org.apache.polygene.bootstrap.ModuleAssembly; +import org.apache.polygene.bootstrap.ServiceDeclaration; +import org.apache.polygene.entitystore.cassandra.CassandraEntityStoreConfiguration; +import org.apache.polygene.entitystore.cassandra.CassandraEntityStoreService; + +public class CassandraDBEntityStoreAssembler + extends Assemblers.VisibilityIdentityConfig<CassandraDBEntityStoreAssembler> +{ + @Override + public void assemble( ModuleAssembly module ) + throws AssemblyException + { + ServiceDeclaration service = module.services( CassandraEntityStoreService.class ).visibleIn( visibility() ); + if( hasIdentity() ) + { + service.identifiedBy( identity() ); + } + if( hasConfig() ) + { + configModule().entities( CassandraEntityStoreConfiguration.class ).visibleIn( configVisibility() ); + } + } +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/c86b1154/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/package.html ---------------------------------------------------------------------- diff --git a/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/package.html b/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/package.html new file mode 100644 index 0000000..2a0077e --- /dev/null +++ b/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/package.html @@ -0,0 +1,43 @@ +<!-- + ~ 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. + ~ + ~ + --> +<html> +<body> +<h2>Casssandra EntityStore.</h2> + <p> + The Cassandra EntityStore leverages the CQL 'map' type, which is the "newer" way of doing variable-wdith rows. + </p> +<p> + For properties, there is a map called '_props' with string key (the name of the property) and string value, + which is the serialized state of the property. +</p> +<p> + For associations, there is map called '_assocs' with string key (the name of the association) and string value, + which is the entity reference in toString() format. +</p> +<p> + For manyassociations, there is map called '_manyassocs' with string key (the name of the manyassociation) and + list of strings value, which is the list of entity references in toString() format. +</p> +<p> + For namedassociations, there is map called '_manyassocs' with string key (the name of the association) and + map of strings value, which is the name as the key and the value is the entity reference in toString() format. +</p> +</body> +</html> http://git-wip-us.apache.org/repos/asf/polygene-java/blob/c86b1154/extensions/entitystore-cassandra/src/test/java/org/apache/polygene/entitystore/cassandra/CassandraMapEntityStoreTest.java ---------------------------------------------------------------------- diff --git a/extensions/entitystore-cassandra/src/test/java/org/apache/polygene/entitystore/cassandra/CassandraMapEntityStoreTest.java b/extensions/entitystore-cassandra/src/test/java/org/apache/polygene/entitystore/cassandra/CassandraMapEntityStoreTest.java new file mode 100644 index 0000000..3f5cc12 --- /dev/null +++ b/extensions/entitystore-cassandra/src/test/java/org/apache/polygene/entitystore/cassandra/CassandraMapEntityStoreTest.java @@ -0,0 +1,89 @@ +/* + * 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. + * + * + */ +package org.apache.polygene.entitystore.cassandra; + +import org.apache.polygene.entitystore.cassandra.assembly.CassandraDBEntityStoreAssembler; +import org.apache.polygene.test.entity.CanRemoveAll; +import org.junit.BeforeClass; +import org.apache.polygene.api.common.Visibility; +import org.apache.polygene.bootstrap.AssemblyException; +import org.apache.polygene.bootstrap.ModuleAssembly; +import org.apache.polygene.test.EntityTestAssembler; +import org.apache.polygene.test.entity.AbstractEntityStoreTest; +import org.apache.polygene.valueserialization.orgjson.OrgJsonValueSerializationAssembler; + +import static org.apache.polygene.test.util.Assume.assumeConnectivity; + +/** + * Test the CassandraEntityStoreService. + * <p>Installing Cassandra and starting it should suffice as the test use Cassandra defaults: 127.0.0.1:3000</p> + */ +public class CassandraMapEntityStoreTest + extends AbstractEntityStoreTest +{ + + + @BeforeClass + public static void beforeCassandraEntityStoreTests() + { + assumeConnectivity( "localhost", 9042 ); + } + + @Override + // START SNIPPET: assembly + public void assemble( ModuleAssembly module ) + throws AssemblyException + { + // END SNIPPET: assembly + super.assemble( module ); + + ModuleAssembly config = module.layer().module( "config" ); + new EntityTestAssembler().assemble( config ); + module.services( CassandraEntityStoreService.class ).withTypes( CanRemoveAll.class ).withMixins( EmptyCassandraTableMixin.class ); + new OrgJsonValueSerializationAssembler().assemble( module ); + + // START SNIPPET: assembly + new CassandraDBEntityStoreAssembler().withConfig( config, Visibility.layer ).assemble( module ); + // END SNIPPET: assembly + + CassandraEntityStoreConfiguration cassandraConfig = config.forMixin( CassandraEntityStoreConfiguration.class ).declareDefaults(); + cassandraConfig.keySpace().set( "polygene:test" ); + cassandraConfig.table().set( "polygene:test:entities" ); + cassandraConfig.replicationFactor().set( 1 ); + // START SNIPPET: assembly + } + // END SNIPPET: assembly + + @Override + public void setUp() + throws Exception + { + super.setUp(); + } + + @Override + public void tearDown() + throws Exception + { + CanRemoveAll cleaner = serviceFinder.findService( CanRemoveAll.class ).get(); + cleaner.removeAll(); + super.tearDown(); + } +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/c86b1154/extensions/entitystore-cassandra/src/test/java/org/apache/polygene/entitystore/cassandra/EmptyCassandraTableMixin.java ---------------------------------------------------------------------- diff --git a/extensions/entitystore-cassandra/src/test/java/org/apache/polygene/entitystore/cassandra/EmptyCassandraTableMixin.java b/extensions/entitystore-cassandra/src/test/java/org/apache/polygene/entitystore/cassandra/EmptyCassandraTableMixin.java new file mode 100644 index 0000000..a620d32 --- /dev/null +++ b/extensions/entitystore-cassandra/src/test/java/org/apache/polygene/entitystore/cassandra/EmptyCassandraTableMixin.java @@ -0,0 +1,20 @@ +package org.apache.polygene.entitystore.cassandra; + +import com.datastax.driver.core.querybuilder.Delete; +import com.datastax.driver.core.querybuilder.QueryBuilder; +import org.apache.polygene.api.injection.scope.This; +import org.apache.polygene.test.entity.CanRemoveAll; + +public class EmptyCassandraTableMixin + implements CanRemoveAll +{ + @This + private CassandraCluster cluster; + + @Override + public void removeAll() + { + Delete delete = QueryBuilder.delete().from(cluster.keyspaceName(), cluster.tableName()); + cluster.session().execute( delete ); + } +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/c86b1154/internals/testsupport-internal/src/main/docker/cassandra/Dockerfile ---------------------------------------------------------------------- diff --git a/internals/testsupport-internal/src/main/docker/cassandra/Dockerfile b/internals/testsupport-internal/src/main/docker/cassandra/Dockerfile new file mode 100644 index 0000000..e382cc1 --- /dev/null +++ b/internals/testsupport-internal/src/main/docker/cassandra/Dockerfile @@ -0,0 +1,16 @@ +# 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. + +FROM cassandra:3.9 http://git-wip-us.apache.org/repos/asf/polygene-java/blob/c86b1154/settings.gradle ---------------------------------------------------------------------- diff --git a/settings.gradle b/settings.gradle index 6858c4c..67ec7c4 100644 --- a/settings.gradle +++ b/settings.gradle @@ -57,13 +57,14 @@ include 'core:api', 'libraries:uowfile', 'extensions:cache-ehcache', 'extensions:cache-memcache', - 'extensions:entitystore-memory', + 'extensions:entitystore-cassandra', 'extensions:entitystore-file', 'extensions:entitystore-geode', 'extensions:entitystore-hazelcast', 'extensions:entitystore-jclouds', 'extensions:entitystore-jdbm', 'extensions:entitystore-leveldb', + 'extensions:entitystore-memory', 'extensions:entitystore-mongodb', 'extensions:entitystore-preferences', 'extensions:entitystore-redis', @@ -81,7 +82,6 @@ include 'core:api', 'extensions:valueserialization-stax', 'tools:model-detail', 'tools:envisage', - 'tools:shell', // 'tools:qidea', 'tests:regression', 'tests:performance', http://git-wip-us.apache.org/repos/asf/polygene-java/blob/c86b1154/tools/shell/build.gradle ---------------------------------------------------------------------- diff --git a/tools/shell/build.gradle b/tools/shell/build.gradle deleted file mode 100644 index 1ec559f..0000000 --- a/tools/shell/build.gradle +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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. - * - * - */ - -apply plugin: 'polygene-tool' -apply plugin: 'application' - -description = "Command line tools for building Apache Polygene⢠applications." -mainClassName = "org.apache.polygene.tools.shell.Main" - -jar { - manifest { - name = "Apache Polygene⢠Command Line" - attributes("Main-Class": mainClassName ) - } -} - -[ distZip, distTar ].each { dist -> dist.classifier = 'bin' } -distTar.compression = Compression.GZIP - -dependencies { - testRuntime libraries.logback -} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/c86b1154/tools/shell/dev-status.xml ---------------------------------------------------------------------- diff --git a/tools/shell/dev-status.xml b/tools/shell/dev-status.xml deleted file mode 100644 index 01d0c15..0000000 --- a/tools/shell/dev-status.xml +++ /dev/null @@ -1,38 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" ?> -<!-- - ~ 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. - ~ - ~ - --> -<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1 - http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd"> - <status> - <!--none,early,beta,stable,mature--> - <codebase>beta</codebase> - - <!-- none, brief, good, complete --> - <documentation>brief</documentation> - - <!-- none, some, good, complete --> - <unittests>good</unittests> - </status> - <licenses> - <license>ALv2</license> - </licenses> -</module> http://git-wip-us.apache.org/repos/asf/polygene-java/blob/c86b1154/tools/shell/src/main/java/org/apache/polygene/tools/shell/create/project/NullProjectCreator.java ---------------------------------------------------------------------- diff --git a/tools/shell/src/main/java/org/apache/polygene/tools/shell/create/project/NullProjectCreator.java b/tools/shell/src/main/java/org/apache/polygene/tools/shell/create/project/NullProjectCreator.java deleted file mode 100644 index 8018dc6..0000000 --- a/tools/shell/src/main/java/org/apache/polygene/tools/shell/create/project/NullProjectCreator.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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. - * - * - */ - -package org.apache.polygene.tools.shell.create.project; - -import java.io.File; -import java.io.IOException; -import java.util.Map; - -public class NullProjectCreator extends AbstractProjectCreator - implements ProjectCreator -{ - - @Override - public void create( String projectName, File projectDir, Map<String, String> properties ) - throws IOException - { - super.create( projectName, projectDir, properties ); // creates the directory structures. - } -}
