sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1811213 - in /sis/branches/JDK8/core: sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/ sis-utility/src/main/java/org/apache/sis/internal/system/ sis-utility/src/main/java/org/apache/sis/setup/
Date Thu, 05 Oct 2017 14:56:40 GMT
Author: desruisseaux
Date: Thu Oct  5 14:56:40 2017
New Revision: 1811213

URL: http://svn.apache.org/viewvc?rev=1811213&view=rev
Log:
If the 'non-free:sis-embedded-data' module is present, connect to the embedded Derby database.

Modified:
    sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/Initializer.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/system/DataDirectory.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/setup/About.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/setup/InstallationResources.java

Modified: sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/Initializer.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/Initializer.java?rev=1811213&r1=1811212&r2=1811213&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/Initializer.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/Initializer.java
[UTF-8] Thu Oct  5 14:56:40 2017
@@ -22,6 +22,7 @@ import java.net.URLClassLoader;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.io.IOException;
 import java.util.concurrent.Callable;
 import java.util.logging.Level;
 import java.util.logging.LogRecord;
@@ -41,6 +42,7 @@ import javax.naming.event.EventContext;
 import javax.naming.event.NamingEvent;
 import javax.naming.event.NamingExceptionEvent;
 import javax.naming.event.ObjectChangeListener;
+import org.apache.sis.setup.InstallationResources;
 import org.apache.sis.internal.system.DefaultFactories;
 import org.apache.sis.internal.system.DataDirectory;
 import org.apache.sis.internal.system.Shutdown;
@@ -93,6 +95,11 @@ public abstract class Initializer {
     public static final String JNDI = "jdbc/" + DATABASE;
 
     /**
+     * A pseudo-authority name used by {@link InstallationResources} for the embedded data
resources.
+     */
+    public static final String EMBEDDED = "Embedded";
+
+    /**
      * 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.
@@ -112,6 +119,7 @@ public abstract class Initializer {
     /**
      * {@code true} if {@link #connected(DatabaseMetaData)} has been invoked at least once.
      * This is reset to {@code false} if the {@link #source} is changed.
+     * We use this information for logging purpose.
      */
     private static boolean connected;
 
@@ -251,6 +259,10 @@ public abstract class Initializer {
                     Listener.register((EventContext) env);
                 }
                 return source;
+                /*
+                 * No Derby shutdown hook for DataSource fetched fron JNDI.
+                 * We presume that shutdowns are handled by the container.
+                 */
             } catch (NameNotFoundException e) {
                 final LogRecord record = Messages.getResources(null).getLogRecord(
                         Level.CONFIG, Messages.Keys.JNDINotSpecified_1, JNDI);
@@ -260,38 +272,51 @@ public abstract class Initializer {
             /*
              * 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.
+             * Only if the SIS_DATA environment variable is not set, verify first if the
'sis-embedded-data' module is
+             * on the classpath. Note that if SIS_DATA is defined and valid, it has precedence.
              */
             final boolean create;
-            final String home = AccessController.doPrivileged((PrivilegedAction<String>)
() -> System.getProperty(DERBY_HOME_KEY));
-            final Path dir = DataDirectory.DATABASES.getDirectory();
-            if (dir != null) {
-                Path path = dir.resolve(DATABASE);
-                if (home != null) try {
+            final boolean isEnvClear = DataDirectory.isEnvClear();
+            if (isEnvClear && (source = embedded()) != null) {
+                create = false;
+            } else {
+                final String home = AccessController.doPrivileged((PrivilegedAction<String>)
() -> System.getProperty(DERBY_HOME_KEY));
+                final Path dir = DataDirectory.DATABASES.getDirectory();
+                if (dir != 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);
+                    }
                     /*
-                     * 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.
+                     * 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 = 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);
+                    path   = path.normalize();
+                    create = !Files.exists(path);
+                    source = forJavaDB(path.toString().replace(path.getFileSystem().getSeparator(),
"/"));
+                } else if (home != null) {
+                    final Path path = Paths.get(home);
+                    create = !Files.exists(path.resolve(DATABASE)) && Files.isDirectory(path);
+                    source = forJavaDB(DATABASE);
+                } else if (!isEnvClear) {
+                    create = false;
+                    source = embedded();        // Try only if we did not already tried after
above JNDI check.
+                    if (source == null) {
+                        return null;
+                    }
+                } else {
+                    return null;
                 }
-                /*
-                 * 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().replace(path.getFileSystem().getSeparator(),
"/"));
-            } else if (home != null) {
-                final Path path = Paths.get(home);
-                create = !Files.exists(path.resolve(DATABASE)) && Files.isDirectory(path);
-                source = forJavaDB(DATABASE);
-            } else {
-                return null;
             }
             /*
              * Register the shutdown hook before to attempt any operation on the database
in order to close
@@ -333,6 +358,34 @@ public abstract class Initializer {
     }
 
     /**
+     * If the {@code non-free:sis-embedded-data} module is present on the classpath,
+     * returns the data source for embedded Derby database. Otherwise returns {@code null}.
+     *
+     * @see <a href="https://issues.apache.org/jira/browse/SIS-337">SIS-337</a>
+     *
+     * @since 0.8
+     */
+    private static DataSource embedded() {
+        for (InstallationResources res : DefaultFactories.createServiceLoader(InstallationResources.class))
{
+            if (res.getAuthorities().contains(EMBEDDED)) try {
+                final String[] names = res.getResourceNames(EMBEDDED);
+                for (int i=0; i<names.length; i++) {
+                    if (DATABASE.equals(names[i])) {
+                        final Object ds = res.getResource(EMBEDDED, i);
+                        if (ds instanceof DataSource) {
+                            return (DataSource) ds;
+                        }
+                    }
+                }
+            } catch (IOException e) {
+                Logging.unexpectedException(Logging.getLogger(Loggers.SQL), Initializer.class,
"getDataSource", e);
+                // Continue - the system will fallback on the hard-coded subset of EPSG definitions.
+            }
+        }
+        return null;
+    }
+
+    /**
      * Prepares a log record saying that a connection to the spatial metadata database has
been created.
      * This method can be invoked after {@link DataSource#getConnection()}. When invoked
for the first time,
      * the record level is set to {@link Level#CONFIG}. On next calls, the level become {@link
Level#FINE}.

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/system/DataDirectory.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/system/DataDirectory.java?rev=1811213&r1=1811212&r2=1811213&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/system/DataDirectory.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/system/DataDirectory.java
[UTF-8] Thu Oct  5 14:56:40 2017
@@ -33,7 +33,7 @@ import org.apache.sis.util.resources.Mes
  * Sub-directories of {@code SIS_DATA} where SIS looks for EPSG database, datum shift grids
and other resources.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 0.7
+ * @version 0.8
  * @since   0.7
  * @module
  */
@@ -106,6 +106,40 @@ public enum DataDirectory {
     }
 
     /**
+     * Returns the value of {@value #ENV} environment variable, or {@code null} if none.
+     * This method does not perform any logging and does not verify if the directory exists.
+     * If the intend is to perform I/O operations, use {@link #getRootDirectory()} instead.
+     *
+     * @return the {@value #ENV} environment variable, or {@code null} if none.
+     * @throws SecurityException if this method is not allowed to query the environment variable.
+     *
+     * @see System#getenv(String)
+     *
+     * @since 0.8
+     */
+    public static String getenv() throws SecurityException {
+        return AccessController.doPrivileged((PrivilegedAction<String>) () -> System.getenv(ENV));
+    }
+
+    /**
+     * Returns {@code true} if the {@value #ENV} environment variable is unset. In case of
doubt, this method
+     * returns {@code false}. This method is used for avoiding or at leat delaying the log
messages emitted by
+     * {@link #getRootDirectory()} when a fallback exists in absence of any user attempt
to configure the system.
+     *
+     * @return {@code true} if the {@value #ENV} environment variable is unset.
+     *
+     * @since 0.8
+     */
+    public static synchronized boolean isEnvClear() {
+        if (rootDirectory == null) try {
+            return getenv() == null;
+        } catch (SecurityException e) {
+            Logging.recoverableException(Logging.getLogger(Loggers.SYSTEM), DataDirectory.class,
"isEnvClear", e);
+        }
+        return false;
+    }
+
+    /**
      * Returns the root directory fetched from the {@code SIS_DATA} environment variable.
      * If the environment variable is not set or the directory does not exist, then this
method returns {@code null}.
      *
@@ -113,7 +147,7 @@ public enum DataDirectory {
      */
     public static synchronized Path getRootDirectory() {
         if (rootDirectory == null) try {
-            final String dir = AccessController.doPrivileged((PrivilegedAction<String>)
() -> System.getenv(ENV));
+            final String dir = getenv();
             if (dir == null || dir.isEmpty()) {
                 warning("getRootDirectory", null, Messages.Keys.DataDirectoryNotSpecified_1,
ENV);
             } else try {

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/setup/About.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/setup/About.java?rev=1811213&r1=1811212&r2=1811213&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/setup/About.java [UTF-8]
(original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/setup/About.java [UTF-8]
Thu Oct  5 14:56:40 2017
@@ -39,8 +39,6 @@ import java.text.DateFormat;
 import java.text.FieldPosition;
 import java.nio.file.Path;
 import java.nio.charset.Charset;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.CharSequences;
 import org.apache.sis.util.Exceptions;
@@ -382,7 +380,7 @@ fill:   for (int i=0; ; i++) {
                     if (sections.contains(PATHS)) {
                         nameKey = Vocabulary.Keys.DataDirectory;
                         try {
-                            value = AccessController.doPrivileged((PrivilegedAction<String>)
() -> System.getenv(DataDirectory.ENV));
+                            value = DataDirectory.getenv();
                         } catch (SecurityException e) {
                             value = e.toString();
                         }

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/setup/InstallationResources.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/setup/InstallationResources.java?rev=1811213&r1=1811212&r2=1811213&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/setup/InstallationResources.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/setup/InstallationResources.java
[UTF-8] Thu Oct  5 14:56:40 2017
@@ -42,7 +42,7 @@ import java.io.BufferedReader;
  * The embedded database is provided as a convenience for avoiding the need to define a {@code
SIS_DATA} directory
  * on the local machine.
  *
- * <table>
+ * <table class="sis">
  *   <caption>Authorities supported by Apache SIS</caption>
  *   <tr><th>Authority</th>          <th>Provided by Maven module</th>
                         <th>Used by class</th></tr>
  *   <tr><td>{@code "EPSG"}</td>     <td>{@code org.apache.sis.non-free:sis-epsg}</td>
         <td>{@link org.apache.sis.referencing.factory.sql.EPSGFactory}</td></tr>
@@ -79,7 +79,7 @@ public abstract class InstallationResour
      * The values recognized by SIS are listed below
      * (note that this list may be expanded in any future SIS versions):
      *
-     * <table>
+     * <table class="sis">
      *   <caption>Authorities supported by Apache SIS</caption>
      *   <tr><th>Authority</th>          <th>Resources</th></tr>
      *   <tr><td>{@code "EPSG"}</td>     <td>SQL installation scripts
for EPSG geodetic dataset.</td></tr>
@@ -104,7 +104,7 @@ public abstract class InstallationResour
      * Returns the terms of use of the resources distributed by the specified authority,
or {@code null} if none.
      * The terms of use can be returned in either plain text or HTML.
      *
-     * <table>
+     * <table class="sis">
      *   <caption>Licenses for some supported authorities</caption>
      *   <tr>
      *     <th>Authority</th>
@@ -133,11 +133,11 @@ public abstract class InstallationResour
      * Examples:
      *
      * <ul class="verbose">
-     *   <li><b>{@code "EPSG"}</b> authority:<br>
+     *   <li><b>{@code "EPSG"} authority:</b>
      *     the resource names are the filenames of all SQL scripts to execute. One of the
first script creates tables,
      *     followed by a script that populates tables with data, followed by a script that
creates foreigner keys.
      *   </li>
-     *   <li><b>{@code "Embedded"}</b> pseudo-authority:<br>
+     *   <li><b>{@code "Embedded"} pseudo-authority:</b>
      *     the database name, which is {@code "SpatialMetadata"}.
      *     When embedded, this database is read-only.
      *   </li>



Mime
View raw message