sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1728238 [1/2] - in /sis/branches/JDK7: ./ core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/ core/sis-metadata/src/test/java/org/apache/sis/internal/metad...
Date Tue, 02 Feb 2016 23:39:20 GMT
Author: desruisseaux
Date: Tue Feb  2 23:39:20 2016
New Revision: 1728238

URL: http://svn.apache.org/viewvc?rev=1728238&view=rev
Log:
Merge from the JDK8 branch.

Added:
    sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/Dialect.java
      - copied unchanged from r1728236, sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/Dialect.java
    sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/ScriptRunner.java
      - copied, changed from r1728236, sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/ScriptRunner.java
    sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/internal/metadata/sql/TestDatabase.java
      - copied unchanged from r1728236, sis/branches/JDK8/core/sis-metadata/src/test/java/org/apache/sis/internal/metadata/sql/TestDatabase.java
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/DatabaseListener.java
      - copied unchanged from r1728236, sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/DatabaseListener.java
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGInstaller.java
      - copied, changed from r1728236, sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGInstaller.java
    sis/branches/JDK7/core/sis-referencing/src/main/resources/META-INF/services/org.apache.sis.internal.metadata.sql.Initializer
      - copied unchanged from r1728236, sis/branches/JDK8/core/sis-referencing/src/main/resources/META-INF/services/org.apache.sis.internal.metadata.sql.Initializer
    sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/sql/EPSGInstallerTest.java
      - copied unchanged from r1728236, sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/sql/EPSGInstallerTest.java
    sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/report/
      - copied from r1728236, sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/report/
Removed:
    sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/CoordinateOperationMethodsHTML.java
    sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/test/HTMLGenerator.java
Modified:
    sis/branches/JDK7/   (props changed)
    sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ReferencingServices.java
    sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ServicesForUtility.java
    sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/Initializer.java
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ServicesForMetadata.java
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/LambertConformal2SP.java
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/AuthorityFactories.java
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/EPSGFactoryFallback.java
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/IdentifiedObjects.java
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGFactory.java
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/SQLTranslator.java
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/package-info.java
    sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/GIGS2001.java
    sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/sql/EPSGFactoryTest.java
    sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/report/CoordinateOperationMethods.java
    sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/jdk8/JDK8.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/system/DataDirectory.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/util/MetadataServices.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/setup/About.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.properties
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages_fr.properties
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.properties
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary_fr.properties
    sis/branches/JDK7/ide-project/NetBeans/build.xml
    sis/branches/JDK7/ide-project/NetBeans/nbproject/project.properties

Propchange: sis/branches/JDK7/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Tue Feb  2 23:39:20 2016
@@ -1,4 +1,4 @@
 /sis/branches/Android:1430670-1480699
 /sis/branches/JDK6:1394913-1508480
-/sis/branches/JDK8:1584960-1727534
+/sis/branches/JDK8:1584960-1728236
 /sis/trunk:1394364-1508466,1519089-1519674

Modified: sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ReferencingServices.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ReferencingServices.java?rev=1728238&r1=1728237&r2=1728238&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ReferencingServices.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ReferencingServices.java [UTF-8] Tue Feb  2 23:39:20 2016
@@ -18,6 +18,7 @@ package org.apache.sis.internal.metadata
 
 import java.util.Map;
 import java.util.Collections;
+import java.util.Locale;
 import javax.measure.unit.Unit;
 import javax.measure.quantity.Length;
 import org.opengis.geometry.Envelope;
@@ -570,4 +571,23 @@ public class ReferencingServices extends
         }
         return fallback;
     }
+
+    /**
+     * Returns information about the Apache SIS configuration to be reported in {@link org.apache.sis.setup.About}.
+     * This method is invoked only for aspects that depends on other modules than {@code sis-utility}.
+     *
+     * <p>Current keys are:</p>
+     * <ul>
+     *   <li>{@code "EPSG"}: version of EPSG database.</li>
+     * </ul>
+     *
+     * @param  key A key identifying the information to return.
+     * @param  locale Language to use if possible.
+     * @return The information, or {@code null} if none.
+     *
+     * @see org.apache.sis.internal.util.MetadataServices#getInformation(String)
+     */
+    public String getInformation(String key, Locale locale) {
+        return null;
+    }
 }

Modified: sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ServicesForUtility.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ServicesForUtility.java?rev=1728238&r1=1728237&r2=1728238&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ServicesForUtility.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ServicesForUtility.java [UTF-8] Tue Feb  2 23:39:20 2016
@@ -18,6 +18,7 @@ package org.apache.sis.internal.metadata
 
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Locale;
 import org.opengis.metadata.Identifier;
 import org.opengis.metadata.citation.Role;
 import org.opengis.metadata.citation.Citation;
@@ -207,4 +208,17 @@ public final class ServicesForUtility ex
         c.freeze();
         return c;
     }
+
+    /**
+     * Returns information about the Apache SIS configuration.
+     * See super-class for a list of keys.
+     *
+     * @param  key A key identifying the information to return.
+     * @param  locale Language to use if possible.
+     * @return The information, or {@code null} if none.
+     */
+    @Override
+    public String getInformation(final String key, final Locale locale) {
+        return ReferencingServices.getInstance().getInformation(key, locale);
+    }
 }

Modified: sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/Initializer.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/Initializer.java?rev=1728238&r1=1728237&r2=1728238&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/Initializer.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/Initializer.java [UTF-8] Tue Feb  2 23:39:20 2016
@@ -28,8 +28,13 @@ import java.sql.Connection;
 import java.sql.SQLException;
 import javax.naming.Context;
 import javax.naming.InitialContext;
-import javax.naming.spi.NamingManager;
+import javax.naming.NamingException;
 import javax.naming.NameNotFoundException;
+import javax.naming.spi.NamingManager;
+import javax.naming.event.EventContext;
+import javax.naming.event.NamingEvent;
+import javax.naming.event.NamingExceptionEvent;
+import javax.naming.event.ObjectChangeListener;
 import org.apache.sis.internal.system.DataDirectory;
 import org.apache.sis.internal.system.Shutdown;
 import org.apache.sis.internal.system.Loggers;
@@ -44,7 +49,7 @@ import java.nio.file.Paths;
 
 
 /**
- * Manages the unique {@link DataSource} instances to the {@code $SIS_DATA/Databases/SpatialMetadata} database.
+ * Manages the unique {@link DataSource} instance to the {@code $SIS_DATA/Databases/SpatialMetadata} database.
  * This includes initialization of a new database if none existed. The schemas will be created by subclasses of
  * this {@code Initializer} class, which must be registered in the following file:
  *
@@ -70,6 +75,20 @@ public abstract class Initializer {
     private static final String HOME_KEY = "derby.system.home";
 
     /**
+     * Name of the JNDI resource to lookup in the {@code "java:comp/env"} context.
+     */
+    public static final String JNDI = "jdbc/" + DATABASE;
+
+    /**
+     * The class loader for JavaDB (i.e. the Derby database distributed with the JDK), created when first needed.
+     * This field is never reset to {@code null} even if the classpath changed because this class loader is for
+     * a JAR file the JDK installation directory, and we presume that the JDK installation do not change.
+     *
+     * @see #forJavaDB(String)
+     */
+    private static URLClassLoader javadbLoader;
+
+    /**
      * The unique, SIS-wide, data source to the {@code $SIS_DATA/Databases/SpatialMetadata} database.
      * Created when first needed, and cleared on shutdown.
      *
@@ -92,6 +111,93 @@ public abstract class Initializer {
     protected abstract void createSchema(Connection connection) throws SQLException;
 
     /**
+     * Invoked when the JNDI data source associated to {@code "jdbc/SpatialMetadata"} changed.
+     */
+    protected abstract void dataSourceChanged();
+
+    /**
+     * A JNDI listener for being informed of changes in the {@link DataSource} associated to {@code "jdbc/SpatialMetadata"}.
+     * This listener clears the {@link Initializer#source} field, so the next call to {@link Initializer#getDataSource()}
+     * will fetch a new one.
+     */
+    private static final class Listener implements ObjectChangeListener, Callable<Object> {
+        /**
+         * The context where this listener has been registered.
+         * Used for unregistering the listener after the data source has been cleared.
+         */
+        private final EventContext context;
+
+        /**
+         * Creates a new listener for the given JNDI context.
+         */
+        private Listener(final EventContext context) {
+            this.context = context;
+        }
+
+        /**
+         * Registers a new listener for the given JNDI context.
+         */
+        static void register(final EventContext context) throws NamingException {
+            final Listener listener = new Listener(context);
+            context.addNamingListener(JNDI, EventContext.OBJECT_SCOPE, listener);
+            Shutdown.register(listener);
+        }
+
+        /**
+         * Invoked when the JVM is shutting down, or when the Servlet or OSGi bundle is uninstalled.
+         * This method unregisters the listener from the JNDI context.
+         */
+        @Override
+        public Object call() throws NamingException {
+            synchronized (Initializer.class) {
+                // Do not clear the DataSource - the shutdown hook for Derby needs it.
+                context.removeNamingListener(this);
+            }
+            return null;
+        }
+
+        /**
+         * Invoked when the data source associated to {@code "jdbc/SpatialMetadata"} changed.
+         * This method clears the {@link Initializer#source}, unregisters this listener
+         * and notifies other SIS modules.
+         *
+         * @param event Ignored. May be null.
+         */
+        @Override
+        public void objectChanged(NamingEvent event) {
+            try {
+                synchronized (Initializer.class) {
+                    source = null;
+                    Shutdown.unregister(this);
+                    context.removeNamingListener(this);
+                }
+            } catch (NamingException e) {
+                /*
+                 * Not a fatal error since the listener may be unregistered anyway, or may be unregistered
+                 * automatically by other kinds of JNDI events. Even if the listener is not unregistered,
+                 * it will hurt to badly: the DataSource would only be fetched more often than necessary.
+                 */
+                Logging.recoverableException(Logging.getLogger(Loggers.SYSTEM), Listener.class, "objectChanged", e);
+            }
+            for (Initializer init : ServiceLoader.load(Initializer.class)) {
+                init.dataSourceChanged();
+            }
+        }
+
+        /**
+         * Invoked if JNDI lost connection to the server while preparing the {@code NamingEvent}.
+         * Clears the data source anyway. In the worst case scenario, the application will fetch
+         * it again from a the JNDI context.
+         */
+        @Override
+        public void namingExceptionThrown(NamingExceptionEvent event) {
+            Logging.unexpectedException(Logging.getLogger(Loggers.SYSTEM),
+                    Listener.class, "namingExceptionThrown", event.getException());
+            objectChanged(null);
+        }
+    }
+
+    /**
      * Returns the data source for the SIS-wide "SpatialMetadata" database.
      * This method returns the first of the following steps that succeed:
      *
@@ -120,18 +226,76 @@ public abstract class Initializer {
         if (source == null) {
             if (hasJNDI()) try {
                 final Context env = (Context) InitialContext.doLookup("java:comp/env");
-                return source = (DataSource) env.lookup("jdbc/" + DATABASE);
+                source = (DataSource) env.lookup(JNDI);
+                if (env instanceof EventContext) {
+                    Listener.register((EventContext) env);
+                }
+                return source;
             } catch (NameNotFoundException e) {
                 final LogRecord record = Messages.getResources(null).getLogRecord(
-                        Level.CONFIG, Messages.Keys.JNDINotSpecified_1, "jdbc/" + DATABASE);
+                        Level.CONFIG, Messages.Keys.JNDINotSpecified_1, JNDI);
                 record.setLoggerName(Loggers.SQL);
                 Logging.log(Initializer.class, "getDataSource", record);
             }
+            /*
+             * At this point we determined that there is no JNDI context or no object binded to "jdbc/SpatialMetadata".
+             * As a fallback, try to open the Derby database located in $SIS_DATA/Databases/SpatialMetadata directory.
+             */
+            boolean create = false;
+            final String home = System.getProperty(HOME_KEY);
             final Path dir = DataDirectory.DATABASES.getDirectory();
             if (dir != null) {
-                source = forJavaDB(dir.resolve(DATABASE));
-            } else if (System.getProperty(HOME_KEY) != null) {
+                Path path = dir.resolve(DATABASE);
+                if (home != null) try {
+                    /*
+                     * If a "derby.system.home" property is set, we may be able to get a shorter path by making it
+                     * relative to Derby home. The intend is to have a nicer URL like "jdbc:derby:SpatialMetadata"
+                     * instead than "jdbc:derby:/a/long/path/to/SIS/Data/Databases/SpatialMetadata". In addition
+                     * to making loggings and EPSGDataAccess.getAuthority() output nicer, it also reduces the risk
+                     * of encoding issues if the path contains spaces or non-ASCII characters.
+                     */
+                    path = Paths.get(home).relativize(path);
+                } catch (IllegalArgumentException | SecurityException e) {
+                    // The path can not be relativized. This is okay.
+                    Logging.recoverableException(Logging.getLogger(Loggers.SQL), Initializer.class, "getDataSource", e);
+                }
+                /*
+                 * Create the Derby data source using the context class loader if possible,
+                 * or otherwise a URL class loader to the JavaDB distributed with the JDK.
+                 */
+                path   = path.normalize();
+                create = !Files.exists(path);
+                source = forJavaDB(path.toString());
+            } else if (home != null) {
                 source = forJavaDB(DATABASE);
+            } else {
+                return null;
+            }
+            /*
+             * Register the shutdown hook before to attempt any operation on the database in order to close
+             * it properly if the schemas creation below fail.
+             */
+            Shutdown.register(new Callable<Object>() {
+                @Override public Object call() throws ReflectiveOperationException {
+                    shutdown();
+                    return null;
+                }
+            });
+            /*
+             * If the database does not exist, create it. We allow creation only if we are inside
+             * the $SIS_DATA directory. The Java code creating the schemas is provided in other
+             * SIS modules. For example sis-referencing may create the EPSG dataset.
+             */
+            if (create) {
+                final Method m = source.getClass().getMethod("setCreateDatabase", String.class);
+                m.invoke(source, "create");
+                try (Connection c = source.getConnection()) {
+                    for (Initializer init : ServiceLoader.load(Initializer.class)) {
+                        init.createSchema(c);
+                    }
+                } finally {
+                    m.invoke(source, "no");     // Any value other than "create".
+                }
             }
         }
         return source;
@@ -168,56 +332,6 @@ public abstract class Initializer {
     }
 
     /**
-     * Creates a data source for a Derby database at the given {@code $SIS_DATA/Databases/SpatialMetadata} location.
-     * If the database does not exist, it will be created.
-     *
-     * @param  path  The {@code $SIS_DATA/Databases/SpatialMetadata} directory.
-     * @return The data source.
-     * @throws Exception if the data source can not be created.
-     */
-    private static DataSource forJavaDB(Path path) throws Exception {
-        /*
-         * If a "derby.system.home" property is set, we may be able to get a shorter path by making it
-         * relative to Derby home. The intend is to have a nicer URL like "jdbc:derby:SpatialMetadata"
-         * instead than "jdbc:derby:/a/long/path/to/SIS/Data/Databases/SpatialMetadata". In addition
-         * to making loggings and EPSGDataAccess.getAuthority() output nicer, it also reduces the risk
-         * of encoding issues if the path contains spaces or non-ASCII characters.
-         */
-        try {
-            final String home = System.getProperty(HOME_KEY);
-            if (home != null) {
-                path = Paths.get(home).relativize(path);
-            }
-        } catch (IllegalArgumentException | SecurityException e) {
-            // The path can not be relativized. This is okay. Use the public method as the logging source.
-            Logging.recoverableException(Logging.getLogger(Loggers.SQL), Initializer.class, "getDataSource", e);
-        }
-        /*
-         * Create the Derby data source using the context class loader if possible,
-         * or otherwise a URL class loader to the JavaDB distributed with the JDK.
-         */
-        path = path.normalize();
-        final DataSource ds = forJavaDB(path.toString());
-        /*
-         * If the database does not exist, create it. We allow creation only here because we are inside
-         * the $SIS_DATA directory. The Java code creating the schemas is provided in other SIS modules.
-         * For example sis-referencing may create the EPSG dataset.
-         */
-        if (!Files.exists(path)) {
-            final Method m = ds.getClass().getMethod("setCreateDatabase", String.class);
-            m.invoke(ds, "create");
-            try (Connection c = ds.getConnection()) {
-                for (Initializer init : ServiceLoader.load(Initializer.class)) {
-                    init.createSchema(c);
-                }
-            } finally {
-                m.invoke(ds, "no");     // Any value other than "create".
-            }
-        }
-        return ds;
-    }
-
-    /**
      * Creates a data source for a Derby database at the given location. The location may be either the
      * {@code $SIS_DATA/Databases/SpatialMetadata} directory, or the {@code SpatialMetadata} database
      * in the directory given by the {@code derby.system.home} property.
@@ -225,29 +339,39 @@ public abstract class Initializer {
      * <p>This method does <strong>not</strong> create the database if it does not exist, because this
      * method does not know if we are inside the {@code $SIS_DATA} directory.</p>
      *
+     * <p>It is caller's responsibility to shutdown the Derby database after usage.</p>
+     *
      * @param  path  Relative or absolute path to the database.
      * @return The data source.
      * @throws Exception if the data source can not be created.
      */
-    private static DataSource forJavaDB(final String path) throws Exception {
+    public static DataSource forJavaDB(final String path) throws Exception {
         try {
             return forJavaDB(path, Thread.currentThread().getContextClassLoader());
         } catch (ClassNotFoundException e) {
-            final String home = System.getProperty("java.home");
-            if (home != null) {
-                final Path file = Paths.get(home).resolveSibling("db/lib/derby.jar");
-                if (Files.isRegularFile(file)) {
-                    return forJavaDB(path, new URLClassLoader(new URL[] {file.toUri().toURL()}));
+            URLClassLoader loader;
+            synchronized (Initializer.class) {
+                loader = javadbLoader;
+                if (loader == null) {
+                    final String home = System.getProperty("java.home");
+                    if (home != null) {
+                        final Path file = Paths.get(home).resolveSibling("db/lib/derby.jar");
+                        if (Files.isRegularFile(file)) {
+                            javadbLoader = loader = new URLClassLoader(new URL[] {file.toUri().toURL()});
+                        }
+                    }
                 }
             }
-            throw e;
+            if (loader == null) {
+                throw e;
+            }
+            return forJavaDB(path, loader);
         }
     }
 
     /**
-     * Creates a data source for the given path using the given class loader.
-     * If this method succeed in creating a data source, then it registers a shutdown hook
-     * for shutting down the database at JVM shutdown time of Servlet/OSGi bundle uninstall time.
+     * Creates a Derby data source for the given path using the given class loader.
+     * It is caller's responsibility to shutdown the Derby database after usage.
      *
      * @throws ClassNotFoundException if Derby is not on the classpath.
      */
@@ -257,12 +381,6 @@ public abstract class Initializer {
         final Class<?>[] args = {String.class};
         c.getMethod("setDatabaseName", args).invoke(ds, path);
         c.getMethod("setDataSourceName", args).invoke(ds, "Apache SIS spatial metadata");
-        Shutdown.register(new Callable<Object>() {
-            @Override public Object call() throws ReflectiveOperationException {
-                shutdown();
-                return null;
-            }
-        });
         return ds;
     }
 
@@ -281,7 +399,11 @@ public abstract class Initializer {
             try {
                 ds.getConnection().close();     // Does the actual shutdown.
             } catch (SQLException e) {          // This is the expected exception.
-                final LogRecord record = new LogRecord(Level.CONFIG, e.getLocalizedMessage());  // Not WARNING.
+                Level level = Level.CONFIG;
+                if (e.getErrorCode() != 45000 || !"08006".equals(e.getSQLState())) {
+                    level = Level.WARNING;
+                }
+                final LogRecord record = new LogRecord(level, e.getLocalizedMessage());
                 record.setLoggerName(Loggers.SQL);
                 Logging.log(Initializer.class, "shutdown", record);
             }

Copied: sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/ScriptRunner.java (from r1728236, sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/ScriptRunner.java)
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/ScriptRunner.java?p2=sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/ScriptRunner.java&p1=sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/ScriptRunner.java&r1=1728236&r2=1728238&rev=1728238&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/ScriptRunner.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/ScriptRunner.java [UTF-8] Tue Feb  2 23:39:20 2016
@@ -19,7 +19,6 @@ package org.apache.sis.internal.metadata
 import java.util.Map;
 import java.util.HashMap;
 import java.util.Locale;
-import java.util.function.BiFunction;
 import java.io.EOFException;
 import java.io.IOException;
 import java.io.InputStream;
@@ -35,6 +34,10 @@ import org.apache.sis.util.ArgumentCheck
 import org.apache.sis.util.CharSequences;
 import org.apache.sis.util.resources.Errors;
 
+// Branch-specific imports
+import org.apache.sis.internal.jdk8.JDK8;
+import org.apache.sis.internal.jdk8.BiFunction;
+
 
 /**
  * Run SQL scripts. The script is expected to use a standardized syntax, where the {@value #QUOTE} character
@@ -325,7 +328,7 @@ public class ScriptRunner implements Aut
      * @param function The function that modify the replacement mapping.
      */
     protected final void modifyReplacements(final BiFunction<String,String,String> function) {
-        replacements.replaceAll(function);
+        JDK8.replaceAll(replacements, function);
     }
 
     /**

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ServicesForMetadata.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ServicesForMetadata.java?rev=1728238&r1=1728237&r2=1728238&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ServicesForMetadata.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ServicesForMetadata.java [UTF-8] Tue Feb  2 23:39:20 2016
@@ -19,10 +19,12 @@ package org.apache.sis.internal.referenc
 import java.util.Map;
 import java.util.Iterator;
 import java.util.Collection;
+import java.util.Locale;
 import javax.measure.unit.Unit;
 import javax.measure.quantity.Length;
 
 import org.opengis.util.FactoryException;
+import org.opengis.util.InternationalString;
 import org.opengis.parameter.ParameterDescriptor;
 import org.opengis.parameter.ParameterValueGroup;
 import org.opengis.referencing.IdentifiedObject;
@@ -44,6 +46,9 @@ import org.opengis.referencing.operation
 import org.opengis.referencing.operation.SingleOperation;
 import org.opengis.referencing.operation.CoordinateOperation;
 import org.opengis.referencing.operation.CoordinateOperationFactory;
+import org.opengis.metadata.citation.Citation;
+import org.opengis.metadata.citation.OnLineFunction;
+import org.opengis.metadata.citation.OnlineResource;
 import org.opengis.metadata.extent.GeographicBoundingBox;
 import org.opengis.metadata.extent.GeographicExtent;
 import org.opengis.metadata.extent.VerticalExtent;
@@ -76,8 +81,11 @@ import org.apache.sis.internal.metadata.
 import org.apache.sis.internal.metadata.ReferencingServices;
 import org.apache.sis.internal.referencing.provider.Affine;
 import org.apache.sis.internal.system.DefaultFactories;
+import org.apache.sis.internal.util.Constants;
 import org.apache.sis.util.collection.Containers;
+import org.apache.sis.util.resources.Vocabulary;
 import org.apache.sis.util.resources.Errors;
+import org.apache.sis.util.Exceptions;
 import org.apache.sis.util.Utilities;
 
 
@@ -86,11 +94,16 @@ import org.apache.sis.util.Utilities;
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.5
- * @version 0.6
+ * @version 0.7
  * @module
  */
 public final class ServicesForMetadata extends ReferencingServices {
     /**
+     * Name of an {@link OnLineFunction} code list value, used for transferring information about the EPSG database.
+     */
+    public static final String CONNECTION = "CONNECTION";
+
+    /**
      * Creates a new instance. This constructor is invoked by reflection only.
      */
     public ServicesForMetadata() {
@@ -650,4 +663,45 @@ public final class ServicesForMetadata e
     public boolean isHeuristicMatchForName(final IdentifiedObject object, final String name) {
         return IdentifiedObjects.isHeuristicMatchForName(object, name);
     }
+
+    /**
+     * Returns information about the Apache SIS configuration.
+     * See super-class for a list of keys.
+     *
+     * @param  key A key identifying the information to return.
+     * @param  locale Language to use if possible.
+     * @return The information, or {@code null} if none.
+     */
+    @Override
+    public String getInformation(final String key, final Locale locale) {
+        switch (key) {
+            /*
+             * Get the version of the EPSG database and the version of the database software.
+             * This operation can be relatively costly as it may open a JDBC connection.
+             */
+            case Constants.EPSG: {
+                final Citation authority;
+                try {
+                    authority = CRS.getAuthorityFactory(Constants.EPSG).getAuthority();
+                } catch (FactoryException e) {
+                    final String msg = Exceptions.getLocalizedMessage(e, locale);
+                    return (msg != null) ? msg : e.toString();
+                }
+                if (authority != null) {
+                    final OnLineFunction f = OnLineFunction.valueOf(CONNECTION);
+                    for (final OnlineResource res : authority.getOnlineResources()) {
+                        if (f.equals(res.getFunction())) {
+                            final InternationalString i18n = res.getDescription();
+                            if (i18n != null) return i18n.toString(locale);
+                        }
+                    }
+                    final InternationalString i18n = authority.getTitle();
+                    if (i18n != null) return i18n.toString(locale);
+                }
+                return Vocabulary.getResources(locale).getString(Vocabulary.Keys.Untitled);
+            }
+            // More cases may be added in future SIS versions.
+        }
+        return super.getInformation(key, locale);
+    }
 }

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/LambertConformal2SP.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/LambertConformal2SP.java?rev=1728238&r1=1728237&r2=1728238&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/LambertConformal2SP.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/LambertConformal2SP.java [UTF-8] Tue Feb  2 23:39:20 2016
@@ -88,7 +88,7 @@ public final class LambertConformal2SP e
     /**
      * The group of all parameters expected by this coordinate operation.
      */
-    static final ParameterDescriptorGroup PARAMETERS;
+    private static final ParameterDescriptorGroup PARAMETERS;
     static {
         final ParameterBuilder builder = builder();
         /*

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/AuthorityFactories.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/AuthorityFactories.java?rev=1728238&r1=1728237&r2=1728238&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/AuthorityFactories.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/AuthorityFactories.java [UTF-8] Tue Feb  2 23:39:20 2016
@@ -106,7 +106,7 @@ final class AuthorityFactories<T extends
         synchronized (EPSG) {
             AuthorityFactory factory = EPSG[0];
             if (factory == null) try {
-                factory = new EPSGFactory();
+                factory = new EPSGFactory(null);
             } catch (FactoryException e) {
                 final LogRecord record = new LogRecord(Level.CONFIG, e.getLocalizedMessage());
                 record.setLoggerName(Loggers.CRS_FACTORY);

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/EPSGFactoryFallback.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/EPSGFactoryFallback.java?rev=1728238&r1=1728237&r2=1728238&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/EPSGFactoryFallback.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/EPSGFactoryFallback.java [UTF-8] Tue Feb  2 23:39:20 2016
@@ -16,8 +16,10 @@
  */
 package org.apache.sis.referencing;
 
+import java.util.Collections;
 import java.util.Set;
 import java.util.LinkedHashSet;
+import java.util.Locale;
 import org.opengis.referencing.IdentifiedObject;
 import org.opengis.referencing.NoSuchAuthorityCodeException;
 import org.opengis.referencing.crs.GeocentricCRS;
@@ -28,9 +30,11 @@ import org.opengis.referencing.crs.CRSAu
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.opengis.metadata.citation.Citation;
 import org.apache.sis.metadata.iso.citation.Citations;
+import org.apache.sis.metadata.iso.citation.DefaultCitation;
 import org.apache.sis.referencing.factory.GeodeticAuthorityFactory;
 import org.apache.sis.internal.referencing.provider.TransverseMercator;
 import org.apache.sis.internal.util.Constants;
+import org.apache.sis.util.iso.SimpleInternationalString;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.util.Debug;
 
@@ -66,17 +70,38 @@ final class EPSGFactoryFallback extends
     static final CRSAuthorityFactory INSTANCE = new EPSGFactoryFallback();
 
     /**
+     * The authority, created when first needed.
+     */
+    private Citation authority;
+
+    /**
      * Constructor for the singleton instance.
      */
     private EPSGFactoryFallback() {
     }
 
     /**
-     * Returns the EPSG authority.
+     * Returns the EPSG authority with only a modification in the title of emphasing that this is a subset
+     * of EPSG dataset.
+     */
+    @Override
+    public synchronized Citation getAuthority() {
+        if (authority == null) {
+            final DefaultCitation c = new DefaultCitation(Citations.EPSG);
+            c.setTitle(new SimpleInternationalString("Subset of " + c.getTitle().toString(Locale.ENGLISH)));
+            authority = c;
+        }
+        return authority;
+    }
+
+    /**
+     * Returns the namespace of EPSG codes.
+     *
+     * @return The {@code "EPSG"} string in a singleton map.
      */
     @Override
-    public Citation getAuthority() {
-        return Citations.EPSG;
+    public Set<String> getCodeSpaces() {
+        return Collections.singleton(Constants.EPSG);
     }
 
     /**

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/IdentifiedObjects.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/IdentifiedObjects.java?rev=1728238&r1=1728237&r2=1728238&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/IdentifiedObjects.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/IdentifiedObjects.java [UTF-8] Tue Feb  2 23:39:20 2016
@@ -623,7 +623,11 @@ public final class IdentifiedObjects ext
         if (identifier == null) {
             return null;
         }
-        return NameMeaning.toURN(type, identifier.getCodeSpace(), identifier.getVersion(), identifier.getCode());
+        String cs = identifier.getCodeSpace();
+        if (cs == null || cs.isEmpty()) {
+            cs = org.apache.sis.internal.util.Citations.getIdentifier(identifier.getAuthority(), true);
+        }
+        return NameMeaning.toURN(type, cs, identifier.getVersion(), identifier.getCode());
     }
 
     /**

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java?rev=1728238&r1=1728237&r2=1728238&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java [UTF-8] Tue Feb  2 23:39:20 2016
@@ -109,6 +109,8 @@ import org.apache.sis.util.collection.Co
 import org.apache.sis.measure.MeasurementRange;
 import org.apache.sis.measure.Units;
 
+import static org.apache.sis.internal.referencing.ServicesForMetadata.CONNECTION;
+
 // Branch-dependent imports
 import org.apache.sis.internal.jdk8.JDK8;
 
@@ -129,7 +131,7 @@ import org.apache.sis.internal.jdk8.JDK8
  *
  * <div class="section">Life cycle and caching</div>
  * {@code EPSGDataAccess} instances should be short-lived since they may hold a significant amount of JDBC resources.
- * Those instances are created on the fly by {@link EPSGFactory} and closed after a relatively short
+ * {@code EPSGDataAccess} instances are created on the fly by {@link EPSGFactory} and closed after a relatively short
  * {@linkplain EPSGFactory#getTimeout timeout}.
  * In addition {@code EPSGFactory} caches the most recently created objects, which reduce greatly
  * the amount of {@code EPSGDataAccess} instantiations (and consequently the amount of database accesses)
@@ -269,9 +271,10 @@ public class EPSGDataAccess extends Geod
     private transient boolean quiet;
 
     /**
-     * The {@code ConcurrentAuthorityFactory} that supply caching for all {@code createFoo(String)} methods.
+     * The {@code ConcurrentAuthorityFactory} that created this Data Access Object (DAO).
+     * The owner supplies caching for all {@code createFoo(String)} methods.
      */
-    protected final EPSGFactory parent;
+    protected final EPSGFactory owner;
 
     /**
      * The connection to the EPSG database. This connection is specified at {@linkplain #EPSGDataAccess construction time}
@@ -297,21 +300,21 @@ public class EPSGDataAccess extends Geod
      * by the {@link EPSGFactory#newDataAccess(Connection, SQLTranslator)} method of a corresponding custom
      * {@code EPSGFactory} subclass.</div>
      *
-     * @param parent      The {@code EPSGFactory} which is creating this Data Access Object (DAO).
+     * @param owner       The {@code EPSGFactory} which is creating this Data Access Object (DAO).
      * @param connection  The connection to the underlying EPSG database.
      * @param translator  The translator from the SQL statements using MS-Access dialect
      *                    to SQL statements using the dialect of the actual database.
      *
      * @see EPSGFactory#newDataAccess(Connection, SQLTranslator)
      */
-    protected EPSGDataAccess(final EPSGFactory parent, final Connection connection, final SQLTranslator translator) {
+    protected EPSGDataAccess(final EPSGFactory owner, final Connection connection, final SQLTranslator translator) {
         ArgumentChecks.ensureNonNull("connection", connection);
         ArgumentChecks.ensureNonNull("translator", translator);
-        this.parent     = parent;
+        this.owner      = owner;
         this.connection = connection;
         this.translator = translator;
-        this.namespace  = parent.nameFactory.createNameSpace(
-                          parent.nameFactory.createLocalName(null, Constants.IOGP), null);
+        this.namespace  = owner.nameFactory.createNameSpace(
+                          owner.nameFactory.createLocalName(null, Constants.IOGP), null);
     }
 
     /**
@@ -322,7 +325,7 @@ public class EPSGDataAccess extends Geod
      */
     @Override
     public Locale getLocale() {
-        return parent.getLocale();
+        return owner.getLocale();
     }
 
     /**
@@ -407,7 +410,7 @@ addURIs:    for (int i=0; ; i++) {
                     case 1: url = "http://www.epsg.org/"; function = OnLineFunction.DOWNLOAD; break;
                     case 2: {
                         url = metadata.getURL();
-                        function = OnLineFunction.valueOf("CONNECTION");
+                        function = OnLineFunction.valueOf(CONNECTION);
                         description = Messages.formatInternational(Messages.Keys.DataBase_4,
                                 Constants.EPSG, version, metadata.getDatabaseProductName(),
                                 Version.valueOf(metadata.getDatabaseMajorVersion(),
@@ -1011,11 +1014,11 @@ addURIs:    for (int i=0; ; i++) {
         properties.clear();
         GenericName gn = null;
         final Locale locale = getLocale();
-        final Citation authority = parent.getAuthority();
+        final Citation authority = owner.getAuthority();
         final InternationalString edition = authority.getEdition();
         final String version = (edition != null) ? edition.toString() : null;
         if (name != null) {
-            gn = parent.nameFactory.createGenericName(namespace, Constants.EPSG, name);
+            gn = owner.nameFactory.createGenericName(namespace, Constants.EPSG, name);
             properties.put("name", gn);
             properties.put(NamedIdentifier.CODE_KEY,      name);
             properties.put(NamedIdentifier.VERSION_KEY,   version);
@@ -1030,6 +1033,7 @@ addURIs:    for (int i=0; ; i++) {
             final ImmutableIdentifier identifier;
             if (deprecated) {
                 identifier = new DeprecatedCode(authority, Constants.EPSG, codeString, version, getSupersession(table, code, locale));
+                properties.put(AbstractIdentifiedObject.DEPRECATED_KEY, Boolean.TRUE);
             } else {
                 identifier = new ImmutableIdentifier(authority, Constants.EPSG, codeString, version,
                                     (gn != null) ? gn.toInternationalString() : null);
@@ -1057,12 +1061,11 @@ addURIs:    for (int i=0; ; i++) {
                     if (naming != null) {
                         ns = namingSystems.get(naming);
                         if (ns == null) {
-                            ns = parent.nameFactory.createNameSpace(
-                                 parent.nameFactory.createLocalName(null, naming), null);
+                            ns = owner.nameFactory.createNameSpace(owner.nameFactory.createLocalName(null, naming), null);
                             namingSystems.put(naming, ns);
                         }
                     }
-                    aliases.add(parent.nameFactory.createLocalName(ns, alias));
+                    aliases.add(owner.nameFactory.createLocalName(ns, alias));
                 }
             }
         }
@@ -1070,7 +1073,7 @@ addURIs:    for (int i=0; ; i++) {
             properties.put(IdentifiedObject.ALIAS_KEY, aliases.toArray(new GenericName[aliases.size()]));
         }
         properties.put(AbstractIdentifiedObject.LOCALE_KEY, locale);
-        properties.put(ReferencingServices.MT_FACTORY, parent.mtFactory);
+        properties.put(ReferencingServices.MT_FACTORY, owner.mtFactory);
         return properties;
     }
 
@@ -1091,7 +1094,7 @@ addURIs:    for (int i=0; ; i++) {
     {
         final Map<String,Object> properties = createProperties(table, name, code, remarks, deprecated);
         if (domainCode != null) {
-            properties.put(Datum.DOMAIN_OF_VALIDITY_KEY, parent.createExtent(domainCode));
+            properties.put(Datum.DOMAIN_OF_VALIDITY_KEY, owner.createExtent(domainCode));
         }
         properties.put(Datum.SCOPE_KEY, scope);
         return properties;
@@ -1249,7 +1252,7 @@ addURIs:    for (int i=0; ; i++) {
                  * Note: Do not invoke 'createProperties' now, even if we have all required informations,
                  *       because the 'properties' map is going to overwritten by calls to 'createDatum', etc.
                  */
-                final CRSFactory crsFactory = parent.crsFactory;
+                final CRSFactory crsFactory = owner.crsFactory;
                 final CoordinateReferenceSystem crs;
                 switch (type.toLowerCase(Locale.US)) {
                     /* ----------------------------------------------------------------------
@@ -1260,17 +1263,17 @@ addURIs:    for (int i=0; ; i++) {
                      * ---------------------------------------------------------------------- */
                     case "geographic 2d":
                     case "geographic 3d": {
-                        final EllipsoidalCS cs = parent.createEllipsoidalCS(getString(code, result, 8));
+                        final EllipsoidalCS cs = owner.createEllipsoidalCS(getString(code, result, 8));
                         final String datumCode = getOptionalString(result, 9);
                         final GeodeticDatum datum;
                         if (datumCode != null) {
-                            datum = parent.createGeodeticDatum(datumCode);
+                            datum = owner.createGeodeticDatum(datumCode);
                         } else {
                             final String geoCode = getString(code, result, 10, 9);
                             result.close();     // Must be closed before call to createGeographicCRS(String)
                             ensureNoCycle(GeographicCRS.class, epsg);
                             try {
-                                datum = parent.createGeographicCRS(geoCode).getDatum();
+                                datum = owner.createGeographicCRS(geoCode).getDatum();
                             } finally {
                                 endOfRecursivity(GeographicCRS.class, epsg);
                             }
@@ -1292,9 +1295,9 @@ addURIs:    for (int i=0; ; i++) {
                         result.close();      // Must be closed before call to createFoo(String)
                         ensureNoCycle(ProjectedCRS.class, epsg);
                         try {
-                            final CartesianCS   cs       = parent.createCartesianCS(csCode);
-                            final GeographicCRS baseCRS  = parent.createGeographicCRS(geoCode);
-                            final CoordinateOperation op = parent.createCoordinateOperation(opCode);
+                            final CartesianCS   cs       = owner.createCartesianCS(csCode);
+                            final GeographicCRS baseCRS  = owner.createGeographicCRS(geoCode);
+                            final CoordinateOperation op = owner.createCoordinateOperation(opCode);
                             if (op instanceof Conversion) {
                                 crs = crsFactory.createProjectedCRS(createProperties("Coordinate Reference System",
                                         name, epsg, area, scope, remarks, deprecated), baseCRS, (Conversion) op, cs);
@@ -1310,8 +1313,8 @@ addURIs:    for (int i=0; ; i++) {
                      *   VERTICAL CRS
                      * ---------------------------------------------------------------------- */
                     case "vertical": {
-                        final VerticalCS    cs    = parent.createVerticalCS   (getString(code, result, 8));
-                        final VerticalDatum datum = parent.createVerticalDatum(getString(code, result, 9));
+                        final VerticalCS    cs    = owner.createVerticalCS   (getString(code, result, 8));
+                        final VerticalDatum datum = owner.createVerticalDatum(getString(code, result, 9));
                         crs = crsFactory.createVerticalCRS(createProperties("Coordinate Reference System",
                                 name, epsg, area, scope, remarks, deprecated), datum, cs);
                         break;
@@ -1324,8 +1327,8 @@ addURIs:    for (int i=0; ; i++) {
                      * ---------------------------------------------------------------------- */
                     case "time":
                     case "temporal": {
-                        final TimeCS        cs    = parent.createTimeCS       (getString(code, result, 8));
-                        final TemporalDatum datum = parent.createTemporalDatum(getString(code, result, 9));
+                        final TimeCS        cs    = owner.createTimeCS       (getString(code, result, 8));
+                        final TemporalDatum datum = owner.createTemporalDatum(getString(code, result, 9));
                         crs = crsFactory.createTemporalCRS(createProperties("Coordinate Reference System",
                                 name, epsg, area, scope, remarks, deprecated), datum, cs);
                         break;
@@ -1343,8 +1346,8 @@ addURIs:    for (int i=0; ; i++) {
                         final CoordinateReferenceSystem crs1, crs2;
                         ensureNoCycle(CompoundCRS.class, epsg);
                         try {
-                            crs1 = parent.createCoordinateReferenceSystem(code1);
-                            crs2 = parent.createCoordinateReferenceSystem(code2);
+                            crs1 = owner.createCoordinateReferenceSystem(code1);
+                            crs2 = owner.createCoordinateReferenceSystem(code2);
                         } finally {
                             endOfRecursivity(CompoundCRS.class, epsg);
                         }
@@ -1357,8 +1360,8 @@ addURIs:    for (int i=0; ; i++) {
                      *   GEOCENTRIC CRS
                      * ---------------------------------------------------------------------- */
                     case "geocentric": {
-                        final CoordinateSystem cs = parent.createCoordinateSystem(getString(code, result, 8));
-                        final GeodeticDatum datum = parent.createGeodeticDatum   (getString(code, result, 9));
+                        final CoordinateSystem cs = owner.createCoordinateSystem(getString(code, result, 8));
+                        final GeodeticDatum datum = owner.createGeodeticDatum   (getString(code, result, 9));
                         final Map<String,Object> properties = createProperties("Coordinate Reference System",
                                 name, epsg, area, scope, remarks, deprecated);
                         if (cs instanceof CartesianCS) {
@@ -1375,8 +1378,8 @@ addURIs:    for (int i=0; ; i++) {
                      *   ENGINEERING CRS
                      * ---------------------------------------------------------------------- */
                     case "engineering": {
-                        final CoordinateSystem cs    = parent.createCoordinateSystem(getString(code, result, 8));
-                        final EngineeringDatum datum = parent.createEngineeringDatum(getString(code, result, 9));
+                        final CoordinateSystem cs    = owner.createCoordinateSystem(getString(code, result, 8));
+                        final EngineeringDatum datum = owner.createEngineeringDatum(getString(code, result, 9));
                         crs = crsFactory.createEngineeringCRS(createProperties("Coordinate Reference System",
                                 name, epsg, area, scope, remarks, deprecated), datum, cs);
                         break;
@@ -1468,7 +1471,7 @@ addURIs:    for (int i=0; ; i++) {
                 } catch (NumberFormatException exception) {
                     unexpectedException("createDatum", exception);          // Not a fatal error.
                 }
-                final DatumFactory datumFactory = parent.datumFactory;
+                final DatumFactory datumFactory = owner.datumFactory;
                 final Datum datum;
                 switch (type.toLowerCase(Locale.US)) {
                     /*
@@ -1478,8 +1481,8 @@ addURIs:    for (int i=0; ; i++) {
                      */
                     case "geodetic": {
                         properties = new HashMap<>(properties);         // Protect from changes
-                        final Ellipsoid ellipsoid    = parent.createEllipsoid    (getString(code, result, 10));
-                        final PrimeMeridian meridian = parent.createPrimeMeridian(getString(code, result, 11));
+                        final Ellipsoid ellipsoid    = owner.createEllipsoid    (getString(code, result, 10));
+                        final PrimeMeridian meridian = owner.createPrimeMeridian(getString(code, result, 11));
                         final BursaWolfParameters[] param = createBursaWolfParameters(epsg);
                         if (param != null) {
                             properties.put(DefaultGeodeticDatum.BURSA_WOLF_KEY, param);
@@ -1615,7 +1618,7 @@ addURIs:    for (int i=0; ; i++) {
             final GeodeticDatum datum;
             ensureNoCycle(BursaWolfParameters.class, code);    // See comment at the begining of this method.
             try {
-                datum = parent.createGeodeticDatum(String.valueOf(info.target));
+                datum = owner.createGeodeticDatum(String.valueOf(info.target));
             } finally {
                 endOfRecursivity(BursaWolfParameters.class, code);
             }
@@ -1632,7 +1635,7 @@ addURIs:    for (int i=0; ; i++) {
                     BursaWolfInfo.setBursaWolfParameter(bwp,
                             getInteger(info.operation, result, 1),
                             getDouble (info.operation, result, 2),
-                            parent.createUnit(getString(info.operation, result, 3)), locale);
+                            owner.createUnit(getString(info.operation, result, 3)), locale);
                 }
             }
             if (info.isFrameRotation()) {
@@ -1700,7 +1703,7 @@ addURIs:    for (int i=0; ; i++) {
                 final String  unitCode          = getString   (code, result, 6);
                 final String  remarks           = getOptionalString (result, 7);
                 final boolean deprecated        = getOptionalBoolean(result, 8);
-                final Unit<Length> unit         = parent.createUnit(unitCode).asType(Length.class);
+                final Unit<Length> unit         = owner.createUnit(unitCode).asType(Length.class);
                 final Map<String,Object> properties = createProperties("Ellipsoid", name, epsg, remarks, deprecated);
                 final Ellipsoid ellipsoid;
                 if (Double.isNaN(inverseFlattening)) {
@@ -1710,7 +1713,7 @@ addURIs:    for (int i=0; ; i++) {
                         throw new FactoryDataException(error().getString(Errors.Keys.NullValueInTable_3, code, column));
                     } else {
                         // We only have semiMinorAxis defined. It is OK
-                        ellipsoid = parent.datumFactory.createEllipsoid(properties, semiMajorAxis, semiMinorAxis, unit);
+                        ellipsoid = owner.datumFactory.createEllipsoid(properties, semiMajorAxis, semiMinorAxis, unit);
                     }
                 } else {
                     if (!Double.isNaN(semiMinorAxis)) {
@@ -1721,7 +1724,7 @@ addURIs:    for (int i=0; ; i++) {
                         record.setLoggerName(Loggers.CRS_FACTORY);
                         Logging.log(EPSGDataAccess.class, "createEllipsoid", record);
                     }
-                    ellipsoid = parent.datumFactory.createFlattenedSphere(properties, semiMajorAxis, inverseFlattening, unit);
+                    ellipsoid = owner.datumFactory.createFlattenedSphere(properties, semiMajorAxis, inverseFlattening, unit);
                 }
                 returnValue = ensureSingleton(ellipsoid, returnValue, code);
             }
@@ -1780,8 +1783,8 @@ addURIs:    for (int i=0; ; i++) {
                 final String  unitCode   = getString   (code, result, 4);
                 final String  remarks    = getOptionalString (result, 5);
                 final boolean deprecated = getOptionalBoolean(result, 6);
-                final Unit<Angle> unit = parent.createUnit(unitCode).asType(Angle.class);
-                final PrimeMeridian primeMeridian = parent.datumFactory.createPrimeMeridian(
+                final Unit<Angle> unit = owner.createUnit(unitCode).asType(Angle.class);
+                final PrimeMeridian primeMeridian = owner.datumFactory.createPrimeMeridian(
                         createProperties("Prime Meridian", name, epsg, remarks, deprecated), longitude, unit);
                 returnValue = ensureSingleton(primeMeridian, returnValue, code);
             }
@@ -1919,7 +1922,7 @@ addURIs:    for (int i=0; ; i++) {
                 final boolean deprecated = getOptionalBoolean(result, 6);
                 final CoordinateSystemAxis[] axes = createCoordinateSystemAxes(epsg, dimension);
                 final Map<String,Object> properties = createProperties("Coordinate System", name, epsg, remarks, deprecated);   // Must be after axes.
-                final CSFactory csFactory = parent.csFactory;
+                final CSFactory csFactory = owner.csFactory;
                 CoordinateSystem cs = null;
                 switch (type.toLowerCase(Locale.US)) {
                     case "ellipsoidal": {
@@ -2052,7 +2055,7 @@ addURIs:    for (int i=0; ; i++) {
                      * If 'i' is out of bounds, an exception will be thrown after the loop.
                      * We do not want to thrown an ArrayIndexOutOfBoundsException here.
                      */
-                    axes[i] = parent.createCoordinateSystemAxis(axis);
+                    axes[i] = owner.createCoordinateSystemAxis(axis);
                 }
                 ++i;
             }
@@ -2113,9 +2116,8 @@ addURIs:    for (int i=0; ; i++) {
                     throw new FactoryDataException(exception.getLocalizedMessage(), exception);
                 }
                 final AxisName an = getAxisName(nameCode);
-                final CoordinateSystemAxis axis = parent.csFactory.createCoordinateSystemAxis(
-                        createProperties("Coordinate Axis", an.name, epsg, an.description, false),
-                        abbreviation, direction, parent.createUnit(unit));
+                final CoordinateSystemAxis axis = owner.csFactory.createCoordinateSystemAxis(createProperties("Coordinate Axis", an.name, epsg, an.description, false),
+                        abbreviation, direction, owner.createUnit(unit));
                 returnValue = ensureSingleton(axis, returnValue, code);
             }
         } catch (SQLException exception) {
@@ -2299,7 +2301,7 @@ addURIs:    for (int i=0; ; i++) {
                         if (element != null) {
                             valueDomain = MeasurementRange.create(Double.NEGATIVE_INFINITY, false,
                                     Double.POSITIVE_INFINITY, false,
-                                    parent.createUnit(element));
+                                    owner.createUnit(element));
                         }
                     } else {
                         type = Double.class;
@@ -2338,7 +2340,7 @@ addURIs:    for (int i=0; ; i++) {
                 " ORDER BY SORT_ORDER", method))
         {
             while (result.next()) {
-                descriptors.add(parent.createParameterDescriptor(getString(method, result, 1)));
+                descriptors.add(owner.createParameterDescriptor(getString(method, result, 1)));
             }
         }
         return descriptors.toArray(new ParameterDescriptor<?>[descriptors.size()]);
@@ -2385,7 +2387,7 @@ addURIs:    for (int i=0; ; i++) {
                 } else {
                     reference = null;
                     final String unitCode = getOptionalString(result, 4);
-                    unit = (unitCode != null) ? parent.createUnit(unitCode) : null;
+                    unit = (unitCode != null) ? owner.createUnit(unitCode) : null;
                 }
                 final ParameterValue<?> param;
                 try {
@@ -2559,21 +2561,24 @@ addURIs:    for (int i=0; ; i++) {
                      * However, this default number of dimensions is not generalizable to other kind of operation methods.
                      * For example the "Geocentric translation" operation method has 3-dimensional source and target CRS.
                      */
+                    boolean isDimensionKnown = true;
                     final int sourceDimensions, targetDimensions;
                     final CoordinateReferenceSystem sourceCRS, targetCRS;
                     if (sourceCode != null) {
-                        sourceCRS = parent.createCoordinateReferenceSystem(sourceCode);
+                        sourceCRS = owner.createCoordinateReferenceSystem(sourceCode);
                         sourceDimensions = sourceCRS.getCoordinateSystem().getDimension();
                     } else {
                         sourceCRS = null;
                         sourceDimensions = 2;       // Acceptable default for projections only.
+                        isDimensionKnown = false;
                     }
                     if (targetCode != null) {
-                        targetCRS = parent.createCoordinateReferenceSystem(targetCode);
+                        targetCRS = owner.createCoordinateReferenceSystem(targetCode);
                         targetDimensions = targetCRS.getCoordinateSystem().getDimension();
                     } else {
                         targetCRS = null;
                         targetDimensions = 2;       // Acceptable default for projections only.
+                        isDimensionKnown = false;
                     }
                     /*
                      * Get the operation method. This is mandatory for conversions and transformations
@@ -2586,8 +2591,10 @@ addURIs:    for (int i=0; ; i++) {
                         method      = null;
                         parameters  = null;
                     } else {
-                        method = parent.createOperationMethod(methodCode.toString());
-                        method = DefaultOperationMethod.redimension(method, sourceDimensions, targetDimensions);
+                        method = owner.createOperationMethod(methodCode.toString());
+                        if (isDimensionKnown) {
+                            method = DefaultOperationMethod.redimension(method, sourceDimensions, targetDimensions);
+                        }
                         parameters = method.getParameters().createValue();
                         fillParameterValues(methodCode, epsg, parameters);
                     }
@@ -2613,7 +2620,7 @@ addURIs:    for (int i=0; ; i++) {
                      * (usually to be used later as part of a ProjectedCRS creation).
                      */
                     final CoordinateOperation operation;
-                    final CoordinateOperationFactory copFactory = parent.copFactory;
+                    final CoordinateOperationFactory copFactory = owner.copFactory;
                     if (isConversion && (sourceCRS == null || targetCRS == null)) {
                         operation = copFactory.createDefiningConversion(opProperties, method, parameters);
                     } else if (isConcatenated) {
@@ -2638,7 +2645,7 @@ addURIs:    for (int i=0; ; i++) {
                         ensureNoCycle(CoordinateOperation.class, epsg);
                         try {
                             for (int i=0; i<operations.length; i++) {
-                                operations[i] = parent.createCoordinateOperation(codes.get(i));
+                                operations[i] = owner.createCoordinateOperation(codes.get(i));
                             }
                         } finally {
                             endOfRecursivity(CoordinateOperation.class, epsg);
@@ -2656,7 +2663,7 @@ addURIs:    for (int i=0; ; i++) {
                          * GeoAPI method can not handle Molodensky transform because it does not give the target datum).
                          */
                         final MathTransform mt;
-                        final MathTransformFactory mtFactory = parent.mtFactory;
+                        final MathTransformFactory mtFactory = owner.mtFactory;
                         if (mtFactory instanceof DefaultMathTransformFactory) {
                             DefaultMathTransformFactory.Context context = new DefaultMathTransformFactory.Context();
                             context.setSource(sourceCRS);
@@ -2733,7 +2740,7 @@ addURIs:    for (int i=0; ; i++) {
         ArgumentChecks.ensureNonNull("sourceCRS", sourceCRS);
         ArgumentChecks.ensureNonNull("targetCRS", targetCRS);
         final String label = sourceCRS + " ⇨ " + targetCRS;
-        final CoordinateOperationSet set = new CoordinateOperationSet(parent);
+        final CoordinateOperationSet set = new CoordinateOperationSet(owner);
         try {
             final int[] pair = toPrimaryKeys(null, null, null, sourceCRS, targetCRS);
             boolean searchTransformations = false;
@@ -2810,7 +2817,7 @@ addURIs:    for (int i=0; ; i++) {
          * Creates a new finder.
          */
         Finder() {
-            super(parent);
+            super(owner);
         }
 
         /**



Mime
View raw message