X-Git-Url: https://git.argeo.org/?a=blobdiff_plain;f=org.argeo.cms%2Fsrc%2Forg%2Fargeo%2Fcms%2Finternal%2Fkernel%2FNodeLogger.java;h=133d82496f67258e21fc13fffa0a3f8f01008cc1;hb=802787847c3e36689f0a6c1a134724d1360c5802;hp=14d88144d1053df6b360dfa4d791f95cd7575998;hpb=a2ad417ed1d0219ac29d70ae985939764c13ce38;p=lgpl%2Fargeo-commons.git diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeLogger.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeLogger.java index 14d88144d..133d82496 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeLogger.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeLogger.java @@ -15,6 +15,15 @@ */ package org.argeo.cms.internal.kernel; +import java.io.IOException; +import java.net.URI; +import java.nio.file.FileSystems; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardWatchEventKinds; +import java.nio.file.WatchEvent; +import java.nio.file.WatchKey; +import java.nio.file.WatchService; import java.security.SignatureException; import java.util.ArrayList; import java.util.Collections; @@ -43,6 +52,7 @@ import org.argeo.node.ArgeoLogListener; import org.argeo.node.ArgeoLogger; import org.argeo.node.NodeConstants; import org.argeo.osgi.useradmin.UserAdminConf; +import org.osgi.framework.Bundle; import org.osgi.framework.Constants; import org.osgi.framework.ServiceReference; import org.osgi.service.cm.ConfigurationAdmin; @@ -53,6 +63,10 @@ import org.osgi.service.log.LogService; /** Not meant to be used directly in standard log4j config */ class NodeLogger implements ArgeoLogger, LogListener { + /** Internal debug for development purposes. */ + private static Boolean debug = false; + + // private final static Log log = LogFactory.getLog(NodeLogger.class); private Boolean disabled = false; @@ -92,6 +106,28 @@ class NodeLogger implements ArgeoLogger, LogListener { while (logEntries.hasMoreElements()) logged(logEntries.nextElement()); lrs.addLogListener(this); + + // configure log4j watcher + String log4jConfiguration = KernelUtils.getFrameworkProp("log4j.configuration"); + if (log4jConfiguration != null && log4jConfiguration.startsWith("file:")) { + if (log4jConfiguration.contains("..")) { + if (log4jConfiguration.startsWith("file://")) + log4jConfiguration = log4jConfiguration.substring("file://".length()); + else if (log4jConfiguration.startsWith("file:")) + log4jConfiguration = log4jConfiguration.substring("file:".length()); + } + try { + Path log4jconfigPath; + if (log4jConfiguration.startsWith("file:")) + log4jconfigPath = Paths.get(new URI(log4jConfiguration)); + else + log4jconfigPath = Paths.get(log4jConfiguration); + Thread log4jConfWatcher = new Log4jConfWatcherThread(log4jconfigPath); + log4jConfWatcher.start(); + } catch (Exception e) { + stdErr("Badly formatted log4j configuration URI " + log4jConfiguration + ": " + e.getMessage()); + } + } } public void init() { @@ -129,6 +165,10 @@ class NodeLogger implements ArgeoLogger, LogListener { // this.layout = layout; // } + public String toString() { + return "Node Logger"; + } + // // OSGi LOGGER // @@ -140,7 +180,8 @@ class NodeLogger implements ArgeoLogger, LogListener { // FIXME Fix Argeo TP if (status.getException() instanceof SignatureException) return; - pluginLog.error(msg(status), status.getException()); + // pluginLog.error(msg(status), status.getException()); + pluginLog.error(msg(status)); } else if (severity == LogService.LOG_WARNING) pluginLog.warn(msg(status), status.getException()); else if (severity == LogService.LOG_INFO && pluginLog.isDebugEnabled()) @@ -152,52 +193,78 @@ class NodeLogger implements ArgeoLogger, LogListener { private String msg(LogEntry status) { StringBuilder sb = new StringBuilder(); sb.append(status.getMessage()); + Bundle bundle = status.getBundle(); + if (bundle != null) { + sb.append(" '" + bundle.getSymbolicName() + "'"); + } ServiceReference sr = status.getServiceReference(); if (sr != null) { sb.append(' '); String[] objectClasses = (String[]) sr.getProperty(Constants.OBJECTCLASS); - sb.append(arrayToString(objectClasses)); + if (isSpringApplicationContext(objectClasses)) { + sb.append("{org.springframework.context.ApplicationContext}"); + Object symbolicName = sr.getProperty(Constants.BUNDLE_SYMBOLICNAME); + if (symbolicName != null) + sb.append(" " + Constants.BUNDLE_SYMBOLICNAME + ": " + symbolicName); + } else { + sb.append(arrayToString(objectClasses)); + } Object cn = sr.getProperty(NodeConstants.CN); if (cn != null) sb.append(" " + NodeConstants.CN + ": " + cn); Object factoryPid = sr.getProperty(ConfigurationAdmin.SERVICE_FACTORYPID); if (factoryPid != null) sb.append(" " + ConfigurationAdmin.SERVICE_FACTORYPID + ": " + factoryPid); -// else { -// Object servicePid = sr.getProperty(Constants.SERVICE_PID); -// if (servicePid != null) -// sb.append(" " + Constants.SERVICE_PID + ": " + servicePid); -// } + // else { + // Object servicePid = sr.getProperty(Constants.SERVICE_PID); + // if (servicePid != null) + // sb.append(" " + Constants.SERVICE_PID + ": " + servicePid); + // } // servlets Object whiteBoardPattern = sr.getProperty(KernelConstants.WHITEBOARD_PATTERN_PROP); - if (whiteBoardPattern != null) - sb.append(" " + KernelConstants.WHITEBOARD_PATTERN_PROP + ": " - + arrayToString((String[]) whiteBoardPattern)); + if (whiteBoardPattern != null) { + if (whiteBoardPattern instanceof String) { + sb.append(" " + KernelConstants.WHITEBOARD_PATTERN_PROP + ": " + whiteBoardPattern); + } else { + sb.append(" " + KernelConstants.WHITEBOARD_PATTERN_PROP + ": " + + arrayToString((String[]) whiteBoardPattern)); + } + } // RWT Object contextName = sr.getProperty(KernelConstants.CONTEXT_NAME_PROP); if (contextName != null) sb.append(" " + KernelConstants.CONTEXT_NAME_PROP + ": " + contextName); - + // user directories Object baseDn = sr.getProperty(UserAdminConf.baseDn.name()); if (baseDn != null) sb.append(" " + UserAdminConf.baseDn.name() + ": " + baseDn); + } return sb.toString(); } private String arrayToString(Object[] arr) { StringBuilder sb = new StringBuilder(); - sb.append('{'); + sb.append('['); for (int i = 0; i < arr.length; i++) { if (i != 0) sb.append(','); sb.append(arr[i]); } - sb.append('}'); + sb.append(']'); return sb.toString(); } + private boolean isSpringApplicationContext(String[] objectClasses) { + for (String clss : objectClasses) { + if (clss.equals("org.eclipse.gemini.blueprint.context.DelegatedExecutionOsgiBundleApplicationContext")) { + return true; + } + } + return false; + } + // // ARGEO LOGGER // @@ -249,10 +316,23 @@ class NodeLogger implements ArgeoLogger, LogListener { } /** For development purpose, since using regular logging is not easy here */ - static void stdOut(Object obj) { + private static void stdOut(Object obj) { System.out.println(obj); } + private static void stdErr(Object obj) { + System.err.println(obj); + } + + private static void debug(Object obj) { + if (debug) + System.out.println(obj); + } + + private static boolean isInternalDebugEnabled() { + return debug; + } + // public void setPattern(String pattern) { // this.pattern = pattern; // } @@ -437,4 +517,43 @@ class NodeLogger implements ArgeoLogger, LogListener { } } + + private class Log4jConfWatcherThread extends Thread { + private Path log4jConfigurationPath; + + public Log4jConfWatcherThread(Path log4jConfigurationPath) { + super("Log4j Configuration Watcher"); + try { + this.log4jConfigurationPath = log4jConfigurationPath.toRealPath(); + } catch (IOException e) { + this.log4jConfigurationPath = log4jConfigurationPath.toAbsolutePath(); + stdOut("Cannot determine real path for " + log4jConfigurationPath + ": " + e.getMessage()); + } + } + + public void run() { + Path parentDir = log4jConfigurationPath.getParent(); + try (final WatchService watchService = FileSystems.getDefault().newWatchService()) { + parentDir.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY); + WatchKey wk; + watching: while ((wk = watchService.take()) != null) { + for (WatchEvent event : wk.pollEvents()) { + final Path changed = (Path) event.context(); + if (log4jConfigurationPath.equals(parentDir.resolve(changed))) { + if (isInternalDebugEnabled()) + debug(log4jConfigurationPath + " has changed, reloading."); + PropertyConfigurator.configure(log4jConfigurationPath.toUri().toURL()); + } + } + // reset the key + boolean valid = wk.reset(); + if (!valid) { + break watching; + } + } + } catch (IOException | InterruptedException e) { + stdErr("Log4j configuration watcher failed: " + e.getMessage()); + } + } + } }