Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristopher Frost2011-10-18 09:35:18 -0400
committerChristopher Frost2011-10-18 09:35:18 -0400
commit5093888c0b228cae2d0b7345824b44e70414d451 (patch)
tree52734ba69149c0a197a24111b3a8e64272221a3d
parent57b80ed4f26e4b6ff174df2ee0362fe23d623e9c (diff)
parent76d0d345b3cc28324920c0649da1d616d1dff307 (diff)
downloadorg.eclipse.virgo.medic-5093888c0b228cae2d0b7345824b44e70414d451.tar.gz
org.eclipse.virgo.medic-5093888c0b228cae2d0b7345824b44e70414d451.tar.xz
org.eclipse.virgo.medic-5093888c0b228cae2d0b7345824b44e70414d451.zip
Merge branch 'master' of ssh://git.eclipse.org/gitroot/virgo/org.eclipse.virgo.medic
Conflicts: org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/impl/MedicActivator.java
-rwxr-xr-xorg.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/impl/LogController.java322
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/impl/MedicActivator.java303
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/impl/config/ConfigurationAdminConfigurationProvider.java23
-rwxr-xr-xorg.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/impl/config/ConfigurationChangeListener.java25
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/impl/config/ConfigurationProvider.java27
-rwxr-xr-xorg.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/impl/LogControllerTests.java232
-rw-r--r--org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/impl/config/ConfigurationAdminConfigurationProviderTests.java131
-rw-r--r--org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/log/impl/LoggingPrintStreamWrapperTests.java71
8 files changed, 814 insertions, 320 deletions
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/impl/LogController.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/impl/LogController.java
new file mode 100755
index 0000000..b3e3f84
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/impl/LogController.java
@@ -0,0 +1,322 @@
+/*******************************************************************************
+ * Copyright (c) 2011 SAP AG
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hristo Iliev, SAP AG - initial contribution
+ *******************************************************************************/
+package org.eclipse.virgo.medic.impl;
+
+import org.eclipse.virgo.medic.dump.DumpGenerator;
+import org.eclipse.virgo.medic.dump.impl.DumpContributorPublisher;
+import org.eclipse.virgo.medic.dump.impl.StandardDumpContributorResolver;
+import org.eclipse.virgo.medic.dump.impl.StandardDumpGenerator;
+import org.eclipse.virgo.medic.eventlog.EventLogger;
+import org.eclipse.virgo.medic.eventlog.EventLoggerFactory;
+import org.eclipse.virgo.medic.eventlog.impl.BundleSearchingPropertyResourceBundleResolver;
+import org.eclipse.virgo.medic.eventlog.impl.EventLoggerServiceFactory;
+import org.eclipse.virgo.medic.eventlog.impl.StandardLocaleResolver;
+import org.eclipse.virgo.medic.eventlog.impl.logback.LogBackEventLoggerFactory;
+import org.eclipse.virgo.medic.impl.config.ConfigurationChangeListener;
+import org.eclipse.virgo.medic.impl.config.ConfigurationProvider;
+import org.eclipse.virgo.medic.log.ConfigurationPublicationFailedException;
+import org.eclipse.virgo.medic.log.DelegatingPrintStream;
+import org.eclipse.virgo.medic.log.LoggingConfigurationPublisher;
+import org.eclipse.virgo.medic.log.impl.*;
+import org.eclipse.virgo.medic.log.impl.config.*;
+import org.eclipse.virgo.medic.log.impl.logback.DelegatingContextSelector;
+import org.eclipse.virgo.medic.log.impl.logback.JoranLoggerContextConfigurer;
+import org.eclipse.virgo.medic.log.impl.logback.LoggerContextConfigurer;
+import org.eclipse.virgo.medic.log.impl.logback.StandardContextSelectorDelegate;
+import org.eclipse.virgo.medic.management.MedicMBeanExporter;
+import org.eclipse.virgo.util.osgi.ServiceRegistrationTracker;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleListener;
+import org.osgi.framework.ServiceFactory;
+import org.osgi.framework.ServiceRegistration;
+import org.slf4j.bridge.SLF4JBridgeHandler;
+
+import java.io.File;
+import java.io.PrintStream;
+import java.util.Arrays;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.logging.ConsoleHandler;
+import java.util.logging.Handler;
+import java.util.logging.Logger;
+
+public class LogController implements ConfigurationChangeListener {
+
+ private static final String LOGGER_NAME_SYSERR = "System.err";
+
+ private static final String LOGGER_NAME_SYSOUT = "System.out";
+
+ private static final String LOGGER_NAME_SYSERR_DELEGATE = "delegating.System.err";
+
+ private static final String LOGGER_NAME_SYSOUT_DELEGATE = "delegating.System.out";
+
+ private static final String PROPERTY_MEDIC_CONFIG_PATH = "org.eclipse.virgo.medic.log.config.path";
+
+ private static final String DEFAULT_CONTEXT_SELECTOR = "ch.qos.logback.classic.selector.DefaultContextSelector";
+
+ private static final String PROPERTY_LOGBACK_CONTEXT_SELECTOR = "logback.ContextSelector";
+
+ private volatile StandardDumpGenerator dumpGenerator;
+
+ private volatile LogBackEventLoggerFactory eventLoggerFactory;
+
+ private volatile DumpContributorPublisher dumpContributorPublisher;
+
+ private volatile PrintStream sysOut = System.out;
+
+ private volatile PrintStream sysErr = System.err;
+
+ private volatile ExecutionStackAccessor stackAccessor;
+
+ private volatile ConsoleHandler javaConsoleHandler;
+
+ private PrintStream delegatingSysOut = new StandardDelegatingPrintStream(System.out);
+
+ private PrintStream delegatingSysErr = new StandardDelegatingPrintStream(System.err);
+
+ private ServiceRegistration<?> delegatingSysOutRegistration;
+ private ServiceRegistration<?> delegatingSysErrRegistration;
+
+ private ServiceRegistration<?> sysOutRegistration;
+ private ServiceRegistration<?> sysErrRegistration;
+
+ private static final List<String> DEFAULT_LOGGING_PACKAGES = Arrays.asList(//
+ "org.apache.commons.logging",//
+ "org.apache.log4j",//
+ "org.slf4j",//
+ "org.slf4j.impl",//
+ "org.eclipse.virgo.medic.log",//
+ "org.eclipse.virgo.medic.log.impl",//
+ "org.eclipse.virgo.medic.log.impl.logback");
+
+ private BundleContext bundleContext;
+ private ConfigurationProvider configurationProvider;
+ private ServiceRegistrationTracker registrationTracker;
+
+ public LogController(BundleContext ctx, ConfigurationProvider cfgProvider, ServiceRegistrationTracker regTracker) throws ConfigurationPublicationFailedException {
+ this.bundleContext = ctx;
+ this.configurationProvider = cfgProvider;
+ this.registrationTracker = regTracker;
+
+ StandardContextSelectorDelegate delegate = createContextSelectorDelegate(bundleContext);
+ registrationTracker.track(bundleContext.registerService(BundleListener.class.getName(), delegate, null));
+ DelegatingContextSelector.setDelegate(delegate);
+
+ StandardLoggingConfigurationPublisher loggingConfigurationPublisher = new StandardLoggingConfigurationPublisher(bundleContext);
+ registrationTracker.track(bundleContext.registerService(LoggingConfigurationPublisher.class.getName(), loggingConfigurationPublisher, null));
+
+ publishDefaultConfigurationIfAvailable(bundleContext, loggingConfigurationPublisher);
+
+ System.setProperty(PROPERTY_LOGBACK_CONTEXT_SELECTOR, DelegatingContextSelector.class.getName());
+
+ this.stackAccessor = new SecurityManagerExecutionStackAccessor();
+
+ this.sysOut = System.out;
+ this.sysErr = System.err;
+ }
+
+ public DumpGenerator dumpStart() {
+ this.dumpGenerator = new StandardDumpGenerator(new StandardDumpContributorResolver(bundleContext), configurationProvider, this.eventLoggerFactory.createEventLogger(bundleContext.getBundle()));
+ registrationTracker.track(bundleContext.registerService(DumpGenerator.class.getName(), this.dumpGenerator, null));
+
+ this.dumpContributorPublisher = new DumpContributorPublisher(bundleContext);
+ this.dumpContributorPublisher.publishDumpContributors();
+
+ return this.dumpGenerator;
+ }
+
+ public void dumpStop() {
+ if (this.dumpGenerator != null) {
+ this.dumpGenerator.close();
+ }
+
+ if (this.dumpContributorPublisher != null) {
+ this.dumpContributorPublisher.retractDumpContributors();
+ }
+ }
+
+ public void logStart() throws ConfigurationPublicationFailedException {
+ Dictionary<String, String> configuration = configurationProvider.getConfiguration();
+
+ SLF4JBridgeHandler.install();
+
+ updateLogConfiguration(configuration);
+ }
+
+ public void logStop() {
+ System.setProperty(PROPERTY_LOGBACK_CONTEXT_SELECTOR, DEFAULT_CONTEXT_SELECTOR);
+
+ DelegatingContextSelector.setDelegate(null);
+
+ if (this.sysOut != null) {
+ System.setOut(this.sysOut);
+ }
+
+ if (this.sysErr != null) {
+ System.setErr(this.sysErr);
+ }
+
+ SLF4JBridgeHandler.uninstall();
+ enableJulConsoleLogger();
+ }
+
+ private void enableJulConsoleLogger() {
+ if (this.javaConsoleHandler != null) {
+ getJavaRootLogger().addHandler(this.javaConsoleHandler);
+ }
+ }
+
+ private void disableJulConsoleHandler() {
+ // remove console handler from root logger
+ Logger rootLogger = getJavaRootLogger();
+ Handler[] handlers = rootLogger.getHandlers();
+ for (Handler handler : handlers) {
+ if (handler instanceof ConsoleHandler) {
+ this.javaConsoleHandler = (ConsoleHandler) handler;
+ rootLogger.removeHandler(handler);
+ }
+ }
+ }
+
+ public void eventLogStart() {
+ this.eventLoggerFactory = createFactory(bundleContext);
+ ServiceFactory<EventLogger> serviceFactory = new EventLoggerServiceFactory(this.eventLoggerFactory);
+ registrationTracker.track(bundleContext.registerService(EventLoggerFactory.class.getName(), this.eventLoggerFactory, null));
+ registrationTracker.track(bundleContext.registerService(EventLogger.class.getName(), serviceFactory, null));
+ }
+
+ private PrintStream wrapPrintStream(PrintStream printStream, String loggerName, LoggingLevel loggingLevel, ExecutionStackAccessor stackAccessor, ConfigurationProvider configurationProvider, String configurationProperty) {
+ LoggingPrintStreamWrapper wrapper = new LoggingPrintStreamWrapper(printStream, loggerName, loggingLevel, stackAccessor, configurationProvider, configurationProperty);
+ return wrapper;
+ }
+
+ private ServiceRegistration<?> publishPrintStream(PrintStream printStream, String name) {
+ Hashtable<String, String> properties = new Hashtable<String, String>();
+ properties.put("org.eclipse.virgo.medic.log.printStream", name);
+
+ ServiceRegistration<?> registration = bundleContext.registerService(PrintStream.class.getName(), printStream, properties);
+ registrationTracker.track(registration);
+
+ return registration;
+ }
+
+ private ServiceRegistration<?> publishDelegatingPrintStream(PrintStream printStream, String name) {
+ Hashtable<String, String> properties = new Hashtable<String, String>();
+ properties.put("org.eclipse.virgo.medic.log.printStream", name);
+
+ String[] classes = new String[]{DelegatingPrintStream.class.getName()};
+ ServiceRegistration<?> delegatingPrintStreamRegistration = bundleContext.registerService(classes, printStream, properties);
+ registrationTracker.track(delegatingPrintStreamRegistration);
+
+ return delegatingPrintStreamRegistration;
+ }
+
+ private void publishDefaultConfigurationIfAvailable(BundleContext context, StandardLoggingConfigurationPublisher publisher) throws ConfigurationPublicationFailedException {
+ String logConfigPath = context.getProperty(PROPERTY_MEDIC_CONFIG_PATH);
+ if (logConfigPath != null) {
+ File logConfigFile = new File(logConfigPath);
+ if (logConfigFile.exists()) {
+ publisher.publishDefaultConfiguration(new File(logConfigPath));
+ }
+ }
+ }
+
+ private static StandardContextSelectorDelegate createContextSelectorDelegate(BundleContext bundleContext) {
+ ConfigurationLocator configurationLocator = createConfigurationLocator(bundleContext);
+ CallingBundleResolver loggingCallerLocator = createLoggingCallerLocator();
+ LoggerContextConfigurer loggerContextConfigurer = new JoranLoggerContextConfigurer();
+ return new StandardContextSelectorDelegate(loggingCallerLocator, configurationLocator, bundleContext.getBundle(), loggerContextConfigurer);
+ }
+
+ /**
+ * Logging configuration is located by searching up to two sources, depending on the bundle doing the logging.
+ * <p/>
+ * Firstly, if and only if the bundle has a specific Medic manifest header, the service registry is searched in
+ * a location specified in the manifest header. Secondly, if the configuration has not already been found, the
+ * the bundle's resources are checked for a Logback configuration file.
+ */
+ private static ConfigurationLocator createConfigurationLocator(BundleContext bundleContext) {
+ return new CompositeConfigurationLocator(new ServiceRegistryConfigurationLocator(bundleContext), new BundleResourceConfigurationLocator());
+ }
+
+ private static CallingBundleResolver createLoggingCallerLocator() {
+ ClassSelector classSelector = createClassSelector();
+ ExecutionStackAccessor executionStackAccessor = createExecutionStackAccessor();
+
+ return new StandardCallingBundleResolver(executionStackAccessor, classSelector);
+ }
+
+ private static ClassSelector createClassSelector() {
+ return new PackageNameFilteringClassSelector(DEFAULT_LOGGING_PACKAGES);
+ }
+
+ private static ExecutionStackAccessor createExecutionStackAccessor() {
+ return new SecurityManagerExecutionStackAccessor();
+ }
+
+ private LogBackEventLoggerFactory createFactory(BundleContext context) {
+ BundleSearchingPropertyResourceBundleResolver resourceBundleResolver = new BundleSearchingPropertyResourceBundleResolver();
+ return new LogBackEventLoggerFactory(resourceBundleResolver, new StandardLocaleResolver(), context.getBundle());
+ }
+
+ private Logger getJavaRootLogger() {
+ return Logger.getLogger("");
+ }
+
+ @Override
+ public void configurationChanged(ConfigurationProvider provider) {
+ Dictionary<String, String> configuration = configurationProvider.getConfiguration();
+ updateLogConfiguration(configuration);
+ }
+
+ private synchronized void updateLogConfiguration(Dictionary<String, String> configuration) {
+ if (Boolean.valueOf(configuration.get(ConfigurationProvider.KEY_LOG_WRAP_SYSOUT))) {
+ delegatingSysOutRegistration = publishDelegatingPrintStream(delegatingSysOut, LOGGER_NAME_SYSOUT_DELEGATE);
+ sysOutRegistration = publishPrintStream(this.sysOut, LOGGER_NAME_SYSOUT);
+
+ System.setOut(wrapPrintStream(System.out, LOGGER_NAME_SYSOUT, LoggingLevel.INFO, stackAccessor, configurationProvider, ConfigurationProvider.KEY_LOG_WRAP_SYSOUT));
+ } else {
+ if (delegatingSysOutRegistration != null) {
+ registrationTracker.unregister(delegatingSysOutRegistration);
+ delegatingSysOutRegistration = null;
+ }
+ if (sysOutRegistration != null) {
+ registrationTracker.unregister(sysOutRegistration);
+ sysOutRegistration = null;
+ }
+ System.setOut(delegatingSysOut);
+ }
+
+ if (Boolean.valueOf(configuration.get(ConfigurationProvider.KEY_LOG_WRAP_SYSERR))) {
+ delegatingSysErrRegistration = publishDelegatingPrintStream(delegatingSysErr, LOGGER_NAME_SYSERR_DELEGATE);
+ sysErrRegistration = publishPrintStream(this.sysErr, LOGGER_NAME_SYSERR);
+
+ System.setErr(wrapPrintStream(System.err, LOGGER_NAME_SYSERR, LoggingLevel.ERROR, stackAccessor, configurationProvider, ConfigurationProvider.KEY_LOG_WRAP_SYSERR));
+ } else {
+ if (delegatingSysErrRegistration != null) {
+ registrationTracker.unregister(delegatingSysErrRegistration);
+ delegatingSysErrRegistration = null;
+ }
+ if (sysErrRegistration != null) {
+ registrationTracker.unregister(sysErrRegistration);
+ sysErrRegistration = null;
+ }
+ System.setErr(delegatingSysErr);
+ }
+
+ if (Boolean.valueOf(configuration.get(ConfigurationProvider.KEY_ENABLE_JUL_CONSOLE_HANDLER))) {
+ enableJulConsoleLogger();
+ } else {
+ disableJulConsoleHandler();
+ }
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/impl/MedicActivator.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/impl/MedicActivator.java
index 06865a3..c34aaa9 100644
--- a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/impl/MedicActivator.java
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/impl/MedicActivator.java
@@ -11,297 +11,76 @@
package org.eclipse.virgo.medic.impl;
-import java.io.File;
-import java.io.PrintStream;
-import java.util.Arrays;
-import java.util.Dictionary;
-import java.util.Hashtable;
-import java.util.List;
-import java.util.logging.ConsoleHandler;
-import java.util.logging.Handler;
-import java.util.logging.Logger;
-
-import org.osgi.framework.BundleActivator;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleListener;
-import org.osgi.framework.ServiceFactory;
-import org.osgi.framework.ServiceReference;
-import org.osgi.service.cm.ConfigurationListener;
-import org.osgi.service.log.LogService;
-import org.slf4j.LoggerFactory;
-import org.slf4j.bridge.SLF4JBridgeHandler;
-
import org.eclipse.equinox.log.ExtendedLogReaderService;
import org.eclipse.virgo.medic.dump.DumpGenerator;
-import org.eclipse.virgo.medic.dump.impl.DumpContributorPublisher;
-import org.eclipse.virgo.medic.dump.impl.StandardDumpContributorResolver;
-import org.eclipse.virgo.medic.dump.impl.StandardDumpGenerator;
-import org.eclipse.virgo.medic.eventlog.EventLogger;
-import org.eclipse.virgo.medic.eventlog.EventLoggerFactory;
-import org.eclipse.virgo.medic.eventlog.impl.BundleSearchingPropertyResourceBundleResolver;
-import org.eclipse.virgo.medic.eventlog.impl.EventLoggerServiceFactory;
-import org.eclipse.virgo.medic.eventlog.impl.StandardLocaleResolver;
-import org.eclipse.virgo.medic.eventlog.impl.logback.LogBackEventLoggerFactory;
import org.eclipse.virgo.medic.impl.config.ConfigurationAdminConfigurationProvider;
import org.eclipse.virgo.medic.impl.config.ConfigurationProvider;
-import org.eclipse.virgo.medic.log.ConfigurationPublicationFailedException;
-import org.eclipse.virgo.medic.log.DelegatingPrintStream;
-import org.eclipse.virgo.medic.log.LoggingConfigurationPublisher;
-import org.eclipse.virgo.medic.log.impl.CallingBundleResolver;
-import org.eclipse.virgo.medic.log.impl.ClassSelector;
-import org.eclipse.virgo.medic.log.impl.ExecutionStackAccessor;
-import org.eclipse.virgo.medic.log.impl.LoggingLevel;
-import org.eclipse.virgo.medic.log.impl.LoggingPrintStreamWrapper;
-import org.eclipse.virgo.medic.log.impl.PackageNameFilteringClassSelector;
-import org.eclipse.virgo.medic.log.impl.SecurityManagerExecutionStackAccessor;
-import org.eclipse.virgo.medic.log.impl.StandardCallingBundleResolver;
-import org.eclipse.virgo.medic.log.impl.StandardDelegatingPrintStream;
-import org.eclipse.virgo.medic.log.impl.config.BundleResourceConfigurationLocator;
-import org.eclipse.virgo.medic.log.impl.config.CompositeConfigurationLocator;
-import org.eclipse.virgo.medic.log.impl.config.ConfigurationLocator;
-import org.eclipse.virgo.medic.log.impl.config.ServiceRegistryConfigurationLocator;
-import org.eclipse.virgo.medic.log.impl.config.StandardLoggingConfigurationPublisher;
-import org.eclipse.virgo.medic.log.impl.logback.DelegatingContextSelector;
-import org.eclipse.virgo.medic.log.impl.logback.JoranLoggerContextConfigurer;
-import org.eclipse.virgo.medic.log.impl.logback.LoggerContextConfigurer;
-import org.eclipse.virgo.medic.log.impl.logback.StandardContextSelectorDelegate;
import org.eclipse.virgo.medic.log.osgi.OSGiLogServiceListener;
import org.eclipse.virgo.medic.management.MedicMBeanExporter;
import org.eclipse.virgo.util.osgi.ServiceRegistrationTracker;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.cm.ConfigurationListener;
+import org.osgi.service.log.LogService;
+import org.slf4j.LoggerFactory;
+/**
+ * This class is threadSafe
+ *
+ */
public final class MedicActivator implements BundleActivator {
- private static final String LOGGER_NAME_SYSERR = "System.err";
-
- private static final String LOGGER_NAME_SYSOUT = "System.out";
-
- private static final String LOGGER_NAME_SYSERR_DELEGATE = "delegating.System.err";
-
- private static final String LOGGER_NAME_SYSOUT_DELEGATE = "delegating.System.out";
-
- private static final String PROPERTY_MEDIC_CONFIG_PATH = "org.eclipse.virgo.medic.log.config.path";
-
- private static final String DEFAULT_CONTEXT_SELECTOR = "ch.qos.logback.classic.selector.DefaultContextSelector";
-
- private static final String PROPERTY_LOGBACK_CONTEXT_SELECTOR = "logback.ContextSelector";
-
- private final ServiceRegistrationTracker registrationTracker = new ServiceRegistrationTracker();
-
- private MedicMBeanExporter medicMBeanExporter;
+ private final ServiceRegistrationTracker registrationTracker = new ServiceRegistrationTracker();
- private volatile StandardDumpGenerator dumpGenerator;
+ private volatile ServiceReference<ExtendedLogReaderService> logReaderReference;
- private volatile LogBackEventLoggerFactory eventLoggerFactory;
+ private LogController logController = null;
- private volatile DumpContributorPublisher dumpContributorPublisher;
-
- private volatile ServiceReference<ExtendedLogReaderService> logReaderReference;
+ private ConfigurationProvider configurationProvider = null;
- private volatile PrintStream sysOut;
+ private MedicMBeanExporter medicMBeanExporter = null;
- private volatile PrintStream sysErr;
-
- private static final List<String> DEFAULT_LOGGING_PACKAGES = Arrays.asList(//
- "org.apache.commons.logging",//
- "org.apache.log4j",//
- "org.slf4j",//
- "org.slf4j.impl",//
- "org.eclipse.virgo.medic.log",//
- "org.eclipse.virgo.medic.log.impl",//
- "org.eclipse.virgo.medic.log.impl.logback");
-
public void start(BundleContext context) throws Exception {
- ConfigurationProvider configurationProvider = new ConfigurationAdminConfigurationProvider(context);
+ this.configurationProvider = new ConfigurationAdminConfigurationProvider(context);
this.registrationTracker.track(context.registerService(ConfigurationListener.class.getName(), configurationProvider, null));
- logStart(context, configurationProvider);
- eventLogStart(context);
- dumpStart(context, configurationProvider);
-
- this.logReaderReference = context.getServiceReference(ExtendedLogReaderService.class);
- ExtendedLogReaderService logReader = context.getService(this.logReaderReference);
- logReader.addLogListener(new OSGiLogServiceListener(LoggerFactory.getLogger(LogService.class)));
- }
- public void stop(BundleContext context) throws Exception {
- this.registrationTracker.unregisterAll();
-
- ServiceReference<ExtendedLogReaderService> localLogReaderReference = this.logReaderReference;
- if(localLogReaderReference != null){
- context.ungetService(localLogReaderReference);
- }
- dumpStop();
- logStop(context);
- }
+ this.logController = new LogController(context, configurationProvider, registrationTracker);
- private void dumpStart(BundleContext context, ConfigurationProvider configurationProvider) {
- this.dumpGenerator = new StandardDumpGenerator(new StandardDumpContributorResolver(context), configurationProvider, this.eventLoggerFactory.createEventLogger(context.getBundle()));
- this.registrationTracker.track(context.registerService(DumpGenerator.class.getName(), this.dumpGenerator, null));
+ configurationProvider.addChangeListener(logController);
- this.dumpContributorPublisher = new DumpContributorPublisher(context);
- this.dumpContributorPublisher.publishDumpContributors();
+ logController.logStart();
+ logController.eventLogStart();
+ DumpGenerator dumpGenerator = logController.dumpStart();
- this.medicMBeanExporter = new MedicMBeanExporter(configurationProvider, this.dumpGenerator);
+ this.medicMBeanExporter = new MedicMBeanExporter(configurationProvider, dumpGenerator);
+
+ this.logReaderReference = context.getServiceReference(ExtendedLogReaderService.class);
+ ExtendedLogReaderService logReader = context.getService(this.logReaderReference);
+ logReader.addLogListener(new OSGiLogServiceListener(LoggerFactory.getLogger(LogService.class)));
}
- private void dumpStop() {
- if(this.medicMBeanExporter != null){
- this.medicMBeanExporter.close();
+ public void stop(BundleContext context) throws Exception {
+ MedicMBeanExporter medicMBeanExporter2 = this.medicMBeanExporter;
+ if(medicMBeanExporter2 != null){
+ medicMBeanExporter2.close();
}
- if (this.dumpGenerator != null) {
- this.dumpGenerator.close();
+ this.registrationTracker.unregisterAll();
+ ServiceReference<ExtendedLogReaderService> localLogReaderReference = this.logReaderReference;
+ if (localLogReaderReference != null) {
+ context.ungetService(localLogReaderReference);
}
- if (this.dumpContributorPublisher != null) {
- this.dumpContributorPublisher.retractDumpContributors();
+ LogController logController2 = logController;
+ ConfigurationProvider configurationProvider2 = configurationProvider;
+ if (configurationProvider2 != null) {
+ configurationProvider2.removeChangeListener(logController2);
}
- }
-
- private void logStart(BundleContext context, ConfigurationProvider configurationProvider) throws ConfigurationPublicationFailedException {
- StandardContextSelectorDelegate delegate = createContextSelectorDelegate(context);
- this.registrationTracker.track(context.registerService(BundleListener.class.getName(), delegate, null));
- DelegatingContextSelector.setDelegate(delegate);
-
- StandardLoggingConfigurationPublisher loggingConfigurationPublisher = new StandardLoggingConfigurationPublisher(context);
- this.registrationTracker.track(context.registerService(LoggingConfigurationPublisher.class.getName(), loggingConfigurationPublisher, null));
-
- publishDefaultConfigurationIfAvailable(context, loggingConfigurationPublisher);
-
- System.setProperty(PROPERTY_LOGBACK_CONTEXT_SELECTOR, DelegatingContextSelector.class.getName());
-
- ExecutionStackAccessor stackAccessor = new SecurityManagerExecutionStackAccessor();
-
- Dictionary<String, String> configuration = configurationProvider.getConfiguration();
-
- PrintStream delegatingSysOut = new StandardDelegatingPrintStream(System.out);
- PrintStream delegatingSysErr = new StandardDelegatingPrintStream(System.err);
-
- this.sysOut = System.out;
- this.sysErr = System.err;
-
- System.setOut(delegatingSysOut);
- System.setErr(delegatingSysErr);
-
- if (Boolean.valueOf(configuration.get(ConfigurationProvider.KEY_LOG_WRAP_SYSOUT))) {
- publishDelegatingPrintStream(delegatingSysOut, LOGGER_NAME_SYSOUT_DELEGATE, context);
- publishPrintStream(this.sysOut, LOGGER_NAME_SYSOUT, context);
-
- System.setOut(wrapPrintStream(System.out, LOGGER_NAME_SYSOUT, LoggingLevel.INFO, stackAccessor, configurationProvider, ConfigurationProvider.KEY_LOG_WRAP_SYSOUT));
- }
-
- if (Boolean.valueOf(configuration.get(ConfigurationProvider.KEY_LOG_WRAP_SYSERR))) {
- publishDelegatingPrintStream(delegatingSysErr, LOGGER_NAME_SYSERR_DELEGATE, context);
- publishPrintStream(this.sysErr, LOGGER_NAME_SYSERR, context);
-
- System.setErr(wrapPrintStream(System.err, LOGGER_NAME_SYSERR, LoggingLevel.ERROR, stackAccessor, configurationProvider, ConfigurationProvider.KEY_LOG_WRAP_SYSERR));
- }
-
- configureJavaLogging(Boolean.valueOf(configuration.get(ConfigurationProvider.KEY_ENABLE_JUL_CONSOLE_HANDLER)));
- }
-
- private PrintStream wrapPrintStream(PrintStream printStream, String loggerName, LoggingLevel loggingLevel, ExecutionStackAccessor stackAccessor, ConfigurationProvider configurationProvider, String configurationProperty) {
- LoggingPrintStreamWrapper wrapper = new LoggingPrintStreamWrapper(printStream, loggerName, loggingLevel, stackAccessor, configurationProvider, configurationProperty);
- return wrapper;
- }
-
- private void publishPrintStream(PrintStream printStream, String name, BundleContext context) {
- Hashtable<String, String> properties = new Hashtable<String, String>();
- properties.put("org.eclipse.virgo.medic.log.printStream", name);
-
- this.registrationTracker.track(context.registerService(PrintStream.class.getName(), printStream, properties));
- }
-
- private void publishDelegatingPrintStream(PrintStream printStream, String name, BundleContext context) {
- Hashtable<String, String> properties = new Hashtable<String, String>();
- properties.put("org.eclipse.virgo.medic.log.printStream", name);
-
- String[] classes = new String[] {DelegatingPrintStream.class.getName()};
- this.registrationTracker.track(context.registerService(classes, printStream, properties));
- }
-
- private void publishDefaultConfigurationIfAvailable(BundleContext context, StandardLoggingConfigurationPublisher publisher) throws ConfigurationPublicationFailedException {
- String logConfigPath = context.getProperty(PROPERTY_MEDIC_CONFIG_PATH);
- if (logConfigPath != null) {
- File logConfigFile = new File(logConfigPath);
- if (logConfigFile.exists()) {
- publisher.publishDefaultConfiguration(new File(logConfigPath));
- }
- }
- }
-
- private static StandardContextSelectorDelegate createContextSelectorDelegate(BundleContext bundleContext) {
- ConfigurationLocator configurationLocator = createConfigurationLocator(bundleContext);
- CallingBundleResolver loggingCallerLocator = createLoggingCallerLocator();
- LoggerContextConfigurer loggerContextConfigurer = new JoranLoggerContextConfigurer();
- return new StandardContextSelectorDelegate(loggingCallerLocator, configurationLocator, bundleContext.getBundle(), loggerContextConfigurer);
- }
-
- /**
- * Logging configuration is located by searching up to two sources, depending on the bundle doing the logging.
- * <p>
- * Firstly, if and only if the bundle has a specific Medic manifest header, the service registry is searched in
- * a location specified in the manifest header. Secondly, if the configuration has not already been found, the
- * the bundle's resources are checked for a Logback configuration file.
- */
- private static ConfigurationLocator createConfigurationLocator(BundleContext bundleContext) {
- return new CompositeConfigurationLocator(new ServiceRegistryConfigurationLocator(bundleContext), new BundleResourceConfigurationLocator());
- }
-
- private static CallingBundleResolver createLoggingCallerLocator() {
- ClassSelector classSelector = createClassSelector();
- ExecutionStackAccessor executionStackAccessor = createExecutionStackAccessor();
-
- return new StandardCallingBundleResolver(executionStackAccessor, classSelector);
- }
-
- private static ClassSelector createClassSelector() {
- return new PackageNameFilteringClassSelector(DEFAULT_LOGGING_PACKAGES);
- }
-
- private static ExecutionStackAccessor createExecutionStackAccessor() {
- return new SecurityManagerExecutionStackAccessor();
- }
- private void logStop(BundleContext context) {
-
- System.setProperty(PROPERTY_LOGBACK_CONTEXT_SELECTOR, DEFAULT_CONTEXT_SELECTOR);
-
- DelegatingContextSelector.setDelegate(null);
-
- if (this.sysOut != null) {
- System.setOut(this.sysOut);
+ if (logController2 != null) {
+ logController2.dumpStop();
+ logController2.logStop();
}
-
- if (this.sysErr != null) {
- System.setErr(this.sysErr);
- }
}
- private void eventLogStart(BundleContext context) {
- this.eventLoggerFactory = createFactory(context);
- ServiceFactory<EventLogger> serviceFactory = new EventLoggerServiceFactory(this.eventLoggerFactory);
- this.registrationTracker.track(context.registerService(EventLoggerFactory.class.getName(), this.eventLoggerFactory, null));
- this.registrationTracker.track(context.registerService(EventLogger.class.getName(), serviceFactory, null));
- }
-
- private LogBackEventLoggerFactory createFactory(BundleContext context) {
- BundleSearchingPropertyResourceBundleResolver resourceBundleResolver = new BundleSearchingPropertyResourceBundleResolver();
- return new LogBackEventLoggerFactory(resourceBundleResolver, new StandardLocaleResolver(), context.getBundle());
- }
-
- private void configureJavaLogging(boolean enableConsoleHandler) {
- SLF4JBridgeHandler.install();
-
- // remove console handler from root logger?
- if (enableConsoleHandler) {
- return;
- }
-
- Logger rootLogger = Logger.getLogger("");
- Handler[] handlers = rootLogger.getHandlers();
- for (Handler handler: handlers) {
- if (handler instanceof ConsoleHandler) {
- rootLogger.removeHandler(handler);
- }
- }
- }
}
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/impl/config/ConfigurationAdminConfigurationProvider.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/impl/config/ConfigurationAdminConfigurationProvider.java
index 12a0682..99c4037 100644
--- a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/impl/config/ConfigurationAdminConfigurationProvider.java
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/impl/config/ConfigurationAdminConfigurationProvider.java
@@ -13,8 +13,10 @@ package org.eclipse.virgo.medic.impl.config;
import java.io.IOException;
import java.util.Dictionary;
+import java.util.HashSet;
import java.util.Hashtable;
+import org.eclipse.virgo.util.common.SynchronizedCollection;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.service.cm.Configuration;
@@ -32,8 +34,11 @@ public final class ConfigurationAdminConfigurationProvider implements Configurat
private volatile Dictionary<String,String> configuration = DEFAULT_CONFIG;
+ private HashSet<ConfigurationChangeListener> listeners;
+
public ConfigurationAdminConfigurationProvider(BundleContext context) {
this.bundleContext = context;
+ this.listeners = new HashSet<ConfigurationChangeListener>();
initialisePropertiesFromConfigurationAdmin();
}
@@ -73,6 +78,8 @@ public final class ConfigurationAdminConfigurationProvider implements Configurat
} else {
this.configuration = DEFAULT_CONFIG;
}
+
+ notifyListeners();
}
private static Dictionary<String, String> createDefaultConfiguration() {
@@ -82,7 +89,21 @@ public final class ConfigurationAdminConfigurationProvider implements Configurat
configuration.put(KEY_LOG_WRAP_SYSERR, Boolean.toString(Boolean.TRUE));
return configuration;
}
-
+
+ public void addChangeListener(ConfigurationChangeListener listener) {
+ listeners.add(listener);
+ }
+
+ public boolean removeChangeListener(ConfigurationChangeListener listener) {
+ return listeners.remove(listener);
+ }
+
+ private void notifyListeners() {
+ for (Object listener: listeners.toArray()) {
+ ((ConfigurationChangeListener) listener).configurationChanged(this);
+ }
+ }
+
private final class MedicConfigurationListener implements ConfigurationListener {
@SuppressWarnings("unchecked")
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/impl/config/ConfigurationChangeListener.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/impl/config/ConfigurationChangeListener.java
new file mode 100755
index 0000000..f647d94
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/impl/config/ConfigurationChangeListener.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2011 SAP AG
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hristo Iliev, SAP AG - initial contribution
+ *******************************************************************************/
+package org.eclipse.virgo.medic.impl.config;
+
+public interface ConfigurationChangeListener {
+
+ /**
+ * Called when the configuration changed.
+ * <p/>
+ * The listener can be called although the configuration is virtually the same - no configuration data
+ * comparison is made.
+ *
+ * @param provider ConfigurationProvider that can be used to obtain the properties.
+ */
+ public void configurationChanged(ConfigurationProvider provider);
+
+}
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/impl/config/ConfigurationProvider.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/impl/config/ConfigurationProvider.java
index 08fae62..ce61df0 100644
--- a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/impl/config/ConfigurationProvider.java
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/impl/config/ConfigurationProvider.java
@@ -16,18 +16,35 @@ import java.util.Dictionary;
public interface ConfigurationProvider {
public static final String KEY_DUMP_ROOT_DIRECTORY = "dump.root.directory";
-
+
public static final String KEY_LOG_WRAP_SYSOUT = "log.wrapSysOut";
-
+
public static final String KEY_LOG_WRAP_SYSERR = "log.wrapSysErr";
-
+
public static final String KEY_LOG_DUMP_BUFFERSIZE = "log.dump.bufferSize";
-
+
public static final String KEY_LOG_DUMP_LEVEL = "log.dump.level";
-
+
public static final String KEY_LOG_DUMP_PATTERN = "log.dump.pattern";
public static final String KEY_ENABLE_JUL_CONSOLE_HANDLER = "log.jul.consoleHandler";
Dictionary<String, String> getConfiguration();
+
+ /**
+ * Adds listener that will be notified when the configuration changes
+ * <p/>
+ * Multiple listeners are supported.
+ *
+ * @param listener Listener to be added
+ */
+ public void addChangeListener(ConfigurationChangeListener listener);
+
+ /**
+ * Removes previously registered listener
+ *
+ * @param listener Listener to be removed
+ * @return Returns <code>true</code> if the lister was registered and <code>false</code> if not
+ */
+ public boolean removeChangeListener(ConfigurationChangeListener listener);
}
diff --git a/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/impl/LogControllerTests.java b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/impl/LogControllerTests.java
new file mode 100755
index 0000000..8dd0825
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/impl/LogControllerTests.java
@@ -0,0 +1,232 @@
+/*******************************************************************************
+ * Copyright (c) 2011 SAP AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hristo Iliev, SAP AG. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.impl;
+
+import org.eclipse.virgo.medic.impl.config.ConfigurationAdminConfigurationProvider;
+import org.eclipse.virgo.medic.impl.config.ConfigurationProvider;
+import org.eclipse.virgo.medic.log.ConfigurationPublicationFailedException;
+import org.eclipse.virgo.medic.log.DelegatingPrintStream;
+import org.eclipse.virgo.medic.log.impl.LoggingPrintStreamWrapper;
+import org.eclipse.virgo.medic.log.impl.StandardDelegatingPrintStream;
+import org.eclipse.virgo.teststubs.osgi.framework.StubBundleContext;
+import org.eclipse.virgo.util.osgi.ServiceRegistrationTracker;
+import org.junit.Test;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.Arrays;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.logging.ConsoleHandler;
+import java.util.logging.Handler;
+import java.util.logging.Logger;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+public class LogControllerTests {
+
+ private static final String LOGGER_NAME_SYSERR = "System.err";
+ private static final String LOGGER_NAME_SYSOUT = "System.out";
+
+ private static final String LOGGER_NAME_SYSERR_DELEGATE = "delegating.System.err";
+ private static final String LOGGER_NAME_SYSOUT_DELEGATE = "delegating.System.out";
+
+ private final StubBundleContext bundleContext = new StubBundleContext();
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void loggingWithWrappedStreams() throws IOException, ConfigurationPublicationFailedException, InvalidSyntaxException {
+ ConfigurationAdmin configurationAdmin = createMock(ConfigurationAdmin.class);
+ Configuration configuration = createMock(Configuration.class);
+
+ Dictionary properties = new Hashtable();
+ properties.put(ConfigurationProvider.KEY_LOG_WRAP_SYSERR, "true");
+ properties.put(ConfigurationProvider.KEY_LOG_WRAP_SYSOUT, "true");
+ createConfigurationMocks(configurationAdmin, configuration, properties, 1);
+
+ ConfigurationAdminConfigurationProvider configurationProvider = new ConfigurationAdminConfigurationProvider(this.bundleContext);
+ LogController controller = new LogController(this.bundleContext, configurationProvider, new ServiceRegistrationTracker());
+
+ controller.logStart();
+
+ checkPublishedStreamServices(DelegatingPrintStream.class, StandardDelegatingPrintStream.class, LOGGER_NAME_SYSOUT_DELEGATE, LOGGER_NAME_SYSERR_DELEGATE);
+ checkPublishedStreamServices(PrintStream.class, PrintStream.class, LOGGER_NAME_SYSOUT, LOGGER_NAME_SYSERR);
+
+ assertTrue(System.out instanceof LoggingPrintStreamWrapper);
+ assertTrue(System.err instanceof LoggingPrintStreamWrapper);
+
+ controller.logStop();
+
+ assertFalse(System.out instanceof LoggingPrintStreamWrapper);
+ assertFalse(System.err instanceof LoggingPrintStreamWrapper);
+
+ verify(configurationAdmin, configuration);
+ }
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void loggingWithNonWrappedStreams() throws IOException, ConfigurationPublicationFailedException, InvalidSyntaxException {
+ ConfigurationAdmin configurationAdmin = createMock(ConfigurationAdmin.class);
+ Configuration configuration = createMock(Configuration.class);
+
+ Dictionary properties = new Hashtable();
+ properties.put(ConfigurationProvider.KEY_LOG_WRAP_SYSERR, "false");
+ properties.put(ConfigurationProvider.KEY_LOG_WRAP_SYSOUT, "false");
+ createConfigurationMocks(configurationAdmin, configuration, properties, 1);
+
+ ConfigurationAdminConfigurationProvider configurationProvider = new ConfigurationAdminConfigurationProvider(this.bundleContext);
+ LogController controller = new LogController(this.bundleContext, configurationProvider, new ServiceRegistrationTracker());
+
+ controller.logStart();
+
+ assertTrue(System.out instanceof StandardDelegatingPrintStream);
+ assertTrue(System.err instanceof StandardDelegatingPrintStream);
+
+ controller.logStop();
+
+ assertFalse(System.out instanceof LoggingPrintStreamWrapper);
+ assertFalse(System.err instanceof LoggingPrintStreamWrapper);
+
+ verify(configurationAdmin, configuration);
+ }
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void changeFromWrappedToNonWrappedStreams() throws IOException, ConfigurationPublicationFailedException, InvalidSyntaxException {
+ ConfigurationAdmin configurationAdmin = createMock(ConfigurationAdmin.class);
+ Configuration configuration = createMock(Configuration.class);
+
+ Dictionary properties = new Hashtable();
+ properties.put(ConfigurationProvider.KEY_LOG_WRAP_SYSERR, "true");
+ properties.put(ConfigurationProvider.KEY_LOG_WRAP_SYSOUT, "true");
+ createConfigurationMocks(configurationAdmin, configuration, properties, 1);
+
+ ConfigurationAdminConfigurationProvider configurationProvider = new ConfigurationAdminConfigurationProvider(this.bundleContext);
+ LogController controller = new LogController(this.bundleContext, configurationProvider, new ServiceRegistrationTracker());
+
+ controller.logStart();
+
+ properties.put(ConfigurationProvider.KEY_LOG_WRAP_SYSERR, "false");
+ properties.put(ConfigurationProvider.KEY_LOG_WRAP_SYSOUT, "false");
+ controller.configurationChanged(configurationProvider);
+
+ assertNull(this.bundleContext.getServiceReferences(DelegatingPrintStream.class.getName(), null));
+
+ assertTrue(System.out instanceof StandardDelegatingPrintStream);
+ assertTrue(System.err instanceof StandardDelegatingPrintStream);
+
+ controller.logStop();
+
+ assertFalse(System.out instanceof LoggingPrintStreamWrapper);
+ assertFalse(System.err instanceof LoggingPrintStreamWrapper);
+ }
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void loggingWithEnabledJULConsoleHandler() throws IOException, ConfigurationPublicationFailedException {
+ ConfigurationAdmin configurationAdmin = createMock(ConfigurationAdmin.class);
+ Configuration configuration = createMock(Configuration.class);
+
+ Dictionary properties = new Hashtable();
+ properties.put(ConfigurationProvider.KEY_ENABLE_JUL_CONSOLE_HANDLER, "true");
+ createConfigurationMocks(configurationAdmin, configuration, properties, 1);
+
+ ConfigurationAdminConfigurationProvider configurationProvider = new ConfigurationAdminConfigurationProvider(this.bundleContext);
+ LogController controller = new LogController(this.bundleContext, configurationProvider, new ServiceRegistrationTracker());
+
+ controller.logStart();
+ assertTrue(checkForJULConsoleHandler());
+
+ controller.logStop();
+ assertTrue(checkForJULConsoleHandler());
+
+ verify(configurationAdmin, configuration);
+ }
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void loggingWithDisabledJULConsoleHandler() throws IOException, ConfigurationPublicationFailedException {
+ ConfigurationAdmin configurationAdmin = createMock(ConfigurationAdmin.class);
+ Configuration configuration = createMock(Configuration.class);
+
+ Dictionary properties = new Hashtable();
+ properties.put(ConfigurationProvider.KEY_ENABLE_JUL_CONSOLE_HANDLER, "false");
+ createConfigurationMocks(configurationAdmin, configuration, properties, 1);
+
+ ConfigurationAdminConfigurationProvider configurationProvider = new ConfigurationAdminConfigurationProvider(this.bundleContext);
+ LogController controller = new LogController(this.bundleContext, configurationProvider, new ServiceRegistrationTracker());
+
+ controller.logStart();
+ assertFalse(checkForJULConsoleHandler());
+
+ controller.logStop();
+ assertTrue(checkForJULConsoleHandler());
+
+ verify(configurationAdmin, configuration);
+ }
+
+ private void checkPublishedStreamServices(Class registeredClass, Class serviceClass, String... streamNames) throws InvalidSyntaxException {
+ ServiceReference<?> serviceReferences[] = this.bundleContext.getServiceReferences(registeredClass.getName(), null);
+
+ for (ServiceReference reference : serviceReferences) {
+ String streamName = (String) reference.getProperty("org.eclipse.virgo.medic.log.printStream");
+
+ boolean foundMatch = checkForMatchingNames(streamName, streamNames);
+ if (!foundMatch) {
+ fail("Stream name [" + streamName + "] not one of the expected " + Arrays.toString(streamNames));
+ }
+
+ assertEquals(serviceClass, this.bundleContext.getService(reference).getClass());
+ }
+ }
+
+ private boolean checkForMatchingNames(String streamName, String[] streamNames) {
+ boolean foundMatch = false;
+ for (String name : streamNames) {
+ if (name.equals(streamName)) {
+ foundMatch = true;
+ break;
+ }
+ }
+ return foundMatch;
+ }
+
+ private ServiceRegistration createConfigurationMocks(ConfigurationAdmin configurationAdmin, Configuration configuration, Dictionary properties, int times) throws IOException {
+ ServiceRegistration serviceRegistration = this.bundleContext.registerService(ConfigurationAdmin.class.getName(), configurationAdmin, null);
+
+ expect(configurationAdmin.getConfiguration("org.eclipse.virgo.medic", null)).andReturn(configuration).times(times);
+ expect(configuration.getProperties()).andReturn(properties).times(times);
+
+ replay(configurationAdmin, configuration);
+
+ return serviceRegistration;
+ }
+
+ private boolean checkForJULConsoleHandler() {
+ Logger rootLogger = Logger.getLogger("");
+ Handler[] handlers = rootLogger.getHandlers();
+ for (Handler handler : handlers) {
+ if (handler instanceof ConsoleHandler) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+}
diff --git a/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/impl/config/ConfigurationAdminConfigurationProviderTests.java b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/impl/config/ConfigurationAdminConfigurationProviderTests.java
index 5ecc0a8..1d96963 100644
--- a/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/impl/config/ConfigurationAdminConfigurationProviderTests.java
+++ b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/impl/config/ConfigurationAdminConfigurationProviderTests.java
@@ -11,33 +11,32 @@
package org.eclipse.virgo.medic.impl.config;
-import static org.easymock.EasyMock.createMock;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.replay;
-import static org.easymock.EasyMock.verify;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
+import org.eclipse.virgo.teststubs.osgi.framework.StubBundleContext;
+import org.junit.Test;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.cm.ConfigurationEvent;
import java.io.IOException;
import java.util.Dictionary;
import java.util.Hashtable;
-import org.junit.Test;
-import org.osgi.service.cm.Configuration;
-import org.osgi.service.cm.ConfigurationAdmin;
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
-import org.eclipse.virgo.medic.impl.config.ConfigurationAdminConfigurationProvider;
-import org.eclipse.virgo.medic.impl.config.ConfigurationProvider;
-import org.eclipse.virgo.teststubs.osgi.framework.StubBundleContext;
+public class ConfigurationAdminConfigurationProviderTests implements ConfigurationChangeListener {
+
+ private static final String CONFIG_ADMIN_PID = "org.eclipse.virgo.medic";
-public class ConfigurationAdminConfigurationProviderTests {
+ private final StubBundleContext bundleContext = new StubBundleContext();
- private final StubBundleContext bundleContext = new StubBundleContext();
+ private int notificationCount;
@Test
@SuppressWarnings("unchecked")
public void getConfigurationWithoutConfigurationAdmin() {
- ConfigurationProvider configurationProvider = new ConfigurationAdminConfigurationProvider(bundleContext);
+ ConfigurationProvider configurationProvider = new ConfigurationAdminConfigurationProvider(bundleContext);
Dictionary configuration = configurationProvider.getConfiguration();
assertNotNull(configuration);
assertEquals(".", configuration.get(ConfigurationProvider.KEY_DUMP_ROOT_DIRECTORY));
@@ -54,7 +53,7 @@ public class ConfigurationAdminConfigurationProviderTests {
expect(configuration.getProperties()).andReturn(null);
replay(configurationAdmin, configuration);
-
+
ConfigurationProvider configurationProvider = new ConfigurationAdminConfigurationProvider(bundleContext);
Dictionary configDictionary = configurationProvider.getConfiguration();
@@ -70,14 +69,10 @@ public class ConfigurationAdminConfigurationProviderTests {
ConfigurationAdmin configurationAdmin = createMock(ConfigurationAdmin.class);
Configuration configuration = createMock(Configuration.class);
- this.bundleContext.registerService(ConfigurationAdmin.class.getName(), configurationAdmin, null);
Dictionary properties = new Hashtable();
properties.put(ConfigurationProvider.KEY_DUMP_ROOT_DIRECTORY, "target");
properties.put("a.b.c", "d.e.f");
- expect(configurationAdmin.getConfiguration("org.eclipse.virgo.medic", null)).andReturn(configuration);
- expect(configuration.getProperties()).andReturn(properties);
-
- replay(configurationAdmin, configuration);
+ createConfigurationMocks(configurationAdmin, configuration, properties, 1);
ConfigurationProvider configurationProvider = new ConfigurationAdminConfigurationProvider(bundleContext);
Dictionary configDictionary = configurationProvider.getConfiguration();
@@ -87,4 +82,98 @@ public class ConfigurationAdminConfigurationProviderTests {
verify(configurationAdmin, configuration);
}
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void configurationListenerNotification() throws IOException {
+ ConfigurationAdmin configurationAdmin = createMock(ConfigurationAdmin.class);
+ Configuration configuration = createMock(Configuration.class);
+
+ Dictionary properties = new Hashtable();
+ properties.put(ConfigurationProvider.KEY_DUMP_ROOT_DIRECTORY, "target");
+ properties.put("a.b.c", "d.e.f");
+ ServiceRegistration serviceRegistration = createConfigurationMocks(configurationAdmin, configuration, properties, 5);
+
+ ConfigurationAdminConfigurationProvider configurationProvider = new ConfigurationAdminConfigurationProvider(bundleContext);
+ ConfigurationEvent event = new ConfigurationEvent(serviceRegistration.getReference(), ConfigurationEvent.CM_UPDATED, null, CONFIG_ADMIN_PID);
+
+ notificationCount = 0;
+
+ updateConfigurationAndCheckForNotification(configurationProvider, event, 0);
+
+ configurationProvider.addChangeListener(this);
+ updateConfigurationAndCheckForNotification(configurationProvider, event, 1);
+
+ updateConfigurationAndCheckForNotification(configurationProvider, event, 2);
+
+ configurationProvider.removeChangeListener(this);
+ updateConfigurationAndCheckForNotification(configurationProvider, event, 2);
+
+ verify(configurationAdmin, configuration);
+ }
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void configurationChange() throws IOException {
+ ConfigurationAdmin configurationAdmin = createMock(ConfigurationAdmin.class);
+ Configuration configuration = createMock(Configuration.class);
+
+ Dictionary properties = new Hashtable();
+ properties.put(ConfigurationProvider.KEY_DUMP_ROOT_DIRECTORY, "target");
+ properties.put("a.b.c", "d.e.f");
+ ServiceRegistration serviceRegistration = createConfigurationMocks(configurationAdmin, configuration, properties, 2);
+
+ // Initial configuration publishing
+ ConfigurationAdminConfigurationProvider configurationProvider = new ConfigurationAdminConfigurationProvider(bundleContext);
+ ConfigurationEvent event = new ConfigurationEvent(serviceRegistration.getReference(), ConfigurationEvent.CM_UPDATED, null, CONFIG_ADMIN_PID);
+
+ notificationCount = 0;
+
+ configurationProvider.addChangeListener(this);
+ updateConfigurationAndCheckForNotification(configurationProvider, event, 1);
+
+ verify(configurationAdmin, configuration);
+
+ // Update the configuration
+ Dictionary newProperties = new Hashtable((Hashtable) properties);
+ newProperties.put("1.2.3", "4.5.6");
+
+ reset(configurationAdmin, configuration);
+
+ serviceRegistration = createConfigurationMocks(configurationAdmin, configuration, newProperties, 1);
+ event = new ConfigurationEvent(serviceRegistration.getReference(), ConfigurationEvent.CM_UPDATED, null, CONFIG_ADMIN_PID);
+
+ // Trigger change event
+ configurationProvider.addChangeListener(this);
+ updateConfigurationAndCheckForNotification(configurationProvider, event, 2);
+
+ Dictionary configDictionary = configurationProvider.getConfiguration();
+ assertNotNull(configDictionary);
+ assertEquals("target", configDictionary.get(ConfigurationProvider.KEY_DUMP_ROOT_DIRECTORY));
+ assertEquals("d.e.f", configDictionary.get("a.b.c"));
+ assertEquals("4.5.6", configDictionary.get("1.2.3"));
+
+ verify(configurationAdmin, configuration);
+ }
+
+ private ServiceRegistration createConfigurationMocks(ConfigurationAdmin configurationAdmin, Configuration configuration, Dictionary properties, int times) throws IOException {
+ ServiceRegistration serviceRegistration = this.bundleContext.registerService(ConfigurationAdmin.class.getName(), configurationAdmin, null);
+
+ expect(configurationAdmin.getConfiguration("org.eclipse.virgo.medic", null)).andReturn(configuration).times(times);
+ expect(configuration.getProperties()).andReturn(properties).times(times);
+
+ replay(configurationAdmin, configuration);
+
+ return serviceRegistration;
+ }
+
+ private void updateConfigurationAndCheckForNotification(ConfigurationAdminConfigurationProvider configurationProvider, ConfigurationEvent event, int count) {
+ configurationProvider.configurationEvent(event);
+ assertEquals(count, notificationCount);
+ }
+
+ @Override
+ public void configurationChanged(ConfigurationProvider configurationProvider) {
+ this.notificationCount++;
+ }
}
diff --git a/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/log/impl/LoggingPrintStreamWrapperTests.java b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/log/impl/LoggingPrintStreamWrapperTests.java
index eb13b49..ec588f7 100644
--- a/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/log/impl/LoggingPrintStreamWrapperTests.java
+++ b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/log/impl/LoggingPrintStreamWrapperTests.java
@@ -20,6 +20,7 @@ import java.util.List;
import java.util.Locale;
import java.util.Properties;
+import org.eclipse.virgo.medic.impl.config.ConfigurationChangeListener;
import org.eclipse.virgo.medic.impl.config.ConfigurationProvider;
import org.eclipse.virgo.medic.log.impl.ExecutionStackAccessor;
import org.eclipse.virgo.medic.log.impl.LoggingPrintStreamWrapper;
@@ -30,18 +31,17 @@ import org.junit.Test;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.spi.LoggingEvent;
-
public class LoggingPrintStreamWrapperTests {
-
+
private PrintStream wrapper;
@Test
public void test() {
produceOutput(this.wrapper);
-
+
List<LoggingEvent> loggingEvents = CapturingAppender.getAndResetLoggingEvents();
assertEquals(22, loggingEvents.size());
-
+
assertEquals("abcdefghij", loggingEvents.get(0).getMessage());
assertEquals("Three strings", loggingEvents.get(1).getMessage());
assertEquals("last one on a new line.", loggingEvents.get(2).getMessage());
@@ -65,24 +65,24 @@ public class LoggingPrintStreamWrapperTests {
assertEquals("A string with a", loggingEvents.get(20).getMessage());
assertEquals("new line in it.", loggingEvents.get(21).getMessage());
}
-
+
@Test
- public void testOutputWithinLoggingCode() {
+ public void testOutputWithinLoggingCode() {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
- PrintStream printStream = new PrintStream(baos);
+ PrintStream printStream = new PrintStream(baos);
PrintStream wrapper = new LoggingPrintStreamWrapper(printStream, getClass().getName(), new ExecutionStackAccessor() {
-
+
public Class<?>[] getExecutionStack() {
return new Class[] {Logger.class};
}
}, new StubConfigurationProvider(), "theProperty");
-
+
produceOutput(wrapper);
-
+
List<LoggingEvent> loggingEvents = CapturingAppender.getAndResetLoggingEvents();
assertEquals(0, loggingEvents.size());
}
-
+
private void produceOutput(PrintStream printStream) {
printStream.append('a');
printStream.append("bcd");
@@ -113,49 +113,49 @@ public class LoggingPrintStreamWrapperTests {
printStream.println(new Object() {@Override public String toString() { return "toString";}});
printStream.println("A string with a\nnew line in it.");
}
-
+
@Test
- public void testByteArrayHandling() {
+ public void testByteArrayHandling() {
String string = "Some text to be turned into bytes.";
String stringWithNewLine = string + "\n";
byte[] stringBytes = stringWithNewLine.getBytes();
-
- wrapper.write(stringBytes, 0, stringBytes.length);
-
+
+ wrapper.write(stringBytes, 0, stringBytes.length);
+
List<LoggingEvent> loggingEvents = CapturingAppender.getAndResetLoggingEvents();
assertEquals(1, loggingEvents.size());
-
+
assertEquals("Some text to be turned into bytes.", loggingEvents.get(0).getMessage());
}
-
+
@Test
- public void testSingleByteHandling() {
+ public void testSingleByteHandling() {
String string = "Some text to be turned into bytes.";
byte[] stringBytes = string.getBytes();
-
+
for (byte b: stringBytes) {
wrapper.write(b);
}
wrapper.println();
-
+
List<LoggingEvent> loggingEvents = CapturingAppender.getAndResetLoggingEvents();
assertEquals(1, loggingEvents.size());
-
+
assertEquals("Some text to be turned into bytes.", loggingEvents.get(0).getMessage());
}
-
+
@Test
public void testPrintNullString(){
-
+
String imNull = null;
-
+
wrapper.println(imNull);
wrapper.print(imNull);
wrapper.println();
-
+
List<LoggingEvent> loggingEvents = CapturingAppender.getAndResetLoggingEvents();
assertEquals(2, loggingEvents.size());
-
+
assertEquals("null", loggingEvents.get(0).getMessage());
assertEquals("null", loggingEvents.get(1).getMessage());
}
@@ -166,11 +166,11 @@ public class LoggingPrintStreamWrapperTests {
PrintStream printStream = new PrintStream(baos);
this.wrapper = new LoggingPrintStreamWrapper(printStream, getClass().getName(), new SecurityManagerExecutionStackAccessor(), new StubConfigurationProvider(), "theProperty");
}
-
+
private final class StubConfigurationProvider implements ConfigurationProvider {
-
+
private final Properties configuration;
-
+
private StubConfigurationProvider() {
this.configuration = new Properties();
this.configuration.setProperty("theProperty", "true");
@@ -179,6 +179,15 @@ public class LoggingPrintStreamWrapperTests {
@SuppressWarnings("unchecked")
public Dictionary getConfiguration() {
return this.configuration;
- }
+ }
+
+ public void addChangeListener(ConfigurationChangeListener listener) {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean removeChangeListener(ConfigurationChangeListener listener) {
+ throw new UnsupportedOperationException();
+ }
+
}
}

Back to the top