This is an automated email from the ASF dual-hosted git repository.

desruisseaux pushed a commit to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git

commit 69fdbb413c721ea88e843bc3c8695d5845d234ef
Author: Martin Desruisseaux <martin.desruisse...@geomatys.com>
AuthorDate: Wed Jan 12 01:08:00 2022 +0100

    Remove the `QuietLogRecord` package-private class, replaced by the use of a 
`java.util.logging.Filter`.
    It allows us to get the same functionality from other packages (in this 
commit, netCDF).
---
 .../apache/sis/util/resources/KeyConstants.java    |  2 +-
 .../apache/sis/internal/netcdf/NamedElement.java   |  6 +-
 .../sis/internal/storage/AbstractResource.java     | 19 ++++++
 .../apache/sis/storage/event/QuietLogRecord.java   | 70 ----------------------
 .../apache/sis/storage/event/StoreListeners.java   | 59 +++++++++++-------
 .../org/apache/sis/storage/event/package-info.java |  3 +-
 6 files changed, 61 insertions(+), 98 deletions(-)

diff --git 
a/core/sis-utility/src/main/java/org/apache/sis/util/resources/KeyConstants.java
 
b/core/sis-utility/src/main/java/org/apache/sis/util/resources/KeyConstants.java
index 8c7d199..4f46302 100644
--- 
a/core/sis-utility/src/main/java/org/apache/sis/util/resources/KeyConstants.java
+++ 
b/core/sis-utility/src/main/java/org/apache/sis/util/resources/KeyConstants.java
@@ -102,7 +102,7 @@ public class KeyConstants {
 
     /**
      * Returns the name of the key at the given index. If there is no name at 
that given
-     * index, format the index as a decimal number. Those decimal numbers are 
parsed by
+     * index, formats the index as a decimal number. Those decimal numbers are 
parsed by
      * our {@link IndexedResourceBundle#handleGetObject(String)} 
implementation.
      */
     final String getKeyName(final short index) {
diff --git 
a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/NamedElement.java
 
b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/NamedElement.java
index 2a0c9cb..a6f1e52 100644
--- 
a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/NamedElement.java
+++ 
b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/NamedElement.java
@@ -23,6 +23,7 @@ import org.apache.sis.util.Characters;
 import org.apache.sis.util.CharSequences;
 import org.apache.sis.internal.system.Modules;
 import org.apache.sis.internal.util.Strings;
+import org.apache.sis.internal.storage.AbstractResource;
 import org.apache.sis.storage.event.StoreListeners;
 import org.apache.sis.util.resources.IndexedResourceBundle;
 
@@ -32,7 +33,7 @@ import org.apache.sis.util.resources.IndexedResourceBundle;
  * All those objects share in common a {@link #getName()} method.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.0
+ * @version 1.2
  * @since   0.8
  * @module
  */
@@ -113,10 +114,9 @@ public abstract class NamedElement {
         record.setSourceClassName(caller.getCanonicalName());
         record.setSourceMethodName(method);
         if (exception != null) {
-            // TODO: avoid reporting the full exception stack trace (maybe 
leverage QuietLogRecord).
             record.setThrown(exception);
         }
-        listeners.warning(record);
+        listeners.warning(record, AbstractResource.removeStackTraceInLogs());
     }
 
     /**
diff --git 
a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/AbstractResource.java
 
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/AbstractResource.java
index d38b603..8888341 100644
--- 
a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/AbstractResource.java
+++ 
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/AbstractResource.java
@@ -18,6 +18,8 @@ package org.apache.sis.internal.storage;
 
 import java.util.Locale;
 import java.util.Optional;
+import java.util.logging.Filter;
+import java.util.logging.LogRecord;
 import org.opengis.util.GenericName;
 import org.opengis.util.InternationalString;
 import org.opengis.metadata.Metadata;
@@ -215,4 +217,21 @@ public class AbstractResource extends StoreListeners 
implements Resource {
             super.addListener(eventType, listener);
         }
     }
+
+    /**
+     * Returns a log filter that removes the stack trace of filtered given log.
+     * It can be used as argument in a call to {@link 
StoreListeners#warning(LogRecord, Filter)}
+     * if the caller was to trim the stack trace in log files or console 
outputs.
+     *
+     * <p>This filter should be used only for filtering {@link LogRecord} 
created by the caller, because
+     * it modifies the record. Users would not expect this side effect on 
records created by them.</p>
+     *
+     * @return a filter for trimming stack trace.
+     */
+    public static Filter removeStackTraceInLogs() {
+        return (record) -> {
+            record.setThrown(null);
+            return true;
+        };
+    }
 }
diff --git 
a/storage/sis-storage/src/main/java/org/apache/sis/storage/event/QuietLogRecord.java
 
b/storage/sis-storage/src/main/java/org/apache/sis/storage/event/QuietLogRecord.java
deleted file mode 100644
index 06a3496..0000000
--- 
a/storage/sis-storage/src/main/java/org/apache/sis/storage/event/QuietLogRecord.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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.storage.event;
-
-import java.util.logging.Level;
-import java.util.logging.LogRecord;
-
-
-/**
- * A log record to be logged without stack trace, unless the user specified it 
explicitly.
- *
- * @author  Martin Desruisseaux (Geomatys)
- * @version 1.0
- * @since   0.3
- * @module
- */
-final class QuietLogRecord extends LogRecord {
-    /**
-     * For cross-version compatibility.
-     */
-    private static final long serialVersionUID = 5652099235767670922L;
-
-    /**
-     * {@code true} if the user invoked {@link #setThrown(Throwable)} 
explicitly.
-     * In such case, {@link #clearImplicitThrown()} will not reset the 
throwable to null.
-     */
-    private boolean explicitThrown;
-
-    /**
-     * Creates a new log record for the given message and exception.
-     */
-    QuietLogRecord(final Level level, final String message, final Exception 
exception) {
-        super(level, message);
-        super.setThrown(exception);
-    }
-
-    /**
-     * Sets the throwable to the given value. The given throwable will not be 
cleared
-     * when the record will be logged.
-     */
-    @Override
-    public void setThrown(final Throwable thrown) {
-        explicitThrown = true;
-        super.setThrown(thrown);
-    }
-
-    /**
-     * Clears the throwable if it has not been explicitly set by the user.
-     * Otherwise do nothing.
-     */
-    void clearImplicitThrown() {
-        if (!explicitThrown) {
-            super.setThrown(null);
-        }
-    }
-}
diff --git 
a/storage/sis-storage/src/main/java/org/apache/sis/storage/event/StoreListeners.java
 
b/storage/sis-storage/src/main/java/org/apache/sis/storage/event/StoreListeners.java
index 8943dc6..e790510 100644
--- 
a/storage/sis-storage/src/main/java/org/apache/sis/storage/event/StoreListeners.java
+++ 
b/storage/sis-storage/src/main/java/org/apache/sis/storage/event/StoreListeners.java
@@ -22,6 +22,7 @@ import java.util.IdentityHashMap;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 import java.util.logging.LogRecord;
+import java.util.logging.Filter;
 import java.lang.reflect.Method;
 import org.apache.sis.util.ArraysExt;
 import org.apache.sis.util.Localized;
@@ -49,8 +50,8 @@ import org.apache.sis.storage.Resource;
  * and additional information like {@linkplain LogRecord#getThrown() stack 
trace}, timestamp, <i>etc.</i>).
  * This {@code StoreListeners} class provides convenience methods like {@link 
#warning(String, Exception)},
  * which build {@code LogRecord} from an exception or from a string. But all 
those {@code warning(…)} methods
- * ultimately delegate to {@link #warning(LogRecord)}, thus providing a single 
point that subclasses can override.
- * When a warning is emitted, the default behavior is:
+ * ultimately delegate to {@link #warning(LogRecord, Filter)}, thus providing 
a single point that subclasses
+ * can override. When a warning is emitted, the default behavior is:
  *
  * <ul>
  *   <li>Notify all listeners that are registered for a given {@link 
WarningEvent} type in this {@code StoreListeners}
@@ -73,7 +74,7 @@ import org.apache.sis.storage.Resource;
  * from multiple threads.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.1
+ * @version 1.2
  * @since   1.0
  * @module
  */
@@ -397,16 +398,11 @@ public class StoreListeners implements Localized {
      * If both are non-null, then the exception message will be concatenated 
after the given message.
      *
      * <h4>Stack trace omission</h4>
-     * If there is no registered listener for the {@link WarningEvent} type, 
then the {@link #warning(LogRecord)}
-     * method will send the record to a logger but <em>without</em> the stack 
trace.
+     * If there is no registered listener for the {@link WarningEvent} type,
+     * then the {@link LogRecord} will be sent to a {@link Logger} but 
<em>without</em> the stack trace.
      * This is done that way because stack traces consume lot of space in the 
logging files, while being considered
      * implementation details in the context of {@code StoreListeners} (on the 
assumption that the logging message
-     * provides sufficient information). If the stack trace is desired, then 
users can either:
-     * <ul>
-     *   <li>invoke {@code warning(LogRecord)} directly, or</li>
-     *   <li>override {@code warning(LogRecord)} and invoke {@link 
LogRecord#setThrown(Throwable)} explicitly, or</li>
-     *   <li>register a listener which will log the record itself.</li>
-     * </ul>
+     * provides sufficient information).
      *
      * @param  level      the warning level.
      * @param  message    the message to log, or {@code null} if none.
@@ -422,7 +418,8 @@ public class StoreListeners implements Localized {
             if (message == null) {
                 message = exception.toString();
             }
-            record = new QuietLogRecord(level, message, exception);
+            record = new LogRecord(level, message);
+            record.setThrown(exception);
         } else {
             ArgumentChecks.ensureNonEmpty("message", message);
             trace = Thread.currentThread().getStackTrace();         // TODO: 
on JDK9, use StackWalker instead.
@@ -437,7 +434,7 @@ public class StoreListeners implements Localized {
         } catch (ClassNotFoundException | SecurityException e) {
             Logging.ignorableException(StoreUtilities.LOGGER, 
StoreListeners.class, "warning", e);
         }
-        warning(record);
+        warning(record, AbstractResource.removeStackTraceInLogs());
     }
 
     /**
@@ -464,28 +461,47 @@ public class StoreListeners implements Localized {
     }
 
     /**
+     * Reports a warning described by the given log record. Invoking this 
method is
+     * equivalent to invoking {@link #warning(LogRecord, Filter)} with a null 
filter.
+     *
+     * @param  description  warning details provided as a log record.
+     */
+    public void warning(final LogRecord description) {
+        warning(description, null);
+    }
+
+    /**
      * Reports a warning described by the given log record. The default 
implementation forwards
      * the given record to one of the following destinations, in preference 
order:
      *
-     * <ul>
+     * <ol>
      *   <li><code>{@linkplain StoreListener#eventOccured 
StoreListener.eventOccured}(new
      *       {@linkplain WarningEvent}(source, record))</code> on all 
listeners registered for this kind of event.</li>
-     *   <li>Only if above step found no listener, then <code>{@linkplain 
Logging#getLogger(String)
-     *       Logging.getLogger}(record.loggerName).{@linkplain 
Logger#log(LogRecord) log}(record)</code>
-     *       where {@code loggerName} is one of the following:
+     *   <li><code>{@linkplain Filter#isLoggable(LogRecord) 
onUnhandled.isLoggable(description)}</code>
+     *       if above step found no listener and the {@code onUnhandled} 
filter is non-null.</li>
+     *   <li><code>{@linkplain Logger#getLogger(String)
+     *       Logger.getLogger}(record.loggerName).{@linkplain 
Logger#log(LogRecord) log}(record)</code>
+     *       if the filter in above step returned {@code true} (or if the 
filter is null).
+     *       In that case, {@code loggerName} is one of the following:
      *     <ul>
      *       <li><code>record.{@linkplain LogRecord#getLoggerName() 
getLoggerName()}</code> if that value is non-null.</li>
      *       <li>Otherwise the value of {@link DataStoreProvider#getLogger()} 
if the provider is found.</li>
      *       <li>Otherwise the source {@link DataStore} package name.</li>
      *     </ul>
      *   </li>
-     * </ul>
+     * </ol>
      *
      * @param  description  warning details provided as a log record.
+     * @param  onUnhandled  filter invoked if the record has not been handled 
by a {@link StoreListener},
+     *                      or {@code null} if none.
+     *
+     * @since 1.2
      */
     @SuppressWarnings("unchecked")
-    public void warning(final LogRecord description) {
-        if (!fire(new WarningEvent(source, description), WarningEvent.class)) {
+    public void warning(final LogRecord description, final Filter onUnhandled) 
{
+        if (!fire(new WarningEvent(source, description), WarningEvent.class) &&
+                (onUnhandled == null || onUnhandled.isLoggable(description)))
+        {
             final String name = description.getLoggerName();
             final Logger logger;
             if (name != null) {
@@ -494,9 +510,6 @@ public class StoreListeners implements Localized {
                 logger = getLogger();
                 description.setLoggerName(logger.getName());
             }
-            if (description instanceof QuietLogRecord) {
-                ((QuietLogRecord) description).clearImplicitThrown();
-            }
             logger.log(description);
         }
     }
diff --git 
a/storage/sis-storage/src/main/java/org/apache/sis/storage/event/package-info.java
 
b/storage/sis-storage/src/main/java/org/apache/sis/storage/event/package-info.java
index c9a46b7..f8a7aaa 100644
--- 
a/storage/sis-storage/src/main/java/org/apache/sis/storage/event/package-info.java
+++ 
b/storage/sis-storage/src/main/java/org/apache/sis/storage/event/package-info.java
@@ -34,7 +34,8 @@
  * to a specific kind of event}.
  *
  * @author  Johann Sorel (Geomatys)
- * @since   1.1
+ * @author  Martin Desruisseaux (Geomatys)
+ * @since   1.2
  * @version 1.0
  * @module
  */

Reply via email to