com.impetus.kundera.loader.GenericClientFactory.java Source code

Java tutorial

Introduction

Here is the source code for com.impetus.kundera.loader.GenericClientFactory.java

Source

/*******************************************************************************
 * * Copyright 2012 Impetus Infotech.
 *  *
 *  * Licensed 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 com.impetus.kundera.loader;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.impetus.kundera.KunderaException;
import com.impetus.kundera.PersistenceProperties;
import com.impetus.kundera.client.Client;
import com.impetus.kundera.configure.PropertyReader;
import com.impetus.kundera.configure.schema.api.SchemaManager;
import com.impetus.kundera.index.IndexManager;
import com.impetus.kundera.index.Indexer;
import com.impetus.kundera.index.IndexingConstants;
import com.impetus.kundera.metadata.model.ClientMetadata;
import com.impetus.kundera.persistence.EntityManagerFactoryImpl.KunderaMetadata;
import com.impetus.kundera.persistence.EntityReader;
import com.impetus.kundera.service.Host;
import com.impetus.kundera.service.policy.LoadBalancingPolicy;
import com.impetus.kundera.service.policy.RetryService;
import com.impetus.kundera.service.policy.RoundRobinBalancingPolicy;
import com.impetus.kundera.utils.InvalidConfigurationException;

/**
 * Abstract class to hold generic definitions for client factory
 * implementations.
 * 
 * @author vivek.mishra
 */
public abstract class GenericClientFactory implements ClientFactory, ClientLifeCycleManager {

    /** The logger. */
    private static Logger logger = LoggerFactory.getLogger(GenericClientFactory.class);

    /** The client. */
    private Client client;

    /** The persistence unit. */
    private String persistenceUnit;

    /** The connection pool or connection. */
    private Object connectionPoolOrConnection;

    /** The reader. */
    protected EntityReader reader;

    /** Configure schema manager. */
    protected SchemaManager schemaManager;

    /** property reader instance */
    protected PropertyReader propertyReader;

    /** Holds persistence unit related property */
    protected Map<String, Object> externalProperties = new HashMap<String, Object>();

    /** Holds LoadBalancer instance **/
    protected LoadBalancingPolicy loadBalancingPolicy = new RoundRobinBalancingPolicy();

    /** Holds Instance of retry service */
    protected RetryService hostRetryService;

    /** Holds one pool instance per host */
    protected ConcurrentMap<Host, Object> hostPools = new ConcurrentHashMap<Host, Object>();

    /**
     * Holds reference to client metadata.
     */
    protected ClientMetadata clientMetadata;

    /** kundera metadata */
    protected KunderaMetadata kunderaMetadata;

    /** The index manager. */
    protected IndexManager indexManager = new IndexManager(null, kunderaMetadata);

    /**
     * Load.
     * 
     * @param persistenceUnit
     *            the persistence unit
     */
    @Override
    public void load(String persistenceUnit, Map<String, Object> puProperties) {
        setPersistenceUnit(persistenceUnit);

        // Load Client Specific Stuff
        logger.info("Loading client metadata for persistence unit : " + persistenceUnit);
        loadClientMetadata(puProperties);

        // initialize the client
        logger.info("Initializing client for persistence unit : " + persistenceUnit);
        initialize(puProperties);

        // Construct Pool
        logger.info("Constructing pool for persistence unit : " + persistenceUnit);
        connectionPoolOrConnection = createPoolOrConnection();
    }

    /**
     * Load client metadata.
     * 
     * @param puProperties
     */
    protected void loadClientMetadata(Map<String, Object> puProperties) {
        clientMetadata = new ClientMetadata();
        String luceneDirectoryPath = puProperties != null
                ? (String) puProperties.get(PersistenceProperties.KUNDERA_INDEX_HOME_DIR)
                : null;

        String indexerClass = puProperties != null
                ? (String) puProperties.get(PersistenceProperties.KUNDERA_INDEXER_CLASS)
                : null;

        String autoGenClass = puProperties != null
                ? (String) puProperties.get(PersistenceProperties.KUNDERA_AUTO_GENERATOR_CLASS)
                : null;

        if (indexerClass == null) {
            indexerClass = kunderaMetadata.getApplicationMetadata().getPersistenceUnitMetadata(persistenceUnit)
                    .getProperties().getProperty(PersistenceProperties.KUNDERA_INDEXER_CLASS);
        }
        if (autoGenClass == null) {
            autoGenClass = kunderaMetadata.getApplicationMetadata().getPersistenceUnitMetadata(persistenceUnit)
                    .getProperties().getProperty(PersistenceProperties.KUNDERA_AUTO_GENERATOR_CLASS);
        }

        if (luceneDirectoryPath == null) {
            luceneDirectoryPath = kunderaMetadata.getApplicationMetadata()
                    .getPersistenceUnitMetadata(persistenceUnit)
                    .getProperty(PersistenceProperties.KUNDERA_INDEX_HOME_DIR);
        }

        if (autoGenClass != null) {
            clientMetadata.setAutoGenImplementor(autoGenClass);
        }

        // in case set empty via external property, means want to avoid lucene
        // directory set up.
        if (luceneDirectoryPath != null && !StringUtils.isEmpty(luceneDirectoryPath)) {
            // Add client metadata
            clientMetadata.setLuceneIndexDir(luceneDirectoryPath);

            // Set Index Manager

            try {
                Method method = Class.forName(IndexingConstants.LUCENE_INDEXER).getDeclaredMethod("getInstance",
                        String.class);

                Indexer indexer = (Indexer) method.invoke(null, luceneDirectoryPath);
                indexManager = new IndexManager(indexer, kunderaMetadata);
            } catch (Exception e) {
                logger.error(
                        "Missing lucene from classpath. Please make sure those are available to load lucene directory {}!",
                        luceneDirectoryPath);
                throw new InvalidConfigurationException(e);
            }

            // indexManager = new IndexManager(LuceneIndexer.getInstance(new
            // StandardAnalyzer(Version.LUCENE_CURRENT),
            // luceneDirectoryPath));
        } else if (indexerClass != null) {
            try {
                Class<?> indexerClazz = Class.forName(indexerClass);
                Indexer indexer = (Indexer) indexerClazz.newInstance();
                indexManager = new IndexManager(indexer, kunderaMetadata);
                clientMetadata.setIndexImplementor(indexerClass);
            } catch (Exception cnfex) {
                logger.error("Error while initialzing indexer:" + indexerClass, cnfex);
                throw new KunderaException(cnfex);
            }
        } else {
            indexManager = new IndexManager(null, kunderaMetadata);
        }
        // if
        // (kunderaMetadata.getClientMetadata(persistenceUnit)
        // ==
        // null)
        // {
        // kunderaMetadata.addClientMetadata(persistenceUnit,
        // clientMetadata);
        // }
    }

    /**
     * Initialize client.
     * 
     * @param puProperties
     */
    public abstract void initialize(Map<String, Object> puProperties);

    /**
     * Creates a new GenericClient object.
     * 
     * @param externalProperties
     * 
     * @return the object
     */
    protected abstract Object createPoolOrConnection();

    /**
     * Gets the client instance.
     * 
     * @return the client instance
     */
    @Override
    public Client getClientInstance() {
        // if threadsafe recycle the same single instance; if not create a new
        // instance

        if (isThreadSafe()) {
            logger.info("Returning threadsafe used client instance for persistence unit : " + persistenceUnit);
            if (client == null) {
                client = instantiateClient(persistenceUnit);
            }
        } else {
            logger.debug("Returning fresh client instance for persistence unit : " + persistenceUnit);
            // no need to hold a client reference.
            return instantiateClient(persistenceUnit);
        }

        return client;
    }

    /**
     * Instantiate client.
     * 
     * @return the client
     */
    protected abstract Client instantiateClient(String persistenceUnit);

    /**
     * Checks if is client thread safe.
     * 
     * @return true, if is client thread safe
     */
    public abstract boolean isThreadSafe();

    /**
     * Gets the persistence unit.
     * 
     * @return the persistence unit
     */
    protected String getPersistenceUnit() {
        return persistenceUnit;
    }

    /**
     * Gets the connection pool or connection.
     * 
     * @return the connection pool or connection
     */
    protected Object getConnectionPoolOrConnection() {
        return connectionPoolOrConnection;
    }

    /**
     * Sets the connection pool or connection.
     */
    protected void setConnectionPoolOrConnection(Object connectionPoolOrConnection) {
        this.connectionPoolOrConnection = connectionPoolOrConnection;
    }

    /**
     * Sets the persistence unit.
     * 
     * @param persistenceUnit
     *            the new persistence unit
     */
    private void setPersistenceUnit(String persistenceUnit) {
        this.persistenceUnit = persistenceUnit;
    }

    /**
     * Sets the persistence unit.
     * 
     * @param persistenceUnit
     *            the new persistence unit
     */
    protected void setKunderaMetadata(KunderaMetadata kunderaMetadata) {
        this.kunderaMetadata = kunderaMetadata;
    }

    /**
     * @param puProperties
     */
    protected void setExternalProperties(Map<String, Object> puProperties) {
        if (puProperties != null) {
            this.externalProperties = puProperties;
        }
    }

    protected void onValidation(final String host, final String port) {
        if (host == null || !StringUtils.isNumeric(port) || port.isEmpty()) {
            logger.error("Host or port should not be null / port should be numeric");
            throw new IllegalArgumentException("Host or port should not be null / port should be numeric");
        }
    }

    protected void unload() {
        if (client != null) {
            client.close();
            client = null;
        }
        externalProperties = null;
        hostPools.clear();
    }

    protected abstract void initializeLoadBalancer(String loadBalancingPolicyName);

    public ClientMetadata getClientMetadata() {
        return this.clientMetadata;
    }

    protected enum LoadBalancer {
        ROUNDROBIN, LEASTACTIVE;

        public static LoadBalancer getValue(String loadBalancename) {
            if (loadBalancename != null && loadBalancename.equalsIgnoreCase(ROUNDROBIN.name())) {
                return ROUNDROBIN;
            } else if (loadBalancename != null && loadBalancename.equalsIgnoreCase(LEASTACTIVE.name())) {
                return LEASTACTIVE;
            } else {
                logger.info("Using default load balancer {} . " + ROUNDROBIN.name());
                return ROUNDROBIN;
            }
        }
    }
}