Package com.force.sdk.jpa

Source Code of com.force.sdk.jpa.ForceStoreManager

/**
* Copyright (c) 2011, salesforce.com, inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided
* that the following conditions are met:
*
*    Redistributions of source code must retain the above copyright notice, this list of conditions and the
*    following disclaimer.
*
*    Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
*    the following disclaimer in the documentation and/or other materials provided with the distribution.
*
*    Neither the name of salesforce.com, inc. nor the names of its contributors may be used to endorse or
*    promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/

package com.force.sdk.jpa;

import java.lang.reflect.Field;
import java.util.*;

import org.datanucleus.*;
import org.datanucleus.metadata.AbstractClassMetaData;
import org.datanucleus.plugin.PluginManager;
import org.datanucleus.plugin.PluginRegistry;
import org.datanucleus.store.*;

import com.force.sdk.connector.ForceConnectorConfig;
import com.force.sdk.connector.ForceConnectorUtils;
import com.force.sdk.jpa.schema.*;
import com.force.sdk.jpa.table.TableImpl;

/**
*
* Store manager that holds all the persistence.xml properties.
*
* @author Fiaz Hossain
*/
public class ForceStoreManager extends AbstractStoreManager {

    /**
     * Store manager type for Force.com JPA.
     */
    public static final String FORCE_KEY = "force";
   
    private static final String FORCE_PREFIX = FORCE_KEY + "://";
   
    // Connection information for the persistence layer to
    // get a connection to the Force.com service
    private ForceConnectorConfig config;
   
    private boolean autoCreateTables = false;
    private boolean autoCreateColumns = false;
    private boolean autoCreateWarnOnError = false;
   
    private int poolTimeBetweenEvictionRunsMillis;
    private int poolMinEvictableIdleTimeMillis;
    ForceMetaDataListener metadataListener;
    private final boolean enableOptimisticTransactions;
    private ForceSchemaWriter schemaWriter;
    private final boolean forDelete;

    /**
     * Looks into system variable and environment variables if url is in ${...} format.
     * @return Connection URL
     */
    @Override
    public String getConnectionURL() {
        String connectionUrl = super.getConnectionURL();

        if (ForceConnectorUtils.isInjectable(connectionUrl)) {
            connectionUrl = ForceConnectorUtils.extractValue(connectionUrl);
            if (connectionUrl == null || connectionUrl.equals("")) {
                throw new IllegalArgumentException("Unable to load ForceConnectorConfig from environment or system property "
                        + super.getConnectionURL());
            }
        }

        return connectionUrl;
    }

    /**
     * Creates a store manager for use with the Force.com API. Set up the API connection
     * configs, set some default properties and read in values from persistence.xml
     *
     * @param clr  the class loader resolver
     * @param omfContext the corresponding object manager factory context
     * @throws NoSuchFieldException thrown if there is a problem setting up the plugin manager
     * @throws IllegalAccessException thrown if there is a problem setting up the plugin manager
     */
    public ForceStoreManager(ClassLoaderResolver clr, OMFContext omfContext) throws NoSuchFieldException, IllegalAccessException {
        super(FORCE_KEY, clr, omfContext);
   
        String endpoint = getConnectionURL();



       
        // Grab the connection information from persistence.xml.  If none exists,
        // we'll use the unit name (see ForceMetaDataManager.loadPersistenceUnit
        // and ForceConnectionFactory.createManagedConnection).
        if (endpoint != null) {
            config = new ForceConnectorConfig();
           
            // Treat any url starting with force:// as a connection url
            if (endpoint.startsWith(FORCE_PREFIX)) {
                config.setConnectionUrl(endpoint);
            // Any other endpoint, we'll treat as a normal Force.com API url
            } else {
                config.setAuthEndpoint(endpoint);
                config.setUsername(getConnectionUserName());
                config.setPassword(getConnectionPassword());
            }
        }
       
        setCustomPluginManager();
       
        // Handler for metadata
        metadataListener = new ForceMetaDataListener(this);
        omfContext.getMetaDataManager().registerListener(metadataListener);

        // Handler for persistence process
        persistenceHandler2 = new ForcePersistenceHandler(this);
       
        // Store schema handler
        schemaHandler = new ForceStoreSchemaHandler(this);
       
        PersistenceConfiguration conf = omfContext.getPersistenceConfiguration();
        boolean autoCreateSchema = conf.getBooleanProperty("datanucleus.autoCreateSchema");
        if (autoCreateSchema) {
            autoCreateTables = true;
            autoCreateColumns = true;
        } else {
            autoCreateTables = conf.getBooleanProperty("datanucleus.autoCreateTables");
            autoCreateColumns = conf.getBooleanProperty("datanucleus.autoCreateColumns");
        }
        autoCreateWarnOnError = conf.getBooleanProperty("datanucleus.autoCreateWarnOnError");
        forDelete = conf.getBooleanProperty("force.deleteSchema");
        boolean purgeOnDelete = conf.getBooleanProperty("force.purgeOnDeleteSchema");
       
        schemaWriter = new ForceSchemaWriter(new SchemaDeleteProperty(forDelete, purgeOnDelete));
       
        // how often should the evictor run
        poolTimeBetweenEvictionRunsMillis = conf.getIntProperty("datanucleus.connectionPool.timeBetweenEvictionRunsMillis");
        if (poolTimeBetweenEvictionRunsMillis == 0) {
            poolTimeBetweenEvictionRunsMillis = 15 * 1000; // default, 15 secs
        }
        
        // how long may a connection sit idle in the pool before it may be evicted
        poolMinEvictableIdleTimeMillis = conf.getIntProperty("datanucleus.connectionPool.minEvictableIdleTimeMillis");
        if (poolMinEvictableIdleTimeMillis == 0) {
            poolMinEvictableIdleTimeMillis = 30 * 1000; // default, 30 secs
        }
       
        // setup optimistic enabled
        Object isEnabled = omfContext.getPersistenceConfiguration().getProperty("datanucleus.Optimistic");
        enableOptimisticTransactions = isEnabled != null && (isEnabled instanceof Boolean && isEnabled.equals(Boolean.TRUE)
                || isEnabled instanceof String && "true".equals(isEnabled));
       
        logConfiguration();
    }
   
    private void setCustomPluginManager() throws NoSuchFieldException, IllegalAccessException {
        PluginManager pluginMgr = omfContext.getPluginManager();
        Field registryField = PluginManager.class.getDeclaredField("registry");
        registryField.setAccessible(true);
        registryField.set(pluginMgr, new ForcePluginRegistry((PluginRegistry) registryField.get(pluginMgr)));
    }

    @Override
    protected void registerConnectionMgr() {
        super.registerConnectionMgr();
        this.connectionMgr.disableConnectionPool();
    }

    public ForceConnectorConfig getConfig() {
        return config;
    }
   
    /**
     * Releases resources.
     */
    @Override
    public void close() {
        omfContext.getMetaDataManager().deregisterListener(metadataListener);
        super.close();
    }

    @Override
    public NucleusConnection getNucleusConnection(ExecutionContext om) {
        return new NativeConnection(getConnection(om));
    }

    /**
     * Accessor for the supported options in string form.
     * {@inheritDoc}
     */
    @Override
    public Collection getSupportedOptions() {
        Set<String> set = new HashSet<String>();
        set.add("ApplicationIdentity");
        set.add("OptimisticTransaction");
        set.add("TransactionIsolationLevel.read-committed");
        return set;
    }
   
    /**
     * Specifies whether fields should be created automatically on app startup.
     * @return {@code true} if fields should be created
     */
    public boolean isAutoCreateColumns() {
        return autoCreateColumns;
    }
   
    /**
     * Specifies whether objects should be created automatically on app startup.
     * @return {@code true} if objects should be created
     */
    public boolean isAutoCreateTables() {
        return autoCreateTables;
    }
   
    /**
     * Used for schema mismatches. For example, a column or table is specified in an application,
     * but the column or table doesn't exist in the Force.com organization, and schema creation
     * is turned OFF for field or columns. Value defaults to {@code false} but can be set in persistence.xml,
     * if true warnings will be logged, exceptions will not be thrown.
     *
     * @return {@code true} if schema mismatches should log warnings, {@code false} if they should throw errors
     */
    public boolean isAutoCreateWarnOnError() {
        return autoCreateWarnOnError;
    }
   
    public int getPoolMinEvictableIdleTimeMillis() {
        return poolMinEvictableIdleTimeMillis;
    }
   
    public int getPoolTimeBetweenEvictionRunsMillis() {
        return poolTimeBetweenEvictionRunsMillis;
    }
   
    /**
     * Retrieves Force.com table information from JPA class metadata.
     *
     * @param acmd JPA class metadata
     * @return Force.com table information
     */
    public TableImpl getTable(AbstractClassMetaData acmd) {
        ForceStoreSchemaHandler sh = (ForceStoreSchemaHandler) getSchemaHandler();
        return sh.getTable(acmd);
    }
   
    /**
     * Registers a table with the schema handler.
     *
     * @param acmd the class metadata of the table to register
     * @param mconn the managed connection to the Force.com APIs
     * @return the created TableImpl for this object
     */
    public TableImpl addTable(AbstractClassMetaData acmd, ForceManagedConnection mconn) {
        ForceStoreSchemaHandler sh = (ForceStoreSchemaHandler) getSchemaHandler();
        return sh.addTable(acmd, mconn);
    }
   
    /**
     * Registers a virtual table with the schema handler (a table not backed by
     * an actual object but is still needed for JPA queries, e.g. ForceOwner)
     *
     * @param acmd the class metadata of the virtual table to register
     * @return the TableImpl for this object
     */
    public TableImpl addVirtualTable(AbstractClassMetaData acmd) {
        ForceStoreSchemaHandler sh = (ForceStoreSchemaHandler) getSchemaHandler();
        return sh.addVirtualTable(acmd);
    }
   
    /**
     * Specifies whether optimistic locking is enabled for this persistence unit. Optimistic transactions
     * prevent two separate transactions from updating the same record at the same time, thus
     * overwriting one transaction's update
     * @return {@code true} if optimistic transactions are enabled
     */
    public boolean isEnableOptimisticTransactions() {
        return enableOptimisticTransactions;
    }
   
    public ForceMetaDataListener getMetaDataListener() {
        return metadataListener;
    }

    /**
     * Creates a {@code ForceManagedConnection} for connection to Force.com.
     * @return the created managed connection to Force.com
     */
    public ForceManagedConnection createConnection() {
        ForceConnectionFactory connFactory =
            (ForceConnectionFactory) getConnectionManager().lookupConnectionFactory(FORCE_KEY);
           
        return (ForceManagedConnection) connFactory.createManagedConnection(null, null);
    }
   
    /**
     * Before entities are registered or created, we execute describe calls on the entities to determine
     * entity shape and whether the entities already exist.
     *
     * @param classes a collection of class metadata to cache describe results for
     */
    void preInitialiseFileMetaData(Collection<AbstractClassMetaData> classes) {
        ForceManagedConnection mconn = createConnection();
        try {
            ((ForceStoreSchemaHandler) getSchemaHandler()).cacheDescribeSObjects(classes, mconn);
        } finally {
            mconn.release();
        }
    }
   
    /**
     * Clears out the describe calls for all entities in this application.
     */
    void postInitialiseFileMetaData() {
        ((ForceStoreSchemaHandler) getSchemaHandler()).clearDescribeSObjects();
    }
   
    public ForceSchemaWriter getSchemaWriter() {
        return schemaWriter;
    }
   
    /**
     * Specifies whether this application has been started up with the flag to delete schema
     * rather than create/upsert it.
     * @return {@code true} if this application should delete schema
     */
    public boolean isForDelete() {
        return forDelete;
    }
}
TOP

Related Classes of com.force.sdk.jpa.ForceStoreManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.