Package org.locationtech.udig.libs.internal

Source Code of org.locationtech.udig.libs.internal.Activator

/*
*    uDig - User Friendly Desktop Internet GIS client
*    http://udig.refractions.net
*    (C) 2012, Refractions Research Inc.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* (http://www.eclipse.org/legal/epl-v10.html), and the Refractions BSD
* License v1.0 (http://udig.refractions.net/files/bsd3-v10.html).
*/
package org.locationtech.udig.libs.internal;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.logging.ConsoleHandler;
import java.util.logging.Filter;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;

import javax.imageio.spi.ImageReaderSpi;
import javax.media.jai.JAI;
import javax.media.jai.util.ImagingListener;

import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.osgi.service.datalocation.Location;
import org.eclipse.osgi.service.debug.DebugOptions;
import org.geotools.data.DataUtilities;
import org.geotools.factory.GeoTools;
import org.geotools.factory.Hints;
import org.geotools.factory.Hints.Key;
import org.geotools.geometry.DirectPosition2D;
import org.geotools.geometry.GeneralDirectPosition;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.metadata.iso.citation.Citations;
import org.geotools.referencing.CRS;
import org.geotools.referencing.ReferencingFactoryFinder;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.geotools.referencing.factory.PropertyAuthorityFactory;
import org.geotools.referencing.factory.ReferencingFactoryContainer;
import org.geotools.referencing.factory.epsg.ThreadedHsqlEpsgFactory;
import org.geotools.image.io.ImageIOExt;
import org.geotools.util.logging.LoggerFactory;
import org.geotools.util.logging.Logging;
import org.opengis.geometry.DirectPosition;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.util.tracker.ServiceTracker;

/**
* The Activator for org.locationtech.udig.libs provides global settings to help all the open source
* projects get along.
* <p>
* Currently this activator supplied:
* <ul>
* <li>hints about axis order for GeoTools</li>
* <li>instructs java not to use native PNG support; see UDIG-1391 for details</li>
* <li>Configures GeoTools library to use normal java logging</li>
* </ul>
* <p>
* The contents of this Activator will change over time according to the needs of the libraries and
* tool kits we are using.
* </p>
*
* @author Jody Garnett
* @version 1.3.0
* @since 1.1.0
*/
public class Activator implements BundleActivator {

    public static String ID = "org.locationtech.udig.libs"; //$NON-NLS-1$
    public static String JDBC_DATA_TRACE_FINE = "org.locationtech.udig.libs/debug/data/jdbc/fine";
    public static String JDBC_TRACE_FINE = "org.locationtech.udig.libs/debug/jdbc/fine";

    private static final String DATABASES_FOLDER_NAME = "databases";
    private static final String EPSG_DATABASEFOLDER_PREFIX = "epsg_v";

    @SuppressWarnings("deprecation")
    public void start( final BundleContext context ) throws Exception {
        if (Platform.getOS().equals(Platform.OS_WIN32)) {
            try {
                // PNG native support is not very good .. this turns it off
                ImageIOExt.allowNativeCodec("png", ImageReaderSpi.class, false); //$NON-NLS-1$
            } catch (Throwable t) {
                // we should not die if JAI is missing; we have a warning for that...
                System.out.println("Difficulty turnning windows native PNG support (which will result in scrambled images from WMS servers)"); //$NON-NLS-1$
                t.printStackTrace();
            }
        }

        // System properites work for controlling referencing behavior
        // not so sure about the geotools global hints
        //
        System.setProperty("org.geotools.referencing.forceXY", "true"); //$NON-NLS-1$ //$NON-NLS-2$
        Map<Key, Boolean> map = new HashMap<Key, Boolean>();
        // these commented out hints are covered by the forceXY system property
        //
        // map.put( Hints.FORCE_LONGITUDE_FIRST_AXIS_ORDER, true );
        // map.put( Hints.FORCE_STANDARD_AXIS_DIRECTIONS, true );
        // map.put( Hints.FORCE_STANDARD_AXIS_UNITS, true );
        map.put(Hints.LENIENT_DATUM_SHIFT, true);
        Hints global = new Hints(map);
        GeoTools.init(global);
        Logging.GEOTOOLS.setLoggerFactory((LoggerFactory<?>)null);
       
        // Suppress JAI warnings when native support unavailable
        JAI.getDefaultInstance().setImagingListener(new ImagingListener() {
            final Logger LOGGER = Logging.getLogger("javax.media.jai");
            public boolean errorOccurred(String message, Throwable thrown, Object where,
                    boolean isRetryable) throws RuntimeException {
                if (message.contains("Continuing in pure Java mode")) {
                    LOGGER.log(Level.FINE, message, thrown);
                } else {
                    LOGGER.log(Level.INFO, message, thrown);
                }
                return false; // we are not trying to recover
            }
        });
       
//        ClassLoader cl = Thread.currentThread().getContextClassLoader();
//        Thread.currentThread().setContextClassLoader(GeoTools.class.getClassLoader());
//        try {
        Logger jdbcLogger = Logging.getLogger("org.geotools.jdbc");
        Logger jdbcDataLogger = Logging.getLogger("org.geotools.data.jdbc");
       
        ConsoleHandler handler = new ConsoleHandler();
        handler.setLevel(Level.FINEST);
       
        Logging.getLogger("org.geotools").addHandler(handler);
        if (isDebugging(JDBC_TRACE_FINE)) {
            jdbcLogger.setLevel(Level.FINEST);
            Logging.getLogger("org.geotools.data.store").addHandler(handler);
            Logging.getLogger("org.geotools.data.store").setLevel(Level.FINEST); // ContentDataStore too
            Logging.getLogger("org.geotools.data.store.JDBCFeatureReader").addHandler(handler);
            Logging.getLogger("org.geotools.data.store.JDBCFeatureReader").setLevel(Level.FINEST);
            Logging.getLogger("org.geotools.data.store.JDBCFeatureSource").addHandler(handler);
            Logging.getLogger("org.geotools.data.store.JDBCFeatureSource").setLevel(Level.FINEST);
            Logging.getLogger("org.geotools.data.store.JDBCFeatureStore").addHandler(handler);
            Logging.getLogger("org.geotools.data.store.JDBCFeatureStore").setLevel(Level.FINEST);
            Logging.getLogger("org.geotools.data.store.SQLDialect").addHandler(handler);
            Logging.getLogger("org.geotools.data.store.SQLDialect").setLevel(Level.FINEST);
        } else {
            jdbcLogger.setLevel(Level.INFO);
        }
        if (isDebugging(JDBC_DATA_TRACE_FINE)) {
            jdbcDataLogger.setLevel(Level.FINEST);
        } else {
            jdbcDataLogger.setLevel(Level.INFO);
        }
//        } finally {
//          Thread.currentThread().setContextClassLoader(cl);
//        }
       
        // We cannot do this here - it takes too long!
        // Early startup is too late
        // functionality moved to the UDIGApplication init method
        //
        // initializeReferencingModule( context.getBundle(), null );
    }
    public static boolean isDebugging(final String trace) {
        return isDebugging()
                && "true".equalsIgnoreCase(Platform.getDebugOption(trace)); //$NON-NLS-1$   
    }

    public static boolean isDebugging() {
        Bundle bundle = Platform.getBundle(ID);
        String key = bundle.getSymbolicName() + "/debug"; //$NON-NLS-1$
        // first check if platform debugging is enabled
        BundleContext context = bundle.getBundleContext();
        if (context == null) {
            return false;
        }
        ServiceTracker<DebugOptions,Object> debugTracker = new ServiceTracker<DebugOptions,Object>(context, DebugOptions.class.getName(),
                null);
        debugTracker.open();

        DebugOptions debugOptions = (DebugOptions) debugTracker.getService();
        if (debugOptions == null) {
            return false;
        }
        // if platform debugging is enabled, check to see if this plugin is enabled for debugging
        return debugOptions.isDebugEnabled() ? debugOptions.getBooleanOption(key,false) : false;
    }

    public static void initializeReferencingModule( IProgressMonitor monitor ) {
        Bundle bundle = Platform.getBundle(ID);
        if (monitor == null)
            monitor = new NullProgressMonitor();

        monitor.beginTask(Messages.Activator_EPSG_DATABASE, 100);
       
        Logger epsgLogger = Logging.getLogger("org.geotools.referencing.factory");
        try {
            epsgLogger.setLevel(Level.SEVERE);
   
            unpackEPSGDatabase();
           
            searchEPSGProperties(bundle, new SubProgressMonitor(monitor, 20));
   
            loadEPSG(bundle, new SubProgressMonitor(monitor, 60));
   
            monitor.subTask(Messages.OPERATIONS_DEFINITIONS);
            load(ReferencingFactoryFinder.getCoordinateOperationAuthorityFactories(null));
            monitor.worked(2);
   
            monitor.subTask(Messages.COORDINATE_REFERENCE_SYSTSMS);
            load(ReferencingFactoryFinder.getCRSFactories(null));
            monitor.worked(8);
   
            monitor.subTask(Messages.COORDINATE_SYSTEMS);
            load(ReferencingFactoryFinder.getCSFactories(null));
            monitor.worked(2);
   
            monitor.subTask(Messages.DATUM_DEFINITIONS);
            load(ReferencingFactoryFinder.getDatumAuthorityFactories(null));
            monitor.worked(2);
   
            monitor.subTask(Messages.DATUMS);
            load(ReferencingFactoryFinder.getDatumFactories(null));
            monitor.worked(2);
   
            monitor.subTask(Messages.MATH_TRANSFORMS);
            load(ReferencingFactoryFinder.getMathTransformFactories(null));
            monitor.worked(4);
        } finally {
            epsgLogger.setLevel(Level.INFO);
        }
    }

    static private void load( Set<?> coordinateOperationAuthorityFactories ) {
        for( Iterator<?> iter = coordinateOperationAuthorityFactories.iterator(); iter.hasNext(); ) {
            iter.next();
        }
    }
    /**
     * Location of the EPSG database; defaults to a folder in the {@link Platform#getInstallLocation()}.
     * <p>
     * You can check to see if this file exists to determine if the database is already unpacked.
     *
     * @return folder used for the EPSG database
     */
    public static File epsgDatabaseFile(){
        // unpack into the shared configuration location
        try {
            Location configLocation = Platform.getInstallLocation();
            return doEpsg(configLocation);
        } catch (MalformedURLException e) {
            // unable to use the config directory - perhaps the user does not have permission
        }
        // if that did not work unpack into the user's data directory
        try {
            Location dataLocation = Platform.getInstanceLocation();
            return doEpsg(dataLocation);
        } catch (MalformedURLException e) {
            // unable to use instance location - ie the data directory
        }
        return null; // database location not known - temporary directory will be used
    }
   
    private static File doEpsg(Location configLocation) throws MalformedURLException{
        File config = DataUtilities.urlToFile( configLocation.getURL() );
        if( config.canWrite() ){
            URL databaseDirectoryUrl = new URL( configLocation.getURL(), DATABASES_FOLDER_NAME );
            File directory = DataUtilities.urlToFile( databaseDirectoryUrl );
            File epsgDirectory = new File( directory, EPSG_DATABASEFOLDER_PREFIX + ThreadedHsqlEpsgFactory.VERSION );
           
            return epsgDirectory;
        }
        return null;
    }
   
    public static void unpackEPSGDatabase(){
        File file = epsgDatabaseFile();
        if( file == null ){
            // default geotools temporary directory will be used
            return;
        }
        File directory = file.getParentFile();
        boolean created = directory.exists() || directory.mkdirs();
        if( created ){
            if( isDebugging() ){
                System.out.println("EPSG database location: "+file);
            }
            System.setProperty( ThreadedHsqlEpsgFactory.DIRECTORY_KEY, directory.toString() );
        }
    }
   
    /**
     * Will load the EPSG database; this will trigger the unpacking of the EPSG database (which may
     * take several minutes); and check in a few locations for an epsg.properties file to load: the
     * locations are the data directory; the configuration directory; and finally the libs plugin
     * bundle itself (which includes a default epsg.properties file that has a few common unofficial
     * codes for things like the google projection).
     * <p>
     * This method will trigger the geotools referencing module to "scanForPlugins" and MUST be
     * called prior to using the geotools library for anything real. I am sorry we could not arrange
     * for this method to be called in an Activator as it simple takes too long and the Platform
     * get's mad at us.
     *
     * @param bundle
     * @param monitor
     */
    public static void searchEPSGProperties( Bundle bundle, IProgressMonitor monitor ) {
        if (monitor == null)
            monitor = new NullProgressMonitor();

        monitor.beginTask(Messages.EPSG_SETUP, IProgressMonitor.UNKNOWN);
        try {
            // go through and check a couple of locations
            // for an "epsg.properties" file full of
            // suplementary codes
            //
            URL epsg = null;
            Location configLocaiton = Platform.getInstallLocation();
            Location dataLocation = Platform.getInstanceLocation();
           
            if (dataLocation != null) {
                try {
                    URL url = dataLocation.getURL();
                    URL proposed = new URL(url, "epsg.properties"); //$NON-NLS-1$
                    monitor.subTask(Messages.CHECK + proposed);
                    String externalForm = proposed.toExternalForm();
                    if ("file".equals(proposed.getProtocol())) { //$NON-NLS-1$
                        String path = externalForm.replaceFirst("file:", "")//$NON-NLS-1$//$NON-NLS-2$
                        File file = new File(path);
                        if (file.exists()) {
                            epsg = file.toURI().toURL();
                        }
                    }
                    monitor.worked(1);
                } catch (Throwable t) {
                    if (isDebugging()) {
                        System.out.println("Could not find data directory epsg.properties"); //$NON-NLS-1$
                        t.printStackTrace();
                    }
                }
            }
            if (epsg == null && configLocaiton != null) {
                try {
                    URL url = configLocaiton.getURL();
                    URL proposed = new URL(url, "epsg.properties"); //$NON-NLS-1$
                    String externalForm = proposed.toExternalForm();
                    monitor.subTask(Messages.Activator_1 + proposed);
                    if ("file".equals(proposed.getProtocol())) { //$NON-NLS-1$
                        String path = externalForm.replaceFirst("file:", "")//$NON-NLS-1$//$NON-NLS-2$
                        File file = new File(path);
                        if (file.exists()) {
                            epsg = file.toURI().toURL();
                        }
                    }
                    monitor.worked(1);
                } catch (Throwable t) {
                    if (isDebugging()) {
                        System.out.println("Could not find configuration epsg.properties"); //$NON-NLS-1$
                        t.printStackTrace();
                    }
                }
            }
            if (epsg == null) {
                try {
                    URL internal = bundle.getEntry("epsg.properties"); //$NON-NLS-1$
                    URL fileUrl = FileLocator.toFileURL(internal);
                    String externalForm = fileUrl.toExternalForm();
                    String path = externalForm.replaceFirst("file:", "")//$NON-NLS-1$//$NON-NLS-2$
                    epsg = new File(path).toURI().toURL();
                } catch (Throwable t) {
                    if (Platform.inDebugMode()) {
                        System.out
                                .println("Could not find org.locationtech.udig.libs/epsg.properties"); //$NON-NLS-1$
                        t.printStackTrace();
                    }
                }
            }

            if (epsg != null) {
                monitor.subTask(Messages.LOADING + epsg);
                Hints hints = new Hints(Hints.CRS_AUTHORITY_FACTORY, PropertyAuthorityFactory.class);
                ReferencingFactoryContainer referencingFactoryContainer = ReferencingFactoryContainer
                        .instance(hints);

                PropertyAuthorityFactory factory = new PropertyAuthorityFactory(
                        referencingFactoryContainer, Citations.fromName("EPSG"), epsg); //$NON-NLS-1$

                ReferencingFactoryFinder.addAuthorityFactory(factory);
                monitor.worked(1);

                monitor.subTask(Messages.REGISTER + epsg);
                ReferencingFactoryFinder.scanForPlugins(); // hook everything up
                monitor.worked(10);
            }

            monitor.subTask(Messages.PLEASE_WAIT);
            CoordinateReferenceSystem wgs84 = CRS.decode("EPSG:4326"); //$NON-NLS-1$
            if (wgs84 == null) {
                String msg = "Unable to locate EPSG authority for EPSG:4326; consider removing temporary 'GeoTools' directory and trying again."; //$NON-NLS-1$
                System.out.println(msg);
                // throw new FactoryException(msg);
            }
            monitor.worked(1);

            // Show EPSG authority chain if in debug mode
            //
            if (isDebugging()) {
                //CRS.main(new String[]{"-dependencies"}); //$NON-NLS-1$
            }
            // Verify EPSG authority configured correctly
            // if we are in development mode
            if (isDebugging()) {
                monitor.subTask("verify epsg definitions"); //$NON-NLS-1$
                verifyReferencingEpsg();
                monitor.subTask("verify epsg operations"); //$NON-NLS-1$
                verifyReferencingOperation();
            }
        } catch (Throwable t) {
            Platform.getLog(bundle).log(
                    new Status(Status.ERROR, Activator.ID, t.getLocalizedMessage(), t));
        } finally {
            monitor.done();
        }
    }

    public static void loadEPSG( Bundle bundle, IProgressMonitor monitor ) {
        if (monitor == null)
            monitor = new NullProgressMonitor();

        monitor.beginTask(Messages.EPSG_SETUP, IProgressMonitor.UNKNOWN);
        try {
            monitor.subTask(Messages.PLEASE_WAIT);
            CoordinateReferenceSystem wgs84 = CRS.decode("EPSG:4326"); //$NON-NLS-1$
            if (wgs84 == null) {
                String msg = "Unable to locate EPSG authority for EPSG:4326; consider removing temporary 'GeoTools' directory and trying again."; //$NON-NLS-1$
                System.out.println(msg);
                // throw new FactoryException(msg);
            }
            monitor.worked(1);

            // Show EPSG authority chain if in debug mode
            //
            if (Platform.inDebugMode()) {
              System.out.println("Coordinate Reference System definitions supplied by:");
                CRS.main(new String[]{"-dependencies"}); //$NON-NLS-1$
            }
            // Verify EPSG authority configured correctly
            // if we are in development mode
            if (Platform.inDevelopmentMode()) {
                monitor.subTask("verify epsg definitions"); //$NON-NLS-1$
                verifyReferencingEpsg();
                monitor.subTask("verify epsg operations"); //$NON-NLS-1$
                verifyReferencingOperation();
            }
        } catch (Throwable t) {
            Platform.getLog(bundle).log(
                    new Status(Status.ERROR, Activator.ID, t.getLocalizedMessage(), t));
        } finally {
            monitor.done();
        }
    }

    /**
     * If this method fails it's because, the epsg jar is either not available, or not set up to
     * handle math transforms in the manner udig expects.
     *
     * @return true if referencing is working and we get the expected result
     * @throws Exception if we cannot even get that far
     */
    private static void verifyReferencingEpsg() throws Exception {
        CoordinateReferenceSystem WGS84 = CRS.decode("EPSG:4326"); // latlong //$NON-NLS-1$
        CoordinateReferenceSystem BC_ALBERS = CRS.decode("EPSG:3005"); //$NON-NLS-1$

        MathTransform transform = CRS.findMathTransform(BC_ALBERS, WGS84);
        DirectPosition here = new DirectPosition2D(BC_ALBERS, 1187128, 395268);
        DirectPosition there = new DirectPosition2D(WGS84, -123.47009173007372, 48.54326498732153);

        DirectPosition check = transform.transform(here, new GeneralDirectPosition(WGS84));
        double delta = Math.abs(check.getOrdinate(0) - there.getOrdinate(0))
                + Math.abs(check.getOrdinate(1) - there.getOrdinate(1));
        if (delta > 0.0001) {
            String msg = "Referencing failed to transformation with expected accuracy: Off by " + delta + "\n" + check + "\n" + there; //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
            System.out.println(msg);
            // throw new FactoryException(msg);
        }
    }
    /**
     * If this method fails it's because, the epsg jar is either not available, or not set up to
     * handle math transforms in the manner udig expects.
     *
     * @return true if referencing is working and we get the expected result
     * @throws Exception if we cannot even get that far
     */
    private static void verifyReferencingOperation() throws Exception {
        // ReferencedEnvelope[-0.24291497975705742 : 0.24291497975711265, -0.5056179775280899 :
        // -0.0]
        // ReferencedEnvelope[-0.24291497975705742 : 0.24291497975711265, -0.5056179775280899 :
        // -0.0]
        CoordinateReferenceSystem EPSG4326 = CRS.decode("EPSG:4326"); //$NON-NLS-1$
        ReferencedEnvelope pixelBounds = new ReferencedEnvelope(-0.24291497975705742,
                0.24291497975711265, -0.5056179775280899, 0.0, EPSG4326);
        CoordinateReferenceSystem WGS84 = DefaultGeographicCRS.WGS84;

        ReferencedEnvelope latLong = pixelBounds.transform(WGS84, false);
        if (latLong == null) {
            String msg = "Unable to transform EPSG:4326 to DefaultGeographicCRS.WGS84"; //$NON-NLS-1$
            System.out.println(msg);
            // throw new FactoryException(msg);
        }
    }

    public void stop( BundleContext context ) throws Exception {
    }

}
TOP

Related Classes of org.locationtech.udig.libs.internal.Activator

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.