All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sf.hajdbc.sql.AbstractDatabaseClusterConfiguration Maven / Gradle / Ivy

There is a newer version: 3.6.61
Show newest version
/*
 * HA-JDBC: High-Availability JDBC
 * Copyright (C) 2012  Paul Ferraro
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY 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
 * along with this program.  If not, see .
 */
package net.sf.hajdbc.sql;

import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.beans.PropertyEditor;
import java.beans.PropertyEditorManager;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlID;
import javax.xml.bind.annotation.XmlIDREF;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.XmlValue;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

import net.sf.hajdbc.Database;
import net.sf.hajdbc.DatabaseClusterConfiguration;
import net.sf.hajdbc.DatabaseFactory;
import net.sf.hajdbc.ExecutorServiceProvider;
import net.sf.hajdbc.Identifiable;
import net.sf.hajdbc.IdentifiableMatcher;
import net.sf.hajdbc.Messages;
import net.sf.hajdbc.SynchronizationStrategy;
import net.sf.hajdbc.TransactionMode;
import net.sf.hajdbc.balancer.BalancerFactory;
import net.sf.hajdbc.cache.DatabaseMetaDataCacheFactory;
import net.sf.hajdbc.codec.DecoderFactory;
import net.sf.hajdbc.codec.MultiplexingDecoderFactory;
import net.sf.hajdbc.dialect.DialectFactory;
import net.sf.hajdbc.distributed.CommandDispatcherFactory;
import net.sf.hajdbc.durability.DurabilityFactory;
import net.sf.hajdbc.io.InputSinkProvider;
import net.sf.hajdbc.lock.LockManagerFactory;
import net.sf.hajdbc.management.DefaultMBeanRegistrar;
import net.sf.hajdbc.management.MBeanRegistrar;
import net.sf.hajdbc.state.StateManagerFactory;
import net.sf.hajdbc.tx.SimpleTransactionIdentifierFactory;
import net.sf.hajdbc.tx.TransactionIdentifierFactory;
import net.sf.hajdbc.tx.UUIDTransactionIdentifierFactory;
import net.sf.hajdbc.util.ServiceLoaders;
import net.sf.hajdbc.util.concurrent.cron.CronExpression;

/**
 * @author Paul Ferraro
 */
@XmlType(propOrder = { "commandDispatcherFactoryDescriptor", "synchronizationStrategyDescriptors", "stateManagerFactoryDescriptor", "lockManagerFactoryDescriptor" })
public abstract class AbstractDatabaseClusterConfiguration> implements DatabaseClusterConfiguration
{
	private static final long serialVersionUID = -2808296483725374829L;

	private CommandDispatcherFactory dispatcherFactory;	
	private Map synchronizationStrategies = new HashMap();
	private StateManagerFactory stateManagerFactory = ServiceLoaders.findRequiredService(StateManagerFactory.class);
	private LockManagerFactory lockManagerFactory = ServiceLoaders.findRequiredService(LockManagerFactory.class);

	protected abstract NestedConfiguration getNestedConfiguration();

	@Override
	public DatabaseFactory getDatabaseFactory()
	{
		return this.getNestedConfiguration().getDatabaseFactory();
	}

	@XmlElement(name = "distributable")
	private CommandDispatcherFactoryDescriptor getCommandDispatcherFactoryDescriptor() throws Exception
	{
		return (this.dispatcherFactory != null) ? new CommandDispatcherFactoryDescriptorAdapter().marshal(this.dispatcherFactory) : null;
	}

	@SuppressWarnings("unused")
	private void setCommandDispatcherFactoryDescriptor(CommandDispatcherFactoryDescriptor descriptor) throws Exception
	{
		this.dispatcherFactory = (descriptor != null) ? new CommandDispatcherFactoryDescriptorAdapter().unmarshal(descriptor) : null;
	}
	
	@XmlElement(name = "sync")
	private SynchronizationStrategyDescriptor[] getSynchronizationStrategyDescriptors() throws Exception
	{
		List results = new ArrayList(this.synchronizationStrategies.size());
		SynchronizationStrategyDescriptorAdapter adapter = new SynchronizationStrategyDescriptorAdapter();

		for (Map.Entry entry: this.synchronizationStrategies.entrySet())
		{
			SynchronizationStrategyDescriptor result = adapter.marshal(entry.getValue());
			
			result.setId(entry.getKey());
			
			results.add(result);
		}
		
		return results.toArray(new SynchronizationStrategyDescriptor[results.size()]);
	}
	
	@SuppressWarnings("unused")
	private void setSynchronizationStrategyDescriptors(SynchronizationStrategyDescriptor[] entries) throws Exception
	{
		SynchronizationStrategyDescriptorAdapter adapter = new SynchronizationStrategyDescriptorAdapter();
		
		for (SynchronizationStrategyDescriptor entry: entries)
		{
			SynchronizationStrategy strategy = adapter.unmarshal(entry);
			
			this.synchronizationStrategies.put(entry.getId(), strategy);
		}
	}
	
	@XmlElement(name = "state")
	private StateManagerFactoryDescriptor getStateManagerFactoryDescriptor() throws Exception
	{
		return new StateManagerFactoryDescriptorAdapter().marshal(this.stateManagerFactory);
	}
	
	@SuppressWarnings("unused")
	private void setStateManagerFactoryDescriptor(StateManagerFactoryDescriptor descriptor) throws Exception
	{
		this.stateManagerFactory = new StateManagerFactoryDescriptorAdapter().unmarshal(descriptor);
	}
	
	@XmlElement(name = "lock")
	private LockManagerFactoryDescriptor getLockManagerFactoryDescriptor() throws Exception
	{
		return new LockManagerFactoryDescriptorAdapter().marshal(this.lockManagerFactory);
	}
	
	@SuppressWarnings("unused")
	private void setLockManagerFactoryDescriptor(LockManagerFactoryDescriptor descriptor) throws Exception
	{
		this.lockManagerFactory = new LockManagerFactoryDescriptorAdapter().unmarshal(descriptor);
	}
	
	/**
	 * {@inheritDoc}
	 * @see net.sf.hajdbc.DatabaseClusterConfiguration#getAutoActivationExpression()
	 */
	@Override
	public CronExpression getAutoActivationExpression()
	{
		return this.getNestedConfiguration().getAutoActivationExpression();
	}

	public void setAutoActivationExpression(CronExpression expression)
	{
		this.getNestedConfiguration().setAutoActivationExpression(expression);
	}
	
	/**
	 * {@inheritDoc}
	 * @see net.sf.hajdbc.DatabaseClusterConfiguration#getBalancerFactory()
	 */
	@Override
	public BalancerFactory getBalancerFactory()
	{
		return this.getNestedConfiguration().getBalancerFactory();
	}

	public void setBalancerFactory(BalancerFactory factory)
	{
		this.getNestedConfiguration().setBalancerFactory(factory);
	}
	
	/**
	 * {@inheritDoc}
	 * @see net.sf.hajdbc.DatabaseClusterConfiguration#getDispatcherFactory()
	 */
	@Override
	public CommandDispatcherFactory getDispatcherFactory()
	{
		return this.dispatcherFactory;
	}

	public void setDispatcherFactory(CommandDispatcherFactory factory)
	{
		this.dispatcherFactory = factory;
	}
	
	/**
	 * {@inheritDoc}
	 * @see net.sf.hajdbc.DatabaseClusterConfiguration#getDatabaseMap()
	 */
	@Override
	public ConcurrentMap getDatabaseMap()
	{
		return this.getNestedConfiguration().getDatabaseMap();
	}

	public void setDatabases(Collection databases)
	{
		Map map = this.getDatabaseMap();
		
		for (D database: databases)
		{
			map.put(database.getId(), database);
		}
	}
	
	/**
	 * {@inheritDoc}
	 * @see net.sf.hajdbc.DatabaseClusterConfiguration#getDatabaseMetaDataCacheFactory()
	 */
	@Override
	public DatabaseMetaDataCacheFactory getDatabaseMetaDataCacheFactory()
	{
		return this.getNestedConfiguration().getDatabaseMetaDataCacheFactory();
	}

	public void setDatabaseMetaDataCacheFactory(DatabaseMetaDataCacheFactory factory)
	{
		this.getNestedConfiguration().setDatabaseMetaDataCacheFactory(factory);
	}
	
	/**
	 * {@inheritDoc}
	 * @see net.sf.hajdbc.DatabaseClusterConfiguration#getDefaultSynchronizationStrategy()
	 */
	@Override
	public String getDefaultSynchronizationStrategy()
	{
		return this.getNestedConfiguration().getDefaultSynchronizationStrategy();
	}

	public void setDefaultSynchronizationStrategy(String strategy)
	{
		this.getNestedConfiguration().setDefaultSynchronizationStrategy(strategy);
	}
	
	/**
	 * {@inheritDoc}
	 * @see net.sf.hajdbc.DatabaseClusterConfiguration#getDialectFactory()
	 */
	@Override
	public DialectFactory getDialectFactory()
	{
		return this.getNestedConfiguration().getDialectFactory();
	}

	public void setDialectFactory(DialectFactory factory)
	{
		this.getNestedConfiguration().setDialectFactory(factory);
	}
	
	/**
	 * {@inheritDoc}
	 * @see net.sf.hajdbc.DatabaseClusterConfiguration#getDurabilityFactory()
	 */
	@Override
	public DurabilityFactory getDurabilityFactory()
	{
		return this.getNestedConfiguration().getDurabilityFactory();
	}

	public void setDurabilityFactory(DurabilityFactory factory)
	{
		this.getNestedConfiguration().setDurabilityFactory(factory);
	}
	
	/**
	 * {@inheritDoc}
	 * @see net.sf.hajdbc.DatabaseClusterConfiguration#getExecutorProvider()
	 */
	@Override
	public ExecutorServiceProvider getExecutorProvider()
	{
		return this.getNestedConfiguration().getExecutorProvider();
	}
	
	public void setExecutorProvider(ExecutorServiceProvider provider)
	{
		this.getNestedConfiguration().setExecutorProvider(provider);
	}
	
	/**
	 * {@inheritDoc}
	 * @see net.sf.hajdbc.DatabaseClusterConfiguration#getThreadFactory()
	 */
	@Override
	public ThreadFactory getThreadFactory()
	{
		return this.getNestedConfiguration().getThreadFactory();
	}

	public void setThreadFactory(ThreadFactory factory)
	{
		this.getNestedConfiguration().setThreadFactory(factory);
	}
	
	/**
	 * {@inheritDoc}
	 * @see net.sf.hajdbc.DatabaseClusterConfiguration#getDecoderFactory()
	 */
	@Override
	public DecoderFactory getDecoderFactory()
	{
		return this.getNestedConfiguration().getDecoderFactory();
	}

	public void setCodecFactory(DecoderFactory factory)
	{
		this.getNestedConfiguration().setDecoderFactory(factory);
	}
	
	/**
	 * {@inheritDoc}
	 * @see net.sf.hajdbc.DatabaseClusterConfiguration#getFailureDetectionExpression()
	 */
	@Override
	public CronExpression getFailureDetectionExpression()
	{
		return this.getNestedConfiguration().getFailureDetectionExpression();
	}

	public void setFailureDetectionExpression(CronExpression expression)
	{
		this.getNestedConfiguration().setFailureDetectionExpression(expression);
	}
	
	/**
	 * {@inheritDoc}
	 * @see net.sf.hajdbc.DatabaseClusterConfiguration#getStateManagerFactory()
	 */
	@Override
	public StateManagerFactory getStateManagerFactory()
	{
		return this.stateManagerFactory;
	}

	public void setStateManagerFactory(StateManagerFactory factory)
	{
		this.stateManagerFactory = factory;
	}
	
	@Override
	public LockManagerFactory getLockManagerFactory()
	{
		return this.lockManagerFactory;
	}

	public void setLockManagerFactory(LockManagerFactory factory)
	{
		this.lockManagerFactory = factory;
	}
	
	/**
	 * {@inheritDoc}
	 * @see net.sf.hajdbc.DatabaseClusterConfiguration#getSynchronizationStrategyMap()
	 */
	@Override
	public Map getSynchronizationStrategyMap()
	{
		return this.synchronizationStrategies;
	}

	public void setSynchronizationStrategyMap(Map strategies)
	{
		this.synchronizationStrategies = strategies;
	}
	
	/**
	 * {@inheritDoc}
	 * @see net.sf.hajdbc.DatabaseClusterConfiguration#getTransactionMode()
	 */
	@Override
	public TransactionMode getTransactionMode()
	{
		return this.getNestedConfiguration().getTransactionMode();
	}

	public void setTransactionMode(TransactionMode mode)
	{
		this.getNestedConfiguration().setTransactionMode(mode);
	}
	
	@Override
	public InputSinkProvider getInputSinkProvider()
	{
		return this.getNestedConfiguration().getInputSinkProvider();
	}

	public void setInputSinkFactoryProvider(InputSinkProvider provider)
	{
		this.getNestedConfiguration().setSinkSourceProvider(provider);
	}
	
	/**
	 * {@inheritDoc}
	 * @see net.sf.hajdbc.DatabaseClusterConfiguration#isCurrentDateEvaluationEnabled()
	 */
	@Override
	public boolean isCurrentDateEvaluationEnabled()
	{
		return this.getNestedConfiguration().isCurrentDateEvaluationEnabled();
	}

	public void setCurrentDateEvaluationEnabled(boolean enabled)
	{
		this.getNestedConfiguration().setCurrentDateEvaluationEnabled(enabled);
	}
	
	/**
	 * {@inheritDoc}
	 * @see net.sf.hajdbc.DatabaseClusterConfiguration#isCurrentTimeEvaluationEnabled()
	 */
	@Override
	public boolean isCurrentTimeEvaluationEnabled()
	{
		return this.getNestedConfiguration().isCurrentTimeEvaluationEnabled();
	}

	public void setCurrentTimeEvaluationEnabled(boolean enabled)
	{
		this.getNestedConfiguration().setCurrentTimeEvaluationEnabled(enabled);
	}
	
	/**
	 * {@inheritDoc}
	 * @see net.sf.hajdbc.DatabaseClusterConfiguration#isCurrentTimestampEvaluationEnabled()
	 */
	@Override
	public boolean isCurrentTimestampEvaluationEnabled()
	{
		return this.getNestedConfiguration().isCurrentTimestampEvaluationEnabled();
	}

	public void setCurrentTimestampEvaluationEnabled(boolean enabled)
	{
		this.getNestedConfiguration().setCurrentTimestampEvaluationEnabled(enabled);
	}
	
	/**
	 * {@inheritDoc}
	 * @see net.sf.hajdbc.DatabaseClusterConfiguration#isIdentityColumnDetectionEnabled()
	 */
	@Override
	public boolean isIdentityColumnDetectionEnabled()
	{
		return this.getNestedConfiguration().isIdentityColumnDetectionEnabled();
	}

	public void setIdentityColumnDetectionEnabled(boolean enabled)
	{
		this.getNestedConfiguration().setIdentityColumnDetectionEnabled(enabled);
	}
	
	/**
	 * {@inheritDoc}
	 * @see net.sf.hajdbc.DatabaseClusterConfiguration#isRandEvaluationEnabled()
	 */
	@Override
	public boolean isRandEvaluationEnabled()
	{
		return this.getNestedConfiguration().isRandEvaluationEnabled();
	}

	public void setRandEvaluationEnabled(boolean enabled)
	{
		this.getNestedConfiguration().setRandEvaluationEnabled(enabled);
	}
	
	/**
	 * {@inheritDoc}
	 * @see net.sf.hajdbc.DatabaseClusterConfiguration#isSequenceDetectionEnabled()
	 */
	@Override
	public boolean isSequenceDetectionEnabled()
	{
		return this.getNestedConfiguration().isSequenceDetectionEnabled();
	}
	
	public void setSequenceDetectionEnabled(boolean enabled)
	{
		this.getNestedConfiguration().setSequenceDetectionEnabled(enabled);
	}
	
	static Map> findDescriptors(Class targetClass) throws Exception
	{
		Map> map = new HashMap>();
		
		for (PropertyDescriptor descriptor: Introspector.getBeanInfo(targetClass).getPropertyDescriptors())
		{
			if ((descriptor.getReadMethod() != null) && (descriptor.getWriteMethod() != null))
			{
				PropertyEditor editor = PropertyEditorManager.findEditor(descriptor.getPropertyType());
				
				if (editor != null)
				{
					map.put(descriptor.getName(), new AbstractMap.SimpleImmutableEntry(descriptor, editor));
				}
			}
		}
		
		return map;
	}
	
	/**
	 * {@inheritDoc}
	 * @see net.sf.hajdbc.DatabaseClusterConfiguration#getMBeanRegistrar()
	 */
	@Override
	public MBeanRegistrar getMBeanRegistrar()
	{
		return this.getNestedConfiguration().getMBeanRegistrar();
	}

	public void setMBeanRegistrar(MBeanRegistrar registrar)
	{
		this.getNestedConfiguration().setMBeanRegistrar(registrar);
	}
	
	/**
	 * {@inheritDoc}
	 * @see net.sf.hajdbc.DatabaseClusterConfiguration#isEmptyClusterAllowed()
	 */
	@Override
	public boolean isEmptyClusterAllowed()
	{
		return this.getNestedConfiguration().isEmptyClusterAllowed();
	}

	public void setEmptyClusterAllowed(boolean emptyClusterAllowed)
	{
		this.getNestedConfiguration().setEmptyClusterAllowed(emptyClusterAllowed);
	}
	
	/**
	 * {@inheritDoc}
	 * @see net.sf.hajdbc.DatabaseClusterConfiguration#getTransactionIdentifierFactory()
	 */
	@Override
	public TransactionIdentifierFactory getTransactionIdentifierFactory()
	{
		return (this.dispatcherFactory != null) ? new UUIDTransactionIdentifierFactory() : new SimpleTransactionIdentifierFactory();
	}

	@XmlType(name = "abstractNestedConfiguration")
	protected static abstract class NestedConfiguration> implements DatabaseClusterConfiguration, DatabaseFactory
	{
		private static final long serialVersionUID = -5674156614205147546L;

		@XmlJavaTypeAdapter(BalancerFactoryAdapter.class)
		@XmlAttribute(name = "balancer")
		private BalancerFactory balancerFactory = ServiceLoaders.findService(BalancerFactory.class);
		
		@XmlJavaTypeAdapter(DatabaseMetaDataCacheFactoryAdapter.class)
		@XmlAttribute(name = "meta-data-cache")
		private DatabaseMetaDataCacheFactory databaseMetaDataCacheFactory = ServiceLoaders.findService(DatabaseMetaDataCacheFactory.class);
		
		@XmlJavaTypeAdapter(DialectFactoryAdapter.class)
		@XmlAttribute(name = "dialect")
		private DialectFactory dialectFactory = ServiceLoaders.findService(DialectFactory.class);
		
		@XmlJavaTypeAdapter(DurabilityFactoryAdapter.class)
		@XmlAttribute(name = "durability")
		private DurabilityFactory durabilityFactory = ServiceLoaders.findService(DurabilityFactory.class);

		@XmlJavaTypeAdapter(SinkSourceProviderAdapter.class)
		@XmlAttribute(name = "input-sink")
		private InputSinkProvider sinkSourceProvider = ServiceLoaders.findService(InputSinkProvider.class);
		
		private ExecutorServiceProvider executorProvider = new DefaultExecutorServiceProvider();
		private ThreadFactory threadFactory = Executors.defaultThreadFactory();
		private DecoderFactory decoderFactory = new MultiplexingDecoderFactory();
		private MBeanRegistrar registrar = new DefaultMBeanRegistrar();
		
		@XmlJavaTypeAdapter(TransactionModeAdapter.class)
		@XmlAttribute(name = "transaction-mode")
		private TransactionMode transactionMode = TransactionModeEnum.SERIAL;

		@XmlJavaTypeAdapter(CronExpressionAdapter.class)
		@XmlAttribute(name = "auto-activate-schedule")
		private CronExpression autoActivationExpression;
		@XmlJavaTypeAdapter(CronExpressionAdapter.class)
		@XmlAttribute(name = "failure-detect-schedule")
		private CronExpression failureDetectionExpression;
		
		@XmlAttribute(name = "eval-current-date")
		private Boolean currentDateEvaluationEnabled = false;
		@XmlAttribute(name = "eval-current-time")
		private Boolean currentTimeEvaluationEnabled = false;
		@XmlAttribute(name = "eval-current-timestamp")
		private Boolean currentTimestampEvaluationEnabled = false;
		@XmlAttribute(name = "eval-rand")
		private Boolean randEvaluationEnabled = false;
		
		@XmlAttribute(name = "detect-identity-columns")
		private Boolean identityColumnDetectionEnabled = false;
		@XmlAttribute(name = "detect-sequences")
		private Boolean sequenceDetectionEnabled = false;

		@XmlAttribute(name = "allow-empty-cluster")
		private Boolean emptyClusterAllowed = false;
		
		private String defaultSynchronizationStrategy;
		
		private ConcurrentMap databases = new ConcurrentHashMap();
		
		@Override
		public DatabaseFactory getDatabaseFactory()
		{
			return this;
		}

		@XmlIDREF
		@XmlAttribute(name = "default-sync", required = true)
		private SynchronizationStrategyDescriptor getDefaultSynchronizationStrategyDescriptor()
		{
			SynchronizationStrategyDescriptor descriptor = new SynchronizationStrategyDescriptor();
			descriptor.setId(this.defaultSynchronizationStrategy);
			return descriptor;
		}
		
		@SuppressWarnings("unused")
		private void setDefaultSynchronizationStrategyDescriptor(SynchronizationStrategyDescriptor descriptor)
		{
			this.defaultSynchronizationStrategy = descriptor.getId();
		}
		
		@Override
		public ConcurrentMap getDatabaseMap()
		{
			return this.databases;
		}
		
		@Override
		public CronExpression getAutoActivationExpression()
		{
			return this.autoActivationExpression;
		}

		void setAutoActivationExpression(CronExpression expression)
		{
			this.autoActivationExpression = expression;
		}
		
		@Override
		public BalancerFactory getBalancerFactory()
		{
			return this.balancerFactory;
		}

		void setBalancerFactory(BalancerFactory factory)
		{
			this.balancerFactory = factory;
		}
		
		@Override
		public CommandDispatcherFactory getDispatcherFactory()
		{
			throw new IllegalStateException();
		}

		@Override
		public DatabaseMetaDataCacheFactory getDatabaseMetaDataCacheFactory()
		{
			return this.databaseMetaDataCacheFactory;
		}

		void setDatabaseMetaDataCacheFactory(DatabaseMetaDataCacheFactory factory)
		{
			this.databaseMetaDataCacheFactory = factory;
		}
		
		@Override
		public String getDefaultSynchronizationStrategy()
		{
			return this.defaultSynchronizationStrategy;
		}

		void setDefaultSynchronizationStrategy(String strategy)
		{
			this.defaultSynchronizationStrategy = strategy;
		}
		
		@Override
		public DialectFactory getDialectFactory()
		{
			return this.dialectFactory;
		}

		void setDialectFactory(DialectFactory factory)
		{
			this.dialectFactory = factory;
		}
		
		@Override
		public DurabilityFactory getDurabilityFactory()
		{
			return this.durabilityFactory;
		}

		void setDurabilityFactory(DurabilityFactory factory)
		{
			this.durabilityFactory = factory;
		}
		
		@Override
		public ExecutorServiceProvider getExecutorProvider()
		{
			return this.executorProvider;
		}

		void setExecutorProvider(ExecutorServiceProvider provider)
		{
			this.executorProvider = provider;
		}
		
		@Override
		public ThreadFactory getThreadFactory()
		{
			return this.threadFactory;
		}

		void setThreadFactory(ThreadFactory factory)
		{
			this.threadFactory = factory;
		}
		
		@Override
		public DecoderFactory getDecoderFactory()
		{
			return this.decoderFactory;
		}

		void setDecoderFactory(DecoderFactory factory)
		{
			this.decoderFactory = factory;
		}
		
		@Override
		public MBeanRegistrar getMBeanRegistrar()
		{
			return this.registrar;
		}
		
		void setMBeanRegistrar(MBeanRegistrar registrar)
		{
			this.registrar = registrar;
		}
		
		@Override
		public CronExpression getFailureDetectionExpression()
		{
			return this.failureDetectionExpression;
		}

		void setFailureDetectionExpression(CronExpression expression)
		{
			this.failureDetectionExpression = expression;
		}
		
		@Override
		public StateManagerFactory getStateManagerFactory()
		{
			throw new IllegalStateException();
		}
		
		@Override
		public LockManagerFactory getLockManagerFactory()
		{
			throw new IllegalStateException();
		}

		@Override
		public Map getSynchronizationStrategyMap()
		{
			throw new IllegalStateException();
		}
		
		@Override
		public TransactionMode getTransactionMode()
		{
			return this.transactionMode;
		}

		void setTransactionMode(TransactionMode mode)
		{
			this.transactionMode = mode;
		}
		
		@Override
		public InputSinkProvider getInputSinkProvider()
		{
			return this.sinkSourceProvider;
		}

		void setSinkSourceProvider(InputSinkProvider provider)
		{
			this.sinkSourceProvider = provider;
		}
		
		@Override
		public boolean isCurrentDateEvaluationEnabled()
		{
			return this.currentDateEvaluationEnabled;
		}
		
		void setCurrentDateEvaluationEnabled(boolean enabled)
		{
			this.currentDateEvaluationEnabled = enabled;
		}
		
		@Override
		public boolean isCurrentTimeEvaluationEnabled()
		{
			return this.currentTimeEvaluationEnabled;
		}
		
		void setCurrentTimeEvaluationEnabled(boolean enabled)
		{
			this.currentTimeEvaluationEnabled = enabled;
		}
		
		@Override
		public boolean isCurrentTimestampEvaluationEnabled()
		{
			return this.currentTimestampEvaluationEnabled;
		}
		
		void setCurrentTimestampEvaluationEnabled(boolean enabled)
		{
			this.currentTimestampEvaluationEnabled = enabled;
		}
		
		@Override
		public boolean isIdentityColumnDetectionEnabled()
		{
			return this.identityColumnDetectionEnabled;
		}
		
		void setIdentityColumnDetectionEnabled(boolean enabled)
		{
			this.identityColumnDetectionEnabled = enabled;
		}
		
		@Override
		public boolean isRandEvaluationEnabled()
		{
			return this.randEvaluationEnabled;
		}

		void setRandEvaluationEnabled(boolean enabled)
		{
			this.randEvaluationEnabled = enabled;
		}
		
		@Override
		public boolean isSequenceDetectionEnabled()
		{
			return this.sequenceDetectionEnabled;
		}
		
		void setSequenceDetectionEnabled(boolean enabled)
		{
			this.sequenceDetectionEnabled = enabled;
		}

		@Override
		public TransactionIdentifierFactory getTransactionIdentifierFactory()
		{
			throw new IllegalStateException();
		}

		/* (non-Javadoc)
		 * @see net.sf.hajdbc.DatabaseClusterConfiguration#isEmptyClusterAllowed()
		 */
		@Override
		public boolean isEmptyClusterAllowed()
		{
			return this.emptyClusterAllowed;
		}
		
		void setEmptyClusterAllowed(boolean emptyClusterAllowed)
		{
			this.emptyClusterAllowed = emptyClusterAllowed;
		}
	}

	static class IdentifiableServiceAdapter extends XmlAdapter
	{
		private final Class serviceClass;
		
		IdentifiableServiceAdapter(Class serviceClass)
		{
			this.serviceClass = serviceClass;
		}

		@Override
		public T unmarshal(final String value)
		{
			return ServiceLoaders.findRequiredService(new IdentifiableMatcher(value), this.serviceClass);
		}

		@Override
		public String marshal(T service)
		{
			return service.getId();
		}
	}

	static class BalancerFactoryAdapter extends IdentifiableServiceAdapter
	{
		BalancerFactoryAdapter()
		{
			super(BalancerFactory.class);
		}
	}

	static class DatabaseMetaDataCacheFactoryAdapter extends IdentifiableServiceAdapter
	{
		DatabaseMetaDataCacheFactoryAdapter()
		{
			super(DatabaseMetaDataCacheFactory.class);
		}
	}

	static class DurabilityFactoryAdapter extends IdentifiableServiceAdapter
	{
		DurabilityFactoryAdapter()
		{
			super(DurabilityFactory.class);
		}
	}

	static class TransactionModeAdapter extends EnumAdapter
	{
		@Override
		protected Class getTargetClass()
		{
			return TransactionModeEnum.class;
		}
	}

	static abstract class EnumAdapter extends XmlAdapter
	{
		@Override
		public I unmarshal(E enumerated)
		{
			return enumerated;
		}
		
		@Override
		public E marshal(I object)
		{
			return this.getTargetClass().cast(object);
		}

		protected abstract Class getTargetClass();
	}

	static class DialectFactoryAdapter extends IdentifiableServiceAdapter
	{
		DialectFactoryAdapter()
		{
			super(DialectFactory.class);
		}
	}

	static class SinkSourceProviderAdapter extends IdentifiableServiceAdapter
	{
		SinkSourceProviderAdapter()
		{
			super(InputSinkProvider.class);
		}
	}
	
	static class CronExpressionAdapter extends XmlAdapter
	{
		@Override
		public String marshal(CronExpression expression)
		{
			return (expression != null) ? expression.getCronExpression() : null;
		}

		@Override
		public CronExpression unmarshal(String value) throws Exception
		{
			return (value != null) ? new CronExpression(value) : null;
		}
	}
	
	@XmlType
	static class CommandDispatcherFactoryDescriptor extends IdentifiableServiceDescriptor
	{
		@XmlAttribute(name = "id", required = false)
		private String id = "jgroups";
		
		@Override
		public String getId()
		{
			return this.id;
		}
		
		@Override
		public void setId(String id)
		{
			this.id = id;
		}
	}

	static class CommandDispatcherFactoryDescriptorAdapter extends IdentifiableServiceDescriptorAdapter
	{
		CommandDispatcherFactoryDescriptorAdapter()
		{
			super(CommandDispatcherFactory.class, CommandDispatcherFactoryDescriptor.class);
		}
	}
	
	@XmlType
	static class SynchronizationStrategyDescriptor extends IdentifiableServiceDescriptor
	{
		@XmlID
		@XmlAttribute(name = "id", required = true)
		private String id;
		
		@Override
		public String getId()
		{
			return this.id;
		}
		
		@Override
		public void setId(String id)
		{
			this.id = id;
		}
	}
	
	static class SynchronizationStrategyDescriptorAdapter extends IdentifiableServiceDescriptorAdapter
	{
		SynchronizationStrategyDescriptorAdapter()
		{
			super(SynchronizationStrategy.class, SynchronizationStrategyDescriptor.class);
		}
	}
	
	@XmlType
	static class StateManagerFactoryDescriptor extends IdentifiableServiceDescriptor
	{
		@XmlAttribute(name = "id", required = true)
		private String id;
		
		@Override
		public String getId()
		{
			return this.id;
		}
		
		@Override
		public void setId(String id)
		{
			this.id = id;
		}
	}

	static class StateManagerFactoryDescriptorAdapter extends IdentifiableServiceDescriptorAdapter
	{
		StateManagerFactoryDescriptorAdapter()
		{
			super(StateManagerFactory.class, StateManagerFactoryDescriptor.class);
		}
	}
	
	@XmlType
	static class LockManagerFactoryDescriptor extends IdentifiableServiceDescriptor
	{
		@XmlAttribute(name = "id", required = true)
		private String id;
		
		@Override
		public String getId()
		{
			return this.id;
		}
		
		@Override
		public void setId(String id)
		{
			this.id = id;
		}
	}

	static class LockManagerFactoryDescriptorAdapter extends IdentifiableServiceDescriptorAdapter
	{
		LockManagerFactoryDescriptorAdapter()
		{
			super(LockManagerFactory.class, LockManagerFactoryDescriptor.class);
		}
	}

	static abstract class IdentifiableServiceDescriptor implements Identifiable
	{
		@XmlElement(name = "property")
		private List properties;
		
		public List getProperties()
		{
			return this.properties;
		}

		public void setProperties(List properties)
		{
			this.properties = properties;
		}
		
		public abstract void setId(String id);
	}

	static class IdentifiableServiceDescriptorAdapter extends XmlAdapter
	{
		private final Class serviceClass;
		private final Class descriptorClass;
		
		IdentifiableServiceDescriptorAdapter(Class serviceClass, Class descriptorClass)
		{
			this.serviceClass = serviceClass;
			this.descriptorClass = descriptorClass;
		}
		
		@Override
		public D marshal(T object) throws Exception
		{
			D result = this.descriptorClass.newInstance();
			List properties = new LinkedList();
			
			result.setId(object.getId());
			result.setProperties(properties);
			
			for (Map.Entry entry: findDescriptors(object.getClass()).values())
			{
				PropertyDescriptor descriptor = entry.getKey();
				PropertyEditor editor = entry.getValue();
				
				Object value = descriptor.getReadMethod().invoke(object);
				if (value != null)
				{
					editor.setValue(value);
					
					Property property = new Property();
					property.setName(descriptor.getName());
					property.setValue(editor.getAsText());
					
					properties.add(property);
				}
			}
			
			return result;
		}

		@Override
		public T unmarshal(D target) throws Exception
		{
			T result = ServiceLoaders.findRequiredService(new IdentifiableMatcher(target.getId()), this.serviceClass);
			List properties = target.getProperties();
			
			if (properties != null)
			{
				Map> descriptors = findDescriptors(result.getClass());
				
				for (Property property: properties)
				{
					String name = property.getName();
					Map.Entry entry = descriptors.get(name);
					
					if (entry == null)
					{
						throw new IllegalArgumentException(Messages.INVALID_PROPERTY.getMessage(name, result.getClass().getName()));
					}
					
					PropertyDescriptor descriptor = entry.getKey();
					PropertyEditor editor = entry.getValue();

					String textValue = property.getValue();
					
					try
					{
						editor.setAsText(textValue);
					}
					catch (Exception e)
					{
						throw new IllegalArgumentException(Messages.INVALID_PROPERTY_VALUE.getMessage(textValue, name, result.getClass().getName()));
					}
					descriptor.getWriteMethod().invoke(result, editor.getValue());
				}
			}
			return result;
		}
	}

	@XmlType
	protected static class Property
	{
		@XmlAttribute(required = true)
		private String name;
		@XmlValue
		private String value;
		
		public String getName()
		{
			return this.name;
		}
		
		public void setName(String name)
		{
			this.name = name;
		}
		
		public String getValue()
		{
			return this.value;
		}
		
		public void setValue(String value)
		{
			this.value = value;
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy