Package org.geotools.data

Source Code of org.geotools.data.DataAccessFinder

/*
*    GeoTools - The Open Source Java GIS Toolkit
*    http://geotools.org
*
*    (C) 2003-2008, 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.data;

import java.io.IOException;
import java.io.Serializable;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.geotools.factory.FactoryCreator;
import org.geotools.factory.FactoryRegistry;
import org.opengis.feature.Feature;
import org.opengis.feature.type.FeatureType;

/**
* Enable programs to find all available DataAccess implementations, including
* the DataStore ones.
*
* <p>
* In order to be located by this finder datasources must provide an
* implementation of the {@link DataAccessFactory} interface.
* </p>
*
* <p>
* In addition to implementing this interface datasouces should have a services
* file:<br/><code>META-INF/services/org.geotools.data.DataAccessFactory</code>
* </p>
*
* <p>
* The file should contain a single line which gives the full name of the
* implementing class.
* </p>
*
* <p>
* Example:<br/><code>org.geotools.data.mytype.MyTypeDataAccessFacotry</code>
* </p>
*
*
*
* @source $URL$
*/
public final class DataAccessFinder {
    /** The logger for the filter module. */
    protected static final Logger LOGGER = org.geotools.util.logging.Logging
            .getLogger("org.geotools.data");

    /**
     * The service registry for this manager. Will be initialized only when
     * first needed.
     */
    private static FactoryRegistry registry;

    // Singleton pattern
    private DataAccessFinder() {
    }

    /**
     * Checks each available datasource implementation in turn and returns the
     * first one which claims to support the resource identified by the params
     * object.
     *
     * @param params
     *            A Map object which contains a defenition of the resource to
     *            connect to. for file based resources the property 'url' should
     *            be set within this Map.
     *
     * @return The first datasource which claims to process the required
     *         resource, returns null if none can be found.
     *
     * @throws IOException
     *             If a suitable loader can be found, but it can not be attached
     *             to the specified resource without errors.
     */
    public static synchronized DataAccess<FeatureType, Feature> getDataStore(
            Map<String, Serializable> params) throws IOException {
        Iterator<DataAccessFactory> ps = getAvailableDataStores();
        return (DataAccess<FeatureType, Feature>) getDataStore(params, ps);
    }

    static DataAccess<? extends FeatureType, ? extends Feature> getDataStore(
            Map<String, Serializable> params, Iterator<? extends DataAccessFactory> ps)
            throws IOException {
        DataAccessFactory fac;

        IOException canProcessButNotAvailable = null;
        while (ps.hasNext()) {
            fac = (DataAccessFactory) ps.next();
            boolean canProcess = false;
            try {
                canProcess = fac.canProcess(params);
            } catch (Throwable t) {
                LOGGER.log(Level.WARNING, "Problem asking " + fac.getDisplayName()
                        + " if it can process request:" + t, t);
                // Protect against DataStores that don't carefully code
                // canProcess
                continue;
            }
            if (canProcess) {
                boolean isAvailable = false;
                try {
                    isAvailable = fac.isAvailable();
                } catch (Throwable t) {
                    LOGGER.log(Level.WARNING, "Difficulity checking if " + fac.getDisplayName()
                            + " is available:" + t, t);
                    // Protect against DataStores that don't carefully code
                    // isAvailable
                    continue;
                }
                if (isAvailable) {
                    try {
                        return fac.createDataStore(params);
                    } catch (IOException couldNotConnect) {
                        canProcessButNotAvailable = couldNotConnect;
                        LOGGER.log(Level.WARNING, fac.getDisplayName()
                                + " should be used, but could not connect", couldNotConnect);
                    }
                } else {
                    canProcessButNotAvailable = new IOException(
                            fac.getDisplayName()
                                    + " should be used, but is not availble. Have you installed the required drivers or jar files?");
                    LOGGER.log(Level.WARNING, fac.getDisplayName()
                            + " should be used, but is not availble", canProcessButNotAvailable);
                }
            }
        }
        if (canProcessButNotAvailable != null) {
            throw canProcessButNotAvailable;
        }
        return null;
    }

    /**
     * Finds all implemtaions of DataAccessFactory which have registered using
     * the services mechanism, regardless weather it has the appropriate
     * libraries on the classpath.
     *
     * @return An iterator over all discovered datastores which have registered
     *         factories
     */
    public static synchronized Iterator<DataAccessFactory> getAllDataStores() {
        Set<DataAccessFactory> all = new HashSet<DataAccessFactory>();
        Iterator<DataStoreFactorySpi> allDataStores = DataStoreFinder.getAllDataStores();
        Iterator<DataAccessFactory> allDataAccess = getAllDataStores(getServiceRegistry(),
                DataAccessFactory.class);
        while (allDataStores.hasNext()) {
            DataStoreFactorySpi next = allDataStores.next();
            all.add(next);
        }

        while (allDataAccess.hasNext()) {
            all.add(allDataAccess.next());
        }

        return all.iterator();
    }

    static synchronized <T extends DataAccessFactory> Iterator<T> getAllDataStores(
            FactoryRegistry registry, Class<T> category) {
        return registry.getServiceProviders(category, null, null);
    }

    /**
     * Finds all implemtaions of DataAccessFactory which have registered using
     * the services mechanism, and that have the appropriate libraries on the
     * classpath.
     *
     * @return An iterator over all discovered datastores which have registered
     *         factories, and whose available method returns true.
     */
    public static synchronized Iterator<DataAccessFactory> getAvailableDataStores() {

        FactoryRegistry serviceRegistry = getServiceRegistry();
        Set<DataAccessFactory> availableDS = getAvailableDataStores(serviceRegistry,
                DataAccessFactory.class);

        Iterator<DataStoreFactorySpi> availableDataStores = DataStoreFinder
                .getAvailableDataStores();
        while (availableDataStores.hasNext()) {
            availableDS.add(availableDataStores.next());
        }

        return availableDS.iterator();
    }

    static synchronized <T extends DataAccessFactory> Set<T> getAvailableDataStores(
            FactoryRegistry registry, Class<T> targetClass) {
        Set<T> availableDS = new HashSet<T>(5);
        Iterator<T> it = registry.getServiceProviders(targetClass, null, null);
        T dsFactory;
        while (it.hasNext()) {
            dsFactory = it.next();

            if (dsFactory.isAvailable()) {
                availableDS.add(dsFactory);
            }
        }

        return availableDS;
    }

    /**
     * Returns the service registry. The registry will be created the first time
     * this method is invoked.
     */
    private static FactoryRegistry getServiceRegistry() {
        assert Thread.holdsLock(DataAccessFinder.class);
        if (registry == null) {
            registry = new FactoryCreator(Arrays.asList(new Class<?>[] { DataAccessFactory.class }));
        }
        return registry;
    }

    /**
     * Scans for factory plug-ins on the application class path. This method is
     * needed because the application class path can theoretically change, or
     * additional plug-ins may become available. Rather than re-scanning the
     * classpath on every invocation of the API, the class path is scanned
     * automatically only on the first invocation. Clients can call this method
     * to prompt a re-scan. Thus this method need only be invoked by
     * sophisticated applications which dynamically make new plug-ins available
     * at runtime.
     */
    public static synchronized void scanForPlugins() {
        DataStoreFinder.scanForPlugins();
        getServiceRegistry().scanForPlugins();
    }
   
    /**
     * Resets the factory finder and prepares for a new full scan of the SPI subsystems
     */
    public static void reset() {
        FactoryRegistry copy = registry;
        registry = null;
        if(copy != null) {
            copy.deregisterAll();
        }
    }
}
TOP

Related Classes of org.geotools.data.DataAccessFinder

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.