Package org.geotools.arcsde

Source Code of org.geotools.arcsde.ArcSDEJNDIDataStoreFactory

/*
*    GeoTools - The Open Source Java GIS Toolkit
*    http://geotools.org
*
*    (C) 2002-2009, Open Source Geospatial Foundation (OSGeo)
*
*    This library 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;
*    version 2.1 of the License.
*
*    This library 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.
*/
package org.geotools.arcsde;

import static org.geotools.arcsde.ArcSDEDataStoreFactory.ALLOW_NON_SPATIAL_PARAM;
import static org.geotools.arcsde.ArcSDEDataStoreFactory.NAMESPACE_PARAM;
import static org.geotools.arcsde.ArcSDEDataStoreFactory.VERSION_PARAM;

import java.awt.RenderingHints.Key;
import java.io.IOException;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;

import javax.naming.Context;
import javax.naming.NamingException;

import org.geotools.arcsde.data.ArcSDEDataStore;
import org.geotools.arcsde.data.ArcSDEDataStoreConfig;
import org.geotools.arcsde.jndi.ArcSDEConnectionFactory;
import org.geotools.arcsde.session.ArcSDEConnectionConfig;
import org.geotools.arcsde.session.ISessionPool;
import org.geotools.data.DataSourceException;
import org.geotools.data.DataStore;
import org.geotools.data.DataStoreFactorySpi;
import org.geotools.factory.GeoTools;
import org.geotools.util.logging.Logging;

/**
* A GeoTools {@link DataStore} factory to access an ArcSDE database by grabbing the connection pool
* from a JNDI reference.
* <p>
* This DataStore factory expects the arcsde connection information to be given as a JNDI resource
* path through the {@link #JNDI_REFNAME jndiRefName} parameter at {@link #createDataStore(Map)}.
* The resource provided by the JNDI context at that location may be either:
* <ul>
* <li>a {@code java.util.Map<String, String>} with the connection parameters from
* {@link ArcSDEConnectionConfig}. If so, the {@link ISessionPool session pool} will be taken from
* {@link ArcSDEConnectionFactory#getInstance(Map)}</li>
* <li>a {@link ISessionPool} instance</li>
* </ul>
* </p>
* <p>
* If not an {@code ISessionPool}, the object will be used to get one from
* {@link ArcSDEConnectionFactory}. Whether the resulting session (connection) pool is shared among
* {@link ArcSDEDataStore} instances is dependent on how the JNDI resource is externally configured.
* For example, on the J2EE container, it will depend on if the JNDI resource is globally configured
* or not, and the required jar files are on a J2EE container shared libraries folder or not.
* </p>
*
* @author Gabriel Roldan (OpenGeo)
*
*
*
* @source $URL$
*         http://svn.osgeo.org/geotools/trunk/modules/plugin/arcsde/datastore/src/main/java/org
*         /geotools/arcsde/ArcSDEJNDIDataStoreFactory.java $
* @version $Id$
* @since 2.5.7
*/
public class ArcSDEJNDIDataStoreFactory implements DataStoreFactorySpi {

    private static final Logger LOGGER = Logging.getLogger("org.geotools.arcsde");

    private final ArcSDEDataStoreFactory delegateFactory;

    /**
     * JNDI context path name
     */
    public static final Param JNDI_REFNAME = new Param("ArcSDE_jndiReferenceName", String.class,
            "JNDI context path", true, "java:comp/env/geotools/arcsde");

    private static final String J2EE_ROOT_CONTEXT = "java:comp/env/";

    public ArcSDEJNDIDataStoreFactory() {
        this.delegateFactory = new ArcSDEDataStoreFactory();
    }

    /**
     * Creates and {@link ArcSDEDataStore} from the provided {@code params}, where the connection
     * pool is provided by JNDI.
     * <p>
     * See {@link #getParametersInfo()} to check which datastore creation parameters are expected by
     * this factory method.
     * </p>
     *
     * @see org.geotools.data.DataStoreFactorySpi#createDataStore(java.util.Map)
     */
    public DataStore createDataStore(Map<String, Serializable> params) throws IOException {
        final String jndiName = (String) JNDI_REFNAME.lookUp(params);

        final Object lookup = lookupJndiResource(jndiName);

        final ISessionPool sessionPool = getSessionPool(jndiName, lookup);

        final String nsUri = (String) NAMESPACE_PARAM.lookUp(params);
        final String version = (String) VERSION_PARAM.lookUp(params);
        final boolean nonSpatial;
        {
            final Boolean allowNonSpatialTables = (Boolean) ALLOW_NON_SPATIAL_PARAM.lookUp(params);
            nonSpatial = allowNonSpatialTables == null ? false : allowNonSpatialTables
                    .booleanValue();
        }

        final ArcSDEConnectionConfig connectionConfig = sessionPool.getConfig();
        final ArcSDEDataStoreConfig dsConfig;
        dsConfig = new ArcSDEDataStoreConfig(connectionConfig, nsUri, version, nonSpatial);

        LOGGER.info("Creating ArcSDE JNDI DataStore with shared session pool for " + dsConfig);
        final ArcSDEDataStore dataStore = delegateFactory.createDataStore(dsConfig, sessionPool);

        return dataStore;
    }

    @SuppressWarnings("unchecked")
    private ISessionPool getSessionPool(final String jndiName, final Object lookup)
            throws IOException, DataSourceException {

        final ISessionPool sessionPool;

        if (lookup instanceof ISessionPool) {

            LOGGER.info("Creating JNDI ArcSDE DataStore with shared session pool for " + lookup);
            sessionPool = (ISessionPool) lookup;

        } else if (lookup instanceof Map) {
            Map<String, Serializable> map = new HashMap<String, Serializable>();
            {
                Map<Object, Object> props = (Map<Object, Object>) lookup;
                String key;
                Object value;
                for (Map.Entry<Object, Object> e : props.entrySet()) {
                    key = String.valueOf(e.getKey());
                    value = e.getValue();
                    map.put(key, value == null ? null : String.valueOf(e.getValue()));
                }
            }
            // use the JNDI factory to grab the shared pool
            ArcSDEConnectionFactory factory = new ArcSDEConnectionFactory();
            sessionPool = factory.getInstance(map);

        } else {
            throw new DataSourceException("Unknown JNDI resource on path " + jndiName
                    + ". Expected one of [" + ArcSDEConnectionConfig.class.getName() + ", "
                    + ISessionPool.class.getName() + "] but got " + lookup.getClass().getName()
                    + " (" + lookup + ")");
        }
        return sessionPool;
    }

    /**
     * Looks up and returns the JNDI resource addressed by {@code jndiName}
     *
     * @param jndiName
     * @return the resource mapped at {@code jndiName}, which shall be either a
     *         {@code java.util.Map<String, String>}, an {@link ArcSDEConnectionConfig} or a
     *         {@link ISessionPool}.
     * @throws IOException
     *             if a resource is not found at {@code jndiName}
     */
    private Object lookupJndiResource(final String jndiName) throws IOException {
        if (jndiName == null) {
            throw new IOException("Missing " + JNDI_REFNAME.description);
        }

        final Context ctx;

        try {
            ctx = GeoTools.getInitialContext(GeoTools.getDefaultHints());
        } catch (NamingException e) {
            throw new RuntimeException(e);
        }

        Object lookup = null;
        try {
            lookup = ctx.lookup(jndiName);
        } catch (NamingException e1) {
            // check if the user did not specify "java:comp/env"
            // and this code is running in a J2EE environment
            try {
                if (jndiName.startsWith(J2EE_ROOT_CONTEXT) == false) {
                    lookup = ctx.lookup(J2EE_ROOT_CONTEXT + jndiName);
                    // success --> issue a waring
                    LOGGER.warning("Using " + J2EE_ROOT_CONTEXT + jndiName + " instead of "
                            + jndiName + " would avoid an unnecessary JNDI lookup");
                }
            } catch (NamingException e2) {
                // do nothing, was only a try
            }
        }

        if (lookup == null) {
            throw new IOException("Cannot find JNDI data source: " + jndiName);
        }
        return lookup;
    }

    /**
     * Returns whether this factory <i>could</i> process the given parameters. That is, it does not
     * check the validity of the parameter, it only asserts the {@link #JNDI_REFNAME} parameter is
     * present. That is so so any failure is handled by {@link #createDataStore(Map)} instead of
     * getting client code silently failing (as this method does not throw an exception)
     *
     * @see org.geotools.data.DataAccessFactory#canProcess(java.util.Map)
     */
    public boolean canProcess(Map<String, Serializable> params) {
        if (params == null) {
            return false;
        }
        String lookUpKey;
        try {
            lookUpKey = (String) JNDI_REFNAME.lookUp(params);
        } catch (IOException e) {
            return false;
        }
        if (lookUpKey == null) {
            return false;
        }
        return true;
    }

    /**
     * @see org.geotools.data.DataAccessFactory#getDescription()
     */
    public String getDescription() {
        return delegateFactory.getDescription() + " (JNDI)";
    }

    /**
     * @see org.geotools.data.DataAccessFactory#getDisplayName()
     */
    public String getDisplayName() {
        return delegateFactory.getDisplayName() + " (JNDI)";
    }

    /**
     * Provides the datastore creation parameter metadata for this factory.
     * <p>
     * The returned parameters are:
     * <ul>
     * <li>{@link #JNDI_REFNAME jndiReferenceName}: the JNDI path to the {@link ISessionPool
     * connection pool}
     * <li> {@link ArcSDEDataStoreConfig#NAMESPACE_PARAM_NAME namespace}: the namespace uri the
     * datastore should create feature types in
     * <li> {@link ArcSDEDataStoreConfig#VERSION_PARAM_NAME database.version} the arcsde database
     * version the datastore shall work upon. If non provided or empty, the DEFAULT version will be
     * used.
     * <li> {@link ArcSDEDataStoreConfig#ALLOW_NON_SPATIAL_TABLES_PARAM_NAME
     * datastore.allowNonSpatialTables} whether to publish non spatial registered tables (aka,
     * Object Classes). Defaults to {@code false}.
     * </ul>
     * </p>
     *
     * @see org.geotools.data.DataAccessFactory#getParametersInfo()
     */
    public Param[] getParametersInfo() {
        return new Param[] { JNDI_REFNAME, NAMESPACE_PARAM, VERSION_PARAM, ALLOW_NON_SPATIAL_PARAM };
    }

    /**
     * Determines if the datastore is available.
     * <p>
     * Check in an Initial Context is available, that is all what can be done Checking for the right
     * jdbc jars in the classpath is not possible here
     * </p>
     *
     * @see org.geotools.data.DataAccessFactory#isAvailable()
     */
    public boolean isAvailable() {
        try {
            GeoTools.getInitialContext(GeoTools.getDefaultHints());
        } catch (NamingException e) {
            return false;
        }
        return delegateFactory.isAvailable();
    }

    /**
     * @see org.geotools.factory.Factory#getImplementationHints()
     */
    public Map<Key, ?> getImplementationHints() {
        return delegateFactory.getImplementationHints();
    }

    /**
     * @see org.geotools.data.DataStoreFactorySpi#createNewDataStore(java.util.Map)
     */
    public DataStore createNewDataStore(Map<String, Serializable> params) throws IOException {
        throw new UnsupportedOperationException("ArcSDE PlugIn does not support createNewDataStore");
    }
}
TOP

Related Classes of org.geotools.arcsde.ArcSDEJNDIDataStoreFactory

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.