Author: desruisseaux
Date: Tue May 22 16:35:40 2018
New Revision: 1832046

URL: http://svn.apache.org/viewvc?rev=1832046&view=rev
Log:
Reduce the amount of exceptions logged when the application can not connect to 
the spatial metadata database.

Added:
    
sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/MetadataFallback.java
   (with props)
Modified:
    
sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/Initializer.java
    
sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/MetadataSource.java
    sis/branches/JDK8/core/sis-referencing-by-identifiers/pom.xml
    
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGFactory.java
    
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/report/CoordinateReferenceSystems.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=1832046&r1=1832045&r2=1832046&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] Tue May 22 16:35:40 2018
@@ -70,7 +70,7 @@ import org.apache.sis.util.logging.Loggi
  * All other methods are related to getting the {@code DataSource} instance, 
through JNDI or otherwise.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 0.8
+ * @version 1.0
  * @since   0.7
  * @module
  */
@@ -422,9 +422,10 @@ public abstract class Initializer {
      * This message can be used for constructing an exception when {@link 
#getDataSource()} returned {@code null}.
      *
      * @param  locale  the locale for the message to produce, or {@code null} 
for the default one.
+     * @param  asLog   {@code true} for returning the message as a {@link 
LogRecord}, {@code false} for a {@link String}.
      * @return message for unspecified data source.
      */
-    public static String unspecified(final Locale locale) {
+    public static Object unspecified(final Locale locale, final boolean asLog) 
{
         final short key;
         final String value;
         if (hasJNDI()) {
@@ -434,7 +435,8 @@ public abstract class Initializer {
             key = Messages.Keys.DataDirectoryNotSpecified_1;
             value = DataDirectory.ENV;
         }
-        return Messages.getResources(locale).getString(key, value);
+        final Messages resources = Messages.getResources(locale);
+        return asLog ? resources.getLogRecord(Level.WARNING, key, value) : 
resources.getString(key, value);
     }
 
     /**
@@ -486,7 +488,7 @@ public abstract class Initializer {
      */
     private static DataSource forJavaDB(final String path, final ClassLoader 
loader) throws Exception {
         final Class<?> c = 
Class.forName("org.apache.derby.jdbc.EmbeddedDataSource", true, loader);
-        final DataSource ds = (DataSource) c.newInstance();
+        final DataSource ds = (DataSource) c.getConstructor().newInstance();
         final Class<?>[] args = {String.class};
         c.getMethod("setDatabaseName", args).invoke(ds, path);
         c.getMethod("setDataSourceName", args).invoke(ds, "Apache SIS spatial 
metadata");

Added: 
sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/MetadataFallback.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/MetadataFallback.java?rev=1832046&view=auto
==============================================================================
--- 
sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/MetadataFallback.java
 (added)
+++ 
sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/MetadataFallback.java
 [UTF-8] Tue May 22 16:35:40 2018
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.metadata.sql;
+
+import org.opengis.util.ControlledVocabulary;
+import org.apache.sis.util.ArgumentChecks;
+import org.apache.sis.util.logging.WarningListener;
+import org.apache.sis.xml.NilReason;
+
+
+/**
+ * A fallback providing hard-coded values of metadata entities.
+ * Used when connection to the spatial metadata can not be established.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 1.0
+ * @since   1.0
+ * @module
+ */
+final class MetadataFallback extends MetadataSource {
+    /**
+     * The unique instance of this fallback.
+     */
+    static final MetadataFallback INSTANCE = new MetadataFallback();
+
+    /**
+     * Creates the singleton.
+     */
+    private MetadataFallback() {
+    }
+
+    /**
+     * Searches for the given metadata in the hard-coded list.
+     *
+     * @param  metadata  the metadata to search for.
+     * @return the identifier of the given metadata, or {@code null} if none.
+     */
+    @Override
+    public String search(final Object metadata) {
+        ArgumentChecks.ensureNonNull("metadata", metadata);
+        return null;
+    }
+
+    /**
+     * Returns a hard-coded metadata filled with the data referenced by the 
specified identifier.
+     * Alternatively, this method can also return a {@code CodeList} or {@code 
Enum} element.
+     *
+     * @param  <T>         the parameterized type of the {@code type} argument.
+     * @param  type        the interface to implement, or {@code CodeList} or 
some {@code Enum} types.
+     * @param  identifier  the identifier of hard-coded values for the 
metadata entity to be returned.
+     * @return an implementation of the required interface, or the code list 
element.
+     */
+    @Override
+    public <T> T lookup(final Class<T> type, final String identifier) {
+        ArgumentChecks.ensureNonNull("type", type);
+        ArgumentChecks.ensureNonEmpty("identifier", identifier);
+        Object value;
+        if (ControlledVocabulary.class.isAssignableFrom(type)) {
+            value = getCodeList(type, identifier);
+        } else {
+            // TODO: move some code from ServicesForUtility here.
+            return NilReason.MISSING.createNilObject(type);
+        }
+        return type.cast(value);
+    }
+
+    /**
+     * Ignored.
+     */
+    @Override
+    public void addWarningListener(WarningListener<? super MetadataSource> 
listener) {
+    }
+
+    /**
+     * Ignored.
+     */
+    @Override
+    public void removeWarningListener(WarningListener<? super MetadataSource> 
listener) {
+    }
+
+    /**
+     * Ignored.
+     */
+    @Override
+    public void close() {
+    }
+}

Propchange: 
sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/MetadataFallback.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/MetadataFallback.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain;charset=UTF-8

Modified: 
sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/MetadataSource.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/MetadataSource.java?rev=1832046&r1=1832045&r2=1832046&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/MetadataSource.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/MetadataSource.java
 [UTF-8] Tue May 22 16:35:40 2018
@@ -41,6 +41,7 @@ import java.sql.Connection;
 import java.sql.Statement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
+import java.sql.SQLTransientException;
 import java.sql.SQLNonTransientException;
 import java.sql.PreparedStatement;
 import org.opengis.annotation.UML;
@@ -106,7 +107,7 @@ import org.apache.sis.util.iso.Types;
  *
  * @author  Touraïvane (IRD)
  * @author  Martin Desruisseaux (IRD, Geomatys)
- * @version 0.8
+ * @version 1.0
  * @since   0.8
  * @module
  */
@@ -285,12 +286,16 @@ public class MetadataSource implements A
     /**
      * The instance connected to the {@code "jdbc/SpatialMetadata"} database,
      * created when first needed and cleared when the classpath change.
+     * May be {@link MetadataFallback#INSTANCE} if we failed to establish
+     * a connection to the database for a non-transient reason.
      */
-    private static volatile MetadataSource instance;
+    private static MetadataSource instance;
     static {
         SystemListener.add(new SystemListener(Modules.METADATA) {
             @Override protected void classpathChanged() {
-                instance = null;
+                synchronized (MetadataSource.class) {
+                    instance = null;
+                }
             }
         });
     }
@@ -302,28 +307,51 @@ public class MetadataSource implements A
      * citations} and {@linkplain 
org.apache.sis.metadata.iso.distribution.DefaultFormat formats}
      * among others.
      *
+     * <p>If connection to the metadata database can not be established, then 
this method returns
+     * a fallback with a few hard-coded values.</p>
+     *
      * @return source of pre-defined metadata records from the {@code 
"jdbc/SpatialMetadata"} database.
-     * @throws MetadataStoreException if this method can not connect to the 
database.
      */
-    public static MetadataSource getProvided() throws MetadataStoreException {
+    public static synchronized MetadataSource getProvided() {
         MetadataSource ms = instance;
         if (ms == null) {
-            final DataSource dataSource;
+            LogRecord warning = null;
+            boolean isTransient = false;
             try {
-                dataSource = Initializer.getDataSource();
-            } catch (Exception e) {
-                throw new 
MetadataStoreException(Errors.format(Errors.Keys.CanNotConnectTo_1, 
Initializer.JNDI), e);
-            }
-            if (dataSource == null) {
-                throw new 
MetadataStoreException(Initializer.unspecified(null));
-            }
-            synchronized (MetadataSource.class) {
-                ms = instance;
-                if (ms == null) {
+                final DataSource dataSource = Initializer.getDataSource();
+                if (dataSource != null) {
                     ms = new MetadataSource(MetadataStandard.ISO_19115, 
dataSource, "metadata", null);
                     ms.install();
-                    instance = ms;
+                } else {
+                    warning = (LogRecord) Initializer.unspecified(null, true);
+                    ms = MetadataFallback.INSTANCE;
                 }
+            } catch (Exception e) {
+                ms = MetadataFallback.INSTANCE;
+                /*
+                 * Derby sometime wraps SQLException into another 
SQLException.  For making the stack strace a
+                 * little bit simpler, keep only the root cause provided that 
the exception type is compatible.
+                 */
+                warning = Errors.getResources((Locale) 
null).getLogRecord(Level.WARNING, Errors.Keys.CanNotConnectTo_1, 
Initializer.JNDI);
+                warning.setThrown(Exceptions.unwrap(e));
+                /*
+                 * If the error is transient or has a transient cause, we will 
not save MetadataFallback.INSTANCE
+                 * in the 'instance' field. The intent is to try again next 
time this method will be invoked, in
+                 * case the transient error has disappeared.
+                 */
+                for (Throwable cause = e; cause != null; cause = 
cause.getCause()) {
+                    if (cause instanceof SQLTransientException) {
+                        isTransient = true;
+                        break;
+                    }
+                }
+            }
+            if (warning != null) {
+                warning.setLoggerName(Loggers.SYSTEM);
+                Logging.log(MetadataSource.class, "getProvided", warning);
+            }
+            if (!isTransient) {
+                instance = ms;
             }
         }
         return ms;
@@ -399,6 +427,21 @@ public class MetadataSource implements A
     }
 
     /**
+     * For {@link MetadataFallback} constructor only.
+     */
+    MetadataSource() {
+        standard     = MetadataStandard.ISO_19115;
+        dataSource   = null;
+        catalog      = null;
+        statements   = null;
+        tableColumns = null;
+        classloader  = getClass().getClassLoader();
+        pool         = null;
+        lastUsed     = null;
+        listeners    = null;
+    }
+
+    /**
      * If the metadata schema does not exist in the database, creates it and 
inserts the pre-defined metadata values.
      * The current implementation has the following restrictions:
      *
@@ -410,32 +453,24 @@ public class MetadataSource implements A
      * Maintenance note: this method is invoked by reflection in {@code 
non-free:sis-embedded-data} module.
      * If we make this method public in a future Apache SIS version, then we 
can remove the reflection code.
      *
-     * @throws MetadataStoreException if an error occurred while inserting the 
metadata.
+     * @throws SQLException if an error occurred while inserting the metadata.
      */
-    final synchronized void install() throws MetadataStoreException {
-        try {
-            final Connection connection = connection();
-            final DatabaseMetaData md = connection.getMetaData();
-            if (md.storesUpperCaseIdentifiers()) {
-                schema = schema.toUpperCase(Locale.US);
-            } else if (md.storesLowerCaseIdentifiers()) {
-                schema = schema.toLowerCase(Locale.US);
-            }
-            quoteSchema = false;
-            try (ResultSet result = md.getTables(catalog, schema, 
"CI_Citation", null)) {
-                if (result.next()) {
-                    return;
-                }
-            }
-            final Installer installer = new Installer(connection);
-            installer.run();
-        } catch (IOException | SQLException e) {
-            /*
-             * Derby sometime wraps SQLException into another SQLException.  
For making the stack strace a
-             * little bit simpler, keep only the root cause provided that the 
exception type is compatible.
-             */
-            throw new MetadataStoreException(e.getLocalizedMessage(), 
Exceptions.unwrap(e));
+    final synchronized void install() throws IOException, SQLException {
+        final Connection connection = connection();
+        final DatabaseMetaData md = connection.getMetaData();
+        if (md.storesUpperCaseIdentifiers()) {
+            schema = schema.toUpperCase(Locale.US);
+        } else if (md.storesLowerCaseIdentifiers()) {
+            schema = schema.toLowerCase(Locale.US);
+        }
+        quoteSchema = false;
+        try (ResultSet result = md.getTables(catalog, schema, "CI_Citation", 
null)) {
+            if (result.next()) {
+                return;
+            }
         }
+        final Installer installer = new Installer(connection);
+        installer.run();
     }
 
     /**
@@ -839,7 +874,7 @@ public class MetadataSource implements A
                 final Class<?> subType = subType(type, identifier);
                 final Dispatcher toSearch = new Dispatcher(identifier, this);
                 try {
-                    value = subType.newInstance();
+                    value = subType.getConstructor().newInstance();
                     final LookupInfo info            = getLookupInfo(subType);
                     final Map<String,Object> map     = asValueMap(value);
                     final Map<String,String> methods = 
standard.asNameMap(subType, NAME_POLICY, KeyNamePolicy.METHOD_NAME);
@@ -984,7 +1019,7 @@ public class MetadataSource implements A
      * message when the actual class is unknown (it must have been checked 
dynamically by the caller however).
      */
     @SuppressWarnings("unchecked")
-    private static ControlledVocabulary getCodeList(final Class<?> type, final 
String name) {
+    static ControlledVocabulary getCodeList(final Class<?> type, final String 
name) {
         if (type.isEnum()) {
             return (ControlledVocabulary) 
Types.forEnumName(type.asSubclass(Enum.class), name);
         } else {

Modified: sis/branches/JDK8/core/sis-referencing-by-identifiers/pom.xml
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing-by-identifiers/pom.xml?rev=1832046&r1=1832045&r2=1832046&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing-by-identifiers/pom.xml (original)
+++ sis/branches/JDK8/core/sis-referencing-by-identifiers/pom.xml Tue May 22 
16:35:40 2018
@@ -135,6 +135,11 @@
       <type>test-jar</type>
       <scope>test</scope>
     </dependency>
+    <!-- dependency>
+      <groupId>org.apache.derby</groupId>
+      <artifactId>derby</artifactId>
+      <scope>test</scope>
+    </dependency -->
   </dependencies>
 
 </project>

Modified: 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGFactory.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGFactory.java?rev=1832046&r1=1832045&r2=1832046&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGFactory.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGFactory.java
 [UTF-8] Tue May 22 16:35:40 2018
@@ -268,7 +268,7 @@ public class EPSGFactory extends Concurr
         if (ds == null) try {
             ds = Initializer.getDataSource();
             if (ds == null) {
-                throw new 
UnavailableFactoryException(Initializer.unspecified(locale));
+                throw new 
UnavailableFactoryException(String.valueOf(Initializer.unspecified(locale, 
false)));
             }
         } catch (Exception e) {
             throw new UnavailableFactoryException(canNotUse(e), e);

Modified: 
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/report/CoordinateReferenceSystems.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/report/CoordinateReferenceSystems.java?rev=1832046&r1=1832045&r2=1832046&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/report/CoordinateReferenceSystems.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/report/CoordinateReferenceSystems.java
 [UTF-8] Tue May 22 16:35:40 2018
@@ -74,7 +74,7 @@ import static org.junit.Assert.*;
  * after any upgrade of the EPSG dataset.</p>
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 0.7
+ * @version 1.0
  * @since   0.7
  * @module
  */
@@ -480,7 +480,7 @@ public final strictfp class CoordinateRe
         properties.setProperty("PRODUCT.URL",     "http://sis.apache.org";);
         properties.setProperty("JAVADOC.GEOAPI",  
"http://www.geoapi.org/snapshot/javadoc";);
         properties.setProperty("FACTORY.NAME",    "EPSG");
-        properties.setProperty("FACTORY.VERSION", "9.1");
+        properties.setProperty("FACTORY.VERSION", "9.3");
         properties.setProperty("FACTORY.VERSION.SUFFIX", ", together with 
other sources");
         properties.setProperty("PRODUCT.VERSION.SUFFIX", " (provided that <a 
href=\"http://sis.apache.org/epsg.html\";>a connection to an EPSG database 
exists</a>)");
         properties.setProperty("DESCRIPTION", "<p><b>Notation:</b></p>\n" +


Reply via email to