Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore6
-rw-r--r--build-medic/build.xml22
-rw-r--r--build.properties13
-rw-r--r--build.versions13
-rw-r--r--org.eclipse.virgo.ch.qos.logback.classic.woven/build.xml11
-rw-r--r--org.eclipse.virgo.ch.qos.logback.classic.woven/ivy.xml27
-rw-r--r--org.eclipse.virgo.ch.qos.logback.classic.woven/src/main/java/.gitignore0
-rw-r--r--org.eclipse.virgo.ch.qos.logback.classic.woven/src/main/resources/.gitignore0
-rw-r--r--org.eclipse.virgo.ch.qos.logback.classic.woven/src/test/java/.gitignore0
-rw-r--r--org.eclipse.virgo.ch.qos.logback.classic.woven/src/test/resources/.gitignore0
-rw-r--r--org.eclipse.virgo.medic.core/.classpath38
-rw-r--r--org.eclipse.virgo.medic.core/.project36
-rw-r--r--org.eclipse.virgo.medic.core/.settings/com.springsource.server.ide.bundlor.core.prefs5
-rw-r--r--org.eclipse.virgo.medic.core/.settings/org.springframework.ide.eclipse.core.prefs67
-rw-r--r--org.eclipse.virgo.medic.core/.springBeans13
-rw-r--r--org.eclipse.virgo.medic.core/build.xml9
-rw-r--r--org.eclipse.virgo.medic.core/ivy.xml36
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/DumpContributorPublisher.java68
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/DumpContributorResolver.java24
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/DumpContributorTracker.java50
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/StandardDump.java84
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/StandardDumpContributorResolver.java41
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/StandardDumpGenerator.java172
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/heap/HeapDumpContributor.java75
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/logback/LogDumpContributor.java188
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/summary/SummaryDumpContributor.java73
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/thread/Java5ThreadInfoWriter.java41
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/thread/Java5ThreadMXBeanDelegate.java51
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/thread/StandardThreadInfoWriter.java53
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/thread/StandardThreadMXBeanDelegate.java34
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/thread/ThreadDumpContributor.java87
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/thread/ThreadInfoWriter.java37
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/thread/ThreadMXBeanDelegate.java49
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/eventlog/impl/BundleSearchingPropertyResourceBundleResolver.java49
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/eventlog/impl/EventLoggerServiceFactory.java34
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/eventlog/impl/LocaleResolver.java30
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/eventlog/impl/MessageResolver.java40
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/eventlog/impl/PropertyResourceBundleResolver.java22
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/eventlog/impl/ResourceBundleUtils.java58
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/eventlog/impl/StandardLocaleResolver.java21
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/eventlog/impl/StandardMessageResolver.java73
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/eventlog/impl/logback/LogBackEventLogger.java103
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/eventlog/impl/logback/LogBackEventLoggerFactory.java42
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/impl/MedicActivator.java272
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/impl/MedicLogEvents.java41
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/impl/config/ConfigurationAdminConfigurationProvider.java103
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/impl/config/ConfigurationProvider.java32
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/impl/config/DictionaryUtils.java28
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/CallingBundleResolver.java24
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/ClassSelector.java17
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/ExecutionStackAccessor.java23
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/LoggingLevel.java24
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/LoggingPrintStreamWrapper.java506
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/PackageNameFilteringClassSelector.java33
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/SecurityManagerExecutionStackAccessor.java24
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/StandardCallingBundleResolver.java36
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/StandardDelegatingPrintStream.java201
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/config/BundleResourceConfigurationLocator.java46
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/config/CompositeConfigurationLocator.java38
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/config/ConfigurationLocator.java21
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/config/ServiceReferenceUtils.java29
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/config/ServiceRegistryConfigurationLocator.java53
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/config/StandardLoggingConfiguration.java83
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/config/StandardLoggingConfigurationPublisher.java55
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/logback/ContextSelectorDelegate.java29
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/logback/DelegatingContextSelector.java92
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/logback/JoranLoggerContextConfigurer.java53
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/logback/LoggerContextConfigurationFailedException.java25
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/logback/LoggerContextConfigurer.java22
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/logback/StandardContextSelectorDelegate.java147
-rw-r--r--org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/logback/ReroutingAwareConsoleAppender.java42
-rw-r--r--org.eclipse.virgo.medic.core/src/main/resources/EventLogMessages_en.properties3
-rw-r--r--org.eclipse.virgo.medic.core/src/main/resources/logback-default.xml39
-rw-r--r--org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/dump/impl/DumpContributorTrackerTests.java46
-rw-r--r--org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/dump/impl/HeapDumpContributorTests.java66
-rw-r--r--org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/dump/impl/StandardDumpGeneratorTests.java147
-rw-r--r--org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/dump/impl/StubDump.java81
-rw-r--r--org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/dump/impl/logback/LogDumpContributorTests.java126
-rw-r--r--org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/dump/impl/logback/StubDump.java81
-rw-r--r--org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/dump/impl/summary/SummaryDumpContributorTests.java147
-rw-r--r--org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/dump/impl/thread/ThreadDumpContributorTests.java55
-rw-r--r--org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/eventlog/impl/BundleSearchingPropertyResourceBundleResolverTests.java89
-rw-r--r--org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/eventlog/impl/ResourceBundleUtilsTests.java105
-rw-r--r--org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/eventlog/impl/StandardLocaleResolverTests.java27
-rw-r--r--org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/eventlog/impl/StandardMessageResolverTests.java80
-rw-r--r--org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/eventlog/impl/logback/DefaultOutputAppender.java34
-rw-r--r--org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/eventlog/impl/logback/LocalizedOutputAppender.java34
-rw-r--r--org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/eventlog/impl/logback/LogBackEventLoggerTests.java122
-rw-r--r--org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/impl/MedicActivatorTests.java77
-rw-r--r--org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/impl/config/ConfigurationAdminConfigurationProviderTests.java90
-rw-r--r--org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/impl/config/DictionaryUtilsTests.java58
-rw-r--r--org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/log/impl/CapturingAppender.java34
-rw-r--r--org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/log/impl/LoggingPrintStreamWrapperTests.java184
-rw-r--r--org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/log/impl/PackageNameFilteringClassSelectorTests.java44
-rw-r--r--org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/log/impl/SecurityManagerExecutionStackAccessorTests.java32
-rw-r--r--org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/log/impl/StandardDelegatingPrintStreamTests.java241
-rw-r--r--org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/log/impl/config/BundleResourceConfigurationLocatorTests.java55
-rw-r--r--org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/log/impl/config/CompositeConfigurationLocatorTests.java67
-rw-r--r--org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/log/impl/config/ServiceRegistryConfigurationLocatorTests.java87
-rw-r--r--org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/log/impl/config/StandardLoggingConfigurationPublisherTests.java38
-rw-r--r--org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/log/impl/logback/DelegatingContextSelectorTests.java135
-rw-r--r--org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/log/impl/logback/JoranLoggerContextConfigurerTests.java69
-rw-r--r--org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/log/impl/logback/StandardContextSelectorTests.java91
-rw-r--r--org.eclipse.virgo.medic.core/src/test/resources/.gitignore0
-rw-r--r--org.eclipse.virgo.medic.core/src/test/resources/logback-test.xml50
-rw-r--r--org.eclipse.virgo.medic.core/src/test/resources/logback.xml16
-rw-r--r--org.eclipse.virgo.medic.core/src/test/resources/messages.properties1
-rw-r--r--org.eclipse.virgo.medic.core/template.mf30
-rw-r--r--org.eclipse.virgo.medic.integrationtest/.classpath39
-rw-r--r--org.eclipse.virgo.medic.integrationtest/.project36
-rw-r--r--org.eclipse.virgo.medic.integrationtest/.settings/com.springsource.server.ide.bundlor.core.prefs5
-rw-r--r--org.eclipse.virgo.medic.integrationtest/.springBeans13
-rw-r--r--org.eclipse.virgo.medic.integrationtest/build.xml8
-rw-r--r--org.eclipse.virgo.medic.integrationtest/ivy.xml33
-rw-r--r--org.eclipse.virgo.medic.integrationtest/src/main/java/.gitignore0
-rw-r--r--org.eclipse.virgo.medic.integrationtest/src/main/java/test/TestClass.java37
-rw-r--r--org.eclipse.virgo.medic.integrationtest/src/main/resources/.gitignore0
-rw-r--r--org.eclipse.virgo.medic.integrationtest/src/test/java/org/eclipse/virgo/medic/dump/test/DumpIntegrationTests.java180
-rw-r--r--org.eclipse.virgo.medic.integrationtest/src/test/java/org/eclipse/virgo/medic/eventlog/test/EventLogIntegrationTests.java115
-rw-r--r--org.eclipse.virgo.medic.integrationtest/src/test/java/org/eclipse/virgo/medic/log/appender/StubAppender.java46
-rw-r--r--org.eclipse.virgo.medic.integrationtest/src/test/java/org/eclipse/virgo/medic/log/test/EntryExitTraceTests.java156
-rw-r--r--org.eclipse.virgo.medic.integrationtest/src/test/java/org/eclipse/virgo/medic/log/test/MedicLoggingIntegrationTests.java55
-rw-r--r--org.eclipse.virgo.medic.integrationtest/src/test/java/org/eclipse/virgo/medic/log/test/PrintStreamWrappingTests.java48
-rw-r--r--org.eclipse.virgo.medic.integrationtest/src/test/resources/EventLogMessages_en.properties1
-rw-r--r--org.eclipse.virgo.medic.integrationtest/src/test/resources/EventLogMessages_it.properties1
-rw-r--r--org.eclipse.virgo.medic.integrationtest/src/test/resources/META-INF/MANIFEST.MF23
-rw-r--r--org.eclipse.virgo.medic.integrationtest/src/test/resources/META-INF/test.config.properties18
-rw-r--r--org.eclipse.virgo.medic.integrationtest/src/test/resources/appender-fragment/META-INF/MANIFEST.MF6
-rw-r--r--org.eclipse.virgo.medic.integrationtest/src/test/resources/appender-fragment/org/eclipse/virgo/medic/log/appender/StubAppender.classbin0 -> 3436 bytes
-rw-r--r--org.eclipse.virgo.medic.integrationtest/src/test/resources/config-fragment/META-INF/MANIFEST.MF5
-rw-r--r--org.eclipse.virgo.medic.integrationtest/src/test/resources/config-fragment/logback.xml42
-rw-r--r--org.eclipse.virgo.medic.integrationtest/src/test/resources/java6-server.profile165
-rw-r--r--org.eclipse.virgo.medic.integrationtest/src/test/resources/logback-test.xml5
-rw-r--r--org.eclipse.virgo.medic.integrationtest/src/test/resources/message-bundle/EventLogMessages_en.properties1
-rw-r--r--org.eclipse.virgo.medic.integrationtest/src/test/resources/message-bundle/EventLogMessages_it.properties1
-rw-r--r--org.eclipse.virgo.medic.integrationtest/src/test/resources/message-bundle/META-INF/MANIFEST.MF3
-rw-r--r--org.eclipse.virgo.medic.integrationtest/src/test/resources/message-fragment/EventLogMessages.properties1
-rw-r--r--org.eclipse.virgo.medic.integrationtest/src/test/resources/message-fragment/META-INF/MANIFEST.MF5
-rw-r--r--org.eclipse.virgo.medic.integrationtest/src/test/resources/test-bundle_1/META-INF/MANIFEST.MF6
-rw-r--r--org.eclipse.virgo.medic.integrationtest/src/test/resources/test-bundle_1/logback.xml15
-rw-r--r--org.eclipse.virgo.medic.integrationtest/src/test/resources/test-bundle_1/test/TestActivator.classbin0 -> 798 bytes
-rw-r--r--org.eclipse.virgo.medic.integrationtest/src/test/resources/test-bundle_2/META-INF/MANIFEST.MF6
-rw-r--r--org.eclipse.virgo.medic.integrationtest/src/test/resources/test-bundle_2/logback.xml15
-rw-r--r--org.eclipse.virgo.medic.integrationtest/src/test/resources/test-bundle_2/test/TestActivator.classbin0 -> 798 bytes
-rw-r--r--org.eclipse.virgo.medic.integrationtest/src/test/resources/test-bundle_3/META-INF/MANIFEST.MF6
-rw-r--r--org.eclipse.virgo.medic.integrationtest/src/test/resources/test-bundle_3/test/TestActivator.classbin0 -> 798 bytes
-rw-r--r--org.eclipse.virgo.medic.integrationtest/template.mf15
-rw-r--r--org.eclipse.virgo.medic.test/.classpath27
-rw-r--r--org.eclipse.virgo.medic.test/.project35
-rw-r--r--org.eclipse.virgo.medic.test/.settings/com.springsource.server.ide.bundlor.core.prefs5
-rw-r--r--org.eclipse.virgo.medic.test/.settings/org.eclipse.wst.common.project.facet.core.xml4
-rw-r--r--org.eclipse.virgo.medic.test/.springBeans13
-rw-r--r--org.eclipse.virgo.medic.test/build.xml8
-rw-r--r--org.eclipse.virgo.medic.test/ivy.xml24
-rw-r--r--org.eclipse.virgo.medic.test/src/main/java/org/eclipse/virgo/medic/test/eventlog/LoggedEvent.java105
-rw-r--r--org.eclipse.virgo.medic.test/src/main/java/org/eclipse/virgo/medic/test/eventlog/MockEventLogger.java164
-rw-r--r--org.eclipse.virgo.medic.test/src/main/resources/.gitignore0
-rw-r--r--org.eclipse.virgo.medic.test/src/test/java/org/eclipse/virgo/medic/test/eventlog/LoggedEventTests.java77
-rw-r--r--org.eclipse.virgo.medic.test/src/test/java/org/eclipse/virgo/medic/test/eventlog/MockEventLoggerTests.java168
-rw-r--r--org.eclipse.virgo.medic.test/src/test/resources/.gitignore0
-rw-r--r--org.eclipse.virgo.medic.test/template.mf10
-rw-r--r--org.eclipse.virgo.medic.testfragment/.classpath28
-rw-r--r--org.eclipse.virgo.medic.testfragment/.project36
-rw-r--r--org.eclipse.virgo.medic.testfragment/.settings/com.springsource.server.ide.bundlor.core.prefs5
-rw-r--r--org.eclipse.virgo.medic.testfragment/.settings/org.eclipse.wst.common.project.facet.core.xml4
-rw-r--r--org.eclipse.virgo.medic.testfragment/.springBeans13
-rw-r--r--org.eclipse.virgo.medic.testfragment/build.xml10
-rw-r--r--org.eclipse.virgo.medic.testfragment/ivy.xml25
-rw-r--r--org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/dump/Dump.java83
-rw-r--r--org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/dump/DumpContributionFailedException.java46
-rw-r--r--org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/dump/DumpContributor.java39
-rw-r--r--org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/dump/DumpGenerationFailedException.java46
-rw-r--r--org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/dump/DumpGenerator.java51
-rw-r--r--org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/dump/JmxDumpContributionParticipant.java34
-rw-r--r--org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/eventlog/EventLogger.java86
-rw-r--r--org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/eventlog/EventLoggerFactory.java36
-rw-r--r--org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/eventlog/Level.java16
-rw-r--r--org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/eventlog/LogEvent.java38
-rw-r--r--org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/log/ConfigurationPublicationFailedException.java30
-rw-r--r--org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/log/DelegatingPrintStream.java34
-rw-r--r--org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/log/EntryExitTrace.aj95
-rw-r--r--org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/log/LoggingConfiguration.java19
-rw-r--r--org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/log/LoggingConfigurationPublisher.java34
-rw-r--r--org.eclipse.virgo.medic.testfragment/src/main/resources/.gitignore0
-rw-r--r--org.eclipse.virgo.medic.testfragment/src/test/java/.gitignore0
-rw-r--r--org.eclipse.virgo.medic.testfragment/src/test/resources/.gitignore0
-rw-r--r--org.eclipse.virgo.medic.testfragment/template.mf13
-rw-r--r--org.eclipse.virgo.medic.weaving/.classpath32
-rw-r--r--org.eclipse.virgo.medic.weaving/.project36
-rw-r--r--org.eclipse.virgo.medic.weaving/.settings/com.springsource.server.ide.bundlor.core.prefs5
-rw-r--r--org.eclipse.virgo.medic.weaving/.settings/org.springframework.ide.eclipse.core.prefs67
-rw-r--r--org.eclipse.virgo.medic.weaving/.springBeans13
-rw-r--r--org.eclipse.virgo.medic.weaving/build.xml12
-rw-r--r--org.eclipse.virgo.medic.weaving/ivy.xml30
-rw-r--r--org.eclipse.virgo.medic.weaving/src/main/java/org/eclipse/virgo/medic/log/impl/logback/LoggingInterceptor.aj67
-rw-r--r--org.eclipse.virgo.medic.weaving/src/main/java/org/eclipse/virgo/medic/log/impl/logback/LoggingListener.java26
-rw-r--r--org.eclipse.virgo.medic.weaving/src/main/java/org/eclipse/virgo/medic/log/impl/logback/NoOpLoggingListener.java33
-rw-r--r--org.eclipse.virgo.medic.weaving/src/main/resources/.gitignore0
-rw-r--r--org.eclipse.virgo.medic.weaving/src/test/java/.gitignore0
-rw-r--r--org.eclipse.virgo.medic.weaving/src/test/resources/.gitignore0
-rw-r--r--org.eclipse.virgo.medic/.classpath28
-rw-r--r--org.eclipse.virgo.medic/.project36
-rw-r--r--org.eclipse.virgo.medic/.settings/com.springsource.server.ide.bundlor.core.prefs5
-rw-r--r--org.eclipse.virgo.medic/.settings/org.eclipse.wst.common.project.facet.core.xml4
-rw-r--r--org.eclipse.virgo.medic/.settings/org.springframework.ide.eclipse.core.prefs68
-rw-r--r--org.eclipse.virgo.medic/.springBeans13
-rw-r--r--org.eclipse.virgo.medic/build.xml10
-rw-r--r--org.eclipse.virgo.medic/ivy.xml25
-rw-r--r--org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/dump/Dump.java83
-rw-r--r--org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/dump/DumpContributionFailedException.java46
-rw-r--r--org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/dump/DumpContributor.java39
-rw-r--r--org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/dump/DumpGenerationFailedException.java46
-rw-r--r--org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/dump/DumpGenerator.java52
-rw-r--r--org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/eventlog/EventLogger.java86
-rw-r--r--org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/eventlog/EventLoggerFactory.java36
-rw-r--r--org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/eventlog/Level.java16
-rw-r--r--org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/eventlog/LogEvent.java38
-rw-r--r--org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/log/ConfigurationPublicationFailedException.java30
-rw-r--r--org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/log/DelegatingPrintStream.java34
-rw-r--r--org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/log/EntryExitTrace.aj99
-rw-r--r--org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/log/LoggingConfiguration.java19
-rw-r--r--org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/log/LoggingConfigurationPublisher.java34
-rw-r--r--org.eclipse.virgo.medic/src/main/resources/.gitignore0
-rw-r--r--org.eclipse.virgo.medic/src/test/java/.gitignore0
-rw-r--r--org.eclipse.virgo.medic/src/test/resources/.gitignore0
-rw-r--r--org.eclipse.virgo.medic/template.mf11
226 files changed, 10426 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..fa91ebf
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,6 @@
+*/src/main/resources/META-INF/MANIFEST.MF
+*/src/test/resources/META-INF/TEST.MF
+integration-repo
+ivy-cache
+target
+serviceability
diff --git a/build-medic/build.xml b/build-medic/build.xml
new file mode 100644
index 0000000..678f857
--- /dev/null
+++ b/build-medic/build.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="build-medic">
+
+ <path id="bundles">
+ <pathelement location="../org.eclipse.virgo.medic"/>
+ <pathelement location="../org.eclipse.virgo.medic.weaving"/>
+ <pathelement location="../org.eclipse.virgo.ch.qos.logback.classic.woven"/>
+ <pathelement location="../org.eclipse.virgo.medic.core"/>
+ <pathelement location="../org.eclipse.virgo.medic.test"/>
+ <pathelement location="../org.eclipse.virgo.medic.testfragment"/>
+ <pathelement location="../org.eclipse.virgo.medic.integrationtest"/>
+ </path>
+
+ <property file="${basedir}/../build.properties"/>
+ <property file="${basedir}/../build.versions"/>
+
+ <import file="${basedir}/../virgo-build/multi-bundle/default.xml"/>
+
+ <target name="precommit" depends="clean, clean-integration, test, findbugs"
+ description="Performs a CI server-like build, should be run prior to performing a push"/>
+
+</project>
diff --git a/build.properties b/build.properties
new file mode 100644
index 0000000..382e802
--- /dev/null
+++ b/build.properties
@@ -0,0 +1,13 @@
+version=1.0.1
+release.type=integration
+javadoc.exclude.package.names=**/internal/**,**/internal
+ivy.cache=ivy-cache
+ivy.cache.dir=${basedir}/../${ivy.cache}
+integration.repo.dir=${basedir}/../integration-repo
+source.version=1.5
+test.vm.args= -Xmx1024M -XX:MaxPermSize=512M -XX:+HeapDumpOnOutOfMemoryError
+findbugs.enforce=true
+clover.enforce=true
+clover.coverage=80%
+
+#debug string to append to test.vm.args= -Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=y
diff --git a/build.versions b/build.versions
new file mode 100644
index 0000000..0df543e
--- /dev/null
+++ b/build.versions
@@ -0,0 +1,13 @@
+# Compile
+ch.qos.logback=0.9.18
+org.slf4j=1.5.10
+org.eclipse.osgi=3.5.1.R35x_v20091005
+org.apache.felix.configadmin=1.2.4
+org.aspectj=1.6.6.RELEASE
+
+# Test
+org.junit=4.7.0
+org.easymock=2.3.0
+org.eclipse.virgo.test=2.1.0.D-20100420091951
+org.eclipse.virgo.teststubs=1.0.0.D-20100420091314
+org.eclipse.virgo.util=2.1.0.D-20100420091708
diff --git a/org.eclipse.virgo.ch.qos.logback.classic.woven/build.xml b/org.eclipse.virgo.ch.qos.logback.classic.woven/build.xml
new file mode 100644
index 0000000..b5d9549
--- /dev/null
+++ b/org.eclipse.virgo.ch.qos.logback.classic.woven/build.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="org.eclipse.virgo.ch.qos.logback.classic.woven">
+
+ <property name="disable.bundlor" value="true"/>
+ <property name="clover.enforce" value="false"/>
+
+ <property file="${basedir}/../build.properties" />
+ <property file="${basedir}/../build.versions" />
+
+ <import file="${basedir}/../virgo-build/weaving-external/default.xml" />
+</project>
diff --git a/org.eclipse.virgo.ch.qos.logback.classic.woven/ivy.xml b/org.eclipse.virgo.ch.qos.logback.classic.woven/ivy.xml
new file mode 100644
index 0000000..bcf6d9d
--- /dev/null
+++ b/org.eclipse.virgo.ch.qos.logback.classic.woven/ivy.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?xml-stylesheet type="text/xsl" href="http://ivyrep.jayasoft.org/ivy-doc.xsl"?>
+<ivy-module
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="http://incubator.apache.org/ivy/schemas/ivy.xsd"
+ version="1.3">
+
+ <info organisation="org.eclipse.virgo.medic" module="${ant.project.name}" />
+
+ <configurations>
+ <include file="${virgo.build.dir}/common/default-ivy-configurations.xml"/>
+ <conf name="bundleclasspath" description="Dependencies to be packaged within the bundle"/>
+ </configurations>
+
+ <publications>
+ <artifact name="${ant.project.name}"/>
+ <artifact name="${ant.project.name}-sources" type="src" ext="jar"/>
+ </publications>
+
+ <dependencies>
+ <dependency org="ch.qos.logback" name="com.springsource.ch.qos.logback.classic" rev="${ch.qos.logback}" conf="external->runtime"/>
+ <dependency org="org.aspectj" name="com.springsource.org.aspectj.runtime" rev="${org.aspectj}" conf="aspects->runtime"/>
+ <dependency org="org.eclipse.virgo.medic" name="org.eclipse.virgo.medic.weaving" rev="latest.integration" conf="aspects->compile"/>
+ <exclude org="org.eclipse.virgo.medic" module="org.eclipse.virgo.medic" conf="aspects"/>
+ </dependencies>
+
+</ivy-module>
diff --git a/org.eclipse.virgo.ch.qos.logback.classic.woven/src/main/java/.gitignore b/org.eclipse.virgo.ch.qos.logback.classic.woven/src/main/java/.gitignore
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/org.eclipse.virgo.ch.qos.logback.classic.woven/src/main/java/.gitignore
diff --git a/org.eclipse.virgo.ch.qos.logback.classic.woven/src/main/resources/.gitignore b/org.eclipse.virgo.ch.qos.logback.classic.woven/src/main/resources/.gitignore
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/org.eclipse.virgo.ch.qos.logback.classic.woven/src/main/resources/.gitignore
diff --git a/org.eclipse.virgo.ch.qos.logback.classic.woven/src/test/java/.gitignore b/org.eclipse.virgo.ch.qos.logback.classic.woven/src/test/java/.gitignore
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/org.eclipse.virgo.ch.qos.logback.classic.woven/src/test/java/.gitignore
diff --git a/org.eclipse.virgo.ch.qos.logback.classic.woven/src/test/resources/.gitignore b/org.eclipse.virgo.ch.qos.logback.classic.woven/src/test/resources/.gitignore
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/org.eclipse.virgo.ch.qos.logback.classic.woven/src/test/resources/.gitignore
diff --git a/org.eclipse.virgo.medic.core/.classpath b/org.eclipse.virgo.medic.core/.classpath
new file mode 100644
index 0000000..0ae8c79
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/.classpath
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src/main/java">
+ <attributes>
+ <attribute name="com.springsource.server.ide.jdt.core.test.classpathentry" value="false"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="src" path="src/main/resources">
+ <attributes>
+ <attribute name="com.springsource.server.ide.jdt.core.test.classpathentry" value="false"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="src" output="target/test-classes" path="src/test/java">
+ <attributes>
+ <attribute name="com.springsource.server.ide.jdt.core.test.classpathentry" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="src" output="target/test-classes" path="src/test/resources">
+ <attributes>
+ <attribute name="com.springsource.server.ide.jdt.core.test.classpathentry" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="var" path="MEDIC_IVY_CACHE/org.junit/com.springsource.org.junit/4.7.0/com.springsource.org.junit-4.7.0.jar" sourcepath="/MEDIC_IVY_CACHE/org.junit/com.springsource.org.junit/4.7.0/com.springsource.org.junit-sources-4.7.0.jar"/>
+ <classpathentry kind="var" path="MEDIC_IVY_CACHE/org.eclipse.osgi/org.eclipse.osgi/3.5.1.R35x_v20091005/org.eclipse.osgi-3.5.1.R35x_v20091005.jar" sourcepath="/MEDIC_IVY_CACHE/org.eclipse.osgi/org.eclipse.osgi/3.5.1.R35x_v20091005/org.eclipse.osgi-sources-3.5.1.R35x_v20091005.jar"/>
+ <classpathentry kind="var" path="MEDIC_IVY_CACHE/org.easymock/com.springsource.org.easymock/2.3.0/com.springsource.org.easymock-2.3.0.jar" sourcepath="/MEDIC_IVY_CACHE/org.easymock/com.springsource.org.easymock/2.3.0/com.springsource.org.easymock-sources-2.3.0.jar"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/org.eclipse.virgo.medic"/>
+ <classpathentry kind="var" path="MEDIC_IVY_CACHE/org.apache.felix/org.apache.felix.configadmin/1.2.4/org.apache.felix.configadmin-1.2.4.jar" sourcepath="/MEDIC_IVY_CACHE/org.apache.felix/org.apache.felix.configadmin/1.2.4/org.apache.felix.configadmin-sources-1.2.4.jar"/>
+ <classpathentry kind="var" path="MEDIC_IVY_CACHE/org.eclipse.virgo.teststubs/org.eclipse.virgo.teststubs.osgi/1.0.0.D-20100420091314/org.eclipse.virgo.teststubs.osgi-1.0.0.D-20100420091314.jar" sourcepath="/MEDIC_IVY_CACHE/org.eclipse.virgo.teststubs/org.eclipse.virgo.teststubs.osgi/1.0.0.D-20100420091314/org.eclipse.virgo.teststubs.osgi-sources-1.0.0.D-20100420091314.jar"/>
+ <classpathentry kind="var" path="MEDIC_IVY_CACHE/org.aspectj/com.springsource.org.aspectj.runtime/1.6.6.RELEASE/com.springsource.org.aspectj.runtime-1.6.6.RELEASE.jar" sourcepath="/MEDIC_IVY_CACHE/org.aspectj/com.springsource.org.aspectj.runtime/1.6.6.RELEASE/com.springsource.org.aspectj.runtime-sources-1.6.6.RELEASE.jar"/>
+ <classpathentry kind="var" path="MEDIC_IVY_CACHE/org.slf4j/com.springsource.slf4j.api/1.5.10/com.springsource.slf4j.api-1.5.10.jar" sourcepath="/MEDIC_IVY_CACHE/org.slf4j/com.springsource.slf4j.api/1.5.10/com.springsource.slf4j.api-sources-1.5.10.jar"/>
+ <classpathentry kind="var" path="MEDIC_IVY_CACHE/ch.qos.logback/com.springsource.ch.qos.logback.classic/0.9.18/com.springsource.ch.qos.logback.classic-0.9.18.jar" sourcepath="/MEDIC_IVY_CACHE/ch.qos.logback/com.springsource.ch.qos.logback.classic/0.9.18/com.springsource.ch.qos.logback.classic-sources-0.9.18.jar"/>
+ <classpathentry kind="var" path="MEDIC_IVY_CACHE/ch.qos.logback/com.springsource.ch.qos.logback.core/0.9.18/com.springsource.ch.qos.logback.core-0.9.18.jar" sourcepath="/MEDIC_IVY_CACHE/ch.qos.logback/com.springsource.ch.qos.logback.core/0.9.18/com.springsource.ch.qos.logback.core-sources-0.9.18.jar"/>
+ <classpathentry kind="var" path="MEDIC_IVY_CACHE/org.eclipse.virgo.util/org.eclipse.virgo.util.osgi/2.1.0.D-20100420091708/org.eclipse.virgo.util.osgi-2.1.0.D-20100420091708.jar"/>
+ <classpathentry kind="con" path="org.eclipse.ajdt.core.ASPECTJRT_CONTAINER"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/org.eclipse.virgo.medic.weaving"/>
+ <classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/org.eclipse.virgo.medic.core/.project b/org.eclipse.virgo.medic.core/.project
new file mode 100644
index 0000000..d69168c
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/.project
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.virgo.medic.core</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.wst.common.project.facet.core.builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.ajdt.core.ajbuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.springframework.ide.eclipse.core.springbuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.springsource.server.ide.bundlor.core.builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.ajdt.ui.ajnature</nature>
+ <nature>com.springsource.server.ide.facet.core.bundlenature</nature>
+ <nature>org.springframework.ide.eclipse.core.springnature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.wst.common.project.facet.core.nature</nature>
+ </natures>
+</projectDescription>
diff --git a/org.eclipse.virgo.medic.core/.settings/com.springsource.server.ide.bundlor.core.prefs b/org.eclipse.virgo.medic.core/.settings/com.springsource.server.ide.bundlor.core.prefs
new file mode 100644
index 0000000..84b9c6a
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/.settings/com.springsource.server.ide.bundlor.core.prefs
@@ -0,0 +1,5 @@
+#Thu Nov 12 08:44:12 GMT 2009
+com.springsource.server.ide.bundlor.core.bundlor.generated.manifest.autoformatting=true
+com.springsource.server.ide.bundlor.core.byte.code.scanning=true
+com.springsource.server.ide.bundlor.core.template.properties.files=../build.versions
+eclipse.preferences.version=1
diff --git a/org.eclipse.virgo.medic.core/.settings/org.springframework.ide.eclipse.core.prefs b/org.eclipse.virgo.medic.core/.settings/org.springframework.ide.eclipse.core.prefs
new file mode 100644
index 0000000..00626fc
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/.settings/org.springframework.ide.eclipse.core.prefs
@@ -0,0 +1,67 @@
+#Wed Aug 19 13:16:35 BST 2009
+eclipse.preferences.version=1
+org.springframework.ide.eclipse.core.builders.enable.aopreferencemodelbuilder=true
+org.springframework.ide.eclipse.core.builders.enable.beanmetadatabuilder=true
+org.springframework.ide.eclipse.core.builders.enable.osgibundleupdater=false
+org.springframework.ide.eclipse.core.enable.project.preferences=false
+org.springframework.ide.eclipse.core.validator.enable.com.springsource.server.ide.manifest.core.manifestvalidator=true
+org.springframework.ide.eclipse.core.validator.enable.com.springsource.sts.bestpractices.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.enable.com.springsource.sts.server.quickfix.manifestvalidator=false
+org.springframework.ide.eclipse.core.validator.enable.org.springframework.ide.eclipse.beans.core.beansvalidator=true
+org.springframework.ide.eclipse.core.validator.enable.org.springframework.ide.eclipse.core.springvalidator=false
+org.springframework.ide.eclipse.core.validator.enable.org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.server.ide.manifest.core.applicationSymbolicNameRule-com.springsource.server.ide.manifest.core.manifestvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.server.ide.manifest.core.applicationVersionRule-com.springsource.server.ide.manifest.core.manifestvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.server.ide.manifest.core.bundleActivationPolicyRule-com.springsource.server.ide.manifest.core.manifestvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.server.ide.manifest.core.bundleActivatorRule-com.springsource.server.ide.manifest.core.manifestvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.server.ide.manifest.core.bundleManifestVersionRule-com.springsource.server.ide.manifest.core.manifestvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.server.ide.manifest.core.bundleNameRule-com.springsource.server.ide.manifest.core.manifestvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.server.ide.manifest.core.bundleSymbolicNameRule-com.springsource.server.ide.manifest.core.manifestvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.server.ide.manifest.core.bundleVersionRule-com.springsource.server.ide.manifest.core.manifestvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.server.ide.manifest.core.exportPackageRule-com.springsource.server.ide.manifest.core.manifestvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.server.ide.manifest.core.importRule-com.springsource.server.ide.manifest.core.manifestvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.server.ide.manifest.core.parsingProblemsRule-com.springsource.server.ide.manifest.core.manifestvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.server.ide.manifest.core.requireBundleRule-com.springsource.server.ide.manifest.core.manifestvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.bestpractices.com.springsource.sts.bestpractices.AvoidDriverManagerDataSource-com.springsource.sts.bestpractices.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.bestpractices.com.springsource.sts.bestpractices.ImportElementsAtTopRulee-com.springsource.sts.bestpractices.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.bestpractices.com.springsource.sts.bestpractices.ParentBeanSpecifiesAbstractClassRule-com.springsource.sts.bestpractices.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.bestpractices.com.springsource.sts.bestpractices.RefElementRule-com.springsource.sts.bestpractices.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.bestpractices.com.springsource.sts.bestpractices.TooManyBeansInFileRule-com.springsource.sts.bestpractices.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.bestpractices.com.springsource.sts.bestpractices.UnnecessaryValueElementRule-com.springsource.sts.bestpractices.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.bestpractices.com.springsource.sts.bestpractices.UseBeanInheritance-com.springsource.sts.bestpractices.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.bestpractices.legacyxmlusage.jndiobjectfactory-com.springsource.sts.bestpractices.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.server.quickfix.importBundleVersionRule-com.springsource.sts.server.quickfix.manifestvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.server.quickfix.importLibraryVersionRule-com.springsource.sts.server.quickfix.manifestvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.server.quickfix.importPackageVersionRule-com.springsource.sts.server.quickfix.manifestvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.server.quickfix.requireBundleVersionRule-com.springsource.sts.server.quickfix.manifestvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanAlias-org.springframework.ide.eclipse.beans.core.beansvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanClass-org.springframework.ide.eclipse.beans.core.beansvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanConstructorArgument-org.springframework.ide.eclipse.beans.core.beansvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanDefinition-org.springframework.ide.eclipse.beans.core.beansvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanDefinitionHolder-org.springframework.ide.eclipse.beans.core.beansvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanFactory-org.springframework.ide.eclipse.beans.core.beansvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanInitDestroyMethod-org.springframework.ide.eclipse.beans.core.beansvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanProperty-org.springframework.ide.eclipse.beans.core.beansvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanReference-org.springframework.ide.eclipse.beans.core.beansvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.methodOverride-org.springframework.ide.eclipse.beans.core.beansvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.parsingProblems-org.springframework.ide.eclipse.beans.core.beansvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.requiredProperty-org.springframework.ide.eclipse.beans.core.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.core.springClasspath-org.springframework.ide.eclipse.core.springvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.action-org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.actionstate-org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.attribute-org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.attributemapper-org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.beanaction-org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.evaluationaction-org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.evaluationresult-org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.exceptionhandler-org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.import-org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.inputattribute-org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.mapping-org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.outputattribute-org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.set-org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.state-org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.subflowstate-org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.transition-org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.variable-org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.webflowstate-org.springframework.ide.eclipse.webflow.core.validator=true
diff --git a/org.eclipse.virgo.medic.core/.springBeans b/org.eclipse.virgo.medic.core/.springBeans
new file mode 100644
index 0000000..8ce1035
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/.springBeans
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beansProjectDescription>
+ <version>1</version>
+ <pluginVersion><![CDATA[2.2.5.200906231226-RC1]]></pluginVersion>
+ <configSuffixes>
+ <configSuffix><![CDATA[xml]]></configSuffix>
+ </configSuffixes>
+ <enableImports><![CDATA[false]]></enableImports>
+ <configs>
+ </configs>
+ <configSets>
+ </configSets>
+</beansProjectDescription>
diff --git a/org.eclipse.virgo.medic.core/build.xml b/org.eclipse.virgo.medic.core/build.xml
new file mode 100644
index 0000000..dda91ba
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/build.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="org.eclipse.virgo.medic.core">
+
+ <property file="${basedir}/../build.properties" />
+ <property file="${basedir}/../build.versions" />
+
+ <import file="${basedir}/../virgo-build/aspect/default.xml" />
+
+</project>
diff --git a/org.eclipse.virgo.medic.core/ivy.xml b/org.eclipse.virgo.medic.core/ivy.xml
new file mode 100644
index 0000000..c12b5a3
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/ivy.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?xml-stylesheet type="text/xsl" href="http://ivyrep.jayasoft.org/ivy-doc.xsl"?>
+<ivy-module
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="http://incubator.apache.org/ivy/schemas/ivy.xsd"
+ version="1.3">
+
+ <info organisation="org.eclipse.virgo.medic" module="${ant.project.name}" />
+
+ <configurations>
+ <include file="${virgo.build.dir}/common/default-ivy-configurations.xml"/>
+ </configurations>
+
+ <publications>
+ <artifact name="${ant.project.name}"/>
+ <artifact name="${ant.project.name}-sources" type="src" ext="jar"/>
+ </publications>
+
+ <dependencies>
+ <dependency org="org.eclipse.virgo.medic" name="org.eclipse.virgo.medic" rev="latest.integration" conf="compile->compile"/>
+
+ <dependency org="org.slf4j" name="com.springsource.slf4j.api" rev="${org.slf4j}" conf="compile->runtime"/>
+ <dependency org="org.eclipse.virgo.util" name="org.eclipse.virgo.util.osgi" rev="${org.eclipse.virgo.util}" conf="compile->runtime"/>
+ <dependency org="org.eclipse.virgo.medic" name="org.eclipse.virgo.ch.qos.logback.classic.woven" rev="latest.integration" conf="provided, additional->runtime"/>
+ <dependency org="org.eclipse.virgo.medic" name="org.eclipse.virgo.medic.weaving" rev="latest.integration" conf="provided, additional->runtime"/>
+ <dependency org="ch.qos.logback" name="com.springsource.ch.qos.logback.core" rev="${ch.qos.logback}" conf="provided, additional->runtime"/>
+ <dependency org="org.eclipse.osgi" name="org.eclipse.osgi" rev="${org.eclipse.osgi}" conf="provided->runtime"/>
+
+ <dependency org="org.apache.felix" name="org.apache.felix.configadmin" rev="${org.apache.felix.configadmin}" conf="optional->runtime"/>
+
+ <dependency org="org.junit" name="com.springsource.org.junit" rev="${org.junit}" conf="test->runtime"/>
+ <dependency org="org.easymock" name="com.springsource.org.easymock" rev="${org.easymock}" conf="test->runtime"/>
+ <dependency org="org.eclipse.virgo.teststubs" name="org.eclipse.virgo.teststubs.osgi" rev="${org.eclipse.virgo.teststubs}" conf="test->runtime"/>
+ </dependencies>
+
+</ivy-module>
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/DumpContributorPublisher.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/DumpContributorPublisher.java
new file mode 100644
index 0000000..3fbaa26
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/DumpContributorPublisher.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.dump.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.virgo.medic.dump.DumpContributor;
+import org.eclipse.virgo.medic.dump.impl.heap.HeapDumpContributor;
+import org.eclipse.virgo.medic.dump.impl.logback.LogDumpContributor;
+import org.eclipse.virgo.medic.dump.impl.summary.SummaryDumpContributor;
+import org.eclipse.virgo.medic.dump.impl.thread.ThreadDumpContributor;
+import org.eclipse.virgo.medic.impl.config.ConfigurationProvider;
+import org.eclipse.virgo.medic.log.impl.logback.LoggingInterceptor;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+
+
+public final class DumpContributorPublisher {
+
+ private final List<ServiceRegistration> contributorRegistrations = new ArrayList<ServiceRegistration>();
+
+ private final BundleContext bundleContext;
+
+ private final ConfigurationProvider configurationProvider;
+
+ private final LogDumpContributor logDumpContributor;
+
+ public DumpContributorPublisher(BundleContext bundleContext, ConfigurationProvider configurationProvider) {
+ this.bundleContext = bundleContext;
+ this.configurationProvider = configurationProvider;
+ this.logDumpContributor = new LogDumpContributor(this.configurationProvider);
+ }
+
+ public void publishDumpContributors() {
+ LoggingInterceptor.aspectOf().setLoggingListener(this.logDumpContributor);
+
+ publishDumpContributor(new SummaryDumpContributor());
+ publishDumpContributor(new HeapDumpContributor());
+ publishDumpContributor(new ThreadDumpContributor());
+ publishDumpContributor(this.logDumpContributor);
+ }
+
+ private void publishDumpContributor(DumpContributor dumpContributor) {
+ ServiceRegistration registration = this.bundleContext.registerService(DumpContributor.class.getName(), dumpContributor, null);
+ this.contributorRegistrations.add(registration);
+ }
+
+ public void retractDumpContributors() {
+ for (ServiceRegistration registration : this.contributorRegistrations) {
+ registration.unregister();
+ }
+
+ LoggingInterceptor.aspectOf().setLoggingListener(null);
+ this.logDumpContributor.clear();
+
+ this.contributorRegistrations.clear();
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/DumpContributorResolver.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/DumpContributorResolver.java
new file mode 100644
index 0000000..55f36f9
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/DumpContributorResolver.java
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.dump.impl;
+
+import java.util.List;
+
+import org.eclipse.virgo.medic.dump.DumpContributor;
+
+
+interface DumpContributorResolver {
+
+ List<DumpContributor> getDumpContributors();
+
+ void close();
+}
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/DumpContributorTracker.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/DumpContributorTracker.java
new file mode 100644
index 0000000..a4a4ae5
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/DumpContributorTracker.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.dump.impl;
+
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.eclipse.virgo.medic.dump.DumpContributor;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
+
+
+final class DumpContributorTracker implements ServiceTrackerCustomizer {
+
+ private final List<DumpContributor> contributors = new CopyOnWriteArrayList<DumpContributor>();
+
+ private final BundleContext bundleContext;
+
+ DumpContributorTracker(BundleContext bundleContext) {
+ this.bundleContext = bundleContext;
+ }
+
+ public Object addingService(ServiceReference reference) {
+ Object service = bundleContext.getService(reference);
+ contributors.add((DumpContributor) service);
+ return service;
+ }
+
+ public void modifiedService(ServiceReference reference, Object service) {
+ }
+
+ public void removedService(ServiceReference reference, Object service) {
+ this.contributors.remove(service);
+ this.bundleContext.ungetService(reference);
+ }
+
+ List<DumpContributor> getDumpContributors() {
+ return this.contributors;
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/StandardDump.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/StandardDump.java
new file mode 100644
index 0000000..3dd9500
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/StandardDump.java
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.dump.impl;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.Map;
+
+import org.eclipse.virgo.medic.dump.Dump;
+import org.eclipse.virgo.medic.dump.DumpContributionFailedException;
+
+
+final class StandardDump implements Dump {
+
+ private final File dumpDirectory;
+
+ private final String cause;
+
+ private final Map<String, Object> context;
+
+ private final Throwable[] throwables;
+
+ private final long timestamp;
+
+ StandardDump(String cause, long timestamp, Map<String, Object> context, Throwable[] throwables, File dumpDirectory) {
+ this.cause = cause;
+ this.timestamp = timestamp;
+ this.context = context;
+ this.throwables = throwables;
+ this.dumpDirectory = dumpDirectory;
+ }
+
+ public String getCause() {
+ return this.cause;
+ }
+
+ public Map<String, Object> getContext() {
+ return this.context;
+ }
+
+ public Throwable[] getThrowables() {
+ return this.throwables;
+ }
+
+ public long getTimestamp() {
+ return this.timestamp;
+ }
+
+ public File createFile(String name) {
+ return new File(this.dumpDirectory, name);
+ }
+
+ public FileOutputStream createFileOutputStream(String name) throws DumpContributionFailedException {
+ try {
+ return new FileOutputStream(createFile(name));
+ } catch (FileNotFoundException e) {
+ throw new DumpContributionFailedException("Unable to open output stream '" + name + "'");
+ }
+ }
+
+ public FileWriter createFileWriter(String name) throws DumpContributionFailedException {
+ try {
+ return new FileWriter(createFile(name));
+ } catch (IOException e) {
+ throw new DumpContributionFailedException("Unable to open file writer '" + name + "'");
+ }
+ }
+
+ File getDumpDirectory() {
+ return this.dumpDirectory;
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/StandardDumpContributorResolver.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/StandardDumpContributorResolver.java
new file mode 100644
index 0000000..7ac0cdf
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/StandardDumpContributorResolver.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.dump.impl;
+
+import java.util.List;
+
+import org.eclipse.virgo.medic.dump.DumpContributor;
+import org.osgi.framework.BundleContext;
+import org.osgi.util.tracker.ServiceTracker;
+
+
+public final class StandardDumpContributorResolver implements DumpContributorResolver {
+
+ private final ServiceTracker serviceTracker;
+
+ private final DumpContributorTracker dumpContributorTracker;
+
+ public StandardDumpContributorResolver(BundleContext bundleContext) {
+ this.dumpContributorTracker = new DumpContributorTracker(bundleContext);
+
+ this.serviceTracker = new ServiceTracker(bundleContext, DumpContributor.class.getName(), this.dumpContributorTracker);
+ this.serviceTracker.open();
+ }
+
+ public List<DumpContributor> getDumpContributors() {
+ return this.dumpContributorTracker.getDumpContributors();
+ }
+
+ public void close() {
+ this.serviceTracker.close();
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/StandardDumpGenerator.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/StandardDumpGenerator.java
new file mode 100644
index 0000000..13cbe68
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/StandardDumpGenerator.java
@@ -0,0 +1,172 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.dump.impl;
+
+import java.io.File;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.virgo.medic.dump.DumpContributionFailedException;
+import org.eclipse.virgo.medic.dump.DumpContributor;
+import org.eclipse.virgo.medic.dump.DumpGenerationFailedException;
+import org.eclipse.virgo.medic.dump.DumpGenerator;
+import org.eclipse.virgo.medic.eventlog.EventLogger;
+import org.eclipse.virgo.medic.impl.MedicLogEvents;
+import org.eclipse.virgo.medic.impl.config.ConfigurationProvider;
+
+
+public final class StandardDumpGenerator implements DumpGenerator {
+
+ private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd-HH-mm-SSS");
+
+ private static final Map<String, Object> NO_CONTEXT = new HashMap<String, Object>();
+
+ private final DumpContributorResolver dumpContributorsAccessor;
+
+ private final ConfigurationProvider configurationProvider;
+
+ private final EventLogger eventLogger;
+
+ private String latestDumpId = null;
+
+ public StandardDumpGenerator(DumpContributorResolver accessor, ConfigurationProvider configurationProvider, EventLogger eventLogger) {
+ this.dumpContributorsAccessor = accessor;
+ this.configurationProvider = configurationProvider;
+ this.eventLogger = eventLogger;
+ }
+
+ public void generateDump(String cause, Throwable... throwables) {
+ this.generateDump(cause, NO_CONTEXT, throwables);
+ }
+
+ public void generateDump(String cause, Map<String, Object> context, Throwable... throwables) {
+ StandardDump dump;
+ try {
+ dump = createDump(cause, context, throwables);
+ } catch (DumpGenerationFailedException e) {
+ return;
+ }
+
+ for (DumpContributor dumpContributor : getDumpContributors(cause)) {
+ try {
+ dumpContributor.contribute(dump);
+ } catch (DumpContributionFailedException e) {
+ this.eventLogger.log(MedicLogEvents.CONTRIBUTION_FAILED, e, dumpContributor.getName(), dump.getTimestamp());
+ }
+ }
+
+ this.eventLogger.log(MedicLogEvents.DUMP_GENERATED, dump.getDumpDirectory());
+ }
+
+ private StandardDump createDump(String cause, Map<String, Object> context, Throwable... throwables) throws DumpGenerationFailedException {
+ File dumpDirectory = null;
+
+ long timestamp = System.currentTimeMillis();
+
+ while ((dumpDirectory = getDumpDirectory(timestamp)) == null) {
+ try {
+ Thread.sleep(10);
+ } catch (InterruptedException ie) {
+ ie.printStackTrace();
+ }
+ timestamp = System.currentTimeMillis();
+ }
+
+ return new StandardDump(cause, timestamp, context, throwables, dumpDirectory);
+ }
+
+ @SuppressWarnings("unchecked")
+ private List<DumpContributor> getDumpContributors(String cause) {
+ Dictionary configuration = this.configurationProvider.getConfiguration();
+ String excludedContributorsProperty = (String) configuration.get("dump.exclusions." + cause);
+ List<String> excludedContributors = toList(excludedContributorsProperty);
+ excludedContributorsProperty = (String) configuration.get("dump.exclusions.*");
+ excludedContributors.addAll(toList(excludedContributorsProperty));
+
+ List<DumpContributor> candidateContributors = this.dumpContributorsAccessor.getDumpContributors();
+
+ List<DumpContributor> includedContributors = new ArrayList<DumpContributor>();
+
+ for (DumpContributor candidate : candidateContributors) {
+ if (!excludedContributors.contains(candidate.getName())) {
+ includedContributors.add(candidate);
+ }
+ }
+
+ return includedContributors;
+ }
+
+ private List<String> toList(String property) {
+ List<String> list = new ArrayList<String>();
+ if (property != null) {
+ String[] components = property.split(",");
+ for (String component : components) {
+ String trimmed = component.trim();
+ list.add(trimmed);
+ }
+ }
+ return list;
+ }
+
+ private String getDumpId(long timestamp) {
+ Date date = new Date(timestamp);
+ synchronized (DATE_FORMAT) {
+ String dumpId = DATE_FORMAT.format(date);
+ if (dumpId.equals(latestDumpId)) {
+ dumpId = null;
+ } else {
+ latestDumpId = dumpId;
+ }
+ return dumpId;
+ }
+ }
+
+ private File getDumpDirectory(long timestamp) throws DumpGenerationFailedException {
+ File dumpDirectory = null;
+
+ String dumpId = getDumpId(timestamp);
+
+ if (dumpId != null) {
+ dumpDirectory = new File(getRootDumpDirectory(), dumpId);
+ if (dumpDirectory.exists()) {
+ dumpDirectory = null;
+ } else {
+ createDirectory(dumpDirectory);
+ }
+ }
+
+ return dumpDirectory;
+ }
+
+ @SuppressWarnings("unchecked")
+ private String getRootDumpDirectory() {
+ Dictionary configuration = this.configurationProvider.getConfiguration();
+ return (String) configuration.get(ConfigurationProvider.KEY_DUMP_ROOT_DIRECTORY);
+ }
+
+ private void createDirectory(File file) throws DumpGenerationFailedException {
+ if (!file.mkdirs()) {
+ this.eventLogger.log(MedicLogEvents.DIRECTORY_CREATION_FAILED, file.getAbsolutePath());
+ throw new DumpGenerationFailedException("Directory creation failed");
+ }
+ }
+
+ public void close() {
+ this.dumpContributorsAccessor.close();
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/heap/HeapDumpContributor.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/heap/HeapDumpContributor.java
new file mode 100644
index 0000000..80daccc
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/heap/HeapDumpContributor.java
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.dump.impl.heap;
+
+import java.io.PrintWriter;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import org.eclipse.virgo.medic.dump.Dump;
+import org.eclipse.virgo.medic.dump.DumpContributionFailedException;
+import org.eclipse.virgo.medic.dump.DumpContributor;
+
+
+public final class HeapDumpContributor implements DumpContributor {
+
+ private final Method heapDumpMethod;
+
+ private final Object diagnosticMBean;
+
+ public HeapDumpContributor() {
+
+ Method heapDumpMethod = null;
+ Object diagnosticMBean = null;
+
+ try {
+ Class<?> managementFactoryClass = Class.forName("sun.management.ManagementFactory", true, HeapDumpContributor.class.getClassLoader());
+ Method method = managementFactoryClass.getMethod("getDiagnosticMXBean");
+ diagnosticMBean = method.invoke(null);
+ heapDumpMethod = diagnosticMBean.getClass().getMethod("dumpHeap", String.class, boolean.class);
+ } catch (Exception e) {
+ heapDumpMethod = null;
+ diagnosticMBean = null;
+ }
+
+ this.heapDumpMethod = heapDumpMethod;
+ this.diagnosticMBean = diagnosticMBean;
+ }
+
+ public void contribute(Dump dump) throws DumpContributionFailedException {
+ try {
+ if (this.heapDumpMethod != null && this.diagnosticMBean != null) {
+ heapDumpMethod.invoke(this.diagnosticMBean, dump.createFile("heap.out").getAbsolutePath(), true);
+ } else {
+ PrintWriter writer = null;
+ try {
+ writer = new PrintWriter(dump.createFileWriter("heap.out"));
+ writer.println("Diagnostic MXBean is not available. Heap dump cannot be generated.");
+ } finally {
+ if (writer != null) {
+ writer.close();
+ }
+ }
+ }
+ } catch (InvocationTargetException e) {
+ throw new DumpContributionFailedException("Failed to generate heap dump contribution", e);
+ } catch (IllegalArgumentException e) {
+ throw new DumpContributionFailedException("Failed to generate heap dump contribution", e);
+ } catch (IllegalAccessException e) {
+ throw new DumpContributionFailedException("Failed to generate heap dump contribution", e);
+ }
+ }
+
+ public String getName() {
+ return "heap";
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/logback/LogDumpContributor.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/logback/LogDumpContributor.java
new file mode 100644
index 0000000..ef89636
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/logback/LogDumpContributor.java
@@ -0,0 +1,188 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.dump.impl.logback;
+
+import java.io.PrintWriter;
+import java.util.Dictionary;
+import java.util.List;
+
+import org.eclipse.virgo.medic.dump.Dump;
+import org.eclipse.virgo.medic.dump.DumpContributionFailedException;
+import org.eclipse.virgo.medic.dump.DumpContributor;
+import org.eclipse.virgo.medic.impl.config.ConfigurationProvider;
+import org.eclipse.virgo.medic.log.impl.logback.LoggingListener;
+import org.slf4j.Marker;
+
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.Logger;
+import ch.qos.logback.classic.LoggerContext;
+import ch.qos.logback.classic.PatternLayout;
+import ch.qos.logback.classic.spi.LoggingEvent;
+import ch.qos.logback.core.helpers.CyclicBuffer;
+
+
+/**
+ * A {@link DumpContributor} that stores {@link LoggingEvent LoggingEvents} in a {@link CyclicBuffer} and
+ * when a dump is triggered, writes those entries (a small subset of all that it has seen) to the dump directory.
+ * <p />
+ *
+ * <strong>Concurrent Semantics</strong><br />
+ *
+ * Not threadsafe
+ *
+ */
+public final class LogDumpContributor implements DumpContributor, LoggingListener {
+
+ private static final String DEFAULT_LEVEL = Level.OFF.levelStr;
+
+ private static final String DEFAULT_BUFFER_SIZE = "10000";
+
+ private static final String DEFAULT_PATTERN = "%message%n";
+
+ private static final String FILE_NAME = "log.log";
+
+ private static final String NAME = "log";
+
+ private final CyclicBuffer<LoggingEvent> buffer;
+
+ private final ConfigurationProvider configurationProvider;
+
+ private final Object monitor = new Object();
+
+ @SuppressWarnings("unchecked")
+ public LogDumpContributor(ConfigurationProvider configurationProvider) {
+ this.configurationProvider = configurationProvider;
+
+ Dictionary configDictionary = this.configurationProvider.getConfiguration();
+ this.buffer = new CyclicBuffer<LoggingEvent>(getBufferSize(configDictionary));
+ }
+
+ public String getName() {
+ return NAME;
+ }
+
+ public void contribute(Dump dump) throws DumpContributionFailedException {
+ Level configuredLevel = getLevel();
+ if (Level.OFF.levelInt > configuredLevel.levelInt) {
+ PrintWriter writer = null;
+ try {
+ writer = new PrintWriter(dump.createFileWriter(FILE_NAME));
+ List<LoggingEvent> loggingEvents = buffer.asList();
+
+ PatternLayout layout = createLayout();
+
+ for (LoggingEvent event : loggingEvents) {
+ writer.print(layout.doLayout(event));
+ }
+ } finally {
+ if (writer != null) {
+ writer.close();
+ }
+ }
+ }
+ }
+
+ private PatternLayout createLayout() {
+ PatternLayout layout = new PatternLayout();
+ layout.setPattern(getPattern(this.configurationProvider.getConfiguration()));
+ layout.setContext(new LoggerContext());
+ layout.start();
+
+ return layout;
+ }
+
+ @SuppressWarnings("unchecked")
+ private Level getLevel() {
+ Dictionary configDictionary = this.configurationProvider.getConfiguration();
+ String level = getLevel(configDictionary);
+ return Level.valueOf(level);
+ }
+
+ @SuppressWarnings("unchecked")
+ private int getBufferSize(Dictionary configuration) {
+ String bufferSizeString = getStringFromConfiguration(configuration, ConfigurationProvider.KEY_LOG_DUMP_BUFFERSIZE, DEFAULT_BUFFER_SIZE);
+ return Integer.parseInt(bufferSizeString);
+ }
+
+ @SuppressWarnings("unchecked")
+ private String getLevel(Dictionary configuration) {
+ return getStringFromConfiguration(configuration, ConfigurationProvider.KEY_LOG_DUMP_LEVEL, DEFAULT_LEVEL);
+ }
+
+ @SuppressWarnings("unchecked")
+ private String getPattern(Dictionary configuration) {
+ return getStringFromConfiguration(configuration, ConfigurationProvider.KEY_LOG_DUMP_PATTERN, DEFAULT_PATTERN);
+ }
+
+ @SuppressWarnings("unchecked")
+ private String getStringFromConfiguration(Dictionary configuration, String key, String defaultValue) {
+ String value = (String)configuration.get(key);
+
+ if (value == null) {
+ value = defaultValue;
+ }
+
+ return value;
+ }
+
+ public void onLogging(Logger logger, String fqcn, Marker marker,
+ Level level, String message, Object param, Throwable throwable) {
+
+ if (level.isGreaterOrEqual(getLevel())) {
+ LoggingEvent event = new LoggingEvent(fqcn, logger, level, message, throwable, new Object[] {param});
+ event.setMarker(marker);
+ event.setThreadName(Thread.currentThread().getName());
+
+ synchronized (this.monitor) {
+ this.buffer.add(event);
+ }
+ }
+ }
+
+ public void onLogging(Logger logger, String fqcn, Marker marker,
+ Level level, String message, Object param1, Object param2,
+ Throwable throwable) {
+
+ if (level.isGreaterOrEqual(getLevel())) {
+ LoggingEvent event = new LoggingEvent(fqcn, logger, level, message, throwable, new Object[] {param1, param2});
+ event.setMarker(marker);
+ event.setThreadName(Thread.currentThread().getName());
+
+ synchronized (this.monitor) {
+ this.buffer.add(event);
+ }
+ }
+ }
+
+ public void onLogging(Logger logger, String fqcn, Marker marker,
+ Level level, String message, Object[] params, Throwable throwable) {
+
+ if (level.isGreaterOrEqual(getLevel())) {
+ LoggingEvent event = new LoggingEvent(fqcn, logger, level, message, throwable, params);
+ event.setMarker(marker);
+ event.setThreadName(Thread.currentThread().getName());
+
+ synchronized (this.monitor) {
+ this.buffer.add(event);
+ }
+ }
+ }
+
+ /**
+ *
+ */
+ public void clear() {
+ synchronized (this.monitor) {
+ this.buffer.clear();
+ }
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/summary/SummaryDumpContributor.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/summary/SummaryDumpContributor.java
new file mode 100644
index 0000000..6c4489c
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/summary/SummaryDumpContributor.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.dump.impl.summary;
+
+import java.io.PrintWriter;
+import java.text.DateFormat;
+import java.util.Date;
+
+import org.eclipse.virgo.medic.dump.Dump;
+import org.eclipse.virgo.medic.dump.DumpContributionFailedException;
+import org.eclipse.virgo.medic.dump.DumpContributor;
+
+
+public final class SummaryDumpContributor implements DumpContributor {
+
+ private final DateFormat dateFormat = DateFormat.getDateInstance();
+
+ private final DateFormat timeFormat = DateFormat.getTimeInstance(DateFormat.LONG);
+
+ private final Object formatterLock = new Object();
+
+ public void contribute(Dump dump) throws DumpContributionFailedException {
+ PrintWriter writer = null;
+ try {
+ writer = new PrintWriter(dump.createFileWriter("summary.txt"));
+ processHeader(writer, dump.getTimestamp());
+ processCause(writer, dump.getCause());
+ processThrowables(writer, dump.getThrowables());
+ } finally {
+ if (writer != null) {
+ writer.close();
+ }
+ }
+ }
+
+ public String getName() {
+ return "summary";
+ }
+
+ private void processHeader(PrintWriter dump, long timestamp) {
+ synchronized (formatterLock) {
+ dump.println("Date:\t\t" + dateFormat.format(new Date(timestamp)));
+ dump.println("Time:\t\t" + timeFormat.format(new Date(timestamp)));
+ }
+ }
+
+ private static void processCause(PrintWriter dump, String cause) {
+ dump.println();
+ dump.println("Cause: " + cause);
+ }
+
+ private static void processThrowables(PrintWriter dump, Throwable... throwables) {
+ if (throwables.length == 0) {
+ dump.println();
+ dump.println("Exception: None");
+ } else {
+ for (Throwable throwable : throwables) {
+ dump.println();
+ dump.println("Exception:");
+ throwable.printStackTrace(dump);
+ }
+ }
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/thread/Java5ThreadInfoWriter.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/thread/Java5ThreadInfoWriter.java
new file mode 100644
index 0000000..557a138
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/thread/Java5ThreadInfoWriter.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.dump.impl.thread;
+
+import java.io.PrintWriter;
+import java.lang.management.ThreadInfo;
+
+final class Java5ThreadInfoWriter implements ThreadInfoWriter {
+
+ /**
+ * {@inheritDoc}
+ */
+ public void write(ThreadInfo threadInfo, PrintWriter writer) {
+ writer.print(String.format("\"%s\" Id=%s %s", threadInfo.getThreadName(), threadInfo.getThreadId(), threadInfo.getThreadState()));
+ if (threadInfo.getLockName() != null) {
+ writer.print(String.format(" on %s", threadInfo.getLockName()));
+ if (threadInfo.getLockOwnerName() != null) {
+ writer.print(String.format(" owned by \"%s\" Id=%s", threadInfo.getLockOwnerName(), threadInfo.getLockOwnerId()));
+ }
+ }
+ if (threadInfo.isInNative()) {
+ writer.println(" (in native)");
+ } else {
+ writer.println();
+ }
+ StackTraceElement[] stackTraceElements = threadInfo.getStackTrace();
+ for (StackTraceElement stackTraceElement : stackTraceElements) {
+ writer.println(" at " + stackTraceElement);
+ }
+ }
+}
+
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/thread/Java5ThreadMXBeanDelegate.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/thread/Java5ThreadMXBeanDelegate.java
new file mode 100644
index 0000000..0c054b6
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/thread/Java5ThreadMXBeanDelegate.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.dump.impl.thread;
+
+import java.lang.management.ManagementFactory;
+import java.lang.management.ThreadInfo;
+import java.lang.management.ThreadMXBean;
+
+/**
+ * A Java 5-based implementation of <code>ThreadMXBeanDelegate</code>. This class requires a Java 5 (or later) VM.
+ * <p/>
+ *
+ * <strong>Concurrent Semantics</strong><br />
+ * Thread-safe.
+ *
+ */
+public class Java5ThreadMXBeanDelegate implements ThreadMXBeanDelegate {
+
+ private ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
+
+ /**
+ * {@inheritDoc}
+ */
+ public long[] findDeadlockedThreads() {
+ return threadBean.findMonitorDeadlockedThreads();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ThreadInfo[] getThreadInfo(long[] threadIds) {
+ return threadBean.getThreadInfo(threadIds, Integer.MAX_VALUE);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ThreadInfo[] dumpAllThreads() {
+ return threadBean.getThreadInfo(threadBean.getAllThreadIds(), Integer.MAX_VALUE);
+ }
+}
+
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/thread/StandardThreadInfoWriter.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/thread/StandardThreadInfoWriter.java
new file mode 100644
index 0000000..fe01b2e
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/thread/StandardThreadInfoWriter.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.dump.impl.thread;
+
+import java.io.PrintWriter;
+import java.lang.management.MonitorInfo;
+import java.lang.management.ThreadInfo;
+
+class StandardThreadInfoWriter implements ThreadInfoWriter {
+
+ public void write(ThreadInfo threadInfo, PrintWriter writer) {
+ writer.print(String.format("\"%s\" Id=%s %s", threadInfo.getThreadName(), threadInfo.getThreadId(), threadInfo.getThreadState()));
+ if (threadInfo.getLockName() != null) {
+ writer.print(String.format(" on %s", threadInfo.getLockName()));
+ if (threadInfo.getLockOwnerName() != null) {
+ writer.print(String.format(" owned by \"%s\" Id=%s", threadInfo.getLockOwnerName(), threadInfo.getLockOwnerId()));
+ }
+ }
+ if (threadInfo.isInNative()) {
+ writer.println(" (in native)");
+ } else {
+ writer.println();
+ }
+ MonitorInfo[] lockedMonitors = threadInfo.getLockedMonitors();
+
+ StackTraceElement[] stackTraceElements = threadInfo.getStackTrace();
+ for (StackTraceElement stackTraceElement : stackTraceElements) {
+ writer.println(" at " + stackTraceElement);
+ MonitorInfo lockedMonitor = findLockedMonitor(stackTraceElement, lockedMonitors);
+ if (lockedMonitor != null) {
+ writer.println(" - locked " + lockedMonitor.getClassName() + "@" + lockedMonitor.getIdentityHashCode());
+ }
+ }
+ }
+
+ private static MonitorInfo findLockedMonitor(StackTraceElement stackTraceElement, MonitorInfo[] lockedMonitors) {
+ for (MonitorInfo monitorInfo : lockedMonitors) {
+ if (stackTraceElement.equals(monitorInfo.getLockedStackFrame())) {
+ return monitorInfo;
+ }
+ }
+ return null;
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/thread/StandardThreadMXBeanDelegate.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/thread/StandardThreadMXBeanDelegate.java
new file mode 100644
index 0000000..e07f607
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/thread/StandardThreadMXBeanDelegate.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.dump.impl.thread;
+
+import java.lang.management.ManagementFactory;
+import java.lang.management.ThreadInfo;
+import java.lang.management.ThreadMXBean;
+
+public class StandardThreadMXBeanDelegate implements ThreadMXBeanDelegate {
+
+ private final ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
+
+ public ThreadInfo[] dumpAllThreads() {
+ return threadBean.dumpAllThreads(true, true);
+ }
+
+ public long[] findDeadlockedThreads() {
+ return threadBean.findDeadlockedThreads();
+ }
+
+ public ThreadInfo[] getThreadInfo(long[] threadIds) {
+ return threadBean.getThreadInfo(threadIds, true, true);
+ }
+
+}
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/thread/ThreadDumpContributor.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/thread/ThreadDumpContributor.java
new file mode 100644
index 0000000..e6b4fd8
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/thread/ThreadDumpContributor.java
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.dump.impl.thread;
+
+import java.io.PrintWriter;
+import java.lang.management.ThreadInfo;
+
+import org.eclipse.virgo.medic.dump.Dump;
+import org.eclipse.virgo.medic.dump.DumpContributionFailedException;
+import org.eclipse.virgo.medic.dump.DumpContributor;
+
+
+public class ThreadDumpContributor implements DumpContributor {
+
+ private final ThreadMXBeanDelegate threadBeanDelegate;
+
+ private final ThreadInfoWriter threadInfoWriter;
+
+ public ThreadDumpContributor(ThreadMXBeanDelegate threadBeanDelegate, ThreadInfoWriter threadInfoPrinter) {
+ this.threadBeanDelegate = threadBeanDelegate;
+ this.threadInfoWriter = threadInfoPrinter;
+ }
+
+ public ThreadDumpContributor() {
+ String javaSpecificationVersion = System.getProperty("java.specification.version");
+ if ("1.5".equals(javaSpecificationVersion)) {
+ this.threadBeanDelegate = new Java5ThreadMXBeanDelegate();
+ this.threadInfoWriter = new Java5ThreadInfoWriter();
+ } else {
+ this.threadBeanDelegate = new StandardThreadMXBeanDelegate();
+ this.threadInfoWriter = new StandardThreadInfoWriter();
+ }
+ }
+
+ public String getName() {
+ return "thread";
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void contribute(Dump dump) throws DumpContributionFailedException {
+ PrintWriter writer = null;
+ try {
+ writer = new PrintWriter(dump.createFileWriter("thread.txt"));
+ processDeadlocks(writer);
+ processAllThreads(writer);
+ writer.close();
+ } finally {
+ if (writer != null) {
+ writer.close();
+ }
+ }
+ }
+
+ private void processDeadlocks(PrintWriter dump) {
+ dump.println("Deadlocked Threads");
+ dump.println("==================");
+ long[] deadlockedThreadIds = this.threadBeanDelegate.findDeadlockedThreads();
+ if (deadlockedThreadIds != null) {
+ dumpThreads(dump, this.threadBeanDelegate.getThreadInfo(deadlockedThreadIds));
+ }
+ }
+
+ private void processAllThreads(PrintWriter dump) {
+ dump.println();
+ dump.println("All Threads");
+ dump.println("===========");
+ dumpThreads(dump, this.threadBeanDelegate.dumpAllThreads());
+ }
+
+ private void dumpThreads(PrintWriter dump, ThreadInfo[] infos) {
+ for (ThreadInfo info : infos) {
+ dump.println();
+ this.threadInfoWriter.write(info, dump);
+ }
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/thread/ThreadInfoWriter.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/thread/ThreadInfoWriter.java
new file mode 100644
index 0000000..cdfe8f2
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/thread/ThreadInfoWriter.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.dump.impl.thread;
+
+import java.io.PrintWriter;
+import java.lang.management.ThreadInfo;
+
+/**
+ * A helper interface for writing {@link ThreadInfo} instances enabling the plugging-in of an implementation that can
+ * cope with the differences in {@link ThreadInfo}'s contents on Java 5 and Java 6 virtual machines.
+ * <p/>
+ *
+ * <strong>Concurrent Semantics</strong><br />
+ *
+ * Implementations <strong>must</strong> be thread-safe.
+ *
+ */
+interface ThreadInfoWriter {
+
+ /**
+ * Writes the supplied {@ThreadInfo} to the supplied {@PrintWriter}.
+ *
+ * @param threadInfo The <code>ThreadInfo</code>
+ * @param writer the <code>PrintWriter</code> to write to
+ */
+ void write(ThreadInfo threadInfo, PrintWriter writer);
+}
+
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/thread/ThreadMXBeanDelegate.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/thread/ThreadMXBeanDelegate.java
new file mode 100644
index 0000000..ac8501a
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/dump/impl/thread/ThreadMXBeanDelegate.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.dump.impl.thread;
+
+import java.lang.management.ThreadInfo;
+
+/**
+ * A delegate for ThreadMXBean to hide the differences in the methods and capabilities of its Java 5 and Java 6
+ * versions.
+ * <p />
+ * <strong>Concurrent Semantics</strong><br />
+ * Implementation <strong>must</strong> be thread-safe.
+ *
+ */
+interface ThreadMXBeanDelegate {
+
+ /**
+ * Finds all threads in the JVM that are deadlocked
+ *
+ * @return An array of thread ids of the deadlocked threads
+ */
+ long[] findDeadlockedThreads();
+
+ /**
+ * Returns an array of <code>ThreadInfo</code> instances, one for each thread identified in the supplied array of
+ * thread ids.
+ *
+ * @param threadIds The thread ids
+ * @return The array of <code>ThreadInfo</code> instances.
+ */
+ public ThreadInfo[] getThreadInfo(long[] threadIds);
+
+ /**
+ * Returns an array of <code>ThreadInfo</code> instances, one for each live thread.
+ *
+ * @return The array of <code>ThreadInfo</code> instances.
+ */
+ public ThreadInfo[] dumpAllThreads();
+}
+
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/eventlog/impl/BundleSearchingPropertyResourceBundleResolver.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/eventlog/impl/BundleSearchingPropertyResourceBundleResolver.java
new file mode 100644
index 0000000..d86a2da
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/eventlog/impl/BundleSearchingPropertyResourceBundleResolver.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.eventlog.impl;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.PropertyResourceBundle;
+
+import org.osgi.framework.Bundle;
+
+public final class BundleSearchingPropertyResourceBundleResolver implements PropertyResourceBundleResolver {
+
+ public List<PropertyResourceBundle> getResourceBundles(Bundle bundle, String candidatePropertiesFileName) {
+ Enumeration<?> entries = bundle.findEntries("", candidatePropertiesFileName, false);
+ List<PropertyResourceBundle> propertyBundles = new ArrayList<PropertyResourceBundle>();
+ if (entries != null) {
+ while (entries.hasMoreElements()) {
+ URL propertiesFile = (URL) entries.nextElement();
+ InputStream input = null;
+ try {
+ input = propertiesFile.openStream();
+ propertyBundles.add(new PropertyResourceBundle(input));
+ } catch (IOException ioe) {
+ } finally {
+ try {
+ if (input != null) {
+ input.close();
+ }
+ } catch (IOException e) {
+ }
+ }
+ }
+ }
+ return propertyBundles;
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/eventlog/impl/EventLoggerServiceFactory.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/eventlog/impl/EventLoggerServiceFactory.java
new file mode 100644
index 0000000..03d7a11
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/eventlog/impl/EventLoggerServiceFactory.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.eventlog.impl;
+
+import org.eclipse.virgo.medic.eventlog.EventLoggerFactory;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.ServiceFactory;
+import org.osgi.framework.ServiceRegistration;
+
+
+public final class EventLoggerServiceFactory implements ServiceFactory {
+
+ private final EventLoggerFactory eventLoggerFactory;
+
+ public EventLoggerServiceFactory(EventLoggerFactory factory) {
+ this.eventLoggerFactory = factory;
+ }
+
+ public Object getService(Bundle bundle, ServiceRegistration registration) {
+ return this.eventLoggerFactory.createEventLogger(bundle);
+ }
+
+ public void ungetService(Bundle bundle, ServiceRegistration registration, Object service) {
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/eventlog/impl/LocaleResolver.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/eventlog/impl/LocaleResolver.java
new file mode 100644
index 0000000..c29742d
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/eventlog/impl/LocaleResolver.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.eventlog.impl;
+
+import java.util.Locale;
+
+/**
+ * A <code>LocaleResolver</code> provides a basic strategy for determining the current {@link Locale}.
+ * <strong>Concurrent Semantics</strong><br />
+ * Implementations <strong>must</strong> be thread-safe.
+ *
+ */
+public interface LocaleResolver {
+
+ /**
+ * Return the current {@link Locale}. This should never return <code>null</code>.
+ *
+ * @return the current <code>Locale</code>. Never <code>null</code>.
+ */
+ Locale getLocale();
+}
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/eventlog/impl/MessageResolver.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/eventlog/impl/MessageResolver.java
new file mode 100644
index 0000000..4ace248
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/eventlog/impl/MessageResolver.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.eventlog.impl;
+
+import java.util.Locale;
+
+/**
+ * A LogEventMessageResolver is used to resolve the message of a logged event.
+ *
+ * <strong>Concurrent Semantics</strong><br />
+ * Implementations <strong>must</strong> be thread-safe.
+ *
+ */
+public interface MessageResolver {
+
+ /**
+ * Resolves the message identified by the supplied event code.
+ * @param eventCode The code identifying the message to be resolved
+ * @return The resolved message, or <code>null</code> if no message could be found
+ */
+ String resolveLogEventMessage(String eventCode);
+
+ /**
+ * Resolves the message identified by the supplied event code in the supplied {@link Locale}.
+ *
+ * @param eventCode The code identifying the message is to be resolved
+ * @param locale the {@link Locale} in which the message is to be resolved
+ * @return The resolved message, or <code>null</code> if no message could be found
+ */
+ String resolveLogEventMessage(String eventCode, Locale locale);
+}
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/eventlog/impl/PropertyResourceBundleResolver.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/eventlog/impl/PropertyResourceBundleResolver.java
new file mode 100644
index 0000000..f043968
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/eventlog/impl/PropertyResourceBundleResolver.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.eventlog.impl;
+
+import java.util.List;
+import java.util.PropertyResourceBundle;
+
+import org.osgi.framework.Bundle;
+
+public interface PropertyResourceBundleResolver {
+
+ List<PropertyResourceBundle> getResourceBundles(Bundle bundle, String candidatePropertiesFileName);
+}
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/eventlog/impl/ResourceBundleUtils.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/eventlog/impl/ResourceBundleUtils.java
new file mode 100644
index 0000000..4bc9795
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/eventlog/impl/ResourceBundleUtils.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.eventlog.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+final class ResourceBundleUtils {
+
+ private static final String PROPERTIES_SUFFIX = ".properties";
+
+ static List<String> generateCandidatePropertiesFileNames(String baseName, Locale locale) {
+ List<String> candidateNames = new ArrayList<String>();
+
+ candidateNames.addAll(generateCandidatePropertiesFileNames(baseName, locale.getLanguage(), locale.getCountry(), locale.getVariant()));
+
+ Locale defaultLocale = Locale.getDefault();
+
+ if (!defaultLocale.equals(locale)) {
+ candidateNames.addAll(generateCandidatePropertiesFileNames(baseName, defaultLocale.getLanguage(), defaultLocale.getCountry(),
+ defaultLocale.getVariant()));
+ }
+
+ candidateNames.add(baseName + PROPERTIES_SUFFIX);
+
+ return candidateNames;
+ }
+
+ private static List<String> generateCandidatePropertiesFileNames(String baseName, String language, String country, String variant) {
+ List<String> candidateNames = new ArrayList<String>();
+
+ if (hasText(language)) {
+ if (hasText(country)) {
+ if (hasText(variant)) {
+ candidateNames.add(baseName + "_" + language + "_" + country + "_" + variant + PROPERTIES_SUFFIX);
+ }
+ candidateNames.add(baseName + "_" + language + "_" + country + PROPERTIES_SUFFIX);
+ }
+ candidateNames.add(baseName + "_" + language + PROPERTIES_SUFFIX);
+ }
+
+ return candidateNames;
+ }
+
+ private static boolean hasText(String string) {
+ return (string != null && string.length() > 0);
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/eventlog/impl/StandardLocaleResolver.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/eventlog/impl/StandardLocaleResolver.java
new file mode 100644
index 0000000..fd63b99
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/eventlog/impl/StandardLocaleResolver.java
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.eventlog.impl;
+
+import java.util.Locale;
+
+public final class StandardLocaleResolver implements LocaleResolver {
+
+ public Locale getLocale() {
+ return Locale.getDefault();
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/eventlog/impl/StandardMessageResolver.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/eventlog/impl/StandardMessageResolver.java
new file mode 100644
index 0000000..5969c1b
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/eventlog/impl/StandardMessageResolver.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.eventlog.impl;
+
+import java.util.List;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.PropertyResourceBundle;
+
+import org.osgi.framework.Bundle;
+
+public final class StandardMessageResolver implements MessageResolver {
+
+ private static final String RESOURCE_BUNDLE_NAME = "EventLogMessages";
+
+ private final LocaleResolver localeResolver;
+
+ private final PropertyResourceBundleResolver resourceBundleLocator;
+
+ private final Bundle primaryBundle;
+
+ private final Bundle secondaryBundle;
+
+ public StandardMessageResolver(LocaleResolver localeResolver, PropertyResourceBundleResolver resourceBundleLocator, Bundle primaryBundle,
+ Bundle secondaryBundle) {
+ this.localeResolver = localeResolver;
+ this.resourceBundleLocator = resourceBundleLocator;
+ this.primaryBundle = primaryBundle;
+ this.secondaryBundle = secondaryBundle;
+ }
+
+ public String resolveLogEventMessage(String eventCode) {
+ return resolveLogEventMessage(eventCode, this.localeResolver.getLocale());
+ }
+
+ public String resolveLogEventMessage(String eventCode, Locale locale) {
+ List<String> candidatePropertiesFileNames = ResourceBundleUtils.generateCandidatePropertiesFileNames(RESOURCE_BUNDLE_NAME, locale);
+
+ String message = resolveMessageInBundle(this.primaryBundle, eventCode, candidatePropertiesFileNames);
+
+ if (message == null) {
+ message = resolveMessageInBundle(this.secondaryBundle, eventCode, candidatePropertiesFileNames);
+ }
+
+ return message;
+ }
+
+ private String resolveMessageInBundle(Bundle bundle, String key, List<String> candidatePropertiesFileNames) {
+ for (String candidatePropertiesFileName : candidatePropertiesFileNames) {
+ List<PropertyResourceBundle> resourceBundles = this.resourceBundleLocator.getResourceBundles(bundle, candidatePropertiesFileName);
+ for (PropertyResourceBundle resourceBundle : resourceBundles) {
+ try {
+ String string = resourceBundle.getString(key);
+ if (string != null) {
+ return string;
+ }
+ } catch (MissingResourceException mre) {
+ // Continue searching
+ }
+ }
+ }
+ return null;
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/eventlog/impl/logback/LogBackEventLogger.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/eventlog/impl/logback/LogBackEventLogger.java
new file mode 100644
index 0000000..85008c6
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/eventlog/impl/logback/LogBackEventLogger.java
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.eventlog.impl.logback;
+
+import java.util.Locale;
+
+import org.eclipse.virgo.medic.eventlog.EventLogger;
+import org.eclipse.virgo.medic.eventlog.Level;
+import org.eclipse.virgo.medic.eventlog.LogEvent;
+import org.eclipse.virgo.medic.eventlog.impl.MessageResolver;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.slf4j.MDC;
+import org.slf4j.helpers.MessageFormatter;
+
+
+class LogBackEventLogger implements EventLogger {
+
+ private static final String MDC_KEY_MEDIC_EVENT_CODE = "medic.eventCode";
+
+ private static final String MISSING_MESSAGE_EVENT_CODE = "ME0001W";
+
+ private final Logger localizedLogger = LoggerFactory.getLogger("org.eclipse.virgo.medic.eventlog.localized");
+
+ private final Logger defaultLogger = LoggerFactory.getLogger("org.eclipse.virgo.medic.eventlog.default");
+
+ private final MessageResolver messageResolver;
+
+ private final Locale defaultLocale = Locale.ENGLISH;
+
+ LogBackEventLogger(MessageResolver messageResolver) {
+ this.messageResolver = messageResolver;
+ }
+
+ public void log(String code, Level level, Object... inserts) {
+ this.log(code, level, null, inserts);
+ }
+
+ public void log(LogEvent logEvent, Object... inserts) {
+ this.log(logEvent.getEventCode(), logEvent.getLevel(), inserts);
+ }
+
+ public void log(String eventCode, Level level, Throwable throwable, Object... inserts) {
+ try {
+ String localisedMessage = messageResolver.resolveLogEventMessage(eventCode);
+
+ if (localisedMessage != null) {
+ logMessage(this.localizedLogger, localisedMessage, level, eventCode, throwable, inserts);
+ } else {
+ logMissingMessage(this.localizedLogger, eventCode, throwable, inserts);
+ }
+
+ String defaultMessage = messageResolver.resolveLogEventMessage(eventCode, defaultLocale);
+
+ if (defaultMessage != null) {
+ logMessage(this.defaultLogger, defaultMessage, level, eventCode, throwable, inserts);
+ } else {
+ logMissingMessage(this.defaultLogger, eventCode, throwable, inserts);
+ }
+ } finally {
+ MDC.remove(MDC_KEY_MEDIC_EVENT_CODE);
+ }
+ }
+
+ public void log(LogEvent logEvent, Throwable throwable, Object... inserts) {
+ this.log(logEvent.getEventCode(), logEvent.getLevel(), throwable, inserts);
+ }
+
+ private void logMissingMessage(Logger logger, String eventCode, Throwable throwable, Object[] inserts) {
+ logMessage(logger, "A message with the key '{}' was not found. The inserts for the message were '{}'", Level.WARNING,
+ MISSING_MESSAGE_EVENT_CODE, throwable, eventCode, inserts);
+ }
+
+ private void logMessage(Logger logger, String message, Level level, String eventCode, Throwable throwable, Object... inserts) {
+ try {
+ MDC.put(MDC_KEY_MEDIC_EVENT_CODE, eventCode);
+ String formattedMessage = MessageFormatter.arrayFormat(message, (Object[]) inserts);
+ switch (level) {
+ case ERROR:
+ logger.error(formattedMessage, throwable);
+ break;
+ case WARNING:
+ logger.warn(formattedMessage, throwable);
+ break;
+ case INFO:
+ logger.info(formattedMessage, throwable);
+ break;
+ }
+ } finally {
+ MDC.remove(MDC_KEY_MEDIC_EVENT_CODE);
+ }
+ }
+
+}
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/eventlog/impl/logback/LogBackEventLoggerFactory.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/eventlog/impl/logback/LogBackEventLoggerFactory.java
new file mode 100644
index 0000000..b5d8349
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/eventlog/impl/logback/LogBackEventLoggerFactory.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.eventlog.impl.logback;
+
+import org.eclipse.virgo.medic.eventlog.EventLogger;
+import org.eclipse.virgo.medic.eventlog.EventLoggerFactory;
+import org.eclipse.virgo.medic.eventlog.impl.LocaleResolver;
+import org.eclipse.virgo.medic.eventlog.impl.MessageResolver;
+import org.eclipse.virgo.medic.eventlog.impl.PropertyResourceBundleResolver;
+import org.eclipse.virgo.medic.eventlog.impl.StandardMessageResolver;
+import org.osgi.framework.Bundle;
+
+
+public class LogBackEventLoggerFactory implements EventLoggerFactory {
+
+ private final Bundle secondaryBundle;
+
+ private final PropertyResourceBundleResolver resourceBundleResolver;
+
+ private final LocaleResolver localeResolver;
+
+ public LogBackEventLoggerFactory(PropertyResourceBundleResolver resourceBundleResolver, LocaleResolver localeResolver, Bundle secondaryBundle) {
+ this.secondaryBundle = secondaryBundle;
+ this.resourceBundleResolver = resourceBundleResolver;
+ this.localeResolver = localeResolver;
+ }
+
+ public EventLogger createEventLogger(Bundle primaryBundle) {
+ MessageResolver messageResolver = new StandardMessageResolver(this.localeResolver, resourceBundleResolver, primaryBundle,
+ this.secondaryBundle);
+ return new LogBackEventLogger(messageResolver);
+ }
+}
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
new file mode 100644
index 0000000..3bc296b
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/impl/MedicActivator.java
@@ -0,0 +1,272 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+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.List;
+import java.util.Properties;
+
+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.packageadmin.PackageAdmin;
+
+
+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.util.osgi.ServiceRegistrationTracker;
+
+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 volatile StandardDumpGenerator dumpGenerator;
+
+ private volatile LogBackEventLoggerFactory eventLoggerFactory;
+
+ private volatile DumpContributorPublisher dumpContributorPublisher;
+
+ private volatile ServiceReference packageAdminReference;
+
+ private volatile PrintStream sysOut;
+
+ 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.registrationTracker.track(context.registerService(ConfigurationListener.class.getName(), configurationProvider, null));
+
+ logStart(context, configurationProvider);
+ eventLogStart(context);
+ dumpStart(context, configurationProvider);
+ }
+
+ public void stop(BundleContext context) throws Exception {
+
+ this.registrationTracker.unregisterAll();
+
+ dumpStop();
+ logStop(context);
+ }
+
+ 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));
+
+ this.dumpContributorPublisher = new DumpContributorPublisher(context, configurationProvider);
+ this.dumpContributorPublisher.publishDumpContributors();
+ }
+
+ private void dumpStop() {
+ if (this.dumpGenerator != null) {
+ this.dumpGenerator.close();
+ }
+
+ if (this.dumpContributorPublisher != null) {
+ this.dumpContributorPublisher.retractDumpContributors();
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private void logStart(BundleContext context, ConfigurationProvider configurationProvider) throws ConfigurationPublicationFailedException {
+ this.packageAdminReference = context.getServiceReference(PackageAdmin.class.getName());
+ PackageAdmin packageAdmin = (PackageAdmin) context.getService(this.packageAdminReference);
+
+ StandardContextSelectorDelegate delegate = createContextSelectorDelegate(context, packageAdmin);
+ 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 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((String)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((String)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));
+ }
+ }
+
+ 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) {
+ Properties properties = new Properties();
+ 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) {
+ Properties properties = new Properties();
+ 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, PackageAdmin packageAdmin) {
+ ConfigurationLocator configurationLocator = createConfigurationLocator(bundleContext);
+ CallingBundleResolver loggingCallerLocator = createLoggingCallerLocator(packageAdmin);
+ LoggerContextConfigurer loggerContextConfigurer = new JoranLoggerContextConfigurer();
+ return new StandardContextSelectorDelegate(loggingCallerLocator, configurationLocator, bundleContext.getBundle(), loggerContextConfigurer);
+ }
+
+ private static ConfigurationLocator createConfigurationLocator(BundleContext bundleContext) {
+ return new CompositeConfigurationLocator(new ServiceRegistryConfigurationLocator(bundleContext), new BundleResourceConfigurationLocator());
+ }
+
+ private static CallingBundleResolver createLoggingCallerLocator(PackageAdmin packageAdmin) {
+ ClassSelector classSelector = createClassSelector();
+ ExecutionStackAccessor executionStackAccessor = createExecutionStackAccessor();
+
+ return new StandardCallingBundleResolver(executionStackAccessor, classSelector, packageAdmin);
+ }
+
+ 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);
+
+ if (this.packageAdminReference != null) {
+ context.ungetService(this.packageAdminReference);
+ this.packageAdminReference = null;
+ }
+
+ DelegatingContextSelector.setDelegate(null);
+
+ if (this.sysOut != null) {
+ System.setOut(this.sysOut);
+ }
+
+ if (this.sysErr != null) {
+ System.setErr(this.sysErr);
+ }
+ }
+
+ private void eventLogStart(BundleContext context) {
+ this.eventLoggerFactory = createFactory(context);
+ ServiceFactory 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());
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/impl/MedicLogEvents.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/impl/MedicLogEvents.java
new file mode 100644
index 0000000..ed7877f
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/impl/MedicLogEvents.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.impl;
+
+import org.eclipse.virgo.medic.eventlog.Level;
+import org.eclipse.virgo.medic.eventlog.LogEvent;
+
+public enum MedicLogEvents implements LogEvent {
+
+ DIRECTORY_CREATION_FAILED(1, Level.WARNING), //
+ CONTRIBUTION_FAILED(2, Level.WARNING), //
+ DUMP_GENERATED(3, Level.INFO);
+
+ private static final String PREFIX = "ME";
+
+ private final int code;
+
+ private final Level level;
+
+ private MedicLogEvents(int code, Level level) {
+ this.code = code;
+ this.level = level;
+ }
+
+ public String getEventCode() {
+ return String.format("%s%04d%1.1s", PREFIX, this.code, this.level);
+ }
+
+ public Level getLevel() {
+ return level;
+ }
+}
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
new file mode 100644
index 0000000..7d9c2f7
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/impl/config/ConfigurationAdminConfigurationProvider.java
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.impl.config;
+
+import java.io.IOException;
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.cm.ConfigurationEvent;
+import org.osgi.service.cm.ConfigurationListener;
+
+public final class ConfigurationAdminConfigurationProvider implements ConfigurationProvider, ConfigurationListener {
+
+ private static final String CONFIG_ADMIN_PID = "org.eclipse.virgo.medic";
+
+ private static final String CONFIG_ADMIN_SERVICE_NAME = "org.osgi.service.cm.ConfigurationAdmin";
+
+ private static final Dictionary<Object, Object> DEFAULT_CONFIG = createDefaultConfiguration();
+
+ private final BundleContext bundleContext;
+
+ @SuppressWarnings("unchecked")
+ private volatile Dictionary configuration = DEFAULT_CONFIG;
+
+ public ConfigurationAdminConfigurationProvider(BundleContext context) {
+ this.bundleContext = context;
+ initialisePropertiesFromConfigurationAdmin();
+ }
+
+ public Dictionary<?, ?> getConfiguration() {
+ return this.configuration;
+ }
+
+
+ private void initialisePropertiesFromConfigurationAdmin() {
+ ServiceReference configAdminReference = this.bundleContext.getServiceReference(CONFIG_ADMIN_SERVICE_NAME);
+
+ if (configAdminReference != null) {
+ this.bundleContext.registerService(ConfigurationListener.class.getName(), new MedicConfigurationListener(), null);
+ setPropertiesFromConfigurationAdmin(configAdminReference);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private void setPropertiesFromConfigurationAdmin(ServiceReference configAdminReference) {
+ ConfigurationAdmin configurationAdmin = (ConfigurationAdmin)this.bundleContext.getService(configAdminReference);
+
+ if (configurationAdmin != null) {
+ try {
+ Configuration configuration = configurationAdmin.getConfiguration(CONFIG_ADMIN_PID, null);
+
+ Dictionary properties = configuration.getProperties();
+
+ if (properties == null) {
+ properties = DEFAULT_CONFIG;
+ } else {
+ DictionaryUtils.merge(properties, DEFAULT_CONFIG);
+ }
+
+ this.configuration = properties;
+ } catch (IOException ioe) {
+ }
+ } else {
+ this.configuration = DEFAULT_CONFIG;
+ }
+ }
+
+ private static Dictionary<Object, Object> createDefaultConfiguration() {
+ Dictionary<Object, Object> configuration = new Hashtable<Object, Object>();
+ configuration.put(KEY_DUMP_ROOT_DIRECTORY, ".");
+ configuration.put(KEY_LOG_WRAP_SYSOUT, Boolean.toString(Boolean.TRUE));
+ configuration.put(KEY_LOG_WRAP_SYSERR, Boolean.toString(Boolean.TRUE));
+ return configuration;
+ }
+
+ private final class MedicConfigurationListener implements ConfigurationListener {
+
+ public void configurationEvent(ConfigurationEvent configEvent) {
+ if (CONFIG_ADMIN_PID.equals(configEvent.getPid()) && configEvent.getType() == ConfigurationEvent.CM_UPDATED) {
+ setPropertiesFromConfigurationAdmin(configEvent.getReference());
+ }
+ }
+ }
+
+ public void configurationEvent(ConfigurationEvent event) {
+ if (event.getType() == ConfigurationEvent.CM_UPDATED && CONFIG_ADMIN_PID.equals(event.getPid())) {
+ setPropertiesFromConfigurationAdmin(event.getReference());
+ }
+ }
+}
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
new file mode 100644
index 0000000..01b6470
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/impl/config/ConfigurationProvider.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.impl.config;
+
+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";
+
+ @SuppressWarnings("unchecked")
+ Dictionary getConfiguration();
+}
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/impl/config/DictionaryUtils.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/impl/config/DictionaryUtils.java
new file mode 100644
index 0000000..285d84d
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/impl/config/DictionaryUtils.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.impl.config;
+
+import java.util.Dictionary;
+import java.util.Enumeration;
+
+final class DictionaryUtils {
+
+ static void merge(Dictionary<Object, Object> primary, Dictionary<Object, Object> secondary) {
+ Enumeration<?> keys = secondary.keys();
+ while (keys.hasMoreElements()) {
+ Object key = keys.nextElement();
+ if (primary.get(key) == null) {
+ primary.put(key, secondary.get(key));
+ }
+ }
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/CallingBundleResolver.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/CallingBundleResolver.java
new file mode 100644
index 0000000..195e368
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/CallingBundleResolver.java
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.log.impl;
+
+import org.osgi.framework.Bundle;
+
+public interface CallingBundleResolver {
+
+ /**
+ * Returns the {@link Bundle} from which the current logging call originated.
+ *
+ * @return the <code>Bundle</code> that made the logging call
+ */
+ Bundle getCallingBundle();
+}
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/ClassSelector.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/ClassSelector.java
new file mode 100644
index 0000000..a949187
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/ClassSelector.java
@@ -0,0 +1,17 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.log.impl;
+
+public interface ClassSelector {
+
+ Class<?> select(Class<?>[] classes);
+}
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/ExecutionStackAccessor.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/ExecutionStackAccessor.java
new file mode 100644
index 0000000..fb0c03a
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/ExecutionStackAccessor.java
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.log.impl;
+
+public interface ExecutionStackAccessor {
+
+ /**
+ * Returns the current execution stack as an array of {@link Class Classes}. The first elements in the array is the
+ * class of this method's caller, the second element is that method's caller, and so on.
+ *
+ * @return the execution stack
+ */
+ Class<?>[] getExecutionStack();
+}
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/LoggingLevel.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/LoggingLevel.java
new file mode 100644
index 0000000..9420366
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/LoggingLevel.java
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.log.impl;
+
+/**
+ * A fixed set of logging levels used to control logging for wrapped print streams.
+ * <p />
+ *
+ * <strong>Concurrent Semantics</strong><br />
+ * Fully thread-safe constants.
+ *
+ */
+public enum LoggingLevel {
+ WARNING, INFO, DEBUG, ERROR;
+}
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/LoggingPrintStreamWrapper.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/LoggingPrintStreamWrapper.java
new file mode 100644
index 0000000..ee50845
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/LoggingPrintStreamWrapper.java
@@ -0,0 +1,506 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.log.impl;
+
+import java.io.PrintStream;
+import java.util.Locale;
+
+import org.eclipse.virgo.medic.impl.config.ConfigurationProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * A <code>LoggingPrintStreamWrapper</code> wraps a PrintStream instance and logs, via SLF4j,
+ * all data that is written to it.
+ * <p />
+ *
+ * <strong>Concurrent Semantics</strong><br />
+ * Thread-safe.
+ *
+ */
+public final class LoggingPrintStreamWrapper extends PrintStream {
+
+ private static final String LOGBACK_PACKAGE_NAME_PREFIX = "ch.qos.logback";
+
+ private final ThreadLocal<StringBuilder> entryBuilders;
+
+ private final Logger logger;
+
+ private final ExecutionStackAccessor executionStackAccessor;
+
+ private final ConfigurationProvider configurationProvider;
+
+ private final String configurationProperty;
+
+ private final PrintStream originalPrintStream;
+
+ private final LoggingLevel loggingLevel;
+
+ private static final String NULL_STRING = "null";
+
+ /**
+ * Creates a new LoggingPrintStreamWrapper for the given PrintStream. Data written to
+ * the stream is logged via SLF4j to a logger with the supplied <code>loggerName</code>.<br/>
+ * The logging level is determined by the parameter of type {@link LoggingLevel}.
+ *
+ * @param printStream The PrintStream instance to wrap
+ * @param loggerName The name of the logger
+ * @param loggingLevel The level of the log entries created
+ * @param executionStackAccessor
+ * @param configurationProvider
+ * @param configurationProperty
+ */
+ public LoggingPrintStreamWrapper(PrintStream printStream, String loggerName, LoggingLevel loggingLevel, ExecutionStackAccessor executionStackAccessor, ConfigurationProvider configurationProvider, String configurationProperty) {
+ super(printStream);
+
+ this.logger = LoggerFactory.getLogger(loggerName);
+ this.loggingLevel = loggingLevel;
+
+ this.executionStackAccessor = executionStackAccessor;
+
+ this.entryBuilders = new ThreadLocal<StringBuilder>() {
+ public StringBuilder initialValue() {
+ return new StringBuilder();
+ }
+ };
+
+ this.configurationProvider = configurationProvider;
+
+ this.configurationProperty = configurationProperty;
+
+ this.originalPrintStream = printStream;
+ }
+
+ /**
+ * Creates a new LoggingPrintStreamWrapper for the given PrintStream. Data written to
+ * the stream is logged via SLF4j to a logger with the supplied <code>loggerName</code>.<br/>
+ * (The logging level is DEBUG by default.)
+ *
+ * @param printStream The PrintStream instance to wrap
+ * @param loggerName The name of the logger
+ * @param executionStackAccessor
+ * @param configurationProvider
+ * @param configurationProperty
+ */
+ public LoggingPrintStreamWrapper(PrintStream printStream, String loggerName, ExecutionStackAccessor executionStackAccessor, ConfigurationProvider configurationProvider, String configurationProperty) {
+ this(printStream, loggerName, LoggingLevel.DEBUG, executionStackAccessor, configurationProvider, configurationProperty);
+ }
+
+ @Override
+ public PrintStream append(char c) {
+ if (!isLoggingEnabled()) {
+ super.append(c);
+ } else {
+ this.internalAppend(c);
+ }
+ return this;
+ }
+
+ private boolean internalAppend(char c) {
+ if (c == '\n' || c == '\r') {
+ createEntryAndLog(entryBuilders.get());
+ return true;
+ } else {
+ entryBuilders.get().append(c);
+ return false;
+ }
+ }
+
+ @Override
+ public PrintStream append(CharSequence csq, int start, int end) {
+ if (!isLoggingEnabled()) {
+ super.append(csq, start, end);
+ } else {
+ this.internalAppend(csq, start, end);
+ }
+
+ return this;
+ }
+
+ private void internalAppend(CharSequence csq, int start, int end) {
+ for (int i = start; i < end; i++) {
+ boolean loggedEntry = internalAppend(csq.charAt(i));
+ if (loggedEntry && i < (end - 1)) {
+ char c = csq.charAt(i + 1);
+ if (c == '\n' || c == '\r') {
+ i++;
+ }
+ }
+ }
+ }
+
+ @Override
+ public PrintStream append(CharSequence csq) {
+ if (!isLoggingEnabled()) {
+ super.append(csq);
+ } else {
+ if(csq == null){
+ throw new NullPointerException("Character Sequence to be added to the printStream from source '" + this.logger.getName() + "' is null");
+ }
+ this.internalAppend(csq, 0, csq.length());
+ }
+ return this;
+ }
+
+ @Override
+ public boolean checkError() {
+ if (!isLoggingEnabled()) {
+ return super.checkError();
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public void close() {
+ if (!isLoggingEnabled()) {
+ super.close();
+ }
+ }
+
+ @Override
+ public void flush() {
+ if (!isLoggingEnabled()) {
+ super.flush();
+ }
+ }
+
+ @Override
+ public PrintStream format(Locale l, String format, Object... args) {
+ if (!isLoggingEnabled()) {
+ super.format(l, format, args);
+ } else {
+ this.internalPrint(String.format(l, format, args));
+ }
+ return this;
+ }
+
+ @Override
+ public PrintStream format(String format, Object... args) {
+ if (!isLoggingEnabled()) {
+ super.format(format, args);
+ } else {
+ this.internalPrint(String.format(format, args));
+ }
+ return this;
+ }
+
+ @Override
+ public void print(boolean b) {
+ if (!isLoggingEnabled()) {
+ super.print(b);
+ } else {
+ this.internalPrint(b);
+ }
+ }
+
+ private void internalPrint(boolean b) {
+ entryBuilders.get().append(b);
+ }
+
+ @Override
+ public void print(char c) {
+ if (!isLoggingEnabled()) {
+ super.print(c);
+ } else {
+ this.internalAppend(c);
+ }
+ }
+
+ @Override
+ public void print(char[] ca) {
+ if (!isLoggingEnabled()) {
+ super.print(ca);
+ } else {
+ this.internalPrint(ca);
+ }
+ }
+
+ private void internalPrint(char[] ca) {
+ final String s = new String(ca);
+ this.internalAppend(s, 0, s.length());
+ }
+
+ @Override
+ public void print(double d) {
+ if (!isLoggingEnabled()) {
+ super.print(d);
+ } else {
+ this.internalPrint(d);
+ }
+ }
+
+ private void internalPrint(double d) {
+ entryBuilders.get().append(d);
+ }
+
+ @Override
+ public void print(float f) {
+ if (!isLoggingEnabled()) {
+ super.print(f);
+ } else {
+ this.internalPrint(f);
+ }
+ }
+
+ private void internalPrint(float f) {
+ entryBuilders.get().append(f);
+ }
+
+ @Override
+ public void print(int i) {
+ if (!isLoggingEnabled()) {
+ super.print(i);
+ } else {
+ this.internalPrint(i);
+ }
+ }
+
+ private void internalPrint(int i) {
+ entryBuilders.get().append(i);
+ }
+
+ @Override
+ public void print(long l) {
+ if (!isLoggingEnabled()) {
+ super.print(l);
+ } else {
+ this.internalPrint(l);
+ }
+ }
+
+ private void internalPrint(long l) {
+ entryBuilders.get().append(l);
+ }
+
+ @Override
+ public void print(Object obj) {
+ if (!isLoggingEnabled()) {
+ super.print(obj);
+ } else {
+ this.internalPrint(obj);
+ }
+ }
+
+ private void internalPrint(Object obj) {
+ if (obj == null) {
+ entryBuilders.get().append(NULL_STRING);
+ } else {
+ internalPrint(obj.toString().toCharArray());
+ }
+ }
+
+ @Override
+ public void print(String s) {
+ if (!isLoggingEnabled()) {
+ super.print(s);
+ } else {
+ this.internalPrint(s);
+ }
+ }
+ private void internalPrint(String s) {
+ if (s == null) {
+ s = NULL_STRING;
+ }
+ this.internalAppend(s, 0, s.length());
+ }
+
+ @Override
+ public PrintStream printf(Locale l, String format, Object... args) {
+ if (!isLoggingEnabled()) {
+ super.printf(l, format, args);
+ } else {
+ this.internalPrint(String.format(l, format, args));
+ }
+ return this;
+ }
+
+ @Override
+ public PrintStream printf(String format, Object... args) {
+ if (!isLoggingEnabled()) {
+ super.printf(format, args);
+ } else {
+ this.internalPrint(String.format(format, args));
+ }
+ return this;
+ }
+
+ @Override
+ public void println() {
+ if (!isLoggingEnabled()) {
+ super.println();
+ } else {
+ createEntryAndLog(entryBuilders.get());
+ }
+ }
+
+ @Override
+ public void println(boolean x) {
+ if (!isLoggingEnabled()) {
+ super.println(x);
+ } else {
+ this.internalPrint(x);
+ createEntryAndLog(entryBuilders.get());
+ }
+ }
+
+ @Override
+ public void println(char x) {
+ if (!isLoggingEnabled()) {
+ super.println(x);
+ } else {
+ this.internalAppend(x);
+ createEntryAndLog(entryBuilders.get());
+ }
+ }
+
+ @Override
+ public void println(char[] x) {
+ if (!isLoggingEnabled()) {
+ super.println(x);
+ } else {
+ this.internalPrint(x);
+ createEntryAndLog(entryBuilders.get());
+ }
+ }
+
+ @Override
+ public void println(double x) {
+ if (!isLoggingEnabled()) {
+ super.println(x);
+ } else {
+ this.internalPrint(x);
+ createEntryAndLog(entryBuilders.get());
+ }
+ }
+
+ @Override
+ public void println(float x) {
+ if (!isLoggingEnabled()) {
+ super.println(x);
+ } else {
+ this.internalPrint(x);
+ createEntryAndLog(entryBuilders.get());
+ }
+ }
+
+ @Override
+ public void println(int x) {
+ if (!isLoggingEnabled()) {
+ super.println(x);
+ } else {
+ this.internalPrint(x);
+ createEntryAndLog(entryBuilders.get());
+ }
+ }
+
+ @Override
+ public void println(long x) {
+ if (!isLoggingEnabled()) {
+ super.println(x);
+ } else {
+ this.internalPrint(x);
+ createEntryAndLog(entryBuilders.get());
+ }
+ }
+
+ @Override
+ public void println(Object x) {
+ if (!isLoggingEnabled()) {
+ super.println(x);
+ } else {
+ this.internalPrint(x);
+ createEntryAndLog(entryBuilders.get());
+ }
+ }
+
+ @Override
+ public void println(String x) {
+ if (!isLoggingEnabled()) {
+ super.println(x);
+ } else {
+ this.internalPrint(x);
+ createEntryAndLog(entryBuilders.get());
+ }
+ }
+
+ @Override
+ protected void setError() {
+ if (!isLoggingEnabled()) {
+ super.setError();
+ }
+ }
+
+ @Override
+ public void write(byte[] buf, int off, int len) {
+ if (!isLoggingEnabled()) {
+ super.write(buf, off, len);
+ } else {
+ byte[] outputBytes = new byte[len];
+ System.arraycopy(buf, off, outputBytes, 0, len);
+ this.internalPrint(new String(outputBytes));
+ }
+ }
+
+ @Override
+ public void write(int b) {
+ if (!isLoggingEnabled()) {
+ super.write(b);
+ } else {
+ if (b == '\n' || b == '\r') {
+ createEntryAndLog(entryBuilders.get());
+ } else {
+ entryBuilders.get().append(new String(new byte[] {(byte)b}));
+ }
+ }
+ }
+
+ private void createEntryAndLog(final StringBuilder stringBuilder) {
+ final String string = stringBuilder.toString();
+ switch (this.loggingLevel) {
+ case DEBUG: this.logger.debug(string); break;
+ case ERROR: this.logger.error(string); break;
+ case INFO: this.logger.info(string); break;
+ case WARNING: this.logger.warn(string); break;
+ }
+ entryBuilders.remove();
+ }
+
+ private boolean isLoggingEnabled() {
+ return isEnabledInConfiguration() && !isWithinLogback();
+ }
+
+ private boolean isWithinLogback() {
+ Class<?>[] executionStack = this.executionStackAccessor.getExecutionStack();
+
+ for (Class<?> clazz : executionStack) {
+ Package pkg = clazz.getPackage();
+ if (pkg != null) {
+ String pkgName = pkg.getName();
+ if (pkgName != null && pkgName.startsWith(LOGBACK_PACKAGE_NAME_PREFIX)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ private boolean isEnabledInConfiguration() {
+ return Boolean.valueOf((String)this.configurationProvider.getConfiguration().get(this.configurationProperty));
+ }
+
+ public PrintStream getOriginalPrintStream() {
+ return this.originalPrintStream;
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/PackageNameFilteringClassSelector.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/PackageNameFilteringClassSelector.java
new file mode 100644
index 0000000..ba2752d
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/PackageNameFilteringClassSelector.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.log.impl;
+
+import java.util.List;
+
+public final class PackageNameFilteringClassSelector implements ClassSelector {
+
+ private final List<String> loggingPackages;
+
+ public PackageNameFilteringClassSelector(List<String> loggingPackages) {
+ this.loggingPackages = loggingPackages;
+ }
+
+ public Class<?> select(Class<?>[] classes) {
+ for (Class<?> clazz : classes) {
+ Package pkg = clazz.getPackage();
+ if (pkg != null && !this.loggingPackages.contains(pkg.getName())) {
+ return clazz;
+ }
+ }
+ return null;
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/SecurityManagerExecutionStackAccessor.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/SecurityManagerExecutionStackAccessor.java
new file mode 100644
index 0000000..865a287
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/SecurityManagerExecutionStackAccessor.java
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.log.impl;
+
+public final class SecurityManagerExecutionStackAccessor extends SecurityManager implements ExecutionStackAccessor {
+
+ public Class<?>[] getExecutionStack() {
+ Class<?>[] classes = super.getClassContext();
+ Class<?>[] executionStack = new Class<?>[classes.length - 1];
+
+ System.arraycopy(classes, 1, executionStack, 0, executionStack.length);
+
+ return executionStack;
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/StandardCallingBundleResolver.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/StandardCallingBundleResolver.java
new file mode 100644
index 0000000..370221e
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/StandardCallingBundleResolver.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.log.impl;
+
+import org.osgi.framework.Bundle;
+import org.osgi.service.packageadmin.PackageAdmin;
+
+public final class StandardCallingBundleResolver implements CallingBundleResolver {
+
+ private final ExecutionStackAccessor stackAccessor;
+
+ private final ClassSelector classSelector;
+
+ private final PackageAdmin packageAdmin;
+
+ public StandardCallingBundleResolver(ExecutionStackAccessor stackAccessor, ClassSelector classSelector, PackageAdmin packageAdmin) {
+ this.stackAccessor = stackAccessor;
+ this.classSelector = classSelector;
+ this.packageAdmin = packageAdmin;
+ }
+
+ public Bundle getCallingBundle() {
+ Class<?>[] executionStack = this.stackAccessor.getExecutionStack();
+ Class<?> loggingCallersClass = classSelector.select(executionStack);
+ return this.packageAdmin.getBundle(loggingCallersClass);
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/StandardDelegatingPrintStream.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/StandardDelegatingPrintStream.java
new file mode 100644
index 0000000..908a939
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/StandardDelegatingPrintStream.java
@@ -0,0 +1,201 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.log.impl;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.util.Locale;
+
+import org.eclipse.virgo.medic.log.DelegatingPrintStream;
+
+
+/**
+ * Standard implementation of {@link DelegatingPrintStream}.
+ *
+ * <p />
+ *
+ * <strong>Concurrent Semantics</strong><br />
+ *
+ * Thread-safe
+ *
+ */
+public final class StandardDelegatingPrintStream extends PrintStream implements DelegatingPrintStream {
+
+ private static final PrintStream NO_OP_PRINT_STREAM = new PrintStream(new NoOpOutputStream());
+
+ private volatile PrintStream delegate;
+
+ /**
+ * Creates a new <code>StandardDelegatingPrintStream</code> that will delegate to the given <code>delegate</code>.
+ *
+ * @param delegate The delegate
+ */
+ public StandardDelegatingPrintStream(PrintStream delegate) {
+ super(new NoOpOutputStream());
+ setDelegate(delegate);
+ }
+
+ public void setDelegate(PrintStream printStream) {
+ if (printStream == null) {
+ this.delegate = NO_OP_PRINT_STREAM;
+ } else {
+ this.delegate = printStream;
+ }
+ }
+
+ public PrintStream append(char c) {
+ return delegate.append(c);
+ }
+
+ public PrintStream append(CharSequence csq, int start, int end) {
+ return delegate.append(csq, start, end);
+ }
+
+ public PrintStream append(CharSequence csq) {
+ return delegate.append(csq);
+ }
+
+ public boolean checkError() {
+ return delegate.checkError();
+ }
+
+ public void close() {
+ delegate.close();
+ }
+
+ public boolean equals(Object obj) {
+ return delegate.equals(obj);
+ }
+
+ public void flush() {
+ delegate.flush();
+ }
+
+ public PrintStream format(Locale l, String format, Object... args) {
+ return delegate.format(l, format, args);
+ }
+
+ public PrintStream format(String format, Object... args) {
+ return delegate.format(format, args);
+ }
+
+ public int hashCode() {
+ return delegate.hashCode();
+ }
+
+ public void print(boolean b) {
+ delegate.print(b);
+ }
+
+ public void print(char c) {
+ delegate.print(c);
+ }
+
+ public void print(char[] s) {
+ delegate.print(s);
+ }
+
+ public void print(double d) {
+ delegate.print(d);
+ }
+
+ public void print(float f) {
+ delegate.print(f);
+ }
+
+ public void print(int i) {
+ delegate.print(i);
+ }
+
+ public void print(long l) {
+ delegate.print(l);
+ }
+
+ public void print(Object obj) {
+ delegate.print(obj);
+ }
+
+ public void print(String s) {
+ delegate.print(s);
+ }
+
+ public PrintStream printf(Locale l, String format, Object... args) {
+ return delegate.printf(l, format, args);
+ }
+
+ public PrintStream printf(String format, Object... args) {
+ return delegate.printf(format, args);
+ }
+
+ public void println() {
+ delegate.println();
+ }
+
+ public void println(boolean x) {
+ delegate.println(x);
+ }
+
+ public void println(char x) {
+ delegate.println(x);
+ }
+
+ public void println(char[] x) {
+ delegate.println(x);
+ }
+
+ public void println(double x) {
+ delegate.println(x);
+ }
+
+ public void println(float x) {
+ delegate.println(x);
+ }
+
+ public void println(int x) {
+ delegate.println(x);
+ }
+
+ public void println(long x) {
+ delegate.println(x);
+ }
+
+ public void println(Object x) {
+ delegate.println(x);
+ }
+
+ public void println(String x) {
+ delegate.println(x);
+ }
+
+ public String toString() {
+ return delegate.toString();
+ }
+
+ public void write(byte[] buf, int off, int len) {
+ delegate.write(buf, off, len);
+ }
+
+ public void write(byte[] b) throws IOException {
+ delegate.write(b);
+ }
+
+ public void write(int b) {
+ delegate.write(b);
+ }
+
+ private static final class NoOpOutputStream extends OutputStream {
+
+ public void write(int b) throws IOException {
+ }
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/config/BundleResourceConfigurationLocator.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/config/BundleResourceConfigurationLocator.java
new file mode 100644
index 0000000..6039f7d
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/config/BundleResourceConfigurationLocator.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.log.impl.config;
+
+import java.io.IOException;
+import java.net.URL;
+
+import org.eclipse.virgo.medic.log.LoggingConfiguration;
+import org.osgi.framework.Bundle;
+
+
+public final class BundleResourceConfigurationLocator implements ConfigurationLocator {
+
+ public LoggingConfiguration locateConfiguration(Bundle bundle) {
+ if (bundle != null) {
+ URL logBackConfigurationEntry = bundle.getResource("logback.xml");
+
+ if (logBackConfigurationEntry == null) {
+ logBackConfigurationEntry = bundle.getResource("logback-default.xml");
+ }
+
+ if (logBackConfigurationEntry != null) {
+ try {
+ return new StandardLoggingConfiguration(logBackConfigurationEntry, createContextName(bundle));
+ } catch (IOException ioe) {
+ // TODO Exception handling
+ }
+ }
+ }
+
+ return null;
+ }
+
+ private static String createContextName(Bundle bundle) {
+ return bundle.getSymbolicName() + "_" + bundle.getVersion();
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/config/CompositeConfigurationLocator.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/config/CompositeConfigurationLocator.java
new file mode 100644
index 0000000..dec1524
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/config/CompositeConfigurationLocator.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.log.impl.config;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.virgo.medic.log.LoggingConfiguration;
+import org.osgi.framework.Bundle;
+
+
+public final class CompositeConfigurationLocator implements ConfigurationLocator {
+
+ private final List<ConfigurationLocator> configurationLocators;
+
+ public CompositeConfigurationLocator(ConfigurationLocator... configurationLocators) {
+ this.configurationLocators = Arrays.asList(configurationLocators);
+ }
+
+ public LoggingConfiguration locateConfiguration(Bundle bundle) {
+ for (ConfigurationLocator configurationLocator : this.configurationLocators) {
+ LoggingConfiguration configuration = configurationLocator.locateConfiguration(bundle);
+ if (configuration != null) {
+ return configuration;
+ }
+ }
+ return null;
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/config/ConfigurationLocator.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/config/ConfigurationLocator.java
new file mode 100644
index 0000000..921ade7
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/config/ConfigurationLocator.java
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.log.impl.config;
+
+import org.eclipse.virgo.medic.log.LoggingConfiguration;
+import org.osgi.framework.Bundle;
+
+
+public interface ConfigurationLocator {
+
+ LoggingConfiguration locateConfiguration(Bundle bundle);
+}
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/config/ServiceReferenceUtils.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/config/ServiceReferenceUtils.java
new file mode 100644
index 0000000..1bb8d9a
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/config/ServiceReferenceUtils.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.log.impl.config;
+
+import org.osgi.framework.ServiceReference;
+
+class ServiceReferenceUtils {
+
+ static ServiceReference selectServiceReference(ServiceReference[] serviceReferences) {
+ ServiceReference highest = null;
+
+ for (ServiceReference serviceReference : serviceReferences) {
+ if (highest == null || serviceReference.compareTo(highest) > 0) {
+ highest = serviceReference;
+ }
+ }
+
+ return highest;
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/config/ServiceRegistryConfigurationLocator.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/config/ServiceRegistryConfigurationLocator.java
new file mode 100644
index 0000000..01a52e5
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/config/ServiceRegistryConfigurationLocator.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.log.impl.config;
+
+import org.eclipse.virgo.medic.log.LoggingConfiguration;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+
+
+public final class ServiceRegistryConfigurationLocator implements ConfigurationLocator {
+
+ private final BundleContext bundleContext;
+
+ static final String LOGGING_CONFIGURATION_ID_SERVICE_PROPERTY = "org.eclipse.virgo.medic.log.configuration.id";
+
+ private static final String MEDIC_LOGGING_CONFIGURATION_HEADER = "Medic-LoggingConfiguration";
+
+ public ServiceRegistryConfigurationLocator(BundleContext bundleContext) {
+ this.bundleContext = bundleContext;
+ }
+
+ public LoggingConfiguration locateConfiguration(Bundle bundle) {
+ if (bundle != null) {
+ String configurationName = (String) bundle.getHeaders().get(MEDIC_LOGGING_CONFIGURATION_HEADER);
+
+ if (configurationName != null) {
+ try {
+ ServiceReference[] serviceReferences = this.bundleContext.getServiceReferences(LoggingConfiguration.class.getName(), "("
+ + LOGGING_CONFIGURATION_ID_SERVICE_PROPERTY + "=" + configurationName + ")");
+ if (serviceReferences != null && serviceReferences.length > 0) {
+ ServiceReference serviceReference = ServiceReferenceUtils.selectServiceReference(serviceReferences);
+ return (LoggingConfiguration) this.bundleContext.getService(serviceReference);
+ }
+ } catch (InvalidSyntaxException ise) {
+
+ }
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/config/StandardLoggingConfiguration.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/config/StandardLoggingConfiguration.java
new file mode 100644
index 0000000..7e74f91
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/config/StandardLoggingConfiguration.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.log.impl.config;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.URL;
+
+import org.eclipse.virgo.medic.log.LoggingConfiguration;
+
+
+class StandardLoggingConfiguration implements LoggingConfiguration {
+
+ private final String configuration;
+
+ private final String name;
+
+ StandardLoggingConfiguration(URL configuration, String name) throws IOException {
+ this(readConfiguration(configuration), name);
+ }
+
+ StandardLoggingConfiguration(File configuration, String name) throws IOException {
+ this(readConfiguration(configuration), name);
+ }
+
+ private StandardLoggingConfiguration(String configuration, String name) {
+ this.configuration = configuration;
+ this.name = name;
+ }
+
+ public String getConfiguration() {
+ return this.configuration;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ private static String readConfiguration(URL configURL) throws IOException {
+ BufferedReader reader = null;
+ try {
+ reader = new BufferedReader(new InputStreamReader(configURL.openStream()));
+ return readConfiguration(reader);
+ } finally {
+ if (reader != null) {
+ reader.close();
+ }
+ }
+ }
+
+ private static String readConfiguration(File configFile) throws IOException {
+ BufferedReader reader = null;
+ try {
+ reader = new BufferedReader(new FileReader(configFile));
+ return readConfiguration(reader);
+ } finally {
+ if (reader != null) {
+ reader.close();
+ }
+ }
+ }
+
+ private static String readConfiguration(BufferedReader reader) throws IOException {
+ StringBuilder configurationBuilder = new StringBuilder();
+ String line;
+ while ((line = reader.readLine()) != null) {
+ configurationBuilder.append(line);
+ }
+ return configurationBuilder.toString();
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/config/StandardLoggingConfigurationPublisher.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/config/StandardLoggingConfigurationPublisher.java
new file mode 100644
index 0000000..3472dc7
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/config/StandardLoggingConfigurationPublisher.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.log.impl.config;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.eclipse.virgo.medic.log.ConfigurationPublicationFailedException;
+import org.eclipse.virgo.medic.log.LoggingConfiguration;
+import org.eclipse.virgo.medic.log.LoggingConfigurationPublisher;
+import org.osgi.framework.BundleContext;
+
+
+public class StandardLoggingConfigurationPublisher implements LoggingConfigurationPublisher {
+
+ private final BundleContext context;
+
+ private static final String DEFAULT_CONFIGURATION_ID = "org.eclipse.virgo.medic";
+
+ public StandardLoggingConfigurationPublisher(BundleContext context) {
+ this.context = context;
+ }
+
+ public void publishConfiguration(File configuration, String id) throws ConfigurationPublicationFailedException {
+ LoggingConfiguration loggingConfiguration = createLoggingConfiguration(configuration, id);
+ Dictionary<String, String> properties = new Hashtable<String, String>();
+
+ properties.put(ServiceRegistryConfigurationLocator.LOGGING_CONFIGURATION_ID_SERVICE_PROPERTY, id);
+ context.registerService(LoggingConfiguration.class.getName(), loggingConfiguration, properties);
+ }
+
+ private static LoggingConfiguration createLoggingConfiguration(File configuration, String id) throws ConfigurationPublicationFailedException {
+ try {
+ return new StandardLoggingConfiguration(configuration, id);
+ } catch (IOException ioe) {
+ throw new ConfigurationPublicationFailedException("Failed to read the configuration from the file '" + configuration.getAbsolutePath()
+ + "'.", ioe);
+ }
+ }
+
+ public void publishDefaultConfiguration(File file) throws ConfigurationPublicationFailedException {
+ publishConfiguration(file, DEFAULT_CONFIGURATION_ID);
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/logback/ContextSelectorDelegate.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/logback/ContextSelectorDelegate.java
new file mode 100644
index 0000000..cbf8662
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/logback/ContextSelectorDelegate.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.log.impl.logback;
+
+import java.util.List;
+
+import ch.qos.logback.classic.LoggerContext;
+
+public interface ContextSelectorDelegate {
+
+ LoggerContext getLoggerContext();
+
+ LoggerContext getLoggerContext(String name);
+
+ LoggerContext detachLoggerContext(String loggerContextName);
+
+ List<String> getContextNames();
+
+ void configureDefaultContext(LoggerContext defaultContext);
+}
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/logback/DelegatingContextSelector.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/logback/DelegatingContextSelector.java
new file mode 100644
index 0000000..f76f555
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/logback/DelegatingContextSelector.java
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.log.impl.logback;
+
+import java.util.Arrays;
+import java.util.List;
+
+import ch.qos.logback.classic.LoggerContext;
+import ch.qos.logback.classic.selector.ContextSelector;
+
+public class DelegatingContextSelector implements ContextSelector {
+
+ private static volatile ContextSelectorDelegate delegate;
+
+ private static volatile LoggerContext defaultLoggerContext;
+
+ private static volatile boolean defaultContextConfigured;
+
+ public DelegatingContextSelector(LoggerContext loggerContext) {
+ DelegatingContextSelector.setDefaultLoggerContext(loggerContext);
+ }
+
+ private static void setDefaultLoggerContext(LoggerContext loggerContext) {
+ if (delegate != null) {
+ configureDefaultContextIfNecessary(delegate, loggerContext);
+ }
+ DelegatingContextSelector.defaultLoggerContext = loggerContext;
+ }
+
+ private static void configureDefaultContextIfNecessary(ContextSelectorDelegate delegate, LoggerContext defaultLoggerContext) {
+ if (!defaultContextConfigured) {
+ delegate.configureDefaultContext(defaultLoggerContext);
+ defaultContextConfigured = true;
+ }
+ }
+
+ public LoggerContext detachLoggerContext(String loggerContextName) {
+ if (delegate == null) {
+ return DelegatingContextSelector.defaultLoggerContext;
+ }
+ return delegate.detachLoggerContext(loggerContextName);
+ }
+
+ public List<String> getContextNames() {
+ if (delegate == null) {
+ return Arrays.asList(defaultLoggerContext.getName());
+ }
+ return delegate.getContextNames();
+ }
+
+ public LoggerContext getDefaultLoggerContext() {
+ return DelegatingContextSelector.defaultLoggerContext;
+ }
+
+ public LoggerContext getLoggerContext() {
+ if (delegate == null) {
+ return defaultLoggerContext;
+ }
+
+ LoggerContext loggerContext = delegate.getLoggerContext();
+ if (loggerContext != null) {
+ return loggerContext;
+ }
+
+ return defaultLoggerContext;
+ }
+
+ public LoggerContext getLoggerContext(String name) {
+ if (name.equals(defaultLoggerContext.getName())) {
+ return defaultLoggerContext;
+ }
+ return delegate.getLoggerContext(name);
+ }
+
+ public static void setDelegate(ContextSelectorDelegate delegate) {
+ if (delegate != null) {
+ if (defaultLoggerContext != null) {
+ configureDefaultContextIfNecessary(delegate, defaultLoggerContext);
+ }
+ }
+ DelegatingContextSelector.delegate = delegate;
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/logback/JoranLoggerContextConfigurer.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/logback/JoranLoggerContextConfigurer.java
new file mode 100644
index 0000000..3eb52c9
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/logback/JoranLoggerContextConfigurer.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.log.impl.logback;
+
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.virgo.medic.log.LoggingConfiguration;
+import org.xml.sax.InputSource;
+
+import ch.qos.logback.classic.LoggerContext;
+import ch.qos.logback.classic.joran.JoranConfigurator;
+import ch.qos.logback.core.joran.spi.JoranException;
+import ch.qos.logback.core.status.Status;
+
+
+public final class JoranLoggerContextConfigurer implements LoggerContextConfigurer {
+
+ public void applyConfiguration(LoggingConfiguration configuration, LoggerContext loggerContext) throws LoggerContextConfigurationFailedException {
+ JoranConfigurator configurator = new JoranConfigurator();
+ configurator.setContext(loggerContext);
+ String configurationString = configuration.getConfiguration();
+ try {
+ configurator.doConfigure(new InputSource(new StringReader(configurationString)));
+ List<Status> statusList = loggerContext.getStatusManager().getCopyOfStatusList();
+ List<String> failureMessages = new ArrayList<String>();
+ for (Status status : statusList) {
+ if (Status.INFO != status.getLevel()) {
+ failureMessages.add(status.getMessage());
+ }
+ }
+ reportFailureIfNecessary(failureMessages);
+ } catch (JoranException je) {
+ throw new LoggerContextConfigurationFailedException("Configuration failed", je);
+ }
+ }
+
+ private static void reportFailureIfNecessary(List<String> failureMessages) throws LoggerContextConfigurationFailedException {
+ if (!failureMessages.isEmpty()) {
+ throw new LoggerContextConfigurationFailedException("Configuration failed with the following problems: " + failureMessages);
+ }
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/logback/LoggerContextConfigurationFailedException.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/logback/LoggerContextConfigurationFailedException.java
new file mode 100644
index 0000000..f4daea8
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/logback/LoggerContextConfigurationFailedException.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.log.impl.logback;
+
+class LoggerContextConfigurationFailedException extends Exception {
+
+ private static final long serialVersionUID = -4259913727730630284L;
+
+ public LoggerContextConfigurationFailedException(String message) {
+ super(message);
+ }
+
+ public LoggerContextConfigurationFailedException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/logback/LoggerContextConfigurer.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/logback/LoggerContextConfigurer.java
new file mode 100644
index 0000000..653cd59
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/logback/LoggerContextConfigurer.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.log.impl.logback;
+
+import org.eclipse.virgo.medic.log.LoggingConfiguration;
+
+import ch.qos.logback.classic.LoggerContext;
+
+
+public interface LoggerContextConfigurer {
+
+ void applyConfiguration(LoggingConfiguration configuration, LoggerContext loggerContext) throws LoggerContextConfigurationFailedException;
+}
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/logback/StandardContextSelectorDelegate.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/logback/StandardContextSelectorDelegate.java
new file mode 100644
index 0000000..e7992d5
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/impl/logback/StandardContextSelectorDelegate.java
@@ -0,0 +1,147 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.log.impl.logback;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.WeakHashMap;
+
+import org.eclipse.virgo.medic.log.LoggingConfiguration;
+import org.eclipse.virgo.medic.log.impl.CallingBundleResolver;
+import org.eclipse.virgo.medic.log.impl.config.ConfigurationLocator;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.BundleListener;
+
+import ch.qos.logback.classic.LoggerContext;
+
+
+public class StandardContextSelectorDelegate implements ContextSelectorDelegate, BundleListener {
+
+ private final CallingBundleResolver loggingCallerLocator;
+
+ private final Map<String, LoggerContext> loggerContexts = new HashMap<String, LoggerContext>();
+
+ private final Map<Bundle, LoggingConfiguration> loggingConfigurations = new WeakHashMap<Bundle, LoggingConfiguration>();
+
+ private final Object monitor = new Object();
+
+ private final ConfigurationLocator configurationLocator;
+
+ private final LoggerContextConfigurer configurer;
+
+ private final Bundle medicBundle;
+
+ public StandardContextSelectorDelegate(CallingBundleResolver loggingCallerLocator, ConfigurationLocator configurationLocator, Bundle medicBundle,
+ LoggerContextConfigurer configurer) {
+ this.loggingCallerLocator = loggingCallerLocator;
+ this.configurationLocator = configurationLocator;
+ this.medicBundle = medicBundle;
+ this.configurer = configurer;
+ }
+
+ public LoggerContext detachLoggerContext(String name) {
+ synchronized (monitor) {
+ return this.loggerContexts.remove(name);
+ }
+ }
+
+ public List<String> getContextNames() {
+ synchronized (this.monitor) {
+ List<String> names = new ArrayList<String>();
+ names.addAll(this.loggerContexts.keySet());
+ return names;
+ }
+ }
+
+ public LoggerContext getLoggerContext() {
+ Bundle callingBundle = this.loggingCallerLocator.getCallingBundle();
+
+ LoggingConfiguration loggingConfiguration = null;
+
+ if (callingBundle != null) {
+ synchronized(this.monitor) {
+ loggingConfiguration = this.loggingConfigurations.get(callingBundle);
+ }
+ }
+
+ if (loggingConfiguration == null) {
+ loggingConfiguration = locateConfiguration(callingBundle);
+ if (loggingConfiguration != null && callingBundle != null) {
+ synchronized(this.monitor) {
+ this.loggingConfigurations.put(callingBundle, loggingConfiguration);
+ }
+ }
+ }
+
+ if (loggingConfiguration != null) {
+ synchronized (this.monitor) {
+ LoggerContext existingContext = this.loggerContexts.get(loggingConfiguration.getName());
+ if (existingContext != null) {
+ return existingContext;
+ } else {
+ LoggerContext configuredContext = createConfiguredContext(loggingConfiguration);
+ this.loggerContexts.put(loggingConfiguration.getName(), configuredContext);
+ return configuredContext;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ private LoggingConfiguration locateConfiguration(Bundle callingBundle) {
+ return this.configurationLocator.locateConfiguration(callingBundle);
+ }
+
+ private LoggerContext createConfiguredContext(LoggingConfiguration configuration) {
+ LoggerContext loggerContext = new LoggerContext();
+ loggerContext.setName(configuration.getName());
+
+ try {
+ this.configurer.applyConfiguration(configuration, loggerContext);
+ } catch (LoggerContextConfigurationFailedException lccfe) {
+ lccfe.printStackTrace(System.err);
+ }
+
+ return loggerContext;
+ }
+
+ public LoggerContext getLoggerContext(String name) {
+ synchronized (monitor) {
+ return this.loggerContexts.get(name);
+ }
+ }
+
+ public void configureDefaultContext(LoggerContext defaultContext) {
+ LoggingConfiguration configuration = locateConfiguration(this.medicBundle);
+
+ if (configuration != null) {
+ defaultContext.reset();
+ try {
+ this.configurer.applyConfiguration(configuration, defaultContext);
+ } catch (LoggerContextConfigurationFailedException lccfe) {
+ lccfe.printStackTrace(System.err);
+ }
+ }
+ }
+
+ public void bundleChanged(BundleEvent event) {
+ if (BundleEvent.UPDATED == event.getType()) {
+ synchronized (this.monitor) {
+ this.loggingConfigurations.remove(event.getBundle());
+ }
+ }
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/logback/ReroutingAwareConsoleAppender.java b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/logback/ReroutingAwareConsoleAppender.java
new file mode 100644
index 0000000..0463c47
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/java/org/eclipse/virgo/medic/log/logback/ReroutingAwareConsoleAppender.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.log.logback;
+
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+
+import org.eclipse.virgo.medic.log.impl.LoggingPrintStreamWrapper;
+
+import ch.qos.logback.core.ConsoleAppender;
+
+
+/**
+ * A special {@link ConsoleAppender} that is aware of re-routing of <code>System.out</code> and <code>System.err</code>
+ * and will always use the original <code>System.out</code> and <code>System.err</code>, rather than the ones that are being rerouted.
+ * <p />
+ *
+ * <strong>Concurrent Semantics</strong><br />
+ *
+ * Thread-safe.
+ *
+ * @param <E> Event type being logged
+ */
+public class ReroutingAwareConsoleAppender<E> extends ConsoleAppender<E> {
+
+ protected OutputStreamWriter createWriter(OutputStream os) {
+ if (os instanceof LoggingPrintStreamWrapper) {
+ return super.createWriter(((LoggingPrintStreamWrapper)os).getOriginalPrintStream());
+ } else {
+ return super.createWriter(os);
+ }
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/main/resources/EventLogMessages_en.properties b/org.eclipse.virgo.medic.core/src/main/resources/EventLogMessages_en.properties
new file mode 100644
index 0000000..5931f9d
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/resources/EventLogMessages_en.properties
@@ -0,0 +1,3 @@
+ME0001W=The directory '{}' does not exist and could not be created
+ME0002W=Dump contributor '{}' failed during contribution to dump '{}'
+ME0003I=Dump '{}' generated
diff --git a/org.eclipse.virgo.medic.core/src/main/resources/logback-default.xml b/org.eclipse.virgo.medic.core/src/main/resources/logback-default.xml
new file mode 100644
index 0000000..cbd6eb2
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/main/resources/logback-default.xml
@@ -0,0 +1,39 @@
+<configuration>
+
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+ <layout class="ch.qos.logback.classic.PatternLayout">
+ <Pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] %-24.24thread %msg %ex%n</Pattern>
+ </layout>
+ </appender>
+
+ <appender name="EVENT_LOG_STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+ <layout class="ch.qos.logback.classic.PatternLayout">
+ <Pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] %-24.24thread &lt;%X{medic.eventCode}&gt; %msg %ex%n</Pattern>
+ </layout>
+ </appender>
+
+ <appender name="EVENT_LOG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <file>serviceability/eventlog/eventlog.log</file>
+ <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
+ <FileNamePattern>serviceability/eventlog/eventlog_%i.log</FileNamePattern>
+ <MinIndex>1</MinIndex>
+ <MaxIndex>4</MaxIndex>
+ </rollingPolicy>
+ <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
+ <MaxFileSize>10MB</MaxFileSize>
+ </triggeringPolicy>
+ <layout class="ch.qos.logback.classic.PatternLayout">
+ <Pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] %-24.24thread &lt;%X{medic.eventCode}&gt; %msg %ex%n</Pattern>
+ </layout>
+ </appender>
+
+ <logger name="org.eclipse.virgo.medic.eventlog.localized">
+ <appender-ref ref="EVENT_LOG_STDOUT" />
+ <appender-ref ref="EVENT_LOG_FILE" />
+ </logger>
+
+ <root level="debug">
+ <appender-ref ref="STDOUT" />
+ </root>
+
+</configuration>
diff --git a/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/dump/impl/DumpContributorTrackerTests.java b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/dump/impl/DumpContributorTrackerTests.java
new file mode 100644
index 0000000..bbf5f7b
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/dump/impl/DumpContributorTrackerTests.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.dump.impl;
+
+import static org.easymock.EasyMock.createMock;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+
+import java.util.List;
+
+import org.junit.Test;
+import org.osgi.framework.ServiceRegistration;
+
+import org.eclipse.virgo.medic.dump.DumpContributor;
+import org.eclipse.virgo.medic.dump.impl.DumpContributorTracker;
+import org.eclipse.virgo.teststubs.osgi.framework.StubBundleContext;
+
+public class DumpContributorTrackerTests {
+
+ @Test
+ public void serviceAdditionAndRemoval() {
+ StubBundleContext bundleContext = new StubBundleContext();
+ DumpContributor service = createMock(DumpContributor.class);
+ ServiceRegistration serviceRegistration = bundleContext.registerService(DumpContributor.class.getName(), service, null);
+
+ DumpContributorTracker tracker = new DumpContributorTracker(bundleContext);
+
+ tracker.addingService(serviceRegistration.getReference());
+ List<DumpContributor> contributors = tracker.getDumpContributors();
+ assertEquals(1, contributors.size());
+ assertSame(service, contributors.get(0));
+
+ tracker.removedService(serviceRegistration.getReference(), service);
+ contributors = tracker.getDumpContributors();
+ assertEquals(0, contributors.size());
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/dump/impl/HeapDumpContributorTests.java b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/dump/impl/HeapDumpContributorTests.java
new file mode 100644
index 0000000..08042c8
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/dump/impl/HeapDumpContributorTests.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.dump.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.virgo.medic.dump.Dump;
+import org.eclipse.virgo.medic.dump.DumpContributionFailedException;
+import org.eclipse.virgo.medic.dump.DumpContributor;
+import org.eclipse.virgo.medic.dump.impl.heap.HeapDumpContributor;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+
+public class HeapDumpContributorTests {
+
+ private final File dumpDirectory = new File("target");
+
+ @Before
+ @After
+ public void cleanupHeadDumps() {
+ File heapDumpFile = new File("target", "heap.out");
+ if (heapDumpFile.exists()) {
+ assertTrue(heapDumpFile.delete());
+ }
+ }
+
+ @Test
+ public void dumpHeap() throws DumpContributionFailedException {
+ DumpContributor contributor = new HeapDumpContributor();
+
+ String cause = "failure";
+ long timestamp = System.currentTimeMillis();
+ Map<String, Object> context = new HashMap<String, Object>();
+
+ Dump dump = new StubDump(cause, timestamp, context, new Throwable[0], dumpDirectory);
+
+ contributor.contribute(dump);
+
+ boolean managementFactoryAvailable;
+
+ try {
+ Class.forName("sun.management.ManagementFactory").getMethod("getDiagnosticMXBean");
+ managementFactoryAvailable = true;
+ } catch (Exception e) {
+ managementFactoryAvailable = false;
+ }
+
+ assertEquals(managementFactoryAvailable, new File(this.dumpDirectory, "heap.out").exists());
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/dump/impl/StandardDumpGeneratorTests.java b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/dump/impl/StandardDumpGeneratorTests.java
new file mode 100644
index 0000000..be37e8b
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/dump/impl/StandardDumpGeneratorTests.java
@@ -0,0 +1,147 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.dump.impl;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
+import static org.easymock.EasyMock.isA;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+
+import java.util.Arrays;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+
+import org.eclipse.virgo.medic.dump.Dump;
+import org.eclipse.virgo.medic.dump.DumpContributor;
+import org.eclipse.virgo.medic.dump.DumpGenerationFailedException;
+import org.eclipse.virgo.medic.dump.DumpGenerator;
+import org.eclipse.virgo.medic.dump.impl.DumpContributorResolver;
+import org.eclipse.virgo.medic.dump.impl.StandardDumpGenerator;
+import org.eclipse.virgo.medic.eventlog.EventLogger;
+import org.eclipse.virgo.medic.impl.config.ConfigurationProvider;
+import org.junit.Test;
+
+
+public class StandardDumpGeneratorTests {
+
+ @Test
+ public void dumpGeneration() throws DumpGenerationFailedException {
+
+ Map<String, Object> context = new HashMap<String, Object>();
+
+ EventLogger eventLogger = createMock(EventLogger.class);
+
+ DumpContributorResolver accessor = createMock(DumpContributorResolver.class);
+ DumpContributor dumpContributor1 = createMock(DumpContributor.class);
+
+ expect(accessor.getDumpContributors()).andReturn(Arrays.asList(dumpContributor1));
+ dumpContributor1.contribute(isA(Dump.class));
+ expectLastCall();
+
+ context = new HashMap<String, Object>();
+ context.put("key", "value");
+
+ dumpContributor1.contribute(isA(Dump.class));
+ expect(dumpContributor1.getName()).andReturn("dc1").anyTimes();
+
+ DumpContributor dumpContributor2 = createMock(DumpContributor.class);
+ dumpContributor2.contribute(isA(Dump.class));
+ expect(dumpContributor2.getName()).andReturn("dc2").anyTimes();
+
+ expect(accessor.getDumpContributors()).andReturn(Arrays.asList(dumpContributor1, dumpContributor2));
+
+ ConfigurationProvider configurationProvider = createMock(ConfigurationProvider.class);
+ Dictionary<Object, Object> configuration = new Hashtable<Object, Object>();
+ configuration.put(ConfigurationProvider.KEY_DUMP_ROOT_DIRECTORY, "target");
+ expect(configurationProvider.getConfiguration()).andReturn(configuration).anyTimes();
+
+ replay(accessor, dumpContributor1, dumpContributor2, configurationProvider);
+
+ DumpGenerator dumpGenerator = new StandardDumpGenerator(accessor, configurationProvider, eventLogger);
+ dumpGenerator.generateDump("foo");
+ dumpGenerator.generateDump("bar", context);
+
+ verify(accessor, dumpContributor1, dumpContributor2, configurationProvider);
+ }
+
+ @Test
+ public void singleExclusion() throws DumpGenerationFailedException {
+ EventLogger eventLogger = createMock(EventLogger.class);
+ DumpContributorResolver accessor = createMock(DumpContributorResolver.class);
+ DumpContributor dumpContributor1 = createMock(DumpContributor.class);
+
+ expect(accessor.getDumpContributors()).andReturn(Arrays.asList(dumpContributor1)).times(2);
+ dumpContributor1.contribute(isA(Dump.class));
+ expect(dumpContributor1.getName()).andReturn("dc1").times(2);
+
+ ConfigurationProvider configurationProvider = createMock(ConfigurationProvider.class);
+ Dictionary<Object, Object> configuration = new Hashtable<Object, Object>();
+ configuration.put("dump.root.directory", "target");
+ configuration.put("dump.exclusions.foo", "dc1");
+ expect(configurationProvider.getConfiguration()).andReturn(configuration).anyTimes();
+
+ replay(accessor, dumpContributor1, configurationProvider);
+
+ DumpGenerator dumpGenerator = new StandardDumpGenerator(accessor, configurationProvider, eventLogger);
+ dumpGenerator.generateDump("foo");
+ dumpGenerator.generateDump("bar");
+
+ verify(accessor, dumpContributor1, configurationProvider);
+ }
+
+ @Test
+ public void multipleExclusion() throws DumpGenerationFailedException {
+ EventLogger eventLogger = createMock(EventLogger.class);
+ DumpContributorResolver accessor = createMock(DumpContributorResolver.class);
+ DumpContributor dumpContributor1 = createMock(DumpContributor.class);
+ DumpContributor dumpContributor2 = createMock(DumpContributor.class);
+
+ expect(accessor.getDumpContributors()).andReturn(Arrays.asList(dumpContributor1, dumpContributor2)).times(2);
+ dumpContributor1.contribute(isA(Dump.class));
+ dumpContributor2.contribute(isA(Dump.class));
+ expect(dumpContributor1.getName()).andReturn("dc1").times(2);
+ expect(dumpContributor2.getName()).andReturn("dc2").times(2);
+
+ ConfigurationProvider configurationProvider = createMock(ConfigurationProvider.class);
+ Dictionary<Object, Object> configuration = new Hashtable<Object, Object>();
+ configuration.put("dump.root.directory", "target");
+ configuration.put("dump.exclusions.foo", "dc1, dc2");
+ expect(configurationProvider.getConfiguration()).andReturn(configuration).anyTimes();
+
+ replay(accessor, dumpContributor1, dumpContributor2, configurationProvider);
+
+ DumpGenerator dumpGenerator = new StandardDumpGenerator(accessor, configurationProvider, eventLogger);
+ dumpGenerator.generateDump("foo");
+ dumpGenerator.generateDump("bar");
+
+ verify(accessor, dumpContributor1, dumpContributor2, configurationProvider);
+ }
+
+ @Test
+ public void close() {
+ EventLogger eventLogger = createMock(EventLogger.class);
+ DumpContributorResolver accessor = createMock(DumpContributorResolver.class);
+ ConfigurationProvider configurationProvider = createMock(ConfigurationProvider.class);
+ accessor.close();
+
+ replay(accessor, configurationProvider);
+
+ StandardDumpGenerator dumpGenerator = new StandardDumpGenerator(accessor, configurationProvider, eventLogger);
+ dumpGenerator.close();
+
+ verify(accessor, configurationProvider);
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/dump/impl/StubDump.java b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/dump/impl/StubDump.java
new file mode 100644
index 0000000..fc88eca
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/dump/impl/StubDump.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.dump.impl;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.Map;
+
+import org.eclipse.virgo.medic.dump.Dump;
+import org.eclipse.virgo.medic.dump.DumpContributionFailedException;
+
+
+public class StubDump implements Dump {
+
+ private final File outputDirectory;
+
+ private final String cause;
+
+ private final Map<String, Object> context;
+
+ private final Throwable[] throwables;
+
+ private final long timestamp;
+
+ public StubDump(String cause, long timestamp, Map<String, Object> context, Throwable[] throwables, File outputDirectory) {
+ this.cause = cause;
+ this.timestamp = timestamp;
+ this.context = context;
+ this.throwables = throwables;
+ this.outputDirectory = outputDirectory;
+ }
+
+ public File createFile(String name) {
+ return new File(outputDirectory, name);
+ }
+
+ public FileOutputStream createFileOutputStream(String name) throws DumpContributionFailedException {
+ try {
+ return new FileOutputStream(createFile(name));
+ } catch (FileNotFoundException e) {
+ throw new DumpContributionFailedException("Unable to open output stream '" + name + "'");
+ }
+ }
+
+ public FileWriter createFileWriter(String name) throws DumpContributionFailedException {
+ try {
+ return new FileWriter(createFile(name));
+ } catch (IOException e) {
+ throw new DumpContributionFailedException("Unable to open file writer '" + name + "'");
+ }
+ }
+
+ public String getCause() {
+ return this.cause;
+ }
+
+ public Map<String, Object> getContext() {
+ return this.context;
+ }
+
+ public Throwable[] getThrowables() {
+ return this.throwables;
+ }
+
+ public long getTimestamp() {
+ return this.timestamp;
+ }
+
+}
diff --git a/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/dump/impl/logback/LogDumpContributorTests.java b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/dump/impl/logback/LogDumpContributorTests.java
new file mode 100644
index 0000000..8a5e369
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/dump/impl/logback/LogDumpContributorTests.java
@@ -0,0 +1,126 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.dump.impl.logback;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.eclipse.virgo.medic.dump.DumpContributionFailedException;
+import org.eclipse.virgo.medic.dump.impl.logback.LogDumpContributor;
+import org.eclipse.virgo.medic.impl.config.ConfigurationProvider;
+import org.junit.Test;
+import org.slf4j.LoggerFactory;
+
+import ch.qos.logback.classic.Level;
+
+import ch.qos.logback.classic.Logger;
+
+
+public class LogDumpContributorTests {
+
+ @Test
+ public void emptyLog() throws DumpContributionFailedException {
+ LogDumpContributor contributor = getContributor();
+ StubDump dump = getDump();
+ contributor.contribute(dump);
+
+ File logFile = dump.createFile("log.log");
+ assertTrue(logFile.exists());
+ assertEquals(0, logFile.length());
+ }
+
+ @Test
+ public void nonEmptyLog() throws DumpContributionFailedException {
+ LogDumpContributor contributor = getContributor();
+ StubDump dump = getDump();
+
+ driveLogging(contributor);
+
+ contributor.contribute(dump);
+
+ File logFile = dump.createFile("log.log");
+ assertTrue(logFile.exists());
+ assertEquals(1, countLines(logFile));
+ }
+
+ @Test
+ public void wrappedLog() throws DumpContributionFailedException {
+ LogDumpContributor contributor = getContributor();
+ StubDump dump = getDump();
+ driveLogging(contributor);
+ driveLogging(contributor);
+ driveLogging(contributor);
+
+ contributor.contribute(dump);
+
+ File logFile = dump.createFile("log.log");
+ assertTrue(logFile.exists());
+ assertEquals(2, countLines(logFile));
+ }
+
+ private LogDumpContributor getContributor() {
+ LogDumpContributor contributor = new LogDumpContributor(new StaticConfigurationProvider());
+ return contributor;
+ }
+
+ private StubDump getDump() {
+ File dumpRoot = new File("target/serviceability/dump");
+ dumpRoot.mkdirs();
+ return new StubDump("testCause", new Date().getTime(), Collections.<String, Object> emptyMap(), new Throwable[0], dumpRoot);
+ }
+
+ private int countLines(File logFile) {
+ BufferedReader reader = null;
+ int count = 0;
+ try {
+ reader = new BufferedReader(new FileReader(logFile));
+ while (reader.readLine() != null) {
+ count++;
+ }
+ } catch (FileNotFoundException e) {
+ } catch (IOException e) {
+ } finally {
+ try {
+ if (reader != null) {
+ reader.close();
+ }
+ } catch (IOException e) {
+ }
+ }
+
+ return count;
+ }
+
+ private static final class StaticConfigurationProvider implements ConfigurationProvider {
+ @SuppressWarnings("unchecked")
+ public Dictionary getConfiguration() {
+ Hashtable configuration = new Hashtable();
+ configuration.put(ConfigurationProvider.KEY_LOG_DUMP_LEVEL, "debug");
+ configuration.put(ConfigurationProvider.KEY_LOG_DUMP_BUFFERSIZE, "2");
+ return configuration;
+ }
+ }
+
+ private final void driveLogging(LogDumpContributor loggingContributor) {
+ loggingContributor.onLogging((Logger)LoggerFactory.getLogger("test"), "com.foo.bar", null, Level.INFO, "test", null, null);
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/dump/impl/logback/StubDump.java b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/dump/impl/logback/StubDump.java
new file mode 100644
index 0000000..6890508
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/dump/impl/logback/StubDump.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.dump.impl.logback;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.Map;
+
+import org.eclipse.virgo.medic.dump.Dump;
+import org.eclipse.virgo.medic.dump.DumpContributionFailedException;
+
+
+public class StubDump implements Dump {
+
+ private final File outputDirectory;
+
+ private final String cause;
+
+ private final Map<String, Object> context;
+
+ private final Throwable[] throwables;
+
+ private final long timestamp;
+
+ public StubDump(String cause, long timestamp, Map<String, Object> context, Throwable[] throwables, File outputDirectory) {
+ this.cause = cause;
+ this.timestamp = timestamp;
+ this.context = context;
+ this.throwables = throwables;
+ this.outputDirectory = outputDirectory;
+ }
+
+ public File createFile(String name) {
+ return new File(outputDirectory, name);
+ }
+
+ public FileOutputStream createFileOutputStream(String name) throws DumpContributionFailedException {
+ try {
+ return new FileOutputStream(createFile(name));
+ } catch (FileNotFoundException e) {
+ throw new DumpContributionFailedException("Unable to open output stream '" + name + "'");
+ }
+ }
+
+ public FileWriter createFileWriter(String name) throws DumpContributionFailedException {
+ try {
+ return new FileWriter(createFile(name));
+ } catch (IOException e) {
+ throw new DumpContributionFailedException("Unable to open file writer '" + name + "'");
+ }
+ }
+
+ public String getCause() {
+ return this.cause;
+ }
+
+ public Map<String, Object> getContext() {
+ return this.context;
+ }
+
+ public Throwable[] getThrowables() {
+ return this.throwables;
+ }
+
+ public long getTimestamp() {
+ return this.timestamp;
+ }
+
+}
diff --git a/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/dump/impl/summary/SummaryDumpContributorTests.java b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/dump/impl/summary/SummaryDumpContributorTests.java
new file mode 100644
index 0000000..5c05b8f
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/dump/impl/summary/SummaryDumpContributorTests.java
@@ -0,0 +1,147 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.dump.impl.summary;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.text.DateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.virgo.medic.dump.Dump;
+import org.eclipse.virgo.medic.dump.DumpContributionFailedException;
+import org.eclipse.virgo.medic.dump.DumpContributor;
+import org.eclipse.virgo.medic.dump.impl.StubDump;
+import org.eclipse.virgo.medic.dump.impl.summary.SummaryDumpContributor;
+import org.junit.Test;
+
+
+public class SummaryDumpContributorTests {
+
+ private final DumpContributor dumpContributor = new SummaryDumpContributor();
+
+ private final File dumpDirectory = new File("target");
+
+ private final DateFormat dateFormat = DateFormat.getDateInstance();
+
+ private final DateFormat timeFormat = DateFormat.getTimeInstance(DateFormat.LONG);
+
+ @Test
+ public void dumpWithoutThrowable() throws DumpContributionFailedException, IOException {
+
+ String cause = "failure";
+ long timestamp = System.currentTimeMillis();
+ Map<String, Object> context = new HashMap<String, Object>();
+
+ Dump dump = new StubDump(cause, timestamp, context, new Throwable[0], dumpDirectory);
+
+ this.dumpContributor.contribute(dump);
+
+ File dumpFile = new File(dumpDirectory, "summary.txt");
+ assertTrue(dumpFile.exists());
+ assertDumpContents(dumpFile, timestamp, cause);
+ }
+
+ @Test
+ public void dumpWithThrowable() throws DumpContributionFailedException, IOException {
+
+ String cause = "failure";
+ long timestamp = System.currentTimeMillis();
+ Map<String, Object> context = new HashMap<String, Object>();
+
+ NullPointerException npe = new NullPointerException();
+ npe.fillInStackTrace();
+
+ Dump dump = new StubDump(cause, timestamp, context, new Throwable[] { npe }, dumpDirectory);
+
+ this.dumpContributor.contribute(dump);
+
+ File dumpFile = new File(dumpDirectory, "summary.txt");
+ assertTrue(dumpFile.exists());
+ assertDumpContents(dumpFile, timestamp, cause, npe);
+ }
+
+ private void assertDumpContents(File dumpFile, long timestamp, String cause, Throwable... throwables) throws IOException {
+ BufferedReader input = new BufferedReader(new FileReader(dumpFile));
+
+ List<String> lines = new ArrayList<String>();
+
+ String line;
+
+ while ((line = input.readLine()) != null) {
+ lines.add(line);
+ }
+
+ assertDatePresent(lines, timestamp);
+ assertTimePresent(lines, timestamp);
+ assertCausePresent(lines, cause);
+ assertThrowablesPresent(lines, throwables);
+ }
+
+ private void assertDatePresent(List<String> lines, long timestamp) {
+ String expectedDate = this.dateFormat.format(new Date(timestamp));
+
+ for (String line : lines) {
+ if (line.contains(expectedDate)) {
+ return;
+ }
+ }
+
+ fail(String.format("The date '%s' was not found in the dump", expectedDate));
+ }
+
+ private void assertTimePresent(List<String> lines, long timestamp) {
+ String expectedTime = this.timeFormat.format(new Date(timestamp));
+
+ for (String line : lines) {
+ if (line.contains(expectedTime)) {
+ return;
+ }
+ }
+
+ fail(String.format("The time '%s' was not found in the dump", expectedTime));
+ }
+
+ private void assertCausePresent(List<String> lines, String cause) {
+ String expectedCause = "Cause: " + cause;
+ for (String line : lines) {
+ if (line.contains(expectedCause)) {
+ return;
+ }
+ }
+ fail(String.format("The expected cause entry '%s' was not found in the dump", expectedCause));
+ }
+
+ private void assertThrowablesPresent(List<String> lines, Throwable... throwables) {
+ String expectedException;
+ if (throwables.length == 0) {
+ expectedException = "Exception: None";
+ } else {
+ expectedException = "Exception:";
+ }
+
+ for (String line : lines) {
+ if (line.equals(expectedException)) {
+ return;
+ }
+ }
+ fail(String.format("The expected exception entry '%s' was not found in the dump", expectedException));
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/dump/impl/thread/ThreadDumpContributorTests.java b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/dump/impl/thread/ThreadDumpContributorTests.java
new file mode 100644
index 0000000..480af0f
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/dump/impl/thread/ThreadDumpContributorTests.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.dump.impl.thread;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.virgo.medic.dump.Dump;
+import org.eclipse.virgo.medic.dump.DumpContributionFailedException;
+import org.eclipse.virgo.medic.dump.DumpContributor;
+import org.eclipse.virgo.medic.dump.impl.StubDump;
+import org.eclipse.virgo.medic.dump.impl.thread.Java5ThreadInfoWriter;
+import org.eclipse.virgo.medic.dump.impl.thread.Java5ThreadMXBeanDelegate;
+import org.eclipse.virgo.medic.dump.impl.thread.StandardThreadInfoWriter;
+import org.eclipse.virgo.medic.dump.impl.thread.StandardThreadMXBeanDelegate;
+import org.eclipse.virgo.medic.dump.impl.thread.ThreadDumpContributor;
+import org.junit.Test;
+
+
+public class ThreadDumpContributorTests {
+
+ private final File dumpDirectory = new File("target");
+
+ @Test
+ public void java5ThreadDump() throws DumpContributionFailedException {
+ DumpContributor contributor = new ThreadDumpContributor(new Java5ThreadMXBeanDelegate(), new Java5ThreadInfoWriter());
+ createContribution(contributor);
+ }
+
+ @Test
+ public void standardThreadDump() throws DumpContributionFailedException {
+ DumpContributor contributor = new ThreadDumpContributor(new StandardThreadMXBeanDelegate(), new StandardThreadInfoWriter());
+ createContribution(contributor);
+ }
+
+ private void createContribution(DumpContributor contributor) throws DumpContributionFailedException {
+ String cause = "failure";
+ long timestamp = System.currentTimeMillis();
+ Map<String, Object> context = new HashMap<String, Object>();
+
+ Dump dump = new StubDump(cause, timestamp, context, new Throwable[0], this.dumpDirectory);
+
+ contributor.contribute(dump);
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/eventlog/impl/BundleSearchingPropertyResourceBundleResolverTests.java b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/eventlog/impl/BundleSearchingPropertyResourceBundleResolverTests.java
new file mode 100644
index 0000000..ead586b
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/eventlog/impl/BundleSearchingPropertyResourceBundleResolverTests.java
@@ -0,0 +1,89 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.eventlog.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.PropertyResourceBundle;
+import java.util.Vector;
+
+import org.junit.Test;
+
+import org.eclipse.virgo.medic.eventlog.impl.BundleSearchingPropertyResourceBundleResolver;
+import org.eclipse.virgo.medic.eventlog.impl.PropertyResourceBundleResolver;
+import org.eclipse.virgo.teststubs.osgi.framework.FindEntriesDelegate;
+import org.eclipse.virgo.teststubs.osgi.framework.StubBundle;
+
+public class BundleSearchingPropertyResourceBundleResolverTests {
+
+ private final PropertyResourceBundleResolver resourceBundleResolver = new BundleSearchingPropertyResourceBundleResolver();
+
+ @Test
+ public void entryNotFound() {
+ StubBundle bundle = new StubBundle().setFindEntriesDelegate(new FindEntriesDelegate() {
+
+ public Enumeration<?> findEntries(String path, String pattern, boolean recurse) {
+ return null;
+ }
+ });
+ List<PropertyResourceBundle> resourceBundles = this.resourceBundleResolver.getResourceBundles(bundle, "foo.properties");
+ assertNotNull(resourceBundles);
+ assertEquals(0, resourceBundles.size());
+ }
+
+ @Test
+ public void nonExistentEntry() {
+ StubBundle bundle = new StubBundle().setFindEntriesDelegate(new FindEntriesDelegate() {
+
+ public Enumeration<?> findEntries(String path, String pattern, boolean recurse) {
+ try {
+ Vector<URL> urls = new Vector<URL>();
+ urls.add(new File("does/not/exist").toURI().toURL());
+ return urls.elements();
+ } catch (MalformedURLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ });
+
+ List<PropertyResourceBundle> resourceBundles = this.resourceBundleResolver.getResourceBundles(bundle, "foo.properties");
+ assertNotNull(resourceBundles);
+ assertEquals(0, resourceBundles.size());
+ }
+
+ @Test
+ public void existingEntry() {
+ StubBundle bundle = new StubBundle().setFindEntriesDelegate(new FindEntriesDelegate() {
+
+ public Enumeration<?> findEntries(String path, String pattern, boolean recurse) {
+ try {
+ Vector<URL> urls = new Vector<URL>();
+ urls.add(new File("src/test/resources/messages.properties").toURI().toURL());
+ return urls.elements();
+ } catch (MalformedURLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ });
+
+ List<PropertyResourceBundle> resourceBundles = this.resourceBundleResolver.getResourceBundles(bundle, "foo.properties");
+ assertNotNull(resourceBundles);
+ assertEquals(1, resourceBundles.size());
+ assertEquals("Bar", resourceBundles.get(0).getString("ABC123"));
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/eventlog/impl/ResourceBundleUtilsTests.java b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/eventlog/impl/ResourceBundleUtilsTests.java
new file mode 100644
index 0000000..e6cc909
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/eventlog/impl/ResourceBundleUtilsTests.java
@@ -0,0 +1,105 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.eventlog.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.util.List;
+import java.util.Locale;
+
+import org.eclipse.virgo.medic.eventlog.impl.ResourceBundleUtils;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class ResourceBundleUtilsTests {
+
+ private Locale defaultLocale;
+
+ @Before
+ public void setDefaultLocale() {
+ this.defaultLocale = Locale.getDefault();
+ Locale.setDefault(new Locale("d", "E", "f"));
+ }
+
+ @After
+ public void restoreDefaultLocale() {
+ Locale.setDefault(this.defaultLocale);
+ }
+
+ @Test
+ public void localeWithVariant() {
+ Locale locale = new Locale("l", "C", "v");
+
+ List<String> candidates = ResourceBundleUtils.generateCandidatePropertiesFileNames("foo", locale);
+
+ assertNotNull(candidates);
+ assertEquals("Expected 7 candidates but got " + candidates, 7, candidates.size());
+
+ assertEquals("foo_l_C_v.properties", candidates.get(0));
+ assertEquals("foo_l_C.properties", candidates.get(1));
+ assertEquals("foo_l.properties", candidates.get(2));
+ assertEquals("foo_d_E_f.properties", candidates.get(3));
+ assertEquals("foo_d_E.properties", candidates.get(4));
+ assertEquals("foo_d.properties", candidates.get(5));
+ assertEquals("foo.properties", candidates.get(6));
+ }
+
+ @Test
+ public void localeWithCountry() {
+ Locale locale = new Locale("l", "C");
+
+ List<String> candidates = ResourceBundleUtils.generateCandidatePropertiesFileNames("foo", locale);
+
+ assertNotNull(candidates);
+ assertEquals("Expected 6 candidates but got " + candidates, 6, candidates.size());
+
+ assertEquals("foo_l_C.properties", candidates.get(0));
+ assertEquals("foo_l.properties", candidates.get(1));
+ assertEquals("foo_d_E_f.properties", candidates.get(2));
+ assertEquals("foo_d_E.properties", candidates.get(3));
+ assertEquals("foo_d.properties", candidates.get(4));
+ assertEquals("foo.properties", candidates.get(5));
+ }
+
+ @Test
+ public void localeWithLanguage() {
+ Locale locale = new Locale("l");
+
+ List<String> candidates = ResourceBundleUtils.generateCandidatePropertiesFileNames("foo", locale);
+
+ assertNotNull(candidates);
+ assertEquals("Expected 5 candidates but got " + candidates, 5, candidates.size());
+
+ assertEquals("foo_l.properties", candidates.get(0));
+ assertEquals("foo_d_E_f.properties", candidates.get(1));
+ assertEquals("foo_d_E.properties", candidates.get(2));
+ assertEquals("foo_d.properties", candidates.get(3));
+ assertEquals("foo.properties", candidates.get(4));
+ }
+
+ @Test
+ public void emptyLocale() {
+ Locale locale = new Locale("");
+
+ List<String> candidates = ResourceBundleUtils.generateCandidatePropertiesFileNames("foo", locale);
+
+ assertNotNull(candidates);
+ assertEquals("Expected 4 candidates but got " + candidates, 4, candidates.size());
+
+ assertEquals("foo_d_E_f.properties", candidates.get(0));
+ assertEquals("foo_d_E.properties", candidates.get(1));
+ assertEquals("foo_d.properties", candidates.get(2));
+ assertEquals("foo.properties", candidates.get(3));
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/eventlog/impl/StandardLocaleResolverTests.java b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/eventlog/impl/StandardLocaleResolverTests.java
new file mode 100644
index 0000000..b26f653
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/eventlog/impl/StandardLocaleResolverTests.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.eventlog.impl;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Locale;
+
+import org.eclipse.virgo.medic.eventlog.impl.StandardLocaleResolver;
+import org.junit.Test;
+
+public class StandardLocaleResolverTests {
+
+ @Test
+ public void getLocale() {
+ assertEquals(Locale.getDefault(), new StandardLocaleResolver().getLocale());
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/eventlog/impl/StandardMessageResolverTests.java b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/eventlog/impl/StandardMessageResolverTests.java
new file mode 100644
index 0000000..0c01ffe
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/eventlog/impl/StandardMessageResolverTests.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.eventlog.impl;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.eq;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.isA;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Locale;
+import java.util.PropertyResourceBundle;
+
+import org.junit.Test;
+
+import org.eclipse.virgo.medic.eventlog.impl.LocaleResolver;
+import org.eclipse.virgo.medic.eventlog.impl.MessageResolver;
+import org.eclipse.virgo.medic.eventlog.impl.PropertyResourceBundleResolver;
+import org.eclipse.virgo.medic.eventlog.impl.StandardMessageResolver;
+import org.eclipse.virgo.teststubs.osgi.framework.StubBundle;
+
+public class StandardMessageResolverTests {
+
+ private final LocaleResolver localeResolver = createMock(LocaleResolver.class);
+
+ private final PropertyResourceBundleResolver resourceBundleResolver = createMock(PropertyResourceBundleResolver.class);
+
+ private final StubBundle primaryBundle = new StubBundle();
+
+ private final StubBundle secondaryBundle = new StubBundle();
+
+ private final MessageResolver messageResolver = new StandardMessageResolver(this.localeResolver, this.resourceBundleResolver, this.primaryBundle,
+ this.secondaryBundle);
+
+ @Test
+ public void resolve() throws FileNotFoundException, IOException {
+
+ expect(this.localeResolver.getLocale()).andReturn(Locale.GERMAN);
+ expect(this.resourceBundleResolver.getResourceBundles(this.primaryBundle, "EventLogMessages_de.properties")).andReturn(
+ Arrays.asList(new PropertyResourceBundle(new FileInputStream("src/test/resources/messages.properties"))));
+ replay(this.localeResolver, this.resourceBundleResolver);
+ assertEquals("Bar", this.messageResolver.resolveLogEventMessage("ABC123"));
+ verify(this.localeResolver, this.resourceBundleResolver);
+ }
+
+ @Test
+ public void resolveWithLocale() throws FileNotFoundException, IOException {
+ expect(this.resourceBundleResolver.getResourceBundles(this.primaryBundle, "EventLogMessages_it.properties")).andReturn(
+ Arrays.asList(new PropertyResourceBundle(new FileInputStream("src/test/resources/messages.properties"))));
+ replay(this.localeResolver, this.resourceBundleResolver);
+ assertEquals("Bar", this.messageResolver.resolveLogEventMessage("ABC123", Locale.ITALIAN));
+ verify(this.localeResolver, this.resourceBundleResolver);
+ }
+
+ @Test
+ public void resolveWithMissingResourceBundle() {
+ expect(this.resourceBundleResolver.getResourceBundles(eq(this.primaryBundle), isA(String.class))).andReturn(
+ Collections.<PropertyResourceBundle> emptyList()).atLeastOnce();
+ replay(this.localeResolver, this.resourceBundleResolver);
+ assertNull(this.messageResolver.resolveLogEventMessage("ABC123", Locale.FRANCE));
+ verify(this.localeResolver, this.resourceBundleResolver);
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/eventlog/impl/logback/DefaultOutputAppender.java b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/eventlog/impl/logback/DefaultOutputAppender.java
new file mode 100644
index 0000000..2e142c9
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/eventlog/impl/logback/DefaultOutputAppender.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.eventlog.impl.logback;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import ch.qos.logback.classic.spi.LoggingEvent;
+import ch.qos.logback.core.AppenderBase;
+
+public class DefaultOutputAppender extends AppenderBase<LoggingEvent> {
+
+ private static List<LoggingEvent> loggingEvents = new ArrayList<LoggingEvent>();
+
+ @Override
+ protected void append(LoggingEvent eventObject) {
+ loggingEvents.add(eventObject);
+ }
+
+ static List<LoggingEvent> getAndResetLoggingEvents() {
+ List<LoggingEvent> loggingEvents = DefaultOutputAppender.loggingEvents;
+ DefaultOutputAppender.loggingEvents = new ArrayList<LoggingEvent>();
+ return loggingEvents;
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/eventlog/impl/logback/LocalizedOutputAppender.java b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/eventlog/impl/logback/LocalizedOutputAppender.java
new file mode 100644
index 0000000..670901f
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/eventlog/impl/logback/LocalizedOutputAppender.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.eventlog.impl.logback;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import ch.qos.logback.classic.spi.LoggingEvent;
+import ch.qos.logback.core.AppenderBase;
+
+public class LocalizedOutputAppender extends AppenderBase<LoggingEvent> {
+
+ private static List<LoggingEvent> loggingEvents = new ArrayList<LoggingEvent>();
+
+ @Override
+ protected void append(LoggingEvent eventObject) {
+ loggingEvents.add(eventObject);
+ }
+
+ static List<LoggingEvent> getAndResetLoggingEvents() {
+ List<LoggingEvent> loggingEvents = LocalizedOutputAppender.loggingEvents;
+ LocalizedOutputAppender.loggingEvents = new ArrayList<LoggingEvent>();
+ return loggingEvents;
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/eventlog/impl/logback/LogBackEventLoggerTests.java b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/eventlog/impl/logback/LogBackEventLoggerTests.java
new file mode 100644
index 0000000..64f27a7
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/eventlog/impl/logback/LogBackEventLoggerTests.java
@@ -0,0 +1,122 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.eventlog.impl.logback;
+
+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 java.util.List;
+import java.util.Locale;
+
+import org.eclipse.virgo.medic.eventlog.EventLogger;
+import org.eclipse.virgo.medic.eventlog.Level;
+import org.eclipse.virgo.medic.eventlog.impl.MessageResolver;
+import org.eclipse.virgo.medic.eventlog.impl.logback.LogBackEventLogger;
+import org.junit.Test;
+
+import ch.qos.logback.classic.spi.LoggingEvent;
+
+
+public class LogBackEventLoggerTests {
+
+ @Test
+ public void defaultAndLocalizedOutput() {
+ MessageResolver resolver = createMock(MessageResolver.class);
+
+ EventLogger eventLogger = new LogBackEventLogger(resolver);
+
+ expect(resolver.resolveLogEventMessage("UT0001E")).andReturn("the message {} {}");
+ expect(resolver.resolveLogEventMessage("UT0002W")).andReturn("the message {} {}");
+ expect(resolver.resolveLogEventMessage("UT0003I")).andReturn("the message {} {}");
+ expect(resolver.resolveLogEventMessage("UT0001E", Locale.ENGLISH)).andReturn("the english message {} {}");
+ expect(resolver.resolveLogEventMessage("UT0002W", Locale.ENGLISH)).andReturn("the english message {} {}");
+ expect(resolver.resolveLogEventMessage("UT0003I", Locale.ENGLISH)).andReturn("the english message {} {}");
+ replay(resolver);
+
+ eventLogger.log("UT0001E", Level.ERROR, true, new Integer(63));
+ eventLogger.log("UT0002W", Level.WARNING, true, new Integer(63));
+ eventLogger.log("UT0003I", Level.INFO, true, new Integer(63));
+
+ verify(resolver);
+
+ List<LoggingEvent> localizedEvents = LocalizedOutputAppender.getAndResetLoggingEvents();
+ assertEquals(3, localizedEvents.size());
+
+ LoggingEvent loggingEvent = localizedEvents.get(0);
+ assertEquals(ch.qos.logback.classic.Level.ERROR, loggingEvent.getLevel());
+ assertEquals("the message true 63", loggingEvent.getMessage());
+ assertEquals("UT0001E", loggingEvent.getMDCPropertyMap().get("medic.eventCode"));
+
+ loggingEvent = localizedEvents.get(1);
+ assertEquals(ch.qos.logback.classic.Level.WARN, loggingEvent.getLevel());
+ assertEquals("the message true 63", loggingEvent.getMessage());
+ assertEquals("UT0002W", loggingEvent.getMDCPropertyMap().get("medic.eventCode"));
+
+ loggingEvent = localizedEvents.get(2);
+ assertEquals(ch.qos.logback.classic.Level.INFO, loggingEvent.getLevel());
+ assertEquals("the message true 63", loggingEvent.getMessage());
+ assertEquals("UT0003I", loggingEvent.getMDCPropertyMap().get("medic.eventCode"));
+
+ List<LoggingEvent> defaultEvents = DefaultOutputAppender.getAndResetLoggingEvents();
+ assertEquals(3, defaultEvents.size());
+
+ loggingEvent = defaultEvents.get(0);
+ assertEquals(ch.qos.logback.classic.Level.ERROR, loggingEvent.getLevel());
+ assertEquals("the english message true 63", loggingEvent.getMessage());
+ assertEquals("UT0001E", loggingEvent.getMDCPropertyMap().get("medic.eventCode"));
+
+ loggingEvent = defaultEvents.get(1);
+ assertEquals(ch.qos.logback.classic.Level.WARN, loggingEvent.getLevel());
+ assertEquals("the english message true 63", loggingEvent.getMessage());
+ assertEquals("UT0002W", loggingEvent.getMDCPropertyMap().get("medic.eventCode"));
+
+ loggingEvent = defaultEvents.get(2);
+ assertEquals(ch.qos.logback.classic.Level.INFO, loggingEvent.getLevel());
+ assertEquals("the english message true 63", loggingEvent.getMessage());
+ assertEquals("UT0003I", loggingEvent.getMDCPropertyMap().get("medic.eventCode"));
+ }
+
+ @Test
+ public void handlingOfMissingMessages() {
+ MessageResolver resolver = createMock(MessageResolver.class);
+
+ EventLogger eventLogger = new LogBackEventLogger(resolver);
+
+ expect(resolver.resolveLogEventMessage("UT0001")).andReturn(null);
+ expect(resolver.resolveLogEventMessage("UT0001", Locale.ENGLISH)).andReturn(null);
+
+ replay(resolver);
+
+ eventLogger.log("UT0001", Level.ERROR, "apple", "orange", 345);
+
+ verify(resolver);
+
+ List<LoggingEvent> defaultEvents = DefaultOutputAppender.getAndResetLoggingEvents();
+ assertEquals(1, defaultEvents.size());
+ LoggingEvent loggingEvent = defaultEvents.get(0);
+ assertEquals(ch.qos.logback.classic.Level.WARN, loggingEvent.getLevel());
+ assertEquals("A message with the key 'UT0001' was not found. The inserts for the message were '[apple, orange, 345]'",
+ loggingEvent.getMessage());
+ assertEquals("ME0001W", loggingEvent.getMDCPropertyMap().get("medic.eventCode"));
+
+ List<LoggingEvent> localizedEvents = LocalizedOutputAppender.getAndResetLoggingEvents();
+ assertEquals(1, localizedEvents.size());
+ loggingEvent = localizedEvents.get(0);
+ assertEquals(ch.qos.logback.classic.Level.WARN, loggingEvent.getLevel());
+ assertEquals("A message with the key 'UT0001' was not found. The inserts for the message were '[apple, orange, 345]'",
+ loggingEvent.getMessage());
+ assertEquals("ME0001W", loggingEvent.getMDCPropertyMap().get("medic.eventCode"));
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/impl/MedicActivatorTests.java b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/impl/MedicActivatorTests.java
new file mode 100644
index 0000000..0711ef8
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/impl/MedicActivatorTests.java
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.impl;
+
+import static org.eclipse.virgo.teststubs.osgi.framework.OSGiAssert.assertServiceListenerCount;
+import static org.eclipse.virgo.teststubs.osgi.framework.OSGiAssert.assertServiceRegistrationCount;
+import static org.easymock.EasyMock.createNiceMock;
+import static org.easymock.EasyMock.replay;
+import static org.junit.Assert.assertEquals;
+
+import java.io.PrintStream;
+
+import org.junit.Test;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleListener;
+import org.osgi.service.cm.ConfigurationListener;
+import org.osgi.service.packageadmin.PackageAdmin;
+
+
+import org.eclipse.virgo.medic.dump.DumpContributor;
+import org.eclipse.virgo.medic.dump.DumpGenerator;
+import org.eclipse.virgo.medic.eventlog.EventLogger;
+import org.eclipse.virgo.medic.eventlog.EventLoggerFactory;
+import org.eclipse.virgo.medic.impl.MedicActivator;
+import org.eclipse.virgo.medic.log.DelegatingPrintStream;
+import org.eclipse.virgo.medic.log.LoggingConfigurationPublisher;
+import org.eclipse.virgo.teststubs.osgi.framework.StubBundle;
+import org.eclipse.virgo.teststubs.osgi.framework.StubBundleContext;
+import org.eclipse.virgo.teststubs.osgi.support.ObjectClassFilter;
+
+public class MedicActivatorTests {
+
+ @Test
+ public void startAndStop() throws Exception {
+ BundleActivator bundleActivator = new MedicActivator();
+ StubBundleContext bundleContext = new StubBundleContext().addFilter(new ObjectClassFilter(DumpContributor.class));
+
+ PackageAdmin packageAdmin = createNiceMock(PackageAdmin.class);
+ replay(packageAdmin);
+
+ bundleContext.registerService(PackageAdmin.class.getName(), packageAdmin, null);
+
+ bundleActivator.start(bundleContext);
+ assertServiceListenerCount(bundleContext, 1);
+ assertServiceRegistrationCount(bundleContext, DumpGenerator.class, 1);
+ assertServiceRegistrationCount(bundleContext, DumpContributor.class, 4);
+ assertServiceRegistrationCount(bundleContext, EventLoggerFactory.class, 1);
+ assertServiceRegistrationCount(bundleContext, EventLogger.class, 1);
+ assertServiceRegistrationCount(bundleContext, LoggingConfigurationPublisher.class, 1);
+ assertServiceRegistrationCount(bundleContext, PrintStream.class, 2);
+ assertServiceRegistrationCount(bundleContext, DelegatingPrintStream.class, 2);
+ assertServiceRegistrationCount(bundleContext, ConfigurationListener.class, 1);
+ assertServiceRegistrationCount(bundleContext, BundleListener.class, 1);
+
+ bundleActivator.stop(bundleContext);
+
+ assertEquals(1, bundleContext.getServiceRegistrations().size());
+ }
+
+ @Test
+ public void copeWithNullsDuringStop() throws Exception {
+ BundleActivator bundleActivator = new MedicActivator();
+ BundleContext context = new StubBundleContext(new StubBundle());
+ bundleActivator.stop(context);
+ }
+
+}
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
new file mode 100644
index 0000000..5ecc0a8
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/impl/config/ConfigurationAdminConfigurationProviderTests.java
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+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 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 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 {
+
+ private final StubBundleContext bundleContext = new StubBundleContext();
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void getConfigurationWithoutConfigurationAdmin() {
+ ConfigurationProvider configurationProvider = new ConfigurationAdminConfigurationProvider(bundleContext);
+ Dictionary configuration = configurationProvider.getConfiguration();
+ assertNotNull(configuration);
+ assertEquals(".", configuration.get(ConfigurationProvider.KEY_DUMP_ROOT_DIRECTORY));
+ }
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void getConfigurationWithEmptyConfigurationAdminConfiguration() throws IOException {
+ ConfigurationAdmin configurationAdmin = createMock(ConfigurationAdmin.class);
+ Configuration configuration = createMock(Configuration.class);
+
+ this.bundleContext.registerService(ConfigurationAdmin.class.getName(), configurationAdmin, null);
+ expect(configurationAdmin.getConfiguration("org.eclipse.virgo.medic", null)).andReturn(configuration);
+ expect(configuration.getProperties()).andReturn(null);
+
+ replay(configurationAdmin, configuration);
+
+ ConfigurationProvider configurationProvider = new ConfigurationAdminConfigurationProvider(bundleContext);
+
+ Dictionary configDictionary = configurationProvider.getConfiguration();
+ assertNotNull(configDictionary);
+ assertEquals(".", configDictionary.get(ConfigurationProvider.KEY_DUMP_ROOT_DIRECTORY));
+
+ verify(configurationAdmin, configuration);
+ }
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void getConfigurationWithConfigurationAdminConfiguration() throws IOException {
+ 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);
+
+ ConfigurationProvider configurationProvider = new ConfigurationAdminConfigurationProvider(bundleContext);
+ Dictionary configDictionary = configurationProvider.getConfiguration();
+ assertNotNull(configDictionary);
+ assertEquals("target", configDictionary.get(ConfigurationProvider.KEY_DUMP_ROOT_DIRECTORY));
+ assertEquals("d.e.f", configDictionary.get("a.b.c"));
+
+ verify(configurationAdmin, configuration);
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/impl/config/DictionaryUtilsTests.java b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/impl/config/DictionaryUtilsTests.java
new file mode 100644
index 0000000..32fa55a
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/impl/config/DictionaryUtilsTests.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.impl.config;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.eclipse.virgo.medic.impl.config.DictionaryUtils;
+import org.junit.Test;
+
+
+@SuppressWarnings("unchecked")
+public class DictionaryUtilsTests {
+
+ @Test
+ public void emptyMerge() {
+ Dictionary primary = new Hashtable();
+ Dictionary secondary = new Hashtable();
+
+ DictionaryUtils.merge(primary, secondary);
+ assertTrue(primary.isEmpty());
+ }
+
+ @Test
+ public void mergeWithoutClash() {
+ Dictionary primary = new Hashtable();
+ primary.put("b", "c");
+ Dictionary secondary = new Hashtable();
+ secondary.put("a", "b");
+
+ DictionaryUtils.merge(primary, secondary);
+ assertEquals("c", primary.get("b"));
+ assertEquals("b", primary.get("a"));
+ }
+
+ @Test
+ public void mergeWithClash() {
+ Dictionary primary = new Hashtable();
+ primary.put("b", "c");
+ Dictionary secondary = new Hashtable();
+ secondary.put("b", "b");
+
+ DictionaryUtils.merge(primary, secondary);
+ assertEquals("c", primary.get("b"));
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/log/impl/CapturingAppender.java b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/log/impl/CapturingAppender.java
new file mode 100644
index 0000000..5ca3784
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/log/impl/CapturingAppender.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.log.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import ch.qos.logback.classic.spi.LoggingEvent;
+import ch.qos.logback.core.AppenderBase;
+
+public class CapturingAppender extends AppenderBase<LoggingEvent> {
+
+ private static List<LoggingEvent> loggingEvents = new ArrayList<LoggingEvent>();
+
+ @Override
+ protected void append(LoggingEvent eventObject) {
+ loggingEvents.add(eventObject);
+ }
+
+ static List<LoggingEvent> getAndResetLoggingEvents() {
+ List<LoggingEvent> loggingEvents = CapturingAppender.loggingEvents;
+ CapturingAppender.loggingEvents = new ArrayList<LoggingEvent>();
+ return loggingEvents;
+ }
+}
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
new file mode 100644
index 0000000..a5f153b
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/log/impl/LoggingPrintStreamWrapperTests.java
@@ -0,0 +1,184 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.log.impl;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.util.Dictionary;
+import java.util.List;
+import java.util.Locale;
+import java.util.Properties;
+
+import org.eclipse.virgo.medic.impl.config.ConfigurationProvider;
+import org.eclipse.virgo.medic.log.impl.ExecutionStackAccessor;
+import org.eclipse.virgo.medic.log.impl.LoggingPrintStreamWrapper;
+import org.eclipse.virgo.medic.log.impl.SecurityManagerExecutionStackAccessor;
+import org.junit.Before;
+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());
+ assertEquals("3,1416", loggingEvents.get(3).getMessage());
+ assertEquals("trueklm", loggingEvents.get(4).getMessage());
+ assertEquals("a123.0456.078910toString", loggingEvents.get(5).getMessage());
+ assertEquals("abcdThree strings", loggingEvents.get(6).getMessage());
+ assertEquals("last one on a new line.", loggingEvents.get(7).getMessage());
+ assertEquals("3,1416", loggingEvents.get(8).getMessage());
+ assertEquals("false", loggingEvents.get(9).getMessage());
+ assertEquals("b", loggingEvents.get(10).getMessage());
+ assertEquals("", loggingEvents.get(11).getMessage());
+ assertEquals("", loggingEvents.get(12).getMessage());
+ assertEquals("abc", loggingEvents.get(13).getMessage());
+ assertEquals("de", loggingEvents.get(14).getMessage());
+ assertEquals("123.0", loggingEvents.get(15).getMessage());
+ assertEquals("456.0", loggingEvents.get(16).getMessage());
+ assertEquals("789", loggingEvents.get(17).getMessage());
+ assertEquals("101112", loggingEvents.get(18).getMessage());
+ assertEquals("toString", loggingEvents.get(19).getMessage());
+ assertEquals("A string with a", loggingEvents.get(20).getMessage());
+ assertEquals("new line in it.", loggingEvents.get(21).getMessage());
+ }
+
+ @Test
+ public void testOutputWithinLoggingCode() {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ 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");
+ printStream.append("abcdefghij", 4, 10);
+ printStream.println();
+ printStream.format("%s %s%n%s%n", "Three", "strings", "last one on a new line.");
+ printStream.format(Locale.FRANCE, "%.4f%n", Math.PI);
+ printStream.print(true);
+ printStream.print('k');
+ printStream.print(new char[] {'l', 'm', '\r', 'a'});
+ printStream.print(123d);
+ printStream.print(456f);
+ printStream.print(7);
+ printStream.print(8910l);
+ printStream.print(new Object() {public String toString() { return "toString";}});
+ printStream.append('\n');
+ printStream.print("abcd");
+ printStream.printf("%s %s%n%s%n", "Three", "strings", "last one on a new line.");
+ printStream.printf(Locale.FRANCE, "%.4f%n", Math.PI);
+ printStream.println(false);
+ printStream.println('b');
+ printStream.println('\n');
+ printStream.println(new char[] {'a', 'b', 'c', '\n', 'd', 'e'});
+ printStream.println(123d);
+ printStream.println(456f);
+ printStream.println(789);
+ printStream.println(101112l);
+ printStream.println(new Object() {public String toString() { return "toString";}});
+ printStream.println("A string with a\nnew line in it.");
+ }
+
+ @Test
+ 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);
+
+ 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() {
+ 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());
+ }
+
+ @Before
+ public void createWrapper() {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ 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");
+ }
+
+ @SuppressWarnings("unchecked")
+ public Dictionary getConfiguration() {
+ return this.configuration;
+ }
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/log/impl/PackageNameFilteringClassSelectorTests.java b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/log/impl/PackageNameFilteringClassSelectorTests.java
new file mode 100644
index 0000000..9fc65b9
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/log/impl/PackageNameFilteringClassSelectorTests.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.log.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import java.util.Arrays;
+
+import org.eclipse.virgo.medic.log.impl.PackageNameFilteringClassSelector;
+import org.junit.Test;
+
+public class PackageNameFilteringClassSelectorTests {
+
+ @Test
+ public void noFiltering() {
+ PackageNameFilteringClassSelector classSelector = new PackageNameFilteringClassSelector(Arrays.asList(""));
+ Class<?> selected = classSelector.select(new Class<?>[] { getClass() });
+ assertEquals(getClass(), selected);
+ }
+
+ @Test
+ public void filterToEmpty() {
+ PackageNameFilteringClassSelector classSelector = new PackageNameFilteringClassSelector(Arrays.asList(getClass().getPackage().getName()));
+ Class<?> selected = classSelector.select(new Class<?>[] { getClass() });
+ assertNull(selected);
+ }
+
+ @Test
+ public void filtered() {
+ PackageNameFilteringClassSelector classSelector = new PackageNameFilteringClassSelector(Arrays.asList(getClass().getPackage().getName()));
+ Class<?> selected = classSelector.select(new Class<?>[] { getClass(), java.util.ArrayList.class });
+ assertEquals(java.util.ArrayList.class, selected);
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/log/impl/SecurityManagerExecutionStackAccessorTests.java b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/log/impl/SecurityManagerExecutionStackAccessorTests.java
new file mode 100644
index 0000000..361fdc7
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/log/impl/SecurityManagerExecutionStackAccessorTests.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.log.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import org.eclipse.virgo.medic.log.impl.ExecutionStackAccessor;
+import org.eclipse.virgo.medic.log.impl.SecurityManagerExecutionStackAccessor;
+import org.junit.Test;
+
+public class SecurityManagerExecutionStackAccessorTests {
+
+ @Test
+ public void getClasses() {
+ ExecutionStackAccessor accessor = new SecurityManagerExecutionStackAccessor();
+ Class<?>[] classes = accessor.getExecutionStack();
+ assertNotNull(classes);
+ assertTrue(classes.length > 0);
+ assertEquals("Unexpected class in stack: " + classes[0], SecurityManagerExecutionStackAccessorTests.class, classes[0]);
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/log/impl/StandardDelegatingPrintStreamTests.java b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/log/impl/StandardDelegatingPrintStreamTests.java
new file mode 100644
index 0000000..f23caed
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/log/impl/StandardDelegatingPrintStreamTests.java
@@ -0,0 +1,241 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.log.impl;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.io.StringWriter;
+import java.util.Locale;
+
+import org.eclipse.virgo.medic.log.impl.StandardDelegatingPrintStream;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ */
+public class StandardDelegatingPrintStreamTests {
+
+ private final WriterOutputStream writerOutputStream = new WriterOutputStream();
+
+ private final StandardDelegatingPrintStream delegatingPrintStream = new StandardDelegatingPrintStream(new PrintStream(writerOutputStream));
+
+ private static final String LINE_SEPARATOR = System.getProperty("line.separator");
+
+ @Before
+ public void setLocale() {
+ Locale.setDefault(Locale.ENGLISH);
+ }
+
+ @Test
+ public void appendChar() {
+ delegatingPrintStream.append('a');
+ assertEquals("a", this.writerOutputStream.getOutput());
+ }
+
+ @Test
+ public void append() {
+ delegatingPrintStream.append("a");
+ assertEquals("a", this.writerOutputStream.getOutput());
+ }
+
+ @Test
+ public void appendSegment() {
+ delegatingPrintStream.append("abc", 1, 2);
+ assertEquals("b", this.writerOutputStream.getOutput());
+ }
+
+ @Test
+ public void format() {
+ delegatingPrintStream.format("%s", "apple");
+ assertEquals("apple", this.writerOutputStream.getOutput());
+ }
+
+ @Test
+ public void formatWithLocale() {
+ delegatingPrintStream.format(Locale.FRENCH, "%f", 3.1417d);
+ assertEquals("3,141700", this.writerOutputStream.getOutput());
+ }
+
+ @Test
+ public void printBoolean() {
+ delegatingPrintStream.print("true");
+ assertEquals("true", this.writerOutputStream.getOutput());
+ }
+
+ @Test
+ public void printChar() {
+ delegatingPrintStream.print('a');
+ assertEquals("a", this.writerOutputStream.getOutput());
+ }
+
+ @Test
+ public void printCharArray() {
+ delegatingPrintStream.print(new char[] {'a', 'b', 'c'});
+ assertEquals("abc", this.writerOutputStream.getOutput());
+ }
+
+ @Test
+ public void printDouble() {
+ delegatingPrintStream.print(3.1d);
+ assertEquals("3.1", this.writerOutputStream.getOutput());
+ }
+
+ @Test
+ public void printFloat() {
+ delegatingPrintStream.print(3.1f);
+ assertEquals("3.1", this.writerOutputStream.getOutput());
+ }
+
+ @Test
+ public void printInt() {
+ delegatingPrintStream.print(3);
+ assertEquals("3", this.writerOutputStream.getOutput());
+ }
+
+ @Test
+ public void printLong() {
+ delegatingPrintStream.print(12345678901234567L);
+ assertEquals("12345678901234567", this.writerOutputStream.getOutput());
+ }
+
+ @Test
+ public void printObject() {
+ delegatingPrintStream.print(new Integer(345));
+ assertEquals("345", this.writerOutputStream.getOutput());
+ }
+
+ @Test
+ public void printString() {
+ delegatingPrintStream.print("hello");
+ assertEquals("hello", this.writerOutputStream.getOutput());
+ }
+
+ @Test
+ public void printf() {
+ delegatingPrintStream.printf("%s", "alpha");
+ assertEquals("alpha", this.writerOutputStream.getOutput());
+ }
+
+ @Test
+ public void printfWithLocale() {
+ delegatingPrintStream.printf(Locale.FRENCH, "%f", 3.1417d);
+ assertEquals("3,141700", this.writerOutputStream.getOutput());
+ }
+
+ @Test
+ public void println() {
+ delegatingPrintStream.println();
+ assertEquals(LINE_SEPARATOR, this.writerOutputStream.getOutput());
+ }
+
+ @Test
+ public void printlnBoolean() {
+ delegatingPrintStream.println(true);
+ assertEquals("true" + LINE_SEPARATOR, this.writerOutputStream.getOutput());
+ }
+
+ @Test
+ public void printlnChar() {
+ delegatingPrintStream.println('a');
+ assertEquals("a" + LINE_SEPARATOR, this.writerOutputStream.getOutput());
+ }
+
+ @Test
+ public void printlnCharArray() {
+ delegatingPrintStream.println(new char[] {'a', 'b', 'c'});
+ assertEquals("abc" + LINE_SEPARATOR, this.writerOutputStream.getOutput());
+ }
+
+ @Test
+ public void printlnDouble() {
+ delegatingPrintStream.println(3.1d);
+ assertEquals("3.1" + LINE_SEPARATOR, this.writerOutputStream.getOutput());
+ }
+
+ @Test
+ public void printlnFloat() {
+ delegatingPrintStream.println(3.1f);
+ assertEquals("3.1" + LINE_SEPARATOR, this.writerOutputStream.getOutput());
+ }
+
+ @Test
+ public void printlnInt() {
+ delegatingPrintStream.println(3);
+ assertEquals("3" + LINE_SEPARATOR, this.writerOutputStream.getOutput());
+ }
+
+ @Test
+ public void printlnLong() {
+ delegatingPrintStream.println(12345678901234567L);
+ assertEquals("12345678901234567" + LINE_SEPARATOR, this.writerOutputStream.getOutput());
+ }
+
+ @Test
+ public void printlnObject() {
+ delegatingPrintStream.println(new Integer(345));
+ assertEquals("345" + LINE_SEPARATOR, this.writerOutputStream.getOutput());
+ }
+
+ @Test
+ public void printlnString() {
+ delegatingPrintStream.println("hello");
+ assertEquals("hello" + LINE_SEPARATOR, this.writerOutputStream.getOutput());
+ }
+
+ @Test
+ public void write() {
+ delegatingPrintStream.write('a');
+ assertEquals("a", this.writerOutputStream.getOutput());
+ }
+
+ @Test
+ public void writeByteArray() throws IOException {
+ delegatingPrintStream.write(new byte[] {'a', 'b', 'c'});
+ assertEquals("abc", this.writerOutputStream.getOutput());
+ }
+
+ @Test
+ public void writeByteArraySegment() {
+ delegatingPrintStream.write(new byte[] {'a', 'b', 'c'}, 1, 2);
+ assertEquals("bc", this.writerOutputStream.getOutput());
+ }
+
+ @Test
+ public void setDelegate() {
+ delegatingPrintStream.print("hello");
+ assertEquals("hello", this.writerOutputStream.getOutput());
+
+ delegatingPrintStream.setDelegate(null);
+ delegatingPrintStream.print("hello");
+ assertEquals("hello", this.writerOutputStream.getOutput());
+
+ delegatingPrintStream.setDelegate(new PrintStream(this.writerOutputStream));
+ delegatingPrintStream.print("hello");
+ assertEquals("hellohello", this.writerOutputStream.getOutput());
+ }
+
+ private static final class WriterOutputStream extends OutputStream {
+ private final StringWriter writer = new StringWriter();
+
+ public void write(int b) throws IOException {
+ writer.write(b);
+ }
+
+ public String getOutput() {
+ return this.writer.toString();
+ }
+ }
+}
+
diff --git a/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/log/impl/config/BundleResourceConfigurationLocatorTests.java b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/log/impl/config/BundleResourceConfigurationLocatorTests.java
new file mode 100644
index 0000000..c9249d1
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/log/impl/config/BundleResourceConfigurationLocatorTests.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.log.impl.config;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.junit.Test;
+import org.osgi.framework.Version;
+
+import org.eclipse.virgo.medic.log.LoggingConfiguration;
+import org.eclipse.virgo.medic.log.impl.config.BundleResourceConfigurationLocator;
+import org.eclipse.virgo.teststubs.osgi.framework.StubBundle;
+
+public class BundleResourceConfigurationLocatorTests {
+
+ private final BundleResourceConfigurationLocator locator = new BundleResourceConfigurationLocator();
+
+ private final StubBundle bundle = new StubBundle("foo", new Version(1, 2, 3));
+
+ @Test
+ public void configFromBundle() throws MalformedURLException {
+ this.bundle.addResource("logback.xml", new URL("file:src/test/resources/logback.xml"));
+ LoggingConfiguration configuration = this.locator.locateConfiguration(this.bundle);
+ assertNotNull(configuration);
+ assertEquals("foo_1.2.3", configuration.getName());
+ }
+
+ @Test
+ public void defaultConfigFromBundle() throws MalformedURLException {
+ this.bundle.addResource("logback-default.xml", new URL("file:src/test/resources/logback.xml"));
+ LoggingConfiguration configuration = this.locator.locateConfiguration(this.bundle);
+ assertNotNull(configuration);
+ assertEquals("foo_1.2.3", configuration.getName());
+ }
+
+ @Test
+ public void noConfigInBundle() {
+ LoggingConfiguration configuration = this.locator.locateConfiguration(this.bundle);
+ assertNull(configuration);
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/log/impl/config/CompositeConfigurationLocatorTests.java b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/log/impl/config/CompositeConfigurationLocatorTests.java
new file mode 100644
index 0000000..db921d0
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/log/impl/config/CompositeConfigurationLocatorTests.java
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.log.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 org.junit.Test;
+
+import org.eclipse.virgo.medic.log.LoggingConfiguration;
+import org.eclipse.virgo.medic.log.impl.config.CompositeConfigurationLocator;
+import org.eclipse.virgo.medic.log.impl.config.ConfigurationLocator;
+import org.eclipse.virgo.teststubs.osgi.framework.StubBundle;
+
+public class CompositeConfigurationLocatorTests {
+
+ @Test
+ public void configurationFromFirstLocator() {
+ ConfigurationLocator locator1 = createMock(ConfigurationLocator.class);
+ ConfigurationLocator locator2 = createMock(ConfigurationLocator.class);
+
+ ConfigurationLocator compositeLocator = new CompositeConfigurationLocator(locator1, locator2);
+
+ StubBundle bundle = new StubBundle();
+
+ LoggingConfiguration loggingConfiguration = createMock(LoggingConfiguration.class);
+
+ expect(locator1.locateConfiguration(bundle)).andReturn(loggingConfiguration);
+ replay(locator1, locator2);
+
+ assertEquals(loggingConfiguration, compositeLocator.locateConfiguration(bundle));
+
+ verify(locator1, locator2);
+ }
+
+ @Test
+ public void configurationFromSubsequentLocator() {
+ ConfigurationLocator locator1 = createMock(ConfigurationLocator.class);
+ ConfigurationLocator locator2 = createMock(ConfigurationLocator.class);
+
+ ConfigurationLocator compositeLocator = new CompositeConfigurationLocator(locator1, locator2);
+
+ StubBundle bundle = new StubBundle();
+
+ LoggingConfiguration loggingConfiguration = createMock(LoggingConfiguration.class);
+
+ expect(locator1.locateConfiguration(bundle)).andReturn(null);
+ expect(locator2.locateConfiguration(bundle)).andReturn(loggingConfiguration);
+ replay(locator1, locator2);
+
+ assertEquals(loggingConfiguration, compositeLocator.locateConfiguration(bundle));
+
+ verify(locator1, locator2);
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/log/impl/config/ServiceRegistryConfigurationLocatorTests.java b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/log/impl/config/ServiceRegistryConfigurationLocatorTests.java
new file mode 100644
index 0000000..aa40348
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/log/impl/config/ServiceRegistryConfigurationLocatorTests.java
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.log.impl.config;
+
+import static org.easymock.EasyMock.createMock;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.junit.Test;
+
+import org.eclipse.virgo.medic.log.LoggingConfiguration;
+import org.eclipse.virgo.medic.log.impl.config.ServiceRegistryConfigurationLocator;
+import org.eclipse.virgo.teststubs.osgi.framework.StubBundle;
+import org.eclipse.virgo.teststubs.osgi.framework.StubBundleContext;
+import org.eclipse.virgo.teststubs.osgi.support.FalseFilter;
+import org.eclipse.virgo.teststubs.osgi.support.PropertiesFilter;
+
+public class ServiceRegistryConfigurationLocatorTests {
+
+ private final StubBundle bundle = new StubBundle();
+
+ private final StubBundleContext bundleContext = new StubBundleContext();
+
+ private final ServiceRegistryConfigurationLocator locator = new ServiceRegistryConfigurationLocator(this.bundleContext);
+
+ @Test
+ public void noConfigurationInServiceRegistry() {
+ this.bundle.addHeader("Medic-LoggingConfiguration", "foo");
+ this.bundleContext.addFilter(new FalseFilter("(org.eclipse.virgo.medic.log.configuration.id=foo)"));
+ LoggingConfiguration configuration = this.locator.locateConfiguration(this.bundle);
+ assertNull(configuration);
+ }
+
+ @Test
+ public void singleConfigurationInServiceRegistry() {
+ this.bundle.addHeader("Medic-LoggingConfiguration", "foo");
+ LoggingConfiguration loggingConfiguration = createMock(LoggingConfiguration.class);
+ this.bundleContext.addFilter(new PropertiesFilter(getDefaultMap()));
+ this.bundleContext.registerService(LoggingConfiguration.class.getName(), loggingConfiguration, getDefaultDictionary());
+ LoggingConfiguration configuration = this.locator.locateConfiguration(this.bundle);
+ assertEquals(loggingConfiguration, configuration);
+ }
+
+ @Test
+ public void multipleConfigurationsInServiceRegistry() {
+ this.bundle.addHeader("Medic-LoggingConfiguration", "foo");
+ LoggingConfiguration loggingConfiguration = createMock(LoggingConfiguration.class);
+ this.bundleContext.addFilter(new PropertiesFilter(getDefaultMap()));
+ this.bundleContext.registerService(LoggingConfiguration.class.getName(), loggingConfiguration, getDefaultDictionary());
+ this.bundleContext.registerService(LoggingConfiguration.class.getName(), loggingConfiguration, getDefaultDictionary());
+ this.bundleContext.registerService(LoggingConfiguration.class.getName(), loggingConfiguration, getDefaultDictionary());
+ LoggingConfiguration configuration = this.locator.locateConfiguration(this.bundle);
+ assertEquals(loggingConfiguration, configuration);
+ }
+
+ @Test
+ public void noHeaderInManifest() {
+ this.locator.locateConfiguration(this.bundle);
+ }
+
+ @SuppressWarnings("unchecked")
+ private Dictionary getDefaultDictionary() {
+ Dictionary properties = new Hashtable();
+ properties.put("org.eclipse.virgo.medic.log.configuration.id", "foo");
+ return properties;
+ }
+
+ private Map<String, Object> getDefaultMap() {
+ Map<String, Object> properties = new TreeMap<String, Object>();
+ properties.put("org.eclipse.virgo.medic.log.configuration.id", "foo");
+ return properties;
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/log/impl/config/StandardLoggingConfigurationPublisherTests.java b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/log/impl/config/StandardLoggingConfigurationPublisherTests.java
new file mode 100644
index 0000000..8028be8
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/log/impl/config/StandardLoggingConfigurationPublisherTests.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.log.impl.config;
+
+import java.io.File;
+
+import org.junit.Test;
+
+import org.eclipse.virgo.medic.log.ConfigurationPublicationFailedException;
+import org.eclipse.virgo.medic.log.LoggingConfigurationPublisher;
+import org.eclipse.virgo.medic.log.impl.config.StandardLoggingConfigurationPublisher;
+import org.eclipse.virgo.teststubs.osgi.framework.StubBundleContext;
+
+public class StandardLoggingConfigurationPublisherTests {
+
+ private final StubBundleContext bundleContext = new StubBundleContext();
+
+ private final LoggingConfigurationPublisher publisher = new StandardLoggingConfigurationPublisher(this.bundleContext);
+
+ @Test(expected = ConfigurationPublicationFailedException.class)
+ public void failedPublication() throws ConfigurationPublicationFailedException {
+ publisher.publishConfiguration(new File("does/not/exist"), "foo");
+ }
+
+ @Test
+ public void publication() throws ConfigurationPublicationFailedException {
+ this.publisher.publishConfiguration(new File("src/test/resources/logback.xml"), "foo");
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/log/impl/logback/DelegatingContextSelectorTests.java b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/log/impl/logback/DelegatingContextSelectorTests.java
new file mode 100644
index 0000000..523de85
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/log/impl/logback/DelegatingContextSelectorTests.java
@@ -0,0 +1,135 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.log.impl.logback;
+
+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.assertNull;
+
+import java.lang.reflect.Field;
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.virgo.medic.log.impl.logback.ContextSelectorDelegate;
+import org.eclipse.virgo.medic.log.impl.logback.DelegatingContextSelector;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import ch.qos.logback.classic.LoggerContext;
+
+public class DelegatingContextSelectorTests {
+
+ private final ContextSelectorDelegate delegate = createMock(ContextSelectorDelegate.class);
+
+ private final LoggerContext loggerContext = new LoggerContext();
+
+ private DelegatingContextSelector delegatingContextSelector;
+
+ @Before
+ public void resetDefaultContextConfiguredFlag() throws IllegalArgumentException, IllegalAccessException, SecurityException, NoSuchFieldException {
+ Field field = DelegatingContextSelector.class.getDeclaredField("defaultContextConfigured");
+ field.setAccessible(true);
+ field.setBoolean(null, false);
+ }
+
+ @After
+ public void cleanup() {
+ DelegatingContextSelector.setDelegate(null);
+ }
+
+ @Test
+ public void detachLoggerContext() {
+ LoggerContext detachedContext = new LoggerContext();
+
+ expect(this.delegate.detachLoggerContext("foo")).andReturn(detachedContext);
+ expect(this.delegate.detachLoggerContext("foo")).andReturn(null);
+ this.delegate.configureDefaultContext(this.loggerContext);
+
+ replay(this.delegate);
+
+ this.delegatingContextSelector = new DelegatingContextSelector(this.loggerContext);
+ DelegatingContextSelector.setDelegate(this.delegate);
+
+ assertEquals(detachedContext, this.delegatingContextSelector.detachLoggerContext("foo"));
+ assertNull(this.delegatingContextSelector.detachLoggerContext("foo"));
+
+ verify(this.delegate);
+ }
+
+ @Test
+ public void getContextNames() {
+ List<String> contextNames = Arrays.asList("a", "b", "c");
+
+ expect(this.delegate.getContextNames()).andReturn(contextNames);
+ this.delegate.configureDefaultContext(this.loggerContext);
+
+ replay(this.delegate);
+
+ this.delegatingContextSelector = new DelegatingContextSelector(this.loggerContext);
+ DelegatingContextSelector.setDelegate(this.delegate);
+
+ assertEquals(contextNames, this.delegatingContextSelector.getContextNames());
+
+ verify(this.delegate);
+ }
+
+ @Test
+ public void getDefaultLoggerContext() {
+ this.delegate.configureDefaultContext(this.loggerContext);
+ replay(this.delegate);
+
+ this.delegatingContextSelector = new DelegatingContextSelector(this.loggerContext);
+ DelegatingContextSelector.setDelegate(this.delegate);
+
+ verify(this.delegate);
+
+ assertEquals(this.loggerContext, this.delegatingContextSelector.getDefaultLoggerContext());
+ }
+
+ @Test
+ public void getLoggerContext() {
+ LoggerContext context = new LoggerContext();
+
+ expect(this.delegate.getLoggerContext()).andReturn(context);
+ this.delegate.configureDefaultContext(this.loggerContext);
+
+ replay(this.delegate);
+
+ this.delegatingContextSelector = new DelegatingContextSelector(this.loggerContext);
+ DelegatingContextSelector.setDelegate(this.delegate);
+
+ assertEquals(context, this.delegatingContextSelector.getLoggerContext());
+
+ verify(this.delegate);
+ }
+
+ @Test
+ public void getNamedLoggerContext() {
+ LoggerContext context = new LoggerContext();
+
+ expect(this.delegate.getLoggerContext("foo")).andReturn(context);
+ this.delegate.configureDefaultContext(this.loggerContext);
+
+ replay(this.delegate);
+
+ this.delegatingContextSelector = new DelegatingContextSelector(this.loggerContext);
+ DelegatingContextSelector.setDelegate(this.delegate);
+
+ assertEquals(context, this.delegatingContextSelector.getLoggerContext("foo"));
+
+ verify(this.delegate);
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/log/impl/logback/JoranLoggerContextConfigurerTests.java b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/log/impl/logback/JoranLoggerContextConfigurerTests.java
new file mode 100644
index 0000000..b7afd78
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/log/impl/logback/JoranLoggerContextConfigurerTests.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.log.impl.logback;
+
+import static org.junit.Assert.assertNotNull;
+
+import org.eclipse.virgo.medic.log.LoggingConfiguration;
+import org.eclipse.virgo.medic.log.impl.logback.JoranLoggerContextConfigurer;
+import org.eclipse.virgo.medic.log.impl.logback.LoggerContextConfigurationFailedException;
+import org.eclipse.virgo.medic.log.impl.logback.LoggerContextConfigurer;
+import org.junit.Test;
+
+import ch.qos.logback.classic.LoggerContext;
+
+
+public class JoranLoggerContextConfigurerTests {
+
+ private final LoggerContextConfigurer configurer = new JoranLoggerContextConfigurer();
+
+ @Test(expected = LoggerContextConfigurationFailedException.class)
+ public void malformedXML() throws LoggerContextConfigurationFailedException {
+ LoggingConfiguration configuration = new StubLoggingConfiguration("dslkjgw", "the-config");
+ configurer.applyConfiguration(configuration, new LoggerContext());
+ }
+
+ @Test(expected = LoggerContextConfigurationFailedException.class)
+ public void malformedConfiguration() throws LoggerContextConfigurationFailedException {
+ LoggingConfiguration configuration = new StubLoggingConfiguration("<configuration><appender/></configuration>", "the-config");
+ configurer.applyConfiguration(configuration, new LoggerContext());
+ }
+
+ @Test
+ public void validConfiguration() throws LoggerContextConfigurationFailedException {
+ LoggingConfiguration configuration = new StubLoggingConfiguration("<configuration><logger name=\"abc\"></logger></configuration>",
+ "the-config");
+ LoggerContext loggerContext = new LoggerContext();
+ configurer.applyConfiguration(configuration, loggerContext);
+ assertNotNull(loggerContext.getLogger("abc"));
+ }
+
+ private final class StubLoggingConfiguration implements LoggingConfiguration {
+
+ private final String configuration;
+
+ private final String name;
+
+ private StubLoggingConfiguration(String configuration, String name) {
+ this.configuration = configuration;
+ this.name = name;
+ }
+
+ public String getConfiguration() {
+ return this.configuration;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/log/impl/logback/StandardContextSelectorTests.java b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/log/impl/logback/StandardContextSelectorTests.java
new file mode 100644
index 0000000..39bfeb6
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/test/java/org/eclipse/virgo/medic/log/impl/logback/StandardContextSelectorTests.java
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.log.impl.logback;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.eq;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.isA;
+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 static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+
+import java.util.List;
+
+import org.junit.Test;
+
+import ch.qos.logback.classic.LoggerContext;
+
+
+import org.eclipse.virgo.medic.log.LoggingConfiguration;
+import org.eclipse.virgo.medic.log.impl.CallingBundleResolver;
+import org.eclipse.virgo.medic.log.impl.config.ConfigurationLocator;
+import org.eclipse.virgo.medic.log.impl.logback.LoggerContextConfigurationFailedException;
+import org.eclipse.virgo.medic.log.impl.logback.LoggerContextConfigurer;
+import org.eclipse.virgo.medic.log.impl.logback.StandardContextSelectorDelegate;
+import org.eclipse.virgo.teststubs.osgi.framework.StubBundle;
+
+public class StandardContextSelectorTests {
+
+ private CallingBundleResolver loggingCallerLocator = createMock(CallingBundleResolver.class);
+
+ private ConfigurationLocator configurationLocator = createMock(ConfigurationLocator.class);
+
+ private StubBundle bundle = new StubBundle();
+
+ private LoggerContextConfigurer loggerContextConfigurer = createMock(LoggerContextConfigurer.class);
+
+ private StandardContextSelectorDelegate contextSelectorDelegate = new StandardContextSelectorDelegate(this.loggingCallerLocator,
+ this.configurationLocator, this.bundle, this.loggerContextConfigurer);
+
+ @Test
+ public void loggerContextWithLocatedConfiguration() throws LoggerContextConfigurationFailedException {
+ LoggingConfiguration loggingConfiguration = createMock(LoggingConfiguration.class);
+ expect(loggingConfiguration.getName()).andReturn("the-configuration").atLeastOnce();
+ expect(this.loggingCallerLocator.getCallingBundle()).andReturn(this.bundle).times(2);
+ expect(this.configurationLocator.locateConfiguration(this.bundle)).andReturn(loggingConfiguration).times(1);
+ this.loggerContextConfigurer.applyConfiguration(eq(loggingConfiguration), isA(LoggerContext.class));
+ replay(this.configurationLocator, this.loggingCallerLocator, this.loggerContextConfigurer, loggingConfiguration);
+
+ LoggerContext loggerContext = this.contextSelectorDelegate.getLoggerContext();
+ assertEquals("the-configuration", loggerContext.getName());
+
+ LoggerContext reusedLoggerContext = this.contextSelectorDelegate.getLoggerContext();
+ assertEquals("the-configuration", reusedLoggerContext.getName());
+
+ assertSame(loggerContext, reusedLoggerContext);
+
+ List<String> contextNames = this.contextSelectorDelegate.getContextNames();
+ assertEquals(1, contextNames.size());
+ assertEquals("the-configuration", contextNames.get(0));
+
+ loggerContext = this.contextSelectorDelegate.getLoggerContext("the-configuration");
+ assertNotNull(loggerContext);
+ assertEquals("the-configuration", loggerContext.getName());
+
+ verify(this.configurationLocator, this.loggingCallerLocator, this.loggerContextConfigurer, loggingConfiguration);
+ }
+
+ @Test
+ public void loggerContextWithNoLocatedConfiguration() {
+ expect(this.loggingCallerLocator.getCallingBundle()).andReturn(this.bundle);
+ expect(this.configurationLocator.locateConfiguration(this.bundle)).andReturn(null);
+ replay(this.configurationLocator, this.loggingCallerLocator);
+
+ LoggerContext loggerContext = this.contextSelectorDelegate.getLoggerContext();
+ assertNull(loggerContext);
+ verify(this.configurationLocator, this.loggingCallerLocator);
+ }
+}
diff --git a/org.eclipse.virgo.medic.core/src/test/resources/.gitignore b/org.eclipse.virgo.medic.core/src/test/resources/.gitignore
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/test/resources/.gitignore
diff --git a/org.eclipse.virgo.medic.core/src/test/resources/logback-test.xml b/org.eclipse.virgo.medic.core/src/test/resources/logback-test.xml
new file mode 100644
index 0000000..c14b954
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/test/resources/logback-test.xml
@@ -0,0 +1,50 @@
+<configuration>
+ <root level="debug"/>
+
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+ <layout class="ch.qos.logback.classic.PatternLayout">
+ <Pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] %-24.24thread &lt;%X{medic.eventCode}&gt; %msg %ex%n</Pattern>
+ </layout>
+ </appender>
+
+ <logger name="org.eclipse.virgo.medic.eventlog.localized">
+ <appender-ref ref="STDOUT" />
+ <appender name="stubAppender" class="org.eclipse.virgo.medic.eventlog.impl.logback.LocalizedOutputAppender">
+ <layout class="ch.qos.logback.classic.PatternLayout">
+ <Pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] %-24.24thread &lt;%X{medic.eventCode}&gt; %msg %ex</Pattern>
+ </layout>
+ </appender>
+ <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <file>target/serviceability/eventlog/eventlog.log</file>
+ <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
+ <FileNamePattern>target/serviceability/eventlog/eventlog_%i.log</FileNamePattern>
+ <MinIndex>1</MinIndex>
+ <MaxIndex>4</MaxIndex>
+ </rollingPolicy>
+ <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
+ <MaxFileSize>10MB</MaxFileSize>
+ </triggeringPolicy>
+ <layout class="ch.qos.logback.classic.PatternLayout">
+ <Pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] %-24.24thread &lt;%X{medic.eventCode}&gt; %msg %ex%n</Pattern>
+ </layout>
+ </appender>
+ </logger>
+
+ <logger name="org.eclipse.virgo.medic.eventlog.default">
+ <appender name="stubAppender" class="org.eclipse.virgo.medic.eventlog.impl.logback.DefaultOutputAppender">
+ <layout class="ch.qos.logback.classic.PatternLayout">
+ <Pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] %-24.24thread &lt;%X{medic.eventCode}&gt; %msg %ex</Pattern>
+ </layout>
+ </appender>
+ </logger>
+
+ <logger name="org.eclipse.virgo.medic.log.impl.LoggingPrintStreamWrapperTests">
+ <appender name="capturingAppender" class="org.eclipse.virgo.medic.log.impl.CapturingAppender">
+ <layout class="ch.qos.logback.classic.PatternLayout">
+ <Pattern>%msg</Pattern>
+ </layout>
+ </appender>
+ <appender-ref ref="STDOUT"/>
+ </logger>
+
+</configuration>
diff --git a/org.eclipse.virgo.medic.core/src/test/resources/logback.xml b/org.eclipse.virgo.medic.core/src/test/resources/logback.xml
new file mode 100644
index 0000000..f9049cf
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/test/resources/logback.xml
@@ -0,0 +1,16 @@
+<configuration>
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+ <layout class="ch.qos.logback.classic.PatternLayout">
+ <Pattern>Bundle1 [%d{yyyy-MM-dd HH:mm:ss.SSS}] %-24.24thread %msg %ex%n</Pattern>
+ </layout>
+ </appender>
+
+ <root level="debug">
+ <appender-ref ref="STDOUT" />
+ </root>
+
+ <logger name="logger">
+ <appender-ref ref="STDOUT" />
+ </logger>
+
+</configuration>
diff --git a/org.eclipse.virgo.medic.core/src/test/resources/messages.properties b/org.eclipse.virgo.medic.core/src/test/resources/messages.properties
new file mode 100644
index 0000000..bf13b7d
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/src/test/resources/messages.properties
@@ -0,0 +1 @@
+ABC123=Bar
diff --git a/org.eclipse.virgo.medic.core/template.mf b/org.eclipse.virgo.medic.core/template.mf
new file mode 100644
index 0000000..a86964a
--- /dev/null
+++ b/org.eclipse.virgo.medic.core/template.mf
@@ -0,0 +1,30 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: org.eclipse.virgo.medic.core
+Bundle-Name: Medic Core Implementation
+Bundle-Vendor: SpringSource Inc.
+Bundle-Version: 1.0.0
+Bundle-Activator: org.eclipse.virgo.medic.impl.MedicActivator
+Import-Template:
+ org.eclipse.virgo.medic.*;version="[1.0.1,1.0.2)",
+ org.eclipse.virgo.util.osgi;version="${org.eclipse.virgo.util:[=.=.=, +1.0.0)}",
+ javax.jms;version="0";resolution:=optional,
+ javax.mail.*;version="0";resolution:=optional,
+ javax.management.*;version="0",
+ javax.naming;version="0",
+ javax.servlet.*;version="0";resolution:=optional,
+ javax.sql;version="0",
+ javax.xml.parsers;version="0",
+ org.aspectj.*;version="${org.aspectj:[=.=.=, +1.0.0)}",
+ org.osgi.framework;version="0",
+ org.osgi.service.*;version="0",
+ org.osgi.util.tracker;version="0",
+ org.slf4j.*;version="${org.slf4j:[=.=.=, +1.0.0)}",
+ org.xml.sax.*;version="0"
+Excluded-Imports:
+ org.codehaus.janino.*
+Export-Template:
+ org.slf4j.impl;version="1.5.10"
+Excluded-Exports:
+ org.eclipse.virgo.medic.*
+Medic-LoggingConfiguration: org.eclipse.virgo.medic
diff --git a/org.eclipse.virgo.medic.integrationtest/.classpath b/org.eclipse.virgo.medic.integrationtest/.classpath
new file mode 100644
index 0000000..b7196c2
--- /dev/null
+++ b/org.eclipse.virgo.medic.integrationtest/.classpath
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src/main/java">
+ <attributes>
+ <attribute name="com.springsource.server.ide.jdt.core.test.classpathentry" value="false"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="src" path="src/main/resources">
+ <attributes>
+ <attribute name="com.springsource.server.ide.jdt.core.test.classpathentry" value="false"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="src" output="target/test-classes" path="src/test/java">
+ <attributes>
+ <attribute name="com.springsource.server.ide.jdt.core.test.classpathentry" value="false"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="src" output="target/test-classes" path="src/test/resources">
+ <attributes>
+ <attribute name="com.springsource.server.ide.jdt.core.test.classpathentry" value="false"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="var" path="MEDIC_IVY_CACHE/org.junit/com.springsource.org.junit/4.7.0/com.springsource.org.junit-4.7.0.jar" sourcepath="/MEDIC_IVY_CACHE/org.junit/com.springsource.org.junit/4.7.0/com.springsource.org.junit-sources-4.7.0.jar"/>
+ <classpathentry kind="var" path="MEDIC_IVY_CACHE/org.eclipse.osgi/org.eclipse.osgi/3.5.1.R35x_v20091005/org.eclipse.osgi-3.5.1.R35x_v20091005.jar" sourcepath="/MEDIC_IVY_CACHE/org.eclipse.osgi/org.eclipse.osgi/3.5.1.R35x_v20091005/org.eclipse.osgi-sources-3.5.1.R35x_v20091005.jar"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="var" path="MEDIC_IVY_CACHE/org.slf4j/com.springsource.slf4j.api/1.5.10/com.springsource.slf4j.api-1.5.10.jar" sourcepath="/MEDIC_IVY_CACHE/org.slf4j/com.springsource.slf4j.api/1.5.10/com.springsource.slf4j.api-sources-1.5.10.jar"/>
+ <classpathentry kind="var" path="MEDIC_IVY_CACHE/ch.qos.logback/com.springsource.ch.qos.logback.classic/0.9.18/com.springsource.ch.qos.logback.classic-0.9.18.jar" sourcepath="/MEDIC_IVY_CACHE/ch.qos.logback/com.springsource.ch.qos.logback.classic/0.9.18/com.springsource.ch.qos.logback.classic-sources-0.9.18.jar"/>
+ <classpathentry kind="var" path="MEDIC_IVY_CACHE/ch.qos.logback/com.springsource.ch.qos.logback.core/0.9.18/com.springsource.ch.qos.logback.core-0.9.18.jar" sourcepath="/MEDIC_IVY_CACHE/ch.qos.logback/com.springsource.ch.qos.logback.core/0.9.18/com.springsource.ch.qos.logback.core-sources-0.9.18.jar"/>
+ <classpathentry kind="var" path="MEDIC_IVY_CACHE/org.eclipse.virgo.test/org.eclipse.virgo.test.framework/2.1.0.D-20100420091951/org.eclipse.virgo.test.framework-2.1.0.D-20100420091951.jar" sourcepath="/MEDIC_IVY_CACHE/org.eclipse.virgo.test/org.eclipse.virgo.test.framework/2.1.0.D-20100420091951/org.eclipse.virgo.test.framework-sources-2.1.0.D-20100420091951.jar"/>
+ <classpathentry kind="con" path="org.eclipse.ajdt.core.ASPECTJRT_CONTAINER"/>
+ <classpathentry kind="var" path="MEDIC_IVY_CACHE/org.apache.felix/org.apache.felix.configadmin/1.2.4/org.apache.felix.configadmin-1.2.4.jar" sourcepath="/MEDIC_IVY_CACHE/org.apache.felix/org.apache.felix.configadmin/1.2.4/org.apache.felix.configadmin-sources-1.2.4.jar"/>
+ <classpathentry kind="src" path="/org.eclipse.virgo.medic">
+ <attributes>
+ <attribute name="org.eclipse.ajdt.aspectpath" value="org.eclipse.ajdt.aspectpath"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="var" path="MEDIC_IVY_CACHE/org.eclipse.virgo.util/org.eclipse.virgo.util.common/2.1.0.D-20100420091708/org.eclipse.virgo.util.common-2.1.0.D-20100420091708.jar" sourcepath="/MEDIC_IVY_CACHE/org.eclipse.virgo.util/org.eclipse.virgo.util.common/2.1.0.D-20100420091708/org.eclipse.virgo.util.common-sources-2.1.0.D-20100420091708.jar"/>
+ <classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/org.eclipse.virgo.medic.integrationtest/.project b/org.eclipse.virgo.medic.integrationtest/.project
new file mode 100644
index 0000000..445d599
--- /dev/null
+++ b/org.eclipse.virgo.medic.integrationtest/.project
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.virgo.medic.integrationtest</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.wst.common.project.facet.core.builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.ajdt.core.ajbuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.springframework.ide.eclipse.core.springbuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.springsource.server.ide.bundlor.core.builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.ajdt.ui.ajnature</nature>
+ <nature>com.springsource.server.ide.facet.core.bundlenature</nature>
+ <nature>org.springframework.ide.eclipse.core.springnature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.wst.common.project.facet.core.nature</nature>
+ </natures>
+</projectDescription>
diff --git a/org.eclipse.virgo.medic.integrationtest/.settings/com.springsource.server.ide.bundlor.core.prefs b/org.eclipse.virgo.medic.integrationtest/.settings/com.springsource.server.ide.bundlor.core.prefs
new file mode 100644
index 0000000..08c417c
--- /dev/null
+++ b/org.eclipse.virgo.medic.integrationtest/.settings/com.springsource.server.ide.bundlor.core.prefs
@@ -0,0 +1,5 @@
+#Thu Nov 12 08:44:20 GMT 2009
+com.springsource.server.ide.bundlor.core.bundlor.generated.manifest.autoformatting=true
+com.springsource.server.ide.bundlor.core.byte.code.scanning=true
+com.springsource.server.ide.bundlor.core.template.properties.files=../build.versions
+eclipse.preferences.version=1
diff --git a/org.eclipse.virgo.medic.integrationtest/.springBeans b/org.eclipse.virgo.medic.integrationtest/.springBeans
new file mode 100644
index 0000000..d079ca1
--- /dev/null
+++ b/org.eclipse.virgo.medic.integrationtest/.springBeans
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beansProjectDescription>
+ <version>1</version>
+ <pluginVersion><![CDATA[2.2.4.RELEASE]]></pluginVersion>
+ <configSuffixes>
+ <configSuffix><![CDATA[xml]]></configSuffix>
+ </configSuffixes>
+ <enableImports><![CDATA[false]]></enableImports>
+ <configs>
+ </configs>
+ <configSets>
+ </configSets>
+</beansProjectDescription>
diff --git a/org.eclipse.virgo.medic.integrationtest/build.xml b/org.eclipse.virgo.medic.integrationtest/build.xml
new file mode 100644
index 0000000..f22c9dd
--- /dev/null
+++ b/org.eclipse.virgo.medic.integrationtest/build.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="org.eclipse.virgo.medic.integrationtest">
+
+ <property file="${basedir}/../build.properties"/>
+ <property file="${basedir}/../build.versions"/>
+ <import file="${basedir}/../virgo-build/weaving/default.xml"/>
+
+</project>
diff --git a/org.eclipse.virgo.medic.integrationtest/ivy.xml b/org.eclipse.virgo.medic.integrationtest/ivy.xml
new file mode 100644
index 0000000..e2d576f
--- /dev/null
+++ b/org.eclipse.virgo.medic.integrationtest/ivy.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?xml-stylesheet type="text/xsl" href="http://ivyrep.jayasoft.org/ivy-doc.xsl"?>
+<ivy-module
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="http://incubator.apache.org/ivy/schemas/ivy.xsd"
+ version="1.3">
+
+ <info organisation="org.eclipse.virgo.medic" module="${ant.project.name}"/>
+
+ <configurations>
+ <include file="${virgo.build.dir}/common/default-ivy-configurations.xml"/>
+ </configurations>
+
+ <publications>
+ <artifact name="${ant.project.name}"/>
+ <artifact name="${ant.project.name}-sources" type="src" ext="jar"/>
+ </publications>
+
+ <dependencies>
+ <dependency org="org.eclipse.osgi" name="org.eclipse.osgi" rev="${org.eclipse.osgi}" conf="compile->runtime"/>
+ <dependency org="org.slf4j" name="com.springsource.slf4j.api" rev="${org.slf4j}" conf="compile->runtime"/>
+
+ <dependency org="org.eclipse.virgo.medic" name="org.eclipse.virgo.medic" rev="latest.integration" conf="aspects->runtime"/>
+ <dependency org="org.aspectj" name="com.springsource.org.aspectj.runtime" rev="${org.aspectj}" conf="aspects->runtime"/>
+
+ <dependency org="org.eclipse.virgo.util" name="org.eclipse.virgo.util.common" rev="${org.eclipse.virgo.util}" conf="test->runtime"/>
+ <dependency org="org.junit" name="com.springsource.org.junit" rev="${org.junit}" conf="test->runtime"/>
+ <dependency org="org.eclipse.virgo.test" name="org.eclipse.virgo.test.framework" rev="${org.eclipse.virgo.test}" conf="test->runtime"/>
+ <dependency org="ch.qos.logback" name="com.springsource.ch.qos.logback.classic" rev="${ch.qos.logback}" conf="test->runtime"/>
+ <dependency org="org.apache.felix" name="org.apache.felix.configadmin" rev="${org.apache.felix.configadmin}" conf="test->runtime"/>
+ </dependencies>
+
+</ivy-module>
diff --git a/org.eclipse.virgo.medic.integrationtest/src/main/java/.gitignore b/org.eclipse.virgo.medic.integrationtest/src/main/java/.gitignore
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/org.eclipse.virgo.medic.integrationtest/src/main/java/.gitignore
diff --git a/org.eclipse.virgo.medic.integrationtest/src/main/java/test/TestClass.java b/org.eclipse.virgo.medic.integrationtest/src/main/java/test/TestClass.java
new file mode 100644
index 0000000..fb1de67
--- /dev/null
+++ b/org.eclipse.virgo.medic.integrationtest/src/main/java/test/TestClass.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package test;
+
+public class TestClass {
+
+ public void publicTest(boolean throwException) {
+ if (throwException) {
+ throw new RuntimeException();
+ }
+ return;
+ }
+
+ void packagePrivateTest(boolean throwException) {
+ if (throwException) {
+ throw new RuntimeException();
+ }
+ return;
+ }
+
+ @SuppressWarnings("unused")
+ private void privateTest(boolean throwException) {
+ if (throwException) {
+ throw new RuntimeException();
+ }
+ return;
+ }
+}
diff --git a/org.eclipse.virgo.medic.integrationtest/src/main/resources/.gitignore b/org.eclipse.virgo.medic.integrationtest/src/main/resources/.gitignore
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/org.eclipse.virgo.medic.integrationtest/src/main/resources/.gitignore
diff --git a/org.eclipse.virgo.medic.integrationtest/src/test/java/org/eclipse/virgo/medic/dump/test/DumpIntegrationTests.java b/org.eclipse.virgo.medic.integrationtest/src/test/java/org/eclipse/virgo/medic/dump/test/DumpIntegrationTests.java
new file mode 100644
index 0000000..3ddddc8
--- /dev/null
+++ b/org.eclipse.virgo.medic.integrationtest/src/test/java/org/eclipse/virgo/medic/dump/test/DumpIntegrationTests.java
@@ -0,0 +1,180 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.dump.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.slf4j.LoggerFactory;
+
+import org.eclipse.virgo.medic.dump.DumpGenerator;
+import org.eclipse.virgo.test.framework.OsgiTestRunner;
+import org.eclipse.virgo.test.framework.TestFrameworkUtils;
+
+@RunWith(OsgiTestRunner.class)
+public class DumpIntegrationTests {
+
+ private final BundleContext bundleContext = TestFrameworkUtils.getBundleContextForTestClass(getClass());
+
+ @Before
+ public void deleteDumps() {
+ File dumpsDir = new File("target", "dumps");
+ if (dumpsDir.exists()) {
+ deleteRecursively(dumpsDir);
+ }
+ }
+
+ private static void deleteRecursively(File file) {
+ if (file.isDirectory()) {
+ File[] files = file.listFiles();
+ if (files != null) {
+ for (File fileInDir : files) {
+ deleteRecursively(fileInDir);
+ }
+ }
+ }
+ assertTrue(file.delete());
+ }
+
+ @Test
+ public void dumpGeneratorAvailableFromServiceRegistry() {
+ ServiceReference serviceReference = this.bundleContext.getServiceReference(DumpGenerator.class.getName());
+ assertNotNull(serviceReference);
+ }
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void dumpDirectoryConfiguration() throws IOException, InterruptedException {
+ Configuration configuration = getConfiguration("org.eclipse.virgo.medic");
+ assertNotNull(configuration);
+
+ Dictionary properties = new Hashtable<String, String>();
+ properties.put("dump.root.directory", "target/dumps/1");
+
+ configuration.update(properties);
+
+ Thread.sleep(2000);
+
+ ServiceReference serviceReference = this.bundleContext.getServiceReference(DumpGenerator.class.getName());
+ DumpGenerator dumpGenerator = (DumpGenerator)this.bundleContext.getService(serviceReference);
+ dumpGenerator.generateDump("bleurgh");
+
+ File file = new File("target/dumps/1");
+ assertTrue(file.exists());
+ assertNotNull(file.list());
+ assertEquals(1, file.list().length);
+ assertDumpContributionsMade(file.listFiles()[0], "heap.out", "summary.txt", "thread.txt");
+
+ properties.put("dump.root.directory", "target/dumps/2");
+ configuration.update(properties);
+
+ Thread.sleep(2000);
+
+ dumpGenerator.generateDump("bleurgh");
+
+ file = new File("target/dumps/2");
+ assertTrue(file.exists());
+ assertNotNull(file.list());
+ assertEquals(1, file.list().length);
+ assertDumpContributionsMade(file.listFiles()[0], "heap.out", "summary.txt", "thread.txt");
+ }
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void exclusionConfiguration() throws IOException, InterruptedException {
+ Configuration configuration = getConfiguration("org.eclipse.virgo.medic");
+ assertNotNull(configuration);
+
+ Dictionary properties = new Hashtable<String, String>();
+ properties.put("dump.root.directory", "target/dumps/1");
+ properties.put("dump.exclusions.bleurgh", "heap");
+
+ configuration.update(properties);
+
+ Thread.sleep(2000);
+
+ ServiceReference serviceReference = this.bundleContext.getServiceReference(DumpGenerator.class.getName());
+ DumpGenerator dumpGenerator = (DumpGenerator)this.bundleContext.getService(serviceReference);
+ dumpGenerator.generateDump("bleurgh");
+
+ File file = new File("target/dumps/1");
+ assertTrue(file.exists());
+ assertNotNull(file.list());
+ assertEquals(1, file.list().length);
+ assertDumpContributionsMade(file.listFiles()[0], "summary.txt", "thread.txt");
+ }
+
+ @Test
+ public void logDumpEnabled() throws IOException, InterruptedException {
+ Configuration configuration = getConfiguration("org.eclipse.virgo.medic");
+ assertNotNull(configuration);
+
+ Dictionary<String, String> properties = new Hashtable<String, String>();
+ properties.put("dump.root.directory", "target/dumps/1");
+ properties.put("log.dump.level", "ERROR");
+
+ configuration.update(properties);
+
+ Thread.sleep(2000);
+
+ LoggerFactory.getLogger(getClass()).info("Test");
+
+ ServiceReference serviceReference = this.bundleContext.getServiceReference(DumpGenerator.class.getName());
+ DumpGenerator dumpGenerator = (DumpGenerator)this.bundleContext.getService(serviceReference);
+ dumpGenerator.generateDump("bleurgh");
+
+ File file = new File("target/dumps/1");
+ assertTrue(file.exists());
+ assertNotNull(file.list());
+ assertEquals(1, file.list().length);
+ assertDumpContributionsMade(file.listFiles()[0], "heap.out", "summary.txt", "thread.txt", "log.log");
+ }
+
+ private Configuration getConfiguration(String pid) throws IOException {
+ ConfigurationAdmin configurationAdmin = getConfigurationAdmin();
+ assertNotNull(configurationAdmin);
+
+ return configurationAdmin.getConfiguration(pid);
+ }
+
+ private ConfigurationAdmin getConfigurationAdmin() {
+ ServiceReference serviceReference = this.bundleContext.getServiceReference(ConfigurationAdmin.class.getName());
+ assertNotNull(serviceReference);
+
+ return (ConfigurationAdmin) this.bundleContext.getService(serviceReference);
+ }
+
+ private static void assertDumpContributionsMade(File dumpDirectory, String... contributions) {
+ assertTrue(dumpDirectory.exists());
+ File[] files = dumpDirectory.listFiles();
+ assertEquals("Found '" + Arrays.toString(files) + "' but expected '" + Arrays.toString(contributions) + "'", contributions.length, files.length);
+ List<String> contributionsList = Arrays.asList(contributions);
+ for (File file : files) {
+ assertTrue("The file " + file.getName() + " was not expected", contributionsList.contains(file.getName()));
+ }
+ }
+}
diff --git a/org.eclipse.virgo.medic.integrationtest/src/test/java/org/eclipse/virgo/medic/eventlog/test/EventLogIntegrationTests.java b/org.eclipse.virgo.medic.integrationtest/src/test/java/org/eclipse/virgo/medic/eventlog/test/EventLogIntegrationTests.java
new file mode 100644
index 0000000..4987221
--- /dev/null
+++ b/org.eclipse.virgo.medic.integrationtest/src/test/java/org/eclipse/virgo/medic/eventlog/test/EventLogIntegrationTests.java
@@ -0,0 +1,115 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.eventlog.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.util.List;
+import java.util.Locale;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.ServiceReference;
+
+import ch.qos.logback.classic.spi.LoggingEvent;
+
+
+import org.eclipse.virgo.medic.eventlog.EventLogger;
+import org.eclipse.virgo.medic.eventlog.EventLoggerFactory;
+import org.eclipse.virgo.medic.eventlog.Level;
+import org.eclipse.virgo.medic.log.appender.StubAppender;
+import org.eclipse.virgo.test.framework.OsgiTestRunner;
+import org.eclipse.virgo.test.framework.TestFrameworkUtils;
+
+@RunWith(OsgiTestRunner.class)
+public class EventLogIntegrationTests {
+
+ private BundleContext bundleContext;
+
+ private Bundle messageBundle;
+
+ @Before
+ public void before() throws BundleException {
+ Locale.setDefault(Locale.ITALIAN);
+ this.bundleContext = TestFrameworkUtils.getBundleContextForTestClass(getClass());
+ messageBundle = this.bundleContext.installBundle("file:src/test/resources/message-bundle");
+ this.bundleContext.installBundle("file:src/test/resources/message-fragment");
+ }
+
+ @Test
+ public void availabilityOfEventLoggerFactory() {
+ ServiceReference serviceReference = this.bundleContext.getServiceReference(EventLoggerFactory.class.getName());
+ assertNotNull(serviceReference);
+ }
+
+ @Test
+ public void availabilityOfEventLogger() {
+ ServiceReference serviceReference = this.bundleContext.getServiceReference(EventLogger.class.getName());
+ assertNotNull(serviceReference);
+ }
+
+ @Test
+ public void eventLoggingWithMessageFromCurrentBundle() {
+ ServiceReference serviceReference = this.bundleContext.getServiceReference(EventLogger.class.getName());
+ assertNotNull(serviceReference);
+ EventLogger eventLogger = (EventLogger)this.bundleContext.getService(serviceReference);
+ eventLogger.log("1234", Level.WARNING, "orange", "lemon");
+
+ List<LoggingEvent> loggingEvent = StubAppender.getAndResetLoggingEvents("default-stub");
+ assertEquals(1, loggingEvent.size());
+ assertEquals("English orange and lemon", loggingEvent.get(0).getMessage());
+
+ loggingEvent = StubAppender.getAndResetLoggingEvents("localized-stub");
+ assertEquals(1, loggingEvent.size());
+ assertEquals("Italian orange and lemon", loggingEvent.get(0).getMessage());
+
+ }
+
+ @Test
+ public void eventLoggingWithMessageFromFragment() throws Exception {
+ ServiceReference serviceReference = this.bundleContext.getServiceReference(EventLoggerFactory.class.getName());
+ assertNotNull(serviceReference);
+ EventLoggerFactory eventLoggerFactory = (EventLoggerFactory)this.bundleContext.getService(serviceReference);
+ EventLogger eventLogger = eventLoggerFactory.createEventLogger(this.messageBundle);
+ eventLogger.log("3456", Level.WARNING, "oak", "sycamore");
+
+ List<LoggingEvent> loggingEvent = StubAppender.getAndResetLoggingEvents("default-stub");
+ assertEquals(1, loggingEvent.size());
+ assertEquals("Shared oak and sycamore", loggingEvent.get(0).getMessage());
+
+ loggingEvent = StubAppender.getAndResetLoggingEvents("localized-stub");
+ assertEquals(1, loggingEvent.size());
+ assertEquals("Shared oak and sycamore", loggingEvent.get(0).getMessage());
+ }
+
+ @Test
+ public void eventLoggingWithMessageFromSpecificBundle() throws Exception {
+ ServiceReference serviceReference = this.bundleContext.getServiceReference(EventLoggerFactory.class.getName());
+ assertNotNull(serviceReference);
+ EventLoggerFactory eventLoggerFactory = (EventLoggerFactory)this.bundleContext.getService(serviceReference);
+ EventLogger eventLogger = eventLoggerFactory.createEventLogger(this.messageBundle);
+ eventLogger.log("2345", Level.WARNING, "potato", "cauliflower");
+
+ List<LoggingEvent> loggingEvent = StubAppender.getAndResetLoggingEvents("default-stub");
+ assertEquals(1, loggingEvent.size());
+ assertEquals("English potato and cauliflower", loggingEvent.get(0).getMessage());
+
+ loggingEvent = StubAppender.getAndResetLoggingEvents("localized-stub");
+ assertEquals(1, loggingEvent.size());
+ assertEquals("Italian potato and cauliflower", loggingEvent.get(0).getMessage());
+ }
+}
diff --git a/org.eclipse.virgo.medic.integrationtest/src/test/java/org/eclipse/virgo/medic/log/appender/StubAppender.java b/org.eclipse.virgo.medic.integrationtest/src/test/java/org/eclipse/virgo/medic/log/appender/StubAppender.java
new file mode 100644
index 0000000..68e2974
--- /dev/null
+++ b/org.eclipse.virgo.medic.integrationtest/src/test/java/org/eclipse/virgo/medic/log/appender/StubAppender.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.log.appender;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import ch.qos.logback.classic.spi.LoggingEvent;
+import ch.qos.logback.core.AppenderBase;
+
+public class StubAppender extends AppenderBase<LoggingEvent> {
+
+ private static Map<String, List<LoggingEvent>> loggingEvents = new HashMap<String, List<LoggingEvent>>();
+
+ @Override
+ protected void append(LoggingEvent eventObject) {
+ getLoggingEventsByName(name).add(eventObject);
+ }
+
+ public static List<LoggingEvent> getAndResetLoggingEvents(String name) {
+ List<LoggingEvent> loggingEvents = getLoggingEventsByName(name);
+ List<LoggingEvent> response = new ArrayList<LoggingEvent>(loggingEvents);
+ loggingEvents.clear();
+ return response;
+ }
+
+ private static List<LoggingEvent> getLoggingEventsByName(String name) {
+ List<LoggingEvent> loggingEventsForName = loggingEvents.get(name);
+ if (loggingEventsForName == null) {
+ loggingEventsForName = new ArrayList<LoggingEvent>();
+ loggingEvents.put(name, loggingEventsForName);
+ }
+ return loggingEventsForName;
+ }
+}
diff --git a/org.eclipse.virgo.medic.integrationtest/src/test/java/org/eclipse/virgo/medic/log/test/EntryExitTraceTests.java b/org.eclipse.virgo.medic.integrationtest/src/test/java/org/eclipse/virgo/medic/log/test/EntryExitTraceTests.java
new file mode 100644
index 0000000..b476e80
--- /dev/null
+++ b/org.eclipse.virgo.medic.integrationtest/src/test/java/org/eclipse/virgo/medic/log/test/EntryExitTraceTests.java
@@ -0,0 +1,156 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.log.test;
+
+import static org.junit.Assert.assertEquals;
+
+import java.lang.reflect.Method;
+import java.util.List;
+
+import org.eclipse.virgo.medic.log.appender.StubAppender;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import test.TestClass;
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.spi.LoggingEvent;
+
+
+public class EntryExitTraceTests {
+
+ private final TestClass testClass = new TestClass();
+
+ @BeforeClass
+ public static void ensureConfiguredContextSelectorIsDefaultContextSelector() {
+ System.setProperty("logback.ContextSelector", "ch.qos.logback.classic.selector.DefaultContextSelector");
+ }
+
+ @Test
+ public void testPublicBefore() {
+ testClass.publicTest(false);
+ List<LoggingEvent> loggingEvents = StubAppender.getAndResetLoggingEvents(null);
+ assertEquals(2, loggingEvents.size());
+ LoggingEvent event = loggingEvents.get(0);
+ assertEquals(Level.INFO, event.getLevel());
+ assertEquals("> public void test.TestClass.publicTest(boolean)", event.getFormattedMessage());
+ assertEquals("public void test.TestClass.publicTest(boolean)", event.getArgumentArray()[1]);
+ }
+
+ @Test
+ public void testPublicAfterReturn() {
+ testClass.publicTest(false);
+ List<LoggingEvent> loggingEvents = StubAppender.getAndResetLoggingEvents(null);
+ assertEquals(2, loggingEvents.size());
+ LoggingEvent event = loggingEvents.get(1);
+ assertEquals(Level.INFO, event.getLevel());
+ assertEquals("< public void test.TestClass.publicTest(boolean)", event.getFormattedMessage());
+ assertEquals("public void test.TestClass.publicTest(boolean)", event.getArgumentArray()[1]);
+ }
+
+ @Test
+ public void testPublicAfterThrowing() {
+ try {
+ testClass.publicTest(true);
+ } catch (Exception e) {
+ List<LoggingEvent> loggingEvents = StubAppender.getAndResetLoggingEvents(null);
+ assertEquals(2, loggingEvents.size());
+ LoggingEvent event = loggingEvents.get(1);
+ assertEquals(Level.INFO, event.getLevel());
+ assertEquals("< public void test.TestClass.publicTest(boolean)", event.getFormattedMessage());
+ assertEquals(RuntimeException.class.getName(), event.getThrowableProxy().getClassName());
+ }
+ }
+
+ @Test
+ public void testPackagePrivateBefore() throws Exception {
+ Method method = testClass.getClass().getDeclaredMethod("packagePrivateTest", boolean.class);
+ method.setAccessible(true);
+ method.invoke(testClass, false);
+ List<LoggingEvent> loggingEvents = StubAppender.getAndResetLoggingEvents(null);
+ assertEquals(2, loggingEvents.size());
+ LoggingEvent event = loggingEvents.get(0);
+ assertEquals(Level.DEBUG, event.getLevel());
+ assertEquals("> void test.TestClass.packagePrivateTest(boolean)", event.getFormattedMessage());
+ assertEquals("void test.TestClass.packagePrivateTest(boolean)", event.getArgumentArray()[1]);
+ }
+
+ @Test
+ public void testPackagePrivateAfterReturn() throws Exception {
+ Method method = testClass.getClass().getDeclaredMethod("packagePrivateTest", boolean.class);
+ method.setAccessible(true);
+ method.invoke(testClass, false);
+ List<LoggingEvent> loggingEvents = StubAppender.getAndResetLoggingEvents(null);
+ assertEquals(2, loggingEvents.size());
+ LoggingEvent event = loggingEvents.get(1);
+ assertEquals(Level.DEBUG, event.getLevel());
+ assertEquals("< void test.TestClass.packagePrivateTest(boolean)", event.getFormattedMessage());
+ assertEquals("void test.TestClass.packagePrivateTest(boolean)", event.getArgumentArray()[1]);
+ }
+
+ @Test
+ public void testPackagePrivateAfterThrowing() {
+ try {
+ Method method = testClass.getClass().getDeclaredMethod("packagePrivateTest", boolean.class);
+ method.setAccessible(true);
+ method.invoke(testClass, true);
+ } catch (Exception e) {
+ List<LoggingEvent> loggingEvents = StubAppender.getAndResetLoggingEvents(null);
+ assertEquals(2, loggingEvents.size());
+ LoggingEvent event = loggingEvents.get(1);
+ assertEquals(Level.DEBUG, event.getLevel());
+ assertEquals("< void test.TestClass.packagePrivateTest(boolean)", event.getFormattedMessage());
+ assertEquals(RuntimeException.class.getName(), event.getThrowableProxy().getClassName());
+ }
+ }
+
+ @Test
+ public void testPrivateBefore() throws Exception {
+ Method method = testClass.getClass().getDeclaredMethod("privateTest", boolean.class);
+ method.setAccessible(true);
+ method.invoke(testClass, false);
+ List<LoggingEvent> loggingEvents = StubAppender.getAndResetLoggingEvents(null);
+ assertEquals(2, loggingEvents.size());
+ LoggingEvent event = loggingEvents.get(0);
+ assertEquals(Level.TRACE, event.getLevel());
+ assertEquals("> private void test.TestClass.privateTest(boolean)", event.getFormattedMessage());
+ assertEquals("private void test.TestClass.privateTest(boolean)", event.getArgumentArray()[1]);
+ }
+
+ @Test
+ public void testPrivateAfterReturn() throws Exception {
+ Method method = testClass.getClass().getDeclaredMethod("privateTest", boolean.class);
+ method.setAccessible(true);
+ method.invoke(testClass, false);
+ List<LoggingEvent> loggingEvents = StubAppender.getAndResetLoggingEvents(null);
+ assertEquals(2, loggingEvents.size());
+ LoggingEvent event = loggingEvents.get(1);
+ assertEquals(Level.TRACE, event.getLevel());
+ assertEquals("< private void test.TestClass.privateTest(boolean)", event.getFormattedMessage());
+ assertEquals("private void test.TestClass.privateTest(boolean)", event.getArgumentArray()[1]);
+ }
+
+ @Test
+ public void testPrivateAfterThrowing() {
+ try {
+ Method method = testClass.getClass().getDeclaredMethod("privateTest", boolean.class);
+ method.setAccessible(true);
+ method.invoke(testClass, true);
+ } catch (Exception e) {
+ List<LoggingEvent> loggingEvents = StubAppender.getAndResetLoggingEvents(null);
+ assertEquals(2, loggingEvents.size());
+ LoggingEvent event = loggingEvents.get(1);
+ assertEquals(Level.TRACE, event.getLevel());
+ assertEquals("< private void test.TestClass.privateTest(boolean)", event.getFormattedMessage());
+ assertEquals(RuntimeException.class.getName(), event.getThrowableProxy().getClassName());
+ }
+ }
+}
diff --git a/org.eclipse.virgo.medic.integrationtest/src/test/java/org/eclipse/virgo/medic/log/test/MedicLoggingIntegrationTests.java b/org.eclipse.virgo.medic.integrationtest/src/test/java/org/eclipse/virgo/medic/log/test/MedicLoggingIntegrationTests.java
new file mode 100644
index 0000000..2b8b5e8
--- /dev/null
+++ b/org.eclipse.virgo.medic.integrationtest/src/test/java/org/eclipse/virgo/medic/log/test/MedicLoggingIntegrationTests.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.log.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+
+
+import org.eclipse.virgo.medic.log.LoggingConfigurationPublisher;
+import org.eclipse.virgo.medic.log.appender.StubAppender;
+import org.eclipse.virgo.test.framework.OsgiTestRunner;
+import org.eclipse.virgo.test.framework.TestFrameworkUtils;
+
+@RunWith(OsgiTestRunner.class)
+public class MedicLoggingIntegrationTests {
+
+ private BundleContext bundleContext;
+
+ @Before
+ public void before() {
+ this.bundleContext = TestFrameworkUtils.getBundleContextForTestClass(getClass());
+ }
+
+ @Test
+ public void test() throws BundleException {
+ bundleContext.installBundle("file:src/test/resources/test-bundle_1").start();
+ assertEquals(1, StubAppender.getAndResetLoggingEvents("bundle1-stub").size());
+
+ bundleContext.installBundle("file:src/test/resources/test-bundle_2").start();
+ assertEquals(1, StubAppender.getAndResetLoggingEvents("bundle2-stub").size());
+
+ bundleContext.installBundle("file:src/test/resources/test-bundle_3").start();
+ assertEquals(1, StubAppender.getAndResetLoggingEvents("root-stub").size());
+ }
+
+ @Test
+ public void availabilityOfConfigurationPublisher() {
+ assertNotNull(bundleContext.getServiceReference(LoggingConfigurationPublisher.class.getName()));
+ }
+}
diff --git a/org.eclipse.virgo.medic.integrationtest/src/test/java/org/eclipse/virgo/medic/log/test/PrintStreamWrappingTests.java b/org.eclipse.virgo.medic.integrationtest/src/test/java/org/eclipse/virgo/medic/log/test/PrintStreamWrappingTests.java
new file mode 100644
index 0000000..6b22ed8
--- /dev/null
+++ b/org.eclipse.virgo.medic.integrationtest/src/test/java/org/eclipse/virgo/medic/log/test/PrintStreamWrappingTests.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.log.test;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.List;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import ch.qos.logback.classic.spi.LoggingEvent;
+
+import org.eclipse.virgo.medic.log.appender.StubAppender;
+import org.eclipse.virgo.test.framework.OsgiTestRunner;
+
+
+@RunWith(OsgiTestRunner.class)
+public class PrintStreamWrappingTests {
+
+ @Test
+ @Ignore("Test fails on the CI server as it wraps System.out")
+ public void sysOutWrapping() {
+ System.out.println("Hello world!");
+ List<LoggingEvent> loggingEvents = StubAppender.getAndResetLoggingEvents("root-stub");
+ assertEquals(1, loggingEvents.size());
+ assertEquals("Hello world!", loggingEvents.get(0).getMessage());
+ }
+
+ @Test
+ @Ignore("Test fails on the CI server as it wraps System.err")
+ public void sysErrWrapping() {
+ System.err.println("Hello world!");
+ List<LoggingEvent> loggingEvents = StubAppender.getAndResetLoggingEvents("root-stub");
+ assertEquals(1, loggingEvents.size());
+ assertEquals("Hello world!", loggingEvents.get(0).getMessage());
+ }
+}
diff --git a/org.eclipse.virgo.medic.integrationtest/src/test/resources/EventLogMessages_en.properties b/org.eclipse.virgo.medic.integrationtest/src/test/resources/EventLogMessages_en.properties
new file mode 100644
index 0000000..7a26421
--- /dev/null
+++ b/org.eclipse.virgo.medic.integrationtest/src/test/resources/EventLogMessages_en.properties
@@ -0,0 +1 @@
+1234=English {} and {}
diff --git a/org.eclipse.virgo.medic.integrationtest/src/test/resources/EventLogMessages_it.properties b/org.eclipse.virgo.medic.integrationtest/src/test/resources/EventLogMessages_it.properties
new file mode 100644
index 0000000..75634d3
--- /dev/null
+++ b/org.eclipse.virgo.medic.integrationtest/src/test/resources/EventLogMessages_it.properties
@@ -0,0 +1 @@
+1234=Italian {} and {}
diff --git a/org.eclipse.virgo.medic.integrationtest/src/test/resources/META-INF/MANIFEST.MF b/org.eclipse.virgo.medic.integrationtest/src/test/resources/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..97e747d
--- /dev/null
+++ b/org.eclipse.virgo.medic.integrationtest/src/test/resources/META-INF/MANIFEST.MF
@@ -0,0 +1,23 @@
+Manifest-Version: 1.0
+Excluded-Import: ch.qos.logback.classic
+Tool: Bundlor 1.0.0.M6
+Bundle-Name: Medic Logging Integration Tests
+Bundle-SymbolicName: org.eclipse.virgo.medic.log.test
+Import-Package: ch.qos.logback.classic.spi,
+ ch.qos.logback.core,
+ org.aspectj.lang;version="[1.6.6,2.0.0)",
+ org.aspectj.lang.reflect;version="[1.6.6,2.0.0)",
+ org.aspectj.runtime.internal;version="[1.6.6,2.0.0)",
+ org.aspectj.runtime.reflect;version="[1.6.6,2.0.0)",
+ org.eclipse.virgo.medic.dump;version="[1.0.1,1.0.2)",
+ org.eclipse.virgo.medic.eventlog;version="[1.0.1,1.0.2)",
+ org.eclipse.virgo.medic.log;version="[1.0.1,1.0.2)",
+ org.eclipse.virgo.medic.log.appender;version=0,
+ org.eclipse.virgo.test.framework,
+ org.junit,
+ org.junit.runner,
+ org.osgi.framework;version=0,
+ org.osgi.service.cm,
+ org.slf4j
+Bundle-Version: 1.0.0
+Bundle-ManifestVersion: 2
diff --git a/org.eclipse.virgo.medic.integrationtest/src/test/resources/META-INF/test.config.properties b/org.eclipse.virgo.medic.integrationtest/src/test/resources/META-INF/test.config.properties
new file mode 100644
index 0000000..8cfabaa
--- /dev/null
+++ b/org.eclipse.virgo.medic.integrationtest/src/test/resources/META-INF/test.config.properties
@@ -0,0 +1,18 @@
+launcher.bundles=\
+file:../ivy-cache/repository/org.aspectj/com.springsource.org.aspectj.runtime/1.6.6.RELEASE/com.springsource.org.aspectj.runtime-1.6.6.RELEASE.jar@start,\
+file:../ivy-cache/repository/org.slf4j/com.springsource.slf4j.api/1.5.10/com.springsource.slf4j.api-1.5.10.jar@start,\
+file:../ivy-cache/repository/org.eclipse.virgo.util/org.eclipse.virgo.util.common/2.1.0.D-20100420091708/org.eclipse.virgo.util.common-2.1.0.D-20100420091708.jar,\
+file:../ivy-cache/repository/org.eclipse.virgo.util/org.eclipse.virgo.util.osgi/2.1.0.D-20100420091708/org.eclipse.virgo.util.osgi-2.1.0.D-20100420091708.jar,\
+file:../ivy-cache/repository/org.eclipse.virgo.util/org.eclipse.virgo.util.parser.manifest/2.1.0.D-20100420091708/org.eclipse.virgo.util.parser.manifest-2.1.0.D-20100420091708.jar,\
+file:../ivy-cache/repository/org.apache.felix/org.apache.felix.configadmin/1.2.4/org.apache.felix.configadmin-1.2.4.jar@start,\
+file:../org.eclipse.virgo.medic/target/artifacts/org.eclipse.virgo.medic.jar@start,\
+file:../org.eclipse.virgo.medic.core/target/artifacts/org.eclipse.virgo.medic.core.jar@start,\
+file:src/test/resources/config-fragment,\
+file:src/test/resources/appender-fragment
+
+osgi.java.profile.bootdelegation=override
+osgi.parentClassloader=fwk
+osgi.context.bootdelegation=false
+osgi.compatibility.bootdelegation=false
+osgi.console=2401
+osgi.java.profile=file:src/test/resources/java6-server.profile
diff --git a/org.eclipse.virgo.medic.integrationtest/src/test/resources/appender-fragment/META-INF/MANIFEST.MF b/org.eclipse.virgo.medic.integrationtest/src/test/resources/appender-fragment/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..732bebd
--- /dev/null
+++ b/org.eclipse.virgo.medic.integrationtest/src/test/resources/appender-fragment/META-INF/MANIFEST.MF
@@ -0,0 +1,6 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: appender.fragment
+Fragment-Host: org.eclipse.virgo.medic.core
+Export-Package: org.eclipse.virgo.medic.log.appender
+
diff --git a/org.eclipse.virgo.medic.integrationtest/src/test/resources/appender-fragment/org/eclipse/virgo/medic/log/appender/StubAppender.class b/org.eclipse.virgo.medic.integrationtest/src/test/resources/appender-fragment/org/eclipse/virgo/medic/log/appender/StubAppender.class
new file mode 100644
index 0000000..39b1b41
--- /dev/null
+++ b/org.eclipse.virgo.medic.integrationtest/src/test/resources/appender-fragment/org/eclipse/virgo/medic/log/appender/StubAppender.class
Binary files differ
diff --git a/org.eclipse.virgo.medic.integrationtest/src/test/resources/config-fragment/META-INF/MANIFEST.MF b/org.eclipse.virgo.medic.integrationtest/src/test/resources/config-fragment/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..cb77330
--- /dev/null
+++ b/org.eclipse.virgo.medic.integrationtest/src/test/resources/config-fragment/META-INF/MANIFEST.MF
@@ -0,0 +1,5 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: config.fragment
+Bundle-Vendor: SpringSource Inc.
+Fragment-Host: org.eclipse.virgo.medic.core
diff --git a/org.eclipse.virgo.medic.integrationtest/src/test/resources/config-fragment/logback.xml b/org.eclipse.virgo.medic.integrationtest/src/test/resources/config-fragment/logback.xml
new file mode 100644
index 0000000..1332bac
--- /dev/null
+++ b/org.eclipse.virgo.medic.integrationtest/src/test/resources/config-fragment/logback.xml
@@ -0,0 +1,42 @@
+<configuration>
+
+ <appender name="localized-console" class="ch.qos.logback.core.ConsoleAppender">
+ <layout class="ch.qos.logback.classic.PatternLayout">
+ <Pattern>Localized: %-24.24thread &lt;%X{medic.eventCode}&gt; %msg %ex%n</Pattern>
+ </layout>
+ </appender>
+
+ <appender name="default-console" class="ch.qos.logback.core.ConsoleAppender">
+ <layout class="ch.qos.logback.classic.PatternLayout">
+ <Pattern>Default: %-24.24thread &lt;%X{medic.eventCode}&gt; %msg %ex%n</Pattern>
+ </layout>
+ </appender>
+
+ <appender name="root-console" class="ch.qos.logback.core.ConsoleAppender">
+ <layout class="ch.qos.logback.classic.PatternLayout">
+ <Pattern>Root: [%d{yyyy-MM-dd HH:mm:ss.SSS}] %-24.24thread %msg %ex%n</Pattern>
+ </layout>
+ </appender>
+
+ <appender name="root-stub" class="org.eclipse.virgo.medic.log.appender.StubAppender"/>
+
+ <appender name="default-stub" class="org.eclipse.virgo.medic.log.appender.StubAppender"/>
+
+ <appender name="localized-stub" class="org.eclipse.virgo.medic.log.appender.StubAppender"/>
+
+ <logger name="org.eclipse.virgo.medic.eventlog.localized">
+ <appender-ref ref="localized-console" />
+ <appender-ref ref="localized-stub" />
+ </logger>
+
+ <logger name="org.eclipse.virgo.medic.eventlog.default">
+ <appender-ref ref="default-console" />
+ <appender-ref ref="default-stub" />
+ </logger>
+
+ <root level="debug">
+ <appender-ref ref="root-stub"/>
+ <appender-ref ref="root-console"/>
+ </root>
+
+</configuration>
diff --git a/org.eclipse.virgo.medic.integrationtest/src/test/resources/java6-server.profile b/org.eclipse.virgo.medic.integrationtest/src/test/resources/java6-server.profile
new file mode 100644
index 0000000..9a72f39
--- /dev/null
+++ b/org.eclipse.virgo.medic.integrationtest/src/test/resources/java6-server.profile
@@ -0,0 +1,165 @@
+org.osgi.framework.system.packages = \
+ javax.accessibility,\
+ javax.crypto,\
+ javax.crypto.interfaces,\
+ javax.crypto.spec,\
+ javax.imageio,\
+ javax.imageio.event,\
+ javax.imageio.metadata,\
+ javax.imageio.plugins.bmp,\
+ javax.imageio.plugins.jpeg,\
+ javax.imageio.spi,\
+ javax.imageio.stream,\
+ javax.jws,\
+ javax.jws;version="2.0",\
+ javax.jws.soap,\
+ javax.jws.soap;version="2.0",\
+ javax.management,\
+ javax.management.loading,\
+ javax.management.modelmbean,\
+ javax.management.monitor,\
+ javax.management.openmbean,\
+ javax.management.relation,\
+ javax.management.remote,\
+ javax.management.remote.rmi,\
+ javax.management.timer,\
+ javax.naming,\
+ javax.naming.directory,\
+ javax.naming.event,\
+ javax.naming.ldap,\
+ javax.naming.spi,\
+ javax.net,\
+ javax.net.ssl,\
+ javax.print,\
+ javax.print.attribute,\
+ javax.print.attribute.standard,\
+ javax.print.event,\
+ javax.rmi,\
+ javax.rmi.CORBA,\
+ javax.rmi.ssl,\
+ javax.security.auth,\
+ javax.security.auth.callback,\
+ javax.security.auth.kerberos,\
+ javax.security.auth.login,\
+ javax.security.auth.spi,\
+ javax.security.auth.x500,\
+ javax.security.cert,\
+ javax.security.sasl,\
+ javax.sound.midi,\
+ javax.sound.midi.spi,\
+ javax.sound.sampled,\
+ javax.sound.sampled.spi,\
+ javax.sql,\
+ javax.sql.rowset,\
+ javax.sql.rowset.serial,\
+ javax.sql.rowset.spi,\
+ javax.swing,\
+ javax.swing.border,\
+ javax.swing.colorchooser,\
+ javax.swing.event,\
+ javax.swing.filechooser,\
+ javax.swing.plaf,\
+ javax.swing.plaf.basic,\
+ javax.swing.plaf.metal,\
+ javax.swing.plaf.multi,\
+ javax.swing.plaf.synth,\
+ javax.swing.table,\
+ javax.swing.text,\
+ javax.swing.text.html,\
+ javax.swing.text.html.parser,\
+ javax.swing.text.rtf,\
+ javax.swing.tree,\
+ javax.swing.undo,\
+ javax.transaction,\
+ javax.transaction;version="1.0.1",\
+ javax.transaction;version="1.1.0",\
+ javax.transaction.xa,\
+ javax.transaction.xa;version="1.0.1",\
+ javax.transaction.xa;version="1.1.0",\
+ javax.xml,\
+ javax.xml;version="1.0.1",\
+ javax.xml.bind,\
+ javax.xml.bind;version="2.0",\
+ javax.xml.bind.annotation,\
+ javax.xml.bind.annotation;version="2.0",\
+ javax.xml.bind.annotation.adapters,\
+ javax.xml.bind.annotation.adapters;version="2.0",\
+ javax.xml.bind.attachment,\
+ javax.xml.bind.attachment;version="2.0",\
+ javax.xml.bind.helpers,\
+ javax.xml.bind.helpers;version="2.0",\
+ javax.xml.bind.util,\
+ javax.xml.bind.util;version="2.0",\
+ javax.xml.datatype,\
+ javax.xml.namespace,\
+ javax.xml.parsers,\
+ javax.xml.soap,\
+ javax.xml.soap;version="1.3.0",\
+ javax.xml.stream,\
+ javax.xml.stream;version="1.0.1",\
+ javax.xml.stream.events,\
+ javax.xml.stream.events;version="1.0.1",\
+ javax.xml.stream.util,\
+ javax.xml.stream.util;version="1.0.1",\
+ javax.xml.transform,\
+ javax.xml.transform.dom,\
+ javax.xml.transform.sax,\
+ javax.xml.transform.stream,\
+ javax.xml.validation,\
+ javax.xml.xpath,\
+ org.ietf.jgss,\
+ org.omg.CORBA,\
+ org.omg.CORBA_2_3,\
+ org.omg.CORBA_2_3.portable,\
+ org.omg.CORBA.DynAnyPackage,\
+ org.omg.CORBA.ORBPackage,\
+ org.omg.CORBA.portable,\
+ org.omg.CORBA.TypeCodePackage,\
+ org.omg.CosNaming,\
+ org.omg.CosNaming.NamingContextExtPackage,\
+ org.omg.CosNaming.NamingContextPackage,\
+ org.omg.Dynamic,\
+ org.omg.DynamicAny,\
+ org.omg.DynamicAny.DynAnyFactoryPackage,\
+ org.omg.DynamicAny.DynAnyPackage,\
+ org.omg.IOP,\
+ org.omg.IOP.CodecFactoryPackage,\
+ org.omg.IOP.CodecPackage,\
+ org.omg.Messaging,\
+ org.omg.PortableInterceptor,\
+ org.omg.PortableInterceptor.ORBInitInfoPackage,\
+ org.omg.PortableServer,\
+ org.omg.PortableServer.CurrentPackage,\
+ org.omg.PortableServer.POAManagerPackage,\
+ org.omg.PortableServer.POAPackage,\
+ org.omg.PortableServer.portable,\
+ org.omg.PortableServer.ServantLocatorPackage,\
+ org.omg.SendingContext,\
+ org.omg.stub.java.rmi,\
+ org.w3c.dom,\
+ org.w3c.dom.bootstrap,\
+ org.w3c.dom.css,\
+ org.w3c.dom.events,\
+ org.w3c.dom.html,\
+ org.w3c.dom.ls,\
+ org.w3c.dom.ranges,\
+ org.w3c.dom.stylesheets,\
+ org.w3c.dom.traversal,\
+ org.w3c.dom.views ,\
+ org.xml.sax,\
+ org.xml.sax.ext,\
+ org.xml.sax.helpers
+org.osgi.framework.bootdelegation = \
+ com_cenqua_clover,\
+ com.cenqua.*,\
+ com.yourkit.*,\
+ sun.reflect,\
+ sun.reflect.*
+org.osgi.framework.executionenvironment = \
+ OSGi/Minimum-1.0,\
+ OSGi/Minimum-1.1,\
+ J2SE-1.3,\
+ J2SE-1.4,\
+ J2SE-1.5,\
+ J2SE-1.6
+osgi.java.profile.name = SpringSource-dm-Server-Java6
diff --git a/org.eclipse.virgo.medic.integrationtest/src/test/resources/logback-test.xml b/org.eclipse.virgo.medic.integrationtest/src/test/resources/logback-test.xml
new file mode 100644
index 0000000..a47881b
--- /dev/null
+++ b/org.eclipse.virgo.medic.integrationtest/src/test/resources/logback-test.xml
@@ -0,0 +1,5 @@
+<configuration>
+ <root level="trace">
+ <appender class="org.eclipse.virgo.medic.log.appender.StubAppender"/>
+ </root>
+</configuration>
diff --git a/org.eclipse.virgo.medic.integrationtest/src/test/resources/message-bundle/EventLogMessages_en.properties b/org.eclipse.virgo.medic.integrationtest/src/test/resources/message-bundle/EventLogMessages_en.properties
new file mode 100644
index 0000000..54b2ddf
--- /dev/null
+++ b/org.eclipse.virgo.medic.integrationtest/src/test/resources/message-bundle/EventLogMessages_en.properties
@@ -0,0 +1 @@
+2345=English {} and {}
diff --git a/org.eclipse.virgo.medic.integrationtest/src/test/resources/message-bundle/EventLogMessages_it.properties b/org.eclipse.virgo.medic.integrationtest/src/test/resources/message-bundle/EventLogMessages_it.properties
new file mode 100644
index 0000000..09d1f6e
--- /dev/null
+++ b/org.eclipse.virgo.medic.integrationtest/src/test/resources/message-bundle/EventLogMessages_it.properties
@@ -0,0 +1 @@
+2345=Italian {} and {}
diff --git a/org.eclipse.virgo.medic.integrationtest/src/test/resources/message-bundle/META-INF/MANIFEST.MF b/org.eclipse.virgo.medic.integrationtest/src/test/resources/message-bundle/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..c4c505c
--- /dev/null
+++ b/org.eclipse.virgo.medic.integrationtest/src/test/resources/message-bundle/META-INF/MANIFEST.MF
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Bundle-SymbolicName: message.bundle
+Bundle-ManifestVersion: 2
diff --git a/org.eclipse.virgo.medic.integrationtest/src/test/resources/message-fragment/EventLogMessages.properties b/org.eclipse.virgo.medic.integrationtest/src/test/resources/message-fragment/EventLogMessages.properties
new file mode 100644
index 0000000..3e78bfa
--- /dev/null
+++ b/org.eclipse.virgo.medic.integrationtest/src/test/resources/message-fragment/EventLogMessages.properties
@@ -0,0 +1 @@
+3456=Shared {} and {}
diff --git a/org.eclipse.virgo.medic.integrationtest/src/test/resources/message-fragment/META-INF/MANIFEST.MF b/org.eclipse.virgo.medic.integrationtest/src/test/resources/message-fragment/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..49ef7bc
--- /dev/null
+++ b/org.eclipse.virgo.medic.integrationtest/src/test/resources/message-fragment/META-INF/MANIFEST.MF
@@ -0,0 +1,5 @@
+Manifest-Version: 1.0
+Bundle-SymbolicName: message.fragment
+Bundle-ManifestVersion: 2
+Fragment-Host: message.bundle
+
diff --git a/org.eclipse.virgo.medic.integrationtest/src/test/resources/test-bundle_1/META-INF/MANIFEST.MF b/org.eclipse.virgo.medic.integrationtest/src/test/resources/test-bundle_1/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..2544d2d
--- /dev/null
+++ b/org.eclipse.virgo.medic.integrationtest/src/test/resources/test-bundle_1/META-INF/MANIFEST.MF
@@ -0,0 +1,6 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: test.bundle
+Import-Package: org.osgi.framework, org.slf4j, org.slf4j.spi
+Bundle-Activator: test.TestActivator
+Bundle-Version: 1.0
diff --git a/org.eclipse.virgo.medic.integrationtest/src/test/resources/test-bundle_1/logback.xml b/org.eclipse.virgo.medic.integrationtest/src/test/resources/test-bundle_1/logback.xml
new file mode 100644
index 0000000..2862b7b
--- /dev/null
+++ b/org.eclipse.virgo.medic.integrationtest/src/test/resources/test-bundle_1/logback.xml
@@ -0,0 +1,15 @@
+<configuration>
+ <appender name="STDOUT" class="org.eclipse.virgo.medic.log.logback.ReroutingAwareConsoleAppender">
+ <layout class="ch.qos.logback.classic.PatternLayout">
+ <Pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] %-24.24thread %msg %ex%n</Pattern>
+ </layout>
+ </appender>
+
+ <appender name="bundle1-stub" class="org.eclipse.virgo.medic.log.appender.StubAppender"/>
+
+ <root level="debug">
+ <appender-ref ref="STDOUT" />
+ <appender-ref ref="bundle1-stub" />
+ </root>
+
+</configuration>
diff --git a/org.eclipse.virgo.medic.integrationtest/src/test/resources/test-bundle_1/test/TestActivator.class b/org.eclipse.virgo.medic.integrationtest/src/test/resources/test-bundle_1/test/TestActivator.class
new file mode 100644
index 0000000..2f77b0a
--- /dev/null
+++ b/org.eclipse.virgo.medic.integrationtest/src/test/resources/test-bundle_1/test/TestActivator.class
Binary files differ
diff --git a/org.eclipse.virgo.medic.integrationtest/src/test/resources/test-bundle_2/META-INF/MANIFEST.MF b/org.eclipse.virgo.medic.integrationtest/src/test/resources/test-bundle_2/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..a3d659b
--- /dev/null
+++ b/org.eclipse.virgo.medic.integrationtest/src/test/resources/test-bundle_2/META-INF/MANIFEST.MF
@@ -0,0 +1,6 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: test.bundle
+Import-Package: org.osgi.framework, org.slf4j, org.slf4j.spi
+Bundle-Activator: test.TestActivator
+Bundle-Version: 2.0
diff --git a/org.eclipse.virgo.medic.integrationtest/src/test/resources/test-bundle_2/logback.xml b/org.eclipse.virgo.medic.integrationtest/src/test/resources/test-bundle_2/logback.xml
new file mode 100644
index 0000000..2f914b7
--- /dev/null
+++ b/org.eclipse.virgo.medic.integrationtest/src/test/resources/test-bundle_2/logback.xml
@@ -0,0 +1,15 @@
+<configuration>
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+ <layout class="ch.qos.logback.classic.PatternLayout">
+ <Pattern>Bundle2 [%d{yyyy-MM-dd HH:mm:ss.SSS}] %-24.24thread %msg %ex%n</Pattern>
+ </layout>
+ </appender>
+
+ <appender name="bundle2-stub" class="org.eclipse.virgo.medic.log.appender.StubAppender"/>
+
+ <root level="debug">
+ <appender-ref ref="STDOUT" />
+ <appender-ref ref="bundle2-stub"/>
+ </root>
+
+</configuration>
diff --git a/org.eclipse.virgo.medic.integrationtest/src/test/resources/test-bundle_2/test/TestActivator.class b/org.eclipse.virgo.medic.integrationtest/src/test/resources/test-bundle_2/test/TestActivator.class
new file mode 100644
index 0000000..2f77b0a
--- /dev/null
+++ b/org.eclipse.virgo.medic.integrationtest/src/test/resources/test-bundle_2/test/TestActivator.class
Binary files differ
diff --git a/org.eclipse.virgo.medic.integrationtest/src/test/resources/test-bundle_3/META-INF/MANIFEST.MF b/org.eclipse.virgo.medic.integrationtest/src/test/resources/test-bundle_3/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..8789b85
--- /dev/null
+++ b/org.eclipse.virgo.medic.integrationtest/src/test/resources/test-bundle_3/META-INF/MANIFEST.MF
@@ -0,0 +1,6 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: test.bundle
+Import-Package: org.osgi.framework, org.slf4j, org.slf4j.spi
+Bundle-Activator: test.TestActivator
+Bundle-Version: 3.0
diff --git a/org.eclipse.virgo.medic.integrationtest/src/test/resources/test-bundle_3/test/TestActivator.class b/org.eclipse.virgo.medic.integrationtest/src/test/resources/test-bundle_3/test/TestActivator.class
new file mode 100644
index 0000000..2f77b0a
--- /dev/null
+++ b/org.eclipse.virgo.medic.integrationtest/src/test/resources/test-bundle_3/test/TestActivator.class
Binary files differ
diff --git a/org.eclipse.virgo.medic.integrationtest/template.mf b/org.eclipse.virgo.medic.integrationtest/template.mf
new file mode 100644
index 0000000..05769c2
--- /dev/null
+++ b/org.eclipse.virgo.medic.integrationtest/template.mf
@@ -0,0 +1,15 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: org.eclipse.virgo.medic.log.test
+Bundle-Name: Medic Logging Integration Tests
+Bundle-Version: 1.0.0
+Import-Template:
+ org.eclipse.virgo.medic.*;version="[1.0.1, 1.0.2)",
+ org.aspectj.*;version="${org.aspectj:[=.=.= , +1.0.0)}"
+Import-Package:
+ org.osgi.framework;version="0",
+ org.eclipse.virgo.medic.log.appender;version="0"
+Excluded-Exports:
+ *
+Excluded-Imports:
+ ch.qos.logback.classic
diff --git a/org.eclipse.virgo.medic.test/.classpath b/org.eclipse.virgo.medic.test/.classpath
new file mode 100644
index 0000000..ed078d7
--- /dev/null
+++ b/org.eclipse.virgo.medic.test/.classpath
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src/main/java">
+ <attributes>
+ <attribute name="com.springsource.server.ide.jdt.core.test.classpathentry" value="false"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="src" path="src/main/resources">
+ <attributes>
+ <attribute name="com.springsource.server.ide.jdt.core.test.classpathentry" value="false"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="src" output="target/test-classes" path="src/test/java">
+ <attributes>
+ <attribute name="com.springsource.server.ide.jdt.core.test.classpathentry" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="src" output="target/test-classes" path="src/test/resources">
+ <attributes>
+ <attribute name="com.springsource.server.ide.jdt.core.test.classpathentry" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="var" path="MEDIC_IVY_CACHE/org.junit/com.springsource.org.junit/4.7.0/com.springsource.org.junit-4.7.0.jar" sourcepath="/MEDIC_IVY_CACHE/org.junit/com.springsource.org.junit/4.7.0/com.springsource.org.junit-sources-4.7.0.jar"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/org.eclipse.virgo.medic"/>
+ <classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/org.eclipse.virgo.medic.test/.project b/org.eclipse.virgo.medic.test/.project
new file mode 100644
index 0000000..723469b
--- /dev/null
+++ b/org.eclipse.virgo.medic.test/.project
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.virgo.medic.test</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.wst.common.project.facet.core.builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.springframework.ide.eclipse.core.springbuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.springsource.server.ide.bundlor.core.builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>com.springsource.server.ide.facet.core.bundlenature</nature>
+ <nature>org.springframework.ide.eclipse.core.springnature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.wst.common.project.facet.core.nature</nature>
+ </natures>
+</projectDescription>
diff --git a/org.eclipse.virgo.medic.test/.settings/com.springsource.server.ide.bundlor.core.prefs b/org.eclipse.virgo.medic.test/.settings/com.springsource.server.ide.bundlor.core.prefs
new file mode 100644
index 0000000..03d978a
--- /dev/null
+++ b/org.eclipse.virgo.medic.test/.settings/com.springsource.server.ide.bundlor.core.prefs
@@ -0,0 +1,5 @@
+#Thu Nov 12 08:44:28 GMT 2009
+com.springsource.server.ide.bundlor.core.bundlor.generated.manifest.autoformatting=true
+com.springsource.server.ide.bundlor.core.byte.code.scanning=true
+com.springsource.server.ide.bundlor.core.template.properties.files=../build.versions
+eclipse.preferences.version=1
diff --git a/org.eclipse.virgo.medic.test/.settings/org.eclipse.wst.common.project.facet.core.xml b/org.eclipse.virgo.medic.test/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 0000000..801f856
--- /dev/null
+++ b/org.eclipse.virgo.medic.test/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<faceted-project>
+ <installed facet="com.springsource.server.bundle" version="1.0"/>
+</faceted-project>
diff --git a/org.eclipse.virgo.medic.test/.springBeans b/org.eclipse.virgo.medic.test/.springBeans
new file mode 100644
index 0000000..5152991
--- /dev/null
+++ b/org.eclipse.virgo.medic.test/.springBeans
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beansProjectDescription>
+ <version>1</version>
+ <pluginVersion><![CDATA[2.2.5.M1]]></pluginVersion>
+ <configSuffixes>
+ <configSuffix><![CDATA[xml]]></configSuffix>
+ </configSuffixes>
+ <enableImports><![CDATA[false]]></enableImports>
+ <configs>
+ </configs>
+ <configSets>
+ </configSets>
+</beansProjectDescription>
diff --git a/org.eclipse.virgo.medic.test/build.xml b/org.eclipse.virgo.medic.test/build.xml
new file mode 100644
index 0000000..6cd0295
--- /dev/null
+++ b/org.eclipse.virgo.medic.test/build.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="org.eclipse.virgo.medic.test">
+
+ <property file="${basedir}/../build.properties"/>
+ <property file="${basedir}/../build.versions"/>
+ <import file="${basedir}/../virgo-build/standard/default.xml"/>
+
+</project>
diff --git a/org.eclipse.virgo.medic.test/ivy.xml b/org.eclipse.virgo.medic.test/ivy.xml
new file mode 100644
index 0000000..43762ad
--- /dev/null
+++ b/org.eclipse.virgo.medic.test/ivy.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?xml-stylesheet type="text/xsl" href="http://ivyrep.jayasoft.org/ivy-doc.xsl"?>
+<ivy-module
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="http://incubator.apache.org/ivy/schemas/ivy.xsd"
+ version="1.3">
+
+ <info organisation="org.eclipse.virgo.medic" module="${ant.project.name}"/>
+
+ <configurations>
+ <include file="${virgo.build.dir}/common/default-ivy-configurations.xml"/>
+ </configurations>
+
+ <publications>
+ <artifact name="${ant.project.name}"/>
+ <artifact name="${ant.project.name}-sources" type="src" ext="jar"/>
+ </publications>
+
+ <dependencies>
+ <dependency org="org.eclipse.virgo.medic" name="org.eclipse.virgo.medic" rev="latest.integration" conf="compile->compile"/>
+ <dependency org="org.junit" name="com.springsource.org.junit" rev="${org.junit}" conf="test->runtime"/>
+ </dependencies>
+
+</ivy-module>
diff --git a/org.eclipse.virgo.medic.test/src/main/java/org/eclipse/virgo/medic/test/eventlog/LoggedEvent.java b/org.eclipse.virgo.medic.test/src/main/java/org/eclipse/virgo/medic/test/eventlog/LoggedEvent.java
new file mode 100644
index 0000000..72db818
--- /dev/null
+++ b/org.eclipse.virgo.medic.test/src/main/java/org/eclipse/virgo/medic/test/eventlog/LoggedEvent.java
@@ -0,0 +1,105 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.test.eventlog;
+
+import java.io.PrintStream;
+
+import org.eclipse.virgo.medic.eventlog.Level;
+
+
+public class LoggedEvent {
+
+ private final String code;
+
+ private final Level level;
+
+ private final Throwable throwable;
+
+ private final Object[] inserts;
+
+ LoggedEvent(String code, Level level, Object... inserts) {
+ this(code, level, null, inserts);
+ }
+
+ LoggedEvent(String code, Level level, Throwable throwable, Object... inserts) {
+ this.code = code;
+ this.level = level;
+ this.throwable = throwable;
+ this.inserts = inserts.clone();
+ }
+
+ /**
+ * Returns the code of the event that was logged.
+ *
+ * @return the logged event's code.
+ */
+ public String getCode() {
+ return this.code;
+ }
+
+ /**
+ * Returns the level of the event that was logged.
+ *
+ * @return the logged event's level
+ */
+ public Level getLevel() {
+ return this.level;
+ }
+
+ /**
+ * Returns the <code>Throwable</code> that was logged as part of the event, or <code>null</code> if no
+ * <code>Throwable</code> was logged
+ *
+ * @return The logged <code>Throwable</code>
+ */
+ public Throwable getThrowable() {
+ return throwable;
+ }
+
+ /**
+ * Returns the inserts that were logged, or an empty array if no inserts were logged.
+ *
+ * @return The logged inserts, never <code>null</code>.
+ */
+ public Object[] getInserts() {
+ return inserts.clone();
+ }
+
+ /**
+ * Print (to outStr) a human-readable form of the LoggedEvent, without fancy formatting.
+ *
+ * @param printStream where to print it
+ */
+ public void print(PrintStream printStream) {
+ printStream.print(String.format("Code: '%s' Level: '%s'", this.code, String.valueOf(this.level)));
+ printInserts(printStream);
+ if (this.throwable!=null) {
+ printStream.print(" Exception: ");
+ this.throwable.printStackTrace(printStream);
+ }
+ }
+
+ /**
+ * Print inserts.
+ *
+ * @param outStr where to print them
+ */
+ private void printInserts(PrintStream outStr) {
+ if (inserts.length != 0) {
+ outStr.print(String.format(" Inserts: {'%s'", String.valueOf(this.inserts[0])));
+ for (int ins = 1; ins < this.inserts.length; ++ins) {
+ outStr.print(String.format(", '%s'", String.valueOf(this.inserts[ins])));
+ }
+ outStr.print("}");
+ }
+ }
+}
diff --git a/org.eclipse.virgo.medic.test/src/main/java/org/eclipse/virgo/medic/test/eventlog/MockEventLogger.java b/org.eclipse.virgo.medic.test/src/main/java/org/eclipse/virgo/medic/test/eventlog/MockEventLogger.java
new file mode 100644
index 0000000..6f7903c
--- /dev/null
+++ b/org.eclipse.virgo.medic.test/src/main/java/org/eclipse/virgo/medic/test/eventlog/MockEventLogger.java
@@ -0,0 +1,164 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.test.eventlog;
+
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.eclipse.virgo.medic.eventlog.EventLogger;
+import org.eclipse.virgo.medic.eventlog.Level;
+import org.eclipse.virgo.medic.eventlog.LogEvent;
+
+
+/**
+ * A mock implementation of {@link EventLogger} for testing purposes. The events that have been logged can be accessed
+ * by calling {@link #getLoggedEvents()}.<br/>
+ * This implementation saves all events for subsequent analysis, and has an option to clear the log for re-use.<br/>
+ * This version also has an operation for asserting that the sequence of events matches a supplied array. This is for
+ * convenient unit tests.
+ * <p/>
+ *
+ * <strong>Concurrent Semantics:</strong><br/>
+ * Thread-safe during logging, but not for retrieval and re-initialisation.
+ */
+public class MockEventLogger implements EventLogger {
+
+ private final List<LoggedEvent> loggedEvents = new CopyOnWriteArrayList<LoggedEvent>();
+
+ private final boolean noisy;
+
+ private volatile boolean called = false;
+
+ private final PrintStream printStream;
+
+ public MockEventLogger() {
+ this(false, null);
+ }
+
+ public MockEventLogger(boolean noisy, PrintStream printStream) {
+ this.noisy = noisy;
+ this.printStream = printStream;
+ }
+
+ public void log(LogEvent logEvent, Object... inserts) {
+ this.log(logEvent.getEventCode(), logEvent.getLevel(), inserts);
+ }
+
+ public void log(LogEvent logEvent, Throwable throwable, Object... inserts) {
+ this.log(logEvent.getEventCode(), logEvent.getLevel(), throwable, inserts);
+ }
+
+ public void log(String code, Level level, Object... inserts) {
+ LoggedEvent loggedEvent = new LoggedEvent(code, level, inserts);
+ this.loggedEvents.add(loggedEvent);
+ this.called = true;
+ if (noisy) {
+ loggedEvent.print(this.printStream);
+ }
+ }
+
+ public void log(String code, Level level, Throwable throwable, Object... inserts) {
+ LoggedEvent loggedEvent = new LoggedEvent(code, level, throwable, inserts);
+ this.loggedEvents.add(loggedEvent);
+ this.called = true;
+ if (noisy) {
+ loggedEvent.print(this.printStream);
+ }
+ }
+
+ /**
+ * Returns a <code>List</code> of the events that have been logged. The order of the items in the list corresponds
+ * to the order in which the events were logged. If no events have been logged an empty list is returned.
+ *
+ * @return the logged events
+ */
+ public List<LoggedEvent> getLoggedEvents() {
+ return this.loggedEvents;
+ }
+
+ /**
+ * @return true if this EventLogger has been called since (re)initialisation.
+ */
+ public boolean getCalled() {
+ return this.called;
+ }
+
+ /**
+ * Reinitialise this EventLogger.
+ */
+ public void reinitialise() {
+ this.called = false;
+ this.loggedEvents.clear();
+ }
+
+ /**
+ * Helper method for unit tests to check sequence of logged events after a test.
+ *
+ * @param codes sequence of message codes expected
+ * @return true iff sequence of codes matches logged events exactly
+ */
+ public boolean isLogged(String... codes) {
+ if (this.loggedEvents.size() != codes.length) {
+ return false;
+ }
+ int index = 0;
+ for (String code : codes) {
+ if (!code.equals(this.loggedEvents.get(index++).getCode())) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Helper method for unit tests to check superset of logged events after a test.
+ *
+ * @param codes sequence of message codes expected to be contained in logged events (in any order)
+ * @return true iff the codes are all in the saved {@link LoggedEvent}s.
+ */
+ public boolean containsLogged(String... codes) {
+ List<String> codeList = new ArrayList<String>();
+ for (LoggedEvent event : this.loggedEvents) {
+ codeList.add(event.getCode());
+ }
+ for (String code : codes) {
+ if (!codeList.contains(code)){
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Helper method for unit tests to retrieve specific logged events from saved events.
+ *
+ * @param codes sequence of message codes to have events extracted, in order.
+ * @return LoggedEvents with supplied codes in same sequence from log.
+ */
+ public List<LoggedEvent> getEventsWithCodes(String... codes) {
+ List<LoggedEvent> eventList = new ArrayList<LoggedEvent>();
+ int eventIndex = 0;
+ int loggedEventsSize = this.loggedEvents.size();
+ for (String code : codes) {
+ while (eventIndex < loggedEventsSize) {
+ LoggedEvent loggedEvent = this.loggedEvents.get(eventIndex++);
+ if (code.equals(loggedEvent.getCode())) {
+ eventList.add(loggedEvent);
+ break;
+ }
+ }
+ }
+ return eventList;
+ }
+}
diff --git a/org.eclipse.virgo.medic.test/src/main/resources/.gitignore b/org.eclipse.virgo.medic.test/src/main/resources/.gitignore
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/org.eclipse.virgo.medic.test/src/main/resources/.gitignore
diff --git a/org.eclipse.virgo.medic.test/src/test/java/org/eclipse/virgo/medic/test/eventlog/LoggedEventTests.java b/org.eclipse.virgo.medic.test/src/test/java/org/eclipse/virgo/medic/test/eventlog/LoggedEventTests.java
new file mode 100644
index 0000000..7ad8333
--- /dev/null
+++ b/org.eclipse.virgo.medic.test/src/test/java/org/eclipse/virgo/medic/test/eventlog/LoggedEventTests.java
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.test.eventlog;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.io.StringWriter;
+import java.io.Writer;
+
+import org.eclipse.virgo.medic.eventlog.Level;
+import org.eclipse.virgo.medic.test.eventlog.LoggedEvent;
+import org.junit.Test;
+
+
+public class LoggedEventTests {
+
+ @Test
+ public void print() {
+ StringWriter printedWriter = new StringWriter();
+ PrintStream printStream = new PrintStream(new WriterOutputStream(printedWriter));
+
+ new LoggedEvent("code", Level.WARNING, "a", 5, true).print(printStream);
+
+ String printed = printedWriter.toString();
+ assertEquals("Code: 'code' Level: 'WARNING' Inserts: {'a', '5', 'true'}", printed);
+ }
+
+ @Test
+ public void printWithOneInsert() {
+ StringWriter printedWriter = new StringWriter();
+ PrintStream printStream = new PrintStream(new WriterOutputStream(printedWriter));
+
+ new LoggedEvent("code", Level.WARNING, 5).print(printStream);
+
+ String printed = printedWriter.toString();
+ System.out.println(printed);
+ assertEquals("Code: 'code' Level: 'WARNING' Inserts: {'5'}", printed);
+ }
+
+ @Test
+ public void printWithNoInserts() {
+ StringWriter printedWriter = new StringWriter();
+ PrintStream printStream = new PrintStream(new WriterOutputStream(printedWriter));
+
+ new LoggedEvent("code", Level.WARNING).print(printStream);
+
+ String printed = printedWriter.toString();
+ System.out.println(printed);
+ assertEquals("Code: 'code' Level: 'WARNING'", printed);
+ }
+
+ private static final class WriterOutputStream extends OutputStream {
+
+ private final Writer writer;
+
+ private WriterOutputStream(Writer writer) {
+ this.writer = writer;
+ }
+
+ @Override
+ public void write(int b) throws IOException {
+ writer.write(b);
+ }
+ }
+}
diff --git a/org.eclipse.virgo.medic.test/src/test/java/org/eclipse/virgo/medic/test/eventlog/MockEventLoggerTests.java b/org.eclipse.virgo.medic.test/src/test/java/org/eclipse/virgo/medic/test/eventlog/MockEventLoggerTests.java
new file mode 100644
index 0000000..933e5c0
--- /dev/null
+++ b/org.eclipse.virgo.medic.test/src/test/java/org/eclipse/virgo/medic/test/eventlog/MockEventLoggerTests.java
@@ -0,0 +1,168 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.test.eventlog;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.List;
+
+import org.eclipse.virgo.medic.eventlog.Level;
+import org.eclipse.virgo.medic.test.eventlog.LoggedEvent;
+import org.eclipse.virgo.medic.test.eventlog.MockEventLogger;
+import org.junit.Test;
+
+
+public class MockEventLoggerTests {
+
+ private final MockEventLogger eventLogger = new MockEventLogger();
+
+ @Test
+ public void emptyList() {
+ List<LoggedEvent> loggedEvents = this.eventLogger.getLoggedEvents();
+ assertNotNull(loggedEvents);
+ assertEquals(0, loggedEvents.size());
+ }
+
+ @Test
+ public void eventWithoutThrowableWithInserts() {
+ this.eventLogger.log("123", Level.INFO, "a", "b", true);
+
+ List<LoggedEvent> loggedEvents = this.eventLogger.getLoggedEvents();
+ assertNotNull(loggedEvents);
+ assertEquals(1, loggedEvents.size());
+
+ LoggedEvent loggedEvent = loggedEvents.get(0);
+ assertEquals("123", loggedEvent.getCode());
+ assertEquals(Level.INFO, loggedEvent.getLevel());
+ assertNull(loggedEvent.getThrowable());
+ assertArrayEquals(new Object[] { "a", "b", true }, loggedEvent.getInserts());
+ }
+
+ @Test
+ public void eventWithoutThrowableWithoutInserts() {
+ this.eventLogger.log("234", Level.ERROR);
+
+ List<LoggedEvent> loggedEvents = this.eventLogger.getLoggedEvents();
+ assertNotNull(loggedEvents);
+ assertEquals(1, loggedEvents.size());
+
+ LoggedEvent loggedEvent = loggedEvents.get(0);
+ assertEquals("234", loggedEvent.getCode());
+ assertEquals(Level.ERROR, loggedEvent.getLevel());
+ assertNull(loggedEvent.getThrowable());
+ assertNotNull(loggedEvent.getInserts());
+ assertEquals(0, loggedEvent.getInserts().length);
+ }
+
+ @Test
+ public void eventWithThrowableWithInserts() {
+ Throwable throwable = new Throwable();
+ this.eventLogger.log("345", Level.WARNING, throwable, "a", "b", true);
+
+ List<LoggedEvent> loggedEvents = this.eventLogger.getLoggedEvents();
+ assertNotNull(loggedEvents);
+ assertEquals(1, loggedEvents.size());
+
+ LoggedEvent loggedEvent = loggedEvents.get(0);
+ assertEquals("345", loggedEvent.getCode());
+ assertEquals(Level.WARNING, loggedEvent.getLevel());
+ assertEquals(throwable, loggedEvent.getThrowable());
+ assertArrayEquals(new Object[] { "a", "b", true }, loggedEvent.getInserts());
+ }
+
+ @Test
+ public void eventWithThrowableWithoutInserts() {
+ Throwable throwable = new Throwable();
+ this.eventLogger.log("456", Level.ERROR, throwable);
+
+ List<LoggedEvent> loggedEvents = this.eventLogger.getLoggedEvents();
+ assertNotNull(loggedEvents);
+ assertEquals(1, loggedEvents.size());
+
+ LoggedEvent loggedEvent = loggedEvents.get(0);
+ assertEquals("456", loggedEvent.getCode());
+ assertEquals(Level.ERROR, loggedEvent.getLevel());
+ assertEquals(throwable, loggedEvent.getThrowable());
+ assertNotNull(loggedEvent.getInserts());
+ assertEquals(0, loggedEvent.getInserts().length);
+ }
+
+ @Test
+ public void multipleEventsIncludingDuplicates() {
+ this.eventLogger.log("123", Level.INFO);
+ this.eventLogger.log("234", Level.INFO);
+ this.eventLogger.log("345", Level.INFO);
+ this.eventLogger.log("345", Level.INFO);
+ this.eventLogger.log("123", Level.INFO);
+
+ List<LoggedEvent> loggedEvents = this.eventLogger.getLoggedEvents();
+ assertNotNull(loggedEvents);
+ assertEquals(5, loggedEvents.size());
+ assertLoggedEventMatch(loggedEvents.get(0), "123", null, null);
+ assertLoggedEventMatch(loggedEvents.get(1), "234", null, null);
+ assertLoggedEventMatch(loggedEvents.get(2), "345", null, null);
+ assertLoggedEventMatch(loggedEvents.get(3), "345", null, null);
+ assertLoggedEventMatch(loggedEvents.get(4), "123", null, null);
+ assertTrue("Correct event code sequence not detected", this.eventLogger.isLogged("123", "234", "345", "345", "123"));
+ assertFalse("Incorrect event code sequence not detected", this.eventLogger.isLogged("123", "234", "345", "123"));
+ assertFalse("Incorrect event code sequence not detected", this.eventLogger.isLogged("123", "234", "345", "123", "123"));
+ }
+
+ @Test
+ public void retrieveEventSequenceWithCodes() {
+ this.eventLogger.log("123", Level.INFO, new Integer(1));
+ this.eventLogger.log("234", Level.INFO, new Integer(2));
+ this.eventLogger.log("345", Level.INFO, new Integer(3));
+ this.eventLogger.log("345", Level.INFO, new Integer(4));
+ this.eventLogger.log("123", Level.INFO, new Integer(5));
+
+ List<LoggedEvent> loggedEvents = this.eventLogger.getEventsWithCodes("345", "123", "345", "xyz");
+ assertNotNull(loggedEvents);
+ assertEquals(2, loggedEvents.size());
+ assertLoggedEventMatch(loggedEvents.get(0), "345", Level.INFO, null, 3);
+ assertLoggedEventMatch(loggedEvents.get(1), "123", Level.INFO, null, 5);
+ }
+
+ @Test
+ public void containsEventCodeSequence() {
+ this.eventLogger.log("123", Level.INFO);
+ this.eventLogger.log("234", Level.INFO);
+ this.eventLogger.log("345", Level.INFO);
+ this.eventLogger.log("345", Level.INFO);
+ this.eventLogger.log("123", Level.INFO);
+
+ assertTrue("Failed to detect codes 234, 123, 345", this.eventLogger.containsLogged("234","123","345"));
+ assertFalse("Erroneously detected all codes 123, xyz, 234", this.eventLogger.containsLogged("123", "xyz", "234"));
+ this.eventLogger.reinitialise();
+ assertFalse("Detected code 123 after reinitialisation", this.eventLogger.containsLogged("123"));
+ assertTrue("eventLogger not empty after reinitialisation", this.eventLogger.getLoggedEvents().isEmpty());
+ }
+
+ private static void assertLoggedEventMatch(LoggedEvent loggedEvent, String code, Level level, Throwable throwable, Object... inserts) {
+ assertNotNull(loggedEvent);
+ assertEquals("LoggedEvent code", code, loggedEvent.getCode());
+ if (level != null) {
+ assertEquals("LoggedEvent level in " + code, level, loggedEvent.getLevel());
+ }
+ assertEquals("LoggedEvent throwable in " + code, throwable, loggedEvent.getThrowable());
+ assertEquals("Number of inserts in " + code, inserts.length, loggedEvent.getInserts().length);
+ int index = 0;
+ for (Object insert : inserts) {
+ assertEquals("LoggedEvent insert in " + code, insert, loggedEvent.getInserts()[index++]);
+ }
+ }
+}
diff --git a/org.eclipse.virgo.medic.test/src/test/resources/.gitignore b/org.eclipse.virgo.medic.test/src/test/resources/.gitignore
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/org.eclipse.virgo.medic.test/src/test/resources/.gitignore
diff --git a/org.eclipse.virgo.medic.test/template.mf b/org.eclipse.virgo.medic.test/template.mf
new file mode 100644
index 0000000..fb6042a
--- /dev/null
+++ b/org.eclipse.virgo.medic.test/template.mf
@@ -0,0 +1,10 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: org.eclipse.virgo.medic.eventlog.test
+Bundle-Name: Medic Event Log Test Bundle
+Bundle-Vendor: SpringSource Inc.
+Bundle-Version: 1.0.0
+Import-Template:
+ org.eclipse.virgo.medic.*;version="0"
+Excluded-Imports:
+ org.junit.*
diff --git a/org.eclipse.virgo.medic.testfragment/.classpath b/org.eclipse.virgo.medic.testfragment/.classpath
new file mode 100644
index 0000000..6635d80
--- /dev/null
+++ b/org.eclipse.virgo.medic.testfragment/.classpath
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src/main/java">
+ <attributes>
+ <attribute name="com.springsource.server.ide.jdt.core.test.classpathentry" value="false"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="src" path="src/main/resources">
+ <attributes>
+ <attribute name="com.springsource.server.ide.jdt.core.test.classpathentry" value="false"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="src" output="target/test-classes" path="src/test/java">
+ <attributes>
+ <attribute name="com.springsource.server.ide.jdt.core.test.classpathentry" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="src" output="target/test-classes" path="src/test/resources">
+ <attributes>
+ <attribute name="com.springsource.server.ide.jdt.core.test.classpathentry" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="var" path="MEDIC_IVY_CACHE/org.eclipse.osgi/org.eclipse.osgi/3.5.1.R35x_v20091005/org.eclipse.osgi-3.5.1.R35x_v20091005.jar" sourcepath="/MEDIC_IVY_CACHE/org.eclipse.osgi/org.eclipse.osgi/3.5.1.R35x_v20091005/org.eclipse.osgi-sources-3.5.1.R35x_v20091005.jar"/>
+ <classpathentry kind="con" path="org.eclipse.ajdt.core.ASPECTJRT_CONTAINER"/>
+ <classpathentry kind="var" path="MEDIC_IVY_CACHE/org.slf4j/com.springsource.slf4j.api/1.5.10/com.springsource.slf4j.api-1.5.10.jar" sourcepath="/MEDIC_IVY_CACHE/org.slf4j/com.springsource.slf4j.api/1.5.10/com.springsource.slf4j.api-sources-1.5.10.jar"/>
+ <classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/org.eclipse.virgo.medic.testfragment/.project b/org.eclipse.virgo.medic.testfragment/.project
new file mode 100644
index 0000000..80226e7
--- /dev/null
+++ b/org.eclipse.virgo.medic.testfragment/.project
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.virgo.medic.testfragment</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.wst.common.project.facet.core.builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.ajdt.core.ajbuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.springsource.server.ide.bundlor.core.builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.springframework.ide.eclipse.core.springbuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.ajdt.ui.ajnature</nature>
+ <nature>com.springsource.server.ide.facet.core.bundlenature</nature>
+ <nature>org.springframework.ide.eclipse.core.springnature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.wst.common.project.facet.core.nature</nature>
+ </natures>
+</projectDescription>
diff --git a/org.eclipse.virgo.medic.testfragment/.settings/com.springsource.server.ide.bundlor.core.prefs b/org.eclipse.virgo.medic.testfragment/.settings/com.springsource.server.ide.bundlor.core.prefs
new file mode 100644
index 0000000..16863b5
--- /dev/null
+++ b/org.eclipse.virgo.medic.testfragment/.settings/com.springsource.server.ide.bundlor.core.prefs
@@ -0,0 +1,5 @@
+#Thu Nov 12 08:44:57 GMT 2009
+com.springsource.server.ide.bundlor.core.bundlor.generated.manifest.autoformatting=true
+com.springsource.server.ide.bundlor.core.byte.code.scanning=true
+com.springsource.server.ide.bundlor.core.template.properties.files=../build.versions
+eclipse.preferences.version=1
diff --git a/org.eclipse.virgo.medic.testfragment/.settings/org.eclipse.wst.common.project.facet.core.xml b/org.eclipse.virgo.medic.testfragment/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 0000000..801f856
--- /dev/null
+++ b/org.eclipse.virgo.medic.testfragment/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<faceted-project>
+ <installed facet="com.springsource.server.bundle" version="1.0"/>
+</faceted-project>
diff --git a/org.eclipse.virgo.medic.testfragment/.springBeans b/org.eclipse.virgo.medic.testfragment/.springBeans
new file mode 100644
index 0000000..5152991
--- /dev/null
+++ b/org.eclipse.virgo.medic.testfragment/.springBeans
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beansProjectDescription>
+ <version>1</version>
+ <pluginVersion><![CDATA[2.2.5.M1]]></pluginVersion>
+ <configSuffixes>
+ <configSuffix><![CDATA[xml]]></configSuffix>
+ </configSuffixes>
+ <enableImports><![CDATA[false]]></enableImports>
+ <configs>
+ </configs>
+ <configSets>
+ </configSets>
+</beansProjectDescription>
diff --git a/org.eclipse.virgo.medic.testfragment/build.xml b/org.eclipse.virgo.medic.testfragment/build.xml
new file mode 100644
index 0000000..daa4411
--- /dev/null
+++ b/org.eclipse.virgo.medic.testfragment/build.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="org.eclipse.virgo.medic.testfragment">
+
+ <property name="clover.coverage" value="0%"/>
+
+ <property file="${basedir}/../build.properties"/>
+ <property file="${basedir}/../build.versions"/>
+ <import file="${basedir}/../virgo-build/aspect/default.xml"/>
+
+</project>
diff --git a/org.eclipse.virgo.medic.testfragment/ivy.xml b/org.eclipse.virgo.medic.testfragment/ivy.xml
new file mode 100644
index 0000000..482ad18
--- /dev/null
+++ b/org.eclipse.virgo.medic.testfragment/ivy.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?xml-stylesheet type="text/xsl" href="http://ivyrep.jayasoft.org/ivy-doc.xsl"?>
+<ivy-module
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="http://incubator.apache.org/ivy/schemas/ivy.xsd"
+ version="1.3">
+
+ <info organisation="org.eclipse.virgo.medic" module="${ant.project.name}"/>
+
+ <configurations>
+ <include file="${virgo.build.dir}/common/default-ivy-configurations.xml"/>
+ </configurations>
+
+ <publications>
+ <artifact name="${ant.project.name}"/>
+ <artifact name="${ant.project.name}-sources" type="src" ext="jar"/>
+ </publications>
+
+ <dependencies>
+ <dependency org="org.eclipse.osgi" name="org.eclipse.osgi" rev="${org.eclipse.osgi}" conf="provided->runtime"/>
+ <dependency org="org.slf4j" name="com.springsource.slf4j.api" rev="${org.slf4j}" conf="aspects->runtime"/>
+ <dependency org="org.aspectj" name="com.springsource.org.aspectj.runtime" rev="${org.aspectj}" conf="aspects->runtime"/>
+ </dependencies>
+
+</ivy-module>
diff --git a/org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/dump/Dump.java b/org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/dump/Dump.java
new file mode 100644
index 0000000..2dd3a81
--- /dev/null
+++ b/org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/dump/Dump.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.dump;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.Writer;
+import java.util.Map;
+
+/**
+ * A <code>Dump</code> represents a dump being generated by a {@link DumpGenerator}. During dump generation
+ * {@link DumpContributor DumpContributors} are called to contribute to the dump. Contributors can request a
+ * {@link Writer}, {@link File}, etc. which they may use to write out their contribution to the dump.
+ */
+public interface Dump {
+
+ /**
+ * Returns a timestamp that identifies that time at which this dump was generated.
+ *
+ * @return The timestamp of the dump's generation
+ */
+ long getTimestamp();
+
+ /**
+ * Returns the context that is associated with this dump. If there is no associated context an empty
+ * <code>Map</code> is returned.
+ *
+ * @return The dump's context
+ */
+ Map<String, Object> getContext();
+
+ /**
+ * Returns the {@link Throwable Throwables} associated with this dump.
+ *
+ * @return The dump's <code>Throwable</code>s
+ */
+ Throwable[] getThrowables();
+
+ /**
+ * Returns the cause of this dump.
+ *
+ * @return The dump's cause.
+ */
+ String getCause();
+
+ /**
+ * Creates a {@link FileWriter} that writes to a file with the supplied name, within this dump's output location.
+ * @param name
+ *
+ * @return a <code>FileWriter</code> to which a contribution to the dump can be written
+ * @throws DumpContributionFailedException
+ */
+ FileWriter createFileWriter(String name) throws DumpContributionFailedException;
+
+ /**
+ * Creates a {@link FileOutputStream} that writes to a file with the supplied name, within this dump's output
+ * location.
+ * @param name
+ *
+ * @return a <code>FileOutputStream</code> to which a contribution to the dump can be written
+ * @throws DumpContributionFailedException
+ */
+ FileOutputStream createFileOutputStream(String name) throws DumpContributionFailedException;
+
+ /**
+ * Creates a {@link File} with the supplied name, within this dump's output location.
+ * @param name
+ *
+ * @return a <code>File</code> to which a contribution to the dump can be written
+ */
+ File createFile(String name);
+
+}
diff --git a/org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/dump/DumpContributionFailedException.java b/org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/dump/DumpContributionFailedException.java
new file mode 100644
index 0000000..edaf464
--- /dev/null
+++ b/org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/dump/DumpContributionFailedException.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.dump;
+
+/**
+ * A <code>DumpContributionFailedException</code> is thrown by a {@link DumpContributor} to indicate that a failure has
+ * occurred when it was attempting to make a contribution to a dump.
+ * <p />
+ *
+ * <strong>Concurrent Semantics</strong><br />
+ * Thread-safe.
+ *
+ */
+public class DumpContributionFailedException extends DumpGenerationFailedException {
+
+ private static final long serialVersionUID = -3196511149954617337L;
+
+ /**
+ * Create a new DumpContributionFailedException with the supplied message that describes the failure
+ *
+ * @param message The message describing the failure
+ */
+ public DumpContributionFailedException(String message) {
+ super(message);
+ }
+
+ /**
+ * Create a new DumpContributionFailedException with the supplied failure cause and message that describes the
+ * failure
+ *
+ * @param message The message describing the failure
+ * @param cause The cause of the contribution failure
+ */
+ public DumpContributionFailedException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/dump/DumpContributor.java b/org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/dump/DumpContributor.java
new file mode 100644
index 0000000..ddffe7c
--- /dev/null
+++ b/org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/dump/DumpContributor.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.dump;
+
+/**
+ * A <code>DumpContributor</code> is implemented to contribute information to a dump. Contributors are 'registered' with
+ * a {@link DumpGenerator} by publishing them in the service registry.
+ * <p />
+ *
+ * <strong>Concurrent Semantics</strong><br />
+ * <code>DumpContributor</code>s must be thread-safe.
+ */
+public interface DumpContributor {
+
+ /**
+ * Contribute to the supplied {@link Dump}.
+ *
+ * @param dump The dump to which a contribution may be made.
+ * @throws DumpContributionFailedException if the dump contribution cannot be created
+ */
+ void contribute(Dump dump) throws DumpContributionFailedException;
+
+ /**
+ * Returns the name of this <code>DumpContributor</code>. The name is used by a {@link DumpGenerator} when
+ * determining which contributors should be excluded from contributing to a dump.
+ *
+ * @return The contributor's name
+ */
+ String getName();
+}
diff --git a/org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/dump/DumpGenerationFailedException.java b/org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/dump/DumpGenerationFailedException.java
new file mode 100644
index 0000000..5dded04
--- /dev/null
+++ b/org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/dump/DumpGenerationFailedException.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.dump;
+
+/**
+ * A <code>DumpGenerationFailedException</code> is thrown by a {@link DumpGenerator} to indicate that a failure has
+ * occurred during dump generation.
+ *
+ * <p />
+ *
+ * <strong>Concurrent Semantics</strong><br />
+ * Thread-safe.
+ *
+ */
+public class DumpGenerationFailedException extends Exception {
+
+ private static final long serialVersionUID = -3196511149954617337L;
+
+ /**
+ * Create a new DumpGenerationFailedException with the supplied message that describes the failure
+ *
+ * @param message The message describing the failure
+ */
+ public DumpGenerationFailedException(String message) {
+ super(message);
+ }
+
+ /**
+ * Create a new DumpGenerationFailedException with the supplied failure cause and message that describes the failure
+ *
+ * @param message The message describing the failure
+ * @param cause The cause of the generation failure
+ */
+ public DumpGenerationFailedException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/dump/DumpGenerator.java b/org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/dump/DumpGenerator.java
new file mode 100644
index 0000000..2a2d530
--- /dev/null
+++ b/org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/dump/DumpGenerator.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.dump;
+
+import java.util.Map;
+
+/**
+ * A <code>DumpGenerator</code> can be used to programatically request the generation of a dump. A
+ * <code>DumpGenerator</code> instance can be obtained from the service registry.
+ * <p />
+ *
+ * When a dump is requested, the <code>DumpGenerator</code> will, by default, provide all {@link DumpContributor
+ * DumpContributors} that are known to it with an opportunity to contribute to the dump. <code>DumpContributor</code>
+ * instances are made known to a <code>DumpGeneraator</code> by publishing them in the service registry.
+ * <p />
+ *
+ * A <code>DumpGenerator</code> can be configured to exclude <code>DumpContributor</code>s from contributing to dumps
+ * with a particular cause. TODO Expand the documentation on contributor exclusion
+ * <p />
+ *
+ * <strong>Concurrent Semantics</strong><br />
+ * <code>DumpGenerator</code>s must be thread-safe.
+ */
+public interface DumpGenerator {
+
+ /**
+ * Generates a dump
+ *
+ * @param cause the cause of the dump
+ * @param throwables {@link Throwable} instances to be associated with the dump
+ */
+ void generateDump(String cause, Throwable... throwables);
+
+ /**
+ * Generates a dump, with additional context.
+ *
+ * @param cause the cause of the dump
+ * @param context additional context that can be used by the <code>DumpProvider</code>s
+ * @param throwables {@link Throwable} instances to be associated with the dump
+ */
+ void generateDump(String cause, Map<String, Object> context, Throwable... throwables);
+}
diff --git a/org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/dump/JmxDumpContributionParticipant.java b/org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/dump/JmxDumpContributionParticipant.java
new file mode 100644
index 0000000..28a897d
--- /dev/null
+++ b/org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/dump/JmxDumpContributionParticipant.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.dump;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import javax.management.DescriptorKey;
+
+/**
+ * Indicates that this MBean should be treated as a JmxDumpContributionParticipant
+ * <p />
+ *
+ */
+@Documented
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface JmxDumpContributionParticipant {
+
+ @DescriptorKey("jmxDumpContributionParticipant")
+ boolean value() default true;
+}
diff --git a/org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/eventlog/EventLogger.java b/org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/eventlog/EventLogger.java
new file mode 100644
index 0000000..8e09071
--- /dev/null
+++ b/org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/eventlog/EventLogger.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.eventlog;
+
+import java.util.ResourceBundle;
+
+/**
+ * An <code>EventLogger</code> provides support for logging events as human-readable, potentially internationalized,
+ * messages identified by a unique code.
+ * <p />
+ * An <code>EventLogger</code> instance can be obtained directly from the service registry. Such instances will search
+ * the <code>Bundle</code> that obtained the instance, and the <code>EventLogger</code> implementations <code>Bundle</code>
+ * for a properties file that contains entry for the an event's code. The implementation bundle is searched to support
+ * providing properties files in fragment bundles which are attached to the implementation.
+ * <p />
+ * Alternatively, an <code>EventLogger</code> can be obtained from an {@link EventLoggerFactory} allowing a specific
+ * <code>Bundle</code> to be supplied that will be used to search for properties files.
+ * <p />
+ * The algorithm used to find properties files matches that described in
+ * {@link ResourceBundle#getBundle(String, java.util.Locale, ClassLoader) ResourceBundle}, with the exception that no
+ * searching for class files is performed.
+ * <p />
+ * <strong>Concurrent Semantics</strong><br />
+ * Implementations <strong>must</strong> be thread-safe.
+ */
+public interface EventLogger {
+
+ /**
+ * Logs an event in the form of a message identified by the supplied code. The message is resolved by searching the
+ * available {@link ResourceBundle ResourceBundles} for an entry with the key that matches the code.
+ *
+ * The event is logged at the supplied level, with the supplied inserts being applied to the message.
+ *
+ * @param code The code of the message to be logged
+ * @param level The level at which the event should be logged
+ * @param inserts The inserts for the message
+ */
+ void log(String code, Level level, Object... inserts);
+
+ /**
+ * Logs an event in the form of a message identified by the supplied code. The message is resolved by searching the
+ * available {@link ResourceBundle ResourceBundles} for an entry with the key that matches the code.
+ *
+ * The event is logged at the supplied level, with the supplied inserts being applied to the message.
+ *
+ * @param logEvent The log event to be logged
+ * @param inserts The inserts for the message
+ */
+ void log(LogEvent logEvent, Object... inserts);
+
+ /**
+ * Logs an event in the form of a message identified by the supplied code. The message is resolved by searching the
+ * available {@link ResourceBundle ResourceBundles} for an entry with the key that matches the code.
+ *
+ * The event is logged at the supplied level, with the supplied inserts being applied to the message. The supplied
+ * <code>Throwable</code> is logged with the message.
+ *
+ * @param code The code of the message to be logged
+ * @param level The level at which the event should be logged
+ * @param throwable The <code>Throwable</code> to be logged
+ * @param inserts The inserts for the message
+ */
+ void log(String code, Level level, Throwable throwable, Object... inserts);
+
+ /**
+ * Logs an event in the form of a message identified by the supplied code. The message is resolved by searching the
+ * available {@link ResourceBundle ResourceBundles} for an entry with the key that matches the code.
+ *
+ * The event is logged at the supplied level, with the supplied inserts being applied to the message. The supplied
+ * <code>Throwable</code> is logged with the message.
+ *
+ * @param logEvent The log event to be logged
+ * @param throwable The <code>Throwable</code> to be logged
+ * @param inserts The inserts for the message
+ */
+ void log(LogEvent logEvent, Throwable throwable, Object... inserts);
+}
diff --git a/org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/eventlog/EventLoggerFactory.java b/org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/eventlog/EventLoggerFactory.java
new file mode 100644
index 0000000..da99120
--- /dev/null
+++ b/org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/eventlog/EventLoggerFactory.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.eventlog;
+
+import java.util.ResourceBundle;
+
+import org.osgi.framework.Bundle;
+
+/**
+ * An <code>EventLoggerFactory</code> is used to create an <code>EventLogger</code> instance that will search a specific
+ * bundle, in addition to the EventLogger implementation's bundle, for {@link ResourceBundle ResourceBundles}.
+ * <p />
+ * <strong>Concurrent Semantics</strong><br />
+ * Implementations <strong>must</strong> be thread-safe.
+ */
+public interface EventLoggerFactory {
+
+ /**
+ * Creates a new <code>EventLogger</code> that will search the supplied bundle, in addition to the
+ * <code>EventLogger</code> implementation's bundle, for {@link ResourceBundle ResourceBundles}.
+ *
+ * @param bundle The <code>Bundle</code> to search for <code>ResourceBundle</code>s.
+ *
+ * @return The <code>EventLogger</code>
+ */
+ public EventLogger createEventLogger(Bundle bundle);
+}
diff --git a/org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/eventlog/Level.java b/org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/eventlog/Level.java
new file mode 100644
index 0000000..b8d9eae
--- /dev/null
+++ b/org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/eventlog/Level.java
@@ -0,0 +1,16 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.eventlog;
+
+public enum Level {
+ ERROR, WARNING, INFO
+}
diff --git a/org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/eventlog/LogEvent.java b/org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/eventlog/LogEvent.java
new file mode 100644
index 0000000..3387160
--- /dev/null
+++ b/org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/eventlog/LogEvent.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.eventlog;
+
+/**
+ * A <code>LogEvent</code> encapsulates the details of an event that is to be logged.
+ * <p/>
+ *
+ * <strong>Concurrent Semantics</strong><br />
+ * Implementations <strong>must</strong> be thread-safe.
+ *
+ */
+public interface LogEvent {
+
+ /**
+ * Returns the code that uniquely identifies this <code>LogEvent</code>. Typically, this code is used to locate the
+ * message for the event in a resource bundle.
+ *
+ * @return The event's code
+ */
+ public String getEventCode();
+
+ /**
+ * Returns the {@link Level} at which this <code>LogEvent</code> should be published.
+ *
+ * @return The level of the event.
+ */
+ public Level getLevel();
+}
diff --git a/org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/log/ConfigurationPublicationFailedException.java b/org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/log/ConfigurationPublicationFailedException.java
new file mode 100644
index 0000000..e2bbf0e
--- /dev/null
+++ b/org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/log/ConfigurationPublicationFailedException.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.log;
+
+/**
+ * Thrown by {@link LoggingConfigurationPublisher} when a request to publish logging configuration fails.
+ */
+public class ConfigurationPublicationFailedException extends Exception {
+
+ private static final long serialVersionUID = 4317804271280636565L;
+
+ /**
+ * Creates a new exception with the supplied message and cause.
+ *
+ * @param message The exception's message
+ * @param cause The exception's cause
+ */
+ public ConfigurationPublicationFailedException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/log/DelegatingPrintStream.java b/org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/log/DelegatingPrintStream.java
new file mode 100644
index 0000000..131f597
--- /dev/null
+++ b/org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/log/DelegatingPrintStream.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.log;
+
+import java.io.PrintStream;
+
+/**
+ * A <code>DelegatingPrintStream</code> is a {@link PrintStream} implementation that delegates to another
+ * {@link PrintStream} instance and allows the delegate to be changed at runtime.
+ * <p />
+ *
+ * <strong>Concurrent Semantics</strong><br />
+ * Thread-safe.
+ *
+ */
+public interface DelegatingPrintStream {
+
+ /**
+ * Sets the {@link PrintStream} to be used as a delegate. The given <code>printStream</code> may be
+ * <code>null</code> to disable delegation.
+ *
+ * @param printStream The delegate, or <code>null</code> to disable delegation.
+ */
+ void setDelegate(PrintStream printStream);
+}
diff --git a/org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/log/EntryExitTrace.aj b/org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/log/EntryExitTrace.aj
new file mode 100644
index 0000000..ed2b3aa
--- /dev/null
+++ b/org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/log/EntryExitTrace.aj
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.log;
+
+import org.aspectj.lang.JoinPoint;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * An aspect that will advise any method with entry and exit trace logging.
+ *
+ * <strong>Concurrent Semantics</strong><br />
+ *
+ * Threadsafe
+ *
+ */
+public aspect EntryExitTrace pertypewithin(*) {
+
+ private volatile Logger logger;
+
+ pointcut medic() : within(org.eclipse.virgo.medic..*);
+
+ pointcut logback() : within(ch.qos.logback..*) || within(org.slf4j.impl..*);
+
+ pointcut infoCandidate() : execution(public * *(..)) && !medic() && !logback();
+
+ pointcut debugCandidate() : execution(!public !private * *(..)) && !medic() && !logback();
+
+ pointcut traceCandidate() : execution(private * *(..)) && !medic() && !logback();
+
+ before() : infoCandidate() {
+ getLogger(thisJoinPointStaticPart).info("{} {}", ">", getSignature(thisJoinPointStaticPart));
+ }
+
+ after() returning : infoCandidate() {
+ getLogger(thisJoinPointStaticPart).info("{} {}", "<", getSignature(thisJoinPointStaticPart));
+ }
+
+ after() throwing(Throwable t) : infoCandidate() {
+ Logger logger = getLogger(thisJoinPointStaticPart);
+ if (logger.isInfoEnabled()) {
+ logger.info(String.format("< %s", getSignature(thisJoinPointStaticPart)), t);
+ }
+ }
+
+ before() : debugCandidate() {
+ getLogger(thisJoinPointStaticPart).debug("{} {}", ">", getSignature(thisJoinPointStaticPart));
+ }
+
+ after() returning : debugCandidate() {
+ getLogger(thisJoinPointStaticPart).debug("{} {}", "<", getSignature(thisJoinPointStaticPart));
+ }
+
+ after() throwing(Throwable t) : debugCandidate() {
+ Logger logger = getLogger(thisJoinPointStaticPart);
+ if (logger.isDebugEnabled()) {
+ logger.debug(String.format("< %s", getSignature(thisJoinPointStaticPart)), t);
+ }
+ }
+
+ before() : traceCandidate() {
+ getLogger(thisJoinPointStaticPart).trace("{} {}", ">", getSignature(thisJoinPointStaticPart));
+ }
+
+ after() returning : traceCandidate() {
+ getLogger(thisJoinPointStaticPart).trace("{} {}", "<", getSignature(thisJoinPointStaticPart));
+ }
+
+ after() throwing(Throwable t) : traceCandidate() {
+ Logger logger = getLogger(thisJoinPointStaticPart);
+ if (logger.isTraceEnabled()) {
+ logger.trace(String.format("< %s", getSignature(thisJoinPointStaticPart)), t);
+ }
+ }
+
+ private Logger getLogger(JoinPoint.StaticPart sp) {
+ if (this.logger == null) {
+ this.logger = LoggerFactory.getLogger(sp.getSignature().getDeclaringType());
+ }
+ return this.logger;
+ }
+
+ private String getSignature(JoinPoint.StaticPart sp) {
+ return sp.getSignature().toLongString();
+ }
+}
diff --git a/org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/log/LoggingConfiguration.java b/org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/log/LoggingConfiguration.java
new file mode 100644
index 0000000..4156c90
--- /dev/null
+++ b/org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/log/LoggingConfiguration.java
@@ -0,0 +1,19 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.log;
+
+public interface LoggingConfiguration {
+
+ String getConfiguration();
+
+ String getName();
+}
diff --git a/org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/log/LoggingConfigurationPublisher.java b/org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/log/LoggingConfigurationPublisher.java
new file mode 100644
index 0000000..e0d3c90
--- /dev/null
+++ b/org.eclipse.virgo.medic.testfragment/src/main/java/org/eclipse/virgo/medic/log/LoggingConfigurationPublisher.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.log;
+
+import java.io.File;
+
+/**
+ * A <code>LoggingConfigurationPublisher</code> is used to publish {@link LoggingConfiguration} into the service
+ * registry. <code>LoggingConfiguration</code> instances in the service registry are referenced by bundles using the
+ * <code>Medic-LoggingConfiguration</code> manifest header.
+ */
+public interface LoggingConfigurationPublisher {
+
+ /**
+ * Publishes the configuration in the supplied <code>File</code> as a <code>LoggingConfiguration</code> instance,
+ * identified with the supplied id. The published configuration can then be referenced by a bundle using the
+ * <code>Medic-LoggingConfiguration</code> manifest header with a value equal to the supplied id.
+ *
+ * @param configuration The configuration to be published
+ * @param id The identifier to be applied to the configuration when its published
+ *
+ * @throws ConfigurationPublicationFailedException if the publication of the configuration fails
+ */
+ void publishConfiguration(File configuration, String id) throws ConfigurationPublicationFailedException;
+}
diff --git a/org.eclipse.virgo.medic.testfragment/src/main/resources/.gitignore b/org.eclipse.virgo.medic.testfragment/src/main/resources/.gitignore
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/org.eclipse.virgo.medic.testfragment/src/main/resources/.gitignore
diff --git a/org.eclipse.virgo.medic.testfragment/src/test/java/.gitignore b/org.eclipse.virgo.medic.testfragment/src/test/java/.gitignore
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/org.eclipse.virgo.medic.testfragment/src/test/java/.gitignore
diff --git a/org.eclipse.virgo.medic.testfragment/src/test/resources/.gitignore b/org.eclipse.virgo.medic.testfragment/src/test/resources/.gitignore
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/org.eclipse.virgo.medic.testfragment/src/test/resources/.gitignore
diff --git a/org.eclipse.virgo.medic.testfragment/template.mf b/org.eclipse.virgo.medic.testfragment/template.mf
new file mode 100644
index 0000000..36875d2
--- /dev/null
+++ b/org.eclipse.virgo.medic.testfragment/template.mf
@@ -0,0 +1,13 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: org.eclipse.virgo.medic.testfragment
+Bundle-Vendor: SpringSource Inc.
+Import-Template:
+ org.aspectj.lang.*;version="${org.aspectj:[=.=.= , +1.0.0)}",
+ javax.management.*;version="0",
+ org.osgi.framework;version="0",
+ org.slf4j.*;version="${org.slf4j:[=.=.=, =.+1.0)}"
+Bundle-Version: 1.0.0
+Bundle-Name: Medic API
+Excluded-Imports:
+ ch.qos.logback.classic.*
diff --git a/org.eclipse.virgo.medic.weaving/.classpath b/org.eclipse.virgo.medic.weaving/.classpath
new file mode 100644
index 0000000..e1203ef
--- /dev/null
+++ b/org.eclipse.virgo.medic.weaving/.classpath
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src/main/java">
+ <attributes>
+ <attribute name="com.springsource.server.ide.jdt.core.test.classpathentry" value="false"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="src" path="src/main/resources">
+ <attributes>
+ <attribute name="com.springsource.server.ide.jdt.core.test.classpathentry" value="false"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="src" output="target/test-classes" path="src/test/java">
+ <attributes>
+ <attribute name="com.springsource.server.ide.jdt.core.test.classpathentry" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="src" output="target/test-classes" path="src/test/resources">
+ <attributes>
+ <attribute name="com.springsource.server.ide.jdt.core.test.classpathentry" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="var" path="MEDIC_IVY_CACHE/ch.qos.logback/com.springsource.ch.qos.logback.core/0.9.18/com.springsource.ch.qos.logback.core-0.9.18.jar" sourcepath="/MEDIC_IVY_CACHE/ch.qos.logback/com.springsource.ch.qos.logback.core/0.9.18/com.springsource.ch.qos.logback.core-sources-0.9.18.jar"/>
+ <classpathentry kind="con" path="org.eclipse.ajdt.core.ASPECTJRT_CONTAINER"/>
+ <classpathentry kind="var" path="MEDIC_IVY_CACHE/org.slf4j/com.springsource.slf4j.api/1.5.10/com.springsource.slf4j.api-1.5.10.jar" sourcepath="/MEDIC_IVY_CACHE/org.slf4j/com.springsource.slf4j.api/1.5.10/com.springsource.slf4j.api-sources-1.5.10.jar"/>
+ <classpathentry kind="var" path="MEDIC_IVY_CACHE/ch.qos.logback/com.springsource.ch.qos.logback.classic/0.9.18/com.springsource.ch.qos.logback.classic-0.9.18.jar" sourcepath="/MEDIC_IVY_CACHE/ch.qos.logback/com.springsource.ch.qos.logback.classic/0.9.18/com.springsource.ch.qos.logback.classic-sources-0.9.18.jar"/>
+ <classpathentry kind="var" path="MEDIC_IVY_CACHE/org.eclipse.osgi/org.eclipse.osgi/3.5.1.R35x_v20091005/org.eclipse.osgi-3.5.1.R35x_v20091005.jar"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/org.eclipse.virgo.medic"/>
+ <classpathentry kind="var" path="MEDIC_IVY_CACHE/org.junit/com.springsource.org.junit/4.7.0/com.springsource.org.junit-4.7.0.jar" sourcepath="/MEDIC_IVY_CACHE/org.junit/com.springsource.org.junit/4.7.0/com.springsource.org.junit-sources-4.7.0.jar"/>
+ <classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/org.eclipse.virgo.medic.weaving/.project b/org.eclipse.virgo.medic.weaving/.project
new file mode 100644
index 0000000..980b181
--- /dev/null
+++ b/org.eclipse.virgo.medic.weaving/.project
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.virgo.medic.weaving</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.wst.common.project.facet.core.builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.ajdt.core.ajbuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.springframework.ide.eclipse.core.springbuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.springsource.server.ide.bundlor.core.builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.ajdt.ui.ajnature</nature>
+ <nature>com.springsource.server.ide.facet.core.bundlenature</nature>
+ <nature>org.springframework.ide.eclipse.core.springnature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.wst.common.project.facet.core.nature</nature>
+ </natures>
+</projectDescription>
diff --git a/org.eclipse.virgo.medic.weaving/.settings/com.springsource.server.ide.bundlor.core.prefs b/org.eclipse.virgo.medic.weaving/.settings/com.springsource.server.ide.bundlor.core.prefs
new file mode 100644
index 0000000..008eb6b
--- /dev/null
+++ b/org.eclipse.virgo.medic.weaving/.settings/com.springsource.server.ide.bundlor.core.prefs
@@ -0,0 +1,5 @@
+#Thu Nov 12 08:45:04 GMT 2009
+com.springsource.server.ide.bundlor.core.bundlor.generated.manifest.autoformatting=true
+com.springsource.server.ide.bundlor.core.byte.code.scanning=true
+com.springsource.server.ide.bundlor.core.template.properties.files=../build.versions
+eclipse.preferences.version=1
diff --git a/org.eclipse.virgo.medic.weaving/.settings/org.springframework.ide.eclipse.core.prefs b/org.eclipse.virgo.medic.weaving/.settings/org.springframework.ide.eclipse.core.prefs
new file mode 100644
index 0000000..00626fc
--- /dev/null
+++ b/org.eclipse.virgo.medic.weaving/.settings/org.springframework.ide.eclipse.core.prefs
@@ -0,0 +1,67 @@
+#Wed Aug 19 13:16:35 BST 2009
+eclipse.preferences.version=1
+org.springframework.ide.eclipse.core.builders.enable.aopreferencemodelbuilder=true
+org.springframework.ide.eclipse.core.builders.enable.beanmetadatabuilder=true
+org.springframework.ide.eclipse.core.builders.enable.osgibundleupdater=false
+org.springframework.ide.eclipse.core.enable.project.preferences=false
+org.springframework.ide.eclipse.core.validator.enable.com.springsource.server.ide.manifest.core.manifestvalidator=true
+org.springframework.ide.eclipse.core.validator.enable.com.springsource.sts.bestpractices.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.enable.com.springsource.sts.server.quickfix.manifestvalidator=false
+org.springframework.ide.eclipse.core.validator.enable.org.springframework.ide.eclipse.beans.core.beansvalidator=true
+org.springframework.ide.eclipse.core.validator.enable.org.springframework.ide.eclipse.core.springvalidator=false
+org.springframework.ide.eclipse.core.validator.enable.org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.server.ide.manifest.core.applicationSymbolicNameRule-com.springsource.server.ide.manifest.core.manifestvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.server.ide.manifest.core.applicationVersionRule-com.springsource.server.ide.manifest.core.manifestvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.server.ide.manifest.core.bundleActivationPolicyRule-com.springsource.server.ide.manifest.core.manifestvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.server.ide.manifest.core.bundleActivatorRule-com.springsource.server.ide.manifest.core.manifestvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.server.ide.manifest.core.bundleManifestVersionRule-com.springsource.server.ide.manifest.core.manifestvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.server.ide.manifest.core.bundleNameRule-com.springsource.server.ide.manifest.core.manifestvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.server.ide.manifest.core.bundleSymbolicNameRule-com.springsource.server.ide.manifest.core.manifestvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.server.ide.manifest.core.bundleVersionRule-com.springsource.server.ide.manifest.core.manifestvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.server.ide.manifest.core.exportPackageRule-com.springsource.server.ide.manifest.core.manifestvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.server.ide.manifest.core.importRule-com.springsource.server.ide.manifest.core.manifestvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.server.ide.manifest.core.parsingProblemsRule-com.springsource.server.ide.manifest.core.manifestvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.server.ide.manifest.core.requireBundleRule-com.springsource.server.ide.manifest.core.manifestvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.bestpractices.com.springsource.sts.bestpractices.AvoidDriverManagerDataSource-com.springsource.sts.bestpractices.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.bestpractices.com.springsource.sts.bestpractices.ImportElementsAtTopRulee-com.springsource.sts.bestpractices.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.bestpractices.com.springsource.sts.bestpractices.ParentBeanSpecifiesAbstractClassRule-com.springsource.sts.bestpractices.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.bestpractices.com.springsource.sts.bestpractices.RefElementRule-com.springsource.sts.bestpractices.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.bestpractices.com.springsource.sts.bestpractices.TooManyBeansInFileRule-com.springsource.sts.bestpractices.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.bestpractices.com.springsource.sts.bestpractices.UnnecessaryValueElementRule-com.springsource.sts.bestpractices.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.bestpractices.com.springsource.sts.bestpractices.UseBeanInheritance-com.springsource.sts.bestpractices.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.bestpractices.legacyxmlusage.jndiobjectfactory-com.springsource.sts.bestpractices.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.server.quickfix.importBundleVersionRule-com.springsource.sts.server.quickfix.manifestvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.server.quickfix.importLibraryVersionRule-com.springsource.sts.server.quickfix.manifestvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.server.quickfix.importPackageVersionRule-com.springsource.sts.server.quickfix.manifestvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.server.quickfix.requireBundleVersionRule-com.springsource.sts.server.quickfix.manifestvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanAlias-org.springframework.ide.eclipse.beans.core.beansvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanClass-org.springframework.ide.eclipse.beans.core.beansvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanConstructorArgument-org.springframework.ide.eclipse.beans.core.beansvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanDefinition-org.springframework.ide.eclipse.beans.core.beansvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanDefinitionHolder-org.springframework.ide.eclipse.beans.core.beansvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanFactory-org.springframework.ide.eclipse.beans.core.beansvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanInitDestroyMethod-org.springframework.ide.eclipse.beans.core.beansvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanProperty-org.springframework.ide.eclipse.beans.core.beansvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanReference-org.springframework.ide.eclipse.beans.core.beansvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.methodOverride-org.springframework.ide.eclipse.beans.core.beansvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.parsingProblems-org.springframework.ide.eclipse.beans.core.beansvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.requiredProperty-org.springframework.ide.eclipse.beans.core.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.core.springClasspath-org.springframework.ide.eclipse.core.springvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.action-org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.actionstate-org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.attribute-org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.attributemapper-org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.beanaction-org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.evaluationaction-org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.evaluationresult-org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.exceptionhandler-org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.import-org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.inputattribute-org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.mapping-org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.outputattribute-org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.set-org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.state-org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.subflowstate-org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.transition-org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.variable-org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.webflowstate-org.springframework.ide.eclipse.webflow.core.validator=true
diff --git a/org.eclipse.virgo.medic.weaving/.springBeans b/org.eclipse.virgo.medic.weaving/.springBeans
new file mode 100644
index 0000000..8ce1035
--- /dev/null
+++ b/org.eclipse.virgo.medic.weaving/.springBeans
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beansProjectDescription>
+ <version>1</version>
+ <pluginVersion><![CDATA[2.2.5.200906231226-RC1]]></pluginVersion>
+ <configSuffixes>
+ <configSuffix><![CDATA[xml]]></configSuffix>
+ </configSuffixes>
+ <enableImports><![CDATA[false]]></enableImports>
+ <configs>
+ </configs>
+ <configSets>
+ </configSets>
+</beansProjectDescription>
diff --git a/org.eclipse.virgo.medic.weaving/build.xml b/org.eclipse.virgo.medic.weaving/build.xml
new file mode 100644
index 0000000..3756372
--- /dev/null
+++ b/org.eclipse.virgo.medic.weaving/build.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="org.eclipse.virgo.medic.weaving">
+
+ <property name="clover.coverage" value="0%"/>
+ <property name="disable.bundlor" value="true"/>
+
+ <property file="${basedir}/../build.properties" />
+ <property file="${basedir}/../build.versions" />
+
+ <import file="${basedir}/../virgo-build/aspect/default.xml" />
+
+</project>
diff --git a/org.eclipse.virgo.medic.weaving/ivy.xml b/org.eclipse.virgo.medic.weaving/ivy.xml
new file mode 100644
index 0000000..fbddf56
--- /dev/null
+++ b/org.eclipse.virgo.medic.weaving/ivy.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?xml-stylesheet type="text/xsl" href="http://ivyrep.jayasoft.org/ivy-doc.xsl"?>
+<ivy-module
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="http://incubator.apache.org/ivy/schemas/ivy.xsd"
+ version="1.3">
+
+ <info organisation="org.eclipse.virgo.medic" module="${ant.project.name}" />
+
+ <configurations>
+ <include file="${virgo.build.dir}/common/default-ivy-configurations.xml"/>
+ <conf name="bundleclasspath" description="Dependencies to be packaged within the bundle"/>
+ </configurations>
+
+ <publications>
+ <artifact name="${ant.project.name}"/>
+ <artifact name="${ant.project.name}-sources" type="src" ext="jar"/>
+ </publications>
+
+ <dependencies>
+ <dependency org="ch.qos.logback" name="com.springsource.ch.qos.logback.core" rev="${ch.qos.logback}" conf="provided, runtime"/>
+ <dependency org="ch.qos.logback" name="com.springsource.ch.qos.logback.classic" rev="${ch.qos.logback}" conf="provided, runtime"/>
+ <dependency org="org.aspectj" name="com.springsource.org.aspectj.runtime" rev="${org.aspectj}" conf="aspects->runtime"/>
+ <dependency org="org.slf4j" name="com.springsource.slf4j.api" rev="${org.slf4j}" conf="aspects->runtime"/>
+ <dependency org="org.eclipse.virgo.medic" name="org.eclipse.virgo.medic" rev="latest.integration" conf="compile->compile"/>
+ <dependency org="org.eclipse.osgi" name="org.eclipse.osgi" rev="${org.eclipse.osgi}" conf="provided->runtime"/>
+ <dependency org="org.junit" name="com.springsource.org.junit" rev="${org.junit}" conf="test->runtime"/>
+ </dependencies>
+
+</ivy-module>
diff --git a/org.eclipse.virgo.medic.weaving/src/main/java/org/eclipse/virgo/medic/log/impl/logback/LoggingInterceptor.aj b/org.eclipse.virgo.medic.weaving/src/main/java/org/eclipse/virgo/medic/log/impl/logback/LoggingInterceptor.aj
new file mode 100644
index 0000000..43e080f
--- /dev/null
+++ b/org.eclipse.virgo.medic.weaving/src/main/java/org/eclipse/virgo/medic/log/impl/logback/LoggingInterceptor.aj
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.log.impl.logback;
+
+import org.slf4j.Marker;
+
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.Logger;
+
+public aspect LoggingInterceptor {
+
+ private volatile LoggingListener loggingListener = new NoOpLoggingListener();
+
+ pointcut withinLoggingInterception() : cflowbelow(within(LoggingInterceptor) && adviceexecution());
+
+ pointcut filteringAndAppendingWithZeroOr3PlusParams(Logger logger, String fqcn, Marker marker, Level level, String message, Object[] params, Throwable throwable)
+ : execution(private void ch.qos.logback.classic.Logger.filterAndLog_0_Or3Plus(String, Marker, Level, String, Object[], Throwable))
+ && this(logger)
+ && args(fqcn, marker, level, message, params, throwable)
+ && !withinLoggingInterception();
+
+ pointcut filteringAndAppendingWithOneParam(Logger logger, String fqcn, Marker marker, Level level, String message, Object param, Throwable throwable)
+ : execution(private void ch.qos.logback.classic.Logger.filterAndLog_1(String, Marker, Level, String, Object, Throwable))
+ && this(logger)
+ && args(fqcn, marker, level, message, param, throwable)
+ && !withinLoggingInterception();
+
+ pointcut filteringAndAppendingWithTwoParams(Logger logger, String fqcn, Marker marker, Level level, String message, Object param1, Object param2, Throwable throwable)
+ : execution(private void ch.qos.logback.classic.Logger.filterAndLog_2(String, Marker, Level, String, Object, Object, Throwable))
+ && this(logger)
+ && args(fqcn, marker, level, message, param1, param2, throwable)
+ && !withinLoggingInterception();
+
+ before(Logger logger, String fqcn, Marker marker, Level level, String message, Object[] params, Throwable throwable) :
+ filteringAndAppendingWithZeroOr3PlusParams(logger, fqcn, marker, level, message, params, throwable) {
+
+ this.loggingListener.onLogging(logger, fqcn, marker, level, message, params, throwable);
+ }
+
+ before(Logger logger, String fqcn, Marker marker, Level level, String message, Object param, Throwable throwable) :
+ filteringAndAppendingWithOneParam(logger, fqcn, marker, level, message, param, throwable) {
+
+ this.loggingListener.onLogging(logger, fqcn, marker, level, message, param, throwable);
+ }
+
+ before(Logger logger, String fqcn, Marker marker, Level level, String message, Object param1, Object param2, Throwable throwable) :
+ filteringAndAppendingWithTwoParams(logger, fqcn, marker, level, message, param1, param2, throwable) {
+
+ this.loggingListener.onLogging(logger, fqcn, marker, level, message, param1, param2, throwable);
+ }
+
+ public void setLoggingListener(LoggingListener listener) {
+ if (listener == null) {
+ listener = new NoOpLoggingListener();
+ }
+ this.loggingListener = listener;
+ }
+}
diff --git a/org.eclipse.virgo.medic.weaving/src/main/java/org/eclipse/virgo/medic/log/impl/logback/LoggingListener.java b/org.eclipse.virgo.medic.weaving/src/main/java/org/eclipse/virgo/medic/log/impl/logback/LoggingListener.java
new file mode 100644
index 0000000..5ab3d95
--- /dev/null
+++ b/org.eclipse.virgo.medic.weaving/src/main/java/org/eclipse/virgo/medic/log/impl/logback/LoggingListener.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.log.impl.logback;
+
+import org.slf4j.Marker;
+
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.Logger;
+
+public interface LoggingListener {
+
+ void onLogging(Logger logger, String fqcn, Marker marker, Level level, String message, Object param, Throwable throwable);
+
+ void onLogging(Logger logger, String fqcn, Marker marker, Level level, String message, Object param1, Object param2, Throwable throwable);
+
+ void onLogging(Logger logger, String fqcn, Marker marker, Level level, String message, Object[] params, Throwable throwable);
+}
diff --git a/org.eclipse.virgo.medic.weaving/src/main/java/org/eclipse/virgo/medic/log/impl/logback/NoOpLoggingListener.java b/org.eclipse.virgo.medic.weaving/src/main/java/org/eclipse/virgo/medic/log/impl/logback/NoOpLoggingListener.java
new file mode 100644
index 0000000..a16e19e
--- /dev/null
+++ b/org.eclipse.virgo.medic.weaving/src/main/java/org/eclipse/virgo/medic/log/impl/logback/NoOpLoggingListener.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.log.impl.logback;
+
+import org.slf4j.Marker;
+
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.Logger;
+
+public class NoOpLoggingListener implements LoggingListener {
+
+ public void onLogging(Logger logger, String fqcn, Marker marker,
+ Level level, String message, Object param, Throwable throwable) {
+ }
+
+ public void onLogging(Logger logger, String fqcn, Marker marker,
+ Level level, String message, Object param1, Object param2,
+ Throwable throwable) {
+ }
+
+ public void onLogging(Logger logger, String fqcn, Marker marker,
+ Level level, String message, Object[] params, Throwable throwable) {
+ }
+}
diff --git a/org.eclipse.virgo.medic.weaving/src/main/resources/.gitignore b/org.eclipse.virgo.medic.weaving/src/main/resources/.gitignore
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/org.eclipse.virgo.medic.weaving/src/main/resources/.gitignore
diff --git a/org.eclipse.virgo.medic.weaving/src/test/java/.gitignore b/org.eclipse.virgo.medic.weaving/src/test/java/.gitignore
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/org.eclipse.virgo.medic.weaving/src/test/java/.gitignore
diff --git a/org.eclipse.virgo.medic.weaving/src/test/resources/.gitignore b/org.eclipse.virgo.medic.weaving/src/test/resources/.gitignore
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/org.eclipse.virgo.medic.weaving/src/test/resources/.gitignore
diff --git a/org.eclipse.virgo.medic/.classpath b/org.eclipse.virgo.medic/.classpath
new file mode 100644
index 0000000..6635d80
--- /dev/null
+++ b/org.eclipse.virgo.medic/.classpath
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src/main/java">
+ <attributes>
+ <attribute name="com.springsource.server.ide.jdt.core.test.classpathentry" value="false"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="src" path="src/main/resources">
+ <attributes>
+ <attribute name="com.springsource.server.ide.jdt.core.test.classpathentry" value="false"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="src" output="target/test-classes" path="src/test/java">
+ <attributes>
+ <attribute name="com.springsource.server.ide.jdt.core.test.classpathentry" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="src" output="target/test-classes" path="src/test/resources">
+ <attributes>
+ <attribute name="com.springsource.server.ide.jdt.core.test.classpathentry" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="var" path="MEDIC_IVY_CACHE/org.eclipse.osgi/org.eclipse.osgi/3.5.1.R35x_v20091005/org.eclipse.osgi-3.5.1.R35x_v20091005.jar" sourcepath="/MEDIC_IVY_CACHE/org.eclipse.osgi/org.eclipse.osgi/3.5.1.R35x_v20091005/org.eclipse.osgi-sources-3.5.1.R35x_v20091005.jar"/>
+ <classpathentry kind="con" path="org.eclipse.ajdt.core.ASPECTJRT_CONTAINER"/>
+ <classpathentry kind="var" path="MEDIC_IVY_CACHE/org.slf4j/com.springsource.slf4j.api/1.5.10/com.springsource.slf4j.api-1.5.10.jar" sourcepath="/MEDIC_IVY_CACHE/org.slf4j/com.springsource.slf4j.api/1.5.10/com.springsource.slf4j.api-sources-1.5.10.jar"/>
+ <classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/org.eclipse.virgo.medic/.project b/org.eclipse.virgo.medic/.project
new file mode 100644
index 0000000..10bb2cb
--- /dev/null
+++ b/org.eclipse.virgo.medic/.project
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.virgo.medic</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.wst.common.project.facet.core.builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.ajdt.core.ajbuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.springsource.server.ide.bundlor.core.builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.springframework.ide.eclipse.core.springbuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.ajdt.ui.ajnature</nature>
+ <nature>com.springsource.server.ide.facet.core.bundlenature</nature>
+ <nature>org.springframework.ide.eclipse.core.springnature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.wst.common.project.facet.core.nature</nature>
+ </natures>
+</projectDescription>
diff --git a/org.eclipse.virgo.medic/.settings/com.springsource.server.ide.bundlor.core.prefs b/org.eclipse.virgo.medic/.settings/com.springsource.server.ide.bundlor.core.prefs
new file mode 100644
index 0000000..a43d19e
--- /dev/null
+++ b/org.eclipse.virgo.medic/.settings/com.springsource.server.ide.bundlor.core.prefs
@@ -0,0 +1,5 @@
+#Thu Nov 12 08:44:05 GMT 2009
+com.springsource.server.ide.bundlor.core.bundlor.generated.manifest.autoformatting=true
+com.springsource.server.ide.bundlor.core.byte.code.scanning=true
+com.springsource.server.ide.bundlor.core.template.properties.files=../build.versions
+eclipse.preferences.version=1
diff --git a/org.eclipse.virgo.medic/.settings/org.eclipse.wst.common.project.facet.core.xml b/org.eclipse.virgo.medic/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 0000000..801f856
--- /dev/null
+++ b/org.eclipse.virgo.medic/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<faceted-project>
+ <installed facet="com.springsource.server.bundle" version="1.0"/>
+</faceted-project>
diff --git a/org.eclipse.virgo.medic/.settings/org.springframework.ide.eclipse.core.prefs b/org.eclipse.virgo.medic/.settings/org.springframework.ide.eclipse.core.prefs
new file mode 100644
index 0000000..a145ba0
--- /dev/null
+++ b/org.eclipse.virgo.medic/.settings/org.springframework.ide.eclipse.core.prefs
@@ -0,0 +1,68 @@
+#Thu Nov 12 08:44:05 GMT 2009
+eclipse.preferences.version=1
+org.springframework.ide.eclipse.core.builders.enable.aopreferencemodelbuilder=true
+org.springframework.ide.eclipse.core.builders.enable.beanmetadatabuilder=true
+org.springframework.ide.eclipse.core.builders.enable.osgibundleupdater=false
+org.springframework.ide.eclipse.core.enable.project.preferences=false
+org.springframework.ide.eclipse.core.validator.enable.com.springsource.server.ide.manifest.core.manifestvalidator=true
+org.springframework.ide.eclipse.core.validator.enable.com.springsource.sts.bestpractices.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.enable.com.springsource.sts.server.quickfix.manifestvalidator=false
+org.springframework.ide.eclipse.core.validator.enable.org.springframework.ide.eclipse.beans.core.beansvalidator=true
+org.springframework.ide.eclipse.core.validator.enable.org.springframework.ide.eclipse.core.springvalidator=false
+org.springframework.ide.eclipse.core.validator.enable.org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.server.ide.manifest.core.applicationSymbolicNameRule-com.springsource.server.ide.manifest.core.manifestvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.server.ide.manifest.core.applicationVersionRule-com.springsource.server.ide.manifest.core.manifestvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.server.ide.manifest.core.bundleActivationPolicyRule-com.springsource.server.ide.manifest.core.manifestvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.server.ide.manifest.core.bundleActivatorRule-com.springsource.server.ide.manifest.core.manifestvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.server.ide.manifest.core.bundleManifestVersionRule-com.springsource.server.ide.manifest.core.manifestvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.server.ide.manifest.core.bundleSymbolicNameRule-com.springsource.server.ide.manifest.core.manifestvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.server.ide.manifest.core.bundleVersionRule-com.springsource.server.ide.manifest.core.manifestvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.server.ide.manifest.core.exportPackageRule-com.springsource.server.ide.manifest.core.manifestvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.server.ide.manifest.core.importRule-com.springsource.server.ide.manifest.core.manifestvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.server.ide.manifest.core.parsingProblemsRule-com.springsource.server.ide.manifest.core.manifestvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.server.ide.manifest.core.requireBundleRule-com.springsource.server.ide.manifest.core.manifestvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.bestpractices.com.springsource.sts.bestpractices.AvoidDriverManagerDataSource-com.springsource.sts.bestpractices.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.bestpractices.com.springsource.sts.bestpractices.ImportElementsAtTopRulee-com.springsource.sts.bestpractices.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.bestpractices.com.springsource.sts.bestpractices.ParentBeanSpecifiesAbstractClassRule-com.springsource.sts.bestpractices.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.bestpractices.com.springsource.sts.bestpractices.RefElementRule-com.springsource.sts.bestpractices.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.bestpractices.com.springsource.sts.bestpractices.TooManyBeansInFileRule-com.springsource.sts.bestpractices.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.bestpractices.com.springsource.sts.bestpractices.UnnecessaryValueElementRule-com.springsource.sts.bestpractices.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.bestpractices.com.springsource.sts.bestpractices.UseBeanInheritance-com.springsource.sts.bestpractices.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.bestpractices.legacyxmlusage.jndiobjectfactory-com.springsource.sts.bestpractices.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.server.quickfix.importBundleVersionRule-com.springsource.sts.server.quickfix.manifestvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.server.quickfix.importLibraryVersionRule-com.springsource.sts.server.quickfix.manifestvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.server.quickfix.importPackageVersionRule-com.springsource.sts.server.quickfix.manifestvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.server.quickfix.requireBundleVersionRule-com.springsource.sts.server.quickfix.manifestvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.autowire.autowire-org.springframework.ide.eclipse.beans.core.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanAlias-org.springframework.ide.eclipse.beans.core.beansvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanClass-org.springframework.ide.eclipse.beans.core.beansvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanConstructorArgument-org.springframework.ide.eclipse.beans.core.beansvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanDefinition-org.springframework.ide.eclipse.beans.core.beansvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanDefinitionHolder-org.springframework.ide.eclipse.beans.core.beansvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanFactory-org.springframework.ide.eclipse.beans.core.beansvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanInitDestroyMethod-org.springframework.ide.eclipse.beans.core.beansvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanProperty-org.springframework.ide.eclipse.beans.core.beansvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanReference-org.springframework.ide.eclipse.beans.core.beansvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.methodOverride-org.springframework.ide.eclipse.beans.core.beansvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.parsingProblems-org.springframework.ide.eclipse.beans.core.beansvalidator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.requiredProperty-org.springframework.ide.eclipse.beans.core.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.toolAnnotation-org.springframework.ide.eclipse.beans.core.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.core.springClasspath-org.springframework.ide.eclipse.core.springvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.action-org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.actionstate-org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.attribute-org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.attributemapper-org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.beanaction-org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.evaluationaction-org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.evaluationresult-org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.exceptionhandler-org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.import-org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.inputattribute-org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.mapping-org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.outputattribute-org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.set-org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.state-org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.subflowstate-org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.transition-org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.variable-org.springframework.ide.eclipse.webflow.core.validator=true
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.webflowstate-org.springframework.ide.eclipse.webflow.core.validator=true
diff --git a/org.eclipse.virgo.medic/.springBeans b/org.eclipse.virgo.medic/.springBeans
new file mode 100644
index 0000000..5152991
--- /dev/null
+++ b/org.eclipse.virgo.medic/.springBeans
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beansProjectDescription>
+ <version>1</version>
+ <pluginVersion><![CDATA[2.2.5.M1]]></pluginVersion>
+ <configSuffixes>
+ <configSuffix><![CDATA[xml]]></configSuffix>
+ </configSuffixes>
+ <enableImports><![CDATA[false]]></enableImports>
+ <configs>
+ </configs>
+ <configSets>
+ </configSets>
+</beansProjectDescription>
diff --git a/org.eclipse.virgo.medic/build.xml b/org.eclipse.virgo.medic/build.xml
new file mode 100644
index 0000000..af86144
--- /dev/null
+++ b/org.eclipse.virgo.medic/build.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="org.eclipse.virgo.medic">
+
+ <property name="clover.coverage" value="0%"/>
+
+ <property file="${basedir}/../build.properties"/>
+ <property file="${basedir}/../build.versions"/>
+ <import file="${basedir}/../virgo-build/aspect/default.xml"/>
+
+</project>
diff --git a/org.eclipse.virgo.medic/ivy.xml b/org.eclipse.virgo.medic/ivy.xml
new file mode 100644
index 0000000..482ad18
--- /dev/null
+++ b/org.eclipse.virgo.medic/ivy.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?xml-stylesheet type="text/xsl" href="http://ivyrep.jayasoft.org/ivy-doc.xsl"?>
+<ivy-module
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="http://incubator.apache.org/ivy/schemas/ivy.xsd"
+ version="1.3">
+
+ <info organisation="org.eclipse.virgo.medic" module="${ant.project.name}"/>
+
+ <configurations>
+ <include file="${virgo.build.dir}/common/default-ivy-configurations.xml"/>
+ </configurations>
+
+ <publications>
+ <artifact name="${ant.project.name}"/>
+ <artifact name="${ant.project.name}-sources" type="src" ext="jar"/>
+ </publications>
+
+ <dependencies>
+ <dependency org="org.eclipse.osgi" name="org.eclipse.osgi" rev="${org.eclipse.osgi}" conf="provided->runtime"/>
+ <dependency org="org.slf4j" name="com.springsource.slf4j.api" rev="${org.slf4j}" conf="aspects->runtime"/>
+ <dependency org="org.aspectj" name="com.springsource.org.aspectj.runtime" rev="${org.aspectj}" conf="aspects->runtime"/>
+ </dependencies>
+
+</ivy-module>
diff --git a/org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/dump/Dump.java b/org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/dump/Dump.java
new file mode 100644
index 0000000..2d631c2
--- /dev/null
+++ b/org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/dump/Dump.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.dump;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.Writer;
+import java.util.Map;
+
+/**
+ * A <code>Dump</code> represents a dump being generated by a {@link DumpGenerator}. During dump generation
+ * {@link DumpContributor DumpContributors} are called to contribute to the dump. Contributors can request a
+ * {@link Writer}, {@link File}, etc. which they may use to write out their contribution to the dump.
+ */
+public interface Dump {
+
+ /**
+ * Returns a timestamp that identifies that time at which this dump was generated.
+ *
+ * @return The timestamp of the dump's generation
+ */
+ long getTimestamp();
+
+ /**
+ * Returns the context that is associated with this dump. If there is no associated context an empty
+ * <code>Map</code> is returned.
+ *
+ * @return The dump's context
+ */
+ Map<String, Object> getContext();
+
+ /**
+ * Returns the {@link Throwable Throwables} associated with this dump.
+ *
+ * @return The dump's <code>Throwable</code>s
+ */
+ Throwable[] getThrowables();
+
+ /**
+ * Returns the cause of this dump.
+ *
+ * @return The dump's cause.
+ */
+ String getCause();
+
+ /**
+ * Creates a {@link FileWriter} that writes to a file with the supplied name, within this dump's output location.
+ * @param name of file to write to
+ *
+ * @return a <code>FileWriter</code> to which a contribution to the dump can be written
+ * @throws DumpContributionFailedException
+ */
+ FileWriter createFileWriter(String name) throws DumpContributionFailedException;
+
+ /**
+ * Creates a {@link FileOutputStream} that writes to a file with the supplied name, within this dump's output
+ * location.
+ * @param name of file to write to
+ *
+ * @return a <code>FileOutputStream</code> to which a contribution to the dump can be written
+ * @throws DumpContributionFailedException
+ */
+ FileOutputStream createFileOutputStream(String name) throws DumpContributionFailedException;
+
+ /**
+ * Creates a {@link File} with the supplied name, within this dump's output location.
+ * @param name of file to write to
+ *
+ * @return a <code>File</code> to which a contribution to the dump can be written
+ */
+ File createFile(String name);
+
+}
diff --git a/org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/dump/DumpContributionFailedException.java b/org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/dump/DumpContributionFailedException.java
new file mode 100644
index 0000000..edaf464
--- /dev/null
+++ b/org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/dump/DumpContributionFailedException.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.dump;
+
+/**
+ * A <code>DumpContributionFailedException</code> is thrown by a {@link DumpContributor} to indicate that a failure has
+ * occurred when it was attempting to make a contribution to a dump.
+ * <p />
+ *
+ * <strong>Concurrent Semantics</strong><br />
+ * Thread-safe.
+ *
+ */
+public class DumpContributionFailedException extends DumpGenerationFailedException {
+
+ private static final long serialVersionUID = -3196511149954617337L;
+
+ /**
+ * Create a new DumpContributionFailedException with the supplied message that describes the failure
+ *
+ * @param message The message describing the failure
+ */
+ public DumpContributionFailedException(String message) {
+ super(message);
+ }
+
+ /**
+ * Create a new DumpContributionFailedException with the supplied failure cause and message that describes the
+ * failure
+ *
+ * @param message The message describing the failure
+ * @param cause The cause of the contribution failure
+ */
+ public DumpContributionFailedException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/dump/DumpContributor.java b/org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/dump/DumpContributor.java
new file mode 100644
index 0000000..ddffe7c
--- /dev/null
+++ b/org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/dump/DumpContributor.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.dump;
+
+/**
+ * A <code>DumpContributor</code> is implemented to contribute information to a dump. Contributors are 'registered' with
+ * a {@link DumpGenerator} by publishing them in the service registry.
+ * <p />
+ *
+ * <strong>Concurrent Semantics</strong><br />
+ * <code>DumpContributor</code>s must be thread-safe.
+ */
+public interface DumpContributor {
+
+ /**
+ * Contribute to the supplied {@link Dump}.
+ *
+ * @param dump The dump to which a contribution may be made.
+ * @throws DumpContributionFailedException if the dump contribution cannot be created
+ */
+ void contribute(Dump dump) throws DumpContributionFailedException;
+
+ /**
+ * Returns the name of this <code>DumpContributor</code>. The name is used by a {@link DumpGenerator} when
+ * determining which contributors should be excluded from contributing to a dump.
+ *
+ * @return The contributor's name
+ */
+ String getName();
+}
diff --git a/org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/dump/DumpGenerationFailedException.java b/org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/dump/DumpGenerationFailedException.java
new file mode 100644
index 0000000..5dded04
--- /dev/null
+++ b/org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/dump/DumpGenerationFailedException.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.dump;
+
+/**
+ * A <code>DumpGenerationFailedException</code> is thrown by a {@link DumpGenerator} to indicate that a failure has
+ * occurred during dump generation.
+ *
+ * <p />
+ *
+ * <strong>Concurrent Semantics</strong><br />
+ * Thread-safe.
+ *
+ */
+public class DumpGenerationFailedException extends Exception {
+
+ private static final long serialVersionUID = -3196511149954617337L;
+
+ /**
+ * Create a new DumpGenerationFailedException with the supplied message that describes the failure
+ *
+ * @param message The message describing the failure
+ */
+ public DumpGenerationFailedException(String message) {
+ super(message);
+ }
+
+ /**
+ * Create a new DumpGenerationFailedException with the supplied failure cause and message that describes the failure
+ *
+ * @param message The message describing the failure
+ * @param cause The cause of the generation failure
+ */
+ public DumpGenerationFailedException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/dump/DumpGenerator.java b/org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/dump/DumpGenerator.java
new file mode 100644
index 0000000..c07f9bc
--- /dev/null
+++ b/org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/dump/DumpGenerator.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.dump;
+
+import java.util.Map;
+
+/**
+ * A <code>DumpGenerator</code> can be used to request the generation of a dump. A
+ * <code>DumpGenerator</code> instance can be obtained from the service registry.
+ * <p />
+ *
+ * When a dump is requested, the <code>DumpGenerator</code> will, by default, provide all {@link DumpContributor}s
+ * that are known to it with an opportunity to contribute to the dump. <code>DumpContributor</code>
+ * instances are made known to a {@link DumpGenerator} by publishing them in the service registry.
+ * <p />
+ *
+ * A {@link DumpGenerator} can be configured to exclude {@link DumpContributor}s from contributing to dumps
+ * with a particular cause. <br/>
+ * TODO Expand the documentation on contributor exclusion
+ * <p />
+ *
+ * <strong>Concurrent Semantics</strong><br />
+ * <code>DumpGenerator</code>s must be thread-safe.
+ */
+public interface DumpGenerator {
+
+ /**
+ * Generates a dump
+ *
+ * @param cause the cause of the dump
+ * @param throwables {@link Throwable} instances to be associated with the dump
+ */
+ void generateDump(String cause, Throwable... throwables);
+
+ /**
+ * Generates a dump, with additional context.
+ *
+ * @param cause the cause of the dump
+ * @param context additional context that can be used by the {@link DumpContributor}s
+ * @param throwables {@link Throwable} instances to be associated with the dump
+ */
+ void generateDump(String cause, Map<String, Object> context, Throwable... throwables);
+}
diff --git a/org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/eventlog/EventLogger.java b/org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/eventlog/EventLogger.java
new file mode 100644
index 0000000..1ffd641
--- /dev/null
+++ b/org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/eventlog/EventLogger.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.eventlog;
+
+import java.util.ResourceBundle;
+
+/**
+ * An <code>EventLogger</code> provides support for logging events as human-readable, potentially internationalized,
+ * messages identified by a unique code.
+ * <p />
+ * An <code>EventLogger</code> instance can be obtained directly from the service registry. Such instances will search
+ * the {@link org.osgi.framework.Bundle} that obtained the instance, and the <code>EventLogger</code> implementations <code>Bundle</code>
+ * for a properties file that contains entry for the an event's code. The implementation bundle is searched to support
+ * providing properties files in fragment bundles which are attached to the implementation.
+ * <p />
+ * Alternatively, an <code>EventLogger</code> can be obtained from an {@link EventLoggerFactory} allowing a specific
+ * <code>Bundle</code> to be supplied that will be used to search for properties files.
+ * <p />
+ * The algorithm used to find properties files matches that described in
+ * {@link ResourceBundle#getBundle(String, java.util.Locale, ClassLoader) ResourceBundle}, with the exception that no
+ * searching for class files is performed.
+ * <p />
+ * <strong>Concurrent Semantics</strong><br />
+ * Implementations <strong>must</strong> be thread-safe.
+ */
+public interface EventLogger {
+
+ /**
+ * Logs an event in the form of a message identified by the supplied code. The message is resolved by searching the
+ * available {@link ResourceBundle ResourceBundles} for an entry with the key that matches the code.
+ *
+ * The event is logged at the supplied level, with the supplied inserts being applied to the message.
+ *
+ * @param code The code of the message to be logged
+ * @param level The level at which the event should be logged
+ * @param inserts The inserts for the message
+ */
+ void log(String code, Level level, Object... inserts);
+
+ /**
+ * Logs an event in the form of a message identified by the supplied code. The message is resolved by searching the
+ * available {@link ResourceBundle ResourceBundles} for an entry with the key that matches the code.
+ *
+ * The event is logged at the supplied level, with the supplied inserts being applied to the message.
+ *
+ * @param logEvent The log event to be logged
+ * @param inserts The inserts for the message
+ */
+ void log(LogEvent logEvent, Object... inserts);
+
+ /**
+ * Logs an event in the form of a message identified by the supplied code. The message is resolved by searching the
+ * available {@link ResourceBundle ResourceBundles} for an entry with the key that matches the code.
+ *
+ * The event is logged at the supplied level, with the supplied inserts being applied to the message. The supplied
+ * <code>Throwable</code> is logged with the message.
+ *
+ * @param code The code of the message to be logged
+ * @param level The level at which the event should be logged
+ * @param throwable The <code>Throwable</code> to be logged
+ * @param inserts The inserts for the message
+ */
+ void log(String code, Level level, Throwable throwable, Object... inserts);
+
+ /**
+ * Logs an event in the form of a message identified by the supplied code. The message is resolved by searching the
+ * available {@link ResourceBundle ResourceBundles} for an entry with the key that matches the code.
+ *
+ * The event is logged at the supplied level, with the supplied inserts being applied to the message. The supplied
+ * <code>Throwable</code> is logged with the message.
+ *
+ * @param logEvent The log event to be logged
+ * @param throwable The <code>Throwable</code> to be logged
+ * @param inserts The inserts for the message
+ */
+ void log(LogEvent logEvent, Throwable throwable, Object... inserts);
+}
diff --git a/org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/eventlog/EventLoggerFactory.java b/org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/eventlog/EventLoggerFactory.java
new file mode 100644
index 0000000..da99120
--- /dev/null
+++ b/org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/eventlog/EventLoggerFactory.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.eventlog;
+
+import java.util.ResourceBundle;
+
+import org.osgi.framework.Bundle;
+
+/**
+ * An <code>EventLoggerFactory</code> is used to create an <code>EventLogger</code> instance that will search a specific
+ * bundle, in addition to the EventLogger implementation's bundle, for {@link ResourceBundle ResourceBundles}.
+ * <p />
+ * <strong>Concurrent Semantics</strong><br />
+ * Implementations <strong>must</strong> be thread-safe.
+ */
+public interface EventLoggerFactory {
+
+ /**
+ * Creates a new <code>EventLogger</code> that will search the supplied bundle, in addition to the
+ * <code>EventLogger</code> implementation's bundle, for {@link ResourceBundle ResourceBundles}.
+ *
+ * @param bundle The <code>Bundle</code> to search for <code>ResourceBundle</code>s.
+ *
+ * @return The <code>EventLogger</code>
+ */
+ public EventLogger createEventLogger(Bundle bundle);
+}
diff --git a/org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/eventlog/Level.java b/org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/eventlog/Level.java
new file mode 100644
index 0000000..b8d9eae
--- /dev/null
+++ b/org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/eventlog/Level.java
@@ -0,0 +1,16 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.eventlog;
+
+public enum Level {
+ ERROR, WARNING, INFO
+}
diff --git a/org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/eventlog/LogEvent.java b/org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/eventlog/LogEvent.java
new file mode 100644
index 0000000..3387160
--- /dev/null
+++ b/org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/eventlog/LogEvent.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.eventlog;
+
+/**
+ * A <code>LogEvent</code> encapsulates the details of an event that is to be logged.
+ * <p/>
+ *
+ * <strong>Concurrent Semantics</strong><br />
+ * Implementations <strong>must</strong> be thread-safe.
+ *
+ */
+public interface LogEvent {
+
+ /**
+ * Returns the code that uniquely identifies this <code>LogEvent</code>. Typically, this code is used to locate the
+ * message for the event in a resource bundle.
+ *
+ * @return The event's code
+ */
+ public String getEventCode();
+
+ /**
+ * Returns the {@link Level} at which this <code>LogEvent</code> should be published.
+ *
+ * @return The level of the event.
+ */
+ public Level getLevel();
+}
diff --git a/org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/log/ConfigurationPublicationFailedException.java b/org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/log/ConfigurationPublicationFailedException.java
new file mode 100644
index 0000000..e2bbf0e
--- /dev/null
+++ b/org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/log/ConfigurationPublicationFailedException.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.log;
+
+/**
+ * Thrown by {@link LoggingConfigurationPublisher} when a request to publish logging configuration fails.
+ */
+public class ConfigurationPublicationFailedException extends Exception {
+
+ private static final long serialVersionUID = 4317804271280636565L;
+
+ /**
+ * Creates a new exception with the supplied message and cause.
+ *
+ * @param message The exception's message
+ * @param cause The exception's cause
+ */
+ public ConfigurationPublicationFailedException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/log/DelegatingPrintStream.java b/org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/log/DelegatingPrintStream.java
new file mode 100644
index 0000000..131f597
--- /dev/null
+++ b/org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/log/DelegatingPrintStream.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.log;
+
+import java.io.PrintStream;
+
+/**
+ * A <code>DelegatingPrintStream</code> is a {@link PrintStream} implementation that delegates to another
+ * {@link PrintStream} instance and allows the delegate to be changed at runtime.
+ * <p />
+ *
+ * <strong>Concurrent Semantics</strong><br />
+ * Thread-safe.
+ *
+ */
+public interface DelegatingPrintStream {
+
+ /**
+ * Sets the {@link PrintStream} to be used as a delegate. The given <code>printStream</code> may be
+ * <code>null</code> to disable delegation.
+ *
+ * @param printStream The delegate, or <code>null</code> to disable delegation.
+ */
+ void setDelegate(PrintStream printStream);
+}
diff --git a/org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/log/EntryExitTrace.aj b/org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/log/EntryExitTrace.aj
new file mode 100644
index 0000000..5e4d2c0
--- /dev/null
+++ b/org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/log/EntryExitTrace.aj
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.log;
+
+import org.aspectj.lang.JoinPoint;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * An aspect that will advise any method with entry and exit trace logging.
+ *
+ * <strong>Concurrent Semantics</strong><br />
+ *
+ * Threadsafe
+ *
+ */
+public aspect EntryExitTrace pertypewithin(*) {
+
+ private volatile Logger logger;
+
+ pointcut performingEntryExitTrace() : cflowbelow(adviceexecution() && within(EntryExitTrace));
+
+ pointcut medic() : within(org.eclipse.virgo.medic..*);
+
+ pointcut util() : within(org.eclipse.virgo.util..*);
+
+ pointcut logback() : within(ch.qos.logback..*) || within(org.slf4j.impl..*);
+
+ pointcut infoCandidate() : execution(public * *(..)) && !medic() && !util() && !logback() && !performingEntryExitTrace();
+
+ pointcut debugCandidate() : execution(!public !private * *(..)) && !medic() && !util() && !logback() && !performingEntryExitTrace();
+
+ pointcut traceCandidate() : execution(private * *(..)) && !medic() && !util() && !logback() && !performingEntryExitTrace();
+
+ before() : infoCandidate() {
+ getLogger(thisJoinPointStaticPart).info("{} {}", ">", getSignature(thisJoinPointStaticPart));
+ }
+
+ after() returning : infoCandidate() {
+ getLogger(thisJoinPointStaticPart).info("{} {}", "<", getSignature(thisJoinPointStaticPart));
+ }
+
+ after() throwing(Throwable t) : infoCandidate() {
+ Logger logger = getLogger(thisJoinPointStaticPart);
+ if (logger.isInfoEnabled()) {
+ logger.info(String.format("< %s", getSignature(thisJoinPointStaticPart)), t);
+ }
+ }
+
+ before() : debugCandidate() {
+ getLogger(thisJoinPointStaticPart).debug("{} {}", ">", getSignature(thisJoinPointStaticPart));
+ }
+
+ after() returning : debugCandidate() {
+ getLogger(thisJoinPointStaticPart).debug("{} {}", "<", getSignature(thisJoinPointStaticPart));
+ }
+
+ after() throwing(Throwable t) : debugCandidate() {
+ Logger logger = getLogger(thisJoinPointStaticPart);
+ if (logger.isDebugEnabled()) {
+ logger.debug(String.format("< %s", getSignature(thisJoinPointStaticPart)), t);
+ }
+ }
+
+ before() : traceCandidate() {
+ getLogger(thisJoinPointStaticPart).trace("{} {}", ">", getSignature(thisJoinPointStaticPart));
+ }
+
+ after() returning : traceCandidate() {
+ getLogger(thisJoinPointStaticPart).trace("{} {}", "<", getSignature(thisJoinPointStaticPart));
+ }
+
+ after() throwing(Throwable t) : traceCandidate() {
+ Logger logger = getLogger(thisJoinPointStaticPart);
+ if (logger.isTraceEnabled()) {
+ logger.trace(String.format("< %s", getSignature(thisJoinPointStaticPart)), t);
+ }
+ }
+
+ private Logger getLogger(JoinPoint.StaticPart sp) {
+ if (this.logger == null) {
+ this.logger = LoggerFactory.getLogger(sp.getSignature().getDeclaringType());
+ }
+ return this.logger;
+ }
+
+ private String getSignature(JoinPoint.StaticPart sp) {
+ return sp.getSignature().toLongString();
+ }
+}
diff --git a/org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/log/LoggingConfiguration.java b/org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/log/LoggingConfiguration.java
new file mode 100644
index 0000000..4156c90
--- /dev/null
+++ b/org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/log/LoggingConfiguration.java
@@ -0,0 +1,19 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.log;
+
+public interface LoggingConfiguration {
+
+ String getConfiguration();
+
+ String getName();
+}
diff --git a/org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/log/LoggingConfigurationPublisher.java b/org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/log/LoggingConfigurationPublisher.java
new file mode 100644
index 0000000..e0d3c90
--- /dev/null
+++ b/org.eclipse.virgo.medic/src/main/java/org/eclipse/virgo/medic/log/LoggingConfigurationPublisher.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.medic.log;
+
+import java.io.File;
+
+/**
+ * A <code>LoggingConfigurationPublisher</code> is used to publish {@link LoggingConfiguration} into the service
+ * registry. <code>LoggingConfiguration</code> instances in the service registry are referenced by bundles using the
+ * <code>Medic-LoggingConfiguration</code> manifest header.
+ */
+public interface LoggingConfigurationPublisher {
+
+ /**
+ * Publishes the configuration in the supplied <code>File</code> as a <code>LoggingConfiguration</code> instance,
+ * identified with the supplied id. The published configuration can then be referenced by a bundle using the
+ * <code>Medic-LoggingConfiguration</code> manifest header with a value equal to the supplied id.
+ *
+ * @param configuration The configuration to be published
+ * @param id The identifier to be applied to the configuration when its published
+ *
+ * @throws ConfigurationPublicationFailedException if the publication of the configuration fails
+ */
+ void publishConfiguration(File configuration, String id) throws ConfigurationPublicationFailedException;
+}
diff --git a/org.eclipse.virgo.medic/src/main/resources/.gitignore b/org.eclipse.virgo.medic/src/main/resources/.gitignore
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/org.eclipse.virgo.medic/src/main/resources/.gitignore
diff --git a/org.eclipse.virgo.medic/src/test/java/.gitignore b/org.eclipse.virgo.medic/src/test/java/.gitignore
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/org.eclipse.virgo.medic/src/test/java/.gitignore
diff --git a/org.eclipse.virgo.medic/src/test/resources/.gitignore b/org.eclipse.virgo.medic/src/test/resources/.gitignore
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/org.eclipse.virgo.medic/src/test/resources/.gitignore
diff --git a/org.eclipse.virgo.medic/template.mf b/org.eclipse.virgo.medic/template.mf
new file mode 100644
index 0000000..aead093
--- /dev/null
+++ b/org.eclipse.virgo.medic/template.mf
@@ -0,0 +1,11 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: org.eclipse.virgo.medic
+Bundle-Vendor: SpringSource Inc.
+Import-Template:
+ org.aspectj.*;version="${org.aspectj:[=.=.= , +1.0.0)}",
+ javax.management.*;version="0",
+ org.osgi.framework;version="0",
+ org.slf4j.*;version="${org.slf4j:[=.=.=, =.+1.0)}"
+Bundle-Version: 1.0.0
+Bundle-Name: Medic API

Back to the top