Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ISPN-1978 Extensible configuration parser for modules #1234

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
48 changes: 48 additions & 0 deletions core/src/main/java/org/infinispan/configuration/Builder.java
@@ -0,0 +1,48 @@
/*
* JBoss, Home of Professional Open Source
* Copyright 2012 Red Hat Inc. and/or its affiliates and other contributors
* as indicated by the @author tags. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package org.infinispan.configuration;

/**
* Builder. Validates and constructs a configuration bean
*
* @author Tristan Tarrant
* @since 5.2
*/
public interface Builder<T> {
/**
* Validate the data in this builder before building the configuration bean
*/
void validate();

/**
* Create the configuration bean
*
* @return
*/
T create();

/**
* Reads the configuration from an already created configuration bean into this builder.
* Returns an appropriate builder to allow fluent configuration
*
* @param template
* @return
*/
Builder<?> read(T template);
}
35 changes: 35 additions & 0 deletions core/src/main/java/org/infinispan/configuration/BuiltBy.java
@@ -0,0 +1,35 @@
/*
* JBoss, Home of Professional Open Source
* Copyright 2012 Red Hat Inc. and/or its affiliates and other contributors
* as indicated by the @author tags. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package org.infinispan.configuration;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
* BuiltBy. An annotation for configuration beans to specify what builder builds them.
* This annotation is required on all non-core configuration classes (i.e. ones which reside
* in external modules)
*
* @author Tristan Tarrant
* @since 5.2
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface BuiltBy {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see you've used the annotation for a custom config builder, but shouldn't this be used in core configuration classes?

I guess in core/ things are tighter and we know which builder goes with which build object.

If that's the case, we should explicitly indicate that this annotation is purely for non-core configuration extensions.

Either way, we need to be explicit.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll be more accurate in the javadoc

Class<? extends Builder<?>> value();
}
Expand Up @@ -18,7 +18,9 @@
*/
package org.infinispan.configuration.cache;

abstract class AbstractConfigurationChildBuilder<T> implements ConfigurationChildBuilder {
import org.infinispan.configuration.Builder;

abstract class AbstractConfigurationChildBuilder<T> implements ConfigurationChildBuilder, Builder<T> {

private final ConfigurationBuilder builder;

Expand Down Expand Up @@ -110,10 +112,4 @@ public Configuration build() {
return builder.build();
}

abstract void validate();

abstract T create();

public abstract ConfigurationChildBuilder read(T template);

}
@@ -0,0 +1,33 @@
/*
* JBoss, Home of Professional Open Source
* Copyright 2012 Red Hat Inc. and/or its affiliates and other contributors
* as indicated by the @author tags. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package org.infinispan.configuration.cache;

/**
* AbstractModuleConfigurationBuilder.
*
* @author Tristan Tarrant
* @since 5.2
*/
public abstract class AbstractModuleConfigurationBuilder<T> extends AbstractConfigurationChildBuilder<T> {

protected AbstractModuleConfigurationBuilder(ConfigurationBuilder builder) {
super(builder);
}

}
Expand Up @@ -116,6 +116,7 @@ public AsyncConfigurationBuilder useReplQueue(boolean use) {
}

@Override
public
void validate() {
if (useReplicationQueue && getClusteringBuilder().cacheMode().isDistributed())
throw new ConfigurationException("Use of the replication queue is invalid when using DISTRIBUTED mode.");
Expand All @@ -125,6 +126,7 @@ void validate() {
}

@Override
public
AsyncConfiguration create() {
return new AsyncConfiguration(asyncMarshalling, replicationQueue, replicationQueueInterval, replicationQueueMaxElements, useReplicationQueue);
}
Expand Down
Expand Up @@ -113,10 +113,12 @@ public AsyncLoaderConfigurationBuilder threadPoolSize(int i) {
}

@Override
public
void validate() {
}

@Override
public
AsyncLoaderConfiguration create() {
return new AsyncLoaderConfiguration(enabled, flushLockTimeout, modificationQueueSize, shutdownTimeout, threadPoolSize);
}
Expand Down
Expand Up @@ -102,6 +102,7 @@ public SyncConfigurationBuilder sync() {
}

@Override
public
void validate() {
asyncConfigurationBuilder.validate();
hashConfigurationBuilder.validate();
Expand All @@ -111,6 +112,7 @@ void validate() {
}

@Override
public
ClusteringConfiguration create() {
return new ClusteringConfiguration(cacheMode, asyncConfigurationBuilder.create(), hashConfigurationBuilder.create(),
l1ConfigurationBuilder.create(), stateTransferConfigurationBuilder.create(), syncConfigurationBuilder.create());
Expand Down
Expand Up @@ -18,6 +18,11 @@
*/
package org.infinispan.configuration.cache;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Configuration {

private final ClassLoader classLoader; //TODO remove this
Expand All @@ -36,6 +41,7 @@ public class Configuration {
private final TransactionConfiguration transactionConfiguration;
private final VersioningConfiguration versioningConfiguration;
private final UnsafeConfiguration unsafeConfiguration;
private final Map<Class<?>, ?> moduleConfiguration;

Configuration(ClusteringConfiguration clusteringConfiguration,
CustomInterceptorsConfiguration customInterceptorsConfiguration,
Expand All @@ -46,7 +52,7 @@ public class Configuration {
LoadersConfiguration loadersConfiguration,
LockingConfiguration lockingConfiguration, StoreAsBinaryConfiguration storeAsBinaryConfiguration,
TransactionConfiguration transactionConfiguration, UnsafeConfiguration unsafeConfiguration,
VersioningConfiguration versioningConfiguration, ClassLoader cl) {
VersioningConfiguration versioningConfiguration, List<?> modules, ClassLoader cl) {
this.clusteringConfiguration = clusteringConfiguration;
this.customInterceptorsConfiguration = customInterceptorsConfiguration;
this.dataContainerConfiguration = dataContainerConfiguration;
Expand All @@ -62,6 +68,11 @@ public class Configuration {
this.transactionConfiguration = transactionConfiguration;
this.unsafeConfiguration = unsafeConfiguration;
this.versioningConfiguration = versioningConfiguration;
Map<Class<?>, Object> modulesMap = new HashMap<Class<?>, Object>();
for(Object module : modules) {
modulesMap.put(module.getClass(), module);
}
this.moduleConfiguration = Collections.unmodifiableMap(modulesMap);
this.classLoader = cl;
}

Expand Down Expand Up @@ -118,6 +129,15 @@ public LockingConfiguration locking() {
return lockingConfiguration;
}

@SuppressWarnings("unchecked")
public <T> T module(Class<T> moduleClass) {
return (T)moduleConfiguration.get(moduleClass);
}

public Map<Class<?>, ?> modules() {
return moduleConfiguration;
}

public StoreAsBinaryConfiguration storeAsBinary() {
return storeAsBinaryConfiguration;
}
Expand Down Expand Up @@ -149,6 +169,7 @@ public String toString() {
", jmxStatistics=" + jmxStatisticsConfiguration +
", loaders=" + loadersConfiguration +
", locking=" + lockingConfiguration +
", modules=" + moduleConfiguration +
", storeAsBinary=" + storeAsBinaryConfiguration +
", transaction=" + transactionConfiguration +
", versioning=" + versioningConfiguration +
Expand Down Expand Up @@ -187,6 +208,8 @@ public boolean equals(Object o) {
return false;
if (lockingConfiguration != null ? !lockingConfiguration.equals(that.lockingConfiguration) : that.lockingConfiguration != null)
return false;
if (moduleConfiguration != null ? !moduleConfiguration.equals(that.moduleConfiguration) : that.moduleConfiguration !=null)
return false;
if (storeAsBinaryConfiguration != null ? !storeAsBinaryConfiguration.equals(that.storeAsBinaryConfiguration) : that.storeAsBinaryConfiguration != null)
return false;
if (transactionConfiguration != null ? !transactionConfiguration.equals(that.transactionConfiguration) : that.transactionConfiguration != null)
Expand All @@ -213,11 +236,13 @@ public int hashCode() {
result = 31 * result + (jmxStatisticsConfiguration != null ? jmxStatisticsConfiguration.hashCode() : 0);
result = 31 * result + (loadersConfiguration != null ? loadersConfiguration.hashCode() : 0);
result = 31 * result + (lockingConfiguration != null ? lockingConfiguration.hashCode() : 0);
result = 31 * result + (moduleConfiguration != null ? moduleConfiguration.hashCode() : 0);
result = 31 * result + (storeAsBinaryConfiguration != null ? storeAsBinaryConfiguration.hashCode() : 0);
result = 31 * result + (transactionConfiguration != null ? transactionConfiguration.hashCode() : 0);
result = 31 * result + (versioningConfiguration != null ? versioningConfiguration.hashCode() : 0);
result = 31 * result + (unsafeConfiguration != null ? unsafeConfiguration.hashCode() : 0);
return result;
}


}
Expand Up @@ -20,6 +20,15 @@

import static java.util.Arrays.asList;

import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import org.infinispan.config.ConfigurationException;
import org.infinispan.configuration.Builder;
import org.infinispan.configuration.BuiltBy;

public class ConfigurationBuilder implements ConfigurationChildBuilder {

private ClassLoader classLoader;
Expand All @@ -38,6 +47,7 @@ public class ConfigurationBuilder implements ConfigurationChildBuilder {
private final TransactionConfigurationBuilder transaction;
private final VersioningConfigurationBuilder versioning;
private final UnsafeConfigurationBuilder unsafe;
private final List<Builder<?>> modules = new ArrayList<Builder<?>>();

public ConfigurationBuilder() {
this.clustering = new ClusteringConfigurationBuilder(this);
Expand Down Expand Up @@ -141,6 +151,26 @@ public UnsafeConfigurationBuilder unsafe() {
return unsafe;
}

public List<Builder<?>> modules() {
return modules;
}

public ConfigurationBuilder clearModules() {
modules.clear();
return this;
}

public <T extends Builder<?>> T addModule(Class<T> klass) {
try {
Constructor<T> constructor = klass.getConstructor(ConfigurationBuilder.class);
T builder = constructor.newInstance(this);
this.modules.add(builder);
return builder;
} catch (Exception e) {
throw new ConfigurationException("Could not instantiate module configuration builder '" + klass.getName() + "'", e);
}
}

@SuppressWarnings("unchecked")
public void validate() {
for (AbstractConfigurationChildBuilder<?> validatable:
Expand All @@ -149,6 +179,9 @@ public void validate() {
versioning, unsafe)) {
validatable.validate();
}
for (Builder<?> m : modules) {
m.validate();
}

// TODO validate that a transport is set if a singleton store is set
}
Expand All @@ -162,11 +195,14 @@ public Configuration build(boolean validate) {
if (validate) {
validate();
}
List<Object> modulesConfig = new LinkedList<Object>();
for (Builder<?> module : modules)
modulesConfig.add(module.create());
return new Configuration(clustering.create(), customInterceptors.create(),
dataContainer.create(), deadlockDetection.create(), eviction.create(),
expiration.create(), indexing.create(), invocationBatching.create(),
jmxStatistics.create(), loaders.create(), locking.create(), storeAsBinary.create(),
transaction.create(), unsafe.create(), versioning.create(), classLoader);// TODO
transaction.create(), unsafe.create(), versioning.create(), modulesConfig, classLoader);// TODO
}

public ConfigurationBuilder read(Configuration template) {
Expand All @@ -187,6 +223,15 @@ public ConfigurationBuilder read(Configuration template) {
this.unsafe.read(template.unsafe());
this.versioning.read(template.versioning());

for (Object c : template.modules().values()) {
BuiltBy builtBy = c.getClass().getAnnotation(BuiltBy.class);
if (builtBy==null) {
throw new ConfigurationException("Missing BuiltBy annotation for configuration bean "+c.getClass().getName());
}
Builder<Object> builder = (Builder<Object>) this.addModule(builtBy.value());
builder.read(c);
}

return this;
}

Expand All @@ -205,6 +250,7 @@ public String toString() {
", jmxStatistics=" + jmxStatistics +
", loaders=" + loaders +
", locking=" + locking +
", modules=" + modules +
", storeAsBinary=" + storeAsBinary +
", transaction=" + transaction +
", versioning=" + versioning +
Expand Down
Expand Up @@ -46,12 +46,12 @@ public InterceptorConfigurationBuilder addInterceptor() {
}

@Override
void validate() {
public void validate() {
// Nothing to validate
}

@Override
CustomInterceptorsConfiguration create() {
public CustomInterceptorsConfiguration create() {
if (interceptorBuilders.isEmpty()) {
return new CustomInterceptorsConfiguration();
} else {
Expand Down