Fall back to java.util.logging in a pure OSGi environment
authorMathieu Baudier <mbaudier@argeo.org>
Thu, 30 Dec 2021 07:59:31 +0000 (08:59 +0100)
committerMathieu Baudier <mbaudier@argeo.org>
Thu, 30 Dec 2021 07:59:31 +0000 (08:59 +0100)
demo/argeo-init.properties [new file with mode: 0644]
demo/argeo_node_osgiboot.properties [deleted file]
demo/cms-e4-rap.properties
demo/logging.properties [new file with mode: 0644]
org.argeo.init/bnd.bnd
org.argeo.init/src/org/argeo/init/logging/ThinHandler.java [new file with mode: 0644]
org.argeo.init/src/org/argeo/init/logging/ThinJavaUtilLogging.java [new file with mode: 0644]
org.argeo.init/src/org/argeo/init/logging/ThinLoggerFinder.java
org.argeo.init/src/org/argeo/init/logging/ThinLogging.java
org.argeo.init/src/org/argeo/init/osgi/Activator.java

diff --git a/demo/argeo-init.properties b/demo/argeo-init.properties
new file mode 100644 (file)
index 0000000..08df826
--- /dev/null
@@ -0,0 +1,24 @@
+#argeo.osgi.baseUrl=http://forge.argeo.org/data/java/argeo-2.1/
+#argeo.osgi.distributionUrl=org/argeo/commons/org.argeo.dep.cms.sdk/2.1.65/org.argeo.dep.cms.sdk-2.1.65.jar
+#argeo.osgi.distributionUrl=org/argeo/commons/org.argeo.dep.cms.sdk/2.1.67/org.argeo.dep.cms.sdk-2.1.67.jar
+#argeo.osgi.distributionUrl=org/argeo/commons/org.argeo.dep.cms.sdk/2.1.68-SNAPSHOT/org.argeo.dep.cms.sdk-2.1.68-SNAPSHOT.jar
+
+#argeo.osgi.boot.debug=true
+
+argeo.osgi.start.1.osgiboot=org.argeo.init
+#argeo.osgi.start.2.node=org.eclipse.equinox.http.servlet,org.eclipse.equinox.http.jetty,org.eclipse.equinox.cm,org.eclipse.rap.rwt.osgi
+#argeo.osgi.start.3.node=org.argeo.cms,org.eclipse.gemini.blueprint.extender,org.eclipse.equinox.http.registry
+
+#java.security.manager=
+#java.security.policy=file:../../all.policy
+
+argeo.node.repo.type=localfs
+org.osgi.service.http.port=7070
+log4j.configuration=file:../../log4j.properties
+
+#java.util.logging.config.file=../../logging.properties
+
+
+# DON'T CHANGE BELOW
+org.eclipse.rap.workbenchAutostart=false
+org.eclipse.equinox.http.jetty.autostart=false
\ No newline at end of file
diff --git a/demo/argeo_node_osgiboot.properties b/demo/argeo_node_osgiboot.properties
deleted file mode 100644 (file)
index 2a8c351..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-#argeo.osgi.baseUrl=http://forge.argeo.org/data/java/argeo-2.1/
-#argeo.osgi.distributionUrl=org/argeo/commons/org.argeo.dep.cms.sdk/2.1.65/org.argeo.dep.cms.sdk-2.1.65.jar
-#argeo.osgi.distributionUrl=org/argeo/commons/org.argeo.dep.cms.sdk/2.1.67/org.argeo.dep.cms.sdk-2.1.67.jar
-#argeo.osgi.distributionUrl=org/argeo/commons/org.argeo.dep.cms.sdk/2.1.68-SNAPSHOT/org.argeo.dep.cms.sdk-2.1.68-SNAPSHOT.jar
-
-#argeo.osgi.boot.debug=true
-
-argeo.osgi.start.1.osgiboot=org.argeo.osgi.boot
-#argeo.osgi.start.2.node=org.eclipse.equinox.http.servlet,org.eclipse.equinox.http.jetty,org.eclipse.equinox.cm,org.eclipse.rap.rwt.osgi
-#argeo.osgi.start.3.node=org.argeo.cms,org.eclipse.gemini.blueprint.extender,org.eclipse.equinox.http.registry
-
-#java.security.manager=
-#java.security.policy=file:../../all.policy
-
-argeo.node.repo.type=localfs
-org.osgi.service.http.port=7070
-log4j.configuration=file:../../log4j.properties
-
-# DON'T CHANGE BELOW
-org.eclipse.rap.workbenchAutostart=false
-org.eclipse.equinox.http.jetty.autostart=false
\ No newline at end of file
index feeab07481e4c20f179f27c08cbcf609b716bae8..5e1e6545d5f6adfc644611e91a3ed4ea58130ede 100644 (file)
@@ -3,7 +3,8 @@ org.eclipse.equinox.http.servlet,\
 org.eclipse.equinox.metatype,\
 org.eclipse.equinox.cm,\
 org.eclipse.equinox.ds,\
-org.eclipse.rap.rwt.osgi
+org.eclipse.rap.rwt.osgi,\
+org.argeo.init
 
 argeo.osgi.start.3.node=\
 org.argeo.cms
diff --git a/demo/logging.properties b/demo/logging.properties
new file mode 100644 (file)
index 0000000..bf86d09
--- /dev/null
@@ -0,0 +1,65 @@
+############################################################
+#      Default Logging Configuration File
+#
+# You can use a different file by specifying a filename
+# with the java.util.logging.config.file system property.  
+# For example java -Djava.util.logging.config.file=myfile
+############################################################
+
+############################################################
+#      Global properties
+############################################################
+
+# "handlers" specifies a comma separated list of log Handler 
+# classes.  These handlers will be installed during VM startup.
+# Note that these classes must be on the system classpath.
+# By default we only configure a ConsoleHandler, which will only
+# show messages at the INFO and above levels.
+#handlers= java.util.logging.ConsoleHandler
+#handlers=org.argeo.init.logging.jse.ThinHandler
+handlers=
+
+# To also add the FileHandler, use the following line instead.
+#handlers= java.util.logging.FileHandler, java.util.logging.ConsoleHandler
+
+# Default global logging level.
+# This specifies which kinds of events are logged across
+# all loggers.  For any given facility this global level
+# can be overriden by a facility specific level
+# Note that the ConsoleHandler also has a separate level
+# setting to limit messages printed to the console.
+.level= INFO
+
+############################################################
+# Handler specific properties.
+# Describes specific configuration info for Handlers.
+############################################################
+
+# default file output is in user's home directory.
+java.util.logging.FileHandler.pattern = %h/java%u.log
+java.util.logging.FileHandler.limit = 50000
+java.util.logging.FileHandler.count = 1
+# Default number of locks FileHandler can obtain synchronously.
+# This specifies maximum number of attempts to obtain lock file by FileHandler
+# implemented by incrementing the unique field %u as per FileHandler API documentation.
+java.util.logging.FileHandler.maxLocks = 100
+java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter
+
+# Limit the message that are printed on the console to INFO and above.
+java.util.logging.ConsoleHandler.level = INFO
+java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
+
+# Example to customize the SimpleFormatter output format 
+# to print one-line log message like this:
+#     <level>: <log message> [<date/time>]
+#
+# java.util.logging.SimpleFormatter.format=%4$s: %5$s [%1$tc]%n
+
+############################################################
+# Facility specific properties.
+# Provides extra control for each logger.
+############################################################
+
+# For example, set the com.xyz.foo logger to only log SEVERE
+# messages:
+com.xyz.foo.level = SEVERE
index f421512735647dc81d08ba6d3c3808c384878400..734c77440d65f76a6fa82e6b09e061e3fc5c3777 100644 (file)
@@ -3,6 +3,8 @@ Class-Path: org.eclipse.osgi.jar
 
 Bundle-Activator: org.argeo.init.osgi.Activator
 
-Import-Package: org.osgi.*;version=0.0.0
+Import-Package: \
+org.osgi.*;version=0.0.0,\
+java.util.logging.*;resolution:=optional
 Private-Package: *
 Export-Package: !*
diff --git a/org.argeo.init/src/org/argeo/init/logging/ThinHandler.java b/org.argeo.init/src/org/argeo/init/logging/ThinHandler.java
new file mode 100644 (file)
index 0000000..e6f4c62
--- /dev/null
@@ -0,0 +1,45 @@
+package org.argeo.init.logging;
+
+import java.lang.System.Logger.Level;
+import java.util.logging.Handler;
+import java.util.logging.LogRecord;
+
+/**
+ * A fallback {@link Handler} forwarding only messages and logger name (all
+ * other {@link LogRecord} information is lost.
+ */
+class ThinHandler extends Handler {
+       @Override
+       public void publish(LogRecord record) {
+               java.lang.System.Logger systemLogger = ThinLoggerFinder.getLogger(record.getLoggerName());
+               systemLogger.log(fromJulLevel(record.getLevel()), record.getMessage());
+       }
+
+       protected Level fromJulLevel(java.util.logging.Level julLevel) {
+               if (java.util.logging.Level.ALL.equals(julLevel))
+                       return Level.ALL;
+               else if (java.util.logging.Level.FINER.equals(julLevel))
+                       return Level.TRACE;
+               else if (java.util.logging.Level.FINE.equals(julLevel))
+                       return Level.DEBUG;
+               else if (java.util.logging.Level.INFO.equals(julLevel))
+                       return Level.INFO;
+               else if (java.util.logging.Level.WARNING.equals(julLevel))
+                       return Level.WARNING;
+               else if (java.util.logging.Level.SEVERE.equals(julLevel))
+                       return Level.ERROR;
+               else if (java.util.logging.Level.OFF.equals(julLevel))
+                       return Level.OFF;
+               else
+                       throw new IllegalArgumentException("Unsupported JUL level " + julLevel);
+       }
+
+       @Override
+       public void flush() {
+       }
+
+       @Override
+       public void close() throws SecurityException {
+       }
+
+}
\ No newline at end of file
diff --git a/org.argeo.init/src/org/argeo/init/logging/ThinJavaUtilLogging.java b/org.argeo.init/src/org/argeo/init/logging/ThinJavaUtilLogging.java
new file mode 100644 (file)
index 0000000..5b51d00
--- /dev/null
@@ -0,0 +1,18 @@
+package org.argeo.init.logging;
+
+import java.util.logging.LogManager;
+import java.util.logging.Logger;
+
+/**
+ * Fallback wrapper around the java.util.logging framework, when thinb logging
+ * could not be instantiated directly.
+ */
+class ThinJavaUtilLogging {
+       public static void init() {
+               LogManager logManager = LogManager.getLogManager();
+               logManager.reset();
+               Logger rootLogger = logManager.getLogger("");
+               rootLogger.addHandler(new ThinHandler());
+               rootLogger.setLevel(java.util.logging.Level.FINE);
+       }
+}
index 7849309460933695f5b60a96d44f5e8cf2592c4c..9607c9478df78c3f5f259111a4ed7aab46ef4cee 100644 (file)
@@ -5,9 +5,11 @@ import java.lang.System.LoggerFinder;
 
 /** Factory for Java system logging. */
 public class ThinLoggerFinder extends LoggerFinder {
-       private ThinLogging logging;
+       private static ThinLogging logging;
 
        public ThinLoggerFinder() {
+               if (logging != null)
+                       throw new IllegalStateException("Only one logging can be initialised.");
                logging = new ThinLogging();
        }
 
@@ -16,4 +18,17 @@ public class ThinLoggerFinder extends LoggerFinder {
                return logging.getLogger(name, module);
        }
 
+       /**
+        * Falls back to java.util.logging if thin logging was not already initialised.
+        */
+       public static void lazyInit() {
+               if (logging != null)
+                       return;
+               logging = new ThinLogging();
+               ThinJavaUtilLogging.init();
+       }
+
+       public static Logger getLogger(String name) {
+               return logging.getLogger(name, null);
+       }
 }
index e7edc19a89e9858b9a7ee0d1ba9eb0e21f97f45c..44baa691993bd3252620a7acad1e978b3512a9e7 100644 (file)
@@ -22,8 +22,6 @@ import java.util.concurrent.TimeUnit;
 
 /** A thin logging system based on the {@link Logger} framework. */
 class ThinLogging {
-//     private static ThinLogging instance;
-
        private SortedMap<String, ThinLogger> loggers = new TreeMap<>();
        private NavigableMap<String, Level> levels = new TreeMap<>();
 
@@ -31,10 +29,6 @@ class ThinLogging {
        private final LogEntryPublisher publisher;
 
        ThinLogging() {
-//             if (instance != null)
-//                     throw new IllegalStateException("Only one logger finder cann be instantiated");
-//             instance = this;
-
                executor = Executors.newCachedThreadPool((r) -> {
                        Thread t = new Thread(r);
                        t.setDaemon(true);
@@ -46,6 +40,8 @@ class ThinLogging {
                publisher.subscribe(subscriber);
 
                Runtime.getRuntime().addShutdownHook(new Thread(() -> close(), "Log shutdown"));
+
+               setDefaultLevel(Level.DEBUG);
        }
 
        protected void close() {
index 5a9527041bf01e5c99bb8cc9598d40c620a6b1ee..3e0d8e1179c251d1299ed99657c354c07030cf44 100644 (file)
@@ -1,9 +1,9 @@
 package org.argeo.init.osgi;
 
-import java.util.Enumeration;
-import java.util.ResourceBundle;
-import java.util.Vector;
+import java.lang.System.Logger;
+import java.lang.System.Logger.Level;
 
+import org.argeo.init.logging.ThinLoggerFinder;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
 
@@ -13,9 +13,17 @@ import org.osgi.framework.BundleContext;
  * //wiki.eclipse.org/Configurator</a>
  */
 public class Activator implements BundleActivator {
+       static {
+               // must be called first
+               ThinLoggerFinder.lazyInit();
+       }
+       Logger logger = System.getLogger(Activator.class.getName());
+
        private Long checkpoint = null;
 
        public void start(final BundleContext bundleContext) throws Exception {
+               logger.log(Level.DEBUG, () -> "Argeo init via OSGi activator");
+
                // admin thread
                Thread adminThread = new AdminThread(bundleContext);
                adminThread.start();
@@ -33,24 +41,4 @@ public class Activator implements BundleActivator {
 
        public void stop(BundleContext context) throws Exception {
        }
-
-       class JournaldResourceBundle extends ResourceBundle {
-
-               @Override
-               protected Object handleGetObject(String key) {
-                       switch (key) {
-                       case "ERROR":
-                               return "<5>";
-                       }
-                       return null;
-               }
-
-               @Override
-               public Enumeration<String> getKeys() {
-                       Vector<String> keys = new Vector<>();
-                       keys.add("ERROR");
-                       return keys.elements();
-               }
-
-       }
 }