From 457f715b18f48cc52f6ee45abad044e1eec6bb58 Mon Sep 17 00:00:00 2001 From: Glenn Marcy Date: Sun, 26 Mar 2017 21:09:51 -0400 Subject: [PATCH] added kernel test projects to gradle workspace --- dev/cnf/gradle/transform/transform.properties | 25 + .../.classpath | 6 + .../.gitignore | 3 + .../.project | 23 + .../bnd.bnd | 18 + .../build.gradle | 0 .../com.ibm.websphere.appserver.api.json.pom | 26 + dev/com.ibm.websphere.filetransfer/.classpath | 7 + .../.classpath.gradle | 7 + dev/com.ibm.websphere.filetransfer/.gitignore | 2 + dev/com.ibm.websphere.filetransfer/.project | 23 + .../org.eclipse.core.resources.prefs | 4 + .../.settings/org.eclipse.jdt.core.prefs | 286 ++ .../.settings/org.eclipse.jdt.ui.prefs | 117 + .../org.sonar.ide.eclipse.core.prefs | 7 + dev/com.ibm.websphere.filetransfer/README.txt | 5 + dev/com.ibm.websphere.filetransfer/bnd.bnd | 15 + .../build.gradle | 0 dev/com.ibm.websphere.filetransfer/build.xml | 5 + .../findbugs.exclude.xml | 16 + .../filetransfer/FileServiceMXBean.java | 231 + .../filetransfer/FileTransferMBean.java | 137 + .../websphere/filetransfer/package-info.java | 21 + dev/com.ibm.ws.config.utility_fat/.classpath | 7 + .../.classpath.gradle | 7 + dev/com.ibm.ws.config.utility_fat/.gitignore | 1 + dev/com.ibm.ws.config.utility_fat/.project | 23 + .../org.eclipse.core.resources.prefs | 4 + .../.settings/org.eclipse.jdt.core.prefs | 280 ++ .../.settings/org.eclipse.jdt.ui.prefs | 62 + dev/com.ibm.ws.config.utility_fat/bnd.bnd | 15 + .../bnd.bnd.gradle | 15 + .../build-test.xml | 13 + .../build.gradle | 0 .../delivery.sets | 1 + .../ibm/ws/config/utility/fat/FATSuite.java | 23 + .../fat/ServerConfigUtilityFatTesting.java | 336 ++ .../ws/config/utility/fat/TestRepository.java | 72 + .../files/massive/massiveRepoLocation.props | 6 + .../bootstrap.properties | 8 + .../files/ejbSnippet.xml | 50 + .../files/remoteJMXConnection.xml | 32 + .../files/resultingSnippet.xml | 36 + .../resources/security/ltpa.keys | 8 + .../com.ibm.ws.config.utility.fat/server.xml | 9 + dev/com.ibm.ws.config_bvt.schema/.classpath | 7 + .../.classpath.gradle | 7 + dev/com.ibm.ws.config_bvt.schema/.project | 23 + .../org.eclipse.core.resources.prefs | 4 + .../.settings/org.eclipse.jdt.core.prefs | 280 ++ .../.settings/org.eclipse.jdt.ui.prefs | 113 + dev/com.ibm.ws.config_bvt.schema/bnd.bnd | 18 + .../bnd.bnd.gradle | 18 + .../build-bvt.xml | 43 + dev/com.ibm.ws.config_bvt.schema/build.gradle | 0 .../bvt-bundle.bnd | 22 + .../resources/config/factory-one.xml | 8 + .../resources/config/factory-two.xml | 7 + .../bvt-bundle/resources/config/singleton.xml | 8 + .../resources/metatype-attributecopy.xml | 58 + .../resources/metatype-childfirstextends.xml | 61 + .../bvt-bundle/resources/metatype-default.xml | 27 + .../bvt-bundle/resources/metatype-dynamic.xml | 35 + .../resources/metatype-extensions-two.xml | 17 + .../resources/metatype-extensions.xml | 83 + .../bvt-bundle/resources/metatype-hidden.xml | 64 + .../resources/metatype-nested-defaults.xml | 59 + .../resources/metatype-nested-merge.xml | 41 + .../resources/metatype-nested-two.xml | 55 + .../bvt-bundle/resources/metatype-nested.xml | 133 + .../resources/metatype-reference.xml | 89 + .../resources/metatype-serviceobjectclass.xml | 41 + .../resources/metatype-variable.xml | 18 + .../bvt-bundle/resources/metatype.xml | 151 + .../src/test/server/BaseHttpTest.java | 62 + .../bvt-bundle/src/test/server/BaseTest.java | 30 + .../src/test/server/BaseTestRunner.java | 166 + .../server/config/ConfigurationAdminTest.java | 79 + .../config/ConfigurationPluginTest.java | 59 + .../test/server/config/FactoryAliasTest.java | 45 + .../server/config/FactoryMetaTypeTest.java | 49 + .../test/server/config/FactorySimpleTest.java | 38 + .../src/test/server/config/FinalTypeTest.java | 41 + .../server/config/ManagedFactoryTest.java | 50 + .../src/test/server/config/ManagedTest.java | 43 + .../NestedConfigComplexElementTest.java | 111 + .../config/NestedConfigElementTest.java | 144 + .../test/server/config/NestedResultTest.java | 45 + .../server/config/NestedSingletonTest.java | 104 + .../test/server/config/PasswordTypeTest.java | 83 + .../test/server/config/SharedAliasTest.java | 39 + .../server/config/SingletonAliasTest.java | 35 + .../server/config/SingletonMetaTypeTest.java | 40 + .../config/SingletonServerMetaTypeTest.java | 44 + .../server/config/SingletonServerTest.java | 33 + .../src/test/server/config/Test.java | 44 + .../src/test/server/config/TestRunner.java | 119 + .../src/test/server/config/VariableTest.java | 37 + .../server/config/defaults/TestRunner.java | 106 + .../server/config/dynamic/ConfigWriter.java | 182 + .../config/dynamic/FactoryNestedTest.java | 85 + .../server/config/dynamic/FactoryTest.java | 141 + .../server/config/dynamic/SingletonTest.java | 81 + .../server/config/dynamic/TestRunner.java | 300 ++ .../nested/AttributeCopyTestRunner.java | 255 + .../nested/ChildFirstExtendsTestRunner.java | 140 + .../config/nested/HiddenTestRunner.java | 320 ++ .../nested/NestedDefaultsTestRunner.java | 117 + .../nested/NestedMergeRulesTestRunner.java | 595 +++ .../nested/NestedSingletonTestRunner.java | 179 + .../test/server/config/nested/TestRunner.java | 650 +++ .../server/config/reference/TestRunner.java | 403 ++ .../soc/ServiceObjectClassTestRunner.java | 198 + .../server/config/variable/TestRunner.java | 90 + .../schema/SchemaGeneratorActivator.java | 108 + .../src/test/server/schema/TestRunner.java | 115 + .../ws/config/bvt/FeatureListMBeanTest.java | 149 + .../ibm/ws/config/bvt/SchemaMBeanTest.java | 156 + .../src/com/ibm/ws/config/bvt/SchemaTest.java | 68 + .../bvt/ServerXMLConfigurationMBeanTest.java | 113 + .../delivery.sets | 1 + .../osgitck-bvt.xml.disabled | 17 + .../publish/features/testschema-1.0.mf | 7 + .../com.ibm.ws.config.bvt.schema/.gitignore | 1 + .../bootstrap.properties | 4 + .../com.ibm.ws.config.bvt.schema/jvm.options | 1 + .../com.ibm.ws.config.bvt.schema/server.xml | 15 + dev/com.ibm.ws.config_fat/.classpath | 7 + dev/com.ibm.ws.config_fat/.classpath.gradle | 7 + dev/com.ibm.ws.config_fat/.gitignore | 1 + dev/com.ibm.ws.config_fat/.project | 23 + .../org.eclipse.core.resources.prefs | 4 + .../.settings/org.eclipse.jdt.core.prefs | 280 ++ .../.settings/org.eclipse.jdt.ui.prefs | 62 + dev/com.ibm.ws.config_fat/bnd.bnd | 14 + dev/com.ibm.ws.config_fat/bnd.bnd.gradle | 14 + dev/com.ibm.ws.config_fat/build-test.xml | 134 + dev/com.ibm.ws.config_fat/build.gradle | 0 dev/com.ibm.ws.config_fat/delivery.sets | 1 + .../test/server/config/BadConfigTests.java | 124 + .../test/server/config/ChildAliasTest.java | 236 + .../server/config/ConfigExtensionsTest.java | 298 ++ .../server/config/ConfigValidatorTest.java | 112 + .../server/config/DelayedVariableTests.java | 56 + .../src/test/server/config/DropinsTest.java | 240 + .../fat/src/test/server/config/FATSuite.java | 39 + .../server/config/FeatureUpdateTests.java | 107 + .../config/FeaturelistGeneratorMBeanTest.java | 376 ++ .../test/server/config/MergedConfigTests.java | 141 + .../server/config/MetatypeProviderTest.java | 88 + .../server/config/ProductExtensionsTest.java | 384 ++ .../config/SchemaGeneratorMBeanTest.java | 455 ++ .../test/server/config/ServerConfigTest.java | 656 +++ .../ServerXMLConfigurationMBeanTest.java | 171 + .../src/test/server/config/ServletRunner.java | 74 + .../server/config/VariableMergeTests.java | 88 + .../config/WSConfigurationHelperTest.java | 125 + dev/com.ibm.ws.config_fat/publish/.gitignore | 1 + .../publish/files/.gitignore | 7 + .../files/badconfig/UniqueValueConflict.xml | 16 + .../publish/files/badconfig/badHttp.xml | 18 + .../publish/files/badconfig/badLogging.xml | 13 + .../publish/files/badconfig/goodConfig.xml | 12 + .../publish/files/childalias/server.xml | 42 + .../publish/files/childalias/serverB.xml | 44 + .../publish/files/childalias/serverC.xml | 46 + .../publish/files/childalias/serverC2.xml | 41 + .../publish/files/childalias/serverC3.xml | 44 + .../publish/files/childalias/serverC4.xml | 44 + .../publish/files/childalias/serverC5.xml | 42 + .../publish/files/childalias/serverC6.xml | 44 + .../publish/files/childalias/serverC7.xml | 44 + .../publish/files/dropins/aBrokenFile.xml | 1 + .../publish/files/dropins/alibrary.xml | 3 + .../publish/files/dropins/blibrary.xml | 3 + .../publish/files/dropins/simple.notxml | 3 + .../publish/files/dropins/simple.xml | 3 + .../publish/files/dropins/simple2.xml | 3 + .../publish/files/extensions/server.xml | 29 + .../publish/files/extensions/serverB1.xml | 13 + .../publish/files/extensions/serverB2.xml | 14 + .../extensions/serverSchemaGenerator.xml | 11 + .../files/featureRemove/serverRemoveJDBC.xml | 37 + .../featureRemove/serverRemoveOpenID.xml | 27 + .../bad-include-server-onError-ignore.xml | 28 + .../bad-include-server-onError-ignore2.xml | 33 + .../files/import.error/bad-include-server.xml | 27 + .../import.error/bad-include-server2.xml | 32 + .../bootstrap-onError-FAIL.properties | 4 + .../files/import.error/bootstrap.properties | 3 + .../files/import.error/malformed-server.xml | 23 + .../publish/files/import.error/original.xml | 21 + .../publish/files/import.error/server.xml | 23 + .../childAliasTest-1.0.mf | 6 + .../childAliasTestB-1.0.mf | 6 + .../childAliasTestC-1.0.mf | 6 + ...configExtensionsSchemaGeneratorTest-1.0.mf | 6 + .../configExtensionsTest-1.0.mf | 7 + .../configExtensionsTestB-1.0.mf | 7 + .../configfatlibertyinternals-1.0.mf | 12 + .../delayedVariable-1.0.mf | 6 + .../mergedConfigTest-1.0.mf | 6 + .../metatypeProviderTest-1.0.mf | 6 + .../publish/files/merge/allInOne.xml | 23 + .../publish/files/merge/break.xml | 11 + .../publish/files/merge/break2.xml | 12 + .../publish/files/merge/fourLevelIgnore.xml | 11 + .../publish/files/merge/fourLevelReplace.xml | 11 + .../publish/files/merge/ignore.xml | 11 + .../publish/files/merge/ignoreReplace.xml | 11 + .../publish/files/merge/merge.xml | 11 + .../publish/files/merge/replace.xml | 11 + .../publish/files/metatype/.gitignore | 1 + .../publish/files/metatype/metatype-1.0.mf | 7 + .../files/metatype/noMetatypeServer.xml | 20 + .../publish/files/metatype/server.xml | 21 + .../config/prod.ext.factory.pid.server.xml | 21 + .../config/prod.ext.invalid.server.xml | 22 + .../config/prod.ext.valid.server.xml | 21 + .../user.prod.ext.factory.pid.server.xml | 21 + .../config/user.prod.ext.invalid.server.xml | 22 + .../config/user.prod.ext.valid.server.xml | 21 + .../features/prodtest1-1.0.mf | 7 + .../features/userProdtest1-1.0.mf | 8 + .../propertiesFiles/testproduct.properties | 2 + .../publish/files/refresh/bad-server.xml | 5 + .../publish/files/refresh/server.xml | 27 + .../files/restart.var/bootstrap.properties | 3 + .../publish/files/restart/server.xml | 26 + .../publish/files/validator/.gitignore | 1 + .../publish/files/validator/bad-signature.xml | 32 + .../files/validator/dropins-enabled.xml | 33 + .../files/variable.error/missing-name.xml | 26 + .../files/variable.error/missing-name2.xml | 28 + .../files/variable.error/missing-value.xml | 26 + .../files/variable.error/missing-value2.xml | 28 + .../publish/files/varmerge/allInOne.xml | 8 + .../publish/files/varmerge/break.xml | 8 + .../publish/files/varmerge/break2.xml | 8 + .../publish/files/varmerge/ignore.xml | 9 + .../publish/files/varmerge/merge.xml | 9 + .../publish/files/varmerge/replace.xml | 9 + .../servers/com.ibm.ws.config.bad/server.xml | 18 + .../server.xml | 6 + .../com.ibm.ws.config.childalias/.gitignore | 1 + .../bootstrap.properties | 2 + .../com.ibm.ws.config.childalias/server.xml | 42 + .../com.ibm.ws.config.delayedVar/.gitignore | 1 + .../bootstrap.properties | 2 + .../com.ibm.ws.config.delayedVar/server.xml | 20 + .../com.ibm.ws.config.dropins/.gitignore | 1 + .../bootstrap.properties | 2 + .../com.ibm.ws.config.dropins/server.xml | 22 + .../bootstrap.properties | 1 + .../bootstrap.properties | 2 + .../com.ibm.ws.config.features/server.xml | 38 + .../com.ibm.ws.config.helper/.gitignore | 1 + .../bootstrap.properties | 2 + .../com.ibm.ws.config.helper/server.xml | 25 + .../com.ibm.ws.config.import.error/.gitignore | 1 + .../bootstrap.properties | 4 + .../common/common.xml | 7 + .../common/relative.xml | 3 + .../common/shared.xml | 5 + .../com.ibm.ws.config.import.error/server.xml | 21 + .../com.ibm.ws.config.import.error/shared.xml | 4 + .../com.ibm.ws.config.import/.gitignore | 1 + .../bootstrap.properties | 3 + .../common/common.xml | 7 + .../common/relative.xml | 3 + .../common/shared.xml | 5 + .../com.ibm.ws.config.import/server.xml | 16 + .../com.ibm.ws.config.import/shared.xml | 4 + .../bootstrap.properties | 2 + .../server.xml | 22 + .../server.xml | 24 + .../com.ibm.ws.config.merging/.gitignore | 1 + .../bootstrap.properties | 2 + .../com.ibm.ws.config.merging/common.xml | 22 + .../com.ibm.ws.config.merging/conflict.xml | 17 + .../com.ibm.ws.config.merging/fourLevelB.xml | 19 + .../com.ibm.ws.config.merging/fourLevelB2.xml | 9 + .../com.ibm.ws.config.merging/fourLevelC.xml | 4 + .../com.ibm.ws.config.merging/fourLevelC2.xml | 4 + .../intermediateReplace.xml | 18 + .../com.ibm.ws.config.merging/noConflict.xml | 13 + .../com.ibm.ws.config.merging/server.xml | 4 + .../.gitignore | 1 + .../bootstrap.properties | 2 + .../server.xml | 21 + .../bootstrap.properties | 2 + .../server.xml | 9 + .../.gitignore | 1 + .../bootstrap.properties | 2 + .../server.xml | 22 + .../com.ibm.ws.config.refresh/.gitignore | 1 + .../bootstrap.properties | 2 + .../com.ibm.ws.config.refresh/server.xml | 22 + .../com.ibm.ws.config.restart.var/.gitignore | 1 + .../bootstrap.properties | 3 + .../com.ibm.ws.config.restart.var/server.xml | 18 + .../com.ibm.ws.config.restart/.gitignore | 1 + .../bootstrap.properties | 2 + .../com.ibm.ws.config.restart/server.xml | 21 + .../.gitignore | 2 + .../bootstrap.properties | 20 + .../server.xml | 17 + .../server.xml | 19 + .../bootstrap.properties | 1 + .../com.ibm.ws.config.update.mbean/server.xml | 9 + .../bootstrap.properties | 1 + .../com.ibm.ws.config.update/server.xml | 9 + .../bootstrap.properties | 2 + .../common/common.xml | 7 + .../com.ibm.ws.config.validate/full.xml | 11 + .../com.ibm.ws.config.validate/server.xml | 22 + .../bootstrap.properties | 1 + .../server.xml | 10 + .../bootstrap.properties | 2 + .../com.ibm.ws.config.validator/server.xml | 33 + .../com.ibm.ws.config.varmerging/.gitignore | 1 + .../bootstrap.properties | 2 + .../com.ibm.ws.config.varmerging/common.xml | 19 + .../com.ibm.ws.config.varmerging/conflict.xml | 5 + .../noConflict.xml | 5 + .../com.ibm.ws.config.varmerging/server.xml | 4 + .../childalias/resources/META-INF/MANIFEST.MF | 3 + .../resources/META-INF/permissions.xml | 69 + .../childalias/resources/WEB-INF/web.xml | 15 + .../childalias/ChildAliasTestServlet.java | 443 ++ .../resources/META-INF/MANIFEST.MF | 3 + .../resources/META-INF/permissions.xml | 69 + .../confighelper/resources/WEB-INF/web.xml | 15 + .../WSConfigurationHelperTestServlet.java | 483 ++ .../dropins/resources/META-INF/MANIFEST.MF | 3 + .../resources/META-INF/permissions.xml | 69 + .../dropins/resources/WEB-INF/web.xml | 15 + .../config/dropins/ConfigDropinsServlet.java | 218 + .../mbeans/resources/META-INF/MANIFEST.MF | 3 + .../mbeans/resources/META-INF/permissions.xml | 69 + .../mbeans/resources/WEB-INF/web.xml | 16 + .../src/web/AppClientServletSchemaGen.java | 163 + .../resources/META-INF/MANIFEST.MF | 3 + .../resources/META-INF/permissions.xml | 69 + .../mergedconfig/resources/WEB-INF/web.xml | 15 + .../merged/MergedConfigTestServlet.java | 304 ++ .../metatype/resources/META-INF/MANIFEST.MF | 3 + .../resources/META-INF/permissions.xml | 69 + .../resources/OSGI-INF/metatype/metatype.xml | 27 + .../server/config/metatype/TestRunner.java | 7 + .../resources/META-INF/MANIFEST.MF | 3 + .../resources/META-INF/permissions.xml | 69 + .../resources/WEB-INF/web.xml | 15 + .../provider/MetatypeProviderTestServlet.java | 198 + .../restart/resources/META-INF/MANIFEST.MF | 3 + .../resources/META-INF/permissions.xml | 69 + .../restart/resources/WEB-INF/web.xml | 15 + .../restart/ConfigRestartTestServlet.java | 250 + .../varmerge/resources/META-INF/MANIFEST.MF | 3 + .../resources/META-INF/permissions.xml | 69 + .../varmerge/resources/WEB-INF/web.xml | 26 + .../merged/DelayedVariableTestServlet.java | 138 + .../config/merged/VarMergeTestServlet.java | 137 + .../test.config.childalias.b/bnd.bnd | 11 + .../resources/metatype-childalias-b.xml | 32 + .../test.config.childalias.c/bnd.bnd | 11 + .../resources/metatype-childalias-c.xml | 32 + .../test.config.childalias/bnd.bnd | 11 + .../resources/metatype-childalias.xml | 153 + .../test.config.extensions.b/bnd.bnd | 11 + .../resources/metatype-extensions-two.xml | 17 + .../bnd.bnd | 15 + .../schema/generator/GeneratorTest.java | 59 + .../test.config.extensions/bnd.bnd | 27 + .../resources/metatype-extensions.xml | 147 + .../extensions/ConfigPropertiesProvider.java | 26 + .../config/extensions/ExtensionsTest.java | 90 + .../config/extensions/TestResultsServlet.java | 102 + .../test.config.variables/bnd.bnd | 12 + .../OSGI-INF/metatype/metatype-variables.xml | 19 + .../test-bundles/test.merged.config/bnd.bnd | 15 + .../metatype/metatype-mergedconfig.xml | 118 + .../OSGI-INF/wlp/defaultInstances.xml | 3 + .../OSGI-INF/wlp/defaultInstances2.xml | 8 + .../OSGI-INF/wlp/defaultInstances3.xml | 5 + .../test.metatype.provider/bnd.bnd | 16 + .../ws/config/metatype/provider/Animal.java | 157 + .../metatype/provider/AnimalNameAttr.java | 116 + .../config/metatype/provider/AnimalToo.java | 57 + .../ws/config/metatype/provider/Plant.java | 89 + .../metatype/provider/PlantNameAttr.java | 111 + .../provider/PlantObjectClassDefinition.java | 77 + .../test-bundles/test.prod.extensions/bnd.bnd | 24 + .../resources/metatype.xml | 26 + .../prod/extensions/ProductExtension1.java | 40 + .../ProductExtension1TestServlet.java | 124 + .../ProductExtension1ServiceImpl.java | 85 + .../test.user.prod.extensions/bnd.bnd | 24 + .../resources/metatype.xml | 26 + .../extensions/UserProductExtension1.java | 40 + .../UserProductExtension1TestServlet.java | 123 + .../UserProductExtension1ServiceImpl.java | 77 + .../test/logging.properties | 76 + .../validator.exclude.xml | 1 + .../.classpath | 7 + .../.classpath.gradle | 7 + .../.gitignore | 2 + .../.project | 23 + .../org.eclipse.core.resources.prefs | 4 + .../.settings/org.eclipse.jdt.core.prefs | 286 ++ .../.settings/org.eclipse.jdt.ui.prefs | 117 + .../bnd.bnd | 35 + .../build.gradle | 0 .../build.xml | 57 + .../findbugs.exclude.xml | 176 + .../legal/copyright.properties | 13 + ...vax.management.remote.JMXConnectorProvider | 1 + .../FileTransferClientMessages.nlsprops | 55 + .../FileTransferClientMessages_cs.nlsprops | 55 + .../FileTransferClientMessages_de.nlsprops | 55 + .../FileTransferClientMessages_es.nlsprops | 55 + .../FileTransferClientMessages_fr.nlsprops | 55 + .../FileTransferClientMessages_hu.nlsprops | 55 + .../FileTransferClientMessages_it.nlsprops | 55 + .../FileTransferClientMessages_ja.nlsprops | 55 + .../FileTransferClientMessages_ko.nlsprops | 55 + .../FileTransferClientMessages_pl.nlsprops | 55 + .../FileTransferClientMessages_pt_BR.nlsprops | 55 + .../FileTransferClientMessages_ro.nlsprops | 55 + .../FileTransferClientMessages_ru.nlsprops | 55 + .../FileTransferClientMessages_zh.nlsprops | 55 + .../FileTransferClientMessages_zh_TW.nlsprops | 55 + .../resources/RESTClientMessages.nlsprops | 146 + .../resources/RESTClientMessages_cs.nlsprops | 146 + .../resources/RESTClientMessages_de.nlsprops | 145 + .../resources/RESTClientMessages_es.nlsprops | 146 + .../resources/RESTClientMessages_fr.nlsprops | 146 + .../resources/RESTClientMessages_hu.nlsprops | 146 + .../resources/RESTClientMessages_it.nlsprops | 146 + .../resources/RESTClientMessages_ja.nlsprops | 146 + .../resources/RESTClientMessages_ko.nlsprops | 144 + .../resources/RESTClientMessages_pl.nlsprops | 146 + .../RESTClientMessages_pt_BR.nlsprops | 146 + .../resources/RESTClientMessages_ro.nlsprops | 146 + .../resources/RESTClientMessages_ru.nlsprops | 146 + .../resources/RESTClientMessages_zh.nlsprops | 144 + .../RESTClientMessages_zh_TW.nlsprops | 143 + .../restConnector-headers.bnd | 9 + .../restConnector.bnd | 8 + .../jmx/connector/rest/ConnectorSettings.java | 283 ++ .../jmx/connector/rest/package-info.java | 16 + .../connector/client/rest/ClientProvider.java | 58 + .../client/rest/internal/Activator.java | 59 + .../client/rest/internal/ClientConstants.java | 43 + .../client/rest/internal/Connector.java | 619 +++ .../client/rest/internal/DynamicURL.java | 45 + .../rest/internal/FileTransferClient.java | 619 +++ .../internal/NotificationListenerEntry.java | 71 + .../rest/internal/NotificationRegistry.java | 907 ++++ .../rest/internal/ObjectIdentityCache.java | 78 + .../internal/RESTMBeanServerConnection.java | 2465 +++++++++ .../ServerNotificationListenerEntry.java | 62 + .../client/rest/internal/package-info.java | 17 + .../FileTransferClientMessagesUtil.java | 48 + .../resources/RESTClientMessagesUtil.java | 75 + .../connector/client/rest/package-info.java | 16 + .../connector/converter/JSONConverter.java | 4418 +++++++++++++++++ .../converter/NotificationRecord.java | 52 + .../NotificationTargetInformation.java | 120 + .../converter/SerializationHelper.java | 20 + .../jmx/connector/converter/package-info.java | 17 + .../datatypes/ConversionException.java | 24 + .../jmx/connector/datatypes/CreateMBean.java | 21 + .../jmx/connector/datatypes/Invocation.java | 20 + .../connector/datatypes/JMXServerInfo.java | 20 + .../connector/datatypes/MBeanInfoWrapper.java | 25 + .../jmx/connector/datatypes/MBeanQuery.java | 24 + .../connector/datatypes/NotificationArea.java | 19 + .../datatypes/NotificationRegistration.java | 23 + .../datatypes/NotificationSettings.java | 17 + .../datatypes/ObjectInstanceWrapper.java | 22 + .../ServerNotificationRegistration.java | 27 + .../jmx/connector/datatypes/package-info.java | 17 + dev/com.ibm.ws.jmx_fat/.classpath | 7 + dev/com.ibm.ws.jmx_fat/.classpath.gradle | 7 + dev/com.ibm.ws.jmx_fat/.gitignore | 1 + dev/com.ibm.ws.jmx_fat/.project | 23 + .../org.eclipse.core.resources.prefs | 4 + .../.settings/org.eclipse.jdt.core.prefs | 280 ++ .../.settings/org.eclipse.jdt.ui.prefs | 62 + dev/com.ibm.ws.jmx_fat/bnd.bnd | 28 + dev/com.ibm.ws.jmx_fat/bnd.bnd.gradle | 28 + dev/com.ibm.ws.jmx_fat/build-test.xml | 18 + dev/com.ibm.ws.jmx_fat/build.gradle | 0 dev/com.ibm.ws.jmx_fat/delivery.sets | 1 + .../src/com/ibm/ws/jmx/fat/AttachSupport.java | 128 + .../com/ibm/ws/jmx/fat/ClientConnector.java | 60 + .../fat/src/com/ibm/ws/jmx/fat/FATSuite.java | 22 + .../fat/src/com/ibm/ws/jmx/fat/JMXTest.java | 239 + .../com/ibm/ws/jmx/fat/LocalConnector.java | 105 + .../attach/ForwardingInvocationHandler.java | 45 + .../ibm/ws/jmx/fat/attach/ObjectProxy.java | 21 + .../attach/VirtualMachineDescriptorProxy.java | 25 + .../jmx/fat/attach/VirtualMachineProxy.java | 44 + .../fat/attach/VirtualMachineProxyHelper.java | 153 + dev/com.ibm.ws.jmx_fat/publish/.gitignore | 2 + .../publish/features/jmxtest-1.0.mf | 8 + .../com.ibm.ws.jmx.fat/bootstrap.properties | 5 + .../servers/com.ibm.ws.jmx.fat/server.xml | 8 + .../test-bundles/test-mbeans/bnd.bnd | 51 + .../com/ibm/ws/jmx/test/fat/BeanCounter.java | 94 + .../ws/jmx/test/fat/DelayedMbeanTester.java | 102 + .../jmx/test/fat/DelayedMbeanTesterMBean.java | 25 + .../ibm/ws/jmx/test/fat/Messages.properties | 4 + .../ibm/ws/jmx/test/fat/ServerConnector.java | 161 + .../src/com/ibm/ws/jmx/test/fat/TestBean.java | 97 + .../com/ibm/ws/jmx/test/fat/TestBean1.java | 21 + .../com/ibm/ws/jmx/test/fat/TestBean2.java | 25 + .../com/ibm/ws/jmx/test/fat/TestBean3.java | 25 + .../com/ibm/ws/jmx/test/fat/package-info.java | 19 + dev/com.ibm.ws.kernel.boot_fat/.classpath | 7 + .../.classpath.gradle | 7 + dev/com.ibm.ws.kernel.boot_fat/.gitignore | 5 + dev/com.ibm.ws.kernel.boot_fat/.project | 23 + .../org.eclipse.core.resources.prefs | 4 + .../.settings/org.eclipse.jdt.core.prefs | 286 ++ .../.settings/org.eclipse.jdt.ui.prefs | 117 + dev/com.ibm.ws.kernel.boot_fat/bnd.bnd | 28 + dev/com.ibm.ws.kernel.boot_fat/bnd.bnd.gradle | 28 + dev/com.ibm.ws.kernel.boot_fat/build-test.xml | 20 + dev/com.ibm.ws.kernel.boot_fat/build.gradle | 0 dev/com.ibm.ws.kernel.boot_fat/delivery.sets | 1 + .../src/com/ibm/ws/kernel/boot/FATSuite.java | 59 + .../ibm/ws/kernel/boot/OnlyRunOnWinRule.java | 41 + .../ws/kernel/boot/ServerClasspathTest.java | 84 + .../kernel/boot/ServerStartAsServiceTest.java | 140 + .../boot/ServerStartJVMOptionsTest.java | 457 ++ .../ibm/ws/kernel/boot/ServerStartTest.java | 153 + .../com/ibm/ws/kernel/boot/ShutdownTest.java | 101 + .../boot/commandline/CreateCommandTest.java | 78 + .../boot/commandline/DumpCommandTest.java | 154 + .../commandline/PauseResumeCommandTest.java | 158 + .../boot/commandline/StartCommandTest.java | 90 + .../commandport/ServerCommandPortTest.java | 243 + .../commands/LogLevelPropertyTest.java | 122 + .../internal/commands/PackageCommandTest.java | 171 + .../kernel/provisioning/KernelChangeTest.java | 80 + .../kernel/provisioning/ProvisioningTest.java | 700 +++ ...ServerAddProductExtensionMultipleTest.java | 203 + ...EmbeddedServerAddProductExtensionTest.java | 203 + .../embeddable/EmbeddedServerDriver.java | 609 +++ .../kernel/embeddable/EmbeddedServerTest.java | 265 + .../applications/SharedLooseEAR.ear.xml | 18 + ...InterimFixesTestBundle1_1.0.0.20130101.jar | Bin 0 -> 797 bytes ...visioningInterimFixesTestBundle1_1.0.0.jar | Bin 0 -> 769 bytes ...InterimFixesTestBundle2_1.0.0.20130101.jar | Bin 0 -> 796 bytes ...visioningInterimFixesTestBundle2_1.0.0.jar | Bin 0 -> 768 bytes ...InterimFixesTestBundle3_1.0.0.20130101.jar | Bin 0 -> 796 bytes ...visioningInterimFixesTestBundle3_1.0.0.jar | Bin 0 -> 769 bytes ...InterimFixesTestBundle4_1.0.0.20130101.jar | Bin 0 -> 792 bytes ...visioningInterimFixesTestBundle4_1.0.0.jar | Bin 0 -> 769 bytes .../files/ProvisioningTestBundle_1.0.0.jar | Bin 0 -> 2300 bytes ...TestBundle_1.0.1.201202020001-APAR0001.jar | Bin 0 -> 2331 bytes ...TestBundle_1.0.1.201203030001-APAR0002.jar | Bin 0 -> 2337 bytes ...Bundle_1.0.1.201204040001-TestAPAR0001.jar | Bin 0 -> 2331 bytes .../files/ProvisioningTestBundle_1.0.1.jar | Bin 0 -> 2300 bytes .../files/ProvisioningTestBundle_1.0.100.jar | Bin 0 -> 2302 bytes ...TestBundle_1.0.2.201201010001-APAR0001.jar | Bin 0 -> 2332 bytes .../files/ProvisioningTestBundle_1.0.2.jar | Bin 0 -> 2299 bytes .../files/ProvisioningTestBundle_1.0.99.jar | Bin 0 -> 2302 bytes .../publish/files/Xfuture/jvm.options | 1 + .../publish/files/Xfuture/server.xml | 11 + .../publish/files/interimFixesServer.xml | 12 + .../publish/files/marker | 1 + .../files/provisioningInterimFixTest-1.0.mf | 6 + .../files/provisioningInterimFixesTest-1.0.mf | 9 + .../publish/files/provisioningTest-1.0.mf | 6 + .../publish/files/service.fingerprint | 1 + .../publish/files/singleInterimFixServer.xml | 12 + .../templateTestAbsolute.properties | 1 + .../templateTestRelative.properties | 1 + .../templates/clients/template2/client.xml | 7 + .../templates/servers/templateTest/server.xml | 14 + .../earContent/META-INF/application.xml | 16 + .../testUtil/classes/META-INF/MANIFEST.MF | 3 + .../testWeb0/WebContent/META-INF/MANIFEST.MF | 2 + .../looseConfig/testWeb0/WebContent/index.jsp | 12 + .../testWeb1/WebContent/META-INF/MANIFEST.MF | 2 + .../looseConfig/testWeb1/WebContent/index.jsp | 12 + .../utils/classes/META-INF/MANIFEST.MF | 3 + .../bootstrap.properties | 1 + .../dropins/snoop.war | Bin 0 -> 7238 bytes .../ServerStartAsServiceTest/server.xml | 12 + .../apps/Apps Loose Web.war.xml | 15 + .../apps/AppsLooseWeb-InvalidRelPaths.war.xml | 15 + .../apps/AppsLooseWeb-RelPaths.war.xml | 15 + .../apps/AppsLooseWeb-Signed.war.xml | 16 + .../apps/AppsLooseWeb.war.xml | 15 + .../bootstrap.properties | 5 + .../dropins/DropinsLooseWeb.ear.xml | 7 + .../com.ibm.ws.kernel.boot.bvt/server.xml | 10 + .../.gitignore | 1 + .../bootstrap.properties | 5 + .../server.xml | 9 + .../.gitignore | 1 + .../bootstrap.properties | 2 + .../server.xml | 6 + .../server.xml | 3 + .../bootstrap.properties | 2 + .../com.ibm.ws.kernel.boot.env.bvt/server.xml | 11 + .../server.xml | 3 + .../server.xml | 3 + .../bootstrap.properties | 5 + .../bootstrap.properties.hpel | 7 + .../server.xml | 4 + .../bootstrap.properties | 2 + .../server.xml | 6 + .../bootstrap.properties | 1 + .../server.xml | 9 + .../bootstrap.properties | 1 + .../server.xml | 12 + .../com.ibm.ws.kernel.shutdown.fat/.gitignore | 1 + .../bootstrap.properties | 2 + .../com.ibm.ws.kernel.shutdown.fat/server.xml | 7 + .../bootstrap.properties | 2 + .../dropins/simpleApp.war/index.jsp | 3 + .../lib/com.ibm.ws.prodtest.internal_1.0.jar | Bin 0 -> 1719 bytes .../producttest/lib/features/prodtest-1.0.mf | 6 + .../server.xml | 12 + .../bootstrap.properties | 2 + .../dropins/simpleApp.war/index.jsp | 3 + .../lib/com.ibm.ws.prodtest.internal_1.0.jar | Bin 0 -> 1719 bytes .../producttest/lib/features/prodtest-1.0.mf | 6 + .../lib/com.ibm.ws.prodtest.internal_1.0.jar | Bin 0 -> 1719 bytes .../lib/features/prodtestb-1.0.mf | 6 + .../server.xml | 13 + .../bootstrap.properties | 2 + .../dropins/simpleApp.war/index.jsp | 3 + .../server.xml | 11 + .../servers/embed_me/bootstrap.properties | 2 + .../publish/servers/embed_me/server.xml | 10 + .../CheckJvmAppClasspathPackagesBean.java | 42 + .../test-applications/shutdownfat/.gitignore | 1 + .../kernel/boot/fat/ShutdownTestServlet.java | 46 + dev/com.ibm.ws.kernel.boot_test/.classpath | 7 + .../.classpath.gradle | 7 + dev/com.ibm.ws.kernel.boot_test/.gitignore | 5 + dev/com.ibm.ws.kernel.boot_test/.project | 23 + .../org.eclipse.core.resources.prefs | 4 + .../.settings/org.eclipse.jdt.core.prefs | 286 ++ .../.settings/org.eclipse.jdt.ui.prefs | 117 + dev/com.ibm.ws.kernel.boot_test/bnd.bnd | 21 + .../bnd.bnd.gradle | 21 + .../build-unittest.xml | 70 + dev/com.ibm.ws.kernel.boot_test/build.gradle | 0 dev/com.ibm.ws.kernel.boot_test/delivery.sets | 1 + dev/com.ibm.ws.kernel.boot_test/launch.bnd | 9 + .../resources/Factory.empty | 0 .../resources/packages.list | 1 + .../serverDefaults/bootstrap.properties | 15 + .../resources/serverDefaults/server.cfg | 21 + .../system-packages_1.6.0.properties | 3 + .../system-packages_1.7.0.properties | 3 + .../system-packages_1.8.0.properties | 3 + dev/com.ibm.ws.kernel.boot_test/simple.bnd | 13 + dev/com.ibm.ws.kernel.boot_test/simple2.bnd | 21 + dev/com.ibm.ws.kernel.boot_test/simple3.bnd | 13 + dev/com.ibm.ws.kernel.boot_test/simple4.bnd | 13 + dev/com.ibm.ws.kernel.boot_test/simple5.bnd | 13 + .../ws/kernel/boot/BootstrapConfigTest.java | 782 +++ .../ws/kernel/boot/LaunchArgumentsTest.java | 318 ++ .../com/ibm/ws/kernel/boot/LauncherTest.java | 205 + .../ws/kernel/boot/SharedBootstrapConfig.java | 72 + .../boot/internal/BootstrapManifestTest.java | 291 ++ .../kernel/boot/internal/FileUtilsTest.java | 260 + .../boot/internal/FrameworkManagerTest.java | 280 ++ .../boot/internal/KernelResolverTest.java | 168 + .../kernel/boot/internal/ServerLockTest.java | 263 + .../boot/internal/ServerRunningTest.java | 131 + .../ws/kernel/boot/internal/TimeoutRule.java | 89 + .../internal/commands/DumpProcessorTest.java | 109 + .../FolderStructureGeneratorTest.java | 59 + .../commands/PackageProcessorTest.java | 133 + .../framework/BasicLauncherDelegate.java | 22 + .../internal/framework/BasicLogProvider.java | 30 + .../jmx/internal/MBeanServerPipelineTest.java | 185 + .../PlatformMBeanServerDelegateTest.java | 31 + .../boot/security/WLPDynamicPolicyTest.java | 163 + .../classloader/JarFileClassLoaderTest.java | 217 + .../ws/kernel/internal/reference/Handler.java | 39 + .../internal/FrameworkConfigurationTest.java | 40 + .../internal/FrameworkManagerTimeTest.java | 276 + .../internal/LibertyProcessImplTest.java | 84 + .../NoRethrowSecurityManagerTest.java | 159 + .../launch/internal/ProvisionerTest.java | 527 ++ .../LocalBundleRepositoryTest.java | 146 + .../provisioining/ServiceFingerprintTest.java | 152 + .../unittest/src/test/shared/Constants.java | 52 + .../src/test/shared/DumpTimerRule.java | 91 + .../unittest/src/test/shared/TestUtils.java | 141 + .../unittest/test data/dump/lib/md5-2.txt | 1 + .../unittest/test data/dump/md5-1.txt | 1 + .../unittest/test data/dump/usr/ignored.txt | 1 + .../unittest/test data/lbr/dev/a.b_1.0.2.mf | 3 + .../unittest/test data/lbr/dev/bad.jar | Bin 0 -> 373 bytes .../unittest/test data/lbr/lib/a.b_1.0.0.jar | Bin 0 -> 373 bytes .../unittest/test data/lbr/lib/a.b_1.0.0.mf | 3 + .../unittest/test data/lbr/lib/a.b_1.0.1.jar | Bin 0 -> 375 bytes .../unittest/test data/lbr/lib/a.b_1.0.1.mf | 3 + .../test data/lbr/lib/a.b_1.0.1.v1.jar | Bin 0 -> 404 bytes .../test data/lbr/lib/a.b_1.0.1.v1.mf | 4 + .../test data/lbr/lib/a.b_1.0.1.v2.jar | Bin 0 -> 398 bytes .../test data/lbr/lib/a.b_1.0.1.v2.mf | 4 + .../test data/lbr/lib/a.b_1.0.100.jar | Bin 0 -> 376 bytes .../unittest/test data/lbr/lib/a.b_1.0.100.mf | 3 + .../test data/lbr/lib/a.b_1.0.2.v1.jar | Bin 0 -> 399 bytes .../test data/lbr/lib/a.b_1.0.2.v1.mf | 4 + .../unittest/test data/lbr/lib/a.b_1.0.jar | Bin 0 -> 387 bytes .../unittest/test data/lbr/lib/a.b_1.0.mf | 3 + .../unittest/test data/lbr/lib/dummy.jar | Bin 0 -> 1756 bytes .../lbr/lib/platform/binaryLogging-1.0.mf | 15 + .../lbr/lib/platform/defaultLogging-1.0.mf | 12 + .../lbr/lib/platform/emptyLogging-1.0.mf | 9 + .../lbr/lib/platform/extension-1.0.mf | 8 + .../test data/lbr/lib/platform/kernel-1.0.mf | 64 + .../lbr/lib/platform/kernelCore-1.0.mf | 13 + .../lbr/lib/platform/kernelCoreMissing-1.0.mf | 10 + .../lbr/lib/platform/missingJar-1.0.mf | 10 + .../test data/lbr/lib/rebuildjars.bat | 15 + .../unittest/test data/lbr/lib/x.y_1.0.jar | Bin 0 -> 371 bytes .../unittest/test data/lbr/lib/x.y_1.0.mf | 3 + .../test data/lib/platform/include.properties | 3 + .../test data/lib/platform/peer.properties | 2 + .../lib/platform/relative.properties | 2 + .../lib/platform/testDefNoEquals.map | 2 + .../WebSphereApplicationServer.properties | 7 + .../test data/nonIFixLBR/lib/a.b_1.0.0.jar | Bin 0 -> 371 bytes .../test data/nonIFixLBR/lib/a.b_1.0.1.jar | Bin 0 -> 373 bytes .../test data/nonIFixLBR/lib/a.b_1.0.100.jar | Bin 0 -> 374 bytes .../test data/nonIFixLBR/lib/a.b_1.0.jar | Bin 0 -> 369 bytes .../test data/nonIFixLBR/lib/x.y_1.0.jar | Bin 0 -> 369 bytes .../test data/resources/resources1.jar | Bin 0 -> 736 bytes .../test data/resources/resources2.jar | Bin 0 -> 736 bytes .../unittest/test data/signed/bad.jar | Bin 0 -> 10323 bytes .../bnd.bnd.gradle | 1 + .../.classpath | 7 + .../.classpath.gradle | 7 + .../.gitignore | 2 + .../.project | 23 + .../org.eclipse.core.resources.prefs | 4 + .../.settings/org.eclipse.jdt.core.prefs | 280 ++ .../.settings/org.eclipse.jdt.ui.prefs | 113 + dev/com.ibm.ws.kernel.filemonitor_fat/bnd.bnd | 16 + .../bnd.bnd.gradle | 16 + .../build-test.xml | 18 + .../build.gradle | 0 .../delivery.sets | 1 + .../fat/AbstractNotificationTest.java | 291 ++ .../ws/kernel/filemonitor/fat/FATSuite.java | 25 + .../filemonitor/fat/FileMonitorTest.java | 1022 ++++ .../fat/FileNotificationMBeanTest.java | 778 +++ .../kernel/filemonitor/fat/MonitorReader.java | 223 + .../publish/.gitignore | 1 + .../features/monitoringPrintingFeature-1.0.mf | 7 + .../bootstrap.properties | 1 + .../server.xml | 15 + .../bnd.bnd | 14 + .../FileMonitorPrintingImplementation.java | 56 + .../test/FileMonitorRegistrationHandler.java | 204 + .../.classpath | 7 + .../.classpath.gradle | 7 + .../.gitignore | 1 + .../.project | 23 + .../org.eclipse.core.resources.prefs | 4 + .../.settings/org.eclipse.jdt.core.prefs | 281 ++ .../.settings/org.eclipse.jdt.ui.prefs | 62 + .../bnd.bnd | 12 + .../bnd.bnd.gradle | 12 + .../build-test.xml | 13 + .../build.gradle | 0 .../delivery.sets | 1 + .../kernel/metatype/helper/fat/FATTest.java | 370 ++ .../files/config_change_fileset/server.xml | 7 + .../publish/files/fileset_list/server.xml | 7 + .../filesetfatlibertyinternals-1.0.mf | 7 + .../files/monitored_fileset/server.xml | 7 + .../publish/files/test3.jar | Bin 0 -> 427 bytes .../files/unmonitored_fileset/server.xml | 7 + .../.gitignore | 2 + .../bootstrap.properties | 5 + ...om.ibm.ws.kernel.metatype.helperServer.xml | 12 + .../resources/fileset_test_bundles/repo.xml | 0 .../resources/fileset_test_bundles/test.txt | 0 .../resources/fileset_test_bundles/test1.jar | 0 .../resources/fileset_test_bundles/test2.jar | 0 .../test_subfolder/test4.jar | 0 .../fileset/resources/WEB-INF/web.xml | 22 + .../helper/test/app/FilesetTestServlet.java | 82 + .../.classpath | 7 + .../.classpath.gradle | 7 + .../.gitignore | 1 + .../.project | 23 + .../org.eclipse.core.resources.prefs | 4 + .../.settings/org.eclipse.jdt.core.prefs | 281 ++ .../.settings/org.eclipse.jdt.ui.prefs | 62 + .../bnd.bnd | 20 + .../bnd.bnd.gradle | 20 + .../build-unittest.xml | 6 + .../build.gradle | 0 .../delivery.sets | 1 + .../internal/AbstractFilesetTestHelper.java | 187 + .../internal/FilesetNameFilterTest.java | 346 ++ .../wsspi/config/internal/FilesetTest.java | 238 + dev/com.ibm.ws.logging.hpel_fat/.classpath | 7 + .../.classpath.gradle | 7 + dev/com.ibm.ws.logging.hpel_fat/.gitignore | 1 + dev/com.ibm.ws.logging.hpel_fat/.project | 23 + .../org.eclipse.core.resources.prefs | 4 + .../.settings/org.eclipse.jdt.core.prefs | 280 ++ .../.settings/org.eclipse.jdt.ui.prefs | 62 + dev/com.ibm.ws.logging.hpel_fat/bnd.bnd | 15 + .../bnd.bnd.gradle | 15 + .../build-test.xml | 20 + dev/com.ibm.ws.logging.hpel_fat/build.gradle | 0 dev/com.ibm.ws.logging.hpel_fat/delivery.sets | 1 + .../com/ibm/ws/fat/hpel/setup/HpelSetup.java | 281 ++ .../com/ibm/ws/fat/hpel/suites/FATSuite.java | 105 + .../ibm/ws/fat/hpel/tests/BinaryLogExec.java | 496 ++ .../tests/BinaryLogRecordContextTest.java | 151 + .../tests/ConcurrentLoggingAccuracyTest.java | 277 ++ .../HPELDataDirFalsePositiveWarningTest.java | 129 + .../HPELLogDirectoryPurgeMaxSizeTest.java | 146 + .../hpel/tests/HPELPurgeMaxSizeErrorTest.java | 116 + .../tests/HpelDeleteEmptyDirectories.java | 312 ++ .../tests/HpelLogDirectoryChangeTest.java | 149 + .../tests/HpelLoggingElementDeleteTest.java | 212 + .../tests/HpelPurgeMaxSizeBackupFileTest.java | 195 + .../tests/HpelPurgeMaxSizeIgnoreTest_1.java | 501 ++ .../tests/HpelPurgeMaxSizeIgnoreTest_2.java | 168 + .../fat/hpel/tests/HpelTextLogRetention.java | 213 + .../ibm/ws/fat/hpel/tests/LogViewerExec.java | 347 ++ .../tests/TraceSpecificationSetToAllTest.java | 150 + .../hpel/tests/VerifyRepositoryAccuracy.java | 337 ++ .../com/ibm/ws/fat/ras/util/CommonTasks.java | 1036 ++++ .../lib/fat.harness.jar | Bin 0 -> 80237 bytes .../lib/htmlunit-2.4.jar | Bin 0 -> 724012 bytes .../lib/phased.junit.jar | Bin 0 -> 24864 bytes .../files/server-HPELDeleteLogDirectory_1.xml | 12 + .../files/server-HPELDeleteLogDirectory_2.xml | 12 + .../files/server-HPELPurgeMaxSizeInvalid.xml | 12 + .../files/server-HPELPurgeMaxSizeTest_1.xml | 12 + .../files/server-HPELPurgeMaxSizeTest_2.xml | 12 + .../files/server-HPELPurgeMaxSizeTest_3.xml | 12 + .../files/server-HPELPurgeMaxSizeTest_4.xml | 13 + .../files/server-HPELPurgeMaxSizeTest_5.xml | 14 + .../files/server-HPELPurgeMaxSizeTest_6.xml | 12 + .../files/server-HPELPurgeMaxSizeTest_7.xml | 11 + .../files/server-HPELPurgeMinTimeTest_1.xml | 14 + .../files/server-HPELPurgeMinTimeTest_2.xml | 13 + .../server-HpelDeleteEmptyDirectories.xml | 14 + .../server-HpelDirChangePurgeMaxTest_1.xml | 13 + .../server-HpelDirChangePurgeMaxTest_2.xml | 13 + .../files/server-HpelLogDirectoryChange_1.xml | 11 + .../files/server-HpelLogDirectoryChange_2.xml | 11 + .../files/server-HpelLogElementDelete_1.xml | 14 + .../files/server-HpelLogElementDelete_2.xml | 11 + .../files/server-HpelTextLogRetention.xml | 13 + .../server-TraceSpecificationSetToAllTest.xml | 9 + .../publish/servers/HpelServer/.gitignore | 1 + .../servers/HpelServer/bootstrap.properties | 3 + .../publish/servers/HpelServer/server.xml | 9 + .../HpelFat/resources/LogCreator.jsp | 136 + .../resources/META-INF/permissions.xml | 14 + .../HpelFat/resources/WEB-INF/web.xml | 22 + .../hpel/handlers/MyCustomHandler.java | 11 + .../hpel_fat/WritingCustomLogServlet.java | 80 + .../LogFat/resources/META-INF/permissions.xml | 14 + .../LogFat/resources/WEB-INF/web.xml | 30 + .../com/ibm/ws/logging/hpel/LRCServlet.java | 39 + .../com/ibm/ws/test/LogDecoratorFilter.java | 145 + .../ws/test/ThreadLocalStringExtension.java | 30 + dev/com.ibm.ws.logging_fat/.classpath | 7 + dev/com.ibm.ws.logging_fat/.classpath.gradle | 7 + dev/com.ibm.ws.logging_fat/.gitignore | 1 + dev/com.ibm.ws.logging_fat/.project | 23 + .../org.eclipse.core.resources.prefs | 4 + .../.settings/org.eclipse.jdt.core.prefs | 280 ++ .../.settings/org.eclipse.jdt.ui.prefs | 113 + dev/com.ibm.ws.logging_fat/bnd.bnd | 28 + dev/com.ibm.ws.logging_fat/bnd.bnd.gradle | 28 + dev/com.ibm.ws.logging_fat/build-test.xml | 36 + dev/com.ibm.ws.logging_fat/build.gradle | 0 dev/com.ibm.ws.logging_fat/delivery.sets | 1 + .../fat/AbstractStackTraceFilteringTest.java | 105 + .../src/com/ibm/ws/logging/fat/FATSuite.java | 30 + .../ibm/ws/logging/fat/HealthCenterTest.java | 48 + .../fat/InvalidTraceSpecificationTest.java | 164 + .../ibm/ws/logging/fat/IsoDateFormatTest.java | 311 ++ ...FilteringForBadlyWrittenThrowableTest.java | 67 + ...ceFilteringForIBMFeatureExceptionTest.java | 78 + ...eringForLoggedExceptionParametersTest.java | 72 + ...ggedExceptionWithACauseParametersTest.java | 67 + ...eFilteringForNoClassDefFoundErrorTest.java | 85 + ...TraceFilteringForPrintedExceptionTest.java | 77 + ...rPrintedExceptionWithIBMCodeAtTopTest.java | 69 + ...gForSpecificationClassesExceptionTest.java | 73 + ...eFilteringForUserFeatureExceptionTest.java | 80 + .../ibm/ws/logging/fat/TestHideMessages.java | 90 + .../fat/TestHideMsgDefinedBootstrap.java | 62 + dev/com.ibm.ws.logging_fat/publish/.gitignore | 1 + .../features/unconfigurableIbmFeature-1.0.mf | 7 + .../features/unconfigurableUserFeature-1.0.mf | 7 + .../files/server-invalidIsoDateFormat.xml | 9 + .../publish/files/server-twomessageids.xml | 11 + .../.gitignore | 1 + .../bootstrap.properties | 1 + .../server.xml | 11 + .../.gitignore | 1 + .../bootstrap.properties | 1 + .../server.xml | 11 + .../bootstrap.properties | 1 + .../server.xml | 9 + .../bootstrap.properties | 2 + .../jvm.options | 1 + .../server.xml | 7 + .../com.ibm.ws.logging.hidemessage/server.xml | 9 + .../bootstrap.properties | 1 + .../server.xml | 7 + .../bootstrap.properties | 1 + .../server.xml | 8 + .../bootstrap.properties | 1 + .../server.xml | 9 + .../bootstrap.properties | 1 + .../com.ibm.ws.logging.tracespec/server.xml | 8 + .../broken-servlet/resources/.gitignore | 1 + .../resources/META-INF/MANIFEST.MF | 3 + .../ws/logging/fat/servlet/BrokenServlet.java | 44 + ...okenWithABadlyWrittenThrowableServlet.java | 50 + .../fat/servlet/BrokenWithACauseServlet.java | 52 + .../fat/servlet/ExceptionPrintingServlet.java | 70 + .../IBMCodeAtTopExceptionPrintingServlet.java | 49 + .../logging/fat/servlet/SpecUsingServlet.java | 65 + .../ffdc-servlet/resources/.gitignore | 1 + .../resources/META-INF/MANIFEST.MF | 3 + .../ws/logging/fat/servlet/FFDCServlet.java | 26 + .../logger-servlet/resources/.gitignore | 1 + .../resources/META-INF/MANIFEST.MF | 3 + .../ws/logging/fat/servlet/LoggerServlet.java | 24 + .../missing-feature-servlet/.gitignore | 1 + .../servlet/MissingEntityManagerServlet.java | 60 + .../bnd.bnd | 19 + .../resources/OSGI-INF/metatype/metatype.xml | 26 + .../ibmfeature/BrokenFeature.java | 50 + .../bnd.bnd | 18 + .../resources/OSGI-INF/metatype/metatype.xml | 26 + .../userfeature/BrokenFeature.java | 50 + .../.classpath.ant | 9 - .../.classpath | 7 + .../.classpath.gradle | 7 + .../.gitignore | 2 + .../.project | 23 + .../org.eclipse.core.resources.prefs | 4 + .../.settings/org.eclipse.jdt.core.prefs | 280 ++ .../.settings/org.eclipse.jdt.ui.prefs | 63 + dev/com.ibm.ws.org.glassfish.json_fat/bnd.bnd | 13 + .../bnd.bnd.gradle | 13 + .../build-test.xml | 41 + .../build.gradle | 0 .../delivery.sets | 1 + .../ws/org/glassfish/json/fat/FATSuite.java | 28 + .../json/fat/tests/AbstractTest.java | 145 + .../json/fat/tests/BasicJSONPTest.java | 85 + .../fat/tests/CustomFeatureJSONPTest.java | 49 + .../publish/.gitignore | 1 + .../features/customJsonpProvider-1.0.mf | 10 + .../.gitignore | 4 + .../bootstrap.properties | 2 + .../build.properties | 1 + .../server.xml | 17 + .../.gitignore | 2 + .../bootstrap.properties | 2 + .../server.xml | 10 + .../JSONPWAR.war/package.properties | 2 + .../resources/META-INF/permissions.xml | 20 + .../resources/WEB-INF/json_read_test_data.js | 6 + .../ws/jsonp/fat/AbstractJSONPServlet.java | 138 + .../ibm/ws/jsonp/fat/BuildJSONPServlet.java | 41 + .../ibm/ws/jsonp/fat/ReadJSONPServlet.java | 41 + .../ibm/ws/jsonp/fat/StreamJSONPServlet.java | 59 + .../ibm/ws/jsonp/fat/WriteJSONPServlet.java | 54 + .../resources/META-INF/permissions.xml | 20 + .../services/javax.json.spi.JsonProvider | 1 + .../ws/jsonp/app/provider/JsonParserImpl.java | 65 + .../jsonp/app/provider/JsonProviderImpl.java | 97 + .../customAppJSONPWAR.war/package.properties | 3 + .../resources/META-INF/permissions.xml | 20 + .../ws/jsonp/fat/CustomAppJSONPServlet.java | 42 + .../package.properties | 2 + .../resources/META-INF/permissions.xml | 20 + .../jsonp/fat/CustomFeatureJSONPServlet.java | 42 + .../resources/META-INF/permissions.xml | 20 + .../services/javax.json.spi.JsonProvider | 1 + .../ws/jsonp/lib/provider/JsonParserImpl.java | 65 + .../jsonp/lib/provider/JsonProviderImpl.java | 97 + .../customLibJSONPWAR.war/package.properties | 3 + .../resources/META-INF/permissions.xml | 20 + .../ws/jsonp/fat/CustomLibJSONPServlet.java | 42 + .../test-bundles/custom.jsonp/bnd.bnd | 25 + .../services/javax.json.spi.JsonProvider | 1 + .../feature/provider/JsonParserImpl.java | 65 + .../feature/provider/JsonProviderImpl.java | 97 + .../.classpath.ant | 6 - dev/com.ibm.ws.product.utility_bvt/bnd.bnd | 2 +- .../bnd.bnd.gradle | 2 +- dev/com.ibm.ws.product.utility_fat/.classpath | 7 + .../.classpath.gradle | 7 + dev/com.ibm.ws.product.utility_fat/.gitignore | 5 + dev/com.ibm.ws.product.utility_fat/.project | 23 + .../org.eclipse.core.resources.prefs | 4 + .../.settings/org.eclipse.jdt.core.prefs | 286 ++ .../.settings/org.eclipse.jdt.ui.prefs | 117 + dev/com.ibm.ws.product.utility_fat/bnd.bnd | 28 + .../bnd.bnd.gradle | 28 + .../build-test.xml | 13 + .../build.gradle | 0 .../delivery.sets | 1 + .../ibm/ws/product/utility/fat/FATSuite.java | 30 + .../fat/ProductInfoLicenseFileTest.java | 205 + .../utility/fat/ProductInfoToolTest.java | 126 + .../utility/fat/ProductInfoValidateTest.java | 67 + .../utility/fat/ProductToolTestCommon.java | 265 + .../utility/fat/ProductUtilToolTest.java | 53 + .../publish/features/usertest.esa | Bin 0 -> 1542 bytes .../usertest.with.versions.props.file.esa | Bin 0 -> 2151 bytes .../publish/files/lafiles/LA_cs | Bin 0 -> 57224 bytes .../publish/files/lafiles/LA_de | Bin 0 -> 73646 bytes .../publish/files/lafiles/LA_el | Bin 0 -> 75934 bytes .../publish/files/lafiles/LA_en | Bin 0 -> 113588 bytes .../publish/files/lafiles/LA_es | Bin 0 -> 68912 bytes .../publish/files/lafiles/LA_fr | Bin 0 -> 88336 bytes .../publish/files/lafiles/LA_in | Bin 0 -> 63082 bytes .../publish/files/lafiles/LA_it | Bin 0 -> 64426 bytes .../publish/files/lafiles/LA_ja | Bin 0 -> 23072 bytes .../publish/files/lafiles/LA_ko | Bin 0 -> 24138 bytes .../publish/files/lafiles/LA_lt | Bin 0 -> 54246 bytes .../publish/files/lafiles/LA_pl | Bin 0 -> 64574 bytes .../publish/files/lafiles/LA_pt | Bin 0 -> 60484 bytes .../publish/files/lafiles/LA_ru | Bin 0 -> 63082 bytes .../publish/files/lafiles/LA_sl | Bin 0 -> 54510 bytes .../publish/files/lafiles/LA_tr | Bin 0 -> 62848 bytes .../publish/files/lafiles/LA_zh | Bin 0 -> 17052 bytes .../publish/files/lafiles/LA_zh_TW | Bin 0 -> 17838 bytes .../publish/files/lafiles/LI_cs | Bin 0 -> 41244 bytes .../publish/files/lafiles/LI_de | Bin 0 -> 45776 bytes .../publish/files/lafiles/LI_el | Bin 0 -> 52838 bytes .../publish/files/lafiles/LI_en | Bin 0 -> 38310 bytes .../publish/files/lafiles/LI_es | Bin 0 -> 45406 bytes .../publish/files/lafiles/LI_fr | Bin 0 -> 48136 bytes .../publish/files/lafiles/LI_in | Bin 0 -> 44530 bytes .../publish/files/lafiles/LI_it | Bin 0 -> 42306 bytes .../publish/files/lafiles/LI_ja | Bin 0 -> 22666 bytes .../publish/files/lafiles/LI_ko | Bin 0 -> 23462 bytes .../publish/files/lafiles/LI_lt | Bin 0 -> 38580 bytes .../publish/files/lafiles/LI_pl | Bin 0 -> 44522 bytes .../publish/files/lafiles/LI_pt | Bin 0 -> 45178 bytes .../publish/files/lafiles/LI_ru | Bin 0 -> 44472 bytes .../publish/files/lafiles/LI_sl | Bin 0 -> 40140 bytes .../publish/files/lafiles/LI_tr | Bin 0 -> 44084 bytes .../publish/files/lafiles/LI_zh | Bin 0 -> 16422 bytes .../publish/files/lafiles/LI_zh_TW | Bin 0 -> 16796 bytes .../publish/files/lafiles/notices | Bin 0 -> 317160 bytes .../com.ibm.ws.prodtest.internal_1.0.jar | Bin 0 -> 1719 bytes .../files/productFeatures/prodtest-1.0.mf | 6 + .../productProperties/testproduct.properties | 2 + .../producttest.properties | 6 + .../usertest.properties | 6 + .../bootstrap.properties | 2 + .../bootstrap.properties | 2 + .../bootstrap.properties | 1 + .../resources/lafiles/LA_cs | Bin 0 -> 57224 bytes .../resources/lafiles/LA_de | Bin 0 -> 73646 bytes .../resources/lafiles/LA_el | Bin 0 -> 75934 bytes .../resources/lafiles/LA_en | Bin 0 -> 113588 bytes .../resources/lafiles/LA_es | Bin 0 -> 68912 bytes .../resources/lafiles/LA_fr | Bin 0 -> 88336 bytes .../resources/lafiles/LA_in | Bin 0 -> 63082 bytes .../resources/lafiles/LA_it | Bin 0 -> 64426 bytes .../resources/lafiles/LA_ja | Bin 0 -> 23072 bytes .../resources/lafiles/LA_ko | Bin 0 -> 24138 bytes .../resources/lafiles/LA_lt | Bin 0 -> 54246 bytes .../resources/lafiles/LA_pl | Bin 0 -> 64574 bytes .../resources/lafiles/LA_pt | Bin 0 -> 60484 bytes .../resources/lafiles/LA_ru | Bin 0 -> 63082 bytes .../resources/lafiles/LA_sl | Bin 0 -> 54510 bytes .../resources/lafiles/LA_tr | Bin 0 -> 62848 bytes .../resources/lafiles/LA_zh | Bin 0 -> 17052 bytes .../resources/lafiles/LA_zh_TW | Bin 0 -> 17838 bytes .../resources/lafiles/LI_cs | Bin 0 -> 41244 bytes .../resources/lafiles/LI_de | Bin 0 -> 45776 bytes .../resources/lafiles/LI_el | Bin 0 -> 52838 bytes .../resources/lafiles/LI_en | Bin 0 -> 38310 bytes .../resources/lafiles/LI_es | Bin 0 -> 45406 bytes .../resources/lafiles/LI_fr | Bin 0 -> 48136 bytes .../resources/lafiles/LI_in | Bin 0 -> 44530 bytes .../resources/lafiles/LI_it | Bin 0 -> 42306 bytes .../resources/lafiles/LI_ja | Bin 0 -> 22666 bytes .../resources/lafiles/LI_ko | Bin 0 -> 23462 bytes .../resources/lafiles/LI_lt | Bin 0 -> 38580 bytes .../resources/lafiles/LI_pl | Bin 0 -> 44522 bytes .../resources/lafiles/LI_pt | Bin 0 -> 45178 bytes .../resources/lafiles/LI_ru | Bin 0 -> 44472 bytes .../resources/lafiles/LI_sl | Bin 0 -> 40140 bytes .../resources/lafiles/LI_tr | Bin 0 -> 44084 bytes .../resources/lafiles/LI_zh | Bin 0 -> 16422 bytes .../resources/lafiles/LI_zh_TW | Bin 0 -> 16796 bytes .../resources/lafiles/notices | Bin 0 -> 317160 bytes .../resources/lafiles/testFile | Bin 0 -> 825 bytes .../resources/lafiles/testfile1 | Bin 0 -> 38 bytes .../resources/md5Tests/TestFile.txt | 1 + .../mockInstalls/TwoAparsArchiveFixPack.jar | Bin 0 -> 1175 bytes .../badDate/lib/fixes/badDate.xml | 21 + .../WebSphereApplicationServer.properties | 6 + .../WebSphereApplicationServer.properties | 6 + .../lib/versions/wlp_fp8509_aparIds.zip | Bin 0 -> 148 bytes .../missingFeatureJar/lib/a_1.1.0.jar | Bin 0 -> 153 bytes .../lib/fixes/missingFeatureJar.xml | 21 + .../WebSphereApplicationServer.properties | 6 + .../lib/versions/wlp_fp8501_aparIds.zip | Bin 0 -> 173 bytes .../lib/versions/wlp_fp8502_aparIds.zip | Bin 0 -> 174 bytes .../mockInstalls/noApar/lib/fixes/noApar.xml | 20 + .../resources/mockInstalls/noApar/lib/foo.txt | 0 .../WebSphereApplicationServer.properties | 6 + .../lib/versions/wlp_fp8501_aparIds.zip | Bin 0 -> 173 bytes .../lib/versions/wlp_fp8502_aparIds.zip | Bin 0 -> 174 bytes .../noOffering/lib/fixes/noOffering.xml | 17 + .../mockInstalls/noOffering/lib/foo.txt | 0 .../WebSphereApplicationServer.properties | 6 + .../noProperties/lib/fixes/noProperties.xml | 21 + .../mockInstalls/noProperties/lib/foo.txt | 0 .../lib/versions/OtherProps.properties | 6 + .../oldStaticFile/lib/fixes/oldStaticFile.xml | 21 + .../mockInstalls/oldStaticFile/lib/foo.txt | 0 .../WebSphereApplicationServer.properties | 6 + .../lib/versions/wlp_fp8501_aparIds.zip | Bin 0 -> 173 bytes .../lib/versions/wlp_fp8502_aparIds.zip | Bin 0 -> 174 bytes .../oldVersion/lib/fixes/oldStaticFile.xml | 21 + .../mockInstalls/oldVersion/lib/foo.txt | 0 .../WebSphereApplicationServer.properties | 6 + .../lib/versions/wlp_fp8501_aparIds.zip | Bin 0 -> 173 bytes .../lib/versions/wlp_fp8502_aparIds.zip | Bin 0 -> 174 bytes .../WebSphereApplicationServer.properties | 6 + .../lib/versions/wlp_fp8505_aparIds.zip | Bin 0 -> 161 bytes .../lib/a_1.1.0.v20120424-1542.jar | Bin 0 -> 153 bytes .../lib/b_1.1.0.v20120424-1542.jar | Bin 0 -> 153 bytes .../oneIFixTwoFP/lib/fixes/iFix1.xml | 22 + .../WebSphereApplicationServer.properties | 6 + .../lib/versions/wlp_fp8501_aparIds.zip | Bin 0 -> 157 bytes .../lib/versions/wlp_fp8502_aparIds.zip | Bin 0 -> 158 bytes .../lib/a_1.1.0.v20120424-1542.jar | Bin 0 -> 153 bytes .../lib/b_1.1.0.v20120424-1542.jar | Bin 0 -> 153 bytes .../lib/fixes/iFix1.xml | 22 + .../lib/fixes/iFix2.xml | 20 + .../WebSphereApplicationServer.properties | 6 + .../lib/versions/wlp_fp8501_aparIds.zip | Bin 0 -> 157 bytes .../lib/versions/wlp_fp8502_aparIds.zip | Bin 0 -> 158 bytes .../.classpath | 7 + .../.classpath.gradle | 7 + .../.gitignore | 5 + dev/com.ibm.ws.product.utility_test/.project | 23 + .../org.eclipse.core.resources.prefs | 4 + .../.settings/org.eclipse.jdt.core.prefs | 286 ++ .../.settings/org.eclipse.jdt.ui.prefs | 117 + dev/com.ibm.ws.product.utility_test/bnd.bnd | 22 + .../bnd.bnd.gradle | 22 + .../build-unittest.xml | 6 + .../build.gradle | 0 .../delivery.sets | 1 + .../resources/lafiles/LA_cs | Bin 0 -> 57224 bytes .../resources/lafiles/LA_de | Bin 0 -> 73646 bytes .../resources/lafiles/LA_el | Bin 0 -> 75934 bytes .../resources/lafiles/LA_en | Bin 0 -> 113588 bytes .../resources/lafiles/LA_es | Bin 0 -> 68912 bytes .../resources/lafiles/LA_fr | Bin 0 -> 88336 bytes .../resources/lafiles/LA_in | Bin 0 -> 63082 bytes .../resources/lafiles/LA_it | Bin 0 -> 64426 bytes .../resources/lafiles/LA_ja | Bin 0 -> 23072 bytes .../resources/lafiles/LA_ko | Bin 0 -> 24138 bytes .../resources/lafiles/LA_lt | Bin 0 -> 54246 bytes .../resources/lafiles/LA_pl | Bin 0 -> 64574 bytes .../resources/lafiles/LA_pt | Bin 0 -> 60484 bytes .../resources/lafiles/LA_ru | Bin 0 -> 63082 bytes .../resources/lafiles/LA_sl | Bin 0 -> 54510 bytes .../resources/lafiles/LA_tr | Bin 0 -> 62848 bytes .../resources/lafiles/LA_zh | Bin 0 -> 17052 bytes .../resources/lafiles/LA_zh_TW | Bin 0 -> 17838 bytes .../resources/lafiles/LI_cs | Bin 0 -> 41244 bytes .../resources/lafiles/LI_de | Bin 0 -> 45776 bytes .../resources/lafiles/LI_el | Bin 0 -> 52838 bytes .../resources/lafiles/LI_en | Bin 0 -> 38310 bytes .../resources/lafiles/LI_es | Bin 0 -> 45406 bytes .../resources/lafiles/LI_fr | Bin 0 -> 48136 bytes .../resources/lafiles/LI_in | Bin 0 -> 44530 bytes .../resources/lafiles/LI_it | Bin 0 -> 42306 bytes .../resources/lafiles/LI_ja | Bin 0 -> 22666 bytes .../resources/lafiles/LI_ko | Bin 0 -> 23462 bytes .../resources/lafiles/LI_lt | Bin 0 -> 38580 bytes .../resources/lafiles/LI_pl | Bin 0 -> 44522 bytes .../resources/lafiles/LI_pt | Bin 0 -> 45178 bytes .../resources/lafiles/LI_ru | Bin 0 -> 44472 bytes .../resources/lafiles/LI_sl | Bin 0 -> 40140 bytes .../resources/lafiles/LI_tr | Bin 0 -> 44084 bytes .../resources/lafiles/LI_zh | Bin 0 -> 16422 bytes .../resources/lafiles/LI_zh_TW | Bin 0 -> 16796 bytes .../resources/lafiles/notices | Bin 0 -> 317160 bytes .../resources/lafiles/testFile | Bin 0 -> 825 bytes .../resources/lafiles/testfile1 | Bin 0 -> 38 bytes .../resources/md5Tests/TestFile.txt | 1 + .../mockInstalls/TwoAparsArchiveFixPack.jar | Bin 0 -> 1175 bytes .../badDate/lib/fixes/badDate.xml | 21 + .../WebSphereApplicationServer.properties | 6 + .../WebSphereApplicationServer.properties | 6 + .../lib/versions/wlp_fp8509_aparIds.zip | Bin 0 -> 148 bytes .../missingFeatureJar/lib/a_1.1.0.jar | Bin 0 -> 153 bytes .../lib/fixes/missingFeatureJar.xml | 21 + .../WebSphereApplicationServer.properties | 6 + .../lib/versions/wlp_fp8501_aparIds.zip | Bin 0 -> 173 bytes .../lib/versions/wlp_fp8502_aparIds.zip | Bin 0 -> 174 bytes .../mockInstalls/noApar/lib/fixes/noApar.xml | 20 + .../resources/mockInstalls/noApar/lib/foo.txt | 0 .../WebSphereApplicationServer.properties | 6 + .../lib/versions/wlp_fp8501_aparIds.zip | Bin 0 -> 173 bytes .../lib/versions/wlp_fp8502_aparIds.zip | Bin 0 -> 174 bytes .../noOffering/lib/fixes/noOffering.xml | 17 + .../mockInstalls/noOffering/lib/foo.txt | 0 .../WebSphereApplicationServer.properties | 6 + .../noProperties/lib/fixes/noProperties.xml | 21 + .../mockInstalls/noProperties/lib/foo.txt | 0 .../lib/versions/OtherProps.properties | 6 + .../oldStaticFile/lib/fixes/oldStaticFile.xml | 21 + .../mockInstalls/oldStaticFile/lib/foo.txt | 0 .../WebSphereApplicationServer.properties | 6 + .../lib/versions/wlp_fp8501_aparIds.zip | Bin 0 -> 173 bytes .../lib/versions/wlp_fp8502_aparIds.zip | Bin 0 -> 174 bytes .../oldVersion/lib/fixes/oldStaticFile.xml | 21 + .../mockInstalls/oldVersion/lib/foo.txt | 0 .../WebSphereApplicationServer.properties | 6 + .../lib/versions/wlp_fp8501_aparIds.zip | Bin 0 -> 173 bytes .../lib/versions/wlp_fp8502_aparIds.zip | Bin 0 -> 174 bytes .../WebSphereApplicationServer.properties | 6 + .../lib/versions/wlp_fp8505_aparIds.zip | Bin 0 -> 161 bytes .../lib/a_1.1.0.v20120424-1542.jar | Bin 0 -> 153 bytes .../lib/b_1.1.0.v20120424-1542.jar | Bin 0 -> 153 bytes .../oneIFixTwoFP/lib/fixes/iFix1.xml | 22 + .../WebSphereApplicationServer.properties | 6 + .../lib/versions/wlp_fp8501_aparIds.zip | Bin 0 -> 157 bytes .../lib/versions/wlp_fp8502_aparIds.zip | Bin 0 -> 158 bytes .../lib/a_1.1.0.v20120424-1542.jar | Bin 0 -> 153 bytes .../lib/b_1.1.0.v20120424-1542.jar | Bin 0 -> 153 bytes .../lib/fixes/iFix1.xml | 22 + .../lib/fixes/iFix2.xml | 20 + .../WebSphereApplicationServer.properties | 6 + .../lib/versions/wlp_fp8501_aparIds.zip | Bin 0 -> 157 bytes .../lib/versions/wlp_fp8502_aparIds.zip | Bin 0 -> 158 bytes .../product/utility/BaseCommandTaskTest.java | 164 + .../product/utility/ExecutionContextTest.java | 58 + .../product/utility/HelpCommandTaskTest.java | 126 + .../product/utility/LicenseUtilityTest.java | 128 + .../ibm/ws/product/utility/MD5UtilsTest.java | 58 + .../extension/IFixCompareCommandTaskTest.java | 690 +++ .../utility/extension/IFixUtilsTest.java | 444 ++ .../extension/ValidateCommandTest.java | 951 ++++ .../utility/extension/utils/TestUtils.java | 406 ++ .../.classpath | 7 + .../.classpath.gradle | 7 + .../.gitignore | 5 + .../.project | 23 + .../org.eclipse.core.resources.prefs | 2 + .../.settings/org.eclipse.jdt.core.prefs | 286 ++ .../.settings/org.eclipse.jdt.ui.prefs | 117 + .../bnd.bnd | 25 + .../bnd.bnd.gradle | 25 + .../build-test.xml | 34 + .../build.gradle | 0 .../ibm/ws/repository/resolver/FATSuite.java | 45 + .../resolver/RepositoryResolverTest.java | 2496 ++++++++++ .../resolver/ResolverTestUtils.java | 89 + .../RepositoryResolveContextFatTest.java | 131 + .../.classpath | 7 + .../.classpath.gradle | 7 + .../.gitignore | 3 + dev/com.ibm.ws.repository.test.utils/.project | 23 + .../org.eclipse.core.resources.prefs | 3 + .../.settings/org.eclipse.jdt.core.prefs | 286 ++ .../.settings/org.eclipse.jdt.ui.prefs | 116 + .../IBMInternalRootCA.der | Bin 0 -> 968 bytes dev/com.ibm.ws.repository.test.utils/bnd.bnd | 13 + .../bnd.bnd.gradle | 13 + .../build-noship.xml | 13 + .../build.gradle | 0 .../delivery.sets | 1 + .../lib/larsServer.jar | Bin 0 -> 2101659 bytes .../ws/repository/base/AssetByIdMatcher.java | 58 + .../ibm/ws/repository/base/DeleteRepo.java | 184 + .../base/DirectoryRepositoryTestUtils.java | 104 + .../base/IBMInternalTrustManager.java | 140 + .../IBMInternalTrustManagerException.java | 12 + .../repository/base/JsonAnyOrderMatcher.java | 87 + .../ws/repository/base/LoginInfoProvider.java | 478 ++ .../ibm/ws/repository/base/Marketplace.java | 43 + .../ws/repository/base/MarketplaceApiKey.java | 25 + .../base/NoRepoAvailableException.java | 93 + .../repository/base/RepositoryTestBase.java | 299 ++ .../repository/base/RepositoryTestUtils.java | 43 + .../base/RepositoryTestUtilsFactory.java | 66 + .../base/RestRepositoryTestUtils.java | 372 ++ .../base/RestoreTrustStoreRule.java | 48 + .../ibm/ws/repository/base/TempFileRule.java | 53 + .../ibm/ws/repository/base/TestBaseClass.java | 213 + .../base/ZipRepositoryTestUtils.java | 91 + .../base/servers/DirectoryConnectionRule.java | 108 + .../base/servers/LarsConnectionRule.java | 91 + .../base/servers/LarsServerRule.java | 261 + .../base/servers/MassiveConnectionRule.java | 70 + .../base/servers/MassiveServerRule.java | 57 + .../servers/RestRepositoryConnectionRule.java | 37 + .../clients/AbstractFileWriteableClient.java | 186 + .../clients/DirectoryWriteableClient.java | 192 + .../src/mongodb.properties | 4 + .../.classpath | 7 + .../.classpath.gradle | 7 + .../.gitignore | 1 + .../.project | 23 + .../org.eclipse.core.resources.prefs | 4 + .../.settings/org.eclipse.jdt.core.prefs | 280 ++ .../.settings/org.eclipse.jdt.ui.prefs | 62 + .../bnd.bnd | 12 + .../bnd.bnd.gradle | 12 + .../build-test.xml | 6 + .../build.gradle | 0 .../com/ibm/ws/repository/base/FATTest.java | 174 + .../publish/files/staticApiKeys.props | 17 + .../staticApiKeysInvalidRepositories.props | 34 + dev/com.ibm.ws.runtime.update_fat/.classpath | 7 + .../.classpath.gradle | 7 + dev/com.ibm.ws.runtime.update_fat/.gitignore | 3 + dev/com.ibm.ws.runtime.update_fat/.project | 23 + .../org.eclipse.core.resources.prefs | 4 + .../.settings/org.eclipse.jdt.core.prefs | 286 ++ .../.settings/org.eclipse.jdt.ui.prefs | 117 + dev/com.ibm.ws.runtime.update_fat/bnd.bnd | 28 + .../bnd.bnd.gradle | 28 + .../build-test.xml | 9 + .../build.gradle | 0 .../update/fat/ConfigUpdateDeliveryTest.java | 168 + .../ibm/ws/runtime/update/fat/FATSuite.java | 25 + .../update/fat/RuntimeQuiesceTest.java | 246 + .../publish/features/quiescelistener-1.0.mf | 6 + .../files/bad-quiesce-listener.server.xml | 12 + .../publish/files/local-connector-server.xml | 10 + .../longrunning-quiesce-listener.server.xml | 12 + .../files/no-quiesce-listener.server.xml | 8 + .../publish/files/quiesce-listener.server.xml | 10 + .../files/user-quiesce-listener.server.xml | 10 + .../bootstrap.properties | 1 + .../com.ibm.ws.runtime.quiesce.fat/server.xml | 9 + .../bootstrap.properties | 1 + .../com.ibm.ws.runtime.update.fat/server.xml | 9 + .../mbean/resources/META-INF/permissions.xml | 19 + .../mbean/resources/WEB-INF/web.xml | 21 + .../mbean/src/web/MBeanServlet.java | 254 + .../test-bundles/test.server.quiesce/bnd.bnd | 19 + .../resources/OSGI-INF/metatype/metatype.xml | 31 + .../server/quiesce/TestQuiesceListener.java | 57 + .../.classpath | 7 + .../.classpath.gradle | 7 + .../.gitignore | 2 + dev/com.ibm.ws.security.utility_fat/.project | 23 + .../org.eclipse.core.resources.prefs | 4 + .../.settings/org.eclipse.jdt.core.prefs | 280 ++ .../.settings/org.eclipse.jdt.ui.prefs | 62 + dev/com.ibm.ws.security.utility_fat/bnd.bnd | 28 + .../bnd.bnd.gradle | 28 + .../build-test.xml | 36 + .../build.gradle | 0 .../ws/security/utility/test/FATSuite.java | 25 + .../test/SecurityUtilityEncodeTest.java | 122 + .../test/SecurityUtilityScriptUtils.java | 166 + dev/com.ibm.ws.threading_fat/.classpath | 7 + .../.classpath.gradle | 7 + dev/com.ibm.ws.threading_fat/.gitignore | 1 + dev/com.ibm.ws.threading_fat/.project | 23 + .../org.eclipse.core.resources.prefs | 4 + .../.settings/org.eclipse.jdt.core.prefs | 280 ++ .../.settings/org.eclipse.jdt.ui.prefs | 62 + dev/com.ibm.ws.threading_fat/bnd.bnd | 28 + dev/com.ibm.ws.threading_fat/bnd.bnd.gradle | 28 + dev/com.ibm.ws.threading_fat/build-test.xml | 20 + dev/com.ibm.ws.threading_fat/build.gradle | 0 dev/com.ibm.ws.threading_fat/delivery.sets | 1 + .../com/ibm/ws/threading/fat/FATSuite.java | 75 + .../com/ibm/ws/threading/fat/MemLeakTest.java | 94 + .../threading/fat/ThreadingExtensionFAT.java | 128 + .../publish/.gitignore | 1 + .../publish/files/.gitignore | 1 + .../threadingMemLeakTestFeature-1.0.mf | 7 + .../features/threadingTestFeature-1.0.mf | 7 + .../bootstrap.properties | 1 + .../server.xml | 9 + .../.gitignore | 1 + .../bootstrap.properties | 1 + .../server.xml | 9 + .../threadingtestapp/.gitignore | 1 + .../src/web/ThreadingTestServlet.java | 46 + .../threadingmemleaktestbundle/bnd.bnd | 12 + .../test/bundle/threading/MemLeakChecker.java | 144 + .../test-bundles/threadingtestbundle/bnd.bnd | 23 + .../bundle/threading/TaskInterceptorImpl.java | 44 + .../bundle/threading/ThreadFactoryImpl.java | 47 + .../.classpath | 7 + .../.classpath.gradle | 7 + .../.project | 23 + .../.settings/org.eclipse.jdt.core.prefs | 12 + .../org.eclipse.ltk.core.refactoring.prefs | 3 + .../bnd.bnd | 28 + .../bnd.bnd.gradle | 28 + .../build-ztest.xml | 22 + .../build.gradle | 0 .../zos/command/processing/zfat/FATSuite.java | 78 + .../zos/command/processing/zfat/FATTest.java | 157 + .../zfat/ZosCommandHandlerTest.java | 109 + .../zfat/ZosCommandHandlerUtility.java | 78 + .../files/NoConsole/bootstrap.properties | 2 + .../publish/files/bootstrap.properties | 1 + .../publish/files/bundles/.gitignore | 1 + .../features/userProdtest-1.0.mf | 7 + .../publish/files/server.xml | 13 + .../bootstrap.properties | 1 + .../server.xml | 13 + .../bootstrap.properties | 2 + .../com.ibm.ws.zos.command.feature/server.xml | 12 + .../test-bundles/userExtension/bnd.bnd | 20 + .../userExtension/resources/metatype.xml | 25 + .../UserProductExtensionCommandHandler.java | 108 + .../.classpath | 7 + .../.classpath.gradle | 7 + .../.gitignore | 4 + .../.project | 23 + .../org.eclipse.core.resources.prefs | 4 + .../.settings/org.eclipse.jdt.core.prefs | 286 ++ .../.settings/org.eclipse.jdt.ui.prefs | 117 + .../bnd.bnd | 23 + .../bnd.bnd.gradle | 23 + .../build-zunittest.xml | 5 + .../build.gradle | 0 .../command/processing/internal/UnitTest.java | 230 + dev/com.ibm.ws.zos.logging_zfat/.classpath | 7 + .../.classpath.gradle | 7 + dev/com.ibm.ws.zos.logging_zfat/.gitignore | 1 + dev/com.ibm.ws.zos.logging_zfat/.project | 23 + .../.settings/org.eclipse.jdt.core.prefs | 11 + dev/com.ibm.ws.zos.logging_zfat/bnd.bnd | 28 + .../bnd.bnd.gradle | 28 + .../build-ztest.xml | 15 + dev/com.ibm.ws.zos.logging_zfat/build.gradle | 0 .../ibm/ws/zos/logging/zfat/EbcdicUtils.java | 133 + .../com/ibm/ws/zos/logging/zfat/FATSuite.java | 45 + .../ws/zos/logging/zfat/ZosLoggingTest.java | 366 ++ .../publish/.gitignore | 3 + .../publish/files/bbgzsrv1.jcl | 51 + .../publish/files/bbgzsrv1.msglog.jcl | 52 + .../publish/files/bbgzsrv1.msglog.segment.jcl | 52 + .../publish/files/msgRouterConfig.xml | 10 + .../publish/files/msgRouterConfig2.xml | 10 + .../defaultServer/bootstrap.properties | 2 + .../publish/servers/defaultServer/server.xml | 8 + dev/com.ibm.ws.zos.logging_ztest/.classpath | 7 + .../.classpath.gradle | 7 + dev/com.ibm.ws.zos.logging_ztest/.gitignore | 4 + dev/com.ibm.ws.zos.logging_ztest/.project | 23 + .../org.eclipse.core.resources.prefs | 4 + .../.settings/org.eclipse.jdt.core.prefs | 286 ++ .../.settings/org.eclipse.jdt.ui.prefs | 117 + dev/com.ibm.ws.zos.logging_ztest/bnd.bnd | 26 + .../bnd.bnd.gradle | 26 + .../build-zunittest.xml | 5 + dev/com.ibm.ws.zos.logging_ztest/build.gradle | 0 .../LoggingHardcopyLogHandlerTest.java | 170 + .../ZosLoggingBundleActivatorTest.java | 176 + dev/fattest.simplicity/bnd.bnd | 47 +- dev/fattest.simplicity/bnd.bnd.gradle | 46 +- .../src/componenttest/rules/DumpUtils.java | 19 +- .../topology/impl/LibertyServer.java | 15 +- dev/wlp.lib.extract_fat/.classpath | 7 + dev/wlp.lib.extract_fat/.classpath.gradle | 7 + dev/wlp.lib.extract_fat/.gitignore | 1 + dev/wlp.lib.extract_fat/.project | 23 + .../org.eclipse.core.resources.prefs | 4 + .../.settings/org.eclipse.jdt.core.prefs | 292 ++ .../.settings/org.eclipse.jdt.ui.prefs | 61 + dev/wlp.lib.extract_fat/bnd.bnd | 28 + dev/wlp.lib.extract_fat/bnd.bnd.gradle | 28 + dev/wlp.lib.extract_fat/build-test.xml | 49 + dev/wlp.lib.extract_fat/build.gradle | 0 dev/wlp.lib.extract_fat/delivery.sets | 1 + .../ExternalDependencyDownloadTest.java | 338 ++ .../fat/src/wlp/lib/extract/FATSuite.java | 30 + .../wlp/lib/extract/PackageRunnableTest.java | 217 + .../publish/files/MANIFEST.MF | 10 + .../publish/files/sampleServer.xml | 8 + .../servers/dependencyHostServer/.gitignore | 2 + .../dependencyHostServer/bootstrap.properties | 1 + .../servers/dependencyHostServer/server.xml | 9 + .../servers/runnableTestServer/server.xml | 8 + .../dependencyHost/resources/WEB-INF/web.xml | 22 + .../src/web/DependencyHostServlet.java | 95 + 1515 files changed, 86714 insertions(+), 84 deletions(-) create mode 100644 dev/com.ibm.websphere.appserver.api.json/.classpath create mode 100644 dev/com.ibm.websphere.appserver.api.json/.gitignore create mode 100644 dev/com.ibm.websphere.appserver.api.json/.project create mode 100644 dev/com.ibm.websphere.appserver.api.json/bnd.bnd create mode 100644 dev/com.ibm.websphere.appserver.api.json/build.gradle create mode 100644 dev/com.ibm.websphere.appserver.api.json/com.ibm.websphere.appserver.api.json.pom create mode 100755 dev/com.ibm.websphere.filetransfer/.classpath create mode 100644 dev/com.ibm.websphere.filetransfer/.classpath.gradle create mode 100644 dev/com.ibm.websphere.filetransfer/.gitignore create mode 100755 dev/com.ibm.websphere.filetransfer/.project create mode 100755 dev/com.ibm.websphere.filetransfer/.settings/org.eclipse.core.resources.prefs create mode 100755 dev/com.ibm.websphere.filetransfer/.settings/org.eclipse.jdt.core.prefs create mode 100755 dev/com.ibm.websphere.filetransfer/.settings/org.eclipse.jdt.ui.prefs create mode 100755 dev/com.ibm.websphere.filetransfer/.settings/org.sonar.ide.eclipse.core.prefs create mode 100755 dev/com.ibm.websphere.filetransfer/README.txt create mode 100755 dev/com.ibm.websphere.filetransfer/bnd.bnd create mode 100644 dev/com.ibm.websphere.filetransfer/build.gradle create mode 100755 dev/com.ibm.websphere.filetransfer/build.xml create mode 100755 dev/com.ibm.websphere.filetransfer/findbugs.exclude.xml create mode 100755 dev/com.ibm.websphere.filetransfer/src/com/ibm/websphere/filetransfer/FileServiceMXBean.java create mode 100755 dev/com.ibm.websphere.filetransfer/src/com/ibm/websphere/filetransfer/FileTransferMBean.java create mode 100755 dev/com.ibm.websphere.filetransfer/src/com/ibm/websphere/filetransfer/package-info.java create mode 100644 dev/com.ibm.ws.config.utility_fat/.classpath create mode 100644 dev/com.ibm.ws.config.utility_fat/.classpath.gradle create mode 100644 dev/com.ibm.ws.config.utility_fat/.gitignore create mode 100755 dev/com.ibm.ws.config.utility_fat/.project create mode 100755 dev/com.ibm.ws.config.utility_fat/.settings/org.eclipse.core.resources.prefs create mode 100755 dev/com.ibm.ws.config.utility_fat/.settings/org.eclipse.jdt.core.prefs create mode 100755 dev/com.ibm.ws.config.utility_fat/.settings/org.eclipse.jdt.ui.prefs create mode 100644 dev/com.ibm.ws.config.utility_fat/bnd.bnd create mode 100644 dev/com.ibm.ws.config.utility_fat/bnd.bnd.gradle create mode 100755 dev/com.ibm.ws.config.utility_fat/build-test.xml create mode 100644 dev/com.ibm.ws.config.utility_fat/build.gradle create mode 100755 dev/com.ibm.ws.config.utility_fat/delivery.sets create mode 100755 dev/com.ibm.ws.config.utility_fat/fat/src/com/ibm/ws/config/utility/fat/FATSuite.java create mode 100755 dev/com.ibm.ws.config.utility_fat/fat/src/com/ibm/ws/config/utility/fat/ServerConfigUtilityFatTesting.java create mode 100755 dev/com.ibm.ws.config.utility_fat/fat/src/com/ibm/ws/config/utility/fat/TestRepository.java create mode 100755 dev/com.ibm.ws.config.utility_fat/publish/files/massive/massiveRepoLocation.props create mode 100755 dev/com.ibm.ws.config.utility_fat/publish/servers/com.ibm.ws.config.utility.fat/bootstrap.properties create mode 100755 dev/com.ibm.ws.config.utility_fat/publish/servers/com.ibm.ws.config.utility.fat/files/ejbSnippet.xml create mode 100755 dev/com.ibm.ws.config.utility_fat/publish/servers/com.ibm.ws.config.utility.fat/files/remoteJMXConnection.xml create mode 100755 dev/com.ibm.ws.config.utility_fat/publish/servers/com.ibm.ws.config.utility.fat/files/resultingSnippet.xml create mode 100755 dev/com.ibm.ws.config.utility_fat/publish/servers/com.ibm.ws.config.utility.fat/resources/security/ltpa.keys create mode 100755 dev/com.ibm.ws.config.utility_fat/publish/servers/com.ibm.ws.config.utility.fat/server.xml create mode 100644 dev/com.ibm.ws.config_bvt.schema/.classpath create mode 100644 dev/com.ibm.ws.config_bvt.schema/.classpath.gradle create mode 100755 dev/com.ibm.ws.config_bvt.schema/.project create mode 100755 dev/com.ibm.ws.config_bvt.schema/.settings/org.eclipse.core.resources.prefs create mode 100755 dev/com.ibm.ws.config_bvt.schema/.settings/org.eclipse.jdt.core.prefs create mode 100755 dev/com.ibm.ws.config_bvt.schema/.settings/org.eclipse.jdt.ui.prefs create mode 100755 dev/com.ibm.ws.config_bvt.schema/bnd.bnd create mode 100755 dev/com.ibm.ws.config_bvt.schema/bnd.bnd.gradle create mode 100755 dev/com.ibm.ws.config_bvt.schema/build-bvt.xml create mode 100644 dev/com.ibm.ws.config_bvt.schema/build.gradle create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle.bnd create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/config/factory-one.xml create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/config/factory-two.xml create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/config/singleton.xml create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-attributecopy.xml create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-childfirstextends.xml create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-default.xml create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-dynamic.xml create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-extensions-two.xml create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-extensions.xml create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-hidden.xml create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-nested-defaults.xml create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-nested-merge.xml create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-nested-two.xml create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-nested.xml create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-reference.xml create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-serviceobjectclass.xml create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-variable.xml create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype.xml create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/BaseHttpTest.java create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/BaseTest.java create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/BaseTestRunner.java create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/ConfigurationAdminTest.java create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/ConfigurationPluginTest.java create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/FactoryAliasTest.java create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/FactoryMetaTypeTest.java create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/FactorySimpleTest.java create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/FinalTypeTest.java create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/ManagedFactoryTest.java create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/ManagedTest.java create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/NestedConfigComplexElementTest.java create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/NestedConfigElementTest.java create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/NestedResultTest.java create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/NestedSingletonTest.java create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/PasswordTypeTest.java create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/SharedAliasTest.java create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/SingletonAliasTest.java create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/SingletonMetaTypeTest.java create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/SingletonServerMetaTypeTest.java create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/SingletonServerTest.java create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/Test.java create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/TestRunner.java create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/VariableTest.java create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/defaults/TestRunner.java create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/dynamic/ConfigWriter.java create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/dynamic/FactoryNestedTest.java create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/dynamic/FactoryTest.java create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/dynamic/SingletonTest.java create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/dynamic/TestRunner.java create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/nested/AttributeCopyTestRunner.java create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/nested/ChildFirstExtendsTestRunner.java create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/nested/HiddenTestRunner.java create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/nested/NestedDefaultsTestRunner.java create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/nested/NestedMergeRulesTestRunner.java create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/nested/NestedSingletonTestRunner.java create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/nested/TestRunner.java create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/reference/TestRunner.java create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/soc/ServiceObjectClassTestRunner.java create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/variable/TestRunner.java create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/schema/SchemaGeneratorActivator.java create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/schema/TestRunner.java create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt/src/com/ibm/ws/config/bvt/FeatureListMBeanTest.java create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt/src/com/ibm/ws/config/bvt/SchemaMBeanTest.java create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt/src/com/ibm/ws/config/bvt/SchemaTest.java create mode 100755 dev/com.ibm.ws.config_bvt.schema/bvt/src/com/ibm/ws/config/bvt/ServerXMLConfigurationMBeanTest.java create mode 100755 dev/com.ibm.ws.config_bvt.schema/delivery.sets create mode 100755 dev/com.ibm.ws.config_bvt.schema/osgitck-bvt.xml.disabled create mode 100755 dev/com.ibm.ws.config_bvt.schema/publish/features/testschema-1.0.mf create mode 100644 dev/com.ibm.ws.config_bvt.schema/publish/servers/com.ibm.ws.config.bvt.schema/.gitignore create mode 100755 dev/com.ibm.ws.config_bvt.schema/publish/servers/com.ibm.ws.config.bvt.schema/bootstrap.properties create mode 100755 dev/com.ibm.ws.config_bvt.schema/publish/servers/com.ibm.ws.config.bvt.schema/jvm.options create mode 100755 dev/com.ibm.ws.config_bvt.schema/publish/servers/com.ibm.ws.config.bvt.schema/server.xml create mode 100644 dev/com.ibm.ws.config_fat/.classpath create mode 100644 dev/com.ibm.ws.config_fat/.classpath.gradle create mode 100644 dev/com.ibm.ws.config_fat/.gitignore create mode 100755 dev/com.ibm.ws.config_fat/.project create mode 100755 dev/com.ibm.ws.config_fat/.settings/org.eclipse.core.resources.prefs create mode 100755 dev/com.ibm.ws.config_fat/.settings/org.eclipse.jdt.core.prefs create mode 100755 dev/com.ibm.ws.config_fat/.settings/org.eclipse.jdt.ui.prefs create mode 100644 dev/com.ibm.ws.config_fat/bnd.bnd create mode 100644 dev/com.ibm.ws.config_fat/bnd.bnd.gradle create mode 100755 dev/com.ibm.ws.config_fat/build-test.xml create mode 100644 dev/com.ibm.ws.config_fat/build.gradle create mode 100755 dev/com.ibm.ws.config_fat/delivery.sets create mode 100755 dev/com.ibm.ws.config_fat/fat/src/test/server/config/BadConfigTests.java create mode 100755 dev/com.ibm.ws.config_fat/fat/src/test/server/config/ChildAliasTest.java create mode 100755 dev/com.ibm.ws.config_fat/fat/src/test/server/config/ConfigExtensionsTest.java create mode 100755 dev/com.ibm.ws.config_fat/fat/src/test/server/config/ConfigValidatorTest.java create mode 100755 dev/com.ibm.ws.config_fat/fat/src/test/server/config/DelayedVariableTests.java create mode 100755 dev/com.ibm.ws.config_fat/fat/src/test/server/config/DropinsTest.java create mode 100755 dev/com.ibm.ws.config_fat/fat/src/test/server/config/FATSuite.java create mode 100755 dev/com.ibm.ws.config_fat/fat/src/test/server/config/FeatureUpdateTests.java create mode 100755 dev/com.ibm.ws.config_fat/fat/src/test/server/config/FeaturelistGeneratorMBeanTest.java create mode 100755 dev/com.ibm.ws.config_fat/fat/src/test/server/config/MergedConfigTests.java create mode 100755 dev/com.ibm.ws.config_fat/fat/src/test/server/config/MetatypeProviderTest.java create mode 100755 dev/com.ibm.ws.config_fat/fat/src/test/server/config/ProductExtensionsTest.java create mode 100755 dev/com.ibm.ws.config_fat/fat/src/test/server/config/SchemaGeneratorMBeanTest.java create mode 100755 dev/com.ibm.ws.config_fat/fat/src/test/server/config/ServerConfigTest.java create mode 100755 dev/com.ibm.ws.config_fat/fat/src/test/server/config/ServerXMLConfigurationMBeanTest.java create mode 100755 dev/com.ibm.ws.config_fat/fat/src/test/server/config/ServletRunner.java create mode 100755 dev/com.ibm.ws.config_fat/fat/src/test/server/config/VariableMergeTests.java create mode 100755 dev/com.ibm.ws.config_fat/fat/src/test/server/config/WSConfigurationHelperTest.java create mode 100644 dev/com.ibm.ws.config_fat/publish/.gitignore create mode 100644 dev/com.ibm.ws.config_fat/publish/files/.gitignore create mode 100755 dev/com.ibm.ws.config_fat/publish/files/badconfig/UniqueValueConflict.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/badconfig/badHttp.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/badconfig/badLogging.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/badconfig/goodConfig.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/childalias/server.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/childalias/serverB.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/childalias/serverC.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/childalias/serverC2.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/childalias/serverC3.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/childalias/serverC4.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/childalias/serverC5.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/childalias/serverC6.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/childalias/serverC7.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/dropins/aBrokenFile.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/dropins/alibrary.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/dropins/blibrary.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/dropins/simple.notxml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/dropins/simple.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/dropins/simple2.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/extensions/server.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/extensions/serverB1.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/extensions/serverB2.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/extensions/serverSchemaGenerator.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/featureRemove/serverRemoveJDBC.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/featureRemove/serverRemoveOpenID.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/import.error/bad-include-server-onError-ignore.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/import.error/bad-include-server-onError-ignore2.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/import.error/bad-include-server.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/import.error/bad-include-server2.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/import.error/bootstrap-onError-FAIL.properties create mode 100755 dev/com.ibm.ws.config_fat/publish/files/import.error/bootstrap.properties create mode 100755 dev/com.ibm.ws.config_fat/publish/files/import.error/malformed-server.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/import.error/original.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/import.error/server.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/internalFeatureForFat/childAliasTest-1.0.mf create mode 100755 dev/com.ibm.ws.config_fat/publish/files/internalFeatureForFat/childAliasTestB-1.0.mf create mode 100755 dev/com.ibm.ws.config_fat/publish/files/internalFeatureForFat/childAliasTestC-1.0.mf create mode 100755 dev/com.ibm.ws.config_fat/publish/files/internalFeatureForFat/configExtensionsSchemaGeneratorTest-1.0.mf create mode 100755 dev/com.ibm.ws.config_fat/publish/files/internalFeatureForFat/configExtensionsTest-1.0.mf create mode 100755 dev/com.ibm.ws.config_fat/publish/files/internalFeatureForFat/configExtensionsTestB-1.0.mf create mode 100755 dev/com.ibm.ws.config_fat/publish/files/internalFeatureForFat/configfatlibertyinternals-1.0.mf create mode 100755 dev/com.ibm.ws.config_fat/publish/files/internalFeatureForFat/delayedVariable-1.0.mf create mode 100755 dev/com.ibm.ws.config_fat/publish/files/internalFeatureForFat/mergedConfigTest-1.0.mf create mode 100755 dev/com.ibm.ws.config_fat/publish/files/internalFeatureForFat/metatypeProviderTest-1.0.mf create mode 100755 dev/com.ibm.ws.config_fat/publish/files/merge/allInOne.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/merge/break.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/merge/break2.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/merge/fourLevelIgnore.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/merge/fourLevelReplace.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/merge/ignore.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/merge/ignoreReplace.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/merge/merge.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/merge/replace.xml create mode 100644 dev/com.ibm.ws.config_fat/publish/files/metatype/.gitignore create mode 100755 dev/com.ibm.ws.config_fat/publish/files/metatype/metatype-1.0.mf create mode 100755 dev/com.ibm.ws.config_fat/publish/files/metatype/noMetatypeServer.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/metatype/server.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/productExtensions/config/prod.ext.factory.pid.server.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/productExtensions/config/prod.ext.invalid.server.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/productExtensions/config/prod.ext.valid.server.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/productExtensions/config/user.prod.ext.factory.pid.server.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/productExtensions/config/user.prod.ext.invalid.server.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/productExtensions/config/user.prod.ext.valid.server.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/productExtensions/features/prodtest1-1.0.mf create mode 100755 dev/com.ibm.ws.config_fat/publish/files/productExtensions/features/userProdtest1-1.0.mf create mode 100755 dev/com.ibm.ws.config_fat/publish/files/productExtensions/propertiesFiles/testproduct.properties create mode 100755 dev/com.ibm.ws.config_fat/publish/files/refresh/bad-server.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/refresh/server.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/restart.var/bootstrap.properties create mode 100755 dev/com.ibm.ws.config_fat/publish/files/restart/server.xml create mode 100644 dev/com.ibm.ws.config_fat/publish/files/validator/.gitignore create mode 100755 dev/com.ibm.ws.config_fat/publish/files/validator/bad-signature.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/validator/dropins-enabled.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/variable.error/missing-name.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/variable.error/missing-name2.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/variable.error/missing-value.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/variable.error/missing-value2.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/varmerge/allInOne.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/varmerge/break.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/varmerge/break2.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/varmerge/ignore.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/varmerge/merge.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/files/varmerge/replace.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.bad/server.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.casesensitivity/server.xml create mode 100644 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.childalias/.gitignore create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.childalias/bootstrap.properties create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.childalias/server.xml create mode 100644 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.delayedVar/.gitignore create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.delayedVar/bootstrap.properties create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.delayedVar/server.xml create mode 100644 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.dropins/.gitignore create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.dropins/bootstrap.properties create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.dropins/server.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.extensions/bootstrap.properties create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.features/bootstrap.properties create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.features/server.xml create mode 100644 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.helper/.gitignore create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.helper/bootstrap.properties create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.helper/server.xml create mode 100644 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import.error/.gitignore create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import.error/bootstrap.properties create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import.error/common/common.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import.error/common/relative.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import.error/common/shared.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import.error/server.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import.error/shared.xml create mode 100644 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import/.gitignore create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import/bootstrap.properties create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import/common/common.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import/common/relative.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import/common/shared.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import/server.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import/shared.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.invalidJDBCoption/bootstrap.properties create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.invalidJDBCoption/server.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.invalidOptionalInclude/server.xml create mode 100644 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.merging/.gitignore create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.merging/bootstrap.properties create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.merging/common.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.merging/conflict.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.merging/fourLevelB.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.merging/fourLevelB2.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.merging/fourLevelC.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.merging/fourLevelC2.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.merging/intermediateReplace.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.merging/noConflict.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.merging/server.xml create mode 100644 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.metatype.provider/.gitignore create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.metatype.provider/bootstrap.properties create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.metatype.provider/server.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.product.extension/bootstrap.properties create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.product.extension/server.xml create mode 100644 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.refresh.error/.gitignore create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.refresh.error/bootstrap.properties create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.refresh.error/server.xml create mode 100644 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.refresh/.gitignore create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.refresh/bootstrap.properties create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.refresh/server.xml create mode 100644 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.restart.var/.gitignore create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.restart.var/bootstrap.properties create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.restart.var/server.xml create mode 100644 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.restart/.gitignore create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.restart/bootstrap.properties create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.restart/server.xml create mode 100644 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.schemaGen.mbean/.gitignore create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.schemaGen.mbean/bootstrap.properties create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.schemaGen.mbean/server.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.uniquevalueconflict/server.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.update.mbean/bootstrap.properties create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.update.mbean/server.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.update/bootstrap.properties create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.update/server.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.validate/bootstrap.properties create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.validate/common/common.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.validate/full.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.validate/server.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.validateConfig/bootstrap.properties create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.validateConfig/server.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.validator/bootstrap.properties create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.validator/server.xml create mode 100644 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.varmerging/.gitignore create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.varmerging/bootstrap.properties create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.varmerging/common.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.varmerging/conflict.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.varmerging/noConflict.xml create mode 100755 dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.varmerging/server.xml create mode 100755 dev/com.ibm.ws.config_fat/test-applications/childalias/resources/META-INF/MANIFEST.MF create mode 100755 dev/com.ibm.ws.config_fat/test-applications/childalias/resources/META-INF/permissions.xml create mode 100755 dev/com.ibm.ws.config_fat/test-applications/childalias/resources/WEB-INF/web.xml create mode 100755 dev/com.ibm.ws.config_fat/test-applications/childalias/src/test/server/config/childalias/ChildAliasTestServlet.java create mode 100755 dev/com.ibm.ws.config_fat/test-applications/confighelper/resources/META-INF/MANIFEST.MF create mode 100755 dev/com.ibm.ws.config_fat/test-applications/confighelper/resources/META-INF/permissions.xml create mode 100755 dev/com.ibm.ws.config_fat/test-applications/confighelper/resources/WEB-INF/web.xml create mode 100755 dev/com.ibm.ws.config_fat/test-applications/confighelper/src/test/config/helper/WSConfigurationHelperTestServlet.java create mode 100755 dev/com.ibm.ws.config_fat/test-applications/dropins/resources/META-INF/MANIFEST.MF create mode 100755 dev/com.ibm.ws.config_fat/test-applications/dropins/resources/META-INF/permissions.xml create mode 100755 dev/com.ibm.ws.config_fat/test-applications/dropins/resources/WEB-INF/web.xml create mode 100755 dev/com.ibm.ws.config_fat/test-applications/dropins/src/test/config/dropins/ConfigDropinsServlet.java create mode 100755 dev/com.ibm.ws.config_fat/test-applications/mbeans/resources/META-INF/MANIFEST.MF create mode 100755 dev/com.ibm.ws.config_fat/test-applications/mbeans/resources/META-INF/permissions.xml create mode 100755 dev/com.ibm.ws.config_fat/test-applications/mbeans/resources/WEB-INF/web.xml create mode 100755 dev/com.ibm.ws.config_fat/test-applications/mbeans/src/web/AppClientServletSchemaGen.java create mode 100755 dev/com.ibm.ws.config_fat/test-applications/mergedconfig/resources/META-INF/MANIFEST.MF create mode 100755 dev/com.ibm.ws.config_fat/test-applications/mergedconfig/resources/META-INF/permissions.xml create mode 100755 dev/com.ibm.ws.config_fat/test-applications/mergedconfig/resources/WEB-INF/web.xml create mode 100755 dev/com.ibm.ws.config_fat/test-applications/mergedconfig/src/test/config/merged/MergedConfigTestServlet.java create mode 100755 dev/com.ibm.ws.config_fat/test-applications/metatype/resources/META-INF/MANIFEST.MF create mode 100755 dev/com.ibm.ws.config_fat/test-applications/metatype/resources/META-INF/permissions.xml create mode 100755 dev/com.ibm.ws.config_fat/test-applications/metatype/resources/OSGI-INF/metatype/metatype.xml create mode 100755 dev/com.ibm.ws.config_fat/test-applications/metatype/src/test/server/config/metatype/TestRunner.java create mode 100755 dev/com.ibm.ws.config_fat/test-applications/metatypeprovider/resources/META-INF/MANIFEST.MF create mode 100755 dev/com.ibm.ws.config_fat/test-applications/metatypeprovider/resources/META-INF/permissions.xml create mode 100755 dev/com.ibm.ws.config_fat/test-applications/metatypeprovider/resources/WEB-INF/web.xml create mode 100755 dev/com.ibm.ws.config_fat/test-applications/metatypeprovider/src/test/metatype/provider/MetatypeProviderTestServlet.java create mode 100755 dev/com.ibm.ws.config_fat/test-applications/restart/resources/META-INF/MANIFEST.MF create mode 100755 dev/com.ibm.ws.config_fat/test-applications/restart/resources/META-INF/permissions.xml create mode 100755 dev/com.ibm.ws.config_fat/test-applications/restart/resources/WEB-INF/web.xml create mode 100755 dev/com.ibm.ws.config_fat/test-applications/restart/src/test/server/config/restart/ConfigRestartTestServlet.java create mode 100755 dev/com.ibm.ws.config_fat/test-applications/varmerge/resources/META-INF/MANIFEST.MF create mode 100755 dev/com.ibm.ws.config_fat/test-applications/varmerge/resources/META-INF/permissions.xml create mode 100755 dev/com.ibm.ws.config_fat/test-applications/varmerge/resources/WEB-INF/web.xml create mode 100755 dev/com.ibm.ws.config_fat/test-applications/varmerge/src/test/config/merged/DelayedVariableTestServlet.java create mode 100755 dev/com.ibm.ws.config_fat/test-applications/varmerge/src/test/config/merged/VarMergeTestServlet.java create mode 100755 dev/com.ibm.ws.config_fat/test-bundles/test.config.childalias.b/bnd.bnd create mode 100755 dev/com.ibm.ws.config_fat/test-bundles/test.config.childalias.b/resources/metatype-childalias-b.xml create mode 100755 dev/com.ibm.ws.config_fat/test-bundles/test.config.childalias.c/bnd.bnd create mode 100755 dev/com.ibm.ws.config_fat/test-bundles/test.config.childalias.c/resources/metatype-childalias-c.xml create mode 100755 dev/com.ibm.ws.config_fat/test-bundles/test.config.childalias/bnd.bnd create mode 100755 dev/com.ibm.ws.config_fat/test-bundles/test.config.childalias/resources/metatype-childalias.xml create mode 100755 dev/com.ibm.ws.config_fat/test-bundles/test.config.extensions.b/bnd.bnd create mode 100755 dev/com.ibm.ws.config_fat/test-bundles/test.config.extensions.b/resources/metatype-extensions-two.xml create mode 100755 dev/com.ibm.ws.config_fat/test-bundles/test.config.extensions.schema.generator/bnd.bnd create mode 100755 dev/com.ibm.ws.config_fat/test-bundles/test.config.extensions.schema.generator/src/test/config/extensions/schema/generator/GeneratorTest.java create mode 100755 dev/com.ibm.ws.config_fat/test-bundles/test.config.extensions/bnd.bnd create mode 100755 dev/com.ibm.ws.config_fat/test-bundles/test.config.extensions/resources/metatype-extensions.xml create mode 100755 dev/com.ibm.ws.config_fat/test-bundles/test.config.extensions/src/test/config/extensions/ConfigPropertiesProvider.java create mode 100755 dev/com.ibm.ws.config_fat/test-bundles/test.config.extensions/src/test/config/extensions/ExtensionsTest.java create mode 100755 dev/com.ibm.ws.config_fat/test-bundles/test.config.extensions/src/test/config/extensions/TestResultsServlet.java create mode 100755 dev/com.ibm.ws.config_fat/test-bundles/test.config.variables/bnd.bnd create mode 100755 dev/com.ibm.ws.config_fat/test-bundles/test.config.variables/resources/OSGI-INF/metatype/metatype-variables.xml create mode 100755 dev/com.ibm.ws.config_fat/test-bundles/test.merged.config/bnd.bnd create mode 100755 dev/com.ibm.ws.config_fat/test-bundles/test.merged.config/resources/OSGI-INF/metatype/metatype-mergedconfig.xml create mode 100755 dev/com.ibm.ws.config_fat/test-bundles/test.merged.config/resources/OSGI-INF/wlp/defaultInstances.xml create mode 100755 dev/com.ibm.ws.config_fat/test-bundles/test.merged.config/resources/OSGI-INF/wlp/defaultInstances2.xml create mode 100755 dev/com.ibm.ws.config_fat/test-bundles/test.merged.config/resources/OSGI-INF/wlp/defaultInstances3.xml create mode 100755 dev/com.ibm.ws.config_fat/test-bundles/test.metatype.provider/bnd.bnd create mode 100755 dev/com.ibm.ws.config_fat/test-bundles/test.metatype.provider/src/com/ibm/ws/config/metatype/provider/Animal.java create mode 100755 dev/com.ibm.ws.config_fat/test-bundles/test.metatype.provider/src/com/ibm/ws/config/metatype/provider/AnimalNameAttr.java create mode 100755 dev/com.ibm.ws.config_fat/test-bundles/test.metatype.provider/src/com/ibm/ws/config/metatype/provider/AnimalToo.java create mode 100755 dev/com.ibm.ws.config_fat/test-bundles/test.metatype.provider/src/com/ibm/ws/config/metatype/provider/Plant.java create mode 100755 dev/com.ibm.ws.config_fat/test-bundles/test.metatype.provider/src/com/ibm/ws/config/metatype/provider/PlantNameAttr.java create mode 100755 dev/com.ibm.ws.config_fat/test-bundles/test.metatype.provider/src/com/ibm/ws/config/metatype/provider/PlantObjectClassDefinition.java create mode 100755 dev/com.ibm.ws.config_fat/test-bundles/test.prod.extensions/bnd.bnd create mode 100755 dev/com.ibm.ws.config_fat/test-bundles/test.prod.extensions/resources/metatype.xml create mode 100755 dev/com.ibm.ws.config_fat/test-bundles/test.prod.extensions/src/test/prod/extensions/ProductExtension1.java create mode 100755 dev/com.ibm.ws.config_fat/test-bundles/test.prod.extensions/src/test/prod/extensions/ProductExtension1TestServlet.java create mode 100755 dev/com.ibm.ws.config_fat/test-bundles/test.prod.extensions/src/test/prod/extensions/internal/ProductExtension1ServiceImpl.java create mode 100755 dev/com.ibm.ws.config_fat/test-bundles/test.user.prod.extensions/bnd.bnd create mode 100755 dev/com.ibm.ws.config_fat/test-bundles/test.user.prod.extensions/resources/metatype.xml create mode 100755 dev/com.ibm.ws.config_fat/test-bundles/test.user.prod.extensions/src/test/user/prod/extensions/UserProductExtension1.java create mode 100755 dev/com.ibm.ws.config_fat/test-bundles/test.user.prod.extensions/src/test/user/prod/extensions/UserProductExtension1TestServlet.java create mode 100755 dev/com.ibm.ws.config_fat/test-bundles/test.user.prod.extensions/src/test/user/prod/extensions/internal/UserProductExtension1ServiceImpl.java create mode 100755 dev/com.ibm.ws.config_fat/test/logging.properties create mode 100644 dev/com.ibm.ws.config_fat/validator.exclude.xml create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/.classpath create mode 100644 dev/com.ibm.ws.jmx.connector.client.rest/.classpath.gradle create mode 100644 dev/com.ibm.ws.jmx.connector.client.rest/.gitignore create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/.project create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/.settings/org.eclipse.core.resources.prefs create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/.settings/org.eclipse.jdt.core.prefs create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/.settings/org.eclipse.jdt.ui.prefs create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/bnd.bnd create mode 100644 dev/com.ibm.ws.jmx.connector.client.rest/build.gradle create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/build.xml create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/findbugs.exclude.xml create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/legal/copyright.properties create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/resources/META-INF/services/javax.management.remote.JMXConnectorProvider create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages.nlsprops create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_cs.nlsprops create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_de.nlsprops create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_es.nlsprops create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_fr.nlsprops create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_hu.nlsprops create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_it.nlsprops create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_ja.nlsprops create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_ko.nlsprops create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_pl.nlsprops create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_pt_BR.nlsprops create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_ro.nlsprops create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_ru.nlsprops create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_zh.nlsprops create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_zh_TW.nlsprops create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages.nlsprops create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_cs.nlsprops create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_de.nlsprops create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_es.nlsprops create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_fr.nlsprops create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_hu.nlsprops create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_it.nlsprops create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_ja.nlsprops create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_ko.nlsprops create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_pl.nlsprops create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_pt_BR.nlsprops create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_ro.nlsprops create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_ru.nlsprops create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_zh.nlsprops create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_zh_TW.nlsprops create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/restConnector-headers.bnd create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/restConnector.bnd create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/websphere/jmx/connector/rest/ConnectorSettings.java create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/websphere/jmx/connector/rest/package-info.java create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/ClientProvider.java create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/internal/Activator.java create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/internal/ClientConstants.java create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/internal/Connector.java create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/internal/DynamicURL.java create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/internal/FileTransferClient.java create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/internal/NotificationListenerEntry.java create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/internal/NotificationRegistry.java create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/internal/ObjectIdentityCache.java create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/internal/RESTMBeanServerConnection.java create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/internal/ServerNotificationListenerEntry.java create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/internal/package-info.java create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessagesUtil.java create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessagesUtil.java create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/package-info.java create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/converter/JSONConverter.java create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/converter/NotificationRecord.java create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/converter/NotificationTargetInformation.java create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/converter/SerializationHelper.java create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/converter/package-info.java create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/datatypes/ConversionException.java create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/datatypes/CreateMBean.java create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/datatypes/Invocation.java create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/datatypes/JMXServerInfo.java create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/datatypes/MBeanInfoWrapper.java create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/datatypes/MBeanQuery.java create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/datatypes/NotificationArea.java create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/datatypes/NotificationRegistration.java create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/datatypes/NotificationSettings.java create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/datatypes/ObjectInstanceWrapper.java create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/datatypes/ServerNotificationRegistration.java create mode 100755 dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/datatypes/package-info.java create mode 100644 dev/com.ibm.ws.jmx_fat/.classpath create mode 100644 dev/com.ibm.ws.jmx_fat/.classpath.gradle create mode 100644 dev/com.ibm.ws.jmx_fat/.gitignore create mode 100755 dev/com.ibm.ws.jmx_fat/.project create mode 100755 dev/com.ibm.ws.jmx_fat/.settings/org.eclipse.core.resources.prefs create mode 100755 dev/com.ibm.ws.jmx_fat/.settings/org.eclipse.jdt.core.prefs create mode 100755 dev/com.ibm.ws.jmx_fat/.settings/org.eclipse.jdt.ui.prefs create mode 100644 dev/com.ibm.ws.jmx_fat/bnd.bnd create mode 100644 dev/com.ibm.ws.jmx_fat/bnd.bnd.gradle create mode 100755 dev/com.ibm.ws.jmx_fat/build-test.xml create mode 100644 dev/com.ibm.ws.jmx_fat/build.gradle create mode 100755 dev/com.ibm.ws.jmx_fat/delivery.sets create mode 100755 dev/com.ibm.ws.jmx_fat/fat/src/com/ibm/ws/jmx/fat/AttachSupport.java create mode 100755 dev/com.ibm.ws.jmx_fat/fat/src/com/ibm/ws/jmx/fat/ClientConnector.java create mode 100755 dev/com.ibm.ws.jmx_fat/fat/src/com/ibm/ws/jmx/fat/FATSuite.java create mode 100755 dev/com.ibm.ws.jmx_fat/fat/src/com/ibm/ws/jmx/fat/JMXTest.java create mode 100755 dev/com.ibm.ws.jmx_fat/fat/src/com/ibm/ws/jmx/fat/LocalConnector.java create mode 100755 dev/com.ibm.ws.jmx_fat/fat/src/com/ibm/ws/jmx/fat/attach/ForwardingInvocationHandler.java create mode 100755 dev/com.ibm.ws.jmx_fat/fat/src/com/ibm/ws/jmx/fat/attach/ObjectProxy.java create mode 100755 dev/com.ibm.ws.jmx_fat/fat/src/com/ibm/ws/jmx/fat/attach/VirtualMachineDescriptorProxy.java create mode 100755 dev/com.ibm.ws.jmx_fat/fat/src/com/ibm/ws/jmx/fat/attach/VirtualMachineProxy.java create mode 100755 dev/com.ibm.ws.jmx_fat/fat/src/com/ibm/ws/jmx/fat/attach/VirtualMachineProxyHelper.java create mode 100644 dev/com.ibm.ws.jmx_fat/publish/.gitignore create mode 100755 dev/com.ibm.ws.jmx_fat/publish/features/jmxtest-1.0.mf create mode 100755 dev/com.ibm.ws.jmx_fat/publish/servers/com.ibm.ws.jmx.fat/bootstrap.properties create mode 100755 dev/com.ibm.ws.jmx_fat/publish/servers/com.ibm.ws.jmx.fat/server.xml create mode 100755 dev/com.ibm.ws.jmx_fat/test-bundles/test-mbeans/bnd.bnd create mode 100755 dev/com.ibm.ws.jmx_fat/test-bundles/test-mbeans/src/com/ibm/ws/jmx/test/fat/BeanCounter.java create mode 100755 dev/com.ibm.ws.jmx_fat/test-bundles/test-mbeans/src/com/ibm/ws/jmx/test/fat/DelayedMbeanTester.java create mode 100755 dev/com.ibm.ws.jmx_fat/test-bundles/test-mbeans/src/com/ibm/ws/jmx/test/fat/DelayedMbeanTesterMBean.java create mode 100755 dev/com.ibm.ws.jmx_fat/test-bundles/test-mbeans/src/com/ibm/ws/jmx/test/fat/Messages.properties create mode 100755 dev/com.ibm.ws.jmx_fat/test-bundles/test-mbeans/src/com/ibm/ws/jmx/test/fat/ServerConnector.java create mode 100755 dev/com.ibm.ws.jmx_fat/test-bundles/test-mbeans/src/com/ibm/ws/jmx/test/fat/TestBean.java create mode 100755 dev/com.ibm.ws.jmx_fat/test-bundles/test-mbeans/src/com/ibm/ws/jmx/test/fat/TestBean1.java create mode 100755 dev/com.ibm.ws.jmx_fat/test-bundles/test-mbeans/src/com/ibm/ws/jmx/test/fat/TestBean2.java create mode 100755 dev/com.ibm.ws.jmx_fat/test-bundles/test-mbeans/src/com/ibm/ws/jmx/test/fat/TestBean3.java create mode 100755 dev/com.ibm.ws.jmx_fat/test-bundles/test-mbeans/src/com/ibm/ws/jmx/test/fat/package-info.java create mode 100644 dev/com.ibm.ws.kernel.boot_fat/.classpath create mode 100644 dev/com.ibm.ws.kernel.boot_fat/.classpath.gradle create mode 100644 dev/com.ibm.ws.kernel.boot_fat/.gitignore create mode 100755 dev/com.ibm.ws.kernel.boot_fat/.project create mode 100755 dev/com.ibm.ws.kernel.boot_fat/.settings/org.eclipse.core.resources.prefs create mode 100755 dev/com.ibm.ws.kernel.boot_fat/.settings/org.eclipse.jdt.core.prefs create mode 100755 dev/com.ibm.ws.kernel.boot_fat/.settings/org.eclipse.jdt.ui.prefs create mode 100644 dev/com.ibm.ws.kernel.boot_fat/bnd.bnd create mode 100644 dev/com.ibm.ws.kernel.boot_fat/bnd.bnd.gradle create mode 100755 dev/com.ibm.ws.kernel.boot_fat/build-test.xml create mode 100644 dev/com.ibm.ws.kernel.boot_fat/build.gradle create mode 100755 dev/com.ibm.ws.kernel.boot_fat/delivery.sets create mode 100755 dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/FATSuite.java create mode 100644 dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/OnlyRunOnWinRule.java create mode 100644 dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/ServerClasspathTest.java create mode 100644 dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/ServerStartAsServiceTest.java create mode 100644 dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/ServerStartJVMOptionsTest.java create mode 100755 dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/ServerStartTest.java create mode 100755 dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/ShutdownTest.java create mode 100755 dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/commandline/CreateCommandTest.java create mode 100755 dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/commandline/DumpCommandTest.java create mode 100644 dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/commandline/PauseResumeCommandTest.java create mode 100755 dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/commandline/StartCommandTest.java create mode 100755 dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/commandport/ServerCommandPortTest.java create mode 100755 dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/internal/commands/LogLevelPropertyTest.java create mode 100755 dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/internal/commands/PackageCommandTest.java create mode 100755 dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/provisioning/KernelChangeTest.java create mode 100755 dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/provisioning/ProvisioningTest.java create mode 100755 dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/wsspi/kernel/embeddable/EmbeddedServerAddProductExtensionMultipleTest.java create mode 100755 dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/wsspi/kernel/embeddable/EmbeddedServerAddProductExtensionTest.java create mode 100755 dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/wsspi/kernel/embeddable/EmbeddedServerDriver.java create mode 100755 dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/wsspi/kernel/embeddable/EmbeddedServerTest.java create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/applications/SharedLooseEAR.ear.xml create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/files/ProvisioningInterimFixesTestBundle1_1.0.0.20130101.jar create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/files/ProvisioningInterimFixesTestBundle1_1.0.0.jar create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/files/ProvisioningInterimFixesTestBundle2_1.0.0.20130101.jar create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/files/ProvisioningInterimFixesTestBundle2_1.0.0.jar create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/files/ProvisioningInterimFixesTestBundle3_1.0.0.20130101.jar create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/files/ProvisioningInterimFixesTestBundle3_1.0.0.jar create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/files/ProvisioningInterimFixesTestBundle4_1.0.0.20130101.jar create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/files/ProvisioningInterimFixesTestBundle4_1.0.0.jar create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/files/ProvisioningTestBundle_1.0.0.jar create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/files/ProvisioningTestBundle_1.0.1.201202020001-APAR0001.jar create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/files/ProvisioningTestBundle_1.0.1.201203030001-APAR0002.jar create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/files/ProvisioningTestBundle_1.0.1.201204040001-TestAPAR0001.jar create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/files/ProvisioningTestBundle_1.0.1.jar create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/files/ProvisioningTestBundle_1.0.100.jar create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/files/ProvisioningTestBundle_1.0.2.201201010001-APAR0001.jar create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/files/ProvisioningTestBundle_1.0.2.jar create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/files/ProvisioningTestBundle_1.0.99.jar create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/files/Xfuture/jvm.options create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/files/Xfuture/server.xml create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/files/interimFixesServer.xml create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/files/marker create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/files/provisioningInterimFixTest-1.0.mf create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/files/provisioningInterimFixesTest-1.0.mf create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/files/provisioningTest-1.0.mf create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/files/service.fingerprint create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/files/singleInterimFixServer.xml create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/files/test_template_option/extensions/templateTestAbsolute.properties create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/files/test_template_option/extensions/templateTestRelative.properties create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/files/test_template_option/templates/clients/template2/client.xml create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/files/test_template_option/templates/servers/templateTest/server.xml create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/resources/looseConfig/earContent/META-INF/application.xml create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/resources/looseConfig/testUtil/classes/META-INF/MANIFEST.MF create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/resources/looseConfig/testWeb0/WebContent/META-INF/MANIFEST.MF create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/resources/looseConfig/testWeb0/WebContent/index.jsp create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/resources/looseConfig/testWeb1/WebContent/META-INF/MANIFEST.MF create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/resources/looseConfig/testWeb1/WebContent/index.jsp create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/resources/looseConfig/utils/classes/META-INF/MANIFEST.MF create mode 100644 dev/com.ibm.ws.kernel.boot_fat/publish/servers/ServerStartAsServiceTest/bootstrap.properties create mode 100644 dev/com.ibm.ws.kernel.boot_fat/publish/servers/ServerStartAsServiceTest/dropins/snoop.war create mode 100644 dev/com.ibm.ws.kernel.boot_fat/publish/servers/ServerStartAsServiceTest/server.xml create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.bvt/apps/Apps Loose Web.war.xml create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.bvt/apps/AppsLooseWeb-InvalidRelPaths.war.xml create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.bvt/apps/AppsLooseWeb-RelPaths.war.xml create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.bvt/apps/AppsLooseWeb-Signed.war.xml create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.bvt/apps/AppsLooseWeb.war.xml create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.bvt/bootstrap.properties create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.bvt/dropins/DropinsLooseWeb.ear.xml create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.bvt/server.xml create mode 100644 dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.classpath.fat/.gitignore create mode 100644 dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.classpath.fat/bootstrap.properties create mode 100644 dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.classpath.fat/server.xml create mode 100644 dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.commandport.disabled.fat/.gitignore create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.commandport.disabled.fat/bootstrap.properties create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.commandport.disabled.fat/server.xml create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.commandport.enabled.fat/server.xml create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.env.bvt/bootstrap.properties create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.env.bvt/server.xml create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.pause.resume.fat/server.xml create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.serverstart.fat/server.xml create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.bootstrap.fat/bootstrap.properties create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.bootstrap.fat/bootstrap.properties.hpel create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.bootstrap.fat/server.xml create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.bootstrap.output.fat/bootstrap.properties create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.bootstrap.output.fat/server.xml create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.provisioning.fat.fingerprint/bootstrap.properties create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.provisioning.fat.fingerprint/server.xml create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.provisioning.fat/bootstrap.properties create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.provisioning.fat/server.xml create mode 100644 dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.shutdown.fat/.gitignore create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.shutdown.fat/bootstrap.properties create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.shutdown.fat/server.xml create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.wsspi.kernel.embeddable.add.product.extension.fat/bootstrap.properties create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.wsspi.kernel.embeddable.add.product.extension.fat/dropins/simpleApp.war/index.jsp create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.wsspi.kernel.embeddable.add.product.extension.fat/producttest/lib/com.ibm.ws.prodtest.internal_1.0.jar create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.wsspi.kernel.embeddable.add.product.extension.fat/producttest/lib/features/prodtest-1.0.mf create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.wsspi.kernel.embeddable.add.product.extension.fat/server.xml create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.wsspi.kernel.embeddable.add.product.extension.multiple.fat/bootstrap.properties create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.wsspi.kernel.embeddable.add.product.extension.multiple.fat/dropins/simpleApp.war/index.jsp create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.wsspi.kernel.embeddable.add.product.extension.multiple.fat/producttest/lib/com.ibm.ws.prodtest.internal_1.0.jar create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.wsspi.kernel.embeddable.add.product.extension.multiple.fat/producttest/lib/features/prodtest-1.0.mf create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.wsspi.kernel.embeddable.add.product.extension.multiple.fat/producttestb/lib/com.ibm.ws.prodtest.internal_1.0.jar create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.wsspi.kernel.embeddable.add.product.extension.multiple.fat/producttestb/lib/features/prodtestb-1.0.mf create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.wsspi.kernel.embeddable.add.product.extension.multiple.fat/server.xml create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.wsspi.kernel.embeddable.fat/bootstrap.properties create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.wsspi.kernel.embeddable.fat/dropins/simpleApp.war/index.jsp create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.wsspi.kernel.embeddable.fat/server.xml create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/servers/embed_me/bootstrap.properties create mode 100755 dev/com.ibm.ws.kernel.boot_fat/publish/servers/embed_me/server.xml create mode 100644 dev/com.ibm.ws.kernel.boot_fat/test-applications/checkJvmAppClasspath/src/com/ibm/ws/kernel/boot/app/classpath/CheckJvmAppClasspathPackagesBean.java create mode 100644 dev/com.ibm.ws.kernel.boot_fat/test-applications/shutdownfat/.gitignore create mode 100755 dev/com.ibm.ws.kernel.boot_fat/test-applications/shutdownfat/src/com/ibm/ws/kernel/boot/fat/ShutdownTestServlet.java create mode 100644 dev/com.ibm.ws.kernel.boot_test/.classpath create mode 100644 dev/com.ibm.ws.kernel.boot_test/.classpath.gradle create mode 100644 dev/com.ibm.ws.kernel.boot_test/.gitignore create mode 100755 dev/com.ibm.ws.kernel.boot_test/.project create mode 100755 dev/com.ibm.ws.kernel.boot_test/.settings/org.eclipse.core.resources.prefs create mode 100755 dev/com.ibm.ws.kernel.boot_test/.settings/org.eclipse.jdt.core.prefs create mode 100755 dev/com.ibm.ws.kernel.boot_test/.settings/org.eclipse.jdt.ui.prefs create mode 100755 dev/com.ibm.ws.kernel.boot_test/bnd.bnd create mode 100755 dev/com.ibm.ws.kernel.boot_test/bnd.bnd.gradle create mode 100755 dev/com.ibm.ws.kernel.boot_test/build-unittest.xml create mode 100644 dev/com.ibm.ws.kernel.boot_test/build.gradle create mode 100755 dev/com.ibm.ws.kernel.boot_test/delivery.sets create mode 100755 dev/com.ibm.ws.kernel.boot_test/launch.bnd create mode 100755 dev/com.ibm.ws.kernel.boot_test/resources/Factory.empty create mode 100755 dev/com.ibm.ws.kernel.boot_test/resources/packages.list create mode 100755 dev/com.ibm.ws.kernel.boot_test/resources/serverDefaults/bootstrap.properties create mode 100755 dev/com.ibm.ws.kernel.boot_test/resources/serverDefaults/server.cfg create mode 100755 dev/com.ibm.ws.kernel.boot_test/resources/system-packages_1.6.0.properties create mode 100755 dev/com.ibm.ws.kernel.boot_test/resources/system-packages_1.7.0.properties create mode 100755 dev/com.ibm.ws.kernel.boot_test/resources/system-packages_1.8.0.properties create mode 100755 dev/com.ibm.ws.kernel.boot_test/simple.bnd create mode 100755 dev/com.ibm.ws.kernel.boot_test/simple2.bnd create mode 100755 dev/com.ibm.ws.kernel.boot_test/simple3.bnd create mode 100755 dev/com.ibm.ws.kernel.boot_test/simple4.bnd create mode 100755 dev/com.ibm.ws.kernel.boot_test/simple5.bnd create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/BootstrapConfigTest.java create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/LaunchArgumentsTest.java create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/LauncherTest.java create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/SharedBootstrapConfig.java create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/internal/BootstrapManifestTest.java create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/internal/FileUtilsTest.java create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/internal/FrameworkManagerTest.java create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/internal/KernelResolverTest.java create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/internal/ServerLockTest.java create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/internal/ServerRunningTest.java create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/internal/TimeoutRule.java create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/internal/commands/DumpProcessorTest.java create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/internal/commands/FolderStructureGeneratorTest.java create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/internal/commands/PackageProcessorTest.java create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/internal/framework/BasicLauncherDelegate.java create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/internal/framework/BasicLogProvider.java create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/jmx/internal/MBeanServerPipelineTest.java create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/jmx/internal/PlatformMBeanServerDelegateTest.java create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/security/WLPDynamicPolicyTest.java create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/internal/classloader/JarFileClassLoaderTest.java create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/internal/reference/Handler.java create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/launch/internal/FrameworkConfigurationTest.java create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/launch/internal/FrameworkManagerTimeTest.java create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/launch/internal/LibertyProcessImplTest.java create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/launch/internal/NoRethrowSecurityManagerTest.java create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/launch/internal/ProvisionerTest.java create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/provisioining/LocalBundleRepositoryTest.java create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/provisioining/ServiceFingerprintTest.java create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/src/test/shared/Constants.java create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/src/test/shared/DumpTimerRule.java create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/src/test/shared/TestUtils.java create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/test data/dump/lib/md5-2.txt create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/test data/dump/md5-1.txt create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/test data/dump/usr/ignored.txt create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/dev/a.b_1.0.2.mf create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/dev/bad.jar create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/a.b_1.0.0.jar create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/a.b_1.0.0.mf create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/a.b_1.0.1.jar create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/a.b_1.0.1.mf create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/a.b_1.0.1.v1.jar create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/a.b_1.0.1.v1.mf create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/a.b_1.0.1.v2.jar create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/a.b_1.0.1.v2.mf create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/a.b_1.0.100.jar create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/a.b_1.0.100.mf create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/a.b_1.0.2.v1.jar create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/a.b_1.0.2.v1.mf create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/a.b_1.0.jar create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/a.b_1.0.mf create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/dummy.jar create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/platform/binaryLogging-1.0.mf create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/platform/defaultLogging-1.0.mf create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/platform/emptyLogging-1.0.mf create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/platform/extension-1.0.mf create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/platform/kernel-1.0.mf create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/platform/kernelCore-1.0.mf create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/platform/kernelCoreMissing-1.0.mf create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/platform/missingJar-1.0.mf create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/rebuildjars.bat create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/x.y_1.0.jar create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/x.y_1.0.mf create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/test data/lib/platform/include.properties create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/test data/lib/platform/peer.properties create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/test data/lib/platform/relative.properties create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/test data/lib/platform/testDefNoEquals.map create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/test data/lib/versions/WebSphereApplicationServer.properties create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/test data/nonIFixLBR/lib/a.b_1.0.0.jar create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/test data/nonIFixLBR/lib/a.b_1.0.1.jar create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/test data/nonIFixLBR/lib/a.b_1.0.100.jar create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/test data/nonIFixLBR/lib/a.b_1.0.jar create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/test data/nonIFixLBR/lib/x.y_1.0.jar create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/test data/resources/resources1.jar create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/test data/resources/resources2.jar create mode 100755 dev/com.ibm.ws.kernel.boot_test/unittest/test data/signed/bad.jar create mode 100644 dev/com.ibm.ws.kernel.filemonitor_fat/.classpath create mode 100644 dev/com.ibm.ws.kernel.filemonitor_fat/.classpath.gradle create mode 100644 dev/com.ibm.ws.kernel.filemonitor_fat/.gitignore create mode 100755 dev/com.ibm.ws.kernel.filemonitor_fat/.project create mode 100755 dev/com.ibm.ws.kernel.filemonitor_fat/.settings/org.eclipse.core.resources.prefs create mode 100755 dev/com.ibm.ws.kernel.filemonitor_fat/.settings/org.eclipse.jdt.core.prefs create mode 100755 dev/com.ibm.ws.kernel.filemonitor_fat/.settings/org.eclipse.jdt.ui.prefs create mode 100644 dev/com.ibm.ws.kernel.filemonitor_fat/bnd.bnd create mode 100644 dev/com.ibm.ws.kernel.filemonitor_fat/bnd.bnd.gradle create mode 100755 dev/com.ibm.ws.kernel.filemonitor_fat/build-test.xml create mode 100644 dev/com.ibm.ws.kernel.filemonitor_fat/build.gradle create mode 100755 dev/com.ibm.ws.kernel.filemonitor_fat/delivery.sets create mode 100755 dev/com.ibm.ws.kernel.filemonitor_fat/fat/src/com/ibm/ws/kernel/filemonitor/fat/AbstractNotificationTest.java create mode 100755 dev/com.ibm.ws.kernel.filemonitor_fat/fat/src/com/ibm/ws/kernel/filemonitor/fat/FATSuite.java create mode 100755 dev/com.ibm.ws.kernel.filemonitor_fat/fat/src/com/ibm/ws/kernel/filemonitor/fat/FileMonitorTest.java create mode 100755 dev/com.ibm.ws.kernel.filemonitor_fat/fat/src/com/ibm/ws/kernel/filemonitor/fat/FileNotificationMBeanTest.java create mode 100755 dev/com.ibm.ws.kernel.filemonitor_fat/fat/src/com/ibm/ws/kernel/filemonitor/fat/MonitorReader.java create mode 100644 dev/com.ibm.ws.kernel.filemonitor_fat/publish/.gitignore create mode 100755 dev/com.ibm.ws.kernel.filemonitor_fat/publish/features/monitoringPrintingFeature-1.0.mf create mode 100755 dev/com.ibm.ws.kernel.filemonitor_fat/publish/servers/com.ibm.ws.kernel.filemonitor.server/bootstrap.properties create mode 100755 dev/com.ibm.ws.kernel.filemonitor_fat/publish/servers/com.ibm.ws.kernel.filemonitor.server/server.xml create mode 100755 dev/com.ibm.ws.kernel.filemonitor_fat/test-bundles/com.ibm.ws.kernel.filemonitor.monitor.test.bundle/bnd.bnd create mode 100755 dev/com.ibm.ws.kernel.filemonitor_fat/test-bundles/com.ibm.ws.kernel.filemonitor.monitor.test.bundle/src/com/ibm/ws/kernel/filemonitor/monitor/test/FileMonitorPrintingImplementation.java create mode 100755 dev/com.ibm.ws.kernel.filemonitor_fat/test-bundles/com.ibm.ws.kernel.filemonitor.monitor.test.bundle/src/com/ibm/ws/kernel/filemonitor/monitor/test/FileMonitorRegistrationHandler.java create mode 100755 dev/com.ibm.ws.kernel.metatype.helper_fat/.classpath create mode 100644 dev/com.ibm.ws.kernel.metatype.helper_fat/.classpath.gradle create mode 100644 dev/com.ibm.ws.kernel.metatype.helper_fat/.gitignore create mode 100755 dev/com.ibm.ws.kernel.metatype.helper_fat/.project create mode 100755 dev/com.ibm.ws.kernel.metatype.helper_fat/.settings/org.eclipse.core.resources.prefs create mode 100755 dev/com.ibm.ws.kernel.metatype.helper_fat/.settings/org.eclipse.jdt.core.prefs create mode 100755 dev/com.ibm.ws.kernel.metatype.helper_fat/.settings/org.eclipse.jdt.ui.prefs create mode 100644 dev/com.ibm.ws.kernel.metatype.helper_fat/bnd.bnd create mode 100644 dev/com.ibm.ws.kernel.metatype.helper_fat/bnd.bnd.gradle create mode 100755 dev/com.ibm.ws.kernel.metatype.helper_fat/build-test.xml create mode 100644 dev/com.ibm.ws.kernel.metatype.helper_fat/build.gradle create mode 100755 dev/com.ibm.ws.kernel.metatype.helper_fat/delivery.sets create mode 100755 dev/com.ibm.ws.kernel.metatype.helper_fat/fat/src/com/ibm/ws/kernel/metatype/helper/fat/FATTest.java create mode 100755 dev/com.ibm.ws.kernel.metatype.helper_fat/publish/files/config_change_fileset/server.xml create mode 100755 dev/com.ibm.ws.kernel.metatype.helper_fat/publish/files/fileset_list/server.xml create mode 100755 dev/com.ibm.ws.kernel.metatype.helper_fat/publish/files/internalFeatureForFat/filesetfatlibertyinternals-1.0.mf create mode 100755 dev/com.ibm.ws.kernel.metatype.helper_fat/publish/files/monitored_fileset/server.xml create mode 100755 dev/com.ibm.ws.kernel.metatype.helper_fat/publish/files/test3.jar create mode 100755 dev/com.ibm.ws.kernel.metatype.helper_fat/publish/files/unmonitored_fileset/server.xml create mode 100644 dev/com.ibm.ws.kernel.metatype.helper_fat/publish/servers/com.ibm.ws.kernel.metatype.helperServer/.gitignore create mode 100755 dev/com.ibm.ws.kernel.metatype.helper_fat/publish/servers/com.ibm.ws.kernel.metatype.helperServer/bootstrap.properties create mode 100755 dev/com.ibm.ws.kernel.metatype.helper_fat/publish/shared/config/com.ibm.ws.kernel.metatype.helperServer.xml create mode 100755 dev/com.ibm.ws.kernel.metatype.helper_fat/publish/shared/resources/fileset_test_bundles/repo.xml create mode 100755 dev/com.ibm.ws.kernel.metatype.helper_fat/publish/shared/resources/fileset_test_bundles/test.txt create mode 100755 dev/com.ibm.ws.kernel.metatype.helper_fat/publish/shared/resources/fileset_test_bundles/test1.jar create mode 100755 dev/com.ibm.ws.kernel.metatype.helper_fat/publish/shared/resources/fileset_test_bundles/test2.jar create mode 100755 dev/com.ibm.ws.kernel.metatype.helper_fat/publish/shared/resources/fileset_test_bundles/test_subfolder/test4.jar create mode 100755 dev/com.ibm.ws.kernel.metatype.helper_fat/test-applications/fileset/resources/WEB-INF/web.xml create mode 100755 dev/com.ibm.ws.kernel.metatype.helper_fat/test-applications/fileset/src/com/ibm/ws/kernel/metatype/helper/test/app/FilesetTestServlet.java create mode 100644 dev/com.ibm.ws.kernel.metatype.helper_test/.classpath create mode 100644 dev/com.ibm.ws.kernel.metatype.helper_test/.classpath.gradle create mode 100644 dev/com.ibm.ws.kernel.metatype.helper_test/.gitignore create mode 100755 dev/com.ibm.ws.kernel.metatype.helper_test/.project create mode 100755 dev/com.ibm.ws.kernel.metatype.helper_test/.settings/org.eclipse.core.resources.prefs create mode 100755 dev/com.ibm.ws.kernel.metatype.helper_test/.settings/org.eclipse.jdt.core.prefs create mode 100755 dev/com.ibm.ws.kernel.metatype.helper_test/.settings/org.eclipse.jdt.ui.prefs create mode 100755 dev/com.ibm.ws.kernel.metatype.helper_test/bnd.bnd create mode 100755 dev/com.ibm.ws.kernel.metatype.helper_test/bnd.bnd.gradle create mode 100755 dev/com.ibm.ws.kernel.metatype.helper_test/build-unittest.xml create mode 100644 dev/com.ibm.ws.kernel.metatype.helper_test/build.gradle create mode 100755 dev/com.ibm.ws.kernel.metatype.helper_test/delivery.sets create mode 100755 dev/com.ibm.ws.kernel.metatype.helper_test/unittest/src/com/ibm/wsspi/config/internal/AbstractFilesetTestHelper.java create mode 100755 dev/com.ibm.ws.kernel.metatype.helper_test/unittest/src/com/ibm/wsspi/config/internal/FilesetNameFilterTest.java create mode 100755 dev/com.ibm.ws.kernel.metatype.helper_test/unittest/src/com/ibm/wsspi/config/internal/FilesetTest.java create mode 100644 dev/com.ibm.ws.logging.hpel_fat/.classpath create mode 100644 dev/com.ibm.ws.logging.hpel_fat/.classpath.gradle create mode 100644 dev/com.ibm.ws.logging.hpel_fat/.gitignore create mode 100755 dev/com.ibm.ws.logging.hpel_fat/.project create mode 100755 dev/com.ibm.ws.logging.hpel_fat/.settings/org.eclipse.core.resources.prefs create mode 100755 dev/com.ibm.ws.logging.hpel_fat/.settings/org.eclipse.jdt.core.prefs create mode 100755 dev/com.ibm.ws.logging.hpel_fat/.settings/org.eclipse.jdt.ui.prefs create mode 100644 dev/com.ibm.ws.logging.hpel_fat/bnd.bnd create mode 100644 dev/com.ibm.ws.logging.hpel_fat/bnd.bnd.gradle create mode 100755 dev/com.ibm.ws.logging.hpel_fat/build-test.xml create mode 100644 dev/com.ibm.ws.logging.hpel_fat/build.gradle create mode 100755 dev/com.ibm.ws.logging.hpel_fat/delivery.sets create mode 100755 dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/setup/HpelSetup.java create mode 100755 dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/suites/FATSuite.java create mode 100755 dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/BinaryLogExec.java create mode 100755 dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/BinaryLogRecordContextTest.java create mode 100755 dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/ConcurrentLoggingAccuracyTest.java create mode 100755 dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/HPELDataDirFalsePositiveWarningTest.java create mode 100755 dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/HPELLogDirectoryPurgeMaxSizeTest.java create mode 100755 dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/HPELPurgeMaxSizeErrorTest.java create mode 100755 dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/HpelDeleteEmptyDirectories.java create mode 100755 dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/HpelLogDirectoryChangeTest.java create mode 100755 dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/HpelLoggingElementDeleteTest.java create mode 100755 dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/HpelPurgeMaxSizeBackupFileTest.java create mode 100755 dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/HpelPurgeMaxSizeIgnoreTest_1.java create mode 100755 dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/HpelPurgeMaxSizeIgnoreTest_2.java create mode 100755 dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/HpelTextLogRetention.java create mode 100755 dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/LogViewerExec.java create mode 100755 dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/TraceSpecificationSetToAllTest.java create mode 100755 dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/VerifyRepositoryAccuracy.java create mode 100755 dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/ras/util/CommonTasks.java create mode 100755 dev/com.ibm.ws.logging.hpel_fat/lib/fat.harness.jar create mode 100755 dev/com.ibm.ws.logging.hpel_fat/lib/htmlunit-2.4.jar create mode 100755 dev/com.ibm.ws.logging.hpel_fat/lib/phased.junit.jar create mode 100755 dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HPELDeleteLogDirectory_1.xml create mode 100755 dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HPELDeleteLogDirectory_2.xml create mode 100755 dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HPELPurgeMaxSizeInvalid.xml create mode 100755 dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HPELPurgeMaxSizeTest_1.xml create mode 100755 dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HPELPurgeMaxSizeTest_2.xml create mode 100755 dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HPELPurgeMaxSizeTest_3.xml create mode 100755 dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HPELPurgeMaxSizeTest_4.xml create mode 100755 dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HPELPurgeMaxSizeTest_5.xml create mode 100755 dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HPELPurgeMaxSizeTest_6.xml create mode 100755 dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HPELPurgeMaxSizeTest_7.xml create mode 100755 dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HPELPurgeMinTimeTest_1.xml create mode 100755 dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HPELPurgeMinTimeTest_2.xml create mode 100755 dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HpelDeleteEmptyDirectories.xml create mode 100755 dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HpelDirChangePurgeMaxTest_1.xml create mode 100755 dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HpelDirChangePurgeMaxTest_2.xml create mode 100755 dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HpelLogDirectoryChange_1.xml create mode 100755 dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HpelLogDirectoryChange_2.xml create mode 100755 dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HpelLogElementDelete_1.xml create mode 100755 dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HpelLogElementDelete_2.xml create mode 100755 dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HpelTextLogRetention.xml create mode 100755 dev/com.ibm.ws.logging.hpel_fat/publish/files/server-TraceSpecificationSetToAllTest.xml create mode 100644 dev/com.ibm.ws.logging.hpel_fat/publish/servers/HpelServer/.gitignore create mode 100755 dev/com.ibm.ws.logging.hpel_fat/publish/servers/HpelServer/bootstrap.properties create mode 100755 dev/com.ibm.ws.logging.hpel_fat/publish/servers/HpelServer/server.xml create mode 100755 dev/com.ibm.ws.logging.hpel_fat/test-applications/HpelFat/resources/LogCreator.jsp create mode 100755 dev/com.ibm.ws.logging.hpel_fat/test-applications/HpelFat/resources/META-INF/permissions.xml create mode 100755 dev/com.ibm.ws.logging.hpel_fat/test-applications/HpelFat/resources/WEB-INF/web.xml create mode 100755 dev/com.ibm.ws.logging.hpel_fat/test-applications/HpelFat/src/com/ibm/ws/logging/hpel/handlers/MyCustomHandler.java create mode 100755 dev/com.ibm.ws.logging.hpel_fat/test-applications/HpelFat/src/com/ibm/ws/logging/hpel_fat/WritingCustomLogServlet.java create mode 100755 dev/com.ibm.ws.logging.hpel_fat/test-applications/LogFat/resources/META-INF/permissions.xml create mode 100755 dev/com.ibm.ws.logging.hpel_fat/test-applications/LogFat/resources/WEB-INF/web.xml create mode 100755 dev/com.ibm.ws.logging.hpel_fat/test-applications/LogFat/src/com/ibm/ws/logging/hpel/LRCServlet.java create mode 100755 dev/com.ibm.ws.logging.hpel_fat/test-applications/LogFat/src/com/ibm/ws/test/LogDecoratorFilter.java create mode 100755 dev/com.ibm.ws.logging.hpel_fat/test-applications/LogFat/src/com/ibm/ws/test/ThreadLocalStringExtension.java create mode 100644 dev/com.ibm.ws.logging_fat/.classpath create mode 100644 dev/com.ibm.ws.logging_fat/.classpath.gradle create mode 100644 dev/com.ibm.ws.logging_fat/.gitignore create mode 100755 dev/com.ibm.ws.logging_fat/.project create mode 100755 dev/com.ibm.ws.logging_fat/.settings/org.eclipse.core.resources.prefs create mode 100755 dev/com.ibm.ws.logging_fat/.settings/org.eclipse.jdt.core.prefs create mode 100755 dev/com.ibm.ws.logging_fat/.settings/org.eclipse.jdt.ui.prefs create mode 100644 dev/com.ibm.ws.logging_fat/bnd.bnd create mode 100644 dev/com.ibm.ws.logging_fat/bnd.bnd.gradle create mode 100755 dev/com.ibm.ws.logging_fat/build-test.xml create mode 100644 dev/com.ibm.ws.logging_fat/build.gradle create mode 100755 dev/com.ibm.ws.logging_fat/delivery.sets create mode 100755 dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/AbstractStackTraceFilteringTest.java create mode 100755 dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/FATSuite.java create mode 100755 dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/HealthCenterTest.java create mode 100755 dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/InvalidTraceSpecificationTest.java create mode 100644 dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/IsoDateFormatTest.java create mode 100755 dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/StackTraceFilteringForBadlyWrittenThrowableTest.java create mode 100755 dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/StackTraceFilteringForIBMFeatureExceptionTest.java create mode 100755 dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/StackTraceFilteringForLoggedExceptionParametersTest.java create mode 100755 dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/StackTraceFilteringForLoggedExceptionWithACauseParametersTest.java create mode 100755 dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/StackTraceFilteringForNoClassDefFoundErrorTest.java create mode 100755 dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/StackTraceFilteringForPrintedExceptionTest.java create mode 100755 dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/StackTraceFilteringForPrintedExceptionWithIBMCodeAtTopTest.java create mode 100755 dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/StackTraceFilteringForSpecificationClassesExceptionTest.java create mode 100755 dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/StackTraceFilteringForUserFeatureExceptionTest.java create mode 100755 dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/TestHideMessages.java create mode 100755 dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/TestHideMsgDefinedBootstrap.java create mode 100644 dev/com.ibm.ws.logging_fat/publish/.gitignore create mode 100755 dev/com.ibm.ws.logging_fat/publish/features/unconfigurableIbmFeature-1.0.mf create mode 100755 dev/com.ibm.ws.logging_fat/publish/features/unconfigurableUserFeature-1.0.mf create mode 100755 dev/com.ibm.ws.logging_fat/publish/files/server-invalidIsoDateFormat.xml create mode 100755 dev/com.ibm.ws.logging_fat/publish/files/server-twomessageids.xml create mode 100644 dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.badconfig.ibm/.gitignore create mode 100755 dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.badconfig.ibm/bootstrap.properties create mode 100755 dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.badconfig.ibm/server.xml create mode 100644 dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.badconfig.user/.gitignore create mode 100755 dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.badconfig.user/bootstrap.properties create mode 100755 dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.badconfig.user/server.xml create mode 100755 dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.brokenserver/bootstrap.properties create mode 100755 dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.brokenserver/server.xml create mode 100755 dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.healthcenter/bootstrap.properties create mode 100755 dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.healthcenter/jvm.options create mode 100755 dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.healthcenter/server.xml create mode 100755 dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.hidemessage/server.xml create mode 100755 dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.hidemsg.bootstrap/bootstrap.properties create mode 100755 dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.hidemsg.bootstrap/server.xml create mode 100755 dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.isodateformat/bootstrap.properties create mode 100644 dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.isodateformat/server.xml create mode 100755 dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.missingfeatureserver/bootstrap.properties create mode 100755 dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.missingfeatureserver/server.xml create mode 100755 dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.tracespec/bootstrap.properties create mode 100755 dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.tracespec/server.xml create mode 100644 dev/com.ibm.ws.logging_fat/test-applications/broken-servlet/resources/.gitignore create mode 100755 dev/com.ibm.ws.logging_fat/test-applications/broken-servlet/resources/META-INF/MANIFEST.MF create mode 100755 dev/com.ibm.ws.logging_fat/test-applications/broken-servlet/src/com/ibm/ws/logging/fat/servlet/BrokenServlet.java create mode 100755 dev/com.ibm.ws.logging_fat/test-applications/broken-servlet/src/com/ibm/ws/logging/fat/servlet/BrokenWithABadlyWrittenThrowableServlet.java create mode 100755 dev/com.ibm.ws.logging_fat/test-applications/broken-servlet/src/com/ibm/ws/logging/fat/servlet/BrokenWithACauseServlet.java create mode 100755 dev/com.ibm.ws.logging_fat/test-applications/broken-servlet/src/com/ibm/ws/logging/fat/servlet/ExceptionPrintingServlet.java create mode 100755 dev/com.ibm.ws.logging_fat/test-applications/broken-servlet/src/com/ibm/ws/logging/fat/servlet/IBMCodeAtTopExceptionPrintingServlet.java create mode 100755 dev/com.ibm.ws.logging_fat/test-applications/broken-servlet/src/com/ibm/ws/logging/fat/servlet/SpecUsingServlet.java create mode 100644 dev/com.ibm.ws.logging_fat/test-applications/ffdc-servlet/resources/.gitignore create mode 100755 dev/com.ibm.ws.logging_fat/test-applications/ffdc-servlet/resources/META-INF/MANIFEST.MF create mode 100755 dev/com.ibm.ws.logging_fat/test-applications/ffdc-servlet/src/com/ibm/ws/logging/fat/servlet/FFDCServlet.java create mode 100644 dev/com.ibm.ws.logging_fat/test-applications/logger-servlet/resources/.gitignore create mode 100755 dev/com.ibm.ws.logging_fat/test-applications/logger-servlet/resources/META-INF/MANIFEST.MF create mode 100755 dev/com.ibm.ws.logging_fat/test-applications/logger-servlet/src/com/ibm/ws/logging/fat/servlet/LoggerServlet.java create mode 100644 dev/com.ibm.ws.logging_fat/test-applications/missing-feature-servlet/.gitignore create mode 100755 dev/com.ibm.ws.logging_fat/test-applications/missing-feature-servlet/src/com/ibm/ws/logging/fat/servlet/MissingEntityManagerServlet.java create mode 100755 dev/com.ibm.ws.logging_fat/test-bundles/test.configuration.fallalloverthefloor.ibmfeature/bnd.bnd create mode 100755 dev/com.ibm.ws.logging_fat/test-bundles/test.configuration.fallalloverthefloor.ibmfeature/resources/OSGI-INF/metatype/metatype.xml create mode 100755 dev/com.ibm.ws.logging_fat/test-bundles/test.configuration.fallalloverthefloor.ibmfeature/src/com/ibm/ws/logging/fat/fallalloverthefloor/ibmfeature/BrokenFeature.java create mode 100755 dev/com.ibm.ws.logging_fat/test-bundles/test.configuration.fallalloverthefloor.userfeature/bnd.bnd create mode 100755 dev/com.ibm.ws.logging_fat/test-bundles/test.configuration.fallalloverthefloor.userfeature/resources/OSGI-INF/metatype/metatype.xml create mode 100755 dev/com.ibm.ws.logging_fat/test-bundles/test.configuration.fallalloverthefloor.userfeature/src/com/ibm/ws/logging/fat/fallalloverthefloor/userfeature/BrokenFeature.java delete mode 100644 dev/com.ibm.ws.org.codehaus.jackson/.classpath.ant create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/.classpath create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/.classpath.gradle create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/.gitignore create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/.project create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/.settings/org.eclipse.core.resources.prefs create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/.settings/org.eclipse.jdt.core.prefs create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/.settings/org.eclipse.jdt.ui.prefs create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/bnd.bnd create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/bnd.bnd.gradle create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/build-test.xml create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/build.gradle create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/delivery.sets create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/fat/src/com/ibm/ws/org/glassfish/json/fat/FATSuite.java create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/fat/src/com/ibm/ws/org/glassfish/json/fat/tests/AbstractTest.java create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/fat/src/com/ibm/ws/org/glassfish/json/fat/tests/BasicJSONPTest.java create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/fat/src/com/ibm/ws/org/glassfish/json/fat/tests/CustomFeatureJSONPTest.java create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/publish/.gitignore create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/publish/features/customJsonpProvider-1.0.mf create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/publish/servers/com.ibm.ws.org.glassfish.json.fat.BasicJsonpServer/.gitignore create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/publish/servers/com.ibm.ws.org.glassfish.json.fat.BasicJsonpServer/bootstrap.properties create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/publish/servers/com.ibm.ws.org.glassfish.json.fat.BasicJsonpServer/build.properties create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/publish/servers/com.ibm.ws.org.glassfish.json.fat.BasicJsonpServer/server.xml create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/publish/servers/com.ibm.ws.org.glassfish.json.fat.CustomFeatureJsonpServer/.gitignore create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/publish/servers/com.ibm.ws.org.glassfish.json.fat.CustomFeatureJsonpServer/bootstrap.properties create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/publish/servers/com.ibm.ws.org.glassfish.json.fat.CustomFeatureJsonpServer/server.xml create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/test-applications/JSONPWAR.war/package.properties create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/test-applications/JSONPWAR.war/resources/META-INF/permissions.xml create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/test-applications/JSONPWAR.war/resources/WEB-INF/json_read_test_data.js create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/test-applications/JSONPWAR.war/src/com/ibm/ws/jsonp/fat/AbstractJSONPServlet.java create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/test-applications/JSONPWAR.war/src/com/ibm/ws/jsonp/fat/BuildJSONPServlet.java create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/test-applications/JSONPWAR.war/src/com/ibm/ws/jsonp/fat/ReadJSONPServlet.java create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/test-applications/JSONPWAR.war/src/com/ibm/ws/jsonp/fat/StreamJSONPServlet.java create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/test-applications/JSONPWAR.war/src/com/ibm/ws/jsonp/fat/WriteJSONPServlet.java create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customAppJSONPProvider.jar/resources/META-INF/permissions.xml create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customAppJSONPProvider.jar/resources/META-INF/services/javax.json.spi.JsonProvider create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customAppJSONPProvider.jar/src/com/ibm/ws/jsonp/app/provider/JsonParserImpl.java create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customAppJSONPProvider.jar/src/com/ibm/ws/jsonp/app/provider/JsonProviderImpl.java create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customAppJSONPWAR.war/package.properties create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customAppJSONPWAR.war/resources/META-INF/permissions.xml create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customAppJSONPWAR.war/src/com/ibm/ws/jsonp/fat/CustomAppJSONPServlet.java create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customFeatureJSONPWAR.war/package.properties create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customFeatureJSONPWAR.war/resources/META-INF/permissions.xml create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customFeatureJSONPWAR.war/src/com/ibm/ws/jsonp/fat/CustomFeatureJSONPServlet.java create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customLibJSONPProvider.jar/resources/META-INF/permissions.xml create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customLibJSONPProvider.jar/resources/META-INF/services/javax.json.spi.JsonProvider create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customLibJSONPProvider.jar/src/com/ibm/ws/jsonp/lib/provider/JsonParserImpl.java create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customLibJSONPProvider.jar/src/com/ibm/ws/jsonp/lib/provider/JsonProviderImpl.java create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customLibJSONPWAR.war/package.properties create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customLibJSONPWAR.war/resources/META-INF/permissions.xml create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customLibJSONPWAR.war/src/com/ibm/ws/jsonp/fat/CustomLibJSONPServlet.java create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/test-bundles/custom.jsonp/bnd.bnd create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/test-bundles/custom.jsonp/resources/META-INF/services/javax.json.spi.JsonProvider create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/test-bundles/custom.jsonp/src/com/ibm/ws/jsonp/feature/provider/JsonParserImpl.java create mode 100644 dev/com.ibm.ws.org.glassfish.json_fat/test-bundles/custom.jsonp/src/com/ibm/ws/jsonp/feature/provider/JsonProviderImpl.java delete mode 100644 dev/com.ibm.ws.org.osgi.service.resolver/.classpath.ant create mode 100644 dev/com.ibm.ws.product.utility_fat/.classpath create mode 100644 dev/com.ibm.ws.product.utility_fat/.classpath.gradle create mode 100644 dev/com.ibm.ws.product.utility_fat/.gitignore create mode 100755 dev/com.ibm.ws.product.utility_fat/.project create mode 100755 dev/com.ibm.ws.product.utility_fat/.settings/org.eclipse.core.resources.prefs create mode 100755 dev/com.ibm.ws.product.utility_fat/.settings/org.eclipse.jdt.core.prefs create mode 100755 dev/com.ibm.ws.product.utility_fat/.settings/org.eclipse.jdt.ui.prefs create mode 100644 dev/com.ibm.ws.product.utility_fat/bnd.bnd create mode 100644 dev/com.ibm.ws.product.utility_fat/bnd.bnd.gradle create mode 100755 dev/com.ibm.ws.product.utility_fat/build-test.xml create mode 100644 dev/com.ibm.ws.product.utility_fat/build.gradle create mode 100755 dev/com.ibm.ws.product.utility_fat/delivery.sets create mode 100755 dev/com.ibm.ws.product.utility_fat/fat/src/com/ibm/ws/product/utility/fat/FATSuite.java create mode 100755 dev/com.ibm.ws.product.utility_fat/fat/src/com/ibm/ws/product/utility/fat/ProductInfoLicenseFileTest.java create mode 100755 dev/com.ibm.ws.product.utility_fat/fat/src/com/ibm/ws/product/utility/fat/ProductInfoToolTest.java create mode 100755 dev/com.ibm.ws.product.utility_fat/fat/src/com/ibm/ws/product/utility/fat/ProductInfoValidateTest.java create mode 100755 dev/com.ibm.ws.product.utility_fat/fat/src/com/ibm/ws/product/utility/fat/ProductToolTestCommon.java create mode 100755 dev/com.ibm.ws.product.utility_fat/fat/src/com/ibm/ws/product/utility/fat/ProductUtilToolTest.java create mode 100755 dev/com.ibm.ws.product.utility_fat/publish/features/usertest.esa create mode 100755 dev/com.ibm.ws.product.utility_fat/publish/features/usertest.with.versions.props.file.esa create mode 100755 dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/LA_cs create mode 100755 dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/LA_de create mode 100755 dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/LA_el create mode 100755 dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/LA_en create mode 100755 dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/LA_es create mode 100755 dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/LA_fr create mode 100755 dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/LA_in create mode 100755 dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/LA_it create mode 100755 dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/LA_ja create mode 100755 dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/LA_ko create mode 100755 dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/LA_lt create mode 100755 dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/LA_pl create mode 100755 dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/LA_pt create mode 100755 dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/LA_ru create mode 100755 dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/LA_sl create mode 100755 dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/LA_tr create mode 100755 dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/LA_zh create mode 100755 dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/LA_zh_TW create mode 100755 dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/LI_cs create mode 100755 dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/LI_de create mode 100755 dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/LI_el create mode 100755 dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/LI_en create mode 100755 dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/LI_es create mode 100755 dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/LI_fr create mode 100755 dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/LI_in create mode 100755 dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/LI_it create mode 100755 dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/LI_ja create mode 100755 dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/LI_ko create mode 100755 dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/LI_lt create mode 100755 dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/LI_pl create mode 100755 dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/LI_pt create mode 100755 dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/LI_ru create mode 100755 dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/LI_sl create mode 100755 dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/LI_tr create mode 100755 dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/LI_zh create mode 100755 dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/LI_zh_TW create mode 100755 dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/notices create mode 100755 dev/com.ibm.ws.product.utility_fat/publish/files/productBundles/com.ibm.ws.prodtest.internal_1.0.jar create mode 100755 dev/com.ibm.ws.product.utility_fat/publish/files/productFeatures/prodtest-1.0.mf create mode 100755 dev/com.ibm.ws.product.utility_fat/publish/files/productProperties/testproduct.properties create mode 100755 dev/com.ibm.ws.product.utility_fat/publish/files/productVersionProperties/producttest.properties create mode 100755 dev/com.ibm.ws.product.utility_fat/publish/files/productVersionProperties/usertest.properties create mode 100755 dev/com.ibm.ws.product.utility_fat/publish/servers/com.ibm.ws.kernel.feature.fat.info.tool/bootstrap.properties create mode 100755 dev/com.ibm.ws.product.utility_fat/publish/servers/com.ibm.ws.kernel.feature.fat.util.tool/bootstrap.properties create mode 100755 dev/com.ibm.ws.product.utility_fat/publish/servers/com.ibm.ws.product.utility.test.validate.server/bootstrap.properties create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/lafiles/LA_cs create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/lafiles/LA_de create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/lafiles/LA_el create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/lafiles/LA_en create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/lafiles/LA_es create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/lafiles/LA_fr create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/lafiles/LA_in create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/lafiles/LA_it create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/lafiles/LA_ja create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/lafiles/LA_ko create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/lafiles/LA_lt create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/lafiles/LA_pl create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/lafiles/LA_pt create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/lafiles/LA_ru create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/lafiles/LA_sl create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/lafiles/LA_tr create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/lafiles/LA_zh create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/lafiles/LA_zh_TW create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/lafiles/LI_cs create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/lafiles/LI_de create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/lafiles/LI_el create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/lafiles/LI_en create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/lafiles/LI_es create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/lafiles/LI_fr create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/lafiles/LI_in create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/lafiles/LI_it create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/lafiles/LI_ja create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/lafiles/LI_ko create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/lafiles/LI_lt create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/lafiles/LI_pl create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/lafiles/LI_pt create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/lafiles/LI_ru create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/lafiles/LI_sl create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/lafiles/LI_tr create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/lafiles/LI_zh create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/lafiles/LI_zh_TW create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/lafiles/notices create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/lafiles/testFile create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/lafiles/testfile1 create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/md5Tests/TestFile.txt create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/mockInstalls/TwoAparsArchiveFixPack.jar create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/mockInstalls/badDate/lib/fixes/badDate.xml create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/mockInstalls/badDate/lib/versions/WebSphereApplicationServer.properties create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/mockInstalls/invalidZip/lib/versions/WebSphereApplicationServer.properties create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/mockInstalls/invalidZip/lib/versions/wlp_fp8509_aparIds.zip create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/mockInstalls/missingFeatureJar/lib/a_1.1.0.jar create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/mockInstalls/missingFeatureJar/lib/fixes/missingFeatureJar.xml create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/mockInstalls/missingFeatureJar/lib/versions/WebSphereApplicationServer.properties create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/mockInstalls/missingFeatureJar/lib/versions/wlp_fp8501_aparIds.zip create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/mockInstalls/missingFeatureJar/lib/versions/wlp_fp8502_aparIds.zip create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/mockInstalls/noApar/lib/fixes/noApar.xml create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/mockInstalls/noApar/lib/foo.txt create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/mockInstalls/noApar/lib/versions/WebSphereApplicationServer.properties create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/mockInstalls/noApar/lib/versions/wlp_fp8501_aparIds.zip create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/mockInstalls/noApar/lib/versions/wlp_fp8502_aparIds.zip create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/mockInstalls/noOffering/lib/fixes/noOffering.xml create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/mockInstalls/noOffering/lib/foo.txt create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/mockInstalls/noOffering/lib/versions/WebSphereApplicationServer.properties create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/mockInstalls/noProperties/lib/fixes/noProperties.xml create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/mockInstalls/noProperties/lib/foo.txt create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/mockInstalls/noProperties/lib/versions/OtherProps.properties create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/mockInstalls/oldStaticFile/lib/fixes/oldStaticFile.xml create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/mockInstalls/oldStaticFile/lib/foo.txt create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/mockInstalls/oldStaticFile/lib/versions/WebSphereApplicationServer.properties create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/mockInstalls/oldStaticFile/lib/versions/wlp_fp8501_aparIds.zip create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/mockInstalls/oldStaticFile/lib/versions/wlp_fp8502_aparIds.zip create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/mockInstalls/oldVersion/lib/fixes/oldStaticFile.xml create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/mockInstalls/oldVersion/lib/foo.txt create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/mockInstalls/oldVersion/lib/versions/WebSphereApplicationServer.properties create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/mockInstalls/oldVersion/lib/versions/wlp_fp8501_aparIds.zip create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/mockInstalls/oldVersion/lib/versions/wlp_fp8502_aparIds.zip create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/mockInstalls/oneFixPackThreeApars/lib/versions/WebSphereApplicationServer.properties create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/mockInstalls/oneFixPackThreeApars/lib/versions/wlp_fp8505_aparIds.zip create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/mockInstalls/oneIFixTwoFP/lib/a_1.1.0.v20120424-1542.jar create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/mockInstalls/oneIFixTwoFP/lib/b_1.1.0.v20120424-1542.jar create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/mockInstalls/oneIFixTwoFP/lib/fixes/iFix1.xml create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/mockInstalls/oneIFixTwoFP/lib/versions/WebSphereApplicationServer.properties create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/mockInstalls/oneIFixTwoFP/lib/versions/wlp_fp8501_aparIds.zip create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/mockInstalls/oneIFixTwoFP/lib/versions/wlp_fp8502_aparIds.zip create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/mockInstalls/twoIFixesThreeAparsTwoFP/lib/a_1.1.0.v20120424-1542.jar create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/mockInstalls/twoIFixesThreeAparsTwoFP/lib/b_1.1.0.v20120424-1542.jar create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/mockInstalls/twoIFixesThreeAparsTwoFP/lib/fixes/iFix1.xml create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/mockInstalls/twoIFixesThreeAparsTwoFP/lib/fixes/iFix2.xml create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/mockInstalls/twoIFixesThreeAparsTwoFP/lib/versions/WebSphereApplicationServer.properties create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/mockInstalls/twoIFixesThreeAparsTwoFP/lib/versions/wlp_fp8501_aparIds.zip create mode 100755 dev/com.ibm.ws.product.utility_fat/resources/mockInstalls/twoIFixesThreeAparsTwoFP/lib/versions/wlp_fp8502_aparIds.zip create mode 100644 dev/com.ibm.ws.product.utility_test/.classpath create mode 100644 dev/com.ibm.ws.product.utility_test/.classpath.gradle create mode 100644 dev/com.ibm.ws.product.utility_test/.gitignore create mode 100755 dev/com.ibm.ws.product.utility_test/.project create mode 100755 dev/com.ibm.ws.product.utility_test/.settings/org.eclipse.core.resources.prefs create mode 100755 dev/com.ibm.ws.product.utility_test/.settings/org.eclipse.jdt.core.prefs create mode 100755 dev/com.ibm.ws.product.utility_test/.settings/org.eclipse.jdt.ui.prefs create mode 100755 dev/com.ibm.ws.product.utility_test/bnd.bnd create mode 100755 dev/com.ibm.ws.product.utility_test/bnd.bnd.gradle create mode 100755 dev/com.ibm.ws.product.utility_test/build-unittest.xml create mode 100644 dev/com.ibm.ws.product.utility_test/build.gradle create mode 100755 dev/com.ibm.ws.product.utility_test/delivery.sets create mode 100755 dev/com.ibm.ws.product.utility_test/resources/lafiles/LA_cs create mode 100755 dev/com.ibm.ws.product.utility_test/resources/lafiles/LA_de create mode 100755 dev/com.ibm.ws.product.utility_test/resources/lafiles/LA_el create mode 100755 dev/com.ibm.ws.product.utility_test/resources/lafiles/LA_en create mode 100755 dev/com.ibm.ws.product.utility_test/resources/lafiles/LA_es create mode 100755 dev/com.ibm.ws.product.utility_test/resources/lafiles/LA_fr create mode 100755 dev/com.ibm.ws.product.utility_test/resources/lafiles/LA_in create mode 100755 dev/com.ibm.ws.product.utility_test/resources/lafiles/LA_it create mode 100755 dev/com.ibm.ws.product.utility_test/resources/lafiles/LA_ja create mode 100755 dev/com.ibm.ws.product.utility_test/resources/lafiles/LA_ko create mode 100755 dev/com.ibm.ws.product.utility_test/resources/lafiles/LA_lt create mode 100755 dev/com.ibm.ws.product.utility_test/resources/lafiles/LA_pl create mode 100755 dev/com.ibm.ws.product.utility_test/resources/lafiles/LA_pt create mode 100755 dev/com.ibm.ws.product.utility_test/resources/lafiles/LA_ru create mode 100755 dev/com.ibm.ws.product.utility_test/resources/lafiles/LA_sl create mode 100755 dev/com.ibm.ws.product.utility_test/resources/lafiles/LA_tr create mode 100755 dev/com.ibm.ws.product.utility_test/resources/lafiles/LA_zh create mode 100755 dev/com.ibm.ws.product.utility_test/resources/lafiles/LA_zh_TW create mode 100755 dev/com.ibm.ws.product.utility_test/resources/lafiles/LI_cs create mode 100755 dev/com.ibm.ws.product.utility_test/resources/lafiles/LI_de create mode 100755 dev/com.ibm.ws.product.utility_test/resources/lafiles/LI_el create mode 100755 dev/com.ibm.ws.product.utility_test/resources/lafiles/LI_en create mode 100755 dev/com.ibm.ws.product.utility_test/resources/lafiles/LI_es create mode 100755 dev/com.ibm.ws.product.utility_test/resources/lafiles/LI_fr create mode 100755 dev/com.ibm.ws.product.utility_test/resources/lafiles/LI_in create mode 100755 dev/com.ibm.ws.product.utility_test/resources/lafiles/LI_it create mode 100755 dev/com.ibm.ws.product.utility_test/resources/lafiles/LI_ja create mode 100755 dev/com.ibm.ws.product.utility_test/resources/lafiles/LI_ko create mode 100755 dev/com.ibm.ws.product.utility_test/resources/lafiles/LI_lt create mode 100755 dev/com.ibm.ws.product.utility_test/resources/lafiles/LI_pl create mode 100755 dev/com.ibm.ws.product.utility_test/resources/lafiles/LI_pt create mode 100755 dev/com.ibm.ws.product.utility_test/resources/lafiles/LI_ru create mode 100755 dev/com.ibm.ws.product.utility_test/resources/lafiles/LI_sl create mode 100755 dev/com.ibm.ws.product.utility_test/resources/lafiles/LI_tr create mode 100755 dev/com.ibm.ws.product.utility_test/resources/lafiles/LI_zh create mode 100755 dev/com.ibm.ws.product.utility_test/resources/lafiles/LI_zh_TW create mode 100755 dev/com.ibm.ws.product.utility_test/resources/lafiles/notices create mode 100755 dev/com.ibm.ws.product.utility_test/resources/lafiles/testFile create mode 100755 dev/com.ibm.ws.product.utility_test/resources/lafiles/testfile1 create mode 100755 dev/com.ibm.ws.product.utility_test/resources/md5Tests/TestFile.txt create mode 100755 dev/com.ibm.ws.product.utility_test/resources/mockInstalls/TwoAparsArchiveFixPack.jar create mode 100755 dev/com.ibm.ws.product.utility_test/resources/mockInstalls/badDate/lib/fixes/badDate.xml create mode 100755 dev/com.ibm.ws.product.utility_test/resources/mockInstalls/badDate/lib/versions/WebSphereApplicationServer.properties create mode 100755 dev/com.ibm.ws.product.utility_test/resources/mockInstalls/invalidZip/lib/versions/WebSphereApplicationServer.properties create mode 100755 dev/com.ibm.ws.product.utility_test/resources/mockInstalls/invalidZip/lib/versions/wlp_fp8509_aparIds.zip create mode 100755 dev/com.ibm.ws.product.utility_test/resources/mockInstalls/missingFeatureJar/lib/a_1.1.0.jar create mode 100755 dev/com.ibm.ws.product.utility_test/resources/mockInstalls/missingFeatureJar/lib/fixes/missingFeatureJar.xml create mode 100755 dev/com.ibm.ws.product.utility_test/resources/mockInstalls/missingFeatureJar/lib/versions/WebSphereApplicationServer.properties create mode 100755 dev/com.ibm.ws.product.utility_test/resources/mockInstalls/missingFeatureJar/lib/versions/wlp_fp8501_aparIds.zip create mode 100755 dev/com.ibm.ws.product.utility_test/resources/mockInstalls/missingFeatureJar/lib/versions/wlp_fp8502_aparIds.zip create mode 100755 dev/com.ibm.ws.product.utility_test/resources/mockInstalls/noApar/lib/fixes/noApar.xml create mode 100755 dev/com.ibm.ws.product.utility_test/resources/mockInstalls/noApar/lib/foo.txt create mode 100755 dev/com.ibm.ws.product.utility_test/resources/mockInstalls/noApar/lib/versions/WebSphereApplicationServer.properties create mode 100755 dev/com.ibm.ws.product.utility_test/resources/mockInstalls/noApar/lib/versions/wlp_fp8501_aparIds.zip create mode 100755 dev/com.ibm.ws.product.utility_test/resources/mockInstalls/noApar/lib/versions/wlp_fp8502_aparIds.zip create mode 100755 dev/com.ibm.ws.product.utility_test/resources/mockInstalls/noOffering/lib/fixes/noOffering.xml create mode 100755 dev/com.ibm.ws.product.utility_test/resources/mockInstalls/noOffering/lib/foo.txt create mode 100755 dev/com.ibm.ws.product.utility_test/resources/mockInstalls/noOffering/lib/versions/WebSphereApplicationServer.properties create mode 100755 dev/com.ibm.ws.product.utility_test/resources/mockInstalls/noProperties/lib/fixes/noProperties.xml create mode 100755 dev/com.ibm.ws.product.utility_test/resources/mockInstalls/noProperties/lib/foo.txt create mode 100755 dev/com.ibm.ws.product.utility_test/resources/mockInstalls/noProperties/lib/versions/OtherProps.properties create mode 100755 dev/com.ibm.ws.product.utility_test/resources/mockInstalls/oldStaticFile/lib/fixes/oldStaticFile.xml create mode 100755 dev/com.ibm.ws.product.utility_test/resources/mockInstalls/oldStaticFile/lib/foo.txt create mode 100755 dev/com.ibm.ws.product.utility_test/resources/mockInstalls/oldStaticFile/lib/versions/WebSphereApplicationServer.properties create mode 100755 dev/com.ibm.ws.product.utility_test/resources/mockInstalls/oldStaticFile/lib/versions/wlp_fp8501_aparIds.zip create mode 100755 dev/com.ibm.ws.product.utility_test/resources/mockInstalls/oldStaticFile/lib/versions/wlp_fp8502_aparIds.zip create mode 100755 dev/com.ibm.ws.product.utility_test/resources/mockInstalls/oldVersion/lib/fixes/oldStaticFile.xml create mode 100755 dev/com.ibm.ws.product.utility_test/resources/mockInstalls/oldVersion/lib/foo.txt create mode 100755 dev/com.ibm.ws.product.utility_test/resources/mockInstalls/oldVersion/lib/versions/WebSphereApplicationServer.properties create mode 100755 dev/com.ibm.ws.product.utility_test/resources/mockInstalls/oldVersion/lib/versions/wlp_fp8501_aparIds.zip create mode 100755 dev/com.ibm.ws.product.utility_test/resources/mockInstalls/oldVersion/lib/versions/wlp_fp8502_aparIds.zip create mode 100755 dev/com.ibm.ws.product.utility_test/resources/mockInstalls/oneFixPackThreeApars/lib/versions/WebSphereApplicationServer.properties create mode 100755 dev/com.ibm.ws.product.utility_test/resources/mockInstalls/oneFixPackThreeApars/lib/versions/wlp_fp8505_aparIds.zip create mode 100755 dev/com.ibm.ws.product.utility_test/resources/mockInstalls/oneIFixTwoFP/lib/a_1.1.0.v20120424-1542.jar create mode 100755 dev/com.ibm.ws.product.utility_test/resources/mockInstalls/oneIFixTwoFP/lib/b_1.1.0.v20120424-1542.jar create mode 100755 dev/com.ibm.ws.product.utility_test/resources/mockInstalls/oneIFixTwoFP/lib/fixes/iFix1.xml create mode 100755 dev/com.ibm.ws.product.utility_test/resources/mockInstalls/oneIFixTwoFP/lib/versions/WebSphereApplicationServer.properties create mode 100755 dev/com.ibm.ws.product.utility_test/resources/mockInstalls/oneIFixTwoFP/lib/versions/wlp_fp8501_aparIds.zip create mode 100755 dev/com.ibm.ws.product.utility_test/resources/mockInstalls/oneIFixTwoFP/lib/versions/wlp_fp8502_aparIds.zip create mode 100755 dev/com.ibm.ws.product.utility_test/resources/mockInstalls/twoIFixesThreeAparsTwoFP/lib/a_1.1.0.v20120424-1542.jar create mode 100755 dev/com.ibm.ws.product.utility_test/resources/mockInstalls/twoIFixesThreeAparsTwoFP/lib/b_1.1.0.v20120424-1542.jar create mode 100755 dev/com.ibm.ws.product.utility_test/resources/mockInstalls/twoIFixesThreeAparsTwoFP/lib/fixes/iFix1.xml create mode 100755 dev/com.ibm.ws.product.utility_test/resources/mockInstalls/twoIFixesThreeAparsTwoFP/lib/fixes/iFix2.xml create mode 100755 dev/com.ibm.ws.product.utility_test/resources/mockInstalls/twoIFixesThreeAparsTwoFP/lib/versions/WebSphereApplicationServer.properties create mode 100755 dev/com.ibm.ws.product.utility_test/resources/mockInstalls/twoIFixesThreeAparsTwoFP/lib/versions/wlp_fp8501_aparIds.zip create mode 100755 dev/com.ibm.ws.product.utility_test/resources/mockInstalls/twoIFixesThreeAparsTwoFP/lib/versions/wlp_fp8502_aparIds.zip create mode 100755 dev/com.ibm.ws.product.utility_test/unittest/src/com/ibm/ws/product/utility/BaseCommandTaskTest.java create mode 100755 dev/com.ibm.ws.product.utility_test/unittest/src/com/ibm/ws/product/utility/ExecutionContextTest.java create mode 100755 dev/com.ibm.ws.product.utility_test/unittest/src/com/ibm/ws/product/utility/HelpCommandTaskTest.java create mode 100755 dev/com.ibm.ws.product.utility_test/unittest/src/com/ibm/ws/product/utility/LicenseUtilityTest.java create mode 100755 dev/com.ibm.ws.product.utility_test/unittest/src/com/ibm/ws/product/utility/MD5UtilsTest.java create mode 100755 dev/com.ibm.ws.product.utility_test/unittest/src/com/ibm/ws/product/utility/extension/IFixCompareCommandTaskTest.java create mode 100755 dev/com.ibm.ws.product.utility_test/unittest/src/com/ibm/ws/product/utility/extension/IFixUtilsTest.java create mode 100755 dev/com.ibm.ws.product.utility_test/unittest/src/com/ibm/ws/product/utility/extension/ValidateCommandTest.java create mode 100755 dev/com.ibm.ws.product.utility_test/unittest/src/com/ibm/ws/product/utility/extension/utils/TestUtils.java create mode 100644 dev/com.ibm.ws.repository.resolver_fat/.classpath create mode 100644 dev/com.ibm.ws.repository.resolver_fat/.classpath.gradle create mode 100644 dev/com.ibm.ws.repository.resolver_fat/.gitignore create mode 100755 dev/com.ibm.ws.repository.resolver_fat/.project create mode 100755 dev/com.ibm.ws.repository.resolver_fat/.settings/org.eclipse.core.resources.prefs create mode 100755 dev/com.ibm.ws.repository.resolver_fat/.settings/org.eclipse.jdt.core.prefs create mode 100755 dev/com.ibm.ws.repository.resolver_fat/.settings/org.eclipse.jdt.ui.prefs create mode 100644 dev/com.ibm.ws.repository.resolver_fat/bnd.bnd create mode 100644 dev/com.ibm.ws.repository.resolver_fat/bnd.bnd.gradle create mode 100755 dev/com.ibm.ws.repository.resolver_fat/build-test.xml create mode 100644 dev/com.ibm.ws.repository.resolver_fat/build.gradle create mode 100755 dev/com.ibm.ws.repository.resolver_fat/fat/src/com/ibm/ws/repository/resolver/FATSuite.java create mode 100755 dev/com.ibm.ws.repository.resolver_fat/fat/src/com/ibm/ws/repository/resolver/RepositoryResolverTest.java create mode 100755 dev/com.ibm.ws.repository.resolver_fat/fat/src/com/ibm/ws/repository/resolver/ResolverTestUtils.java create mode 100755 dev/com.ibm.ws.repository.resolver_fat/fat/src/com/ibm/ws/repository/resolver/internal/RepositoryResolveContextFatTest.java create mode 100755 dev/com.ibm.ws.repository.test.utils/.classpath create mode 100644 dev/com.ibm.ws.repository.test.utils/.classpath.gradle create mode 100644 dev/com.ibm.ws.repository.test.utils/.gitignore create mode 100755 dev/com.ibm.ws.repository.test.utils/.project create mode 100755 dev/com.ibm.ws.repository.test.utils/.settings/org.eclipse.core.resources.prefs create mode 100755 dev/com.ibm.ws.repository.test.utils/.settings/org.eclipse.jdt.core.prefs create mode 100755 dev/com.ibm.ws.repository.test.utils/.settings/org.eclipse.jdt.ui.prefs create mode 100755 dev/com.ibm.ws.repository.test.utils/IBMInternalRootCA.der create mode 100644 dev/com.ibm.ws.repository.test.utils/bnd.bnd create mode 100644 dev/com.ibm.ws.repository.test.utils/bnd.bnd.gradle create mode 100755 dev/com.ibm.ws.repository.test.utils/build-noship.xml create mode 100644 dev/com.ibm.ws.repository.test.utils/build.gradle create mode 100755 dev/com.ibm.ws.repository.test.utils/delivery.sets create mode 100755 dev/com.ibm.ws.repository.test.utils/lib/larsServer.jar create mode 100755 dev/com.ibm.ws.repository.test.utils/src/com/ibm/ws/repository/base/AssetByIdMatcher.java create mode 100755 dev/com.ibm.ws.repository.test.utils/src/com/ibm/ws/repository/base/DeleteRepo.java create mode 100755 dev/com.ibm.ws.repository.test.utils/src/com/ibm/ws/repository/base/DirectoryRepositoryTestUtils.java create mode 100755 dev/com.ibm.ws.repository.test.utils/src/com/ibm/ws/repository/base/IBMInternalTrustManager.java create mode 100755 dev/com.ibm.ws.repository.test.utils/src/com/ibm/ws/repository/base/IBMInternalTrustManagerException.java create mode 100644 dev/com.ibm.ws.repository.test.utils/src/com/ibm/ws/repository/base/JsonAnyOrderMatcher.java create mode 100755 dev/com.ibm.ws.repository.test.utils/src/com/ibm/ws/repository/base/LoginInfoProvider.java create mode 100755 dev/com.ibm.ws.repository.test.utils/src/com/ibm/ws/repository/base/Marketplace.java create mode 100755 dev/com.ibm.ws.repository.test.utils/src/com/ibm/ws/repository/base/MarketplaceApiKey.java create mode 100755 dev/com.ibm.ws.repository.test.utils/src/com/ibm/ws/repository/base/NoRepoAvailableException.java create mode 100755 dev/com.ibm.ws.repository.test.utils/src/com/ibm/ws/repository/base/RepositoryTestBase.java create mode 100755 dev/com.ibm.ws.repository.test.utils/src/com/ibm/ws/repository/base/RepositoryTestUtils.java create mode 100755 dev/com.ibm.ws.repository.test.utils/src/com/ibm/ws/repository/base/RepositoryTestUtilsFactory.java create mode 100755 dev/com.ibm.ws.repository.test.utils/src/com/ibm/ws/repository/base/RestRepositoryTestUtils.java create mode 100644 dev/com.ibm.ws.repository.test.utils/src/com/ibm/ws/repository/base/RestoreTrustStoreRule.java create mode 100644 dev/com.ibm.ws.repository.test.utils/src/com/ibm/ws/repository/base/TempFileRule.java create mode 100755 dev/com.ibm.ws.repository.test.utils/src/com/ibm/ws/repository/base/TestBaseClass.java create mode 100755 dev/com.ibm.ws.repository.test.utils/src/com/ibm/ws/repository/base/ZipRepositoryTestUtils.java create mode 100755 dev/com.ibm.ws.repository.test.utils/src/com/ibm/ws/repository/base/servers/DirectoryConnectionRule.java create mode 100755 dev/com.ibm.ws.repository.test.utils/src/com/ibm/ws/repository/base/servers/LarsConnectionRule.java create mode 100755 dev/com.ibm.ws.repository.test.utils/src/com/ibm/ws/repository/base/servers/LarsServerRule.java create mode 100755 dev/com.ibm.ws.repository.test.utils/src/com/ibm/ws/repository/base/servers/MassiveConnectionRule.java create mode 100755 dev/com.ibm.ws.repository.test.utils/src/com/ibm/ws/repository/base/servers/MassiveServerRule.java create mode 100755 dev/com.ibm.ws.repository.test.utils/src/com/ibm/ws/repository/base/servers/RestRepositoryConnectionRule.java create mode 100755 dev/com.ibm.ws.repository.test.utils/src/com/ibm/ws/repository/test/utils/clients/AbstractFileWriteableClient.java create mode 100755 dev/com.ibm.ws.repository.test.utils/src/com/ibm/ws/repository/test/utils/clients/DirectoryWriteableClient.java create mode 100755 dev/com.ibm.ws.repository.test.utils/src/mongodb.properties create mode 100755 dev/com.ibm.ws.repository.test.utils_test/.classpath create mode 100644 dev/com.ibm.ws.repository.test.utils_test/.classpath.gradle create mode 100644 dev/com.ibm.ws.repository.test.utils_test/.gitignore create mode 100755 dev/com.ibm.ws.repository.test.utils_test/.project create mode 100755 dev/com.ibm.ws.repository.test.utils_test/.settings/org.eclipse.core.resources.prefs create mode 100755 dev/com.ibm.ws.repository.test.utils_test/.settings/org.eclipse.jdt.core.prefs create mode 100755 dev/com.ibm.ws.repository.test.utils_test/.settings/org.eclipse.jdt.ui.prefs create mode 100644 dev/com.ibm.ws.repository.test.utils_test/bnd.bnd create mode 100644 dev/com.ibm.ws.repository.test.utils_test/bnd.bnd.gradle create mode 100755 dev/com.ibm.ws.repository.test.utils_test/build-test.xml create mode 100644 dev/com.ibm.ws.repository.test.utils_test/build.gradle create mode 100755 dev/com.ibm.ws.repository.test.utils_test/fat/src/com/ibm/ws/repository/base/FATTest.java create mode 100755 dev/com.ibm.ws.repository.test.utils_test/publish/files/staticApiKeys.props create mode 100755 dev/com.ibm.ws.repository.test.utils_test/publish/files/staticApiKeysInvalidRepositories.props create mode 100644 dev/com.ibm.ws.runtime.update_fat/.classpath create mode 100644 dev/com.ibm.ws.runtime.update_fat/.classpath.gradle create mode 100644 dev/com.ibm.ws.runtime.update_fat/.gitignore create mode 100755 dev/com.ibm.ws.runtime.update_fat/.project create mode 100755 dev/com.ibm.ws.runtime.update_fat/.settings/org.eclipse.core.resources.prefs create mode 100755 dev/com.ibm.ws.runtime.update_fat/.settings/org.eclipse.jdt.core.prefs create mode 100755 dev/com.ibm.ws.runtime.update_fat/.settings/org.eclipse.jdt.ui.prefs create mode 100644 dev/com.ibm.ws.runtime.update_fat/bnd.bnd create mode 100644 dev/com.ibm.ws.runtime.update_fat/bnd.bnd.gradle create mode 100755 dev/com.ibm.ws.runtime.update_fat/build-test.xml create mode 100644 dev/com.ibm.ws.runtime.update_fat/build.gradle create mode 100755 dev/com.ibm.ws.runtime.update_fat/fat/src/com/ibm/ws/runtime/update/fat/ConfigUpdateDeliveryTest.java create mode 100755 dev/com.ibm.ws.runtime.update_fat/fat/src/com/ibm/ws/runtime/update/fat/FATSuite.java create mode 100755 dev/com.ibm.ws.runtime.update_fat/fat/src/com/ibm/ws/runtime/update/fat/RuntimeQuiesceTest.java create mode 100755 dev/com.ibm.ws.runtime.update_fat/publish/features/quiescelistener-1.0.mf create mode 100755 dev/com.ibm.ws.runtime.update_fat/publish/files/bad-quiesce-listener.server.xml create mode 100755 dev/com.ibm.ws.runtime.update_fat/publish/files/local-connector-server.xml create mode 100755 dev/com.ibm.ws.runtime.update_fat/publish/files/longrunning-quiesce-listener.server.xml create mode 100755 dev/com.ibm.ws.runtime.update_fat/publish/files/no-quiesce-listener.server.xml create mode 100755 dev/com.ibm.ws.runtime.update_fat/publish/files/quiesce-listener.server.xml create mode 100755 dev/com.ibm.ws.runtime.update_fat/publish/files/user-quiesce-listener.server.xml create mode 100755 dev/com.ibm.ws.runtime.update_fat/publish/servers/com.ibm.ws.runtime.quiesce.fat/bootstrap.properties create mode 100755 dev/com.ibm.ws.runtime.update_fat/publish/servers/com.ibm.ws.runtime.quiesce.fat/server.xml create mode 100755 dev/com.ibm.ws.runtime.update_fat/publish/servers/com.ibm.ws.runtime.update.fat/bootstrap.properties create mode 100755 dev/com.ibm.ws.runtime.update_fat/publish/servers/com.ibm.ws.runtime.update.fat/server.xml create mode 100755 dev/com.ibm.ws.runtime.update_fat/test-applications/mbean/resources/META-INF/permissions.xml create mode 100755 dev/com.ibm.ws.runtime.update_fat/test-applications/mbean/resources/WEB-INF/web.xml create mode 100755 dev/com.ibm.ws.runtime.update_fat/test-applications/mbean/src/web/MBeanServlet.java create mode 100755 dev/com.ibm.ws.runtime.update_fat/test-bundles/test.server.quiesce/bnd.bnd create mode 100755 dev/com.ibm.ws.runtime.update_fat/test-bundles/test.server.quiesce/resources/OSGI-INF/metatype/metatype.xml create mode 100755 dev/com.ibm.ws.runtime.update_fat/test-bundles/test.server.quiesce/src/test/server/quiesce/TestQuiesceListener.java create mode 100644 dev/com.ibm.ws.security.utility_fat/.classpath create mode 100644 dev/com.ibm.ws.security.utility_fat/.classpath.gradle create mode 100644 dev/com.ibm.ws.security.utility_fat/.gitignore create mode 100755 dev/com.ibm.ws.security.utility_fat/.project create mode 100755 dev/com.ibm.ws.security.utility_fat/.settings/org.eclipse.core.resources.prefs create mode 100755 dev/com.ibm.ws.security.utility_fat/.settings/org.eclipse.jdt.core.prefs create mode 100755 dev/com.ibm.ws.security.utility_fat/.settings/org.eclipse.jdt.ui.prefs create mode 100644 dev/com.ibm.ws.security.utility_fat/bnd.bnd create mode 100644 dev/com.ibm.ws.security.utility_fat/bnd.bnd.gradle create mode 100755 dev/com.ibm.ws.security.utility_fat/build-test.xml create mode 100644 dev/com.ibm.ws.security.utility_fat/build.gradle create mode 100755 dev/com.ibm.ws.security.utility_fat/fat/src/com/ibm/ws/security/utility/test/FATSuite.java create mode 100755 dev/com.ibm.ws.security.utility_fat/fat/src/com/ibm/ws/security/utility/test/SecurityUtilityEncodeTest.java create mode 100755 dev/com.ibm.ws.security.utility_fat/fat/src/com/ibm/ws/security/utility/test/SecurityUtilityScriptUtils.java create mode 100644 dev/com.ibm.ws.threading_fat/.classpath create mode 100644 dev/com.ibm.ws.threading_fat/.classpath.gradle create mode 100644 dev/com.ibm.ws.threading_fat/.gitignore create mode 100755 dev/com.ibm.ws.threading_fat/.project create mode 100755 dev/com.ibm.ws.threading_fat/.settings/org.eclipse.core.resources.prefs create mode 100755 dev/com.ibm.ws.threading_fat/.settings/org.eclipse.jdt.core.prefs create mode 100755 dev/com.ibm.ws.threading_fat/.settings/org.eclipse.jdt.ui.prefs create mode 100644 dev/com.ibm.ws.threading_fat/bnd.bnd create mode 100644 dev/com.ibm.ws.threading_fat/bnd.bnd.gradle create mode 100755 dev/com.ibm.ws.threading_fat/build-test.xml create mode 100644 dev/com.ibm.ws.threading_fat/build.gradle create mode 100755 dev/com.ibm.ws.threading_fat/delivery.sets create mode 100755 dev/com.ibm.ws.threading_fat/fat/src/com/ibm/ws/threading/fat/FATSuite.java create mode 100755 dev/com.ibm.ws.threading_fat/fat/src/com/ibm/ws/threading/fat/MemLeakTest.java create mode 100755 dev/com.ibm.ws.threading_fat/fat/src/com/ibm/ws/threading/fat/ThreadingExtensionFAT.java create mode 100644 dev/com.ibm.ws.threading_fat/publish/.gitignore create mode 100644 dev/com.ibm.ws.threading_fat/publish/files/.gitignore create mode 100755 dev/com.ibm.ws.threading_fat/publish/files/features/threadingMemLeakTestFeature-1.0.mf create mode 100755 dev/com.ibm.ws.threading_fat/publish/files/features/threadingTestFeature-1.0.mf create mode 100755 dev/com.ibm.ws.threading_fat/publish/servers/com.ibm.ws.threading.memleak_fat_server/bootstrap.properties create mode 100755 dev/com.ibm.ws.threading_fat/publish/servers/com.ibm.ws.threading.memleak_fat_server/server.xml create mode 100644 dev/com.ibm.ws.threading_fat/publish/servers/com.ibm.ws.threading_fat_server/.gitignore create mode 100755 dev/com.ibm.ws.threading_fat/publish/servers/com.ibm.ws.threading_fat_server/bootstrap.properties create mode 100755 dev/com.ibm.ws.threading_fat/publish/servers/com.ibm.ws.threading_fat_server/server.xml create mode 100644 dev/com.ibm.ws.threading_fat/test-applications/threadingtestapp/.gitignore create mode 100755 dev/com.ibm.ws.threading_fat/test-applications/threadingtestapp/src/web/ThreadingTestServlet.java create mode 100755 dev/com.ibm.ws.threading_fat/test-bundles/threadingmemleaktestbundle/bnd.bnd create mode 100755 dev/com.ibm.ws.threading_fat/test-bundles/threadingmemleaktestbundle/src/test/bundle/threading/MemLeakChecker.java create mode 100755 dev/com.ibm.ws.threading_fat/test-bundles/threadingtestbundle/bnd.bnd create mode 100755 dev/com.ibm.ws.threading_fat/test-bundles/threadingtestbundle/src/test/bundle/threading/TaskInterceptorImpl.java create mode 100755 dev/com.ibm.ws.threading_fat/test-bundles/threadingtestbundle/src/test/bundle/threading/ThreadFactoryImpl.java create mode 100644 dev/com.ibm.ws.zos.command.processing_zfat/.classpath create mode 100644 dev/com.ibm.ws.zos.command.processing_zfat/.classpath.gradle create mode 100755 dev/com.ibm.ws.zos.command.processing_zfat/.project create mode 100755 dev/com.ibm.ws.zos.command.processing_zfat/.settings/org.eclipse.jdt.core.prefs create mode 100755 dev/com.ibm.ws.zos.command.processing_zfat/.settings/org.eclipse.ltk.core.refactoring.prefs create mode 100644 dev/com.ibm.ws.zos.command.processing_zfat/bnd.bnd create mode 100644 dev/com.ibm.ws.zos.command.processing_zfat/bnd.bnd.gradle create mode 100755 dev/com.ibm.ws.zos.command.processing_zfat/build-ztest.xml create mode 100644 dev/com.ibm.ws.zos.command.processing_zfat/build.gradle create mode 100644 dev/com.ibm.ws.zos.command.processing_zfat/fat/src/com/ibm/ws/zos/command/processing/zfat/FATSuite.java create mode 100755 dev/com.ibm.ws.zos.command.processing_zfat/fat/src/com/ibm/ws/zos/command/processing/zfat/FATTest.java create mode 100644 dev/com.ibm.ws.zos.command.processing_zfat/fat/src/com/ibm/ws/zos/command/processing/zfat/ZosCommandHandlerTest.java create mode 100644 dev/com.ibm.ws.zos.command.processing_zfat/fat/src/com/ibm/ws/zos/command/processing/zfat/ZosCommandHandlerUtility.java create mode 100755 dev/com.ibm.ws.zos.command.processing_zfat/publish/files/NoConsole/bootstrap.properties create mode 100755 dev/com.ibm.ws.zos.command.processing_zfat/publish/files/bootstrap.properties create mode 100644 dev/com.ibm.ws.zos.command.processing_zfat/publish/files/bundles/.gitignore create mode 100644 dev/com.ibm.ws.zos.command.processing_zfat/publish/files/productExtensions/features/userProdtest-1.0.mf create mode 100755 dev/com.ibm.ws.zos.command.processing_zfat/publish/files/server.xml create mode 100755 dev/com.ibm.ws.zos.command.processing_zfat/publish/servers/COM.IBM.WS.ZOS.COMMAND.PROCESSING/bootstrap.properties create mode 100755 dev/com.ibm.ws.zos.command.processing_zfat/publish/servers/COM.IBM.WS.ZOS.COMMAND.PROCESSING/server.xml create mode 100644 dev/com.ibm.ws.zos.command.processing_zfat/publish/servers/com.ibm.ws.zos.command.feature/bootstrap.properties create mode 100644 dev/com.ibm.ws.zos.command.processing_zfat/publish/servers/com.ibm.ws.zos.command.feature/server.xml create mode 100644 dev/com.ibm.ws.zos.command.processing_zfat/test-bundles/userExtension/bnd.bnd create mode 100644 dev/com.ibm.ws.zos.command.processing_zfat/test-bundles/userExtension/resources/metatype.xml create mode 100644 dev/com.ibm.ws.zos.command.processing_zfat/test-bundles/userExtension/src/test/user/prod/extension/internal/commandhandler/UserProductExtensionCommandHandler.java create mode 100644 dev/com.ibm.ws.zos.command.processing_ztest/.classpath create mode 100644 dev/com.ibm.ws.zos.command.processing_ztest/.classpath.gradle create mode 100644 dev/com.ibm.ws.zos.command.processing_ztest/.gitignore create mode 100755 dev/com.ibm.ws.zos.command.processing_ztest/.project create mode 100755 dev/com.ibm.ws.zos.command.processing_ztest/.settings/org.eclipse.core.resources.prefs create mode 100755 dev/com.ibm.ws.zos.command.processing_ztest/.settings/org.eclipse.jdt.core.prefs create mode 100755 dev/com.ibm.ws.zos.command.processing_ztest/.settings/org.eclipse.jdt.ui.prefs create mode 100755 dev/com.ibm.ws.zos.command.processing_ztest/bnd.bnd create mode 100755 dev/com.ibm.ws.zos.command.processing_ztest/bnd.bnd.gradle create mode 100755 dev/com.ibm.ws.zos.command.processing_ztest/build-zunittest.xml create mode 100644 dev/com.ibm.ws.zos.command.processing_ztest/build.gradle create mode 100755 dev/com.ibm.ws.zos.command.processing_ztest/unittest/src/com/ibm/ws/zos/command/processing/internal/UnitTest.java create mode 100644 dev/com.ibm.ws.zos.logging_zfat/.classpath create mode 100644 dev/com.ibm.ws.zos.logging_zfat/.classpath.gradle create mode 100644 dev/com.ibm.ws.zos.logging_zfat/.gitignore create mode 100755 dev/com.ibm.ws.zos.logging_zfat/.project create mode 100755 dev/com.ibm.ws.zos.logging_zfat/.settings/org.eclipse.jdt.core.prefs create mode 100644 dev/com.ibm.ws.zos.logging_zfat/bnd.bnd create mode 100644 dev/com.ibm.ws.zos.logging_zfat/bnd.bnd.gradle create mode 100755 dev/com.ibm.ws.zos.logging_zfat/build-ztest.xml create mode 100644 dev/com.ibm.ws.zos.logging_zfat/build.gradle create mode 100755 dev/com.ibm.ws.zos.logging_zfat/fat/src/com/ibm/ws/zos/logging/zfat/EbcdicUtils.java create mode 100755 dev/com.ibm.ws.zos.logging_zfat/fat/src/com/ibm/ws/zos/logging/zfat/FATSuite.java create mode 100755 dev/com.ibm.ws.zos.logging_zfat/fat/src/com/ibm/ws/zos/logging/zfat/ZosLoggingTest.java create mode 100644 dev/com.ibm.ws.zos.logging_zfat/publish/.gitignore create mode 100755 dev/com.ibm.ws.zos.logging_zfat/publish/files/bbgzsrv1.jcl create mode 100755 dev/com.ibm.ws.zos.logging_zfat/publish/files/bbgzsrv1.msglog.jcl create mode 100755 dev/com.ibm.ws.zos.logging_zfat/publish/files/bbgzsrv1.msglog.segment.jcl create mode 100755 dev/com.ibm.ws.zos.logging_zfat/publish/files/msgRouterConfig.xml create mode 100755 dev/com.ibm.ws.zos.logging_zfat/publish/files/msgRouterConfig2.xml create mode 100755 dev/com.ibm.ws.zos.logging_zfat/publish/servers/defaultServer/bootstrap.properties create mode 100755 dev/com.ibm.ws.zos.logging_zfat/publish/servers/defaultServer/server.xml create mode 100644 dev/com.ibm.ws.zos.logging_ztest/.classpath create mode 100644 dev/com.ibm.ws.zos.logging_ztest/.classpath.gradle create mode 100644 dev/com.ibm.ws.zos.logging_ztest/.gitignore create mode 100755 dev/com.ibm.ws.zos.logging_ztest/.project create mode 100755 dev/com.ibm.ws.zos.logging_ztest/.settings/org.eclipse.core.resources.prefs create mode 100755 dev/com.ibm.ws.zos.logging_ztest/.settings/org.eclipse.jdt.core.prefs create mode 100755 dev/com.ibm.ws.zos.logging_ztest/.settings/org.eclipse.jdt.ui.prefs create mode 100755 dev/com.ibm.ws.zos.logging_ztest/bnd.bnd create mode 100755 dev/com.ibm.ws.zos.logging_ztest/bnd.bnd.gradle create mode 100755 dev/com.ibm.ws.zos.logging_ztest/build-zunittest.xml create mode 100644 dev/com.ibm.ws.zos.logging_ztest/build.gradle create mode 100755 dev/com.ibm.ws.zos.logging_ztest/unittest/src/com/ibm/ws/zos/logging/internal/LoggingHardcopyLogHandlerTest.java create mode 100755 dev/com.ibm.ws.zos.logging_ztest/unittest/src/com/ibm/ws/zos/logging/internal/ZosLoggingBundleActivatorTest.java create mode 100644 dev/wlp.lib.extract_fat/.classpath create mode 100644 dev/wlp.lib.extract_fat/.classpath.gradle create mode 100644 dev/wlp.lib.extract_fat/.gitignore create mode 100755 dev/wlp.lib.extract_fat/.project create mode 100755 dev/wlp.lib.extract_fat/.settings/org.eclipse.core.resources.prefs create mode 100755 dev/wlp.lib.extract_fat/.settings/org.eclipse.jdt.core.prefs create mode 100755 dev/wlp.lib.extract_fat/.settings/org.eclipse.jdt.ui.prefs create mode 100644 dev/wlp.lib.extract_fat/bnd.bnd create mode 100644 dev/wlp.lib.extract_fat/bnd.bnd.gradle create mode 100755 dev/wlp.lib.extract_fat/build-test.xml create mode 100644 dev/wlp.lib.extract_fat/build.gradle create mode 100755 dev/wlp.lib.extract_fat/delivery.sets create mode 100755 dev/wlp.lib.extract_fat/fat/src/wlp/lib/extract/ExternalDependencyDownloadTest.java create mode 100755 dev/wlp.lib.extract_fat/fat/src/wlp/lib/extract/FATSuite.java create mode 100755 dev/wlp.lib.extract_fat/fat/src/wlp/lib/extract/PackageRunnableTest.java create mode 100755 dev/wlp.lib.extract_fat/publish/files/MANIFEST.MF create mode 100755 dev/wlp.lib.extract_fat/publish/files/sampleServer.xml create mode 100644 dev/wlp.lib.extract_fat/publish/servers/dependencyHostServer/.gitignore create mode 100755 dev/wlp.lib.extract_fat/publish/servers/dependencyHostServer/bootstrap.properties create mode 100755 dev/wlp.lib.extract_fat/publish/servers/dependencyHostServer/server.xml create mode 100755 dev/wlp.lib.extract_fat/publish/servers/runnableTestServer/server.xml create mode 100755 dev/wlp.lib.extract_fat/test-applications/dependencyHost/resources/WEB-INF/web.xml create mode 100755 dev/wlp.lib.extract_fat/test-applications/dependencyHost/src/web/DependencyHostServlet.java diff --git a/dev/cnf/gradle/transform/transform.properties b/dev/cnf/gradle/transform/transform.properties index 1644b43fc33..051ac51213b 100644 --- a/dev/cnf/gradle/transform/transform.properties +++ b/dev/cnf/gradle/transform/transform.properties @@ -5,6 +5,7 @@ com.ibm.json4j=Kernel com.ibm.os400.native=Kernel com.ibm.websphere.appserver.api.config=Kernel com.ibm.websphere.appserver.api.hpel=Kernel +com.ibm.websphere.appserver.api.json=KernelTest com.ibm.websphere.appserver.api.kernel.service=Kernel com.ibm.websphere.appserver.kernel-1.0=Kernel com.ibm.websphere.appserver.kernelCore-1.0=Kernel @@ -17,6 +18,7 @@ com.ibm.websphere.appserver.spi.kernel.service=Kernel com.ibm.websphere.appserver.spi.logging=Kernel com.ibm.websphere.appserver.spi.threading=Kernel com.ibm.websphere.appserver.spi.zosCommandProcessing=Kernel +com.ibm.websphere.filetransfer=KernelTest com.ibm.websphere.javaee.jsonp.1.0=Kernel com.ibm.websphere.javaee.servlet.3.0=KernelTest com.ibm.websphere.javaee.servlet.3.1=KernelTest @@ -41,8 +43,11 @@ com.ibm.ws.config.server.schemagen=Kernel com.ibm.ws.config.server.schemagen.serverschemagen=Kernel com.ibm.ws.config.utility=Kernel com.ibm.ws.config.utility.configUtility=Kernel +com.ibm.ws.config.utility_fat=KernelTest com.ibm.ws.config.utility_test=KernelTest com.ibm.ws.config_bvt.parser=KernelTest +com.ibm.ws.config_bvt.schema=KernelTest +com.ibm.ws.config_fat=KernelTest com.ibm.ws.config_test=KernelTest com.ibm.ws.crypto.certificateutil=Kernel com.ibm.ws.crypto.certificateutil_bvt=KernelTest @@ -64,7 +69,9 @@ com.ibm.ws.install.utility.installUtility=Kernel com.ibm.ws.install.ws-cikLauncher=Kernel com.ibm.ws.install_test=KernelTest com.ibm.ws.jmx=Kernel +com.ibm.ws.jmx.connector.client.rest=KernelTest com.ibm.ws.jmx.scripting.client=Kernel +com.ibm.ws.jmx_fat=KernelTest com.ibm.ws.jmx_test=KernelTest com.ibm.ws.kernel.boot=Kernel com.ibm.ws.kernel.boot.archive=Kernel @@ -77,6 +84,7 @@ com.ibm.ws.kernel.boot.nested=Kernel com.ibm.ws.kernel.boot.ws-launch=Kernel com.ibm.ws.kernel.boot.ws-server=Kernel com.ibm.ws.kernel.boot_bvt=KernelTest +com.ibm.ws.kernel.boot_fat=KernelTest com.ibm.ws.kernel.boot_test=KernelTest com.ibm.ws.kernel.cmdline=Kernel com.ibm.ws.kernel.cmdline_test=KernelTest @@ -90,10 +98,12 @@ com.ibm.ws.kernel.feature_bvt=KernelTest com.ibm.ws.kernel.feature_fat=KernelTest com.ibm.ws.kernel.feature_test=KernelTest com.ibm.ws.kernel.filemonitor=Kernel +com.ibm.ws.kernel.filemonitor_fat=KernelTest com.ibm.ws.kernel.filemonitor_test=KernelTest com.ibm.ws.kernel.instrument.agent=Kernel com.ibm.ws.kernel.instrument.check=Kernel com.ibm.ws.kernel.metatype.helper=Kernel +com.ibm.ws.kernel.metatype.helper_fat=KernelTest com.ibm.ws.kernel.metatype.helper_test=KernelTest com.ibm.ws.kernel.security.thread=Kernel com.ibm.ws.kernel.service=Kernel @@ -106,9 +116,11 @@ com.ibm.ws.logging.hpel=Kernel com.ibm.ws.logging.hpel.binarylogviewer=Kernel com.ibm.ws.logging.hpel.osgi=Kernel com.ibm.ws.logging.hpel_bvt=KernelTest +com.ibm.ws.logging.hpel_fat=KernelTest com.ibm.ws.logging.hpel_test=KernelTest com.ibm.ws.logging.osgi=Kernel com.ibm.ws.logging_bvt=KernelTest +com.ibm.ws.logging_fat=KernelTest com.ibm.ws.logging_test=KernelTest com.ibm.ws.org.apache.ant=KernelPrereq com.ibm.ws.org.apache.aries.jmx.api=KernelPrereq @@ -126,40 +138,52 @@ com.ibm.ws.org.eclipse.equinox.coordinator=KernelPrereq com.ibm.ws.org.eclipse.equinox.metatype=KernelPrereq com.ibm.ws.org.eclipse.equinox.region=KernelPrereq com.ibm.ws.org.glassfish.json=KernelPrereq +com.ibm.ws.org.glassfish.json_fat=KernelTest com.ibm.ws.org.objectweb.asm=KernelPrereq com.ibm.ws.org.osgi.annotation.versioning=KernelPrereq com.ibm.ws.org.osgi.service.resolver=KernelTest com.ibm.ws.product.utility=Kernel com.ibm.ws.product.utility.productutil=Kernel com.ibm.ws.product.utility_bvt=KernelTest +com.ibm.ws.product.utility_fat=KernelTest com.ibm.ws.product.utility_test=KernelTest com.ibm.ws.ras.instrument=Kernel com.ibm.ws.repository=Kernel com.ibm.ws.repository.liberty=Kernel com.ibm.ws.repository.resolver=Kernel +com.ibm.ws.repository.resolver_fat=KernelTest com.ibm.ws.repository.resolver_test=KernelTest +com.ibm.ws.repository.test.utils=KernelTest +com.ibm.ws.repository.test.utils_test=KernelTest com.ibm.ws.runtime.update=Kernel com.ibm.ws.runtime.update_bvt=KernelTest +com.ibm.ws.runtime.update_fat=KernelTest com.ibm.ws.runtime.update_test=KernelTest com.ibm.ws.security.thread.zos.hooks=Kernel com.ibm.ws.security.utility=Kernel com.ibm.ws.security.utility.securityutil=Kernel com.ibm.ws.security.utility_bvt=KernelTest +com.ibm.ws.security.utility_fat=KernelTest com.ibm.ws.security.utility_test=KernelTest com.ibm.ws.threading=Kernel com.ibm.ws.threading_bvt=KernelTest +com.ibm.ws.threading_fat=KernelTest com.ibm.ws.threading_test=KernelTest com.ibm.ws.timer=KernelTest com.ibm.ws.transport.http=KernelTest com.ibm.ws.zos.channel.console=Kernel com.ibm.ws.zos.command.processing=Kernel com.ibm.ws.zos.command.processing_test=KernelTest +com.ibm.ws.zos.command.processing_zfat=KernelTest +com.ibm.ws.zos.command.processing_ztest=KernelTest com.ibm.ws.zos.core=Kernel com.ibm.ws.zos.core_test=KernelTest com.ibm.ws.zos.diagnostics=Kernel com.ibm.ws.zos.diagnostics_test=KernelTest com.ibm.ws.zos.logging=Kernel com.ibm.ws.zos.logging_test=KernelTest +com.ibm.ws.zos.logging_zfat=KernelTest +com.ibm.ws.zos.logging_ztest=KernelTest com.ibm.wsspi.org.osgi.core=KernelPrereq com.ibm.wsspi.org.osgi.namespace.service=KernelPrereq com.ibm.wsspi.org.osgi.service.cm=KernelPrereq @@ -180,4 +204,5 @@ prereq.java.1.7=KernelPrereq prereq.java.1.8=KernelPrereq prereq.java.tools=KernelPrereq wlp.lib.extract=Kernel +wlp.lib.extract_fat=KernelTest wlp.lib.extract_test=KernelTest diff --git a/dev/com.ibm.websphere.appserver.api.json/.classpath b/dev/com.ibm.websphere.appserver.api.json/.classpath new file mode 100644 index 00000000000..bd52baaf243 --- /dev/null +++ b/dev/com.ibm.websphere.appserver.api.json/.classpath @@ -0,0 +1,6 @@ + + + + + + diff --git a/dev/com.ibm.websphere.appserver.api.json/.gitignore b/dev/com.ibm.websphere.appserver.api.json/.gitignore new file mode 100644 index 00000000000..05ee82b1e37 --- /dev/null +++ b/dev/com.ibm.websphere.appserver.api.json/.gitignore @@ -0,0 +1,3 @@ +/bin/ +/build/ +/generated/ diff --git a/dev/com.ibm.websphere.appserver.api.json/.project b/dev/com.ibm.websphere.appserver.api.json/.project new file mode 100644 index 00000000000..93a49f1138b --- /dev/null +++ b/dev/com.ibm.websphere.appserver.api.json/.project @@ -0,0 +1,23 @@ + + + com.ibm.websphere.appserver.api.json + + + + + + org.eclipse.jdt.core.javabuilder + + + + + bndtools.core.bndbuilder + + + + + + org.eclipse.jdt.core.javanature + bndtools.core.bndnature + + diff --git a/dev/com.ibm.websphere.appserver.api.json/bnd.bnd b/dev/com.ibm.websphere.appserver.api.json/bnd.bnd new file mode 100644 index 00000000000..41f99c8f9b5 --- /dev/null +++ b/dev/com.ibm.websphere.appserver.api.json/bnd.bnd @@ -0,0 +1,18 @@ +-include= ~../cnf/resources/bnd/bundle.props +bVersion: 1.0 + +Bundle-Name: WebSphere JSON API +Bundle-Description: WebSphere JSON API, version ${bVersion} +Bundle-SymbolicName: com.ibm.websphere.appserver.api.json + +Export-Package: com.ibm.json.java,com.ibm.json.xml + +Import-Package: com.ibm.json.java,com.ibm.json.xml + +-includeresource: {META-INF/maven/com.ibm.websphere.appserver.api/com.ibm.websphere.appserver.api.json/pom.xml=com.ibm.websphere.appserver.api.json.pom} + +publish.wlp.jar.suffix: dev/api/ibm + +-buildpath: \ + ${javac.bootclasspath.java6}, \ + com.ibm.json4j;version=latest diff --git a/dev/com.ibm.websphere.appserver.api.json/build.gradle b/dev/com.ibm.websphere.appserver.api.json/build.gradle new file mode 100644 index 00000000000..e69de29bb2d diff --git a/dev/com.ibm.websphere.appserver.api.json/com.ibm.websphere.appserver.api.json.pom b/dev/com.ibm.websphere.appserver.api.json/com.ibm.websphere.appserver.api.json.pom new file mode 100644 index 00000000000..3d8e15485db --- /dev/null +++ b/dev/com.ibm.websphere.appserver.api.json/com.ibm.websphere.appserver.api.json.pom @@ -0,0 +1,26 @@ + + + + + + + IBM International License Agreement for Non-Warranted Programs + http://public.dhe.ibm.com/ibmdl/export/pub/software/websphere/wasdev/maven/licenses/L-JTHS-8SZMHX/HTML/ + repo + Additional notices http://public.dhe.ibm.com/ibmdl/export/pub/software/websphere/wasdev/maven/licenses/L-JTHS-8SZMHX/HTML/notices.html + + + + 4.0.0 + com.ibm.websphere.appserver.api + com.ibm.websphere.appserver.api.json + ${bFullVersion} + WebSphere JSON API + WebSphere JSON API, version 1.0 + diff --git a/dev/com.ibm.websphere.filetransfer/.classpath b/dev/com.ibm.websphere.filetransfer/.classpath new file mode 100755 index 00000000000..2876090f903 --- /dev/null +++ b/dev/com.ibm.websphere.filetransfer/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/dev/com.ibm.websphere.filetransfer/.classpath.gradle b/dev/com.ibm.websphere.filetransfer/.classpath.gradle new file mode 100644 index 00000000000..2876090f903 --- /dev/null +++ b/dev/com.ibm.websphere.filetransfer/.classpath.gradle @@ -0,0 +1,7 @@ + + + + + + + diff --git a/dev/com.ibm.websphere.filetransfer/.gitignore b/dev/com.ibm.websphere.filetransfer/.gitignore new file mode 100644 index 00000000000..57b341172a1 --- /dev/null +++ b/dev/com.ibm.websphere.filetransfer/.gitignore @@ -0,0 +1,2 @@ +/bin/ +/generated/ diff --git a/dev/com.ibm.websphere.filetransfer/.project b/dev/com.ibm.websphere.filetransfer/.project new file mode 100755 index 00000000000..d0435f4bb97 --- /dev/null +++ b/dev/com.ibm.websphere.filetransfer/.project @@ -0,0 +1,23 @@ + + + com.ibm.websphere.filetransfer + + + + + + org.eclipse.jdt.core.javabuilder + + + + + bndtools.core.bndbuilder + + + + + + org.eclipse.jdt.core.javanature + bndtools.core.bndnature + + diff --git a/dev/com.ibm.websphere.filetransfer/.settings/org.eclipse.core.resources.prefs b/dev/com.ibm.websphere.filetransfer/.settings/org.eclipse.core.resources.prefs new file mode 100755 index 00000000000..25d9425fe34 --- /dev/null +++ b/dev/com.ibm.websphere.filetransfer/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,4 @@ +#Ant properties +#Automatically generated by the ant prepare.settings.files task +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/dev/com.ibm.websphere.filetransfer/.settings/org.eclipse.jdt.core.prefs b/dev/com.ibm.websphere.filetransfer/.settings/org.eclipse.jdt.core.prefs new file mode 100755 index 00000000000..845c3083c7d --- /dev/null +++ b/dev/com.ibm.websphere.filetransfer/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,286 @@ +#Ant properties +#Automatically generated by the ant prepare.settings.files task +org.eclipse.jdt.core.codeComplete.argumentPrefixes= +org.eclipse.jdt.core.codeComplete.argumentSuffixes= +org.eclipse.jdt.core.codeComplete.fieldPrefixes= +org.eclipse.jdt.core.codeComplete.fieldSuffixes= +org.eclipse.jdt.core.codeComplete.localPrefixes= +org.eclipse.jdt.core.codeComplete.localSuffixes= +org.eclipse.jdt.core.codeComplete.staticFieldPrefixes= +org.eclipse.jdt.core.codeComplete.staticFieldSuffixes= +org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes= +org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes= +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.6 +org.eclipse.jdt.core.formatter.align_type_members_on_columns=false +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=0 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=18 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=2 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=2 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=18 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=2 +org.eclipse.jdt.core.formatter.alignment_for_assignment=0 +org.eclipse.jdt.core.formatter.alignment_for_binary_expression=18 +org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=0 +org.eclipse.jdt.core.formatter.alignment_for_enum_constants=16 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=18 +org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=18 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=18 +org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=0 +org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=20 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=4 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +org.eclipse.jdt.core.formatter.blank_lines_before_field=0 +org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 +org.eclipse.jdt.core.formatter.blank_lines_before_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 +org.eclipse.jdt.core.formatter.blank_lines_before_package=0 +org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 +org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 +org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false +org.eclipse.jdt.core.formatter.comment.format_block_comments=true +org.eclipse.jdt.core.formatter.comment.format_header=false +org.eclipse.jdt.core.formatter.comment.format_html=false +org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true +org.eclipse.jdt.core.formatter.comment.format_line_comments=false +org.eclipse.jdt.core.formatter.comment.format_source_code=true +org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true +org.eclipse.jdt.core.formatter.comment.indent_root_tags=true +org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert +org.eclipse.jdt.core.formatter.comment.line_length=180 +org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true +org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true +org.eclipse.jdt.core.formatter.compact_else_if=true +org.eclipse.jdt.core.formatter.continuation_indentation=4 +org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=4 +org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off +org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on +org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false +org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=false +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true +org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_empty_lines=false +org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true +org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true +org.eclipse.jdt.core.formatter.indentation.size=8 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert +org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.join_lines_in_comments=false +org.eclipse.jdt.core.formatter.join_wrapped_lines=false +org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false +org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false +org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false +org.eclipse.jdt.core.formatter.lineSplit=180 +org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=true +org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=true +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 +org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=false +org.eclipse.jdt.core.formatter.tabulation.char=space +org.eclipse.jdt.core.formatter.tabulation.size=4 +org.eclipse.jdt.core.formatter.use_on_off_tags=true +org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false +org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true +org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true diff --git a/dev/com.ibm.websphere.filetransfer/.settings/org.eclipse.jdt.ui.prefs b/dev/com.ibm.websphere.filetransfer/.settings/org.eclipse.jdt.ui.prefs new file mode 100755 index 00000000000..c874b581698 --- /dev/null +++ b/dev/com.ibm.websphere.filetransfer/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,117 @@ +#Ant properties +#Automatically generated by the ant prepare.settings.files task +cleanup.add_default_serial_version_id=false +cleanup.add_generated_serial_version_id=true +cleanup.add_missing_annotations=true +cleanup.add_missing_deprecated_annotations=true +cleanup.add_missing_methods=false +cleanup.add_missing_nls_tags=false +cleanup.add_missing_override_annotations=true +cleanup.add_missing_override_annotations_interface_methods=true +cleanup.add_serial_version_id=false +cleanup.always_use_blocks=true +cleanup.always_use_parentheses_in_expressions=false +cleanup.always_use_this_for_non_static_field_access=false +cleanup.always_use_this_for_non_static_method_access=false +cleanup.convert_to_enhanced_for_loop=false +cleanup.correct_indentation=true +cleanup.format_source_code=false +cleanup.format_source_code_changes_only=false +cleanup.make_local_variable_final=false +cleanup.make_parameters_final=true +cleanup.make_private_fields_final=false +cleanup.make_type_abstract_if_missing_method=false +cleanup.make_variable_declarations_final=false +cleanup.never_use_blocks=false +cleanup.never_use_parentheses_in_expressions=true +cleanup.organize_imports=false +cleanup.qualify_static_field_accesses_with_declaring_class=false +cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true +cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true +cleanup.qualify_static_member_accesses_with_declaring_class=true +cleanup.qualify_static_method_accesses_with_declaring_class=false +cleanup.remove_private_constructors=true +cleanup.remove_trailing_whitespaces=true +cleanup.remove_trailing_whitespaces_all=true +cleanup.remove_trailing_whitespaces_ignore_empty=false +cleanup.remove_unnecessary_casts=true +cleanup.remove_unnecessary_nls_tags=true +cleanup.remove_unused_imports=true +cleanup.remove_unused_local_variables=false +cleanup.remove_unused_private_fields=true +cleanup.remove_unused_private_members=false +cleanup.remove_unused_private_methods=true +cleanup.remove_unused_private_types=true +cleanup.sort_members=false +cleanup.sort_members_all=false +cleanup.use_blocks=true +cleanup.use_blocks_only_for_return_and_throw=false +cleanup.use_parentheses_in_expressions=true +cleanup.use_this_for_non_static_field_access=false +cleanup.use_this_for_non_static_field_access_only_if_necessary=true +cleanup.use_this_for_non_static_method_access=false +cleanup.use_this_for_non_static_method_access_only_if_necessary=true +eclipse.preferences.version=1 +editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true +org.eclipse.jdt.ui.exception.name=e +org.eclipse.jdt.ui.gettersetter.use.is=false +org.eclipse.jdt.ui.ignorelowercasenames=true +org.eclipse.jdt.ui.importorder=java;javax;org;com; +org.eclipse.jdt.ui.javadoc=true +org.eclipse.jdt.ui.keywordthis=false +org.eclipse.jdt.ui.ondemandthreshold=99 +org.eclipse.jdt.ui.overrideannotation=true +org.eclipse.jdt.ui.staticondemandthreshold=99 +org.eclipse.jdt.ui.text.custom_code_templates= +sp_cleanup.add_default_serial_version_id=true +sp_cleanup.add_generated_serial_version_id=false +sp_cleanup.add_missing_annotations=true +sp_cleanup.add_missing_deprecated_annotations=true +sp_cleanup.add_missing_methods=false +sp_cleanup.add_missing_nls_tags=false +sp_cleanup.add_missing_override_annotations=true +sp_cleanup.add_missing_override_annotations_interface_methods=true +sp_cleanup.add_serial_version_id=false +sp_cleanup.always_use_blocks=true +sp_cleanup.always_use_parentheses_in_expressions=false +sp_cleanup.always_use_this_for_non_static_field_access=false +sp_cleanup.always_use_this_for_non_static_method_access=false +sp_cleanup.convert_to_enhanced_for_loop=false +sp_cleanup.correct_indentation=false +sp_cleanup.format_source_code=true +sp_cleanup.format_source_code_changes_only=false +sp_cleanup.make_local_variable_final=false +sp_cleanup.make_parameters_final=false +sp_cleanup.make_private_fields_final=true +sp_cleanup.make_type_abstract_if_missing_method=false +sp_cleanup.make_variable_declarations_final=true +sp_cleanup.never_use_blocks=false +sp_cleanup.never_use_parentheses_in_expressions=true +sp_cleanup.on_save_use_additional_actions=true +sp_cleanup.organize_imports=true +sp_cleanup.qualify_static_field_accesses_with_declaring_class=false +sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_with_declaring_class=false +sp_cleanup.qualify_static_method_accesses_with_declaring_class=false +sp_cleanup.remove_private_constructors=true +sp_cleanup.remove_trailing_whitespaces=true +sp_cleanup.remove_trailing_whitespaces_all=true +sp_cleanup.remove_trailing_whitespaces_ignore_empty=false +sp_cleanup.remove_unnecessary_casts=true +sp_cleanup.remove_unnecessary_nls_tags=true +sp_cleanup.remove_unused_imports=true +sp_cleanup.remove_unused_local_variables=false +sp_cleanup.remove_unused_private_fields=true +sp_cleanup.remove_unused_private_members=false +sp_cleanup.remove_unused_private_methods=true +sp_cleanup.remove_unused_private_types=true +sp_cleanup.sort_members=false +sp_cleanup.sort_members_all=false +sp_cleanup.use_blocks=false +sp_cleanup.use_blocks_only_for_return_and_throw=false +sp_cleanup.use_parentheses_in_expressions=false +sp_cleanup.use_this_for_non_static_field_access=false +sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true +sp_cleanup.use_this_for_non_static_method_access=false +sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true diff --git a/dev/com.ibm.websphere.filetransfer/.settings/org.sonar.ide.eclipse.core.prefs b/dev/com.ibm.websphere.filetransfer/.settings/org.sonar.ide.eclipse.core.prefs new file mode 100755 index 00000000000..e0b979e14e4 --- /dev/null +++ b/dev/com.ibm.websphere.filetransfer/.settings/org.sonar.ide.eclipse.core.prefs @@ -0,0 +1,7 @@ +analyseLocally=false +eclipse.preferences.version=1 +extraProperties= +lastAnalysisDate=1366911191199 +projectKey=Liberty-8.5.5\:com.ibm.websphere.filetransfer +serverUrl=http\://szeged.hursley.ibm.com\:8080/sonar +version=2 diff --git a/dev/com.ibm.websphere.filetransfer/README.txt b/dev/com.ibm.websphere.filetransfer/README.txt new file mode 100755 index 00000000000..9cd48f08a57 --- /dev/null +++ b/dev/com.ibm.websphere.filetransfer/README.txt @@ -0,0 +1,5 @@ +Last update: 2013/08/13 + +This project (com.ibm.websphere.filetransfer) is intended to encapsulate all of +the public API and SPI related to file transfer support. Do not add non-public +interfaces to this project. diff --git a/dev/com.ibm.websphere.filetransfer/bnd.bnd b/dev/com.ibm.websphere.filetransfer/bnd.bnd new file mode 100755 index 00000000000..c5c4404d0cf --- /dev/null +++ b/dev/com.ibm.websphere.filetransfer/bnd.bnd @@ -0,0 +1,15 @@ +-include= ~../cnf/resources/bnd/bundle.props +bVersion=1.0 + +Bundle-Name: WebSphere File Services APIs +Bundle-SymbolicName: com.ibm.websphere.filetransfer +Bundle-Description: APIs for WebSphere File Services; version=${bVersion} +Bundle-ActivationPolicy: lazy + +Export-Package: com.ibm.websphere.filetransfer + +instrument.disabled: true + +-buildpath: \ + ${javac.bootclasspath.java6}, \ + com.ibm.ws.org.osgi.annotation.versioning.1.0.0;version=latest diff --git a/dev/com.ibm.websphere.filetransfer/build.gradle b/dev/com.ibm.websphere.filetransfer/build.gradle new file mode 100644 index 00000000000..e69de29bb2d diff --git a/dev/com.ibm.websphere.filetransfer/build.xml b/dev/com.ibm.websphere.filetransfer/build.xml new file mode 100755 index 00000000000..511276204f2 --- /dev/null +++ b/dev/com.ibm.websphere.filetransfer/build.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dev/com.ibm.websphere.filetransfer/findbugs.exclude.xml b/dev/com.ibm.websphere.filetransfer/findbugs.exclude.xml new file mode 100755 index 00000000000..1cf8902cff2 --- /dev/null +++ b/dev/com.ibm.websphere.filetransfer/findbugs.exclude.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.websphere.filetransfer/src/com/ibm/websphere/filetransfer/FileServiceMXBean.java b/dev/com.ibm.websphere.filetransfer/src/com/ibm/websphere/filetransfer/FileServiceMXBean.java new file mode 100755 index 00000000000..acf390bfa21 --- /dev/null +++ b/dev/com.ibm.websphere.filetransfer/src/com/ibm/websphere/filetransfer/FileServiceMXBean.java @@ -0,0 +1,231 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.websphere.filetransfer; + +import java.beans.ConstructorProperties; +import java.util.Date; +import java.util.List; + +/** + * This MBean provides file service operations on the host system on which + * the server resides. + *

+ * The ObjectName for this MBean is {@value #OBJECT_NAME}. + *

+ * All paths are implicitly remote, as the operations performed by this MBean + * occur on the host which the server resides. All paths are required to be + * absolute, either explicitly or rooted with a WebSphere variable such as + * ${wlp.install.dir}. + * + * @ibm-api + */ +public interface FileServiceMXBean { + + /** + * A String representing the {@link javax.management.ObjectName} that this MXBean maps to. + */ + String OBJECT_NAME = "WebSphere:feature=restConnector,type=FileService,name=FileService"; + + /** + * Option indicating all available keys should be used for the query. + */ + String REQUEST_OPTIONS_ALL = "a"; + + /** + * Option indicating that "isDirectory" key should be used for the query. + */ + String REQUEST_OPTIONS_IS_DIRECTORY = "d"; + + /** + * Option indicating that "isReadOnly" key should be used for the query. + */ + String REQUEST_OPTIONS_READ_ONLY = "r"; + + /** + * Option indicating that "size" key should be used for the query. + */ + String REQUEST_OPTIONS_SIZE = "s"; + + /** + * Option indicating that "lastModified" key should be used for the query. + */ + String REQUEST_OPTIONS_LAST_MODIFIED = "t"; + + /** + * The name of the attribute representing the list of read locations. + */ + String ATTRIBUTE_NAME_READ_LIST = "ReadList"; + + /** + * The name of the attribute representing the list of write locations. + */ + String ATTRIBUTE_NAME_WRITE_LIST = "WriteList"; + + /** + * Get the configured list of read-accessible locations on the host where + * this server resides. This list is configurable for each server by + * modifying the server.xml. Each directory to allow for read access can + * be specified to the <remoteFileAccess> configuration element + * 'readDir' attribute. + *

+ * For example: + *
+ *

+     * <remoteFileAccess>
+     *     <readDir>$ server.output.dir}/payloads</readDir>
+     * </remoteFileAccess>
+     * 
+ *

+ * The default is an empty list. + * + * @return a list of Strings containing the absolute paths which are read-accessible. + */ + List getReadList(); + + /** + * Get the configured list of write-accessible locations on the host where + * this server resides. This list is configurable for each server by + * modifying the server.xml. Each direcoty to allow for write access can + * be specified to the <remoteFileAccess> configuration element + * 'writeDir' attribute. + *

+ * For example: + *
+ *

+     * <remoteFileAccess>
+     *     <writeDir>${server.output.dir}/target</writeDir>
+     * </remoteFileAccess>
+     * 
+ *

+ * The default is a list containing 3 entries: ${wlp.install.dir}, + * ${wlp.user.dir} and ${server.output.dir}. + * + * @return a list of Strings containing the absolute paths which are write-accessible. + */ + List getWriteList(); + + /** + * Get the metadata pertaining to the specified path. The result object + * will contain the requested metadata subset as indicated by the + * requestOptions String value, which should be constructed as a + * concatenation of the desired values. + *

+ * For example: to obtain a request that provides only the "size" and + * "lastModified" metadata values, the user can pass in "st" as the + * requestOptions field. + * + * @param path the absolute path of the file or directory for which to retrieve the metadata + * @param requestOptions a String representing the concatenation of the requested metadata keys. See REQUEST_OPTIONS_* fields. + * @return a CompositeData containing the requested metadata + */ + MetaData getMetaData(String path, String requestOptions); + + /** + * List the directory/files for the given path. + * + * @param directory the absolute path of the directory to list + * @param recursive a boolean to specify if the search should be done to all descendant paths + * @param requestOptions a String representing the concatenation of the requested metadata keys + * @return an array of CompositeData, representing the requested metadata for each entry + */ + MetaData[] getDirectoryEntries(String directory, boolean recursive, String requestOptions); + + /** + * Create an archive of the given sourcePath. + *

+ * This operation occurs on the file system on which this server resides. + * Therefore the sourcePath and targetPath are paths on the server's host + * system. + * + * @param sourcePath the absolute path of the entity to archive + * @param targetPath the absolute path to where resulting archive is to be stored + * @return true if archive was successfully created, false otherwise + */ + boolean createArchive(String sourcePath, String targetPath); + + /** + * Expand the archive at the given sourcePath. + *

+ * This operation occurs on the file system on which this server resides. + * Therefore the sourcePath and targetPath are paths on the server's host + * system. + * + * @param sourcePath the absolute path of the archive to be expanded + * @param targetPath the absolute path to where archive is to be expanded + * @return true if archive was successfully expanded, false otherwise + */ + boolean expandArchive(String sourcePath, String targetPath); + + /** + * Return type for the getMetaData and getDirectoryEntries methods. + * + * The JMX framework will convert this to a CompositeData object on the client side. + */ + public class MetaData { + + private final Boolean directory; + private final Boolean readOnly; + private final Date lastModified; + private final Long size; + private final String fileName; + + @ConstructorProperties({ "directory", "lastModified", "size", "readOnly", "fileName" }) + public MetaData(Boolean directory, Date lastModified, Long size, Boolean readOnly, String fileName) { + this.directory = directory; + this.lastModified = (lastModified == null) ? null : (Date) lastModified.clone(); + this.size = size; + this.readOnly = readOnly; + this.fileName = fileName; + } + + /** + * Boolean value indicating whether or not the entity is a directory. + * + * @return {@code true} if the entity is a directory, {@code false} otherwise. + */ + public Boolean getDirectory() { + return this.directory; + } + + /** + * @return Date object representing the time the entity was last modified + */ + public Date getLastModified() { + return (this.lastModified == null) ? null : (Date) this.lastModified.clone(); + } + + /** + * @return Long object indicating the size of the entity. + */ + public Long getSize() { + return this.size; + } + + /** + * Boolean value indicating whether or not the entity is read-only. + * + * @return {@code true} if the entity is read-only, {@code false} otherwise. + */ + public Boolean getReadOnly() { + return this.readOnly; + } + + /** + * @return String value indicating the entity's absolute path. + */ + public String getFileName() { + return this.fileName; + } + + } + +} diff --git a/dev/com.ibm.websphere.filetransfer/src/com/ibm/websphere/filetransfer/FileTransferMBean.java b/dev/com.ibm.websphere.filetransfer/src/com/ibm/websphere/filetransfer/FileTransferMBean.java new file mode 100755 index 00000000000..33b9690890c --- /dev/null +++ b/dev/com.ibm.websphere.filetransfer/src/com/ibm/websphere/filetransfer/FileTransferMBean.java @@ -0,0 +1,137 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012, 2015 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.websphere.filetransfer; + +import java.io.IOException; +import java.util.List; + +/** + * This MBean exposes remote file transfer capabilities and must be accessed + * only within IBM's JMX REST Connector. Accessing this MBean by any + * other means will result in a {@link java.lang.UnsupportedOperationException}. + *

+ * The ObjectName for this MBean is {@value #OBJECT_NAME}. + *

+ * For the remote file parameters (ie: remoteSourceFile for download/delete + * and remoteTargetFile for upload) the following characteristics apply: + *

+ *

+ * For the local file parameters (ie: localTargetFile for download and and + * localSourceFile for upload) the following characteristics apply: + *

+ * + * @ibm-api + */ +public interface FileTransferMBean { + + /** + * A string representing the {@link javax.management.ObjectName} that this MBean maps to. + */ + String OBJECT_NAME = "WebSphere:feature=restConnector,type=FileTransfer,name=FileTransfer"; + + /** + * Download a file from the specified remote source location and write it + * in the specified local target location. + *

+ * Directories are not supported as the remote source file. To download a + * directory, it must first be archived. + * + * @param remoteSourceFile the remote file location of the source to download + * @param localTargetFile the local file location where the source contents will be written + * @throws IOException if there are any issues handling the source or target files + */ + void downloadFile(String remoteSourceFile, String localTargetFile) throws IOException; + + /** + * Download part of a file from the specified remote source location using the specified start and + * end offset byte values and write it in the specified local target location. + *

+ * Directories are not supported as the remote source file. To download a + * directory, it must first be archived. + *

+ * This partial download feature is currently available only in non-routing scenarios. + * + * @param remoteSourceFile the remote file location of the source to download + * @param localTargetFile the local file location where the source contents will be written + * @param startOffset index of the first byte to copy (zero-based and inclusive) + * @param endOffset index of the last byte to copy (zero-based and inclusive). + * Specify -1 to copy until the end of file. + * + * @return Index to use as start offset for next partial file download request. + * If this value is greater than the startOffset value that was passed in, then + * some bytes (equivalent to the difference) were transferred by this download request. + *
+ * Note: It is assumed that in-between the download requests, remote source file is not + * modified in any way except for appending contents to end of the file. + * + * @throws IOException if there are any issues handling the source or target files + */ + long downloadFile(String remoteSourceFile, String localTargetFile, long startOffset, long endOffset) throws IOException; + + /** + * Upload a file from the specified local source location and write it + * in the specified remote target location. + *

+ * This method optionally supports expanding an archive (specified as the local + * source file) to the remote target file. The supported compression + * formats are 'zip' and 'jar' (including war and ear) . All other format types will result in + * undefined behaviour. + *

+ * Directories are not supported as the local source file. To upload a + * directory, it must first be archived and can then be expanded during upload using the expandOnCompletion option. + * This option has a special behaviour: the archive will be uploaded as a regular file to the remote system, and then we + * will make a directory that matches the filename specified by remoteTargetFile, and the contents will be expanded inside that new folder. + * + *

Example: Uploading an archive with remoteTargetFile /home/myFolder/wlp.zip and the expandOnCompletion + * option set to true will upload the archive wlp.zip to the remote file system, create a folder called wlp.zip + * under the directory /home/myFolder, and then expand the contents of the archive inside the folder /home/myFolder/wlp.zip. + * + * If expandOnCompletion flag is false,then remoteTargetFile must match a filename with an extension (unless the file has not extension), and + * cannot be a folder. + * + * + * @param localSourceFile the local path to the file that will be uploaded. + * The source file must be a file, since directories are not supported. + * @param remoteTargetFile the remote path of the uploaded file. + * The target file must be a file, since directories are not supported. + * @param expandOnCompletion indicates if the archive should be expanded automatically after it is uploaded. + * @throws IOException if there are any issues handling the request + */ + void uploadFile(String localSourceFile, String remoteTargetFile, boolean expandOnCompletion) throws IOException; + + /** + * Delete a file located at the remote specified location. + *

+ * Recursive deletion of a directory is not supported, however deletion of + * an empty directory is supported. + * + * @param remoteSourceFile the location of the remote file to be deleted + * @throws IOException if there are any issues handling the request + */ + void deleteFile(String remoteSourceFile) throws IOException; + + /** + * Delete files and folders (empty and non-empty) at the remote specified locations + * + * @param remoteArtifacts list of locations of remote files and folders (empty and non-empty) to delete + * @throws IOException if there are any issues handling the request + */ + void deleteAll(List remoteArtifacts) throws IOException; + +} diff --git a/dev/com.ibm.websphere.filetransfer/src/com/ibm/websphere/filetransfer/package-info.java b/dev/com.ibm.websphere.filetransfer/src/com/ibm/websphere/filetransfer/package-info.java new file mode 100755 index 00000000000..4b8251a907a --- /dev/null +++ b/dev/com.ibm.websphere.filetransfer/src/com/ibm/websphere/filetransfer/package-info.java @@ -0,0 +1,21 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011, 2014 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ + +/** + * This package is intended to encapsulate the public API and SPI related + * to file transfer. Do not add non-public interfaces to this package. + * + * @version 1.1 + */ +@org.osgi.annotation.versioning.Version("1.1") +package com.ibm.websphere.filetransfer; + diff --git a/dev/com.ibm.ws.config.utility_fat/.classpath b/dev/com.ibm.ws.config.utility_fat/.classpath new file mode 100644 index 00000000000..c422489df40 --- /dev/null +++ b/dev/com.ibm.ws.config.utility_fat/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/dev/com.ibm.ws.config.utility_fat/.classpath.gradle b/dev/com.ibm.ws.config.utility_fat/.classpath.gradle new file mode 100644 index 00000000000..c422489df40 --- /dev/null +++ b/dev/com.ibm.ws.config.utility_fat/.classpath.gradle @@ -0,0 +1,7 @@ + + + + + + + diff --git a/dev/com.ibm.ws.config.utility_fat/.gitignore b/dev/com.ibm.ws.config.utility_fat/.gitignore new file mode 100644 index 00000000000..27e131e35a6 --- /dev/null +++ b/dev/com.ibm.ws.config.utility_fat/.gitignore @@ -0,0 +1 @@ +/bootstrapping.properties diff --git a/dev/com.ibm.ws.config.utility_fat/.project b/dev/com.ibm.ws.config.utility_fat/.project new file mode 100755 index 00000000000..91eb01d8ee5 --- /dev/null +++ b/dev/com.ibm.ws.config.utility_fat/.project @@ -0,0 +1,23 @@ + + + com.ibm.ws.config.utility_fat + + + + + + org.eclipse.jdt.core.javabuilder + + + + + bndtools.core.bndbuilder + + + + + + org.eclipse.jdt.core.javanature + bndtools.core.bndnature + + diff --git a/dev/com.ibm.ws.config.utility_fat/.settings/org.eclipse.core.resources.prefs b/dev/com.ibm.ws.config.utility_fat/.settings/org.eclipse.core.resources.prefs new file mode 100755 index 00000000000..25d9425fe34 --- /dev/null +++ b/dev/com.ibm.ws.config.utility_fat/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,4 @@ +#Ant properties +#Automatically generated by the ant prepare.settings.files task +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/dev/com.ibm.ws.config.utility_fat/.settings/org.eclipse.jdt.core.prefs b/dev/com.ibm.ws.config.utility_fat/.settings/org.eclipse.jdt.core.prefs new file mode 100755 index 00000000000..f48ecd6cc60 --- /dev/null +++ b/dev/com.ibm.ws.config.utility_fat/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,280 @@ +#Ant properties +#Automatically generated by the ant prepare.settings.files task +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.6 +org.eclipse.jdt.core.formatter.align_type_members_on_columns=false +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=0 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=18 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=2 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=2 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=18 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=2 +org.eclipse.jdt.core.formatter.alignment_for_assignment=0 +org.eclipse.jdt.core.formatter.alignment_for_binary_expression=18 +org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=0 +org.eclipse.jdt.core.formatter.alignment_for_enum_constants=16 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=18 +org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=18 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=18 +org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=0 +org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=20 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=4 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +org.eclipse.jdt.core.formatter.blank_lines_before_field=0 +org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 +org.eclipse.jdt.core.formatter.blank_lines_before_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 +org.eclipse.jdt.core.formatter.blank_lines_before_package=0 +org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 +org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 +org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false +org.eclipse.jdt.core.formatter.comment.format_block_comments=true +org.eclipse.jdt.core.formatter.comment.format_header=false +org.eclipse.jdt.core.formatter.comment.format_html=false +org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true +org.eclipse.jdt.core.formatter.comment.format_line_comments=false +org.eclipse.jdt.core.formatter.comment.format_source_code=true +org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true +org.eclipse.jdt.core.formatter.comment.indent_root_tags=true +org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert +org.eclipse.jdt.core.formatter.comment.line_length=180 +org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true +org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true +org.eclipse.jdt.core.formatter.compact_else_if=true +org.eclipse.jdt.core.formatter.continuation_indentation=4 +org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=4 +org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off +org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on +org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false +org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=false +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true +org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_empty_lines=false +org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true +org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true +org.eclipse.jdt.core.formatter.indentation.size=8 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert +org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.join_lines_in_comments=false +org.eclipse.jdt.core.formatter.join_wrapped_lines=false +org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false +org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false +org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false +org.eclipse.jdt.core.formatter.lineSplit=180 +org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=true +org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=true +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 +org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=false +org.eclipse.jdt.core.formatter.tabulation.char=space +org.eclipse.jdt.core.formatter.tabulation.size=4 +org.eclipse.jdt.core.formatter.use_on_off_tags=true +org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false +org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true +org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true diff --git a/dev/com.ibm.ws.config.utility_fat/.settings/org.eclipse.jdt.ui.prefs b/dev/com.ibm.ws.config.utility_fat/.settings/org.eclipse.jdt.ui.prefs new file mode 100755 index 00000000000..c92277a371a --- /dev/null +++ b/dev/com.ibm.ws.config.utility_fat/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,62 @@ +#Ant properties +#Automatically generated by the ant prepare.settings.files task +eclipse.preferences.version=1 +editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true +org.eclipse.jdt.ui.ignorelowercasenames=true +org.eclipse.jdt.ui.importorder=java;javax;org;com; +org.eclipse.jdt.ui.javadoc=true +org.eclipse.jdt.ui.ondemandthreshold=99 +org.eclipse.jdt.ui.staticondemandthreshold=99 +org.eclipse.jdt.ui.text.custom_code_templates= +sp_cleanup.add_default_serial_version_id=true +sp_cleanup.add_generated_serial_version_id=false +sp_cleanup.add_missing_annotations=true +sp_cleanup.add_missing_deprecated_annotations=true +sp_cleanup.add_missing_methods=false +sp_cleanup.add_missing_nls_tags=false +sp_cleanup.add_missing_override_annotations=true +sp_cleanup.add_missing_override_annotations_interface_methods=true +sp_cleanup.add_serial_version_id=false +sp_cleanup.always_use_blocks=true +sp_cleanup.always_use_parentheses_in_expressions=false +sp_cleanup.always_use_this_for_non_static_field_access=false +sp_cleanup.always_use_this_for_non_static_method_access=false +sp_cleanup.convert_to_enhanced_for_loop=false +sp_cleanup.correct_indentation=false +sp_cleanup.format_source_code=true +sp_cleanup.format_source_code_changes_only=false +sp_cleanup.make_local_variable_final=false +sp_cleanup.make_parameters_final=false +sp_cleanup.make_private_fields_final=true +sp_cleanup.make_type_abstract_if_missing_method=false +sp_cleanup.make_variable_declarations_final=true +sp_cleanup.never_use_blocks=false +sp_cleanup.never_use_parentheses_in_expressions=true +sp_cleanup.on_save_use_additional_actions=true +sp_cleanup.organize_imports=true +sp_cleanup.qualify_static_field_accesses_with_declaring_class=false +sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_with_declaring_class=false +sp_cleanup.qualify_static_method_accesses_with_declaring_class=false +sp_cleanup.remove_private_constructors=true +sp_cleanup.remove_trailing_whitespaces=true +sp_cleanup.remove_trailing_whitespaces_all=true +sp_cleanup.remove_trailing_whitespaces_ignore_empty=false +sp_cleanup.remove_unnecessary_casts=true +sp_cleanup.remove_unnecessary_nls_tags=true +sp_cleanup.remove_unused_imports=true +sp_cleanup.remove_unused_local_variables=false +sp_cleanup.remove_unused_private_fields=true +sp_cleanup.remove_unused_private_members=false +sp_cleanup.remove_unused_private_methods=true +sp_cleanup.remove_unused_private_types=true +sp_cleanup.sort_members=false +sp_cleanup.sort_members_all=false +sp_cleanup.use_blocks=false +sp_cleanup.use_blocks_only_for_return_and_throw=false +sp_cleanup.use_parentheses_in_expressions=false +sp_cleanup.use_this_for_non_static_field_access=false +sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true +sp_cleanup.use_this_for_non_static_method_access=false +sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true diff --git a/dev/com.ibm.ws.config.utility_fat/bnd.bnd b/dev/com.ibm.ws.config.utility_fat/bnd.bnd new file mode 100644 index 00000000000..d87d7bffc3b --- /dev/null +++ b/dev/com.ibm.ws.config.utility_fat/bnd.bnd @@ -0,0 +1,15 @@ +-include= ~../cnf/resources/bnd/bundle.props +bVersion=1.0 + +src: \ + fat/src + +-buildpath: \ + ${javac.bootclasspath.java6}, \ + ../build.sharedResources/lib/junit/old/junit.jar;version=file, \ + fattest.simplicity;version=latest, \ + ../fattest.simplicity/lib/public.api.jar;version=file, \ + com.ibm.ws.org.apache.commons.io.1.4;version=latest, \ + com.ibm.ws.repository;version=latest, \ + com.ibm.ws.repository.liberty;version=latest, \ + com.ibm.ws.config.utility;version=latest diff --git a/dev/com.ibm.ws.config.utility_fat/bnd.bnd.gradle b/dev/com.ibm.ws.config.utility_fat/bnd.bnd.gradle new file mode 100644 index 00000000000..d87d7bffc3b --- /dev/null +++ b/dev/com.ibm.ws.config.utility_fat/bnd.bnd.gradle @@ -0,0 +1,15 @@ +-include= ~../cnf/resources/bnd/bundle.props +bVersion=1.0 + +src: \ + fat/src + +-buildpath: \ + ${javac.bootclasspath.java6}, \ + ../build.sharedResources/lib/junit/old/junit.jar;version=file, \ + fattest.simplicity;version=latest, \ + ../fattest.simplicity/lib/public.api.jar;version=file, \ + com.ibm.ws.org.apache.commons.io.1.4;version=latest, \ + com.ibm.ws.repository;version=latest, \ + com.ibm.ws.repository.liberty;version=latest, \ + com.ibm.ws.config.utility;version=latest diff --git a/dev/com.ibm.ws.config.utility_fat/build-test.xml b/dev/com.ibm.ws.config.utility_fat/build-test.xml new file mode 100755 index 00000000000..e546d657a95 --- /dev/null +++ b/dev/com.ibm.ws.config.utility_fat/build-test.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/dev/com.ibm.ws.config.utility_fat/build.gradle b/dev/com.ibm.ws.config.utility_fat/build.gradle new file mode 100644 index 00000000000..e69de29bb2d diff --git a/dev/com.ibm.ws.config.utility_fat/delivery.sets b/dev/com.ibm.ws.config.utility_fat/delivery.sets new file mode 100755 index 00000000000..674398425a0 --- /dev/null +++ b/dev/com.ibm.ws.config.utility_fat/delivery.sets @@ -0,0 +1 @@ +SLE diff --git a/dev/com.ibm.ws.config.utility_fat/fat/src/com/ibm/ws/config/utility/fat/FATSuite.java b/dev/com.ibm.ws.config.utility_fat/fat/src/com/ibm/ws/config/utility/fat/FATSuite.java new file mode 100755 index 00000000000..19b0cca3054 --- /dev/null +++ b/dev/com.ibm.ws.config.utility_fat/fat/src/com/ibm/ws/config/utility/fat/FATSuite.java @@ -0,0 +1,23 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2015 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.config.utility.fat; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +/** + * Collection of all FAT tests + */ +@RunWith(Suite.class) +@SuiteClasses({ ServerConfigUtilityFatTesting.class }) +public class FATSuite {} \ No newline at end of file diff --git a/dev/com.ibm.ws.config.utility_fat/fat/src/com/ibm/ws/config/utility/fat/ServerConfigUtilityFatTesting.java b/dev/com.ibm.ws.config.utility_fat/fat/src/com/ibm/ws/config/utility/fat/ServerConfigUtilityFatTesting.java new file mode 100755 index 00000000000..69f63909d74 --- /dev/null +++ b/dev/com.ibm.ws.config.utility_fat/fat/src/com/ibm/ws/config/utility/fat/ServerConfigUtilityFatTesting.java @@ -0,0 +1,336 @@ +package com.ibm.ws.config.utility.fat; + +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2015 + * + * The source code for this program is not published or other- + * wise divested of its trade secrets, irrespective of what has + * been deposited with the U.S. Copyright Office. + */ +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.IOException; +import java.util.Properties; + +import org.apache.commons.io.FileUtils; +import org.junit.AfterClass; +import org.junit.Assume; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.ibm.websphere.simplicity.Machine; +import com.ibm.websphere.simplicity.ProgramOutput; +import com.ibm.websphere.simplicity.log.Log; +import componenttest.custom.junit.runner.Mode; +import componenttest.custom.junit.runner.Mode.TestMode; +import componenttest.topology.impl.LibertyServer; + +public class ServerConfigUtilityFatTesting extends TestRepository { + + private static final Class c = ServerConfigUtilityFatTesting.class; + + static Machine machine; + String installRoot = server.getInstallRoot(); + String controllerPort = System.getProperty("HTTP_default.secure"); + String adminUser = "user001"; + String adminPassword = "pass001"; + String keystorePassword = "passwordKeystore"; + String encodingType = "aes"; + String configFilePath = System.getProperty("user.dir") + System.getProperty("file.separator") + "configFile.txt"; + + private static final String SLASH = System.getProperty("file.separator"); + public static LibertyServer server = TestRepository.server; + + @BeforeClass + public static void setUp() throws Exception { + Assume.assumeTrue(new TestRepository().testRepositoryConnection()); + final String methodName = "setUp"; + Log.entering(c, methodName); + + machine = server.getMachine(); + Log.info(c, methodName, "Starting Server"); + server.startServer(); + + // Wait for the smarter planet message + assertNotNull("The smarter planet message did not get printed", server.waitForStringInLog("CWWKF0011I")); + Log.exiting(c, methodName); + } + + @AfterClass + public static void tearDown() throws Exception { + if (server.isStarted()) { + server.stopServer(); + } + } + + public static String readFile(String path) throws IOException { + return FileUtils.readFileToString(new File(path)).trim(); + } + + @Mode(TestMode.LITE) + @Test + public void testConfigUtilityUseLocalFile() throws Exception { + Assume.assumeTrue(testRepositoryConnection()); + final String methodName = "testConfigUtilityUseLocalFile"; + + Log.entering(c, methodName); + Properties env = new Properties(); + + String p = server.getServerRoot() + SLASH + "files" + SLASH + "remoteJMXConnection.xml"; + Log.info(c, methodName, "Running configUtility --useLocalFile"); + Log.info(c, methodName, "Path to --useLocalFile" + p); + ProgramOutput po = machine.execute(server.getInstallRoot() + "/bin/configUtility", + new String[] { + "install", + "--useLocalFile=" + p, + "--VadminUser=" + adminUser, + "--VwritePath=path1", + "--encoding=" + encodingType, + "--key=" + "123", + "--VhttpPort=8081" + }, + installRoot, + env); + + Log.info(c, methodName, "Executed configUtility command:" + po.getCommand()); + Log.info(c, methodName, "--useLocalFile result:\n" + po.getStdout()); + assertEquals("ConfigUtility task should complete with return code as 0.", 0, po.getReturnCode()); + + assertTrue("Fail: did not match expected username:", po.getStdout().contains("userName=\"" + adminUser + "\"")); + assertTrue("Fail: did not match expected writePath snippet:path1", po.getStdout().contains("path1")); + assertTrue("Fail: did not match expected httpPort snippet:", po.getStdout().toString().contains("httpPort=\"8081\"")); + + Log.exiting(c, methodName); + } + + @Mode(TestMode.LITE) + @Test + public void testConfigUtilityCheckErrorCodes() throws Exception { + Assume.assumeTrue(testRepositoryConnection()); + final String methodName = "testConfigUtilityCheckErrorCodes"; + + Log.entering(c, methodName); + Properties env = new Properties(); + + String p = server.getServerRoot() + SLASH + "files" + SLASH + "remoteJMXConnection.xml"; + Log.info(c, methodName, "Running configUtility --useLocalFile"); + Log.info(c, methodName, "Path to --useLocalFile" + p); + + ProgramOutput po = machine.execute(server.getInstallRoot() + "/bin/configUtility", + new String[] { + "install", + "--useLocalFile=" + p + "abc", + "--VadminUser=" + adminUser, + "--VwritePath=path1", + "--encoding=" + encodingType, + "--key=" + "123", + "--VhttpPort=8081" + }, + installRoot, + env); + + Log.info(c, methodName, "Executed configUtility command:" + po.getCommand()); + Log.info(c, methodName, "--useLocalFile result:\n" + po.getStdout()); + assertEquals("ConfigUtility task should complete with return code as 255.", 255, po.getReturnCode()); + + Log.exiting(c, methodName); + } + + @Mode(TestMode.LITE) + @Test + public void testInvalidValArgsConfigUtility() throws Exception { + Assume.assumeTrue(testRepositoryConnection()); + final String methodName = "testInvalidValArgsConfigUtility"; + + Log.entering(c, methodName); + Properties env = new Properties(); + + String p = server.getServerRoot() + SLASH + "files" + SLASH + "remoteJMXConnection.xml"; + Log.info(c, methodName, "Running configUtility --useLocalFile"); + Log.info(c, methodName, "Path to --useLocalFile" + p); + + ProgramOutput po = machine.execute(server.getInstallRoot() + "/bin/configUtility", + new String[] { + "install", + "--useLocalFile=" + p, + "--Vinvalid=" + adminUser, + "--VwritePath=path1", + "--encoding=" + encodingType, + "--key=" + "123", + "--VhttpPort=8081" + }, + installRoot, + env); + + Log.info(c, methodName, "Executed configUtility command:" + po.getCommand()); + Log.info(c, methodName, "--useLocalFile result:\n" + po.getStdout()); + assertEquals("ConfigUtility task should complete with return code as 20.", 20, po.getReturnCode()); + + Log.exiting(c, methodName); + } + + @Mode(TestMode.LITE) + @Test + public void testEncodingConfigUtilityUseLocalFile() throws Exception { + Assume.assumeTrue(testRepositoryConnection()); + final String methodName = "testEncodingConfigUtilityUseLocalFile"; + + Log.entering(c, methodName); + Properties env = new Properties(); + + Log.info(c, methodName, "Running configUtility --useLocalFile"); + + String p = server.getServerRoot() + SLASH + "files" + SLASH + "remoteJMXConnection.xml"; + ProgramOutput po = machine.execute(server.getInstallRoot() + "/bin/configUtility", + new String[] { + "install", + "--useLocalFile=" + p, + "--VadminUser=" + adminUser, + "--VwritePath=" + "path1", + "--VadminPassword=" + adminPassword, + "--VkeystorePassword=" + keystorePassword, + "--encoding=" + encodingType, + "--key=" + "123" + }, + installRoot, + env); + + Log.info(c, methodName, "Executed configUtility command:" + po.getCommand()); + Log.info(c, methodName, "ConfigUtility result:\n" + po.getStdout()); + assertEquals("ConfigUtility task should complete with return code as 0.", 0, po.getReturnCode()); + + assertTrue("Fail: did not match expected username:", po.getStdout().contains("userName=\"" + adminUser + "\"")); + assertTrue("Fail: did not match expected writePath snippet:path1", po.getStdout().contains("path1")); + assertFalse("Fail: adminPassword should not match generated password:", + po.getStdout().contains(adminPassword)); + assertTrue("Fail: did not match expected encodingType 'aes':", + po.getStdout().contains("userPassword=\"{aes}")); + + Log.exiting(c, methodName); + } + + @Mode(TestMode.LITE) + @Test + public void testDefaultEncodingConfigUtility() throws Exception { + Assume.assumeTrue(testRepositoryConnection()); + final String methodName = "testDefaultEncodingConfigUtility"; + + Log.entering(c, methodName); + Properties env = new Properties(); + + Log.info(c, methodName, "Running configUtility --useLocalFile"); + String p = server.getServerRoot() + SLASH + "files" + SLASH + "remoteJMXConnection.xml"; + ProgramOutput po = machine.execute(server.getInstallRoot() + "/bin/configUtility", + new String[] { + "install", + "--useLocalFile=" + p, + "--VadminUser=" + adminUser, + "--VwritePath=" + "path1", + "--VadminPassword=" + adminPassword, + "--VkeystorePassword=" + keystorePassword + }, + installRoot, + env); + + Log.info(c, methodName, "Executed configUtility command:" + po.getCommand()); + Log.info(c, methodName, "ConfigUtility result:\n" + po.getStdout()); + assertEquals("ConfigUtility task should complete with return code as 0.", 0, po.getReturnCode()); + + assertTrue("Fail: did not match expected username:", po.getStdout().contains("userName=\"" + adminUser + "\"")); + assertTrue("Fail: did not match expected writePath snippet:path1", po.getStdout().contains("path1")); + assertFalse("Fail: adminPassword should not match generated password:", + po.getStdout().contains(adminPassword)); + assertTrue("Fail: did not match expected encodingType 'xor':userPassword=\"{xor}", + po.getStdout().contains("userPassword=\"{xor}")); + + Log.exiting(c, methodName); + } + + @Mode(TestMode.LITE) + @Test + public void testFindAllConfigSnippets() throws Exception { + Assume.assumeTrue(testRepositoryConnection()); + final String methodName = "testFindAllConfigSnippets"; + + Log.entering(c, methodName); + Properties env = new Properties(); + + Log.info(c, methodName, "Running configUtility find"); + + ProgramOutput po = machine.execute(server.getInstallRoot() + "/bin/configUtility", + new String[] { "find" }, + installRoot, + env); + + Log.info(c, methodName, "Executed configUtility command:" + po.getCommand()); + + assertFalse("FAIL: configUtility find should return all snippets:", po.getStdout().isEmpty()); + Log.exiting(c, methodName); + } + + @Mode(TestMode.LITE) + @Test + public void testFindRelatedConfigSnippets() throws Exception { + Assume.assumeTrue(testRepositoryConnection()); + final String methodName = "testFindRelatedConfigSnippets"; + + Log.entering(c, methodName); + Properties env = new Properties(); + String arg = "security"; + + Log.info(c, methodName, "Running configUtility find " + arg); + + ProgramOutput po = machine.execute(server.getInstallRoot() + "/bin/configUtility", + new String[] { "find", arg }, + installRoot, + env); + + Log.info(c, methodName, "Executed configUtility command:" + po.getCommand()); + + assertFalse("FAIL: configUtility info should return snippets related to " + arg, po.getStdout().isEmpty()); + Log.exiting(c, methodName); + } + + @Mode(TestMode.LITE) + @Test + public void testCreateConfigFileSnippets() throws Exception { + Assume.assumeTrue(testRepositoryConnection()); + final String methodName = "testCreateConfigFileSnippets"; + + Log.entering(c, methodName); + Properties env = new Properties(); + + Log.info(c, methodName, "Running configUtility -list"); + Log.info(c, methodName, "Create Config File in " + configFilePath); + String p = server.getServerRoot() + SLASH + "files" + SLASH + "remoteJMXConnection.xml"; + ProgramOutput po = machine.execute(server.getInstallRoot() + "/bin/configUtility", + new String[] { + "install", + "--useLocalFile=" + p, + "--VadminUser=" + adminUser, + "--VwritePath=" + "path1", + "--VadminPassword=" + adminPassword, + "--VkeystorePassword=" + keystorePassword, + "--createConfigFile=" + configFilePath + }, + installRoot, + env); + + Log.info(c, methodName, "Executed configUtility command:" + po.getCommand()); + Log.info(c, methodName, "ConfigFile result:\n" + po.getStdout()); + + File configFile = new File(configFilePath); + assertTrue("The configFile " + configFilePath + " was created.", configFile.exists()); + configFile.deleteOnExit(); + + Log.exiting(c, methodName); + } +} \ No newline at end of file diff --git a/dev/com.ibm.ws.config.utility_fat/fat/src/com/ibm/ws/config/utility/fat/TestRepository.java b/dev/com.ibm.ws.config.utility_fat/fat/src/com/ibm/ws/config/utility/fat/TestRepository.java new file mode 100755 index 00000000000..1a8adb15702 --- /dev/null +++ b/dev/com.ibm.ws.config.utility_fat/fat/src/com/ibm/ws/config/utility/fat/TestRepository.java @@ -0,0 +1,72 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2015 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.config.utility.fat; + +import java.io.File; + +import org.junit.Rule; +import org.junit.rules.TestName; + +import com.ibm.websphere.simplicity.log.Log; +import com.ibm.ws.repository.connections.RestRepositoryConnection; +import com.ibm.ws.repository.connections.liberty.MainRepository; + +import componenttest.topology.impl.LibertyServer; +import componenttest.topology.impl.LibertyServerFactory; + +/** + * + * TestRepository makes sure that the connection to the repository is successful + */ +public class TestRepository { + + private static Class logClass = TestRepository.class; + public static boolean connectedToRepo = false; + public static String massiveRepoFile; + private static String repositoryUrl; + public static LibertyServer server = LibertyServerFactory.getLibertyServer("com.ibm.ws.config.utility.fat"); + + @Rule + public final TestName method = new TestName(); + private static final String SLASH = System.getProperty("file.separator"); + + @SuppressWarnings("deprecation") + public boolean testRepositoryConnection() { + Log.entering(logClass, method.getMethodName()); + try { + massiveRepoFile = server.pathToAutoFVTTestFiles + "massive" + SLASH + "massiveRepoLocation.props"; + + String repositoryDescriptionUrl = new File(massiveRepoFile).getCanonicalFile().toURI().toURL().toString(); + System.setProperty("repository.description.url", repositoryDescriptionUrl); + + RestRepositoryConnection connection = MainRepository.createConnection(); + connectedToRepo = connection.isRepositoryAvailable(); + + if (connectedToRepo) { + Log.info(logClass, method.getMethodName(), "Repository connection is OK."); + } else { + connectedToRepo = false; + Log.info(logClass, method.getMethodName(), "Cannot connect to the test repository: " + repositoryUrl); + } + + } catch (Exception e) { + Log.info(logClass, method.getMethodName(), "Cannot connect to the repository : " + e.getMessage()); + connectedToRepo = false; + } finally { + MainRepository.clearCachedRepoProperties(); + } + + Log.exiting(logClass, method.getMethodName()); + return connectedToRepo; + } + +} diff --git a/dev/com.ibm.ws.config.utility_fat/publish/files/massive/massiveRepoLocation.props b/dev/com.ibm.ws.config.utility_fat/publish/files/massive/massiveRepoLocation.props new file mode 100755 index 00000000000..7ce8be4e822 --- /dev/null +++ b/dev/com.ibm.ws.config.utility_fat/publish/files/massive/massiveRepoLocation.props @@ -0,0 +1,6 @@ +# Details for Test Massive Repo - Toronto Polaris Team + +repository.url=http://ltestl91.hursley.ibm.com:9002/ma/v1 +apiKey=79984835186 +userId=xmlxsltb@ca.ibm.com +password=Polaris2015 \ No newline at end of file diff --git a/dev/com.ibm.ws.config.utility_fat/publish/servers/com.ibm.ws.config.utility.fat/bootstrap.properties b/dev/com.ibm.ws.config.utility_fat/publish/servers/com.ibm.ws.config.utility.fat/bootstrap.properties new file mode 100755 index 00000000000..08ade3c8318 --- /dev/null +++ b/dev/com.ibm.ws.config.utility_fat/publish/servers/com.ibm.ws.config.utility.fat/bootstrap.properties @@ -0,0 +1,8 @@ +com.ibm.ws.logging.trace.specification=*=event=enabled:\ +com.ibm.ws.collective.member.*=all=enabled:\ +com.ibm.ws.collective.repository.*=all=enabled +com.ibm.ws.collective.utility.*=all=enabled +com.ibm.ws.logging.max.file.size=0 +ds.loglevel=debug + +bootstrap.include=../testports.properties \ No newline at end of file diff --git a/dev/com.ibm.ws.config.utility_fat/publish/servers/com.ibm.ws.config.utility.fat/files/ejbSnippet.xml b/dev/com.ibm.ws.config.utility_fat/publish/servers/com.ibm.ws.config.utility.fat/files/ejbSnippet.xml new file mode 100755 index 00000000000..0d8f77439f6 --- /dev/null +++ b/dev/com.ibm.ws.config.utility_fat/publish/servers/com.ibm.ws.config.utility.fat/files/ejbSnippet.xml @@ -0,0 +1,50 @@ + +Downloading the requested config snippet... + +Modifiying the config snippet... + + + + + appSecurity-2.0 + ejbLite-3.1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Please ensure administrative security is configured for the server. diff --git a/dev/com.ibm.ws.config.utility_fat/publish/servers/com.ibm.ws.config.utility.fat/files/remoteJMXConnection.xml b/dev/com.ibm.ws.config.utility_fat/publish/servers/com.ibm.ws.config.utility.fat/files/remoteJMXConnection.xml new file mode 100755 index 00000000000..a31952449ff --- /dev/null +++ b/dev/com.ibm.ws.config.utility_fat/publish/servers/com.ibm.ws.config.utility.fat/files/remoteJMXConnection.xml @@ -0,0 +1,32 @@ + + + + + + + restConnector-1.0 + + + + + + + + + + + + + + + ${writePath} + ${readPath} + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config.utility_fat/publish/servers/com.ibm.ws.config.utility.fat/files/resultingSnippet.xml b/dev/com.ibm.ws.config.utility_fat/publish/servers/com.ibm.ws.config.utility.fat/files/resultingSnippet.xml new file mode 100755 index 00000000000..e94b5be515f --- /dev/null +++ b/dev/com.ibm.ws.config.utility_fat/publish/servers/com.ibm.ws.config.utility.fat/files/resultingSnippet.xml @@ -0,0 +1,36 @@ + + + + + + + + restConnector-1.0 + + + + + + + + + + + + + + + ${writePath} + ${readPath} + + + + +Please ensure administrative security is configured for the server. +An administrative user is required to join members to the collective. diff --git a/dev/com.ibm.ws.config.utility_fat/publish/servers/com.ibm.ws.config.utility.fat/resources/security/ltpa.keys b/dev/com.ibm.ws.config.utility_fat/publish/servers/com.ibm.ws.config.utility.fat/resources/security/ltpa.keys new file mode 100755 index 00000000000..e0e7d511ac3 --- /dev/null +++ b/dev/com.ibm.ws.config.utility_fat/publish/servers/com.ibm.ws.config.utility.fat/resources/security/ltpa.keys @@ -0,0 +1,8 @@ +#Sun Jan 15 15:01:21 CST 2012 +com.ibm.websphere.CreationDate=Sun Jan 15 15\:01\:21 CST 2012 +com.ibm.websphere.CreationHost=localhost +com.ibm.websphere.ltpa.Realm=PreGeneratedLTPAKeys +com.ibm.websphere.ltpa.version=1.0 +com.ibm.websphere.ltpa.3DESKey=xpUAUsH4SZc+VuiAqzL+Tz+MfBmb+6vv3/cGjIn+mR4\= +com.ibm.websphere.ltpa.PublicKey=AMan4Qo5MKIeYf26TJbTZwRdYai7rWRVXDwy/6XI1iq+CVxny1O74rE4cn7wXalID05hKwm/HUxvFd72Y3dABzL1bTUpl1uE6SQNePrcdrQC8rmtichsdvY0baiGYexURYP7fbHF5Z70RfQGCPYnuZTB9jsHdh4HJlrOlsx6K2mJAQAB +com.ibm.websphere.ltpa.PrivateKey=TkjZeR/1L6khA7UKNjBRI1T+nbwEWXv1AWVSOCEgpKfLvw8iAkIc7+8I2zfc3j88XciTxDuagepUDoWCXHJ1ithSptZSLnHBASD7Ki1dLTKY7jszPXmIIwoa8YaQFtuuNeSJ7r6r8krSB5ml5sk7aTF0Sed8TFrx1aDEQRIZCovZV8BQX29bBZC99gTqk3chCpcOVRqcxvQRGzdP0PenvaA9afeflV5t4Iw8errfmHjedNVDog90ZVVAeecO+ZLqn7yAHh98ZTdV9IEVyqnFI7XQljrMJsNt3zl/tB7ktQ6VuyxJmlQdDbmvJ+F6DZeR9lVC991a/Ks0i1VKVOrwhPxJYLX2Xz7MWpLu09pwapo\= diff --git a/dev/com.ibm.ws.config.utility_fat/publish/servers/com.ibm.ws.config.utility.fat/server.xml b/dev/com.ibm.ws.config.utility_fat/publish/servers/com.ibm.ws.config.utility.fat/server.xml new file mode 100755 index 00000000000..80576a2e13b --- /dev/null +++ b/dev/com.ibm.ws.config.utility_fat/publish/servers/com.ibm.ws.config.utility.fat/server.xml @@ -0,0 +1,9 @@ + + + + + servlet-3.0 + restConnector-1.0 + + + diff --git a/dev/com.ibm.ws.config_bvt.schema/.classpath b/dev/com.ibm.ws.config_bvt.schema/.classpath new file mode 100644 index 00000000000..c8c4cd4a46c --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/dev/com.ibm.ws.config_bvt.schema/.classpath.gradle b/dev/com.ibm.ws.config_bvt.schema/.classpath.gradle new file mode 100644 index 00000000000..c8c4cd4a46c --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/.classpath.gradle @@ -0,0 +1,7 @@ + + + + + + + diff --git a/dev/com.ibm.ws.config_bvt.schema/.project b/dev/com.ibm.ws.config_bvt.schema/.project new file mode 100755 index 00000000000..34341dba146 --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/.project @@ -0,0 +1,23 @@ + + + com.ibm.ws.config_bvt.schema + + + + + + org.eclipse.jdt.core.javabuilder + + + + + bndtools.core.bndbuilder + + + + + + org.eclipse.jdt.core.javanature + bndtools.core.bndnature + + diff --git a/dev/com.ibm.ws.config_bvt.schema/.settings/org.eclipse.core.resources.prefs b/dev/com.ibm.ws.config_bvt.schema/.settings/org.eclipse.core.resources.prefs new file mode 100755 index 00000000000..25d9425fe34 --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,4 @@ +#Ant properties +#Automatically generated by the ant prepare.settings.files task +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/dev/com.ibm.ws.config_bvt.schema/.settings/org.eclipse.jdt.core.prefs b/dev/com.ibm.ws.config_bvt.schema/.settings/org.eclipse.jdt.core.prefs new file mode 100755 index 00000000000..f48ecd6cc60 --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,280 @@ +#Ant properties +#Automatically generated by the ant prepare.settings.files task +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.6 +org.eclipse.jdt.core.formatter.align_type_members_on_columns=false +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=0 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=18 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=2 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=2 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=18 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=2 +org.eclipse.jdt.core.formatter.alignment_for_assignment=0 +org.eclipse.jdt.core.formatter.alignment_for_binary_expression=18 +org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=0 +org.eclipse.jdt.core.formatter.alignment_for_enum_constants=16 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=18 +org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=18 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=18 +org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=0 +org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=20 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=4 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +org.eclipse.jdt.core.formatter.blank_lines_before_field=0 +org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 +org.eclipse.jdt.core.formatter.blank_lines_before_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 +org.eclipse.jdt.core.formatter.blank_lines_before_package=0 +org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 +org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 +org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false +org.eclipse.jdt.core.formatter.comment.format_block_comments=true +org.eclipse.jdt.core.formatter.comment.format_header=false +org.eclipse.jdt.core.formatter.comment.format_html=false +org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true +org.eclipse.jdt.core.formatter.comment.format_line_comments=false +org.eclipse.jdt.core.formatter.comment.format_source_code=true +org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true +org.eclipse.jdt.core.formatter.comment.indent_root_tags=true +org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert +org.eclipse.jdt.core.formatter.comment.line_length=180 +org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true +org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true +org.eclipse.jdt.core.formatter.compact_else_if=true +org.eclipse.jdt.core.formatter.continuation_indentation=4 +org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=4 +org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off +org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on +org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false +org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=false +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true +org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_empty_lines=false +org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true +org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true +org.eclipse.jdt.core.formatter.indentation.size=8 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert +org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.join_lines_in_comments=false +org.eclipse.jdt.core.formatter.join_wrapped_lines=false +org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false +org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false +org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false +org.eclipse.jdt.core.formatter.lineSplit=180 +org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=true +org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=true +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 +org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=false +org.eclipse.jdt.core.formatter.tabulation.char=space +org.eclipse.jdt.core.formatter.tabulation.size=4 +org.eclipse.jdt.core.formatter.use_on_off_tags=true +org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false +org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true +org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true diff --git a/dev/com.ibm.ws.config_bvt.schema/.settings/org.eclipse.jdt.ui.prefs b/dev/com.ibm.ws.config_bvt.schema/.settings/org.eclipse.jdt.ui.prefs new file mode 100755 index 00000000000..3d73ed77a17 --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,113 @@ +#Ant properties +#Automatically generated by the ant prepare.settings.files task +cleanup.add_default_serial_version_id=false +cleanup.add_generated_serial_version_id=true +cleanup.add_missing_annotations=true +cleanup.add_missing_deprecated_annotations=true +cleanup.add_missing_methods=false +cleanup.add_missing_nls_tags=false +cleanup.add_missing_override_annotations=true +cleanup.add_missing_override_annotations_interface_methods=true +cleanup.add_serial_version_id=false +cleanup.always_use_blocks=true +cleanup.always_use_parentheses_in_expressions=false +cleanup.always_use_this_for_non_static_field_access=false +cleanup.always_use_this_for_non_static_method_access=false +cleanup.convert_to_enhanced_for_loop=false +cleanup.correct_indentation=true +cleanup.format_source_code=false +cleanup.format_source_code_changes_only=false +cleanup.make_local_variable_final=false +cleanup.make_parameters_final=true +cleanup.make_private_fields_final=false +cleanup.make_type_abstract_if_missing_method=false +cleanup.make_variable_declarations_final=false +cleanup.never_use_blocks=false +cleanup.never_use_parentheses_in_expressions=true +cleanup.organize_imports=true +cleanup.qualify_static_field_accesses_with_declaring_class=false +cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true +cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true +cleanup.qualify_static_member_accesses_with_declaring_class=true +cleanup.qualify_static_method_accesses_with_declaring_class=false +cleanup.remove_private_constructors=true +cleanup.remove_trailing_whitespaces=true +cleanup.remove_trailing_whitespaces_all=true +cleanup.remove_trailing_whitespaces_ignore_empty=false +cleanup.remove_unnecessary_casts=true +cleanup.remove_unnecessary_nls_tags=true +cleanup.remove_unused_imports=true +cleanup.remove_unused_local_variables=false +cleanup.remove_unused_private_fields=true +cleanup.remove_unused_private_members=false +cleanup.remove_unused_private_methods=true +cleanup.remove_unused_private_types=true +cleanup.sort_members=false +cleanup.sort_members_all=false +cleanup.use_blocks=true +cleanup.use_blocks_only_for_return_and_throw=false +cleanup.use_parentheses_in_expressions=true +cleanup.use_this_for_non_static_field_access=false +cleanup.use_this_for_non_static_field_access_only_if_necessary=true +cleanup.use_this_for_non_static_method_access=false +cleanup.use_this_for_non_static_method_access_only_if_necessary=true +eclipse.preferences.version=1 +editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true +org.eclipse.jdt.ui.ignorelowercasenames=true +org.eclipse.jdt.ui.importorder=java;javax;org;com; +org.eclipse.jdt.ui.javadoc=true +org.eclipse.jdt.ui.ondemandthreshold=99 +org.eclipse.jdt.ui.staticondemandthreshold=99 +org.eclipse.jdt.ui.text.custom_code_templates= +sp_cleanup.add_default_serial_version_id=true +sp_cleanup.add_generated_serial_version_id=false +sp_cleanup.add_missing_annotations=true +sp_cleanup.add_missing_deprecated_annotations=true +sp_cleanup.add_missing_methods=false +sp_cleanup.add_missing_nls_tags=false +sp_cleanup.add_missing_override_annotations=true +sp_cleanup.add_missing_override_annotations_interface_methods=true +sp_cleanup.add_serial_version_id=false +sp_cleanup.always_use_blocks=true +sp_cleanup.always_use_parentheses_in_expressions=false +sp_cleanup.always_use_this_for_non_static_field_access=false +sp_cleanup.always_use_this_for_non_static_method_access=false +sp_cleanup.convert_to_enhanced_for_loop=false +sp_cleanup.correct_indentation=false +sp_cleanup.format_source_code=true +sp_cleanup.format_source_code_changes_only=false +sp_cleanup.make_local_variable_final=false +sp_cleanup.make_parameters_final=false +sp_cleanup.make_private_fields_final=true +sp_cleanup.make_type_abstract_if_missing_method=false +sp_cleanup.make_variable_declarations_final=true +sp_cleanup.never_use_blocks=false +sp_cleanup.never_use_parentheses_in_expressions=true +sp_cleanup.on_save_use_additional_actions=true +sp_cleanup.organize_imports=true +sp_cleanup.qualify_static_field_accesses_with_declaring_class=false +sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_with_declaring_class=false +sp_cleanup.qualify_static_method_accesses_with_declaring_class=false +sp_cleanup.remove_private_constructors=true +sp_cleanup.remove_trailing_whitespaces=true +sp_cleanup.remove_trailing_whitespaces_all=true +sp_cleanup.remove_trailing_whitespaces_ignore_empty=false +sp_cleanup.remove_unnecessary_casts=true +sp_cleanup.remove_unnecessary_nls_tags=true +sp_cleanup.remove_unused_imports=true +sp_cleanup.remove_unused_local_variables=false +sp_cleanup.remove_unused_private_fields=true +sp_cleanup.remove_unused_private_members=false +sp_cleanup.remove_unused_private_methods=true +sp_cleanup.remove_unused_private_types=true +sp_cleanup.sort_members=false +sp_cleanup.sort_members_all=false +sp_cleanup.use_blocks=false +sp_cleanup.use_blocks_only_for_return_and_throw=false +sp_cleanup.use_parentheses_in_expressions=false +sp_cleanup.use_this_for_non_static_field_access=false +sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true +sp_cleanup.use_this_for_non_static_method_access=false +sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true diff --git a/dev/com.ibm.ws.config_bvt.schema/bnd.bnd b/dev/com.ibm.ws.config_bvt.schema/bnd.bnd new file mode 100755 index 00000000000..d6ad84f508f --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bnd.bnd @@ -0,0 +1,18 @@ +-include= ~../cnf/resources/bnd/liberty-release.props +bVersion=1.0 + +-nobundles=true + +src: \ + bvt/src + +-buildpath: \ + ${javac.bootclasspath.java6}, \ + ../build.sharedResources/lib/junit/old/junit.jar;version=file, \ + ../build.sharedResources/lib/ws-junit/ws-junit.jar;version=file, \ + fattest.simplicity;version=latest, \ + ../fattest.simplicity/lib/public.api.jar;version=file, \ + com.ibm.websphere.filetransfer;version=latest, \ + com.ibm.ws.jmx.connector.client.rest;version=latest, \ + com.ibm.ws.kernel.service;version=latest, \ + com.ibm.ws.config;version=latest diff --git a/dev/com.ibm.ws.config_bvt.schema/bnd.bnd.gradle b/dev/com.ibm.ws.config_bvt.schema/bnd.bnd.gradle new file mode 100755 index 00000000000..d6ad84f508f --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bnd.bnd.gradle @@ -0,0 +1,18 @@ +-include= ~../cnf/resources/bnd/liberty-release.props +bVersion=1.0 + +-nobundles=true + +src: \ + bvt/src + +-buildpath: \ + ${javac.bootclasspath.java6}, \ + ../build.sharedResources/lib/junit/old/junit.jar;version=file, \ + ../build.sharedResources/lib/ws-junit/ws-junit.jar;version=file, \ + fattest.simplicity;version=latest, \ + ../fattest.simplicity/lib/public.api.jar;version=file, \ + com.ibm.websphere.filetransfer;version=latest, \ + com.ibm.ws.jmx.connector.client.rest;version=latest, \ + com.ibm.ws.kernel.service;version=latest, \ + com.ibm.ws.config;version=latest diff --git a/dev/com.ibm.ws.config_bvt.schema/build-bvt.xml b/dev/com.ibm.ws.config_bvt.schema/build-bvt.xml new file mode 100755 index 00000000000..cfd95ae8350 --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/build-bvt.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/com.ibm.ws.config_bvt.schema/build.gradle b/dev/com.ibm.ws.config_bvt.schema/build.gradle new file mode 100644 index 00000000000..e69de29bb2d diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle.bnd b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle.bnd new file mode 100755 index 00000000000..6a076d8a1fa --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle.bnd @@ -0,0 +1,22 @@ +-include= ~../cnf/resources/bnd/bundle.props +bVersion = 1.0 + +Bundle-Name: Schema Generator Servlet +Bundle-SymbolicName: test.server.schema +Bundle-Description: Schema Generator Servlet Bundle, version ${bVersion} + +Service-Component: test.server.schema.servlet; \ + implementation:=test.server.schema.SchemaGeneratorActivator; \ + http=org.osgi.service.http.HttpService; \ + schemaGenerator=com.ibm.websphere.metatype.SchemaGenerator; \ + locationService=com.ibm.wsspi.kernel.service.location.WsLocationAdmin; \ + immediate:=true; \ + properties:="service.vendor=IBM" + +Private-Package: test.server.* + +Import-Package: \ + !*.internal.*, * + +Include-Resource: \ + @junit.jar diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/config/factory-one.xml b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/config/factory-one.xml new file mode 100755 index 00000000000..ec9638411f3 --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/config/factory-one.xml @@ -0,0 +1,8 @@ + + + + 192.168.1.1 + 192.168.1.2 + + + diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/config/factory-two.xml b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/config/factory-two.xml new file mode 100755 index 00000000000..ac83f85b806 --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/config/factory-two.xml @@ -0,0 +1,7 @@ + + + + localhost + + + diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/config/singleton.xml b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/config/singleton.xml new file mode 100755 index 00000000000..aa6de86a06b --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/config/singleton.xml @@ -0,0 +1,8 @@ + + + + 192.168.1.1 + 192.168.1.2 + + + diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-attributecopy.xml b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-attributecopy.xml new file mode 100755 index 00000000000..814ccb257f1 --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-attributecopy.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-childfirstextends.xml b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-childfirstextends.xml new file mode 100755 index 00000000000..a4eef6a04bd --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-childfirstextends.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-default.xml b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-default.xml new file mode 100755 index 00000000000..4104848f4cd --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-default.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-dynamic.xml b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-dynamic.xml new file mode 100755 index 00000000000..5c3bb23e0e4 --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-dynamic.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-extensions-two.xml b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-extensions-two.xml new file mode 100755 index 00000000000..fb6ec51a0f7 --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-extensions-two.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-extensions.xml b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-extensions.xml new file mode 100755 index 00000000000..3c8cd56a279 --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-extensions.xml @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-hidden.xml b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-hidden.xml new file mode 100755 index 00000000000..dc9cba68f5c --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-hidden.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-nested-defaults.xml b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-nested-defaults.xml new file mode 100755 index 00000000000..3517b65d8f2 --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-nested-defaults.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-nested-merge.xml b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-nested-merge.xml new file mode 100755 index 00000000000..45191d7342d --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-nested-merge.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-nested-two.xml b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-nested-two.xml new file mode 100755 index 00000000000..298392be79b --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-nested-two.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-nested.xml b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-nested.xml new file mode 100755 index 00000000000..2517e32e3e4 --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-nested.xml @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-reference.xml b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-reference.xml new file mode 100755 index 00000000000..822bc5c71ad --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-reference.xml @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-serviceobjectclass.xml b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-serviceobjectclass.xml new file mode 100755 index 00000000000..eb51e264151 --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-serviceobjectclass.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-variable.xml b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-variable.xml new file mode 100755 index 00000000000..df6523ed86a --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype-variable.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype.xml b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype.xml new file mode 100755 index 00000000000..8221cb375f0 --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/resources/metatype.xml @@ -0,0 +1,151 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/BaseHttpTest.java b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/BaseHttpTest.java new file mode 100755 index 00000000000..7d0c513401b --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/BaseHttpTest.java @@ -0,0 +1,62 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011 + * + * The source code for this program is not published or otherwise divested of + * its trade secrets, irrespective of what has been deposited with the U.S. + * Copyright Office. + */ +package test.server; + +import java.util.Dictionary; +import java.util.HashSet; +import java.util.Set; + +import javax.servlet.Servlet; +import javax.servlet.ServletException; + +import org.osgi.service.component.ComponentContext; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; +import org.osgi.service.http.HttpContext; +import org.osgi.service.http.HttpService; +import org.osgi.service.http.NamespaceException; + +@Component +public abstract class BaseHttpTest { + + protected volatile HttpService http = null; + private final Set registrations = new HashSet(); + + protected void activate(ComponentContext context) throws Exception {} + + protected void deactivate(ComponentContext context) { + for (String alias : registrations) { + http.unregister(alias); + } + http = null; + } + + protected void registerServlet(String alias, Servlet servlet, Dictionary initParams, HttpContext context) throws ServletException, NamespaceException { + if (http == null) { + throw new NullPointerException("Http service is not present"); + } + http.registerServlet(alias, servlet, initParams, context); + registrations.add(alias); + } + + @Reference(name = "http", service = HttpService.class) + protected void setHttp(HttpService ref) { + this.http = ref; + } + + protected void unsetHttp(HttpService ref) { + if (ref == this.http) { + this.http = null; + } + } + +} diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/BaseTest.java b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/BaseTest.java new file mode 100755 index 00000000000..94e1f52e156 --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/BaseTest.java @@ -0,0 +1,30 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011 + * + * The source code for this program is not published or otherwise divested of + * its trade secrets, irrespective of what has been deposited with the U.S. + * Copyright Office. + */ +package test.server; + +public abstract class BaseTest { + + public static final long TIMEOUT = 30 * 1000; + + protected String name; + + public BaseTest(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public abstract String[] getServiceClasses(); + +} diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/BaseTestRunner.java b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/BaseTestRunner.java new file mode 100755 index 00000000000..a753213ba9d --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/BaseTestRunner.java @@ -0,0 +1,166 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011 + * + * The source code for this program is not published or otherwise divested of + * its trade secrets, irrespective of what has been deposited with the U.S. + * Copyright Office. + */ +package test.server; + +import static org.junit.Assert.fail; + +import java.io.BufferedWriter; +import java.io.Closeable; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.Dictionary; +import java.util.Enumeration; +import java.util.Hashtable; + +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.osgi.framework.BundleContext; +import org.osgi.framework.Constants; +import org.osgi.framework.ServiceReference; +import org.osgi.service.cm.ConfigurationAdmin; +import org.osgi.service.component.ComponentContext; +import org.osgi.service.component.annotations.Reference; + +import com.ibm.wsspi.kernel.service.location.WsLocationAdmin; +import com.ibm.wsspi.kernel.service.location.WsResource; + +import test.server.config.dynamic.ConfigWriter; + +public abstract class BaseTestRunner extends BaseHttpTest { + + protected BundleContext bundleContext; + protected WsLocationAdmin locationService; + protected ConfigurationAdmin configAdmin; + + @Override + protected void activate(ComponentContext context) throws Exception { + super.activate(context); + + bundleContext = context.getBundleContext(); + ServiceReference ref = bundleContext.getServiceReference(ConfigurationAdmin.class.getName()); + configAdmin = (ConfigurationAdmin) bundleContext.getService(ref); + } + + protected void addTest(BaseTest test) { + Dictionary properties = new Hashtable(); + properties.put(Constants.SERVICE_PID, test.getName()); + bundleContext.registerService(test.getServiceClasses(), test, properties); + } + + @Reference(name = "locationService", service = WsLocationAdmin.class) + protected void setLocationService(WsLocationAdmin ref) { + this.locationService = ref; + } + + protected void unsetLocationService(WsLocationAdmin ref) { + if (ref == this.locationService) { + this.locationService = null; + } + } + + private WsResource getConfigRoot() { + return locationService.resolveResource("${server.config.dir}/server.xml"); + } + + protected ConfigWriter readConfiguration() throws Exception { + InputStream in = getConfigRoot().get(); + try { + return new ConfigWriter(in); + } finally { + close(in); + } + } + + protected void writeConfiguration(ConfigWriter configWriter) throws Exception { + // try to write the entire config in one step (or least possible) + OutputStreamWriter os = new OutputStreamWriter(getConfigRoot().putStream(), "UTF-8"); + BufferedWriter writer = new BufferedWriter(os, 25 * 1024); + try { + configWriter.write(writer); + } finally { + close(writer); + } + StringWriter sw = new StringWriter(); + configWriter.write(sw); + System.out.println(sw.toString()); + } + + public static void dictionaryEquals(Dictionary one, Dictionary two) { + if (one.size() != two.size()) { + fail("Dictionaries are not the same: " + one + " " + two); + } + Enumeration e = one.keys(); + while (e.hasMoreElements()) { + Object key = e.nextElement(); + Object value1 = one.get(key); + Object value2 = two.get(key); + if (value1 instanceof String[] && value2 instanceof String[]) { + value1 = Arrays.asList((String[]) value1); + value2 = Arrays.asList((String[]) value2); + } + if (!value1.equals(value2)) { + fail("Dictionaries are not the same: " + key + " " + value1 + " " + value2); + } + } + } + + private void invokeTest(String testName) throws Exception { + Method method = getClass().getDeclaredMethod(testName); + method.invoke(this); + } + + public class TestDynamicConfigServlet extends HttpServlet { + private static final long serialVersionUID = 1L; + + @Override + public void doGet(HttpServletRequest rq, HttpServletResponse rsp) throws IOException { + PrintWriter pw = rsp.getWriter(); + rsp.setContentType("text/plain"); + + String testName = rq.getParameter("testName"); + + try { + log("Begin test: " + testName); + invokeTest(testName); + pw.println("OK"); + } catch (NoSuchMethodException e) { + pw.println("FAILED - Invalid test name: " + testName); + } catch (InvocationTargetException e) { + pw.println("FAILED"); + e.getTargetException().printStackTrace(pw); + } catch (Throwable e) { + pw.println("FAILED"); + e.printStackTrace(pw); + } finally { + log("End test: " + testName); + } + } + + } + + public static void close(Closeable closeable) { + if (closeable != null) { + try { + closeable.close(); + } catch (IOException ignore) { + } + } + } +} diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/ConfigurationAdminTest.java b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/ConfigurationAdminTest.java new file mode 100755 index 00000000000..79161e62be3 --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/ConfigurationAdminTest.java @@ -0,0 +1,79 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package test.server.config; + +import java.util.Dictionary; +import java.util.Hashtable; + +import junit.framework.Assert; + +import org.osgi.service.cm.Configuration; +import org.osgi.service.cm.ConfigurationAdmin; + +/** + * + */ +public class ConfigurationAdminTest extends Test { + private final ConfigurationAdmin configAdmin; + + public ConfigurationAdminTest(String name, ConfigurationAdmin ca) { + super(name, 0); + this.configAdmin = ca; + } + + public void testConfigurationAdmin() throws Exception { + String myPID = "my.test.pid"; + Configuration cfg = configAdmin.createFactoryConfiguration(myPID); + Dictionary props = new Hashtable(); + props.put("a", "a"); +// props.put("A", "a"); + cfg.update(props); + + Configuration caCfg = configAdmin.getConfiguration(cfg.getPid()); + Dictionary caProps = caCfg.getProperties(); + + // check # of elements + Assert.assertNotNull("missing key a", caProps.remove("a")); + Object o = caProps.remove("A"); + Assert.assertNull("has key A: " + o, o); + + // update dictionary make sure its copied + props.put("b", "b"); + Assert.assertNull("b is present", caProps.get("b")); + + caProps.put("c", "c"); + Dictionary caProps2 = caCfg.getProperties(); + Assert.assertNull("c is present", caProps2.get("c")); + + caCfg.update(caProps); + Assert.assertNull("c is present", caProps2.get("c")); + + caProps2 = caCfg.getProperties(); + Assert.assertNotNull("c is not present", caProps2.get("C")); + } + + @Override + public String[] getServiceClasses() { + return null; + } + + @Override + public Throwable getException() { + try { + testConfigurationAdmin(); + } catch (Throwable t) { + exception = t; + } + + return exception; + } +} diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/ConfigurationPluginTest.java b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/ConfigurationPluginTest.java new file mode 100755 index 00000000000..ad92d4dd101 --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/ConfigurationPluginTest.java @@ -0,0 +1,59 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011 + * + * The source code for this program is not published or otherwise divested of + * its trade secrets, irrespective of what has been deposited with the U.S. + * Copyright Office. + */ +package test.server.config; + +import java.util.Dictionary; + +import org.osgi.framework.Constants; +import org.osgi.framework.ServiceReference; +import org.osgi.service.cm.ConfigurationException; +import org.osgi.service.cm.ConfigurationPlugin; + +public class ConfigurationPluginTest extends ManagedFactoryTest implements ConfigurationPlugin { + + /** */ + private static final String VALUE = "VALUE"; + /** */ + private static final String NEW_KEY = "NEW_KEY"; + /** */ + private static final String INJECT = "inject"; + + public ConfigurationPluginTest(String name) { + super(name, 2); + } + + @Override + public String[] getServiceClasses() { + String[] baseServices = super.getServiceClasses(); + String[] services = new String[baseServices.length + 1]; + services[0] = ConfigurationPlugin.class.getName(); + System.arraycopy(baseServices, 0, services, 1, baseServices.length); + return services; + } + + @Override + public void configurationUpdated(String pid, Dictionary props) throws ConfigurationException { + if (Boolean.TRUE.equals(props.get(INJECT))) { + if (!props.get(NEW_KEY).equals(VALUE)) { + throw new ConfigurationException(NEW_KEY, "Missing " + VALUE); + } + } + } + + @Override + public void modifyConfiguration(ServiceReference ref, Dictionary props) { + if (name.equals(ref.getProperty(Constants.SERVICE_PID)) && Boolean.TRUE.equals(props.get(INJECT))) { + props.put(NEW_KEY, VALUE); + } + } + +} diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/FactoryAliasTest.java b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/FactoryAliasTest.java new file mode 100755 index 00000000000..2967607e157 --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/FactoryAliasTest.java @@ -0,0 +1,45 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011 + * + * The source code for this program is not published or otherwise divested of + * its trade secrets, irrespective of what has been deposited with the U.S. + * Copyright Office. + */ +package test.server.config; + +import static org.junit.Assert.assertEquals; + +import java.util.Dictionary; + +import org.osgi.service.cm.ConfigurationException; + +public class FactoryAliasTest extends ManagedFactoryTest { + + public FactoryAliasTest(String name, int count) { + super(name, count); + } + + @Override + public void configurationUpdated(String pid, Dictionary properties) throws ConfigurationException { + String id = (String) properties.get("id"); + + assertEquals("kids", new Integer(3), properties.get("kids")); + + if ("simpsons".equals(id)) { + assertEquals("lastName", "Simpson", properties.get("lastName")); + assertEquals("firstName", "Homer", properties.get("firstName")); + assertEquals("fullName", "Homer Simpson", properties.get("fullName")); + } else if ("griffins".equals(id)) { + assertEquals("lastName", "Griffin", properties.get("lastName")); + assertEquals("firstName", "Peter", properties.get("firstName")); + assertEquals("fullName", "Peter Griffin", properties.get("fullName")); + } else { + throw new RuntimeException("Invalid instance id: " + id); + } + } + +} diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/FactoryMetaTypeTest.java b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/FactoryMetaTypeTest.java new file mode 100755 index 00000000000..86fa93a8d0d --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/FactoryMetaTypeTest.java @@ -0,0 +1,49 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011 + * + * The source code for this program is not published or otherwise divested of + * its trade secrets, irrespective of what has been deposited with the U.S. + * Copyright Office. + */ +package test.server.config; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; + +import java.util.Arrays; +import java.util.Dictionary; +import java.util.Vector; + +import org.osgi.service.cm.ConfigurationException; + +public class FactoryMetaTypeTest extends ManagedFactoryTest { + + public FactoryMetaTypeTest(String name) { + super(name); + } + + @Override + public void configurationUpdated(String pid, Dictionary properties) throws ConfigurationException { + String id = (String) properties.get("id"); + if ("FamilyGuy".equals(id)) { + // picked up directly from metatype + assertEquals("present", Boolean.TRUE, properties.get("present")); + assertArrayEquals("int array", new int[] { 1, 2, 3 }, (int[]) properties.get("intColl")); + assertEquals("long vector", new Vector(Arrays.asList(4l, 5l, 6l, 7l)), properties.get("longColl")); + + // from metatype + assertEquals("lastname", "Griffin", properties.get("lastname")); + assertEquals("spouse", "Lois Griffin", properties.get("spouse")); + + // from server config + assertArrayEquals("children", new String[] { "Meg Griffin", "Chris Griffin" }, (String[]) properties.get("children")); + } else { + throw new RuntimeException("Invalid instance id: " + id); + } + } + +} diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/FactorySimpleTest.java b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/FactorySimpleTest.java new file mode 100755 index 00000000000..0b003cf92bf --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/FactorySimpleTest.java @@ -0,0 +1,38 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011 + * + * The source code for this program is not published or otherwise divested of + * its trade secrets, irrespective of what has been deposited with the U.S. + * Copyright Office. + */ +package test.server.config; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; + +import java.util.Dictionary; + +import org.osgi.service.cm.ConfigurationException; + +public class FactorySimpleTest extends ManagedFactoryTest { + + public FactorySimpleTest(String name, int count) { + super(name, count); + } + + @Override + public void configurationUpdated(String pid, Dictionary properties) throws ConfigurationException { + String id = (String) properties.get("id"); + if ("serverInstance".equals(id)) { + assertEquals("simple attr", "foo", properties.get("simpleAttr")); + assertArrayEquals("collection attr", new String[] { "Lisa", "Simpson" }, (String[]) properties.get("collAttr")); + } else { + throw new RuntimeException("Invalid instance id: " + id); + } + } + +} diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/FinalTypeTest.java b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/FinalTypeTest.java new file mode 100755 index 00000000000..adaf906721a --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/FinalTypeTest.java @@ -0,0 +1,41 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package test.server.config; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import java.util.Dictionary; + +/** + * + */ +public class FinalTypeTest extends ManagedTest { + + /** + * @param name + */ + public FinalTypeTest(String name) { + super(name); + } + + /** {@inheritDoc} */ + @Override + public void configurationUpdated(Dictionary properties) throws Exception { + assertEquals("name", "someName", properties.get("name")); + assertNull("finalField1 should be null but is " + properties.get("finalField1"), properties.get("finalField1")); + String configDir = System.getProperty("user.variable"); + assertEquals("finalField2 should be an expanded variable", configDir, properties.get("finalField2")); + assertEquals("finalField3 should be a default value", "someDefault", properties.get("finalField3")); + } + +} diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/ManagedFactoryTest.java b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/ManagedFactoryTest.java new file mode 100755 index 00000000000..327e68eb0af --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/ManagedFactoryTest.java @@ -0,0 +1,50 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011 + * + * The source code for this program is not published or otherwise divested of + * its trade secrets, irrespective of what has been deposited with the U.S. + * Copyright Office. + */ +package test.server.config; + +import java.util.Dictionary; + +import org.osgi.service.cm.ConfigurationException; +import org.osgi.service.cm.ManagedServiceFactory; + +public abstract class ManagedFactoryTest extends Test implements ManagedServiceFactory { + + public ManagedFactoryTest(String name) { + this(name, 1); + } + + public ManagedFactoryTest(String name, int count) { + super(name, count); + } + + @Override + public String[] getServiceClasses() { + return new String[] { ManagedServiceFactory.class.getName() }; + } + + @Override + public void updated(String pid, Dictionary properties) throws ConfigurationException { + try { + configurationUpdated(pid, properties); + } catch (Throwable e) { + exception = e; + } finally { + latch.countDown(); + } + } + + public abstract void configurationUpdated(String pid, Dictionary properties) throws Exception; + + @Override + public void deleted(String pid) {} + +} diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/ManagedTest.java b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/ManagedTest.java new file mode 100755 index 00000000000..f4228aa1f45 --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/ManagedTest.java @@ -0,0 +1,43 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011 + * + * The source code for this program is not published or otherwise divested of + * its trade secrets, irrespective of what has been deposited with the U.S. + * Copyright Office. + */ +package test.server.config; + +import java.util.Dictionary; + +import org.osgi.service.cm.ConfigurationException; +import org.osgi.service.cm.ManagedService; + +public abstract class ManagedTest extends Test implements ManagedService { + + public ManagedTest(String name) { + super(name); + } + + @Override + public String[] getServiceClasses() { + return new String[] { ManagedService.class.getName() }; + } + + @Override + public void updated(Dictionary properties) throws ConfigurationException { + try { + configurationUpdated(properties); + } catch (Throwable e) { + exception = e; + } finally { + latch.countDown(); + } + } + + public abstract void configurationUpdated(Dictionary properties) throws Exception; + +} diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/NestedConfigComplexElementTest.java b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/NestedConfigComplexElementTest.java new file mode 100755 index 00000000000..c6e485c1ef9 --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/NestedConfigComplexElementTest.java @@ -0,0 +1,111 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package test.server.config; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.Dictionary; +import java.util.HashMap; +import java.util.Map; + +import org.osgi.service.cm.Configuration; +import org.osgi.service.cm.ConfigurationAdmin; + +/** + * Test a complex config requirement that was requested from the security team + */ +public class NestedConfigComplexElementTest extends ManagedFactoryTest { + + private final ConfigurationAdmin configAdmin; + private final Map realms, ids, passwords, users; + private final String GROUP_ELEM = "group"; + private final String USER_ELEM = "user"; + private final String ID_ATTR = "id"; + private final String PASSWORD_ATTR = "password"; + private final String REALM_ATTR = "realm"; + + /** + * @param name + */ + public NestedConfigComplexElementTest(String name, ConfigurationAdmin configAdmin) { + super(name); + this.configAdmin = configAdmin; + realms = new HashMap(); + ids = new HashMap(); + passwords = new HashMap(); + users = new HashMap(); + init(); + } + + /** + * results data to compare against + */ + private void init() { + realms.put("SampleBasicRealm", null); + ids.put("admin", "SampleBasicRealm"); + ids.put("user1", "SampleBasicRealm"); + ids.put("user2", "SampleBasicRealm"); + ids.put("user3", "SampleBasicRealm"); + ids.put("memberlessGroup", "SampleBasicRealm"); + ids.put("adminGroup", "SampleBasicRealm"); + ids.put("users", "SampleBasicRealm"); + passwords.put("admin", "admin"); + passwords.put("user1", "user1"); + passwords.put("user2", "user2"); + passwords.put("user3", "user3"); + users.put("admin", "SampleBasicRealm"); + users.put("user1", "SampleBasicRealm"); + users.put("user2", "SampleBasicRealm"); + } + + /** {@inheritDoc} */ + @Override + public void configurationUpdated(String pid, Dictionary properties) throws Exception { + String name = (String) properties.get(REALM_ATTR); + assertTrue(realms.containsKey(name)); + String[] userArr = (String[]) properties.get(USER_ELEM); + assertNotNull(userArr); + assertEquals(4, userArr.length); + String[] groupArr = (String[]) properties.get(GROUP_ELEM); + assertNotNull(groupArr); + assertEquals(3, groupArr.length); + + for (int i = 0; i < userArr.length; i++) { + Configuration config = configAdmin.getConfiguration(userArr[i]); + Dictionary prop = config.getProperties(); + String id = (String) prop.get(ID_ATTR); + assertTrue(ids.containsKey(id)); + assertEquals(ids.get(id), name); + String password = (String) prop.get(PASSWORD_ATTR); + assertTrue(passwords.containsKey(password)); + assertEquals(passwords.get(password), id); + } + + for (int i = 0; i < groupArr.length; i++) { + Configuration config = configAdmin.getConfiguration(groupArr[i]); + Dictionary prop = config.getProperties(); + String id = (String) prop.get(ID_ATTR); + assertTrue(ids.containsKey(id)); + assertEquals(ids.get(id), name); + String[] userList = (String[]) prop.get(USER_ELEM); + if (userList != null) { + for (int j = 0; j < userList.length; j++) { + assertTrue(users.containsKey(userList[j])); + assertEquals(users.get(userList[j]), name); + } + } + } + + } +} diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/NestedConfigElementTest.java b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/NestedConfigElementTest.java new file mode 100755 index 00000000000..7d117125cd9 --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/NestedConfigElementTest.java @@ -0,0 +1,144 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package test.server.config; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.Dictionary; +import java.util.HashMap; +import java.util.Map; + +import org.osgi.service.cm.Configuration; +import org.osgi.service.cm.ConfigurationAdmin; + +import com.ibm.ws.config.xml.internal.XMLConfigConstants; + +/** + * + */ +public class NestedConfigElementTest extends ManagedFactoryTest { + + private final ConfigurationAdmin configAdmin; + private final Map apps, hostNames, ports; + + /** + * @param name + */ + public NestedConfigElementTest(String name, ConfigurationAdmin configAdmin) { + super(name); + this.configAdmin = configAdmin; + apps = new HashMap(); + hostNames = new HashMap(); + ports = new HashMap(); + init(); + } + + /** + * results data to compare against + */ + private void init() { + apps.put("fred", null); + apps.put("bob", null); + apps.put("app", null); + hostNames.put("w3.ibm.com", "fred"); + hostNames.put("w3.hursley.ibm.com", "fred"); + hostNames.put("butterfly.torolab.ibm.com", "bob"); + hostNames.put("mallet.torolab.ibm.com", "bob"); + hostNames.put("*", "app"); + hostNames.put("nonexistent", "app"); + ports.put("9084", "app"); + ports.put("9085", "app"); + ports.put("9080", "fred"); + ports.put("9081", "fred"); + ports.put("9082", "bob"); + ports.put("9083", "bob"); + } + + /** {@inheritDoc} */ + @Override + public void configurationUpdated(String pid, Dictionary properties) throws Exception { + String parentPID = (String) properties.get("service.pid"); + assertEquals("Expected top level pid", "test.config.nested.elements", properties.get("service.factoryPid")); + String[] virtualHosts = (String[]) properties.get("testVirtualHost"); + assertNotNull(virtualHosts); + assertEquals("There should be two virtual hosts", 2, virtualHosts.length); + String name = (String) properties.get("name"); + assertTrue(apps.containsKey(name)); + + if ("fred".equals(name)) { + String[] nestedSingleton = (String[]) properties.get("aNestedSingleton"); + Configuration singletonConfig = configAdmin.getConfiguration(nestedSingleton[0]); + assertEquals("Expected pid", "bundletwo.singleton", singletonConfig.getPid()); + Dictionary singletonProps = singletonConfig.getProperties(); + assertEquals("The config.parentPID value should be equal to the parent's service.pid value", parentPID, + singletonProps.get(XMLConfigConstants.CFG_PARENT_PID)); + assertEquals("The displayID should be application[fred]/aNestedSingleton", "application[fred]/aNestedSingleton", + singletonProps.get(XMLConfigConstants.CFG_CONFIG_INSTANCE_DISPLAY_ID)); + assertEquals(1, ((String[]) singletonProps.get("anArray")).length); + + String[] libraries = (String[]) properties.get("library"); + assertNotNull(libraries); + assertEquals(2, libraries.length); + + for (int i = 0; i < libraries.length; i++) { + Configuration config = configAdmin.getConfiguration(libraries[i]); + assertEquals("Expected factoryPid", "test.config.nested.bundletwo", config.getFactoryPid()); + Dictionary prop = config.getProperties(); + assertEquals("The config.parentPID value should be equal to the parent's service.pid value", parentPID, + prop.get(XMLConfigConstants.CFG_PARENT_PID)); + String aString = (String) prop.get("aString"); + String[] anArray = (String[]) prop.get("anArray"); + if ("defaultString".equals(aString)) { + assertEquals(4, anArray.length); + assertEquals("The displayID should be application[fred]/library[default-1]", "application[fred]/library[default-1]", + prop.get(XMLConfigConstants.CFG_CONFIG_INSTANCE_DISPLAY_ID)); + } else if ("notADefault".equals(aString)) { + assertEquals(3, anArray.length); + assertEquals("The displayID should be application[fred]/library[default-0]", "application[fred]/library[default-0]", + prop.get(XMLConfigConstants.CFG_CONFIG_INSTANCE_DISPLAY_ID)); + } else { + fail("Invalid value for attribute aString: " + aString); + } + + } + + for (int i = 0; i < virtualHosts.length; i++) { + Configuration config = configAdmin.getConfiguration(virtualHosts[i]); + assertEquals("Expected factoryPid", "test.config.nested.virtualHost", config.getFactoryPid()); + Dictionary prop = config.getProperties(); + assertEquals("The config.parentPID value should be equal to the parent's service.pid value", parentPID, + prop.get(XMLConfigConstants.CFG_PARENT_PID)); + String[] hostAliases = (String[]) prop.get("testHostAlias"); + assertEquals(1, hostAliases.length); + Configuration aliasConfig = configAdmin.getConfiguration(hostAliases[0]); + assertEquals("Expected factoryPid", "test.host.alias", aliasConfig.getFactoryPid()); + Dictionary aliasProps = aliasConfig.getProperties(); + String[] aliases = (String[]) aliasProps.get("names"); + assertEquals(2, aliases.length); + } + } + for (int i = 0; i < virtualHosts.length; i++) { + Configuration config = configAdmin.getConfiguration(virtualHosts[i]); + Dictionary prop = config.getProperties(); + String host = (String) prop.get("host"); + assertTrue(hostNames.containsKey(host)); + assertEquals(hostNames.get(host), name); + String port = String.valueOf(prop.get("port")); + assertTrue(ports.containsKey(port)); + assertEquals(ports.get(port), name); + } + + } +} diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/NestedResultTest.java b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/NestedResultTest.java new file mode 100755 index 00000000000..e147e32ad39 --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/NestedResultTest.java @@ -0,0 +1,45 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011 + * + * The source code for this program is not published or otherwise divested of + * its trade secrets, irrespective of what has been deposited with the U.S. + * Copyright Office. + */ +package test.server.config; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.util.Dictionary; +import java.util.Map; + +import org.osgi.service.cm.ConfigurationException; + +public class NestedResultTest extends ManagedFactoryTest { + + private Map> expectedProperties; + + public NestedResultTest(String name, int count) { + super(name, count); + } + + public void setExpectedProperties(Map> expectedProperties) { + this.expectedProperties = expectedProperties; + } + + @Override + public void configurationUpdated(String pid, Dictionary properties) throws ConfigurationException { + String name = (String) properties.get("name"); + + Map expectedProps = expectedProperties.get(name); + assertNotNull("Unexpected name: " + name, expectedProps); + for (Map.Entry entry : expectedProps.entrySet()) { + assertEquals("property " + entry.getKey() + " mismatch", entry.getValue(), properties.get(entry.getKey())); + } + } + +} diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/NestedSingletonTest.java b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/NestedSingletonTest.java new file mode 100755 index 00000000000..a5e8eab0354 --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/NestedSingletonTest.java @@ -0,0 +1,104 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011 + * + * The source code for this program is not published or otherwise divested of + * its trade secrets, irrespective of what has been deposited with the U.S. + * Copyright Office. + */ +package test.server.config; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.util.Dictionary; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Map; + +import org.osgi.service.cm.Configuration; +import org.osgi.service.cm.ConfigurationAdmin; +import org.osgi.service.cm.ManagedService; + +/** + * Test singleton pids + */ +public class NestedSingletonTest extends ManagedTest { + + private final ConfigurationAdmin configAdmin; + private final String nestedElement; + private Map> expectedProperties; + + public NestedSingletonTest(String name, String nestedElement, ConfigurationAdmin configAdmin) { + super(name); + this.configAdmin = configAdmin; + this.nestedElement = nestedElement; + } + + public void setExpectedProperties(Map> expectedProperties) { + this.expectedProperties = expectedProperties; + } + + public static Map> getExpectedProperties() { + Map map1 = new HashMap(); + map1.put("pass", "9999"); + map1.put("fail", "7777"); + + Map map2 = new HashMap(); + map2.put("pass", "100"); + map2.put("fail", "0"); + + Map> expectedProperties = new HashMap>(); + expectedProperties.put("one", map1); + expectedProperties.put("two", map2); + + return expectedProperties; + } + + public static Map> getMetatypeExpectedProperties() { + Map map1 = new HashMap(); + map1.put("pass", Integer.valueOf(9999)); + map1.put("fail", Integer.valueOf(7777)); + + Map map2 = new HashMap(); + map2.put("pass", Integer.valueOf(100)); + map2.put("fail", Integer.valueOf(0)); + + Map> expectedProperties = new Hashtable>(); + expectedProperties.put("one", map1); + expectedProperties.put("two", map2); + + return expectedProperties; + } + + @Override + public String[] getServiceClasses() { + return new String[] { ManagedService.class.getName() }; + } + + @Override + public void configurationUpdated(Dictionary properties) throws Exception { + assertEquals("singletonNested1", (properties.get("name"))); + + String[] testResults = (String[]) properties.get(nestedElement); + assertNotNull(testResults); + assertEquals(2, testResults.length); + + Map> expectedProperties = new HashMap>(this.expectedProperties); + for (int i = 0; i < testResults.length; i++) { + Configuration config = configAdmin.getConfiguration(testResults[i]); + Dictionary prop = config.getProperties(); + String innerName = (String) prop.get("name"); + Map expectedProps = expectedProperties.remove(innerName); + assertNotNull("Unexpected name: " + innerName, expectedProps); + for (Map.Entry entry : expectedProps.entrySet()) { + assertEquals("property " + entry.getKey() + " mismatch", entry.getValue(), prop.get(entry.getKey())); + } + } + + assertEquals(0, expectedProperties.size()); + } +} diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/PasswordTypeTest.java b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/PasswordTypeTest.java new file mode 100755 index 00000000000..62606d1c881 --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/PasswordTypeTest.java @@ -0,0 +1,83 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package test.server.config; + +import static org.junit.Assert.assertEquals; + +import java.util.Dictionary; + +import com.ibm.wsspi.kernel.service.utils.SerializableProtectedString; + +/** + * + */ +public class PasswordTypeTest extends ManagedFactoryTest { + + /** + * @param name + */ + public PasswordTypeTest(String name) { + super(name); + } + + /** {@inheritDoc} */ + @Override + public void configurationUpdated(String pid, Dictionary properties) throws Exception { + + String id = (String) properties.get("id"); + + if (id.equals("p1")) { + + // + assertEquals("p1.name", "admin", properties.get("name")); + SerializableProtectedString sps = (SerializableProtectedString) properties.get("password"); + assertEquals("p1.password", "secret,secret", new String(sps.getChars())); + + } else if (id.equals("p2")) { + + // + // Only substitution variables are path-normalized. p2 contains no substitution + // variables, therefore none of the attribute values are path-normalized. + + assertEquals("p2.name", "my//name/", properties.get("name")); + SerializableProtectedString sps = (SerializableProtectedString) properties.get("password"); + assertEquals("p2.password", "secret//secret/", new String(sps.getChars())); + + } else if (id.equals("p3")) { + + // + // p3.name=my//name/ + // p3.password=secret//secret/ + + // p3 contains substitution variables. Substitution variables are path-normalized for all + // attribute types EXCEPT ibm:type="password". This test ensures that the password attribute + // value is not path-normalized. + + // Path-normalization will... + // 1. convert sequences of "//" to just "/" + // 2. strip off any trailing "/" from the value. + + // NOTE: We are (at least temporarily) removing path normalization for variables, so the test below is + // changing to expect that "my//name/" will not be normalized. + assertEquals("p3.name", "my//name/", properties.get("name")); + + // "secret//secret/" ==> "secret//secret/" (no normalization) + SerializableProtectedString sps = (SerializableProtectedString) properties.get("password"); + assertEquals("p2.password", "secret//secret/", new String(sps.getChars())); + + } else { + throw new RuntimeException("Invalid test.config.password instance id: " + id); + } + + } + +} diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/SharedAliasTest.java b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/SharedAliasTest.java new file mode 100755 index 00000000000..565e14bd20f --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/SharedAliasTest.java @@ -0,0 +1,39 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011 + * + * The source code for this program is not published or otherwise divested of + * its trade secrets, irrespective of what has been deposited with the U.S. + * Copyright Office. + */ +package test.server.config; + +import static org.junit.Assert.assertEquals; + +import java.util.Dictionary; + +import org.osgi.service.cm.ConfigurationException; + +public class SharedAliasTest extends ManagedTest { + + private final String firstName; + private final String lastName; + + public SharedAliasTest(String name, String firstName, String lastName) { + super(name); + this.firstName = firstName; + this.lastName = lastName; + } + + @Override + public void configurationUpdated(Dictionary properties) throws ConfigurationException { + assertEquals("kids", "5", properties.get("kids")); + assertEquals("lastName", lastName, properties.get("lastName")); + assertEquals("firstName", firstName, properties.get("firstName")); + assertEquals("fullName", firstName + " " + lastName, properties.get("fullName")); + } + +} diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/SingletonAliasTest.java b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/SingletonAliasTest.java new file mode 100755 index 00000000000..c400a17442a --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/SingletonAliasTest.java @@ -0,0 +1,35 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011 + * + * The source code for this program is not published or otherwise divested of + * its trade secrets, irrespective of what has been deposited with the U.S. + * Copyright Office. + */ +package test.server.config; + +import static org.junit.Assert.assertEquals; + +import java.util.Dictionary; + +import org.osgi.service.cm.ConfigurationException; + +public class SingletonAliasTest extends ManagedTest { + + public SingletonAliasTest(String name) { + super(name); + } + + @Override + public void configurationUpdated(Dictionary properties) throws ConfigurationException { + assertEquals("kids", new Integer(2), properties.get("kids")); + assertEquals("lastName", "Smith", properties.get("lastName")); + assertEquals("firstName", "Stan", properties.get("firstName")); + assertEquals("fullName", "Stan Smith", properties.get("fullName")); + assertEquals("others", "Roger Smith, Klaus Smith", properties.get("others")); + } + +} diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/SingletonMetaTypeTest.java b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/SingletonMetaTypeTest.java new file mode 100755 index 00000000000..c3bf255ee7f --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/SingletonMetaTypeTest.java @@ -0,0 +1,40 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011 + * + * The source code for this program is not published or otherwise divested of + * its trade secrets, irrespective of what has been deposited with the U.S. + * Copyright Office. + */ +package test.server.config; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; + +import java.util.Arrays; +import java.util.Dictionary; +import java.util.Vector; + +import org.osgi.service.cm.ConfigurationException; + +public class SingletonMetaTypeTest extends ManagedTest { + + public SingletonMetaTypeTest(String name) { + super(name); + } + + @Override + public void configurationUpdated(Dictionary properties) throws ConfigurationException { + // all picked up directly from metatype + assertEquals("present", Boolean.TRUE, properties.get("present")); + assertArrayEquals("int array", new int[] { 1, 2, 3 }, (int[]) properties.get("intColl")); + assertEquals("long vector", new Vector(Arrays.asList(4l, 5l, 6l, 7l)), properties.get("longColl")); + + assertEquals("lastname", "Simpson", properties.get("lastname")); + assertEquals("spouse", "Marge Simpson", properties.get("spouse")); + } + +} diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/SingletonServerMetaTypeTest.java b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/SingletonServerMetaTypeTest.java new file mode 100755 index 00000000000..726c6c4b9ed --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/SingletonServerMetaTypeTest.java @@ -0,0 +1,44 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011 + * + * The source code for this program is not published or otherwise divested of + * its trade secrets, irrespective of what has been deposited with the U.S. + * Copyright Office. + */ +package test.server.config; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; + +import java.util.Arrays; +import java.util.Dictionary; +import java.util.Vector; + +import org.osgi.service.cm.ConfigurationException; + +public class SingletonServerMetaTypeTest extends ManagedTest { + + public SingletonServerMetaTypeTest(String name) { + super(name); + } + + @Override + public void configurationUpdated(Dictionary properties) throws ConfigurationException { + // picked up directly from metatype + assertEquals("present", Boolean.TRUE, properties.get("present")); + assertArrayEquals("int array", new int[] { 1, 2, 3 }, (int[]) properties.get("intColl")); + assertEquals("long vector", new Vector(Arrays.asList(4l, 5l, 6l, 7l)), properties.get("longColl")); + + // from metatype + assertEquals("lastname", "Doe", properties.get("lastname")); + assertEquals("spouse", "Marge Doe", properties.get("spouse")); + + // from server config + assertArrayEquals("children", new String[] { "Jon Doe", "Jane Doe" }, (String[]) properties.get("children")); + } + +} diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/SingletonServerTest.java b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/SingletonServerTest.java new file mode 100755 index 00000000000..549e622ce1a --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/SingletonServerTest.java @@ -0,0 +1,33 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011 + * + * The source code for this program is not published or otherwise divested of + * its trade secrets, irrespective of what has been deposited with the U.S. + * Copyright Office. + */ +package test.server.config; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; + +import java.util.Dictionary; + +import org.osgi.service.cm.ConfigurationException; + +public class SingletonServerTest extends ManagedTest { + + public SingletonServerTest(String name) { + super(name); + } + + @Override + public void configurationUpdated(Dictionary properties) throws ConfigurationException { + assertEquals("simple attr", "abc", properties.get("simpleAttr")); + assertArrayEquals("collection attr", new String[] { "a", "b", "c" }, (String[]) properties.get("collAttr")); + } + +} diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/Test.java b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/Test.java new file mode 100755 index 00000000000..c69c0fe48be --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/Test.java @@ -0,0 +1,44 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011 + * + * The source code for this program is not published or otherwise divested of + * its trade secrets, irrespective of what has been deposited with the U.S. + * Copyright Office. + */ +package test.server.config; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import test.server.BaseTest; + +public abstract class Test extends BaseTest { + + protected CountDownLatch latch; + protected Throwable exception; + + public Test(String name) { + this(name, 1); + } + + public Test(String name, int count) { + super(name); + this.latch = new CountDownLatch(count); + } + + public Throwable getException() { + try { + if (!latch.await(10, TimeUnit.SECONDS)) { + return new RuntimeException("Timed out"); + } + } catch (InterruptedException e) { + return new RuntimeException("Interrupted"); + } + return exception; + } + +} diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/TestRunner.java b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/TestRunner.java new file mode 100755 index 00000000000..e889b18a9c1 --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/TestRunner.java @@ -0,0 +1,119 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011 + * + * The source code for this program is not published or otherwise divested of + * its trade secrets, irrespective of what has been deposited with the U.S. + * Copyright Office. + */ +package test.server.config; + +import java.io.IOException; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Hashtable; +import java.util.List; + +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.osgi.framework.BundleContext; +import org.osgi.framework.Constants; +import org.osgi.framework.ServiceReference; +import org.osgi.service.cm.ConfigurationAdmin; +import org.osgi.service.component.ComponentContext; + +import test.server.BaseHttpTest; + +public class TestRunner extends BaseHttpTest { + + private BundleContext bundleContext; + private final List tests = new ArrayList(); + + @Override + protected void activate(ComponentContext componentContext) throws Exception { + super.activate(componentContext); + + bundleContext = componentContext.getBundleContext(); + ServiceReference ref = bundleContext.getServiceReference(ConfigurationAdmin.class.getName()); + ConfigurationAdmin configAdmin = (ConfigurationAdmin) bundleContext.getService(ref); + + addTest(new SingletonServerTest("test.config.singleton.server")); + addTest(new SingletonServerMetaTypeTest("test.config.singleton.server.metatype")); + addTest(new SingletonMetaTypeTest("test.config.singleton.metatype")); + + addTest(new FactorySimpleTest("test.config.factory.simple", 1)); + addTest(new FactoryMetaTypeTest("test.config.factory.metatype")); + + addTest(new VariableTest("test.config.variable")); + + addTest(new SingletonAliasTest("test.config.singleton.alias")); + addTest(new FactoryAliasTest("test.config.factory.alias", 2)); + + addTest(new SharedAliasTest("test.config.simpsons.alias", "Homer", "Simpson")); + addTest(new SharedAliasTest("test.config.griffins.alias", "Peter", "Griffin")); + + addTest(new NestedConfigElementTest("test.config.nested.elements", configAdmin)); + addTest(new NestedConfigComplexElementTest("test.config.complex.nested.elements", configAdmin)); + + addTest(new PasswordTypeTest("test.config.password")); + + addTest(new FinalTypeTest("test.config.final")); + + NestedSingletonTest nestedSingletonTest = new NestedSingletonTest("test.config.nested.managed", "test.config.nested.result", configAdmin); + nestedSingletonTest.setExpectedProperties(NestedSingletonTest.getExpectedProperties()); + addTest(nestedSingletonTest); + + NestedResultTest nestedResultTest = new NestedResultTest("test.config.nested.result.metatype", 2); + nestedResultTest.setExpectedProperties(NestedSingletonTest.getMetatypeExpectedProperties()); + + addTest(nestedResultTest); + + tests.add(new ConfigurationAdminTest("test.config.configAdmin", configAdmin)); + + addTest(new ConfigurationPluginTest("test.config.plugin")); + + registerServlet("/parser-test", new TestVerifierServlet(), null, null); + + System.out.println("Parser test servlet started"); + } + + private void addTest(Test test) { + Hashtable properties = new Hashtable(); + properties.put(Constants.SERVICE_PID, test.getName()); + tests.add(test); + bundleContext.registerService(test.getServiceClasses(), test, properties); + } + + class TestVerifierServlet extends HttpServlet { + private static final long serialVersionUID = 1L; + + @Override + public void doGet(HttpServletRequest rq, HttpServletResponse rsp) throws IOException { + int failedCount = 0; + boolean failed = false; + for (Test test : tests) { + Throwable t = test.getException(); + if (t != null) { + failed = true; + System.out.println("Test " + test.getName() + " failed:"); + t.printStackTrace(); + failedCount++; + } + } + PrintWriter pw = rsp.getWriter(); + rsp.setContentType("text/plain"); + if (failed) { + pw.println(failedCount + " of " + tests.size() + " tests " + "FAILED, check messages.log for information"); + } else { + pw.println("OK"); + } + } + + } + +} diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/VariableTest.java b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/VariableTest.java new file mode 100755 index 00000000000..a53cc62a741 --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/VariableTest.java @@ -0,0 +1,37 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011 + * + * The source code for this program is not published or otherwise divested of + * its trade secrets, irrespective of what has been deposited with the U.S. + * Copyright Office. + */ +package test.server.config; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; + +import java.util.Dictionary; + +import org.osgi.service.cm.ConfigurationException; + +public class VariableTest extends ManagedTest { + + public VariableTest(String name) { + super(name); + } + + @Override + public void configurationUpdated(Dictionary properties) throws ConfigurationException { + assertEquals("lastname", "Potter", properties.get("lastname")); + assertEquals("name", "Harry Potter", properties.get("name")); + assertArrayEquals("names", new String[] { "Lisa Griffin", "Lois Griffin" }, (String[]) properties.get("names")); + assertEquals("testVariable should be the variable defined in bootstrap", "variableFromBootstrap", properties.get("testVariable")); + assertEquals("testVarNotExist should use the default from the metatype", "defaultFromMetaType", properties.get("testVarNotExist")); + assertEquals("testToken should use the default from the metatype", "default value", properties.get("testToken")); + } + +} diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/defaults/TestRunner.java b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/defaults/TestRunner.java new file mode 100755 index 00000000000..14acf46a664 --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/defaults/TestRunner.java @@ -0,0 +1,106 @@ +/* +IBM Confidential + * +OCO Source Materials + * +Copyright IBM Corp. 2011 + * +The source code for this program is not published or otherwise divested of +its trade secrets, irrespective of what has been deposited with the U.S. +Copyright Office. + */ +package test.server.config.defaults; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import java.util.Dictionary; + +import org.osgi.service.component.ComponentContext; + +import test.server.BaseTestRunner; +import test.server.config.dynamic.ConfigWriter; +import test.server.config.dynamic.FactoryTest; +import test.server.config.dynamic.SingletonTest; + +import com.ibm.ws.config.xml.internal.XMLConfigConstants; + +public class TestRunner extends BaseTestRunner { + + @Override + protected void activate(ComponentContext context) throws Exception { + super.activate(context); + registerServlet("/default-config-test", new TestDynamicConfigServlet(), null, null); + } + + public void testDefaultConfigSingleton() throws Exception { + SingletonTest parent = new SingletonTest("test.config.default.singleton"); + addTest(parent); + + Dictionary dictionary; + + // wait for the initial configuration to be injected. + dictionary = parent.waitForUpdate(); + assertEquals("port", Integer.valueOf(5678), dictionary.get("port")); + assertArrayEquals("hostname", new String[] { "192.168.1.1", "192.168.1.2" }, (String[]) dictionary.get("hostname")); + + ConfigWriter writer; + + // STEP 1: update singleton to disable default configuration + writer = readConfiguration(); + writer.setValue("defaultSingleton", null, XMLConfigConstants.CONFIG_ENABLED_ATTRIBUTE, "false"); + writeConfiguration(writer); + + // wait for deleted configuration + dictionary = parent.waitForUpdate(); + assertNull(dictionary); + + // STEP 2: update singleton to enable default configuration + writer = readConfiguration(); + writer.setValue("defaultSingleton", null, XMLConfigConstants.CONFIG_ENABLED_ATTRIBUTE, "true"); + writeConfiguration(writer); + + // wait for updated configuration + dictionary = parent.waitForUpdate(); + assertEquals("port", Integer.valueOf(5678), dictionary.get("port")); + assertArrayEquals("hostname", new String[] { "192.168.1.1", "192.168.1.2" }, (String[]) dictionary.get("hostname")); + } + + public void testDefaultConfigFactory() throws Exception { + + FactoryTest parent = new FactoryTest("test.config.default.factory"); + addTest(parent); + + // wait for the initial configurations to be injected. + Dictionary oneDictionary = parent.waitForUpdate("one"); + assertEquals("port", Integer.valueOf(1234), oneDictionary.get("port")); + assertArrayEquals("hostname", new String[] { "192.168.1.1", "192.168.1.2" }, (String[]) oneDictionary.get("hostname")); + + Dictionary twoDictionary = parent.waitForUpdate("two"); + assertEquals("port", Integer.valueOf(9999), twoDictionary.get("port")); + assertArrayEquals("hostname", new String[] { "localhost", "ibm.com" }, (String[]) twoDictionary.get("hostname")); + + ConfigWriter writer; + + // STEP 1: update instance two to disable default configuration + writer = readConfiguration(); + writer.setValue("defaultFactory", "two", XMLConfigConstants.CONFIG_ENABLED_ATTRIBUTE, "false"); + writeConfiguration(writer); + + // wait for instance two delete + twoDictionary = parent.waitForUpdate("two"); + assertNull(twoDictionary); + + // STEP 2: update instance two to enable default configuration + writer = readConfiguration(); + writer.setValue("defaultFactory", "two", XMLConfigConstants.CONFIG_ENABLED_ATTRIBUTE, "true"); + writeConfiguration(writer); + + // wait for instance two update + twoDictionary = parent.waitForUpdate("two"); + assertEquals("port", Integer.valueOf(9999), twoDictionary.get("port")); + assertArrayEquals("hostname", new String[] { "localhost", "ibm.com" }, (String[]) twoDictionary.get("hostname")); + } + +} diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/dynamic/ConfigWriter.java b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/dynamic/ConfigWriter.java new file mode 100755 index 00000000000..009e72beb1e --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/dynamic/ConfigWriter.java @@ -0,0 +1,182 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011 + * + * The source code for this program is not published or otherwise divested of + * its trade secrets, irrespective of what has been deposited with the U.S. + * Copyright Office. + */ +package test.server.config.dynamic; + +import java.io.File; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.StringReader; +import java.io.Writer; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.List; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Result; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; + +public class ConfigWriter { + + private static DocumentBuilderFactory DOM_FACTORY = DocumentBuilderFactory.newInstance(); + + private final Document document; + + public ConfigWriter() throws Exception { + DocumentBuilder builder = DOM_FACTORY.newDocumentBuilder(); + document = builder.newDocument(); + document.appendChild(document.createElement("server")); + } + + public ConfigWriter(InputStream in) throws Exception { + DocumentBuilder builder = DOM_FACTORY.newDocumentBuilder(); + document = builder.parse(in); + } + + private static boolean matches(Node node, String nodeName, String id, String idAttribute) { + if (node instanceof Element && nodeName.equals(node.getNodeName())) { + if (id == null) { + return true; + } else { + Element element = (Element) node; + return id.equals(element.getAttribute(idAttribute)); + } + } + return false; + } + + private Element getConfigNode(String nodeName, String id, String idAttribute) { + Element root = document.getDocumentElement(); + NodeList children = root.getChildNodes(); + for (int i = 0; i < children.getLength(); i++) { + Node child = children.item(i); + if (matches(child, nodeName, id, idAttribute)) { + return (Element) child; + } + } + return null; + } + + private List getConfigNodes(String nodeName, String id, String idAttribute) { + Element root = document.getDocumentElement(); + NodeList children = root.getChildNodes(); + List nodes = new ArrayList(); + for (int i = 0; i < children.getLength(); i++) { + Node child = children.item(i); + if (matches(child, nodeName, id, idAttribute)) { + nodes.add((Element) child); + } + } + return nodes; + } + + public boolean deleteConfig(String nodeName, String id, boolean allInstances) { + return deleteConfig(nodeName, id, "id", allInstances); + } + + public boolean deleteConfig(String nodeName, String id, String idAttribute, boolean allInstances) { + boolean didSomething = false; + Element root = document.getDocumentElement(); + if (allInstances) { + List toRemove = getConfigNodes(nodeName, id, idAttribute); + for (Node node : toRemove) { + root.removeChild(node); + didSomething = true; + } + } else { + Node node = getConfigNode(nodeName, id, idAttribute); + if (node != null) { + root.removeChild(node); + didSomething = true; + } + } + return didSomething; + } + + public void addConfig(String element) throws Exception { + DocumentBuilder builder = DOM_FACTORY.newDocumentBuilder(); + Document doc = builder.parse(new InputSource(new StringReader(element))); + addConfig(doc.getDocumentElement()); + } + + public void addConfig(String pattern, Object... args) throws Exception { + addConfig(MessageFormat.format(pattern, args)); + } + + public void addConfig(Element element) { + Node node = document.importNode(element, true); + Element root = document.getDocumentElement(); + root.appendChild(node); + } + + public boolean setValue(String nodeName, String id, String propertyName, String value) { + return setValue(nodeName, id, "id", propertyName, value); + } + + public boolean setValue(String nodeName, String id, String idAttribute, String propertyName, String value) { + Element element = getConfigNode(nodeName, id, idAttribute); + if (element != null) { + element.setAttribute(propertyName, value); + return true; + } else { + return false; + } + } + + public boolean removeProperty(String nodeName, String id, String propertyName) { + return removeProperty(nodeName, id, "id", propertyName); + } + + public boolean removeProperty(String nodeName, String id, String idAttribute, String propertyName) { + Element element = getConfigNode(nodeName, id, idAttribute); + if (element != null) { + // TODO: check for subelement with this name + return (element.getAttributes().removeNamedItem(propertyName) != null); + } else { + return false; + } + } + + public void write(File file) throws Exception { + write(new StreamResult(file)); + } + + public void write(OutputStream out) throws Exception { + write(new StreamResult(out)); + } + + public void write(Writer writer) throws Exception { + write(new StreamResult(writer)); + } + + private void write(Result result) throws Exception { + TransformerFactory tf = TransformerFactory.newInstance(); + Transformer transformer = tf.newTransformer(); + //transformer.setOutputProperty (OutputKeys.OMIT_XML_DECLARATION, "yes"); + transformer.setOutputProperty(OutputKeys.METHOD, "xml"); + transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); + transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4"); + + transformer.transform(new DOMSource(document), result); + } +} diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/dynamic/FactoryNestedTest.java b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/dynamic/FactoryNestedTest.java new file mode 100755 index 00000000000..c89a8be5495 --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/dynamic/FactoryNestedTest.java @@ -0,0 +1,85 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011 + * + * The source code for this program is not published or otherwise divested of + * its trade secrets, irrespective of what has been deposited with the U.S. + * Copyright Office. + */ +package test.server.config.dynamic; + +import java.util.ArrayList; +import java.util.Dictionary; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.osgi.service.cm.ConfigurationException; +import org.osgi.service.cm.ManagedServiceFactory; + +import test.server.BaseTest; + +public class FactoryNestedTest extends BaseTest implements ManagedServiceFactory { + + private final Map> dictionaries; + + public FactoryNestedTest(String name) { + super(name); + dictionaries = new HashMap>(); + } + + @Override + public String[] getServiceClasses() { + return new String[] { ManagedServiceFactory.class.getName() }; + } + + @Override + public void updated(String pid, Dictionary properties) throws ConfigurationException { + notify(pid, properties); + } + + @Override + public void deleted(String pid) { + notify(pid, null); + } + + private void notify(String id, Dictionary properties) { + List list = getDictionaries(id); + synchronized (list) { + list.add(properties); + list.notifyAll(); + } + } + + private List getDictionaries(String pid) { + synchronized (dictionaries) { + List updates = dictionaries.get(pid); + if (updates == null) { + updates = new ArrayList(); + dictionaries.put(pid, updates); + } + return updates; + } + } + + public Dictionary waitForUpdate(String pid) { + List list = getDictionaries(pid); + synchronized (list) { + while (list.isEmpty()) { + try { + list.wait(TIMEOUT); + } catch (InterruptedException e) { + throw new RuntimeException("Interrupted"); + } + if (list.isEmpty()) { + throw new RuntimeException("Timed out: " + pid); + } + } + return list.remove(0); + } + } + +} diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/dynamic/FactoryTest.java b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/dynamic/FactoryTest.java new file mode 100755 index 00000000000..d17d4070bf1 --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/dynamic/FactoryTest.java @@ -0,0 +1,141 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011 + * + * The source code for this program is not published or otherwise divested of + * its trade secrets, irrespective of what has been deposited with the U.S. + * Copyright Office. + */ +package test.server.config.dynamic; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Dictionary; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.osgi.service.cm.ConfigurationException; +import org.osgi.service.cm.ManagedServiceFactory; + +import test.server.BaseTest; + +public class FactoryTest extends BaseTest implements ManagedServiceFactory { + + private final Map pid2IdMapping; + private final Map id2PidMapping; + private final Map>> dictionaries; + private final String idAttribute; + + public FactoryTest(String name) { + this(name, "id"); + } + + public FactoryTest(String name, String idAttribute) { + super(name); + this.dictionaries = new HashMap>>(); + this.pid2IdMapping = Collections.synchronizedMap(new HashMap()); + this.id2PidMapping = Collections.synchronizedMap(new HashMap()); + this.idAttribute = idAttribute; + } + + public void reset() { + synchronized (dictionaries) { + dictionaries.clear(); + } + } + + @Override + public String[] getServiceClasses() { + return new String[] { ManagedServiceFactory.class.getName() }; + } + + @SuppressWarnings("unchecked") + @Override + public void updated(String pid, @SuppressWarnings("rawtypes") Dictionary properties) throws ConfigurationException { + String id = (String) properties.get(idAttribute); + pid2IdMapping.put(pid, id); + id2PidMapping.put(id, pid); + notify(id, properties); + } + + @Override + public void deleted(String pid) { + String id = pid2IdMapping.get(pid); + notify(id, null); + } + + public String getPid(String id) { + return id2PidMapping.get(id); + } + + public Set getPids() { + return pid2IdMapping.keySet(); + } + + private void notify(String id, Dictionary properties) { + List> list = getDictionaries(id); + synchronized (list) { + list.add(properties); + list.notifyAll(); + } + } + + private List> getDictionaries(String id) { + synchronized (dictionaries) { + List> updates = dictionaries.get(id); + if (updates == null) { + updates = new ArrayList>(); + dictionaries.put(id, updates); + } + return updates; + } + } + + public Dictionary waitForUpdate(String id) { + return waitForUpdate(id, TIMEOUT); + } + + /** + * @param string + * @param i + * @return + */ + public Dictionary waitForUpdate(String id, long timeToWait) { + List> list = getDictionaries(id); + synchronized (list) { + while (list.isEmpty()) { + try { + list.wait(timeToWait); + } catch (InterruptedException e) { + throw new RuntimeException("Interrupted"); + } + if (list.isEmpty()) { + throw new RuntimeException("Timed out"); + } + } + return list.remove(0); + } + } + + /** + * @param string + * @return + */ + public boolean hasDictionary(String id) { + List> list = getDictionaries(id); + synchronized (list) { + try { + list.wait(5000); + } catch (InterruptedException e) { + //Ignore, we're just waiting five seconds to make this method more accurate + } + return !list.isEmpty(); + } + } + +} diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/dynamic/SingletonTest.java b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/dynamic/SingletonTest.java new file mode 100755 index 00000000000..710a09c40c8 --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/dynamic/SingletonTest.java @@ -0,0 +1,81 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011 + * + * The source code for this program is not published or otherwise divested of + * its trade secrets, irrespective of what has been deposited with the U.S. + * Copyright Office. + */ +package test.server.config.dynamic; + +import java.util.ArrayList; +import java.util.Dictionary; +import java.util.List; +import java.util.logging.Logger; + +import org.osgi.service.cm.ConfigurationException; +import org.osgi.service.cm.ManagedService; + +import test.server.BaseTest; + +public class SingletonTest extends BaseTest implements ManagedService { + private final static String CLASS_NAME = SingletonTest.class.getName(); + private final static Logger LOGGER = Logger.getLogger(CLASS_NAME); + + private final List dictionaries; + + public SingletonTest(String name) { + super(name); + dictionaries = new ArrayList(); + } + + @Override + public String[] getServiceClasses() { + return new String[] { ManagedService.class.getName() }; + } + + @Override + public void updated(Dictionary properties) throws ConfigurationException { + synchronized (dictionaries) { + LOGGER.finest("updated - " + properties); + dictionaries.add(properties); + dictionaries.notifyAll(); + } + } + + public Dictionary waitForUpdate() { + LOGGER.entering(CLASS_NAME, "waitForUpdate"); + synchronized (dictionaries) { + while (dictionaries.isEmpty()) { + try { + LOGGER.finest("waitForUpdate - waiting"); + dictionaries.wait(TIMEOUT); + } catch (InterruptedException e) { + LOGGER.finest("waitForUpdate - interrupted"); + throw new RuntimeException("Interrupted"); + } + if (dictionaries.isEmpty()) { + LOGGER.finest("waitForUpdate - timed out"); + throw new RuntimeException("Timed out"); + } + } + Dictionary d = dictionaries.remove(0); + LOGGER.exiting(CLASS_NAME, "waitForUpdate", d); + return d; + } + } + + /** + * + */ + public void reset() { + synchronized (dictionaries) { + dictionaries.clear(); + } + + } + +} diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/dynamic/TestRunner.java b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/dynamic/TestRunner.java new file mode 100755 index 00000000000..7dec335997d --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/dynamic/TestRunner.java @@ -0,0 +1,300 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011 + * + * The source code for this program is not published or otherwise divested of + * its trade secrets, irrespective of what has been deposited with the U.S. + * Copyright Office. + */ +package test.server.config.dynamic; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import java.util.Dictionary; + +import org.osgi.service.component.ComponentContext; + +import test.server.BaseTestRunner; + +public class TestRunner extends BaseTestRunner { + + @Override + protected void activate(ComponentContext context) throws Exception { + super.activate(context); + registerServlet("/dynamic-config-test", new TestDynamicConfigServlet(), null, null); + } + + public void testSingleton() throws Exception { + Dictionary dictionary; + ConfigWriter writer; + + SingletonTest singletonTest = new SingletonTest("test.config.dynamic.singleton"); + addTest(singletonTest); + + // step 1. wait for the initial configuration to be injected. + dictionary = singletonTest.waitForUpdate(); + assertEquals("testValue", "10", dictionary.get("testValue")); + + // step 2a. modify the configuration + writer = readConfiguration(); + writer.setValue("test.config.dynamic.singleton", null, "testValue", "15"); + writeConfiguration(writer); + // step 2b: wait for update + dictionary = singletonTest.waitForUpdate(); + assertEquals("testValue", "15", dictionary.get("testValue")); + + // step 3a. delete configuration + writer = readConfiguration(); + writer.deleteConfig("test.config.dynamic.singleton", null, false); + writeConfiguration(writer); + // step 3b. wait for update + dictionary = singletonTest.waitForUpdate(); + assertEquals("Test deleted", null, dictionary); + + // step 4a. add configuration back in + writer = readConfiguration(); + writer.addConfig(""); + writeConfiguration(writer); + // step 4b. wait for update + dictionary = singletonTest.waitForUpdate(); + assertEquals("Test added", "hello", dictionary.get("message")); + } + + public void testFactory() throws Exception { + Dictionary dictionary; + ConfigWriter writer; + + FactoryTest factoryTest = new FactoryTest("test.config.dynamic.factory"); + addTest(factoryTest); + + // step 1. wait for the initial configuration to be injected. + dictionary = factoryTest.waitForUpdate("1"); + assertEquals("instance 1 testValue", "10", dictionary.get("testValue")); + + // step 2a. modify instance 1 configuration & add instance 2 configuration + writer = readConfiguration(); + writer.setValue("test.config.dynamic.factory", "1", "testValue", "15"); + writer.addConfig(""); + writeConfiguration(writer); + // step 2b: wait for updates + dictionary = factoryTest.waitForUpdate("1"); + assertEquals("instance 1 testValue", "15", dictionary.get("testValue")); + dictionary = factoryTest.waitForUpdate("2"); + assertEquals("instance 2 message", "bye", dictionary.get("message")); + + // step 3a. delete instance 1 configuration & modify instance 2 configuration + writer = readConfiguration(); + writer.deleteConfig("test.config.dynamic.factory", "1", false); + writer.setValue("test.config.dynamic.factory", "2", "message", "what's up"); + writeConfiguration(writer); + // step 3b. wait for updates + dictionary = factoryTest.waitForUpdate("1"); + assertEquals("instance 1 deleted", null, dictionary); + dictionary = factoryTest.waitForUpdate("2"); + assertEquals("instance 2 message", "what's up", dictionary.get("message")); + + // step 4a. add instance 1 configuration back in & delete instance 2 + writer = readConfiguration(); + writer.addConfig(""); + writer.deleteConfig("test.config.dynamic.factory", "2", false); + writeConfiguration(writer); + // step 4b. wait for updates + dictionary = factoryTest.waitForUpdate("1"); + assertEquals("instance 1 added", "hello", dictionary.get("message")); + dictionary = factoryTest.waitForUpdate("2"); + assertEquals("instance 2 deleted", null, dictionary); + } + + public void testSingletonMetatype() throws Exception { + Dictionary dictionary; + ConfigWriter writer; + + SingletonTest singletonMetatypeTest = new SingletonTest("test.config.dynamic.singleton.metatype"); + addTest(singletonMetatypeTest); + + // step 1. wait for the initial configuration to be injected. + // This singleton was not configured in server.xml -- It's created because all of its required + // fields have defaults + dictionary = singletonMetatypeTest.waitForUpdate(); + // Make sure auto-added singletons use the alias for the display id + assertEquals("singletonMetatype", dictionary.get("config.displayId")); + + // step 2a. modify the configuration using an alias + writer = readConfiguration(); + writer.addConfig(""); + writeConfiguration(writer); + // step 2b: wait for update + dictionary = singletonMetatypeTest.waitForUpdate(); + assertEquals("version", "2.0", dictionary.get("version")); + assertEquals("threads", new Integer(100), dictionary.get("threads")); + + // step 3a. delete configuration using an alias + writer = readConfiguration(); + writer.deleteConfig("singletonMetatype", null, false); + writeConfiguration(writer); + // step 3b. wait for update - defaults should be injected + dictionary = singletonMetatypeTest.waitForUpdate(); + assertEquals("version", "1.0", dictionary.get("version")); + assertEquals("threads", new Integer(100), dictionary.get("threads")); + + // step 4a. add configuration back in + writer = readConfiguration(); + writer.addConfig(""); + writeConfiguration(writer); + // step 4b. wait for update + dictionary = singletonMetatypeTest.waitForUpdate(); + assertEquals("version", "1.0", dictionary.get("version")); + assertEquals("threads", new Integer(500), dictionary.get("threads")); + } + + public void testFactoryMetatype() throws Exception { + Dictionary dictionary; + ConfigWriter writer; + + FactoryTest factoryTest = new FactoryTest("test.config.dynamic.factory.metatype"); + addTest(factoryTest); + + // step 1. wait for the initial configuration to be injected. + dictionary = factoryTest.waitForUpdate("one"); + + // step 2a. modify instance 1 configuration & add instance 2 configuration + // The timeout value is of type duration(s), so the value is in seconds instead of milliseconds + writer = readConfiguration(); + writer.setValue("test.config.dynamic.factory.metatype", "one", "timeout", "123m"); + writer.addConfig(""); + writeConfiguration(writer); + // step 2b: wait for updates + dictionary = factoryTest.waitForUpdate("one"); + assertEquals("instance one timeout", new Long(123 * 60), dictionary.get("timeout")); + assertEquals("instance one minSize", new Integer(10), dictionary.get("minSize")); + dictionary = factoryTest.waitForUpdate("two"); + assertEquals("instance two timeout", new Long(100), dictionary.get("timeout")); + assertEquals("instance two minSize", new Integer(456), dictionary.get("minSize")); + + // step 3a. delete instance 1 configuration & modify instance 2 configuration + writer = readConfiguration(); + writer.deleteConfig("test.config.dynamic.factory.metatype", "one", false); + writer.setValue("factoryMetatype", "two", "timeout", "7890ms"); + writeConfiguration(writer); + // step 3b. wait for updates + dictionary = factoryTest.waitForUpdate("one"); + assertEquals("instance one deleted", null, dictionary); + dictionary = factoryTest.waitForUpdate("two"); + assertEquals("instance two timeout", new Long(7), dictionary.get("timeout")); + assertEquals("instance two minSize", new Integer(456), dictionary.get("minSize")); + + // step 4a. add instance 1 configuration back in & delete instance 2 + writer = readConfiguration(); + writer.addConfig(""); + writer.deleteConfig("factoryMetatype", "two", false); + writeConfiguration(writer); + // step 4b. wait for updates + dictionary = factoryTest.waitForUpdate("one"); + assertEquals("instance one timeout", new Long(100), dictionary.get("timeout")); + assertEquals("instance one minSize", new Integer(91011), dictionary.get("minSize")); + dictionary = factoryTest.waitForUpdate("two"); + assertEquals("instance 2 deleted", null, dictionary); + } + + public void testFactoryOptionalId() throws Exception { + Dictionary dictionary; + ConfigWriter writer; + + String idAttribute = "name"; + + FactoryTest factoryTest = new FactoryTest("test.config.dynamic.factory.optional.metatype", idAttribute); + addTest(factoryTest); + + // step 1a. wait for initial configuration of first instance + dictionary = factoryTest.waitForUpdate("one"); + assertEquals("instance one timeout", new Long(100), dictionary.get("timeout")); + assertEquals("instance one minSize", new Integer(10), dictionary.get("minSize")); + assertNull(dictionary.get("id")); + + // step 1b. wait for initial configuration of second instance + dictionary = factoryTest.waitForUpdate("four"); + assertEquals("instance one timeout", new Long(5000), dictionary.get("timeout")); + assertEquals("instance one minSize", new Integer(10), dictionary.get("minSize")); + assertNull(dictionary.get("id")); + + assertEquals(2, factoryTest.getPids().size()); + + // step 2a. modify default instance & add another instance + writer = readConfiguration(); + writer.setValue("factoryOptionalMetatype", "one", idAttribute, "timeout", "123"); + writer.addConfig(""); + writeConfiguration(writer); + + // step 2b. wait for updates on default instance + dictionary = factoryTest.waitForUpdate("one"); + assertEquals("instance one timeout", new Long(123), dictionary.get("timeout")); + assertEquals("instance one minSize", new Integer(10), dictionary.get("minSize")); + assertNull(dictionary.get("id")); + + // step 2c. wait for updates on second instance + dictionary = factoryTest.waitForUpdate("two"); + assertEquals("instance one timeout", new Long(100), dictionary.get("timeout")); + assertEquals("instance one minSize", new Integer(456), dictionary.get("minSize")); + assertEquals("two", dictionary.get("id")); + + assertEquals(3, factoryTest.getPids().size()); + + // step 3a. delete the default instance + writer = readConfiguration(); + writer.deleteConfig("factoryOptionalMetatype", "one", idAttribute, false); + writeConfiguration(writer); + + // step 3a. wait for the update + dictionary = factoryTest.waitForUpdate("one"); + assertNull("default instance deleted", dictionary); + + assertEquals(3, factoryTest.getPids().size()); + + // step 4a. add a new default instance & update the second instance + writer = readConfiguration(); + writer.addConfig(""); + writer.setValue("factoryOptionalMetatype", "two", idAttribute, "timeout", "789"); + writeConfiguration(writer); + + // step 4b. wait for updates on the default instance + dictionary = factoryTest.waitForUpdate("three"); + assertEquals("instance one timeout", new Long(222), dictionary.get("timeout")); + assertEquals("instance one minSize", new Integer(111), dictionary.get("minSize")); + assertNull(dictionary.get("id")); + + // step 4c. wait for updates on the two instance + dictionary = factoryTest.waitForUpdate("two"); + assertEquals("instance one timeout", new Long(789), dictionary.get("timeout")); + assertEquals("instance one minSize", new Integer(456), dictionary.get("minSize")); + assertEquals("two", dictionary.get("id")); + + assertEquals(4, factoryTest.getPids().size()); + + // step 5a. delete two & three, update four + writer = readConfiguration(); + writer.deleteConfig("factoryOptionalMetatype", "two", idAttribute, false); + writer.deleteConfig("factoryOptionalMetatype", "three", idAttribute, false); + writer.setValue("factoryOptionalMetatype", "four", idAttribute, "timeout", "6000"); + writeConfiguration(writer); + + // step 5b. wait for updates + dictionary = factoryTest.waitForUpdate("two"); + assertEquals("instance 2 deleted", null, dictionary); + + // step 5c. wait for updates + dictionary = factoryTest.waitForUpdate("three"); + assertEquals("instance 2 deleted", null, dictionary); + + // step 5d. wait for updates + dictionary = factoryTest.waitForUpdate("four"); + assertEquals("instance one timeout", new Long(6000), dictionary.get("timeout")); + assertEquals("instance one minSize", new Integer(10), dictionary.get("minSize")); + assertNull(dictionary.get("id")); + + assertEquals(4, factoryTest.getPids().size()); + } +} diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/nested/AttributeCopyTestRunner.java b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/nested/AttributeCopyTestRunner.java new file mode 100755 index 00000000000..b80a7a5dad8 --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/nested/AttributeCopyTestRunner.java @@ -0,0 +1,255 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package test.server.config.nested; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; +import java.util.Dictionary; + +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; +import org.osgi.service.cm.ConfigurationAdmin; +import org.osgi.service.component.ComponentContext; + +import test.server.BaseTestRunner; +import test.server.config.dynamic.ConfigWriter; +import test.server.config.dynamic.FactoryTest; + +/** + * + */ +public class AttributeCopyTestRunner extends BaseTestRunner { + + String parentName = "com.ibm.ws.config.attributeCopy"; + String childName = "com.ibm.ws.config.attributeCopy.child"; + String child2Name = "com.ibm.ws.config.attributeCopy.grandchild"; + String subTypeName = "com.ibm.ws.config.attributeCopy.subType"; + + private FactoryTest parent; + private FactoryTest child; + private FactoryTest child2; + private FactoryTest subType; + + private ConfigurationAdmin configAdmin; + + @Override + protected void activate(ComponentContext context) throws Exception { + super.activate(context); + registerServlet("/attribute-copy", new TestDynamicConfigServlet(), null, null); + + this.parent = new FactoryTest(parentName); + this.child = new FactoryTest(childName); + this.child2 = new FactoryTest(child2Name); + this.subType = new FactoryTest(subTypeName); + + addTest(parent); + addTest(child); + addTest(child2); + addTest(subType); + + BundleContext bundleContext = context.getBundleContext(); + ServiceReference ref = bundleContext.getServiceReference(ConfigurationAdmin.class.getName()); + this.configAdmin = (ConfigurationAdmin) bundleContext.getService(ref); + } + + public void testSimpleAttributeCopy() throws Exception { + Dictionary dictionary; + ConfigWriter writer; + + try { + // Reset to avoid contamination + resetFactoryTests(); + + /* + * + */ + + // *** STEP 1 *** + // Write initial configuration + writer = readConfiguration(); + writer.addConfig(""); + writeConfiguration(writer); + + // wait for the initial configuration to be injected. + dictionary = parent.waitForUpdate("a"); + assertEquals("id should be \"a\"", + "a", dictionary.get("id")); + assertEquals("Bob", dictionary.get("copiedName")); + + } finally { + // Clean up + writer = readConfiguration(); + writer.deleteConfig("copyTest", "a", false); + writeConfiguration(writer); + } + } + + public void testSimpleAttributeCopyArray() throws Exception { + Dictionary dictionary; + ConfigWriter writer; + + try { + // Reset to avoid contamination + resetFactoryTests(); + + /* + * + */ + + // *** STEP 1 *** + // Write initial configuration + writer = readConfiguration(); + writer.addConfig(""); + writeConfiguration(writer); + + // wait for the initial configuration to be injected. + dictionary = parent.waitForUpdate("a"); + assertEquals("id should be \"a\"", + "a", dictionary.get("id")); + String[] hobbies = (String[]) dictionary.get("hobbies"); + assertTrue("copiedHobbies should be the same as hobbies", Arrays.equals(hobbies, (String[]) dictionary.get("copiedHobbies"))); + + } finally { + // Clean up + writer = readConfiguration(); + writer.deleteConfig("copyTest", "a", false); + writeConfiguration(writer); + } + } + + public void testNestedAttributeCopy() throws Exception { + Dictionary dictionary; + ConfigWriter writer; + + try { + // Reset to avoid contamination + resetFactoryTests(); + + /* + * + * + * + */ + + // *** STEP 1 *** + // Write initial configuration + writer = readConfiguration(); + writer.addConfig("" + + "" + + ""); + writeConfiguration(writer); + + // wait for the initial configuration to be injected. + dictionary = parent.waitForUpdate("a"); + assertEquals("id should be \"a\"", + "a", dictionary.get("id")); + assertEquals("Bob", dictionary.get("copiedName")); + assertEquals("Eleanor", dictionary.get("copiedChild")); + + } finally { + // Clean up + writer = readConfiguration(); + writer.deleteConfig("copyTest", "a", false); + writeConfiguration(writer); + } + } + + public void testDoubleNestedAttributeCopy() throws Exception { + Dictionary dictionary; + ConfigWriter writer; + + try { + // Reset to avoid contamination + resetFactoryTests(); + + /* + * + * + * + * + * + */ + + // *** STEP 1 *** + // Write initial configuration + writer = readConfiguration(); + writer.addConfig("" + + "" + + "" + + "" + + ""); + writeConfiguration(writer); + + // wait for the initial configuration to be injected. + dictionary = parent.waitForUpdate("a"); + assertEquals("id should be \"a\"", + "a", dictionary.get("id")); + assertEquals("Bob", dictionary.get("copiedName")); + assertEquals("Eleanor", dictionary.get("copiedChild")); + assertEquals("Ringo", dictionary.get("copiedGrandchild")); + + } finally { + // Clean up + writer = readConfiguration(); + writer.deleteConfig("copyTest", "a", false); + writeConfiguration(writer); + } + } + + public void testExtendsAttributeCopy() throws Exception { + Dictionary dictionary; + ConfigWriter writer; + + try { + // Reset to avoid contamination + resetFactoryTests(); + + /* + * + */ + + // *** STEP 1 *** + // Write initial configuration + writer = readConfiguration(); + writer.addConfig(""); + writeConfiguration(writer); + + // wait for the initial configuration to be injected. + dictionary = subType.waitForUpdate("a"); + assertEquals("id should be \"a\"", + "a", dictionary.get("id")); + assertEquals("subType value", dictionary.get("value")); + assertEquals("subType value", dictionary.get("valueCopy")); + assertEquals("supertype name", dictionary.get("name")); + assertEquals("supertype name", dictionary.get("nameCopy")); + assertEquals("supertype name", dictionary.get("superNameCopy")); + + } finally { + // Clean up + writer = readConfiguration(); + writer.deleteConfig("acSubType", "a", false); + writeConfiguration(writer); + } + } + + /** + * Reset factories to avoid test contamination + */ + private void resetFactoryTests() { + parent.reset(); + child.reset(); + child2.reset(); + subType.reset(); + } +} diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/nested/ChildFirstExtendsTestRunner.java b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/nested/ChildFirstExtendsTestRunner.java new file mode 100755 index 00000000000..83e7bb3556b --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/nested/ChildFirstExtendsTestRunner.java @@ -0,0 +1,140 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package test.server.config.nested; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.util.Dictionary; + +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.component.ComponentContext; + +import test.server.BaseTestRunner; +import test.server.config.dynamic.ConfigWriter; +import test.server.config.dynamic.FactoryTest; + +/** + * + */ +public class ChildFirstExtendsTestRunner extends BaseTestRunner { + + String parentName = "com.ibm.example.topLevelElement"; + String childName = "com.ibm.example.child.a"; + String child2Name = "com.ibm.example.child.b"; + String child3Name = "com.ibm.example.child.c"; + String topName = "com.ibm.example.top.d"; + String abstractName = "com.ibm.example.supertype"; + + private FactoryTest parent; + private FactoryTest child; + private FactoryTest child2; + private FactoryTest child3; + private FactoryTest top; + + private ConfigurationAdmin configAdmin; + + @Override + protected void activate(ComponentContext context) throws Exception { + super.activate(context); + registerServlet("/child-first-extends", new TestDynamicConfigServlet(), null, null); + + this.parent = new FactoryTest(parentName); + this.child = new FactoryTest(childName); + this.child2 = new FactoryTest(child2Name); + this.child3 = new FactoryTest(child3Name); + this.top = new FactoryTest(topName); + + addTest(parent); + addTest(child); + addTest(child2); + addTest(child3); + addTest(top); + + BundleContext bundleContext = context.getBundleContext(); + ServiceReference ref = bundleContext.getServiceReference(ConfigurationAdmin.class.getName()); + this.configAdmin = (ConfigurationAdmin) bundleContext.getService(ref); + } + + public void testChildFirstExtends() throws Exception { + Dictionary dictionary; + ConfigWriter writer; + + try { + // Reset to avoid contamination + resetFactoryTests(); + + /* + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ + + // *** STEP 1 *** + // Write initial configuration + writer = readConfiguration(); + writer.addConfig("" + + "" + + ""); + writeConfiguration(writer); + + // wait for the initial configuration to be injected. + dictionary = parent.waitForUpdate("a"); + assertEquals("id should be \"a\"", + "a", dictionary.get("id")); + + dictionary = child.waitForUpdate("child.a"); + assertEquals("a1", dictionary.get("attrA1")); + assertEquals("The child should inherit from the supertype", "value", dictionary.get("commonAttribute")); + + Configuration[] superTypes = configAdmin.listConfigurations("(service.factoryPid=" + abstractName + ")"); + assertNotNull(superTypes); + assertEquals(1, superTypes.length); + dictionary = superTypes[0].getProperties(); + assertEquals("value", dictionary.get("commonAttribute")); + + } finally { + // Clean up + writer = readConfiguration(); + writer.deleteConfig("topLevelElement", "a", false); + writeConfiguration(writer); + } + } + + /** + * Reset factories to avoid test contamination + */ + private void resetFactoryTests() { + parent.reset(); + child.reset(); + child2.reset(); + child3.reset(); + top.reset(); + } +} diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/nested/HiddenTestRunner.java b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/nested/HiddenTestRunner.java new file mode 100755 index 00000000000..14b340927b7 --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/nested/HiddenTestRunner.java @@ -0,0 +1,320 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package test.server.config.nested; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; + +import java.util.Dictionary; + +import org.osgi.service.component.ComponentContext; + +import test.server.BaseTestRunner; +import test.server.config.dynamic.ConfigWriter; +import test.server.config.dynamic.FactoryTest; + +/** + * + */ +public class HiddenTestRunner extends BaseTestRunner { + private final String grandparentName = "test.config.hidden.grandparent"; + private final String parentName = "test.config.hidden.parent"; + private final String childName = "test.config.hidden.child"; + private final String childExtended = "test.config.hidden.child.extended"; + + private FactoryTest grandparent; + private FactoryTest parent; + private FactoryTest child; + private FactoryTest extendedChild; + + @Override + protected void activate(ComponentContext context) throws Exception { + super.activate(context); + registerServlet("/hidden-test", new TestDynamicConfigServlet(), null, null); + + this.grandparent = new FactoryTest(grandparentName); + this.parent = new FactoryTest(parentName); + this.child = new FactoryTest(childName); + this.extendedChild = new FactoryTest(childExtended); + + addTest(grandparent); + addTest(parent); + addTest(child); + addTest(extendedChild); + } + + public void testHiddenChildWithExtends() throws Exception { + Dictionary dictionary; + ConfigWriter writer; + + try { + // Reset to avoid contamination + grandparent.reset(); + parent.reset(); + extendedChild.reset(); + + // *** STEP 1 *** + // Write initial configuration + writer = readConfiguration(); + writer.addConfig("" + + " " + + " " + + " " + + ""); + writeConfiguration(writer); + + // wait for the initial configuration to be injected. + dictionary = grandparent.waitForUpdate("grandparent"); + assertEquals("name should be \"hidden grandparent\"", + "hidden grandparent", dictionary.get("name")); + + dictionary = parent.waitForUpdate("parent"); + assertEquals("name should be \"hidden parent\"", + "hidden parent", dictionary.get("name")); + + dictionary = extendedChild.waitForUpdate("child"); + assertEquals("The name for the child should be I am an extended element", "I am an extended element", dictionary.get("name")); + assertEquals("The child should inherit from the supertype", "inheritedProperty", dictionary.get("abstractProperty")); + + // *** STEP 2 *** + // Update child + writer = readConfiguration(); + writer.deleteConfig("grandparentOfHiddenElement", "grandparent", false); + writer.addConfig("" + + " " + + " " + + " " + + ""); + writeConfiguration(writer); + + dictionary = extendedChild.waitForUpdate("child"); + assertEquals("The child name should be Updated extended element", "Updated extended element", dictionary.get("name")); + + // Check that the parent dictionary isn't updated + assertFalse("There should not be an update to the parent", parent.hasDictionary("parent")); + + // Check that the grandparent dictionary isn't updated + assertFalse("There should not be an update to the grandparent", grandparent.hasDictionary("grandparent")); + + // *** STEP 3 *** + // Update parent + writer = readConfiguration(); + writer.deleteConfig("grandparentOfHiddenElement", "grandparent", false); + writer.addConfig("" + + " " + + " " + + " " + + ""); + writeConfiguration(writer); + + // Check that the child wasn't updated + assertFalse("The child should not be updated", extendedChild.hasDictionary("child")); + + // Check parent update + dictionary = parent.waitForUpdate("parent"); + assertEquals("name should be \"hidden parent updated\"", + "hidden parent updated", dictionary.get("name")); + + // Check grandparent update + dictionary = grandparent.waitForUpdate("grandparent"); + assertEquals("name should be \"hidden grandparent\"", + "hidden grandparent", dictionary.get("name")); + + // *** STEP 4 *** + // Delete child -- This should not result in an update to the parent + writer = readConfiguration(); + writer.deleteConfig("grandparentOfHiddenElement", "grandparent", false); + writer.addConfig("" + + " " + + " " + + ""); + writeConfiguration(writer); + + // Check that the child was deleted + assertNull("The child dictionary should be null", extendedChild.waitForUpdate("child")); + + // Check that the parent dictionary isn't updated + assertFalse("There should not be an update to the parent", parent.hasDictionary("parent")); + + // Check that the grandparent dictionary isn't updated + assertFalse("There should not be an update to the grandparent", grandparent.hasDictionary("grandparent")); + + // *** STEP 5 *** + // Put the child back -- This should not result in an update to the parent + writer = readConfiguration(); + writer.deleteConfig("grandparentOfHiddenElement", "grandparent", false); + writer.addConfig("" + + " " + + " " + + " " + + ""); + writeConfiguration(writer); + + // Check that the child was updated + dictionary = extendedChild.waitForUpdate("child"); + assertEquals("The name for the child should be Returned extended element", "Returned extended element", dictionary.get("name")); + assertEquals("The child should inherit from the supertype", "inheritedProperty", dictionary.get("abstractProperty")); + + // Check that the parent dictionary isn't updated + assertFalse("There should not be an update to the parent", parent.hasDictionary("parent")); + + // Check that the grandparent dictionary isn't updated + assertFalse("There should not be an update to the grandparent", grandparent.hasDictionary("grandparent")); + + } finally { + // Clean up + writer = readConfiguration(); + writer.deleteConfig("grandparentOfHiddenElement", "grandparent", false); + writeConfiguration(writer); + try { + grandparent.waitForUpdate("grandparent"); + } catch (Exception ex) { + ex.printStackTrace(); + // We don't care. Just waiting to make sure server update has gone through. If something went wrong earlier, that might not happen. + } + } + } + + public void testHiddenChild() throws Exception { + Dictionary dictionary; + ConfigWriter writer; + + try { + + // Reset to avoid contamination + grandparent.reset(); + parent.reset(); + child.reset(); + + // *** STEP 1 *** + // Write initial configuration + writer = readConfiguration(); + writer.addConfig("" + + " " + + " " + + " " + + ""); + writeConfiguration(writer); + + // wait for the initial configuration to be injected. + dictionary = grandparent.waitForUpdate("grandparent"); + assertEquals("name should be \"hidden grandparent\"", + "hidden grandparent", dictionary.get("name")); + + dictionary = parent.waitForUpdate("parent"); + assertEquals("name should be \"hidden parent\"", + "hidden parent", dictionary.get("name")); + + dictionary = child.waitForUpdate("child"); + assertEquals("The name for the child should be I am stealthy!", "I am stealthy!", dictionary.get("name")); + + // *** STEP 2 *** + // Update child + writer = readConfiguration(); + writer.deleteConfig("grandparentOfHiddenElement", "grandparent", false); + writer.addConfig("" + + " " + + " " + + " " + + ""); + writeConfiguration(writer); + + dictionary = child.waitForUpdate("child"); + assertEquals("The child name should be You can't see me.", "You can't see me.", dictionary.get("name")); + + // Check that the parent dictionary isn't updated + assertFalse("There should not be an update to the parent", parent.hasDictionary("parent")); + + // Check that the grandparent dictionary isn't updated + assertFalse("There should not be an update to the grandparent", grandparent.hasDictionary("grandparent")); + + // *** STEP 3 *** + // Update parent + writer = readConfiguration(); + writer.deleteConfig("grandparentOfHiddenElement", "grandparent", false); + writer.addConfig("" + + " " + + " " + + " " + + ""); + writeConfiguration(writer); + + // Check that the child wasn't updated + assertFalse("The child should not be updated", child.hasDictionary("child")); + + // Check parent update + dictionary = parent.waitForUpdate("parent"); + assertEquals("name should be \"hidden parent updated\"", + "hidden parent updated", dictionary.get("name")); + + // Check grandparent update + dictionary = grandparent.waitForUpdate("grandparent"); + assertEquals("name should be \"hidden grandparent\"", + "hidden grandparent", dictionary.get("name")); + + // *** STEP 4 *** + // Delete child -- This should not result in an update to the parent + writer = readConfiguration(); + writer.deleteConfig("grandparentOfHiddenElement", "grandparent", false); + writer.addConfig("" + + " " + + " " + + ""); + writeConfiguration(writer); + + // Check that the child wasn't updated + assertNull("The child dictionary should be null", child.waitForUpdate("child")); + + // Check that the parent dictionary isn't updated + assertFalse("There should not be an update to the parent", parent.hasDictionary("parent")); + + // Check that the grandparent dictionary isn't updated + assertFalse("There should not be an update to the grandparent", grandparent.hasDictionary("grandparent")); + + // *** STEP 5 *** + // Put the child back -- This should not result in an update to the parent + writer = readConfiguration(); + writer.deleteConfig("grandparentOfHiddenElement", "grandparent", false); + writer.addConfig("" + + " " + + " " + + " " + + ""); + writeConfiguration(writer); + + // Check that the child was updated + dictionary = child.waitForUpdate("child"); + assertEquals("The name for the child should be I'm back!", "I'm back!", dictionary.get("name")); + + // Check that the parent dictionary isn't updated + assertFalse("There should not be an update to the parent", parent.hasDictionary("parent")); + + // Check that the grandparent dictionary isn't updated + assertFalse("There should not be an update to the grandparent", grandparent.hasDictionary("grandparent")); + + } finally { + // Clean up + writer = readConfiguration(); + writer.deleteConfig("grandparentOfHiddenElement", "grandparent", false); + writeConfiguration(writer); + try { + grandparent.waitForUpdate("grandparent"); + parent.waitForUpdate("parent"); + } catch (Exception ex) { + ex.printStackTrace(); + // We don't care. Just waiting to make sure server update has gone through. If something went wrong earlier, that might not happen. + } + } + } + +} diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/nested/NestedDefaultsTestRunner.java b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/nested/NestedDefaultsTestRunner.java new file mode 100755 index 00000000000..666503ac363 --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/nested/NestedDefaultsTestRunner.java @@ -0,0 +1,117 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested of + * its trade secrets, irrespective of what has been deposited with the U.S. + * Copyright Office. + */ +package test.server.config.nested; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import java.util.Dictionary; +import java.util.Vector; + +import org.osgi.service.cm.Configuration; +import org.osgi.service.component.ComponentContext; + +import test.server.BaseTestRunner; +import test.server.config.dynamic.ConfigWriter; +import test.server.config.dynamic.FactoryTest; + +import com.ibm.ws.config.xml.internal.XMLConfigConstants; + +public class NestedDefaultsTestRunner extends BaseTestRunner { + + private final String parentName = "test.config.nested.defaults"; + private FactoryTest parent; + + @Override + protected void activate(ComponentContext context) throws Exception { + super.activate(context); + registerServlet("/nested-defaults-test", new TestDynamicConfigServlet(), null, null); + + this.parent = new FactoryTest(parentName); + addTest(parent); + } + + public void testRemoveAttribute() throws Exception { + testNestedDefaults("cardPos"); + } + + public void testRemoveAttributeNegativeCardinality() throws Exception { + testNestedDefaults("cardNeg"); + } + + public void testRemoveAttributeZeroCardinality() throws Exception { + testNestedDefaults("cardZero"); + } + + private void testNestedDefaults(String childName) throws Exception { + + Dictionary dictionary; + ConfigWriter writer; + String[] pids = new String[] {}; + + try { + parent.reset(); + + // *** STEP 1 *** + // Write initial configuration + writer = readConfiguration(); + writer.addConfig("<{0} id=\"parent\" someAttribute=\"empty attributes test\">" + + " <{1} hello=\"hello\" enabled=\"true\"/>" + + "", parentName, childName); + writeConfiguration(writer); + // wait for the initial configuration to be injected. + dictionary = parent.waitForUpdate("parent"); + assertEquals("someAttribute should be \"empty attributes test\"", + "empty attributes test", dictionary.get("someAttribute")); + + // *** STEP 2 *** + // Remove attribute from child + writer = readConfiguration(); + writer.deleteConfig(parentName, "parent", false); + writer.addConfig("<{0} id=\"parent\" someAttribute=\"empty attributes test\">" + + " <{1}/>" + + "", parentName, childName); + writeConfiguration(writer); + + dictionary = parent.waitForUpdate("parent"); + assertEquals("someAttribute should be \"empty attributes test\"", + "empty attributes test", dictionary.get("someAttribute")); + + Object children = dictionary.get(childName); + if (children instanceof String) { + pids = new String[] { (String) children }; + } else if (children instanceof Vector) { + Vector v = (Vector) children; + pids = v.toArray(pids); + } else { + pids = (String[]) dictionary.get(childName); + } + + assertNotNull("There should be a child element", pids); + assertEquals("There should be only one child element", 1, pids.length); + + Configuration childConfig = configAdmin.getConfiguration(pids[0]); + + assertEquals("Enabled attribute should be true", Boolean.TRUE, childConfig.getProperties().get("enabled")); + assertNull("The attribute hello should be null", childConfig.getProperties().get("hello")); + assertEquals("The parent's child pid should equal the child's service.pid value", pids[0], childConfig.getProperties().get(XMLConfigConstants.CFG_SERVICE_PID)); + } finally { + // Clean up + writer = readConfiguration(); + writer.deleteConfig(parentName, "parent", false); + writeConfiguration(writer); + } + + } + +} diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/nested/NestedMergeRulesTestRunner.java b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/nested/NestedMergeRulesTestRunner.java new file mode 100755 index 00000000000..4c907ea98e8 --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/nested/NestedMergeRulesTestRunner.java @@ -0,0 +1,595 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package test.server.config.nested; + +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.io.IOException; +import java.util.ArrayList; +import java.util.Dictionary; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +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.component.ComponentContext; +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; +import org.osgi.service.http.HttpService; + +import com.ibm.wsspi.kernel.service.location.WsLocationAdmin; + +import test.server.BaseTestRunner; +import test.server.config.dynamic.ConfigWriter; +import test.server.config.dynamic.FactoryTest; + +/** + * + */ +@Component(service = NestedMergeRulesTestRunner.class, + name = "test.server.config.nestedMergeRules", + immediate = true, + property = { "service.vendor=IBM" }) +public class NestedMergeRulesTestRunner extends BaseTestRunner { + + private FactoryTest parentFactoryONE; + private FactoryTest parentFactoryMULTIPLE; + + private static final String parentName = "test.nestedmerge.parent"; + + private static final String XML_NEW_LINE = "\r\n"; + + private ConfigWriter writer; + + private ConfigurationAdmin configAdmin; + + @Override + @Reference(name = "locationService", service = WsLocationAdmin.class) + protected void setLocationService(WsLocationAdmin ref) { + this.locationService = ref; + } + + @Override + protected void unsetLocationService(WsLocationAdmin ref) { + if (ref == this.locationService) { + this.locationService = null; + } + } + + @Override + @Reference(name = "http", service = HttpService.class) + protected void setHttp(HttpService ref) { + this.http = ref; + } + + @Override + protected void unsetHttp(HttpService ref) { + if (ref == this.http) { + this.http = null; + } + } + + @Override + @Activate + protected void activate(ComponentContext context) throws Exception { + super.activate(context); + registerServlet("/nested-merge-rules", new TestDynamicConfigServlet(), null, null); + + this.parentFactoryONE = new FactoryTest(parentName + ".ONE"); + this.parentFactoryMULTIPLE = new FactoryTest(parentName + ".MULTIPLE"); + addTest(parentFactoryONE); + addTest(parentFactoryMULTIPLE); + + BundleContext bundleContext = context.getBundleContext(); + ServiceReference ref = bundleContext.getServiceReference(ConfigurationAdmin.class.getName()); + this.configAdmin = (ConfigurationAdmin) bundleContext.getService(ref); + + } + + private static class Child { + + Map attributes = new HashMap(); + + void addAttribute(String name, String value) { + attributes.put(name, value); + } + + void validateAttributes(Dictionary values) { + for (Map.Entry entry : attributes.entrySet()) { + if (!"id".equals(entry.getKey())) { + assertEquals(entry.getValue(), values.get(entry.getKey())); + } + } + } + + protected String getAlias() { + return "child"; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append('<'); + builder.append(getAlias()); + for (Map.Entry entry : attributes.entrySet()) { + builder.append(' '); + builder.append(entry.getKey()); + builder.append('='); + builder.append('"'); + builder.append(entry.getValue()); + builder.append('"'); + } + builder.append("/>"); + return builder.toString(); + } + + /** + * @return + */ + protected String getId() { + return attributes.get("id"); + } + + } + + private static class DefaultChild extends Child { + @Override + protected String getAlias() { + return "defaultChild"; + } + + @Override + protected String getId() { + return "childId"; + } + } + + private class Parent { + List children = new ArrayList(); + private final String id; + private final Cardinality cardinality; + private final String parentAliasName; + + public Parent(String id, Cardinality cardinality) { + this.id = id; + this.cardinality = cardinality; + parentAliasName = "nmrParent." + cardinality; + } + + void addChild(Child child) { + children.add(child); + } + + public String getId() { + return this.id; + } + + void validateAttributes(Dictionary values, Result expected) throws IOException { + assertEquals("id should be " + getId(), + getId(), values.get("id")); + + validateChildren(values, expected); + + } + + void validateChildren(Dictionary values, Result expected) throws IOException { + String childAliasName = "child"; + Object childValue = values.get(childAliasName); + assertNotNull(childValue); + + if (expected.getNumberOfChildren() == 1) { + if (cardinality == Cardinality.ONE) { + assertTrue("There should be one child pid", childValue instanceof String); + validateSingleChild((String) childValue); + } else { + assertEquals("There should be one child pid", 1, ((String[]) childValue).length); + validateChildren((String[]) childValue); + } + } else { + String[] childValues = (String[]) childValue; + assertEquals("The number of children should equal the number of evaluated pids", + expected.getNumberOfChildren(), childValues.length); + validateChildren(childValues); + } + + } + + /** + * @param childValue + * @throws IOException + */ + private void validateChildren(String[] childValues) throws IOException { + for (String pid : childValues) { + Configuration cfg = configAdmin.getConfiguration(pid); + Dictionary dictionary = cfg.getProperties(); + Child child = getChild(dictionary); + child.validateAttributes(dictionary); + } + + } + + /** + * @param object + * @return + */ + private Child getChild(Dictionary dictionary) { + String id = (String) dictionary.get("id"); + if (id == null) { + return null; + } else { + for (Child child : children) { + if (id.equals(child.getId())) { + return child; + } else if (id.contains("default-")) { + Enumeration keys = dictionary.keys(); + String key = keys.nextElement(); + if ("id".equals(key)) + key = keys.nextElement(); + if (child.attributes.containsKey(key)) + return child; + } + } + return null; + } + } + + /** + * @param childValue + * @throws IOException + */ + private void validateSingleChild(String childValue) throws IOException { + Configuration cfg = configAdmin.getConfiguration(childValue); + for (Child child : children) { + child.validateAttributes(cfg.getProperties()); + } + + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append('<'); + builder.append(parentAliasName); + builder.append(" id="); + builder.append('"'); + builder.append(id); + builder.append('"'); + builder.append('>'); + + for (Child child : children) { + builder.append(XML_NEW_LINE); + builder.append(child); + } + builder.append(XML_NEW_LINE); + builder.append('<'); + builder.append('/'); + builder.append(parentAliasName); + builder.append('>'); + return builder.toString(); + } + + public void addChildren(Child... children) { + for (Child child : children) { + addChild(child); + } + } + + /** + * + */ + public void write() throws Exception { + writer = readConfiguration(); + writer.addConfig(toString()); + writeConfiguration(writer); + } + + public void delete(Result expected) throws Exception { + // Clean up + writer = readConfiguration(); + writer.deleteConfig(parentAliasName, getId(), false); + writeConfiguration(writer); + if (expected.shouldSucceed()) + assertNull(getFactory().waitForUpdate(getId())); + else + assertFalse(getFactory().hasDictionary(getId())); + + } + + /** + * @throws IOException + * + */ + public void validate(Result expected) throws IOException { + if (expected.shouldSucceed()) { + Dictionary dictionary = getFactory().waitForUpdate(getId()); + validateAttributes(dictionary, expected); + } else { + assertFalse(getFactory().hasDictionary(getId())); + } + } + + /** + * @return + */ + private FactoryTest getFactory() { + if (cardinality == Cardinality.ONE) + return parentFactoryONE; + else + return parentFactoryMULTIPLE; + } + + /** + * + */ + public void test(Result result) throws Exception { + + try { + clean(); + write(); + validate(result); + } finally { + delete(result); + } + + } + + /** + * + */ + private void clean() { + parentFactoryONE.reset(); + parentFactoryMULTIPLE.reset(); + } + } + + /** + * Multiple children with null IDs should be merged when cardinality is zero + */ + public void testNullIDsCardinalityZero() throws Exception { + + Parent parent = new Parent("parent", Cardinality.ONE); + Child c1 = new Child(); + c1.addAttribute("attr1", "a1"); + Child c2 = new Child(); + c2.addAttribute("attr2", "a2"); + parent.addChildren(c1, c2); + + Result r = new Result(true, 1); + parent.test(r); + + } + + /** + * Multiple children with distinct IDs should be merged. This makes no sense to me whatsoever, but it was the + * resolution of the design issue. + * + * @throws Exception + */ + public void testMultipleIDsCardinalityZero() throws Exception { + Parent parent = new Parent("parent", Cardinality.ONE); + Child c1 = new Child(); + c1.addAttribute("id", "id1"); + c1.addAttribute("attr1", "a1"); + Child c2 = new Child(); + c2.addAttribute("id", "id2"); + c2.addAttribute("attr2", "a2"); + parent.addChildren(c1, c2); + + Result r = new Result(true, 1); + parent.test(r); + } + + /** + * Multiple children with the same ID should be merged when cardinality is zero. + * + * @throws Exception + */ + public void testSingleIDCardinalityZero() throws Exception { + Parent parent = new Parent("parent", Cardinality.ONE); + Child c1 = new Child(); + c1.addAttribute("id", "id1"); + c1.addAttribute("attr1", "a1"); + Child c2 = new Child(); + c2.addAttribute("id", "id1"); + c2.addAttribute("attr2", "a2"); + parent.addChildren(c1, c2); + + Result r = new Result(true, 1); + parent.test(r); + } + + /** + * Multiple distinct IDs with multiple cardinality should result in multiple children. + * + * @throws Exception + */ + public void testMultipleIDsCardinalityMultiple() throws Exception { + Parent parent = new Parent("parent", Cardinality.MULTIPLE); + Child c1 = new Child(); + c1.addAttribute("id", "id1"); + c1.addAttribute("attr1", "a1"); + Child c2 = new Child(); + c2.addAttribute("id", "id2"); + c2.addAttribute("attr2", "a2"); + parent.addChildren(c1, c2); + + Result r = new Result(true, 2); + parent.test(r); + } + + /** + * Multiple null IDs with multiple cardinality should result in multiple children. + * + * @throws Exception + */ + public void testNullIDsCardinalityMultiple() throws Exception { + Parent parent = new Parent("parent", Cardinality.MULTIPLE); + Child c1 = new Child(); + c1.addAttribute("attr1", "a1"); + Child c2 = new Child(); + c2.addAttribute("attr2", "a2"); + parent.addChildren(c1, c2); + + Result r = new Result(true, 2); + parent.test(r); + } + + /** + * Multiple children with the same ID should result in one merged element + * + * @throws Exception + */ + public void testSingleIDCardinalityMultiple() throws Exception { + Parent parent = new Parent("parent", Cardinality.MULTIPLE); + Child c1 = new Child(); + c1.addAttribute("id", "id1"); + c1.addAttribute("attr1", "a1"); + Child c2 = new Child(); + c2.addAttribute("id", "id1"); + c2.addAttribute("attr2", "a2"); + parent.addChildren(c1, c2); + + Result r = new Result(true, 1); + parent.test(r); + } + + public void testMixedIDsCardinalityMultiple() throws Exception { + Parent parent = new Parent("parent", Cardinality.MULTIPLE); + Child c1 = new Child(); + c1.addAttribute("id", "id1"); + c1.addAttribute("attr1", "a1"); + + Child c2 = new Child(); + c2.addAttribute("id", "id1"); + c2.addAttribute("attr2", "a2"); + + Child c3 = new Child(); + c3.addAttribute("id", "id2"); + c3.addAttribute("attr1", "b1"); + + parent.addChildren(c1, c2, c3); + + Result r = new Result(true, 2); + parent.test(r); + } + + public void testMultipleParentsNullIDsCardinalityZero() throws Exception { + Parent parent = new Parent("parent", Cardinality.ONE); + Child c1 = new Child(); + c1.addAttribute("attr1", "a1"); + parent.addChild(c1); + + Parent parent2 = new Parent("parent2", Cardinality.ONE); + Child c2 = new Child(); + c2.addAttribute("attr2", "a2"); + parent2.addChild(c2); + + Result r = new Result(true, 1); + parent.test(r); + parent2.test(r); + } + + public void testMultipleParentsSingleIDCardinalityZero() throws Exception { + Parent parent = new Parent("parent", Cardinality.ONE); + Child c1 = new Child(); + c1.addAttribute("id", "id1"); + c1.addAttribute("attr1", "a1"); + parent.addChild(c1); + + Parent parent2 = new Parent("parent2", Cardinality.ONE); + Child c2 = new Child(); + c2.addAttribute("id", "id1"); + c2.addAttribute("attr2", "a2"); + parent2.addChild(c2); + + Result r = new Result(true, 1); + parent.test(r); + parent2.test(r); + } + + public void testMultipleParentsMixedIDsCardinalityMultiple() throws Exception { + Parent parent = new Parent("parent", Cardinality.MULTIPLE); + Parent parent2 = new Parent("parent2", Cardinality.MULTIPLE); + + Child c1 = new Child(); + c1.addAttribute("id", "id1"); + c1.addAttribute("attr1", "a1"); + + Child c2 = new Child(); + c2.addAttribute("id", "id1"); + c2.addAttribute("attr2", "a2"); + + Child c3 = new Child(); + c3.addAttribute("id", "id2"); + c3.addAttribute("attr1", "b1"); + + parent.addChildren(c1, c2, c3); + + Child c4 = new Child(); + c4.addAttribute("id", "id1"); + c4.addAttribute("attr4", "a4"); + + Child c5 = new Child(); + c5.addAttribute("id", "id2"); + c5.addAttribute("attr5", "attr5"); + + parent2.addChildren(c4, c5); + + Result r = new Result(true, 2); + + parent.test(r); + } + + public void testDefaultIDMerging() throws Exception { + Parent parent = new Parent("parent", Cardinality.MULTIPLE); + DefaultChild c1 = new DefaultChild(); + c1.addAttribute("attr1", "a1"); + DefaultChild c2 = new DefaultChild(); + c2.addAttribute("attr2", "a2"); + parent.addChildren(c1, c2); + + Result r = new Result(true, 1); + parent.test(r); + } + + private static class Result { + + private final int numberOfElements; + private final boolean shouldWork; + + public Result(boolean shouldWork, int elements) { + this.shouldWork = shouldWork; + this.numberOfElements = elements; + } + + public boolean shouldSucceed() { + return shouldWork; + } + + public int getNumberOfChildren() { + return numberOfElements; + } + } + + private static enum Cardinality { + ONE, MULTIPLE + }; +} diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/nested/NestedSingletonTestRunner.java b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/nested/NestedSingletonTestRunner.java new file mode 100755 index 00000000000..cd909085bc7 --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/nested/NestedSingletonTestRunner.java @@ -0,0 +1,179 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package test.server.config.nested; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.fail; + +import java.util.Dictionary; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Map; + +import org.osgi.service.cm.Configuration; +import org.osgi.service.component.ComponentContext; + +import test.server.BaseTestRunner; +import test.server.config.dynamic.ConfigWriter; +import test.server.config.dynamic.SingletonTest; + +/** + * + */ +public class NestedSingletonTestRunner extends BaseTestRunner { + + private SingletonTest child; + private final String parentName = "test.config.nested.managed.metatype"; + private final String parentAlias = "singletonNested"; + private final String childName = "test.singleton.under.singleton"; + private final String nestedElementTwo = "resultTwo"; + private final String singletonElement = "singletonResult"; + private final String nestedElement = "testResult"; + private SingletonTest parent; + + @Override + protected void activate(ComponentContext context) throws Exception { + super.activate(context); + registerServlet("/nested-singleton-test", new TestDynamicConfigServlet(), null, null); + + this.child = new SingletonTest(childName); + this.parent = new SingletonTest(parentName); + addTest(child); + addTest(parent); + } + + public static Map> getMetatypeExpectedProperties() { + Map map1 = new HashMap(); + map1.put("pass", Integer.valueOf(9999)); + map1.put("fail", Integer.valueOf(7777)); + + Map map2 = new HashMap(); + map2.put("pass", Integer.valueOf(100)); + map2.put("fail", Integer.valueOf(0)); + + Map> expectedProperties = new Hashtable>(); + expectedProperties.put("one", map1); + expectedProperties.put("two", map2); + + return expectedProperties; + } + + /* + * Test that the initial configuration is parsed and transformed correctly. Moved from TestRunner + * because it can be affected by testUpdateReceived(). Both should be called from the same test. + */ + public void testInitialConfiguration() throws Exception { + Dictionary properties = parent.waitForUpdate(); + + String[] singleton = (String[]) properties.get(singletonElement); + if (singleton != null) { + Configuration singletonConfig = configAdmin.getConfiguration(singleton[0]); + Dictionary singletonProps = singletonConfig.getProperties(); + String singletonString = (String) singletonProps.get("someString"); + String[] singletonArray = (String[]) singletonProps.get("someArray"); + assertEquals("aSingleton", singletonString); + assertEquals(3, singletonArray.length); + } + String[] resultsTwo = (String[]) properties.get(nestedElementTwo); + assertNotNull(resultsTwo); + assertEquals("There should be three nested results", 3, resultsTwo.length); + for (int i = 0; i < resultsTwo.length; i++) { + Configuration config = configAdmin.getConfiguration(resultsTwo[i]); + Dictionary prop = config.getProperties(); + String someString = (String) prop.get("someString"); + String[] someArray = (String[]) prop.get("someArray"); + if ("notDefault".equals(someString)) { + assertEquals(3, someArray.length); + } else if ("zzz".equals(someString)) { + if (someArray.length == 2) { + assertEquals("Incorrect defined value for array", "ten", someArray[0]); + assertEquals("Incorrect defined value for array", "eleven", someArray[1]); + } else if (someArray.length == 3) { + assertEquals("Incorrect default value for array", "four", someArray[0]); + assertEquals("Incorrect default value for array", "five", someArray[1]); + assertEquals("Incorrect default value for array", "six", someArray[2]); + } else { + fail("Incorrect number of entries for someArray attribute: " + someArray.length); + } + + } else { + fail("Incorrect value for attribute someString: " + someString); + } + } + + String[] testResults = (String[]) properties.get(nestedElement); + assertNotNull(testResults); + assertEquals(2, testResults.length); + + Map> expectedProperties = getMetatypeExpectedProperties(); + for (int i = 0; i < testResults.length; i++) { + Configuration config = configAdmin.getConfiguration(testResults[i]); + Dictionary prop = config.getProperties(); + String innerName = (String) prop.get("name"); + Map expectedProps = expectedProperties.remove(innerName); + assertNotNull("Unexpected name: " + innerName, expectedProps); + for (Map.Entry entry : expectedProps.entrySet()) { + assertEquals("property " + entry.getKey() + " mismatch", entry.getValue(), prop.get(entry.getKey())); + } + } + + assertEquals(0, expectedProperties.size()); + } + + /** + * Make sure a cross bundle nested singleton update causes the ManagedService to be updated + * + * @throws Exception + */ + public void testUpdateReceived() throws Exception { + + ConfigWriter writer; + Dictionary dictionary; + + // *** STEP 1 *** + // Clear any previous updates + child.reset(); + + // Delete any existing elements + writer = readConfiguration(); + boolean updated = writer.deleteConfig(parentName, null, true); + updated |= writer.deleteConfig(parentAlias, null, true); + if (updated) { + // The update check here is just a convenience for debugging. When the test is run, there should + // always be an element to delete. + writeConfiguration(writer); + assertNotNull("Singleton deletion should result in a configuration with all default properties", child.waitForUpdate()); + } + + // Write initial configuration + writer = readConfiguration(); + writer.addConfig("<{0} name=\"Jane Doe\">" + + " <{1} someString=\"hello\"/>" + + "", parentName, childName); + writeConfiguration(writer); + + // wait for the initial configuration to be injected. + + dictionary = child.waitForUpdate(); + assertEquals("someString should be \"hello\"", "hello", dictionary.get("someString")); + + // Clean up + writer = readConfiguration(); + writer.deleteConfig(parentName, null, true); + writer.deleteConfig(parentAlias, null, true); + writeConfiguration(writer); + assertNull("Singleton deletion should result in a null dictionary", child.waitForUpdate()); + + } +} diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/nested/TestRunner.java b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/nested/TestRunner.java new file mode 100755 index 00000000000..4a86375e42a --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/nested/TestRunner.java @@ -0,0 +1,650 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011 + * + * The source code for this program is not published or otherwise divested of + * its trade secrets, irrespective of what has been deposited with the U.S. + * Copyright Office. + */ +package test.server.config.nested; + +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 static org.junit.Assert.fail; + +import java.util.Arrays; +import java.util.Dictionary; +import java.util.HashSet; +import java.util.Set; + +import org.osgi.framework.Constants; +import org.osgi.service.cm.Configuration; +import org.osgi.service.cm.ConfigurationException; +import org.osgi.service.component.ComponentContext; + +import test.server.BaseTestRunner; +import test.server.config.dynamic.ConfigWriter; +import test.server.config.dynamic.FactoryNestedTest; +import test.server.config.dynamic.FactoryTest; +import test.server.config.dynamic.SingletonTest; + +import com.ibm.ws.config.xml.internal.XMLConfigConstants; + +public class TestRunner extends BaseTestRunner { + + @Override + protected void activate(ComponentContext context) throws Exception { + super.activate(context); + registerServlet("/nested-config-test", new TestDynamicConfigServlet(), null, null); + } + + public void testNested() throws Exception { + testNested("test.config.nested.singleton", "test.config.nested.singleton", + "test.config.nested.child", "test.config.nested.child"); + } + + public void testNestedMetatype() throws Exception { + testNested("nestedSingleton", "test.config.nested.singleton.metatype", + "nestedChildOne", "test.config.nested.child.one.metatype"); + } + + @SuppressWarnings("unchecked") + private void testNested(String parentName, String parentPid, String childName, String childPid) throws Exception { + Dictionary dictionary; + ConfigWriter writer; + String[] pids; + + SingletonTest parent = new SingletonTest(parentPid); + addTest(parent); + + FactoryNestedTest child = new FactoryNestedTest(childPid); + addTest(child); + + // *** STEP 1 *** + // wait for the initial configuration to be injected. + dictionary = parent.waitForUpdate(); + + // *** STEP 2 *** + // add first nested child + writer = readConfiguration(); + writer.deleteConfig(parentName, null, false); + writer.addConfig("<{0} name=\"myNestedSingleton\">" + + " <{1} name=\"myNestedChildOne\" a=\"b\" value=\"10\"/>" + + "", parentName, childName); + writeConfiguration(writer); + + // parent gets injected with the first child pid + dictionary = parent.waitForUpdate(); + assertEquals("name property", "myNestedSingleton", dictionary.get("name")); + String parentServicePid = (String) dictionary.get(XMLConfigConstants.CFG_SERVICE_PID); + pids = (String[]) dictionary.get(childName); + assertNotNull("child pids", pids); + assertEquals("child pids", 1, pids.length); + String firstChildPid = pids[0]; + + // first child instance is created + dictionary = child.waitForUpdate(firstChildPid); + assertEquals("name property", "myNestedChildOne", dictionary.get("name")); + assertEquals("value property", "10", dictionary.get("value")); + assertEquals("a property", "b", dictionary.get("a")); + + assertEquals("Nested Child config.parentPID should be equal to parent's service.pid", parentServicePid, + dictionary.get(XMLConfigConstants.CFG_PARENT_PID)); + + // *** STEP 3 *** + // add second nested child + writer = readConfiguration(); + writer.deleteConfig(parentName, null, false); + writer.addConfig("<{0} name=\"myNestedSingleton\">" + + " <{1} name=\"myNestedChildOne\" a=\"b\" value=\"10\"/>" + + " <{1} name=\"myNestedChildTwo\" b=\"c\" value=\"20\"/>" + + "", parentName, childName); + writeConfiguration(writer); + + // parent gets injected with the second child pid + dictionary = parent.waitForUpdate(); + assertEquals("name property", "myNestedSingleton", dictionary.get("name")); + pids = (String[]) dictionary.get(childName); + assertNotNull("child pids", pids); + assertEquals("child pids", 2, pids.length); + Set pidSet = toSet(pids); + assertTrue("first child pid", pidSet.contains(firstChildPid)); + pidSet.remove(firstChildPid); + String secondChildPid = pidSet.iterator().next(); + + // second child instance is created + dictionary = child.waitForUpdate(secondChildPid); + assertEquals("name property", "myNestedChildTwo", dictionary.get("name")); + assertEquals("value property", "20", dictionary.get("value")); + assertEquals("b property", "c", dictionary.get("b")); + + // *** STEP 4 *** + // update second child and remove first + writer = readConfiguration(); + writer.deleteConfig(parentName, null, false); + writer.addConfig("<{0} name=\"myNestedSingleton\">" + + " <{1} name=\"myNestedChildTwo\" b=\"c\" value=\"40\"/>" + + "", parentName, childName); + writeConfiguration(writer); + + // parent gets updated with a single pid + dictionary = parent.waitForUpdate(); + assertEquals("name property", "myNestedSingleton", dictionary.get("name")); + pids = (String[]) dictionary.get(childName); + assertNotNull("child pids", pids); + assertEquals("child pids", 1, pids.length); + + String deletedPid = null; + String updatedPid = null; + + if (firstChildPid.equals(pids[0])) { + updatedPid = firstChildPid; + deletedPid = secondChildPid; + } else if (secondChildPid.equals(pids[0])) { + updatedPid = secondChildPid; + deletedPid = firstChildPid; + } else { + fail("Unexpected child pid: " + pids[0]); + } + + // one child instance is removed + dictionary = child.waitForUpdate(deletedPid); + assertNull("child removed", dictionary); + + // one child instance is updated + dictionary = child.waitForUpdate(updatedPid); + assertEquals("name property", "myNestedChildTwo", dictionary.get("name")); + assertEquals("value property", "40", dictionary.get("value")); + assertNull("a property", dictionary.get("a")); + assertEquals("b property", "c", dictionary.get("b")); + + // *** STEP 5 *** + // delete parent configuration + writer = readConfiguration(); + writer.deleteConfig(parentName, null, false); + writeConfiguration(writer); + + // remaining child instance is removed + dictionary = child.waitForUpdate(updatedPid); + assertNull("child was not removed", dictionary); + + // parent is removed + dictionary = parent.waitForUpdate(); + assertNull("parent was not removed", dictionary); + } + + @SuppressWarnings("unchecked") + public void testNestedReferences() throws Exception { + Dictionary dictionary; + ConfigWriter writer; + String[] pids; + + String parentName = "test.config.nested.singleton.ref"; + SingletonTest parent = new SingletonTest(parentName); + addTest(parent); + + String childName = "test.config.nested.child.ref.1"; + FactoryNestedTest child = new FactoryNestedTest(childName); + addTest(child); + + // *** STEP 1 *** + // wait for the initial configuration to be injected. + dictionary = parent.waitForUpdate(); + + // *** STEP 2 *** + // add first nested child + writer = readConfiguration(); + writer.addConfig("<{0} id=\"1\" name=\"myNestedChildOne\" a=\"b\" value=\"10\"/>", childName); + writer.deleteConfig(parentName, null, false); + writer.addConfig("<{0} name=\"myNestedSingleton\">" + + " <{1} ref=\"1\" />" + + "", parentName, childName); + writeConfiguration(writer); + + // parent gets injected with the first child pid + dictionary = parent.waitForUpdate(); + assertEquals("name property", "myNestedSingleton", dictionary.get("name")); + pids = (String[]) dictionary.get(childName); + assertNotNull("child pids", pids); + assertEquals("child pids", 1, pids.length); + String firstChildPid = pids[0]; + + // first child instance is created + dictionary = child.waitForUpdate(firstChildPid); + assertEquals("name property", "myNestedChildOne", dictionary.get("name")); + assertEquals("value property", "10", dictionary.get("value")); + assertEquals("a property", "b", dictionary.get("a")); + + // *** STEP 3 *** + // add second nested child + writer = readConfiguration(); + writer.addConfig("<{0} id=\"2\" name=\"myNestedChildTwo\" b=\"c\" value=\"20\"/>", childName); + writer.deleteConfig(parentName, null, false); + writer.addConfig("<{0} name=\"myNestedSingleton\">" + + " <{1} ref=\"1\" />" + + " <{1} ref=\"2\" />" + + "", parentName, childName); + writeConfiguration(writer); + + // parent gets injected with the second child pid + dictionary = parent.waitForUpdate(); + assertEquals("name property", "myNestedSingleton", dictionary.get("name")); + pids = (String[]) dictionary.get(childName); + assertNotNull("child pids", pids); + assertEquals("child pids", 2, pids.length); + Set pidSet = toSet(pids); + assertTrue("first child pid", pidSet.contains(firstChildPid)); + pidSet.remove(firstChildPid); + String secondChildPid = pidSet.iterator().next(); + + // second child instance is created + dictionary = child.waitForUpdate(secondChildPid); + assertEquals("name property", "myNestedChildTwo", dictionary.get("name")); + assertEquals("value property", "20", dictionary.get("value")); + assertEquals("b property", "c", dictionary.get("b")); + + // *** STEP 4 *** + // update second child and remove first + writer = readConfiguration(); + writer.deleteConfig(childName, "1", false); + writer.setValue(childName, "2", "value", "40"); + writeConfiguration(writer); + + // parent gets updated with a single pid + dictionary = parent.waitForUpdate(); + assertEquals("name property", "myNestedSingleton", dictionary.get("name")); + pids = (String[]) dictionary.get(childName); + assertNotNull("child pids", pids); + assertEquals("child pids", 1, pids.length); + + String deletedPid = null; + String updatedPid = null; + + if (firstChildPid.equals(pids[0])) { + updatedPid = firstChildPid; + deletedPid = secondChildPid; + } else if (secondChildPid.equals(pids[0])) { + updatedPid = secondChildPid; + deletedPid = firstChildPid; + } else { + fail("Unexpected child pid: " + pids[0]); + } + + // one child instance is removed + dictionary = child.waitForUpdate(deletedPid); + assertNull("child removed", dictionary); + + // one child instance is updated + dictionary = child.waitForUpdate(updatedPid); + assertEquals("name property", "myNestedChildTwo", dictionary.get("name")); + assertEquals("value property", "40", dictionary.get("value")); + assertNull("a property", dictionary.get("a")); + assertEquals("b property", "c", dictionary.get("b")); + + // *** STEP 5 *** + // delete parent configuration + writer = readConfiguration(); + writer.deleteConfig(parentName, null, false); + writeConfiguration(writer); + + // parent is removed + dictionary = parent.waitForUpdate(); + assertNull("parent was not removed", dictionary); + + // remaining child is still there + Configuration[] configs = configAdmin.listConfigurations("(" + Constants.SERVICE_PID + "=" + updatedPid + ")"); + assertNotNull(configs); + assertEquals(1, configs.length); + } + + public void testNestedFactoryReferences() throws Exception { + testNestedFactoryReferences("test.config.nested.factory.ref", "test.config.nested.factory.ref", + "test.config.nested.child.ref.2", "test.config.nested.child.ref.2"); + } + + public void testNestedMetatypeFactoryReferences() throws Exception { + testNestedFactoryReferences("nestedFactory", "test.config.nested.factory.metatype", + "nestedChildTwo", "test.config.nested.child.two.metatype"); + } + + @SuppressWarnings("unchecked") + private void testNestedFactoryReferences(String parentName, String parentPid, String childName, String childPid) throws Exception { + Dictionary dictionary; + ConfigWriter writer; + String[] pids; + + FactoryTest parent = new FactoryTest(parentPid); + addTest(parent); + + FactoryNestedTest child = new FactoryNestedTest(childPid); + addTest(child); + + // *** STEP 1 *** + // add initial configurations + writer = readConfiguration(); + writer.addConfig("<{0} id=\"1\" name=\"myNestedChildOne\" a=\"b\" value=\"10\"/>", childName); + writer.deleteConfig(parentName, null, true); + writer.addConfig("<{0} id=\"one\" name=\"myNestedFactoryOne\">" + + " <{1} ref=\"1\" />" + + "", parentName, childName); + writer.addConfig("<{0} id=\"two\" name=\"myNestedFactoryTwo\">" + + " <{1} ref=\"1\" />" + + "", parentName, childName); + writeConfiguration(writer); + + // parents get injected with the first child pid + Dictionary dictionaryOne = parent.waitForUpdate("one"); + assertEquals("name property", "myNestedFactoryOne", dictionaryOne.get("name")); + String[] onePids = (String[]) dictionaryOne.get(childName); + assertNotNull("child pids", onePids); + assertEquals("child pids", 1, onePids.length); + + Dictionary dictionaryTwo = parent.waitForUpdate("two"); + assertEquals("name property", "myNestedFactoryTwo", dictionaryTwo.get("name")); + String[] twoPids = (String[]) dictionaryTwo.get(childName); + assertNotNull("child pids", twoPids); + assertEquals("child pids", 1, twoPids.length); + + // both pids should be the same + assertEquals("child pids are not the same", onePids[0], twoPids[0]); + + // child "1" is created + dictionary = child.waitForUpdate(onePids[0]); + assertEquals("name property", "myNestedChildOne", dictionary.get("name")); + assertEquals("value property", "10", dictionary.get("value")); + assertEquals("a property", "b", dictionary.get("a")); + + // *** STEP 2 *** + // add "2" child, modify "1" child, and add reference to "2" child to "one" parent + writer = readConfiguration(); + writer.addConfig("<{0} id=\"2\" name=\"myNestedChildTwo\" b=\"c\" value=\"20\"/>", childName); + writer.setValue(childName, "1", "value", "40"); + writer.deleteConfig(parentName, "one", false); + writer.addConfig("<{0} id=\"one\" name=\"myNestedFactoryOne\">" + + " <{1} ref=\"1\" />" + + " <{1} ref=\"2\" />" + + "", parentName, childName); + writeConfiguration(writer); + + // "two" parent should be notified and have no changes + dictionary = parent.waitForUpdate("two"); + dictionaryEquals(dictionaryTwo, dictionary); + + // "one" parent should be notified and have 2 pids + dictionary = parent.waitForUpdate("one"); + assertEquals("name property", "myNestedFactoryOne", dictionary.get("name")); + pids = (String[]) dictionary.get(childName); + assertNotNull("child pids", pids); + assertEquals("child pids", 2, pids.length); + Set pidSet = toSet(pids); + assertTrue(pidSet.contains(onePids[0])); + pidSet.remove(onePids[0]); + String child2Pid = pidSet.iterator().next(); + + // child "1" is updated + dictionary = child.waitForUpdate(onePids[0]); + assertEquals("name property", "myNestedChildOne", dictionary.get("name")); + assertEquals("value property", "40", dictionary.get("value")); + assertEquals("a property", "b", dictionary.get("a")); + + // child "2" is created + dictionary = child.waitForUpdate(child2Pid); + assertEquals("name property", "myNestedChildTwo", dictionary.get("name")); + assertEquals("value property", "20", dictionary.get("value")); + assertEquals("b property", "c", dictionary.get("b")); + + // *** STEP 3 **** + // delete "1" child + writer = readConfiguration(); + writer.deleteConfig(childName, "1", false); + writeConfiguration(writer); + + // child "1" is deleted + dictionary = child.waitForUpdate(onePids[0]); + assertNull(dictionary); + + // parent "two" has no pids + dictionary = parent.waitForUpdate("two"); + assertEquals("name property", "myNestedFactoryTwo", dictionary.get("name")); + assertEquals(Arrays.asList(), Arrays.asList((String[]) dictionary.get(childName))); + + // parent "one" has one pid + dictionary = parent.waitForUpdate("one"); + assertEquals("name property", "myNestedFactoryOne", dictionary.get("name")); + pids = (String[]) dictionary.get(childName); + assertNotNull("child pids", pids); + assertEquals("child pids", 1, pids.length); + assertEquals(child2Pid, pids[0]); + } + + @SuppressWarnings("unchecked") + public void testNestedNonUniqueReferences() throws Exception { + Dictionary dictionary; + ConfigWriter writer; + String[] pids; + + String parentName = "test.config.nested.singleton.1"; + SingletonTest parent = new SingletonTest(parentName); + addTest(parent); + + String childOneName = "test.config.nested.child.ref.3"; + FactoryNestedTest childOne = new FactoryNestedTest(childOneName); + addTest(childOne); + + String childTwoName = "test.config.nested.child.ref.4"; + FactoryNestedTest childTwo = new FactoryNestedTest(childTwoName); + addTest(childTwo); + + dictionary = parent.waitForUpdate(); + + // *** STEP 1 *** + // add initial configurations - the references use the same id + writer = readConfiguration(); + writer.addConfig("<{0} id=\"1\" name=\"myChildOne\" a=\"b\" value=\"10\"/>", childOneName); + writer.addConfig("<{0} id=\"1\" name=\"myChildTwo\" a=\"b\" strValue=\"bob\"/>", childTwoName); + writer.deleteConfig(parentName, null, true); + writer.addConfig("<{0} name=\"myNestedSingleton\">" + + " <{1} ref=\"1\" />" + + " <{2} ref=\"1\" />" + + "", parentName, childOneName, childTwoName); + writeConfiguration(writer); + + // parent gets injected with the children pids + dictionary = parent.waitForUpdate(); + assertEquals("name property", "myNestedSingleton", dictionary.get("name")); + + pids = (String[]) dictionary.get(childOneName); + assertNotNull("child pids", pids); + assertEquals("child pids", 1, pids.length); + String childOnePid = pids[0]; + + pids = (String[]) dictionary.get(childTwoName); + assertNotNull("child pids", pids); + assertEquals("child pids", 1, pids.length); + String childTwoPid = pids[0]; + + assertFalse("pids are the same: " + childOnePid, childOnePid.equals(childTwoPid)); + } + + @SuppressWarnings("unchecked") + public void testFactoryOptionalId() throws Exception { + ConfigWriter writer; + + FactoryTest parent = new FactoryTest("test.config.nested.factory.optional.metatype", "name"); + addTest(parent); + + FactoryNestedTest child = new FactoryNestedTest("test.config.nested.factory.optional.child.1"); + addTest(child); + + FactoryNestedTest childChild = new FactoryNestedTest("test.config.nested.factory.optional.child.2"); + addTest(childChild); + + String parentName = "nestedOptionalFactory"; + String firstChildName = "nestedOptionalChildOne"; + String secondChildName = "nestedOptionalChildTwo"; + + // write initial configuration + writer = readConfiguration(); + writer.addConfig("<{0} name=\"myOptionalFactory\">" + + " <{1} name=\"myNestedChild\" a=\"b\" value=\"10\">" + + " <{2} name=\"myDoubleNestedChild\" threads=\"15\"/>" + + " " + + "", parentName, firstChildName, secondChildName); + writeConfiguration(writer); + + // parent get injected with the child + Dictionary dictionaryOne = parent.waitForUpdate("myOptionalFactory"); + assertEquals(Short.valueOf("5"), dictionaryOne.get("poolSize")); + String[] onePids = (String[]) dictionaryOne.get(firstChildName); + assertNotNull("child pids", onePids); + assertEquals("child pids", 1, onePids.length); + + // first child is updated + Dictionary dictionaryTwo = child.waitForUpdate(onePids[0]); + assertEquals("name property", "myNestedChild", dictionaryTwo.get("name")); + assertEquals("value property", "10", dictionaryTwo.get("value")); + assertEquals("a property", "b", dictionaryTwo.get("a")); + assertEquals(Long.valueOf("5000"), dictionaryTwo.get("idleTime")); + String[] twoPids = (String[]) dictionaryTwo.get(secondChildName); + assertNotNull("child pids", twoPids); + assertEquals("child pids", 1, twoPids.length); + + // second child is updated + Dictionary dictionaryThree = childChild.waitForUpdate(twoPids[0]); + assertEquals("name property", "myDoubleNestedChild", dictionaryThree.get("name")); + assertEquals("value property", "15", dictionaryThree.get("threads")); + assertEquals(Integer.valueOf("1000"), dictionaryThree.get("timeout")); + + // update double nested configuration + writer = readConfiguration(); + writer.deleteConfig(parentName, "myOptionalFactory", "name", false); + writer.addConfig("<{0} name=\"myOptionalFactory\">" + + " <{1} name=\"myNestedChild\" a=\"b\" value=\"10\">" + + " <{2} name=\"myDoubleNestedChild\" threads=\"20\"/>" + + " " + + "", parentName, firstChildName, secondChildName); + writeConfiguration(writer); + + Dictionary dictionary = null; + + // top parent should be notified of the changes but have no differences + dictionary = parent.waitForUpdate("myOptionalFactory"); + dictionaryEquals(dictionaryOne, dictionary); + + // first child should be notified of the changes but have no differences + dictionary = child.waitForUpdate(onePids[0]); + dictionaryEquals(dictionaryTwo, dictionary); + + // second child should be notified of the changes + dictionary = childChild.waitForUpdate(twoPids[0]); + assertEquals("name property", "myDoubleNestedChild", dictionary.get("name")); + assertEquals("value property", "20", dictionary.get("threads")); + assertEquals(Integer.valueOf("1000"), dictionary.get("timeout")); + } + + public static class TimestampFactoryTest extends FactoryTest { + + private long sleep = -1; + + public TimestampFactoryTest(String name) { + super(name); + } + + public void setSleep(long sleep) { + this.sleep = sleep; + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + @Override + public void updated(String pid, Dictionary properties) throws ConfigurationException { + properties.put("timestamp", System.currentTimeMillis()); + if (sleep > 0) { + try { + Thread.sleep(sleep); + } catch (InterruptedException e) { + // ignore + } + } + super.updated(pid, properties); + } + } + + @SuppressWarnings("unchecked") + public void testUpdateOrder() throws Exception { + Dictionary dictionary; + ConfigWriter writer; + + TimestampFactoryTest a = new TimestampFactoryTest("test.config.order.a"); + TimestampFactoryTest b = new TimestampFactoryTest("test.config.order.b"); + TimestampFactoryTest c = new TimestampFactoryTest("test.config.order.c"); + TimestampFactoryTest d = new TimestampFactoryTest("test.config.order.d"); + TimestampFactoryTest e = new TimestampFactoryTest("test.config.order.e"); + + addTest(a); + addTest(b); + addTest(c); + addTest(d); + addTest(e); + + // *** STEP 1 *** + // wait for the initial configuration to be injected. + dictionary = a.waitForUpdate("a"); + assertEquals("a", dictionary.get("name")); + dictionary = b.waitForUpdate("b"); + assertEquals("b", dictionary.get("name")); + dictionary = c.waitForUpdate("c"); + assertEquals("c", dictionary.get("name")); + dictionary = d.waitForUpdate("d"); + assertEquals("d", dictionary.get("name")); + dictionary = e.waitForUpdate("e"); + assertEquals("e", dictionary.get("name")); + + // *** STEP 2 *** + // update e and check for updates in right order + long timeout = 1000; + a.setSleep(timeout); + b.setSleep(timeout); + c.setSleep(timeout); + d.setSleep(timeout); + e.setSleep(timeout); + + writer = readConfiguration(); + writer.setValue("test.config.order.e", "e", "name", "ee"); + writeConfiguration(writer); + + long aTimeout, bTimeout, cTimeout, dTimeout, eTimeout; + + dictionary = a.waitForUpdate("a"); + assertEquals("a", dictionary.get("name")); + aTimeout = (Long) dictionary.get("timestamp"); + dictionary = b.waitForUpdate("b"); + assertEquals("b", dictionary.get("name")); + bTimeout = (Long) dictionary.get("timestamp"); + dictionary = c.waitForUpdate("c"); + assertEquals("c", dictionary.get("name")); + cTimeout = (Long) dictionary.get("timestamp"); + dictionary = d.waitForUpdate("d"); + assertEquals("d", dictionary.get("name")); + dTimeout = (Long) dictionary.get("timestamp"); + dictionary = e.waitForUpdate("e"); + assertEquals("ee", dictionary.get("name")); + eTimeout = (Long) dictionary.get("timestamp"); + + // expected update order, e, d, c, b, a + assertTrue(dTimeout > eTimeout); + assertTrue(cTimeout > dTimeout); + assertTrue(bTimeout > cTimeout); + assertTrue(aTimeout > bTimeout); + } + + private static Set toSet(String[] array) { + return new HashSet(Arrays.asList(array)); + } + +} diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/reference/TestRunner.java b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/reference/TestRunner.java new file mode 100755 index 00000000000..324c233c618 --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/reference/TestRunner.java @@ -0,0 +1,403 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011 + * + * The source code for this program is not published or otherwise divested of + * its trade secrets, irrespective of what has been deposited with the U.S. + * Copyright Office. + */ +package test.server.config.reference; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import java.util.Dictionary; +import java.util.Vector; + +import org.osgi.framework.BundleContext; +import org.osgi.framework.Constants; +import org.osgi.framework.ServiceReference; +import org.osgi.service.cm.Configuration; +import org.osgi.service.cm.ConfigurationAdmin; +import org.osgi.service.component.ComponentContext; + +import test.server.BaseTestRunner; +import test.server.config.dynamic.ConfigWriter; +import test.server.config.dynamic.FactoryNestedTest; +import test.server.config.dynamic.FactoryTest; +import test.server.config.dynamic.SingletonTest; + +public class TestRunner extends BaseTestRunner { + + @Override + protected void activate(ComponentContext context) throws Exception { + super.activate(context); + registerServlet("/reference-config-test", new TestDynamicConfigServlet(), null, null); + + BundleContext bundleContext = context.getBundleContext(); + ServiceReference ref = bundleContext.getServiceReference(ConfigurationAdmin.class.getName()); + this.configAdmin = (ConfigurationAdmin) bundleContext.getService(ref); + + } + + public void testTwoReferencesOnePid() throws Exception { + + String id = "testTwoReferencesOnePid"; + + FactoryTest parent = new FactoryTest("test.config.reference.parent"); + addTest(parent); + + ConfigWriter writer = readConfiguration(); + + writer.addConfig("" + + " " + + " " + + ""); + writeConfiguration(writer); + + Dictionary dictionary = parent.waitForUpdate(id); + assertNotNull(dictionary.get("widget")); + assertNotNull(dictionary.get("part")); + + // Update a widget + + writer = readConfiguration(); + writer.deleteConfig("test.config.reference.parent", id, true); + writer.addConfig("" + + " " + + " " + + ""); + writeConfiguration(writer); + + dictionary = parent.waitForUpdate(id); + assertNotNull(dictionary.get("widget")); + assertNotNull(dictionary.get("part")); + + // Update a part + writer = readConfiguration(); + writer.deleteConfig("test.config.reference.parent", id, true); + writer.addConfig("" + + " " + + " " + + ""); + writeConfiguration(writer); + + // Check that the final configuration is ok + dictionary = parent.waitForUpdate(id); + String[] widgets = (String[]) dictionary.get("widget"); + String[] parts = (String[]) dictionary.get("part"); + + assertNotNull(widgets); + assertNotNull(parts); + + assertEquals(1, widgets.length); + assertEquals(1, parts.length); + + String widgetPid = widgets[0]; + String partPid = parts[0]; + + Configuration[] widgetConfigs = configAdmin.listConfigurations("(" + Constants.SERVICE_PID + "=" + widgetPid + ")"); + Configuration[] partConfigs = configAdmin.listConfigurations("(" + Constants.SERVICE_PID + "=" + partPid + ")"); + assertNotNull(widgetConfigs); + assertNotNull(partConfigs); + + assertEquals("There should be one widget in CA", 1, widgetConfigs.length); + assertEquals("There should be one part in CA", 1, partConfigs.length); + + Dictionary widgetDictionary = widgetConfigs[0].getProperties(); + Dictionary partDictionary = partConfigs[0].getProperties(); + assertEquals("widget 2", widgetDictionary.get("someProperty")); + assertEquals("widget 2", partDictionary.get("someProperty")); + + } + + public void testReferenceAttribute() throws Exception { + SingletonTest parent = new SingletonTest("test.config.reference.attribute"); + addTest(parent); + + FactoryNestedTest child = new FactoryNestedTest("test.config.reference.attribute.child"); + addTest(child); + + // wait for the initial configuration to be injected. + Dictionary parentDictionary = parent.waitForUpdate(); + assertEquals("version property", "3.0", parentDictionary.get("version")); + assertEquals("maxThreads property", Integer.valueOf(100), parentDictionary.get("maxThreads")); + String pid = (String) parentDictionary.get("reference"); + assertNotNull("reference pid", pid); + + // check the child info + Dictionary childDictionary = child.waitForUpdate(pid); + assertEquals("name property", "one", childDictionary.get("name")); + assertEquals("threads property", Integer.valueOf(100), childDictionary.get("threads")); + + Dictionary dictionary; + ConfigWriter writer; + + // STEP 1: update child and check if parent is updated + writer = readConfiguration(); + writer.setValue("childAttributeReference", "ref1", "threads", "500"); + writeConfiguration(writer); + + // check updated child info + dictionary = child.waitForUpdate(pid); + assertEquals("name property", "one", dictionary.get("name")); + assertEquals("threads property", Integer.valueOf(500), dictionary.get("threads")); + + // check parent got updated + dictionary = parent.waitForUpdate(); + dictionaryEquals(parentDictionary, dictionary); + + // STEP 2: delete child and check if parent is updated + writer = readConfiguration(); + writer.deleteConfig("childAttributeReference", "ref1", false); + writeConfiguration(writer); + + // check updated child info + dictionary = child.waitForUpdate(pid); + assertNull(dictionary); + + // check parent got updated + dictionary = parent.waitForUpdate(); + assertEquals("version property", "3.0", dictionary.get("version")); + assertEquals("maxThreads property", Integer.valueOf(100), dictionary.get("maxThreads")); + assertNull(dictionary.get("reference")); + + // STEP 3: add child back up and check if parent is updated + writer = readConfiguration(); + writer.addConfig(""); + writeConfiguration(writer); + + parentDictionary = parent.waitForUpdate(); + assertEquals("version property", "3.0", parentDictionary.get("version")); + assertEquals("maxThreads property", Integer.valueOf(100), parentDictionary.get("maxThreads")); + pid = (String) parentDictionary.get("reference"); + assertNotNull("reference pid", pid); + + // check updated child info + dictionary = child.waitForUpdate(pid); + assertEquals("name property", "noname", dictionary.get("name")); + assertEquals("threads property", Integer.valueOf(300), dictionary.get("threads")); + } + + public void testReferenceElement() throws Exception { + + SingletonTest parent = new SingletonTest("test.config.reference.element"); + addTest(parent); + + FactoryNestedTest child = new FactoryNestedTest("test.config.reference.element.child"); + addTest(child); + + // wait for the initial configuration to be injected. + Dictionary parentDictionary = parent.waitForUpdate(); + assertEquals("version property", "4.0", parentDictionary.get("version")); + assertEquals("maxThreads property", Integer.valueOf(200), parentDictionary.get("maxThreads")); + // check pids in references + String[] pids = (String[]) parentDictionary.get("references"); + assertNotNull("reference pids", pids); + assertEquals("child pids", 4, pids.length); + // check pids in referenceList + Vector pidList = (Vector) parentDictionary.get("referenceList"); + assertNotNull("reference pids", pidList); + assertEquals("child pids", 4, pidList.size()); + assertEquals(pids[0], pidList.get(0)); + assertEquals(pids[1], pidList.get(2)); + assertEquals(pids[2], pidList.get(1)); + // check pids in childRef + String[] pids2 = (String[]) parentDictionary.get("childRef"); + assertNotNull(pids2); + assertEquals(2, pids2.length); + assertEquals(pids[0], pids2[1]); + assertEquals(pids[1], pids2[0]); + // these elements should not be in the dictionary + assertNull(parentDictionary.get("referencesRef")); + assertNull(parentDictionary.get("referenceListRef")); + assertNull(parentDictionary.get("child")); + + // check the first reference info + Dictionary childOneDictionary = child.waitForUpdate(pids[0]); + assertEquals("name property", "five", childOneDictionary.get("name")); + assertEquals("threads property", Integer.valueOf(5), childOneDictionary.get("threads")); + + // check the first reference info + Dictionary childTwoDictionary = child.waitForUpdate(pids[1]); + assertEquals("name property", "unavailable", childTwoDictionary.get("name")); + assertEquals("threads property", Integer.valueOf(300), childTwoDictionary.get("threads")); + + // check the second reference info + Dictionary childThreeDictionary = child.waitForUpdate(pids[2]); + assertEquals("name property", "two", childThreeDictionary.get("name")); + assertEquals("threads property", Integer.valueOf(200), childThreeDictionary.get("threads")); + + // check the nested reference from "references" + Dictionary childFourDictionary = child.waitForUpdate(pids[3]); + assertEquals("name property", "nested-one", childFourDictionary.get("name")); + assertEquals("threads property", Integer.valueOf(5000), childFourDictionary.get("threads")); + + // check the nested reference from "referenceList" + Dictionary childFiveictionary = child.waitForUpdate(pidList.get(3)); + assertEquals("name property", "nested-two", childFiveictionary.get("name")); + assertEquals("threads property", Integer.valueOf(6000), childFiveictionary.get("threads")); + + Dictionary dictionary; + ConfigWriter writer; + + // STEP 1: update child and check if parent is updated + writer = readConfiguration(); + writer.setValue("childElementReference", "ref2", "threads", "444"); + writeConfiguration(writer); + + // check updated child info + dictionary = child.waitForUpdate(pids[2]); + assertEquals("name property", "two", dictionary.get("name")); + assertEquals("threads property", Integer.valueOf(444), dictionary.get("threads")); + + // check parent got updated + dictionary = parent.waitForUpdate(); + dictionaryEquals(parentDictionary, dictionary); + + // STEP 2: delete child two and check if parent is updated + writer = readConfiguration(); + writer.deleteConfig("childElementReference", "ref3", false); + writeConfiguration(writer); + + // check updated child info + dictionary = child.waitForUpdate(pids[1]); + assertNull(dictionary); + + // check parent got updated + parentDictionary = parent.waitForUpdate(); + assertEquals("version property", "4.0", parentDictionary.get("version")); + assertEquals("maxThreads property", Integer.valueOf(200), parentDictionary.get("maxThreads")); + // check pids in references + String[] newPids = (String[]) parentDictionary.get("references"); + assertNotNull("reference pids", newPids); + assertEquals("child pids", 3, newPids.length); + assertEquals(pids[0], newPids[0]); + assertEquals(pids[2], newPids[1]); + assertEquals(pids[3], newPids[2]); + // check pids in referenceList + Vector newPidList = (Vector) parentDictionary.get("referenceList"); + assertNotNull("reference pids", newPidList); + assertEquals("child pids", 3, newPidList.size()); + assertEquals(pidList.get(0), newPidList.get(0)); + assertEquals(pids[2], newPidList.get(1)); + assertEquals(pidList.get(3), newPidList.get(2)); + // check pids in childRef + String[] newPids2 = (String[]) parentDictionary.get("childRef"); + assertNotNull(newPids2); + assertEquals(1, newPids2.length); + assertEquals(pids[0], newPids2[0]); + // these elements should not be in the dictionary + assertNull(parentDictionary.get("referencesRef")); + assertNull(parentDictionary.get("referenceListRef")); + assertNull(parentDictionary.get("child")); + + // STEP 3: add child two back up and check if parent is updated + writer = readConfiguration(); + writer.addConfig(""); + writeConfiguration(writer); + + // check parent got updated + parentDictionary = parent.waitForUpdate(); + assertEquals("version property", "4.0", parentDictionary.get("version")); + assertEquals("maxThreads property", Integer.valueOf(200), parentDictionary.get("maxThreads")); + // check pids in references + pids = (String[]) parentDictionary.get("references"); + assertNotNull("reference pids", pids); + assertEquals("child pids", 4, pids.length); + assertEquals(newPids[0], pids[0]); + assertEquals(newPids[1], pids[2]); + assertEquals(newPids[2], pids[3]); + // check pids in referenceList + pidList = (Vector) parentDictionary.get("referenceList"); + assertNotNull("reference pids", pidList); + assertEquals("child pids", 4, pidList.size()); + assertEquals(pids[0], pidList.get(0)); + assertEquals(pids[1], pidList.get(2)); + assertEquals(pids[2], pidList.get(1)); + assertEquals(newPidList.get(2), pidList.get(3)); + // check pids in childRef + pids2 = (String[]) parentDictionary.get("childRef"); + assertNotNull(pids2); + assertEquals(2, pids2.length); + assertEquals(pids[0], pids2[1]); + assertEquals(pids[1], pids2[0]); + // these elements should not be in the dictionary + assertNull(parentDictionary.get("referencesRef")); + assertNull(parentDictionary.get("referenceListRef")); + assertNull(parentDictionary.get("child")); + + // check updated child info + dictionary = child.waitForUpdate(pids[1]); + assertEquals("name property", "noname", dictionary.get("name")); + assertEquals("threads property", Integer.valueOf(666), dictionary.get("threads")); + } + + public void testReferenceUpdates() throws Exception { + + FactoryTest nodeA = new FactoryTest("test.config.reference.node.a", "uniqueName"); + addTest(nodeA); + + FactoryTest nodeB = new FactoryTest("test.config.reference.node.b"); + addTest(nodeB); + + FactoryTest nodeC = new FactoryTest("test.config.reference.node.c"); + addTest(nodeC); + + Dictionary nodeADictionary = nodeA.waitForUpdate("foo"); + String nodeBOnePid = (String) nodeADictionary.get("nodeRef"); + assertNotNull(nodeBOnePid); + + Dictionary nodeCDictionary = nodeC.waitForUpdate("three"); + assertEquals("ford", nodeCDictionary.get("name")); + String nodeCPid = nodeC.getPid("three"); + + Dictionary nodeBOneDictionary = nodeB.waitForUpdate("one"); + assertEquals(Integer.valueOf(100), nodeBOneDictionary.get("value")); + assertEquals(nodeBOnePid, nodeB.getPid("one")); + assertEquals(nodeCPid, nodeBOneDictionary.get("nodeRef")); + + Dictionary nodeBTwoDictionary = nodeB.waitForUpdate("two"); + assertEquals(Integer.valueOf(200), nodeBTwoDictionary.get("value")); + assertEquals(nodeBOnePid, nodeB.getPid("one")); + assertEquals(nodeCPid, nodeBTwoDictionary.get("nodeRef")); + + ConfigWriter writer; + Dictionary dictionary; + + // Test 1: Update nodeB one - that should update nodeA + writer = readConfiguration(); + writer.setValue("nodeB", "one", "value", "5555"); + writeConfiguration(writer); + + nodeBOneDictionary = nodeB.waitForUpdate("one"); + assertEquals(Integer.valueOf(5555), nodeBOneDictionary.get("value")); + assertEquals(nodeBOnePid, nodeB.getPid("one")); + assertEquals(nodeCPid, nodeBOneDictionary.get("nodeRef")); + + dictionary = nodeA.waitForUpdate("foo"); + dictionaryEquals(nodeADictionary, dictionary); + + // Test 2: Update nodeC - that should update everything! + writer = readConfiguration(); + writer.setValue("nodeC", "three", "name", "honda"); + writeConfiguration(writer); + + nodeCDictionary = nodeC.waitForUpdate("three"); + assertEquals("honda", nodeCDictionary.get("name")); + + dictionary = nodeB.waitForUpdate("one"); + dictionaryEquals(nodeBOneDictionary, dictionary); + + dictionary = nodeB.waitForUpdate("two"); + dictionaryEquals(nodeBTwoDictionary, dictionary); + + dictionary = nodeA.waitForUpdate("foo"); + dictionaryEquals(nodeADictionary, dictionary); + } + +} diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/soc/ServiceObjectClassTestRunner.java b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/soc/ServiceObjectClassTestRunner.java new file mode 100755 index 00000000000..6dd69492b77 --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/soc/ServiceObjectClassTestRunner.java @@ -0,0 +1,198 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package test.server.config.soc; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import java.util.Dictionary; + +import org.osgi.framework.BundleContext; +import org.osgi.framework.Constants; +import org.osgi.framework.ServiceReference; +import org.osgi.service.cm.Configuration; +import org.osgi.service.cm.ConfigurationAdmin; +import org.osgi.service.component.ComponentContext; + +import test.server.BaseTestRunner; +import test.server.config.dynamic.ConfigWriter; +import test.server.config.dynamic.FactoryTest; + +/** + * + */ +public class ServiceObjectClassTestRunner extends BaseTestRunner { + + String simpleSOCPID = "com.ibm.ws.config.soc.simple"; + String applePID = "com.ibm.ws.config.soc.apple"; + String orangePID = "com.ibm.ws.config.soc.orange"; + + private FactoryTest simpleSOCTest; + + private ConfigurationAdmin configAdmin; + + @Override + protected void activate(ComponentContext context) throws Exception { + super.activate(context); + registerServlet("/serviceObjectClass-test", new TestDynamicConfigServlet(), null, null); + + this.simpleSOCTest = new FactoryTest(simpleSOCPID); + + addTest(simpleSOCTest); + + BundleContext bundleContext = context.getBundleContext(); + ServiceReference ref = bundleContext.getServiceReference(ConfigurationAdmin.class.getName()); + this.configAdmin = (ConfigurationAdmin) bundleContext.getService(ref); + } + + public void testSimpleServiceObjectClass() throws Exception { + Dictionary dictionary; + ConfigWriter writer; + + try { + // Reset to avoid contamination + resetFactoryTests(); + + /* + * + * + * + */ + + // *** STEP 1 *** + // Write initial configuration + writer = readConfiguration(); + writer.addConfig(""); + writer.addConfig(""); + writer.addConfig(""); + writeConfiguration(writer); + + // wait for the initial configuration to be injected. + dictionary = simpleSOCTest.waitForUpdate("a"); + assertEquals("id should be \"a\"", + "a", dictionary.get("id")); + + String referencePid = (String) dictionary.get("fruitRef"); + + Configuration[] references = configAdmin.listConfigurations("(" + Constants.SERVICE_PID + "=" + referencePid + ")"); + assertNotNull(references); + assertEquals("There should be one reference", 1, references.length); + + Dictionary appleDictionary = references[0].getProperties(); + assertEquals("id should be apple", "apple", appleDictionary.get("id")); + assertNull("apple should not contain properties from orange metatype", appleDictionary.get("orangeType")); + assertEquals("apple should have properties from apple metatype", "macintosh", appleDictionary.get("appleType")); + + // *** STEP 2 *** + // Update apple->orange + writer = readConfiguration(); + writer.setValue("serviceObjectClassTest", "a", "fruitRef", "orange"); + writeConfiguration(writer); + + // wait for the dictionary update + dictionary = simpleSOCTest.waitForUpdate("a"); + assertEquals("id should be \"a\"", + "a", dictionary.get("id")); + referencePid = (String) dictionary.get("fruitRef"); + + references = configAdmin.listConfigurations("(" + Constants.SERVICE_PID + "=" + referencePid + ")"); + assertNotNull(references); + assertEquals("There should be one reference", 1, references.length); + + Dictionary orangeDictionary = references[0].getProperties(); + assertEquals("id should be orange", "orange", orangeDictionary.get("id")); + assertNull("orange should not contain properties from apple metatype", orangeDictionary.get("appleType")); + assertEquals("orange should have properties from orange metatype", "clementine", orangeDictionary.get("orangeType")); + + } finally { + // Clean up + writer = readConfiguration(); + writer.deleteConfig("serviceObjectClassTest", "a", true); + writer.deleteConfig("apple", "apple", true); + writer.deleteConfig("orange", "orange", true); + writeConfiguration(writer); + } + } + + public void testServiceObjectClassConflict() throws Exception { + Dictionary dictionary; + ConfigWriter writer; + + try { + // Reset to avoid contamination + resetFactoryTests(); + + /* + * + * + * + */ + + // *** STEP 1 *** + // Write initial configuration + writer = readConfiguration(); + writer.addConfig(""); + writer.addConfig(""); + writer.addConfig(""); + writeConfiguration(writer); + + // wait for the initial configuration to be injected. + dictionary = simpleSOCTest.waitForUpdate("a"); + assertEquals("id should be \"a\"", + "a", dictionary.get("id")); + + // fruitRef should be null because we can't distinguish between apple/orange + assertNull(dictionary.get("fruitRef")); + + // *** STEP 2 *** + // Update apple->orange to eliminate conflict + writer = readConfiguration(); + writer.deleteConfig("orange", "apple", true); + writer.addConfig(""); + writeConfiguration(writer); + + // wait for the dictionary update + dictionary = simpleSOCTest.waitForUpdate("a"); + assertEquals("id should be \"a\"", + "a", dictionary.get("id")); + + String referencePid = (String) dictionary.get("fruitRef"); + + Configuration[] references = configAdmin.listConfigurations("(" + Constants.SERVICE_PID + "=" + referencePid + ")"); + assertNotNull(references); + assertEquals("There should be one reference", 1, references.length); + + Dictionary appleDictionary = references[0].getProperties(); + assertEquals("id should be apple", "apple", appleDictionary.get("id")); + assertNull("apple should not contain properties from orange metatype", appleDictionary.get("orangeType")); + assertEquals("apple should have properties from apple metatype", "macintosh", appleDictionary.get("appleType")); + + } finally { + // Clean up + writer = readConfiguration(); + writer.deleteConfig("serviceObjectClassTest", "a", false); + writer.deleteConfig("apple", "apple", true); + writer.deleteConfig("orange", "orange", true); + writer.deleteConfig("orange", "apple", true); + writeConfiguration(writer); + } + } + + /** + * Reset factories to avoid test contamination + */ + private void resetFactoryTests() { + simpleSOCTest.reset(); + + } +} diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/variable/TestRunner.java b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/variable/TestRunner.java new file mode 100755 index 00000000000..a65b5720988 --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/config/variable/TestRunner.java @@ -0,0 +1,90 @@ +/* +IBM Confidential + * +OCO Source Materials + * +Copyright IBM Corp. 2011 + * +The source code for this program is not published or otherwise divested of +its trade secrets, irrespective of what has been deposited with the U.S. +Copyright Office. + */ +package test.server.config.variable; + +import static org.junit.Assert.assertEquals; + +import java.util.Dictionary; + +import org.osgi.service.component.ComponentContext; + +import test.server.BaseTestRunner; +import test.server.config.dynamic.ConfigWriter; +import test.server.config.dynamic.FactoryTest; + +public class TestRunner extends BaseTestRunner { + + @Override + protected void activate(ComponentContext context) throws Exception { + super.activate(context); + registerServlet("/variable-config-test", new TestDynamicConfigServlet(), null, null); + } + + public void testVariableChange() throws Exception { + + FactoryTest parent = new FactoryTest("test.config.variable.factory"); + addTest(parent); + + // wait for the initial configurations to be injected. + Dictionary oneDictionary = parent.waitForUpdate("one"); + assertEquals("port", Integer.valueOf(1234), oneDictionary.get("port")); + assertEquals("host", "localhost", oneDictionary.get("host")); + assertEquals("ipAddress", "${localIpAddress}", oneDictionary.get("ipAddress")); + + Dictionary twoDictionary = parent.waitForUpdate("two"); + assertEquals("port", Integer.valueOf(5678), twoDictionary.get("port")); + assertEquals("host", "127.0.0.1", twoDictionary.get("host")); + assertEquals("ipAddress", "${localIpAddress}", twoDictionary.get("ipAddress")); + + ConfigWriter writer; + + // STEP 1: change hostname variable + writer = readConfiguration(); + writer.setValue("variable", "hostname", "name", "value", "ibm.com"); + writeConfiguration(writer); + + // wait for instance one to update + oneDictionary = parent.waitForUpdate("one"); + assertEquals("port", Integer.valueOf(1234), oneDictionary.get("port")); + assertEquals("host", "ibm.com", oneDictionary.get("host")); + assertEquals("ipAddress", "${localIpAddress}", oneDictionary.get("ipAddress")); + + // STEP 2: add localIpAdress variable + writer = readConfiguration(); + writer.addConfig(""); + writeConfiguration(writer); + + // wait for instance one update + oneDictionary = parent.waitForUpdate("one"); + assertEquals("port", Integer.valueOf(1234), oneDictionary.get("port")); + assertEquals("host", "ibm.com", oneDictionary.get("host")); + assertEquals("ipAddress", "192.168.1.1", oneDictionary.get("ipAddress")); + + // wait for instance two update + twoDictionary = parent.waitForUpdate("two"); + assertEquals("port", Integer.valueOf(5678), twoDictionary.get("port")); + assertEquals("host", "127.0.0.1", twoDictionary.get("host")); + assertEquals("ipAddress", "192.168.1.1", twoDictionary.get("ipAddress")); + + // STEP 3: set localHostNames variable + writer = readConfiguration(); + writer.addConfig(""); + writeConfiguration(writer); + + // wait for instance two update + twoDictionary = parent.waitForUpdate("two"); + assertEquals("port", Integer.valueOf(5678), twoDictionary.get("port")); + assertEquals("host", "w3.ibm.com", twoDictionary.get("host")); + assertEquals("ipAddress", "192.168.1.1", twoDictionary.get("ipAddress")); + } + +} diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/schema/SchemaGeneratorActivator.java b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/schema/SchemaGeneratorActivator.java new file mode 100755 index 00000000000..6469831a933 --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/schema/SchemaGeneratorActivator.java @@ -0,0 +1,108 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011 + * + * The source code for this program is not published or otherwise divested of + * its trade secrets, irrespective of what has been deposited with the U.S. + * Copyright Office. + */ +package test.server.schema; + +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.io.Writer; + +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.service.component.ComponentContext; + +import test.server.BaseHttpTest; + +import com.ibm.websphere.metatype.SchemaGenerator; +import com.ibm.websphere.metatype.SchemaGeneratorOptions; +import com.ibm.wsspi.kernel.service.location.WsLocationAdmin; +import com.ibm.wsspi.kernel.service.location.WsResource; + +public class SchemaGeneratorActivator extends BaseHttpTest { + + private BundleContext bundleContext; + private SchemaGenerator schemaGenerator; + private WsLocationAdmin locationService; + + @Override + protected void activate(ComponentContext context) throws Exception { + super.activate(context); + this.bundleContext = context.getBundleContext(); + registerServlet("/schema", new SchemaGeneratorServlet(), null, null); + System.out.println("Schema generator servlet started"); + } + + protected void setSchemaGenerator(SchemaGenerator ref) { + this.schemaGenerator = ref; + } + + protected void unsetSchemaGenerator(SchemaGenerator ref) { + if (ref == this.schemaGenerator) { + this.schemaGenerator = null; + } + } + + protected void setLocationService(WsLocationAdmin ref) { + this.locationService = ref; + } + + protected void unsetLocationService(WsLocationAdmin ref) { + if (ref == this.locationService) { + this.locationService = null; + } + } + + class SchemaGeneratorServlet extends HttpServlet { + private static final long serialVersionUID = 1L; + + @Override + public void doGet(HttpServletRequest rq, HttpServletResponse rsp) throws IOException { + Bundle[] bundles = bundleContext.getBundles(); + + SchemaGeneratorOptions options = new SchemaGeneratorOptions(); + options.setEncoding("UTF-8"); + options.setBundles(bundles); + + if ("file".equals(rq.getParameter("output"))) { + // generate schema and output it to a file + WsResource resource = locationService.resolveResource("${server.config.dir}/schema.xsd"); + Writer writer = new OutputStreamWriter(resource.putStream(), "UTF-8"); + PrintWriter pw = rsp.getWriter(); + try { + schemaGenerator.generate(writer, options); + + // Generation didn't die, woohoo! + rsp.setContentType("text/plain"); + pw.println("OK. Wrote: " + resource.toExternalURI()); + } catch (Throwable t) { + System.err.println("Exception " + t); + t.printStackTrace(); + pw.println("ERROR. Exception occurred: " + t.toString()); + } finally { + writer.close(); + pw.close(); + } + } else { + // generate schema and output it back + rsp.setContentType("text/xml"); + rsp.setCharacterEncoding("UTF-8"); + PrintWriter pw = rsp.getWriter(); + schemaGenerator.generate(pw, options); + } + } + } + +} diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/schema/TestRunner.java b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/schema/TestRunner.java new file mode 100755 index 00000000000..4bc24906d36 --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt-bundle/src/test/server/schema/TestRunner.java @@ -0,0 +1,115 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011 + * + * The source code for this program is not published or otherwise divested of + * its trade secrets, irrespective of what has been deposited with the U.S. + * Copyright Office. + */ +package test.server.schema; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.PrintWriter; + +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.xml.XMLConstants; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamSource; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; + +import org.osgi.framework.BundleContext; +import org.osgi.service.component.ComponentContext; +import org.w3c.dom.Document; + +import test.server.BaseHttpTest; + +import com.ibm.websphere.metatype.SchemaGenerator; +import com.ibm.websphere.metatype.SchemaGeneratorOptions; +import com.ibm.wsspi.kernel.service.location.WsLocationAdmin; +import com.ibm.wsspi.kernel.service.location.WsLocationConstants; +import com.ibm.wsspi.kernel.service.location.WsResource; + +public class TestRunner extends BaseHttpTest { + + private BundleContext bundleContext; + private SchemaGenerator schemaGenerator; + private WsLocationAdmin locationService; + + @Override + protected void activate(ComponentContext context) throws Exception { + super.activate(context); + + bundleContext = context.getBundleContext(); + + registerServlet("/schema-test", new TestVerifierServlet(), null, null); + } + + protected void setSchemaGenerator(SchemaGenerator ref) { + this.schemaGenerator = ref; + } + + protected void unsetSchemaGenerator(SchemaGenerator ref) { + if (ref == this.schemaGenerator) { + this.schemaGenerator = null; + } + } + + protected void setLocationService(WsLocationAdmin ref) { + this.locationService = ref; + } + + protected void unsetLocationService(WsLocationAdmin ref) { + if (ref == this.locationService) { + this.locationService = null; + } + } + + class TestVerifierServlet extends HttpServlet { + private static final long serialVersionUID = 1L; + + @Override + public void doGet(HttpServletRequest rq, HttpServletResponse rsp) throws IOException { + PrintWriter pw = rsp.getWriter(); + rsp.setContentType("text/plain"); + + try { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + SchemaGeneratorOptions options = new SchemaGeneratorOptions(); + options.setEncoding("UTF-8"); + options.setBundles(bundleContext.getBundles()); + schemaGenerator.generate(out, options); + out.flush(); + + SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); + Schema schema = schemaFactory.newSchema(new StreamSource(new ByteArrayInputStream(out.toByteArray()))); + + DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance(); + domFactory.setNamespaceAware(true); + DocumentBuilder domBuilder = domFactory.newDocumentBuilder(); + + WsResource resource = locationService.resolveResource(WsLocationConstants.SYMBOL_SERVER_CONFIG_DIR + "test.xml"); + + Document document = domBuilder.parse(resource.get()); + + schema.newValidator().validate(new DOMSource(document)); + + pw.println("OK"); + } catch (Exception e) { + pw.println("FAILED"); + e.printStackTrace(pw); + } + } + + } + +} diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt/src/com/ibm/ws/config/bvt/FeatureListMBeanTest.java b/dev/com.ibm.ws.config_bvt.schema/bvt/src/com/ibm/ws/config/bvt/FeatureListMBeanTest.java new file mode 100755 index 00000000000..f4e67ebccb1 --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt/src/com/ibm/ws/config/bvt/FeatureListMBeanTest.java @@ -0,0 +1,149 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2014 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.config.bvt; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.security.SecureRandom; +import java.security.cert.X509Certificate; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +import javax.management.MBeanServerConnection; +import javax.management.ObjectName; +import javax.management.remote.JMXConnector; +import javax.management.remote.JMXConnectorFactory; +import javax.management.remote.JMXServiceURL; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSession; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; + +import org.junit.BeforeClass; +import org.junit.Test; + +import test.common.SharedLocationManager; + +import com.ibm.websphere.config.mbeans.FeatureListMBean; +import com.ibm.websphere.filetransfer.FileTransferMBean; +import com.ibm.websphere.simplicity.log.Log; +import com.ibm.ws.jmx.connector.client.rest.ClientProvider; +import com.ibm.wsspi.kernel.service.location.WsLocationAdmin; + +/** + * This test tests basic functionality of the com.ibm.websphere.config.mbeans.FeatureListMBean, + * i.e. whether a non-empty file is generated by the MBean + */ +public class FeatureListMBeanTest { + + private static Class logClass = FeatureListMBeanTest.class; + + private static String outputDir; + private static MBeanServerConnection connection; + private static JMXConnector jmxConnector; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + final String methodName = "setUpBeforeClass"; + Log.entering(logClass, methodName); + + String installDir = System.getProperty("install.dir"); + WsLocationAdmin locMgr = (WsLocationAdmin) SharedLocationManager.createDefaultLocations(installDir, getProfile()); + + outputDir = locMgr.resolveString("${server.output.dir}"); + Log.info(logClass, methodName, "serverRoot=" + outputDir); + + // Set up the trust store + TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() { + @Override + public X509Certificate[] getAcceptedIssuers() { + return null; + } + + @Override + public void checkClientTrusted(X509Certificate[] certs, String authType) {} + + @Override + public void checkServerTrusted(X509Certificate[] certs, String authType) {} + } }; + + SSLContext sc = SSLContext.getInstance("SSL"); + sc.init(null, trustAllCerts, new SecureRandom()); + HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); + HostnameVerifier hv = new HostnameVerifier() { + @Override + public boolean verify(String urlHostName, SSLSession session) { + return true; + } + }; + HttpsURLConnection.setDefaultHostnameVerifier(hv); + + Map environment = new HashMap(); + environment.put("jmx.remote.protocol.provider.pkgs", "com.ibm.ws.jmx.connector.client"); + environment.put(JMXConnector.CREDENTIALS, new String[] { "theUser", "thePassword" }); + environment.put(ClientProvider.DISABLE_HOSTNAME_VERIFICATION, true); + environment.put(ClientProvider.READ_TIMEOUT, 2 * 60 * 1000); + JMXServiceURL url = new JMXServiceURL("REST", "localhost", getSSLPort(), "/IBMJMXConnectorREST"); + Log.info(logClass, methodName, "JMXServiceURL: " + url); + jmxConnector = JMXConnectorFactory.connect(url, environment); + connection = jmxConnector.getMBeanServerConnection(); + assertNotNull("MBeanServerConnection should not be null", connection); + } + + @Test + public void testFeatureListMBean() throws Exception { + String methodName = "testFeatureListMBean"; + Log.entering(logClass, methodName); + + //Invoke feature list generation + ObjectName name = new ObjectName(FeatureListMBean.OBJECT_NAME); + String[] signature = new String[] { "java.lang.String", "java.lang.String", "java.lang.String" }; + Object[] params = new String[] { "UTF-8", Locale.getDefault().toString(), null }; + @SuppressWarnings("unchecked") + Map returnedMap = (Map) connection.invoke(name, "generate", params, signature); + Log.info(logClass, methodName, returnedMap.toString()); + Log.info(logClass, methodName, "Return code from Returned Map should not be 0: " + returnedMap.get(FeatureListMBean.KEY_RETURN_CODE)); + + //Check return code + assertTrue("Return code is not 0", (Integer) returnedMap.get(FeatureListMBean.KEY_RETURN_CODE) == 0); + + //Download generated file + String sourcePath = (String) returnedMap.get(FeatureListMBean.KEY_FILE_PATH); + String targetPath = outputDir + "/download_target/featurelist.xml"; + Log.info(logClass, methodName, "sourcePath: " + sourcePath + "targetPath " + targetPath); + + signature = new String[] { "java.lang.String", "java.lang.String" }; + params = new Object[] { sourcePath, targetPath }; + ObjectName objName = new ObjectName(FileTransferMBean.OBJECT_NAME); + connection.invoke(objName, "downloadFile", params, signature); + + //Check that file is not empty + File file = new File(targetPath); + Log.info(logClass, methodName, "Returned file (targetPath): " + file.length()); + assertTrue("Returned file is empty", file.length() > 0); + Log.exiting(logClass, methodName); + } + + private static int getSSLPort() { + return Integer.valueOf(System.getProperty("HTTP_default.secure", "8020")); + } + + private static String getProfile() { + return System.getProperty("profile", "com.ibm.ws.config.bvt.schema"); + + } +} diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt/src/com/ibm/ws/config/bvt/SchemaMBeanTest.java b/dev/com.ibm.ws.config_bvt.schema/bvt/src/com/ibm/ws/config/bvt/SchemaMBeanTest.java new file mode 100755 index 00000000000..ca159601a55 --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt/src/com/ibm/ws/config/bvt/SchemaMBeanTest.java @@ -0,0 +1,156 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2014 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.config.bvt; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.security.SecureRandom; +import java.security.cert.X509Certificate; +import java.util.HashMap; +import java.util.Map; + +import javax.management.MBeanServerConnection; +import javax.management.ObjectName; +import javax.management.remote.JMXConnector; +import javax.management.remote.JMXConnectorFactory; +import javax.management.remote.JMXServiceURL; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSession; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; + +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestRule; + +import test.common.SharedLocationManager; +import test.common.SharedOutputManager; + +import com.ibm.websphere.config.mbeans.FeatureListMBean; +import com.ibm.websphere.config.mbeans.ServerSchemaGenerator; +import com.ibm.websphere.filetransfer.FileTransferMBean; +import com.ibm.websphere.simplicity.log.Log; +import com.ibm.ws.jmx.connector.client.rest.ClientProvider; +import com.ibm.wsspi.kernel.service.location.WsLocationAdmin; + +/** + * + */ +public class SchemaMBeanTest { + + private static Class logClass = SchemaMBeanTest.class; + + private static String outputDir; + private static MBeanServerConnection connection; + private static JMXConnector jmxConnector; + private static SharedOutputManager outputMgr = SharedOutputManager.getInstance(); + + @Rule + public TestRule managerRule = outputMgr; + + @BeforeClass + public static void setUp() throws Exception { + final String methodName = "setUp"; + Log.entering(logClass, methodName); + + String installDir = System.getProperty("install.dir"); + WsLocationAdmin locMgr = (WsLocationAdmin) SharedLocationManager.createDefaultLocations(installDir, getProfile()); + + outputDir = locMgr.resolveString("${server.output.dir}"); + Log.info(logClass, methodName, "serverRoot=" + outputDir); + + // Set up the trust store + TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() { + @Override + public X509Certificate[] getAcceptedIssuers() { + return null; + } + + @Override + public void checkClientTrusted(X509Certificate[] certs, String authType) {} + + @Override + public void checkServerTrusted(X509Certificate[] certs, String authType) {} + } }; + + SSLContext sc = SSLContext.getInstance("SSL"); + sc.init(null, trustAllCerts, new SecureRandom()); + HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); + HostnameVerifier hv = new HostnameVerifier() { + @Override + public boolean verify(String urlHostName, SSLSession session) { + return true; + } + }; + HttpsURLConnection.setDefaultHostnameVerifier(hv); + + Map environment = new HashMap(); + environment.put("jmx.remote.protocol.provider.pkgs", "com.ibm.ws.jmx.connector.client"); + environment.put(JMXConnector.CREDENTIALS, new String[] { "theUser", "thePassword" }); + environment.put(ClientProvider.DISABLE_HOSTNAME_VERIFICATION, true); + environment.put(ClientProvider.READ_TIMEOUT, 2 * 60 * 1000); + JMXServiceURL url = new JMXServiceURL("REST", "localhost", getSSLPort(), "/IBMJMXConnectorREST"); + Log.info(logClass, methodName, "JMXServiceURL: " + url); + jmxConnector = JMXConnectorFactory.connect(url, environment); + connection = jmxConnector.getMBeanServerConnection(); + assertNotNull("MBeanServerConnection should not be null", connection); + } + + @Test + public void testSchemaMBean() throws Exception { + String methodName = "testSchemaMBean"; + Log.entering(logClass, methodName); + + //Invoke schema generation + ObjectName name = new ObjectName(ServerSchemaGenerator.OBJECT_NAME); + String[] signature = new String[] { "java.lang.String", "java.lang.String", "java.lang.String", "java.lang.String" }; + Object[] params = new String[] { null, null, null, null }; + @SuppressWarnings("unchecked") + Map returnedMap = (Map) connection.invoke(name, "generateInstallSchema", params, signature); + Log.info(logClass, methodName, returnedMap.toString()); + Log.info(logClass, methodName, "Return code from Returned Map should not be 0: " + returnedMap.get(FeatureListMBean.KEY_RETURN_CODE)); + + //Check return code + assertTrue((Integer) returnedMap.get(ServerSchemaGenerator.KEY_RETURN_CODE) == 0); + + //Download generated file + String sourcePath = (String) returnedMap.get(ServerSchemaGenerator.KEY_FILE_PATH); + String targetPath = outputDir + "/download_target/schema.xsd"; + Log.info(logClass, methodName, "sourcePath: " + sourcePath + "targetPath " + targetPath); + + signature = new String[] { "java.lang.String", "java.lang.String" }; + params = new Object[] { sourcePath, targetPath }; + ObjectName objName = new ObjectName(FileTransferMBean.OBJECT_NAME); + connection.invoke(objName, "downloadFile", params, signature); + + //Ensure the file is bigger than 1 MB + File file = new File(targetPath); + Log.info(logClass, methodName, "Returned file (targetPath): " + file.length()); + assertTrue("Returned file is empty", file.length() > 1000000); + Log.exiting(logClass, methodName); + } + + private static int getSSLPort() { + return Integer.valueOf(System.getProperty("HTTP_default.secure", "8020")); + } + + private static String getProfile() { + return System.getProperty("profile", "com.ibm.ws.config.bvt.schema"); + + } + +} diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt/src/com/ibm/ws/config/bvt/SchemaTest.java b/dev/com.ibm.ws.config_bvt.schema/bvt/src/com/ibm/ws/config/bvt/SchemaTest.java new file mode 100755 index 00000000000..36fde20df4c --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt/src/com/ibm/ws/config/bvt/SchemaTest.java @@ -0,0 +1,68 @@ +package com.ibm.ws.config.bvt; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestRule; + +import test.common.SharedOutputManager; + +public class SchemaTest { + + private static SharedOutputManager outputMgr = SharedOutputManager.getInstance(); + + @Rule + public TestRule outputRule = outputMgr; + + private String getPort() { + return System.getProperty("HTTP_default", "8000"); + } + + private String read(InputStream in) throws IOException { + InputStreamReader isr = new InputStreamReader(in); + BufferedReader br = new BufferedReader(isr); + StringBuilder builder = new StringBuilder(); + String line; + while ((line = br.readLine()) != null) { + builder.append(line); + builder.append(System.getProperty("line.separator")); + } + return builder.toString(); + } + + @Test + public void testSchemaGeneratorAll() throws Exception { + test("/schema?output=file", "testSchemaGeneratorAll"); + } + + private void test(String testUri, String testName) throws Exception { + HttpURLConnection con = null; + try { + URL url = new URL("http://localhost:" + getPort() + testUri); + con = (HttpURLConnection) url.openConnection(); + con.setDoInput(true); + con.setDoOutput(true); + con.setUseCaches(false); + con.setRequestMethod("GET"); + InputStream is = con.getInputStream(); + assertNotNull(is); + + String output = read(is); + System.out.println(output); + assertTrue("Response should start with OK", output.trim().startsWith("OK")); + } finally { + if (con != null) { + con.disconnect(); + } + } + } +} diff --git a/dev/com.ibm.ws.config_bvt.schema/bvt/src/com/ibm/ws/config/bvt/ServerXMLConfigurationMBeanTest.java b/dev/com.ibm.ws.config_bvt.schema/bvt/src/com/ibm/ws/config/bvt/ServerXMLConfigurationMBeanTest.java new file mode 100755 index 00000000000..e4233b9f935 --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/bvt/src/com/ibm/ws/config/bvt/ServerXMLConfigurationMBeanTest.java @@ -0,0 +1,113 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2014 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.config.bvt; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import javax.management.MBeanServerConnection; +import javax.management.ObjectName; +import javax.management.remote.JMXConnector; +import javax.management.remote.JMXConnectorFactory; +import javax.management.remote.JMXServiceURL; + +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestRule; + +import test.common.SharedLocationManager; +import test.common.SharedOutputManager; + +import com.ibm.websphere.config.mbeans.ServerXMLConfigurationMBean; +import com.ibm.websphere.filetransfer.FileTransferMBean; +import com.ibm.ws.jmx.connector.client.rest.ClientProvider; +import com.ibm.wsspi.kernel.service.location.WsLocationAdmin; + +/** + * This test tests the basic functionality of the com.ibm.websphere.config.mbeans.ServerXMLConfigurationMBean. + * It verifies that fetchConfigurationFilePaths() returns the expected collection of file paths and then checks + * that the files can be downloaded using the FileTransferMBean from those paths. + */ +public class ServerXMLConfigurationMBeanTest { + + private static String outputDir; + private static MBeanServerConnection connection; + private static JMXConnector jmxConnector; + private static SharedOutputManager outputMgr = SharedOutputManager.getInstance(); + + @Rule + public TestRule managerRule = outputMgr; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + String installDir = System.getProperty("install.dir"); + WsLocationAdmin locMgr = (WsLocationAdmin) SharedLocationManager.createDefaultLocations(installDir, getProfile()); + + outputDir = locMgr.resolveString("${server.output.dir}"); + + // Set up the trust store + System.setProperty("javax.net.ssl.trustStore", outputDir + "/resources/security/key.jks"); + System.setProperty("javax.net.ssl.trustStorePassword", "Liberty"); + + Map environment = new HashMap(); + environment.put("jmx.remote.protocol.provider.pkgs", "com.ibm.ws.jmx.connector.client"); + environment.put(JMXConnector.CREDENTIALS, new String[] { "theUser", "thePassword" }); + environment.put(ClientProvider.DISABLE_HOSTNAME_VERIFICATION, true); + environment.put(ClientProvider.READ_TIMEOUT, 2 * 60 * 1000); + JMXServiceURL url = new JMXServiceURL("REST", "localhost", getSSLPort(), "/IBMJMXConnectorREST"); + jmxConnector = JMXConnectorFactory.connect(url, environment); + connection = jmxConnector.getMBeanServerConnection(); + } + + @Test + public void testServerXMLConfigurationMBean() throws Exception { + ObjectName name = new ObjectName(ServerXMLConfigurationMBean.OBJECT_NAME); + @SuppressWarnings("unchecked") + Collection configFilePaths = (Collection) connection.invoke(name, "fetchConfigurationFilePaths", new Object[] {}, new String[] {}); + + // Check that the collection contains the expected file paths. + assertEquals("Config file path collection size is not 2.", 2, configFilePaths.size()); + assertTrue("server.xml is missing from the collection.", + configFilePaths.contains("${server.config.dir}/server.xml")); + assertTrue("bvtTestPorts.xml is missing from the collection.", + configFilePaths.contains("${shared.config.dir}/bvtTestPorts.xml")); + + // Download configuration files. + for (String sourcePath : configFilePaths) { + String targetPath = outputDir + "/download_target/" + + sourcePath.substring(sourcePath.lastIndexOf('/') + 1); + + String[] signature = new String[] { "java.lang.String", "java.lang.String" }; + Object[] params = new Object[] { sourcePath, targetPath }; + ObjectName objName = new ObjectName(FileTransferMBean.OBJECT_NAME); + connection.invoke(objName, "downloadFile", params, signature); + + // Check that file is not empty + File file = new File(targetPath); + assertTrue("Returned file is empty", file.length() > 0); + } + } + + private static int getSSLPort() { + return Integer.valueOf(System.getProperty("HTTP_default.secure", "8020")); + } + + private static String getProfile() { + return System.getProperty("profile", "com.ibm.ws.config.bvt.schema"); + } +} diff --git a/dev/com.ibm.ws.config_bvt.schema/delivery.sets b/dev/com.ibm.ws.config_bvt.schema/delivery.sets new file mode 100755 index 00000000000..9a2dcf02d11 --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/delivery.sets @@ -0,0 +1 @@ +SLE \ No newline at end of file diff --git a/dev/com.ibm.ws.config_bvt.schema/osgitck-bvt.xml.disabled b/dev/com.ibm.ws.config_bvt.schema/osgitck-bvt.xml.disabled new file mode 100755 index 00000000000..f73b8e4b4fa --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/osgitck-bvt.xml.disabled @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/dev/com.ibm.ws.config_bvt.schema/publish/features/testschema-1.0.mf b/dev/com.ibm.ws.config_bvt.schema/publish/features/testschema-1.0.mf new file mode 100755 index 00000000000..dffbf68043b --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/publish/features/testschema-1.0.mf @@ -0,0 +1,7 @@ +Subsystem-ManifestVersion: 1 +IBM-ShortName:testschema-1.0 +Subsystem-SymbolicName: testschema-1.0; visibility:=public +Subsystem-Version: 1.0.0 +Subsystem-Content: test.server.schema; version="[1,1.0.100)" +Subsystem-Type: osgi.subsystem.feature +IBM-Feature-Version: 2 diff --git a/dev/com.ibm.ws.config_bvt.schema/publish/servers/com.ibm.ws.config.bvt.schema/.gitignore b/dev/com.ibm.ws.config_bvt.schema/publish/servers/com.ibm.ws.config.bvt.schema/.gitignore new file mode 100644 index 00000000000..7f52d8f632f --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/publish/servers/com.ibm.ws.config.bvt.schema/.gitignore @@ -0,0 +1 @@ +/download_target diff --git a/dev/com.ibm.ws.config_bvt.schema/publish/servers/com.ibm.ws.config.bvt.schema/bootstrap.properties b/dev/com.ibm.ws.config_bvt.schema/publish/servers/com.ibm.ws.config.bvt.schema/bootstrap.properties new file mode 100755 index 00000000000..dee20e162ff --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/publish/servers/com.ibm.ws.config.bvt.schema/bootstrap.properties @@ -0,0 +1,4 @@ +com.ibm.ws.logging.trace.specification=*=event=enabled:config=all=enabled +com.ibm.ws.logging.max.file.size=0 + +bootstrap.include=../testports.properties diff --git a/dev/com.ibm.ws.config_bvt.schema/publish/servers/com.ibm.ws.config.bvt.schema/jvm.options b/dev/com.ibm.ws.config_bvt.schema/publish/servers/com.ibm.ws.config.bvt.schema/jvm.options new file mode 100755 index 00000000000..32354345ade --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/publish/servers/com.ibm.ws.config.bvt.schema/jvm.options @@ -0,0 +1 @@ +-Xmx256M \ No newline at end of file diff --git a/dev/com.ibm.ws.config_bvt.schema/publish/servers/com.ibm.ws.config.bvt.schema/server.xml b/dev/com.ibm.ws.config_bvt.schema/publish/servers/com.ibm.ws.config.bvt.schema/server.xml new file mode 100755 index 00000000000..d55c4a4e967 --- /dev/null +++ b/dev/com.ibm.ws.config_bvt.schema/publish/servers/com.ibm.ws.config.bvt.schema/server.xml @@ -0,0 +1,15 @@ + + + + + + httpservice-2.2 + testschema-1.0 + restConnector-1.0 + + + + + + + diff --git a/dev/com.ibm.ws.config_fat/.classpath b/dev/com.ibm.ws.config_fat/.classpath new file mode 100644 index 00000000000..c422489df40 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/dev/com.ibm.ws.config_fat/.classpath.gradle b/dev/com.ibm.ws.config_fat/.classpath.gradle new file mode 100644 index 00000000000..c422489df40 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/.classpath.gradle @@ -0,0 +1,7 @@ + + + + + + + diff --git a/dev/com.ibm.ws.config_fat/.gitignore b/dev/com.ibm.ws.config_fat/.gitignore new file mode 100644 index 00000000000..27e131e35a6 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/.gitignore @@ -0,0 +1 @@ +/bootstrapping.properties diff --git a/dev/com.ibm.ws.config_fat/.project b/dev/com.ibm.ws.config_fat/.project new file mode 100755 index 00000000000..c33ca1c04e7 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/.project @@ -0,0 +1,23 @@ + + + com.ibm.ws.config_fat + + + + + + org.eclipse.jdt.core.javabuilder + + + + + bndtools.core.bndbuilder + + + + + + org.eclipse.jdt.core.javanature + bndtools.core.bndnature + + diff --git a/dev/com.ibm.ws.config_fat/.settings/org.eclipse.core.resources.prefs b/dev/com.ibm.ws.config_fat/.settings/org.eclipse.core.resources.prefs new file mode 100755 index 00000000000..25d9425fe34 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,4 @@ +#Ant properties +#Automatically generated by the ant prepare.settings.files task +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/dev/com.ibm.ws.config_fat/.settings/org.eclipse.jdt.core.prefs b/dev/com.ibm.ws.config_fat/.settings/org.eclipse.jdt.core.prefs new file mode 100755 index 00000000000..f48ecd6cc60 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,280 @@ +#Ant properties +#Automatically generated by the ant prepare.settings.files task +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.6 +org.eclipse.jdt.core.formatter.align_type_members_on_columns=false +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=0 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=18 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=2 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=2 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=18 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=2 +org.eclipse.jdt.core.formatter.alignment_for_assignment=0 +org.eclipse.jdt.core.formatter.alignment_for_binary_expression=18 +org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=0 +org.eclipse.jdt.core.formatter.alignment_for_enum_constants=16 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=18 +org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=18 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=18 +org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=0 +org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=20 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=4 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +org.eclipse.jdt.core.formatter.blank_lines_before_field=0 +org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 +org.eclipse.jdt.core.formatter.blank_lines_before_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 +org.eclipse.jdt.core.formatter.blank_lines_before_package=0 +org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 +org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 +org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false +org.eclipse.jdt.core.formatter.comment.format_block_comments=true +org.eclipse.jdt.core.formatter.comment.format_header=false +org.eclipse.jdt.core.formatter.comment.format_html=false +org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true +org.eclipse.jdt.core.formatter.comment.format_line_comments=false +org.eclipse.jdt.core.formatter.comment.format_source_code=true +org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true +org.eclipse.jdt.core.formatter.comment.indent_root_tags=true +org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert +org.eclipse.jdt.core.formatter.comment.line_length=180 +org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true +org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true +org.eclipse.jdt.core.formatter.compact_else_if=true +org.eclipse.jdt.core.formatter.continuation_indentation=4 +org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=4 +org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off +org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on +org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false +org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=false +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true +org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_empty_lines=false +org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true +org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true +org.eclipse.jdt.core.formatter.indentation.size=8 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert +org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.join_lines_in_comments=false +org.eclipse.jdt.core.formatter.join_wrapped_lines=false +org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false +org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false +org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false +org.eclipse.jdt.core.formatter.lineSplit=180 +org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=true +org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=true +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 +org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=false +org.eclipse.jdt.core.formatter.tabulation.char=space +org.eclipse.jdt.core.formatter.tabulation.size=4 +org.eclipse.jdt.core.formatter.use_on_off_tags=true +org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false +org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true +org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true diff --git a/dev/com.ibm.ws.config_fat/.settings/org.eclipse.jdt.ui.prefs b/dev/com.ibm.ws.config_fat/.settings/org.eclipse.jdt.ui.prefs new file mode 100755 index 00000000000..c92277a371a --- /dev/null +++ b/dev/com.ibm.ws.config_fat/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,62 @@ +#Ant properties +#Automatically generated by the ant prepare.settings.files task +eclipse.preferences.version=1 +editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true +org.eclipse.jdt.ui.ignorelowercasenames=true +org.eclipse.jdt.ui.importorder=java;javax;org;com; +org.eclipse.jdt.ui.javadoc=true +org.eclipse.jdt.ui.ondemandthreshold=99 +org.eclipse.jdt.ui.staticondemandthreshold=99 +org.eclipse.jdt.ui.text.custom_code_templates= +sp_cleanup.add_default_serial_version_id=true +sp_cleanup.add_generated_serial_version_id=false +sp_cleanup.add_missing_annotations=true +sp_cleanup.add_missing_deprecated_annotations=true +sp_cleanup.add_missing_methods=false +sp_cleanup.add_missing_nls_tags=false +sp_cleanup.add_missing_override_annotations=true +sp_cleanup.add_missing_override_annotations_interface_methods=true +sp_cleanup.add_serial_version_id=false +sp_cleanup.always_use_blocks=true +sp_cleanup.always_use_parentheses_in_expressions=false +sp_cleanup.always_use_this_for_non_static_field_access=false +sp_cleanup.always_use_this_for_non_static_method_access=false +sp_cleanup.convert_to_enhanced_for_loop=false +sp_cleanup.correct_indentation=false +sp_cleanup.format_source_code=true +sp_cleanup.format_source_code_changes_only=false +sp_cleanup.make_local_variable_final=false +sp_cleanup.make_parameters_final=false +sp_cleanup.make_private_fields_final=true +sp_cleanup.make_type_abstract_if_missing_method=false +sp_cleanup.make_variable_declarations_final=true +sp_cleanup.never_use_blocks=false +sp_cleanup.never_use_parentheses_in_expressions=true +sp_cleanup.on_save_use_additional_actions=true +sp_cleanup.organize_imports=true +sp_cleanup.qualify_static_field_accesses_with_declaring_class=false +sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_with_declaring_class=false +sp_cleanup.qualify_static_method_accesses_with_declaring_class=false +sp_cleanup.remove_private_constructors=true +sp_cleanup.remove_trailing_whitespaces=true +sp_cleanup.remove_trailing_whitespaces_all=true +sp_cleanup.remove_trailing_whitespaces_ignore_empty=false +sp_cleanup.remove_unnecessary_casts=true +sp_cleanup.remove_unnecessary_nls_tags=true +sp_cleanup.remove_unused_imports=true +sp_cleanup.remove_unused_local_variables=false +sp_cleanup.remove_unused_private_fields=true +sp_cleanup.remove_unused_private_members=false +sp_cleanup.remove_unused_private_methods=true +sp_cleanup.remove_unused_private_types=true +sp_cleanup.sort_members=false +sp_cleanup.sort_members_all=false +sp_cleanup.use_blocks=false +sp_cleanup.use_blocks_only_for_return_and_throw=false +sp_cleanup.use_parentheses_in_expressions=false +sp_cleanup.use_this_for_non_static_field_access=false +sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true +sp_cleanup.use_this_for_non_static_method_access=false +sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true diff --git a/dev/com.ibm.ws.config_fat/bnd.bnd b/dev/com.ibm.ws.config_fat/bnd.bnd new file mode 100644 index 00000000000..abe08945c20 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/bnd.bnd @@ -0,0 +1,14 @@ +-include= ~../cnf/resources/bnd/bundle.props +bVersion=1.0 + +src: \ + fat/src + +-buildpath: \ + ${javac.bootclasspath.java6}, \ + ../build.sharedResources/lib/junit/old/junit.jar;version=file, \ + fattest.simplicity;version=latest, \ + ../fattest.simplicity/lib/public.api.jar;version=file, \ + com.ibm.websphere.filetransfer;version=latest, \ + com.ibm.ws.jmx.connector.client.rest;version=latest, \ + com.ibm.ws.config;version=latest diff --git a/dev/com.ibm.ws.config_fat/bnd.bnd.gradle b/dev/com.ibm.ws.config_fat/bnd.bnd.gradle new file mode 100644 index 00000000000..abe08945c20 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/bnd.bnd.gradle @@ -0,0 +1,14 @@ +-include= ~../cnf/resources/bnd/bundle.props +bVersion=1.0 + +src: \ + fat/src + +-buildpath: \ + ${javac.bootclasspath.java6}, \ + ../build.sharedResources/lib/junit/old/junit.jar;version=file, \ + fattest.simplicity;version=latest, \ + ../fattest.simplicity/lib/public.api.jar;version=file, \ + com.ibm.websphere.filetransfer;version=latest, \ + com.ibm.ws.jmx.connector.client.rest;version=latest, \ + com.ibm.ws.config;version=latest diff --git a/dev/com.ibm.ws.config_fat/build-test.xml b/dev/com.ibm.ws.config_fat/build-test.xml new file mode 100755 index 00000000000..d42ad757442 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/build-test.xml @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/com.ibm.ws.config_fat/build.gradle b/dev/com.ibm.ws.config_fat/build.gradle new file mode 100644 index 00000000000..e69de29bb2d diff --git a/dev/com.ibm.ws.config_fat/delivery.sets b/dev/com.ibm.ws.config_fat/delivery.sets new file mode 100755 index 00000000000..674398425a0 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/delivery.sets @@ -0,0 +1 @@ +SLE diff --git a/dev/com.ibm.ws.config_fat/fat/src/test/server/config/BadConfigTests.java b/dev/com.ibm.ws.config_fat/fat/src/test/server/config/BadConfigTests.java new file mode 100755 index 00000000000..05ffbca817e --- /dev/null +++ b/dev/com.ibm.ws.config_fat/fat/src/test/server/config/BadConfigTests.java @@ -0,0 +1,124 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package test.server.config; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import java.util.List; + +import org.junit.Test; + +import componenttest.annotation.ExpectedFFDC; +import componenttest.topology.impl.LibertyServer; +import componenttest.topology.impl.LibertyServerFactory; + +/** + * + */ +public class BadConfigTests { + + @Test + public void testBadPortConfig() throws Exception { + LibertyServer server = LibertyServerFactory.getLibertyServer("com.ibm.ws.config.bad"); + server.startServer("badconfig.log"); + + try { + // Start the server with bad configuration + assertNotNull("There should be an error during server start", server.waitForStringInLog("CWWKG0075E.*missingbvt.prop.HTTP_default.*")); + assertNotNull("The server should start", server.waitForStringInLog("CWWKF0011I.*")); + assertNull("There should not be a cached instance used", server.waitForStringInLog("CWWKG0076W", 1000)); + + // Update the configuration to good values + server.setMarkToEndOfLog(); + server.setServerConfigurationFile("badconfig/goodConfig.xml"); + + assertNotNull("The config should be updated", server.waitForStringInLogUsingMark("CWWKG0017I.*")); + assertNull("There should not be a validation error", server.waitForStringInLogUsingMark("CWWKG0075E", 1000)); + + // Update at runtime to an invalid configuration. The cached values should still be used + server.setMarkToEndOfLog(); + server.setServerConfigurationFile("badconfig/badHttp.xml"); + + assertNotNull("There should be an error during server start", server.waitForStringInLogUsingMark("CWWKG0075E.*missingbvt.prop.HTTP_default.*")); + assertNotNull("There should be a cached instance used", server.waitForStringInLogUsingMark("CWWKG0076W")); + assertNotNull("The config should be updated", server.waitForStringInLogUsingMark("CWWKG0017I.*")); + + // Update a singleton () at runtime. The cached values should still be used + server.setMarkToEndOfLog(); + server.setServerConfigurationFile("badconfig/badLogging.xml"); + + assertNotNull("There should be a warning during server start", server.waitForStringInLogUsingMark("CWWKG0083W.*maxFiles.*-1.*2.*")); + assertNotNull("The config should be updated", server.waitForStringInLogUsingMark("CWWKG0017I.*")); + + } finally { + server.stopServer(); + } + + } + + @Test + public void testUniqueValueConflictConfig() throws Exception { + + LibertyServer server = LibertyServerFactory.getLibertyServer("com.ibm.ws.config.uniquevalueconflict"); + server.startServer("uniquevalueconflict.log"); + try { + // Update the configuration to good values + server.setMarkToEndOfLog(); + server.setServerConfigurationFile("badconfig/UniqueValueConflict.xml"); + + assertNotNull(" Distinct values specified for the attribute", server.waitForStringInLogUsingMark("CWWKG0031E.*")); + assertNotNull(" ConfigUpdateException does not occur", server.waitForStringInLogUsingMark("CWWKG0074E.*")); + } + + finally { + server.stopServer(); + } + + } + + @Test + public void testInvalidOptionInJDBCConfig() throws Exception { + LibertyServer server = LibertyServerFactory.getLibertyServer("com.ibm.ws.config.invalidJDBCoption"); + server.startServer("invalidJDBCoption.log"); + + assertNotNull("The server should start", server.waitForStringInLog("CWWKF0011I.*")); + + // Clear log offsets so we can search for all warning messages + server.resetLogOffsets(); + + try { + List matches = server.findStringsInLogs("CWWKG0032W.*createDatabase.*whatever.*"); + // Start the server with invalid configuration and ensure that the warning is printed exactly once + assertEquals("There should be exactly one (1) warning for createDatabase", 1, matches.size()); + } finally { + server.stopServer(); + } + + } + + @Test + @ExpectedFFDC("java.net.MalformedURLException") + public void testInvalidOptionalInclude() throws Exception { + LibertyServer server = LibertyServerFactory.getLibertyServer("com.ibm.ws.config.invalidOptionalInclude"); + server.startServer("invalidOptionalInclude.log"); + + try { + // Start the server, skipping the optional include with a bad protocol - ensure warning message is printed + assertNotNull("There should be an error during server start", server.waitForStringInLog("CWWKG0084W.*bogus.*")); + } finally { + server.stopServer(); + } + + } +} diff --git a/dev/com.ibm.ws.config_fat/fat/src/test/server/config/ChildAliasTest.java b/dev/com.ibm.ws.config_fat/fat/src/test/server/config/ChildAliasTest.java new file mode 100755 index 00000000000..c518137022b --- /dev/null +++ b/dev/com.ibm.ws.config_fat/fat/src/test/server/config/ChildAliasTest.java @@ -0,0 +1,236 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012, 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package test.server.config; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; + +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestName; + +import componenttest.topology.impl.LibertyServer; +import componenttest.topology.impl.LibertyServerFactory; + +public class ChildAliasTest { + + /** + * Utility to set the method name as a String before the test + */ + @Rule + public TestName name = new TestName(); + + public String testName = ""; + + @Before + public void setTestName() { + // set the current test name + testName = name.getMethodName(); + } + + private static final String CONTEXT_ROOT = "/childalias"; + + private static LibertyServer testServer = LibertyServerFactory.getLibertyServer("com.ibm.ws.config.childalias"); + + @BeforeClass + public static void setUpForConfigExtensionsTests() throws Exception { + //copy the extensions tests features into the server features location + testServer.copyFileToLibertyInstallRoot("lib/features", "internalFeatureForFat/childAliasTest-1.0.mf"); + testServer.copyFileToLibertyInstallRoot("lib/features", "internalFeatureForFat/childAliasTestB-1.0.mf"); + testServer.copyFileToLibertyInstallRoot("lib/features", "internalFeatureForFat/childAliasTestC-1.0.mf"); + + // Copy the config fat internal feature + testServer.copyFileToLibertyInstallRoot("lib/features", "internalFeatureForFat/configfatlibertyinternals-1.0.mf"); + + //copy the extensions tests bundles into the server lib location + testServer.copyFileToLibertyInstallRoot("lib", "bundles/test.config.childalias_1.0.0.jar"); + testServer.copyFileToLibertyInstallRoot("lib", "bundles/test.config.childalias.b_1.0.0.jar"); + testServer.copyFileToLibertyInstallRoot("lib", "bundles/test.config.childalias.c_1.0.0.jar"); + + testServer.startServer(); + //make sure the URL is available + assertNotNull(testServer.waitForStringInLog("CWWKT0016I.*" + CONTEXT_ROOT)); + assertNotNull(testServer.waitForStringInLog("CWWKF0011I")); + } + + @AfterClass + public static void shutdown() throws Exception { + testServer.stopServer(); + testServer.deleteFileFromLibertyInstallRoot("lib/features/childAliasTest-1.0.mf"); + testServer.deleteFileFromLibertyInstallRoot("lib/features/childAliasTestB-1.0.mf"); + testServer.deleteFileFromLibertyInstallRoot("lib/features/childAliasTestC-1.0.mf"); + testServer.deleteFileFromLibertyInstallRoot("lib/test.config.childalias_1.0.0.jar"); + testServer.deleteFileFromLibertyInstallRoot("lib/test.config.childalias.b_1.0.0.jar"); + testServer.deleteFileFromLibertyInstallRoot("lib/test.config.childalias.c_1.0.0.jar"); + + testServer.deleteFileFromLibertyInstallRoot("lib/features/configfatlibertyinternals-1.0.mf"); + } + + @Test + public void testChildAlias1() throws Exception { + test(testServer); + } + + @Test + public void testChildAlias2() throws Exception { + test(testServer); + } + + @Test + public void testChildAliasSingleton1() throws Exception { + test(testServer); + } + + @Test + public void testChildAliasSingleton2() throws Exception { + test(testServer); + } + + @Test + public void testBundleOrdering1() throws Exception { + // Because this test ensures bundle ordering with config elements defined + // in different bundles, a fresh start of the server with the config is needed + // so that this test can run in any order while simulating bundle start ordering. + testServer.stopServer(); + testServer.setServerConfigurationFile("childalias/server.xml"); + testServer.startServer(); + + testServer.setMarkToEndOfLog(); + testServer.setServerConfigurationFile("childalias/serverB.xml"); + testServer.waitForConfigUpdateInLogUsingMark(null); + test(testServer); + } + + @Test + public void testBundleOrdering2() throws Exception { + // Because this test ensures bundle ordering with config elements defined + // in different bundles, a fresh start of the server with the config is needed + // so that this test can run in any order while simulating bundle start ordering. + testServer.stopServer(); + testServer.setServerConfigurationFile("childalias/serverB.xml"); + testServer.startServer(); + + testServer.setMarkToEndOfLog(); + testServer.setServerConfigurationFile("childalias/serverC.xml"); + testServer.waitForConfigUpdateInLogUsingMark(null); + test(testServer); + } + + @Test + public void testBundleOrderingAliasConflict() throws Exception { + // Because this test ensures bundle ordering with config elements defined + // in different bundles, a fresh start of the server with the config is needed + // so that this test can run in any order while simulating bundle start ordering. + testServer.stopServer(); + testServer.setServerConfigurationFile("childalias/serverB.xml"); + testServer.startServer(); + + testServer.setMarkToEndOfLog(); + testServer.setServerConfigurationFile("childalias/serverC.xml"); + testServer.waitForConfigUpdateInLogUsingMark(null); + test(testServer); + } + + @Test + public void testRemoveChild() throws Exception { + testServer.setMarkToEndOfLog(); + testServer.setServerConfigurationFile("childalias/serverC2.xml"); + testServer.waitForConfigUpdateInLogUsingMark(null); + test(testServer); + } + + @Test + public void testAddNewChild() throws Exception { + testServer.setMarkToEndOfLog(); + testServer.setServerConfigurationFile("childalias/serverC3.xml"); + testServer.waitForConfigUpdateInLogUsingMark(null); + test(testServer); + } + + @Test + public void testUpdateChild() throws Exception { + testServer.setMarkToEndOfLog(); + testServer.setServerConfigurationFile("childalias/serverC4.xml"); + testServer.waitForConfigUpdateInLogUsingMark(null); + test(testServer); + } + + @Test + public void testRemoveSingletonChild() throws Exception { + testServer.setMarkToEndOfLog(); + testServer.setServerConfigurationFile("childalias/serverC5.xml"); + testServer.waitForConfigUpdateInLogUsingMark(null); + test(testServer); + } + + @Test + public void testAddNewSingletonChild() throws Exception { + testServer.setMarkToEndOfLog(); + testServer.setServerConfigurationFile("childalias/serverC6.xml"); + testServer.waitForConfigUpdateInLogUsingMark(null); + test(testServer); + } + + @Test + public void testUpdateSingletonChild() throws Exception { + testServer.setMarkToEndOfLog(); + testServer.setServerConfigurationFile("childalias/serverC7.xml"); + testServer.waitForConfigUpdateInLogUsingMark(null); + test(testServer); + } + + private void test(LibertyServer server) throws Exception { + HttpURLConnection con = null; + try { + URL url = new URL("http://" + server.getHostname() + ":" + server.getHttpDefaultPort() + + CONTEXT_ROOT + "/child-alias-test?" + "testName=" + testName); + con = (HttpURLConnection) url.openConnection(); + con.setDoInput(true); + con.setDoOutput(true); + con.setUseCaches(false); + con.setRequestMethod("GET"); + InputStream is = con.getInputStream(); + assertNotNull(is); + + String output = read(is); + System.out.println(output); + assertTrue(output, output.trim().startsWith("OK")); + } finally { + if (con != null) { + con.disconnect(); + } + } + } + + private static String read(InputStream in) throws IOException { + InputStreamReader isr = new InputStreamReader(in); + BufferedReader br = new BufferedReader(isr); + StringBuilder builder = new StringBuilder(); + String line; + while ((line = br.readLine()) != null) { + builder.append(line); + builder.append(System.getProperty("line.separator")); + } + return builder.toString(); + } + +} diff --git a/dev/com.ibm.ws.config_fat/fat/src/test/server/config/ConfigExtensionsTest.java b/dev/com.ibm.ws.config_fat/fat/src/test/server/config/ConfigExtensionsTest.java new file mode 100755 index 00000000000..87a0274de05 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/fat/src/test/server/config/ConfigExtensionsTest.java @@ -0,0 +1,298 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012, 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package test.server.config; + +import static org.junit.Assert.assertNotNull; + +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestName; + +import componenttest.topology.impl.LibertyServer; +import componenttest.topology.impl.LibertyServerFactory; +import componenttest.topology.utils.HttpUtils; + +/** + * + */ +public class ConfigExtensionsTest { + + /** + * Utility to set the method name as a String before the test + */ + @Rule + public TestName name = new TestName(); + + public String testName = ""; + private static final String servicePidName = "service.pid"; + + @Before + public void setTestName() { + // set the current test name + testName = name.getMethodName(); + } + + private static final String CONTEXT_ROOT = "/config-extensions-test"; + private static final String PID_PASS = "PASSED: test bundle was called with properties for ID"; + private static LibertyServer extensionsServer = LibertyServerFactory.getLibertyServer("com.ibm.ws.config.extensions"); + + @BeforeClass + public static void setUpForConfigExtensionsTests() throws Exception { + //copy the extensions tests features into the server features location + extensionsServer.copyFileToLibertyInstallRoot("lib/features", "internalFeatureForFat/configExtensionsTest-1.0.mf"); + extensionsServer.copyFileToLibertyInstallRoot("lib/features", "internalFeatureForFat/configExtensionsTestB-1.0.mf"); + //copy the extensions tests bundles into the server lib location + extensionsServer.copyFileToLibertyInstallRoot("lib", "bundles/test.config.extensions_1.0.0.jar"); + extensionsServer.copyFileToLibertyInstallRoot("lib", "bundles/test.config.extensions.b_1.0.0.jar"); + extensionsServer.copyFileToLibertyInstallRoot("lib", "bundles/test.config.extensions.schema.generator_1.0.0.jar"); + + //use our default server.xml to start with + extensionsServer.setServerConfigurationFile("extensions/server.xml"); + extensionsServer.startServer(); + //make sure the URL is available + extensionsServer.waitForStringInLog("CWWKT0016I.*" + CONTEXT_ROOT); + } + + @AfterClass + public static void shutdown() throws Exception { + extensionsServer.stopServer(); + // Delete the files we copied over + extensionsServer.deleteFileFromLibertyInstallRoot("lib/features/configExtensionsTest-1.0.mf"); + extensionsServer.deleteFileFromLibertyInstallRoot("lib/features/configExtensionsTestB-1.0.mf"); + + extensionsServer.deleteFileFromLibertyInstallRoot("lib/test.config.extensions_1.0.0.jar"); + extensionsServer.deleteFileFromLibertyInstallRoot("lib/test.config.extensions.b_1.0.0.jar"); + extensionsServer.deleteFileFromLibertyInstallRoot("lib/test.config.extensions.schema.generator_1.0.0.jar"); + + } + + /** + * Tests whether the ibm:extends works at runtime. + * The test verifies that the delegating factory service registered by the ExtendedMetatypeManager + * does make a call to the factory service that is provided by the super type + */ + @Test + public void testExtendsBasic() throws Exception { + String servicePid = servicePidName + "=test.config.extensions.super"; + //verify that the MSF was called with config for the correct id as expected + //If the ID property was incorrect, the delegating listener forwarded the wrong information or was provided the wrong information by config + HttpUtils.findStringInUrl(extensionsServer, CONTEXT_ROOT + "/test?id=test.config.extensions.sub.config1&" + servicePid, PID_PASS); + } + + /** + * Tests whether the ibm:rename works at runtime. + * The test verifies that an attribute specified in the server.xml using an ibm:rename + * gets converted to the original name before being passed back to the super type. + */ + @Test + public void testExtendsRename() throws Exception { + String servicePid = servicePidName + "=test.config.extensions.super"; + //check that the renamed property came from test.config.extensions.sub configuration + //If the renamed property value was not correct, the delegating listener did not pass the value back to the original key name or did not detect the rename + HttpUtils.findStringInUrl(extensionsServer, CONTEXT_ROOT + "/test?id=test.config.extensions.sub.config1&prop=testAttribute1&" + servicePid, "renamed value"); + } + + /** + * This is the same as testExtendsBasic, but for a sub type that ibm:extends another + * sub type, so it checks that the service factory call gets delegated all the way back to the + * top of the stack. + */ + @Test + public void testExtendsHierarchy() throws Exception { + String servicePid = servicePidName + "=test.config.extensions.super"; + //check that the properties supplied for next go through the hierarchy to the top parent + HttpUtils.findStringInUrl(extensionsServer, CONTEXT_ROOT + "/test?id=test.config.extensions.sub.sub.config1&" + servicePid, PID_PASS); + + HttpUtils.findStringInUrl(extensionsServer, CONTEXT_ROOT + "/test?id=test.config.extensions.sub.sub.config1&prop=testAttribute1&" + servicePid, "rqd"); + HttpUtils.findStringInUrl(extensionsServer, CONTEXT_ROOT + "/test?id=test.config.extensions.sub.sub.config1&prop=testAttribute2&" + servicePid, "2"); + HttpUtils.findStringInUrl(extensionsServer, CONTEXT_ROOT + "/test?id=test.config.extensions.sub.sub.config1&prop=testAttr3RenameSub&" + servicePid, "3"); + HttpUtils.findStringInUrl(extensionsServer, CONTEXT_ROOT + "/test?id=test.config.extensions.sub.sub.config1&prop=testAttribute4&" + servicePid, "four"); + } + + /** + * This tests the error scenario where someone tries to use the ibm:extends + * attribute on a non-factory PID + */ + @Test + public void testExtendsNonFactory() throws Exception { + String id = "CWWKG0061E"; + assertNotNull("The error message " + id + " for trying to use ibm:extends on a non-factory PID was not found", + extensionsServer.waitForStringInLog(id + ".*test\\.config\\.extensions\\.sub\\.non\\.factorypid.*test\\.config\\.extensions\\.sub")); + } + + /** + * This tests the error scenario where someone tries uses the ibm:extends + * attribute on a factory PID, but the specified super is a non-factory PID + */ + @Test + public void testExtendsNonFactorySuper() { + String id = "CWWKG0062E"; + assertNotNull("The error message " + id + " for trying to use ibm:extends with a non-factory super was not found", + extensionsServer.waitForStringInLog(id + ".*test\\.config\\.extensions\\.parent\\.non\\.factorypid.*test\\.config\\.extensions\\.extends\\.non\\.factorypid")); + } + + /** + * This tests the scenario where ibm:extends provides a value that does not exist + */ + @Test + public void testInvalidSuper() { + String id = "CWWKG0059E"; + assertNotNull("The error message " + id + " for invalid super was not found", + extensionsServer.waitForStringInLog(id + ".*test\\.config\\.extensions\\.sub\\.error\\.no\\.parent\\.pid.*test\\.config\\.extensions\\.invalid\\.parent")); + } + + /** + * This tests the scenario where ibm:extends provides a value that does not exist + */ + @Test + public void testInvalidRename() { + String id = "CWWKG0067E"; + assertNotNull( + "The error message " + id + " for invalid rename was not found", + extensionsServer.waitForStringInLog(id + + ".*testInvalidAttribute.*testInvalidAttrRename.*test\\.config\\.extensions\\.sub\\.error\\.no\\.parent\\.override\\.attr")); + } + + @Test + public void testRequiredAttributes() { + String id = "CWWKG0058E"; + //[ERROR ] CWWKG0058E: test.config.extensions.extends.attr.required is missing required attribute testAttr4 + assertNotNull("The error message " + id + " for a missing required attribute defined on a sub type was not found", + extensionsServer.waitForStringInLog(id + ".*" + + "test\\.config\\.extensions\\.extends\\.attr\\.required" + + ".*" + + "testAttr4")); + + assertNotNull("The error message " + id + " for a missing required attribute defined on a super type was not found", + extensionsServer.waitForStringInLog(id + ".*" + + "test\\.config\\.extensions\\.extends\\.attr\\.required\\.parent" + + ".*" + + "testAttribute2")); + } + + @Test + public void testAttemptToOverrideFinalMeta() { + String id = "CWWKG0060E"; + assertNotNull("The error message " + id + " for attempting to re-assign a final value was not found", + extensionsServer.waitForStringInLog(id + ".*" + "testOverrideFinal" + ".*" + "test.config.extensions.override.final" + ".*" + "test.config.extensions.super")); + } + + /** + * This tests the scenario where ibm:extends is used on an OCD when the super type does not exist. + * A feature is then installed that provides the super. + * After the feature is installed it should be possible to use the sub type. + * + * This test requires a different server configuration, so it must restore + * the original that other tests rely upon. + */ + @Test + public void testLateArrivingSecondBundleSuper() throws Exception { + try { + //stop the server, collecting logs from any previous tests + //and switch to the alternate serverB1.xml config + extensionsServer.stopServer(true); + extensionsServer.setServerConfigurationFile("extensions/serverB1.xml"); + extensionsServer.startServer(); + String id = "CWWKG0059E"; + assertNotNull("The error message " + id + " for invalid super was not found", + extensionsServer.waitForStringInLog(id + ".*test\\.config\\.extensions\\.different\\.bundle.*test\\.config\\.extensions\\.super")); + //now switch on the bundle providing the super (and our test system wab) + //by setting the serverB2.xml config + extensionsServer.setMarkToEndOfLog(); + extensionsServer.setServerConfigurationFile("extensions/serverB2.xml"); + //wait for our test app to be available + extensionsServer.waitForStringInLog("CWWKT0016I.*" + CONTEXT_ROOT); + String servicePid = servicePidName + "=test.config.extensions.super"; + //now check that the super got a call for the sub defined in the other bundle + HttpUtils.findStringInUrl(extensionsServer, CONTEXT_ROOT + "/test?id=test.config.extensions.different.bundle.config&" + servicePid, PID_PASS); + } finally { + //stop and package up this server + extensionsServer.stopServer(true); + //restore the original server.xml + //by setting our original server.xml back again + extensionsServer.setServerConfigurationFile("extensions/server.xml"); + //and finally restart the server + extensionsServer.startServer(); + //make sure the URL is available + extensionsServer.waitForStringInLog("CWWKT0016I.*" + CONTEXT_ROOT); + } + } + + /** + * This test requires a different server configuration, so it must restore + * the original that other tests rely upon. + * + * @throws Exception + */ + @Test + public void testSchemaGeneratorErrorMessages() throws Exception { + try { + extensionsServer.copyFileToLibertyInstallRoot("lib/features", "internalFeatureForFat/configExtensionsSchemaGeneratorTest-1.0.mf"); + extensionsServer.stopServer(true); + extensionsServer.setServerConfigurationFile("extensions/serverSchemaGenerator.xml"); + extensionsServer.startServer(); + + String msgId = "CWWKG0063E"; + assertNotNull("Expected message " + msgId + " not found in log.", extensionsServer.waitForStringInLog(msgId + ".*testInvalidAttribute")); + + msgId = "CWWKG0064E"; + assertNotNull("Expected message " + msgId + " not found in log.", extensionsServer.waitForStringInLog(msgId + ".*testAttr2Rename")); + + msgId = "CWWKG0065E"; + assertNotNull("Expected message " + msgId + " not found in log.", extensionsServer.waitForStringInLog(msgId + ".*test.config.extensions.parent.non.factorypid")); + + msgId = "CWWKG0066E"; + assertNotNull("Expected message " + msgId + " not found in log.", extensionsServer.waitForStringInLog(msgId + ".*test.config.extensions.sub.error.no.parent.pid")); + } finally { + //stop and package up this server + extensionsServer.stopServer(true); + //restore the original server.xml + //by setting our original server.xml back again + extensionsServer.setServerConfigurationFile("extensions/server.xml"); + //and finally restart the server + extensionsServer.startServer(); + //make sure the URL is available + extensionsServer.waitForStringInLog("CWWKT0016I.*" + CONTEXT_ROOT); + } + } + + /** + * This tests the scenario where a PID that extends another PID that has a name=internal attr, is configured correctly. + */ + @Test + public void testInternalExtension() throws Exception { + + String servicePid = servicePidName + "=test.config.extensions.internal.super"; + + //check that the required attribute has been set on the internal super class + HttpUtils.findStringInUrl(extensionsServer, + CONTEXT_ROOT + "/test?pid=test.config.extensions.internal.sub1&id=internal1&prop=internalAttr1&" + servicePid, + "sub1Attr1"); + } + + /** + * This tests the scenario where a PID that extends another PID that has a name=internal attr, and is missing a required attr, issues the + * expected error message. + */ + @Test + public void testInternalExtensionWithMissingRequiredAttribute() throws Exception { + + String id = "CWWKG0058E"; + assertNotNull( + "The error message " + id + " for internal required attribute was not found", + extensionsServer.waitForStringInLog(id + ".*internalsub2.*internalAttr1")); + } + +} diff --git a/dev/com.ibm.ws.config_fat/fat/src/test/server/config/ConfigValidatorTest.java b/dev/com.ibm.ws.config_fat/fat/src/test/server/config/ConfigValidatorTest.java new file mode 100755 index 00000000000..a84ea7cb8ac --- /dev/null +++ b/dev/com.ibm.ws.config_fat/fat/src/test/server/config/ConfigValidatorTest.java @@ -0,0 +1,112 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package test.server.config; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import componenttest.annotation.ExpectedFFDC; +import componenttest.topology.impl.LibertyFileManager; +import componenttest.topology.impl.LibertyServer; +import componenttest.topology.impl.LibertyServerFactory; + +/** + * Tests the XML signing and validation functions, ensuring correct behavior when signing is enforced + * and invalid documents are encountered. + */ +public class ConfigValidatorTest { + + // Since we have tracing enabled give server longer timeout to start up. + private static final long SERVER_START_TIMEOUT = 30 * 1000; + + @Test + @ExpectedFFDC({ "com.ibm.websphere.config.ConfigValidationException", "java.lang.ClassNotFoundException" }) + public void testValidator() throws Exception { + LibertyServer server = LibertyServerFactory.getLibertyServer("com.ibm.ws.config.validator"); + String jarName = "com.ibm.ws.config.ext_1.0." + server.getMicroVersion() + ".jar"; + server.copyFileToLibertyInstallRoot("lib/features", "internalFeatureForFat/configfatlibertyinternals-1.0.mf"); + + // Backup fragment and bring in embedder validation fragment + LibertyFileManager.renameLibertyFile(server.getMachine(), + server.getInstallRoot() + "/lib/" + jarName, + server.getInstallRoot() + "/lib/" + jarName + ".bak"); + server.copyFileToLibertyInstallRoot("lib", "validator/" + jarName); + + try { + server.setServerStartTimeout(SERVER_START_TIMEOUT); + + server.startServer("goodSignature.log", true, true, false); + assertNotNull("Configuration validation should be issued", + server.waitForStringInLog("CWWKG0043I:.*EmbeddedXMLConfigValidator")); + + // Copy in invalid server.xml, trigger refresh + server.setMarkToEndOfLog(); + server.setServerConfigurationFile("validator/bad-signature.xml"); + assertNotNull("An error message should be issued with invalid config refresh", + server.waitForStringInLog("CWWKG0047E:.*")); + assertNotNull("A warning message should be issued with invalid config refresh", + server.waitForStringInLog("CWWKG0057W:.*")); + assertTrue(server.isStarted()); + + // Stop server, don't clean up. + server.stopServer(false); + + try { + server.startServerExpectFailure("badSignature.log", false, false); + } catch (Exception e) { + System.out.println("Caught exception of type " + e.getClass()); + } + assertNotNull("An error message should be issued on invalid config startup", + server.waitForStringInLog("CWWKG0047E:.*")); + assertNotNull("A fatal message should be issued on invalid config startup", + server.waitForStringInLog("CWWKG0044E:.*")); + assertNotNull("The server should be stopped after invalid config startup", + server.waitForStringInLog("CWWKE0036I:.*")); + + // Stop server, don't clean up. + server.stopServer(false); + + // Copy in invalid server.xml + server.setServerConfigurationFile("validator/dropins-enabled.xml"); + + try { + server.startServerExpectFailure("dropinsEnabled.log", false, false); + } catch (Exception e) { + System.out.println("Caught exception of type " + e.getClass()); + } + assertNotNull("There should be a message about a valid signature", + server.waitForStringInLog("CWWKG0055I:.*")); + assertNotNull("There should be a fatal message because dropins are enabled", + server.waitForStringInLog("CWWKG0056E:.*")); + assertNotNull("The server should be stopped after invalid config startup", + server.waitForStringInLog("CWWKE0036I:.*")); + + } finally { + // Just in case one of the conditions above failed, make sure the server + // stops. Skip the server archive here (it would get skipped for already stopped) + server.stopServer(false); + + // Make sure we *do* capture the data for these attempts + server.postStopServerArchive(); + + // Restore default validation fragment + LibertyFileManager.deleteLibertyFile(server.getMachine(), + server.getInstallRoot() + "/lib/" + jarName); + LibertyFileManager.renameLibertyFile(server.getMachine(), + server.getInstallRoot() + "/lib/" + jarName + ".bak", + server.getInstallRoot() + "/lib/" + jarName); + } + } + +} diff --git a/dev/com.ibm.ws.config_fat/fat/src/test/server/config/DelayedVariableTests.java b/dev/com.ibm.ws.config_fat/fat/src/test/server/config/DelayedVariableTests.java new file mode 100755 index 00000000000..bc10c617f11 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/fat/src/test/server/config/DelayedVariableTests.java @@ -0,0 +1,56 @@ +package test.server.config; + +import static org.junit.Assert.assertNotNull; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import componenttest.topology.impl.LibertyServer; +import componenttest.topology.impl.LibertyServerFactory; + +public class DelayedVariableTests extends ServletRunner { + + private static final String CONTEXT_ROOT = "varmergedconfig"; + + @Override + protected String getContextRoot() { + return CONTEXT_ROOT; + } + + @Override + protected String getServletMapping() { + return "delayedVarTests"; + } + + private static LibertyServer server = LibertyServerFactory.getLibertyServer("com.ibm.ws.config.delayedVar"); + + @Test + public void testVariableDelay() throws Exception { + test(server); + } + + @BeforeClass + public static void setUpForMergedConfigTests() throws Exception { + //copy the config feature into the server features location + server.copyFileToLibertyInstallRoot("lib/features", "internalFeatureForFat/configfatlibertyinternals-1.0.mf"); + server.copyFileToLibertyInstallRoot("lib/features", "internalFeatureForFat/delayedVariable-1.0.mf"); + + //copy the bundle into the server lib location + server.copyFileToLibertyInstallRoot("lib", "bundles/test.config.variables_1.0.0.jar"); + + server.startServer("delayedVariables.log"); + //make sure the URL is available + assertNotNull(server.waitForStringInLog("CWWKT0016I.*" + CONTEXT_ROOT)); + assertNotNull(server.waitForStringInLog("CWWKF0011I")); + } + + @AfterClass + public static void shutdown() throws Exception { + server.stopServer(); + server.deleteFileFromLibertyInstallRoot("lib/features/configfatlibertyinternals-1.0.mf"); + server.deleteFileFromLibertyInstallRoot("lib/test.config.variables_1.0.0.jar"); + server.deleteFileFromLibertyInstallRoot("lib/features/delayedVariable-1.0.mf"); + } + +} diff --git a/dev/com.ibm.ws.config_fat/fat/src/test/server/config/DropinsTest.java b/dev/com.ibm.ws.config_fat/fat/src/test/server/config/DropinsTest.java new file mode 100755 index 00000000000..bcb4ce55d85 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/fat/src/test/server/config/DropinsTest.java @@ -0,0 +1,240 @@ +package test.server.config; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import componenttest.annotation.ExpectedFFDC; +import componenttest.topology.impl.LibertyServer; +import componenttest.topology.impl.LibertyServerFactory; + +public class DropinsTest extends ServletRunner { + + private static final String CONTEXT_ROOT = "configdropins"; + + @Override + protected String getContextRoot() { + return CONTEXT_ROOT; + } + + @Override + protected String getServletMapping() { + return "dropinsTest"; + } + + private static LibertyServer server = LibertyServerFactory.getLibertyServer("com.ibm.ws.config.dropins"); + + @Test + public void testNonXmlFile() throws Exception { + try { + server.setMarkToEndOfLog(); + server.addDropinDefaultConfiguration("dropins/simple.xml"); + server.waitForConfigUpdateInLogUsingMark(null); + server.setMarkToEndOfLog(); + server.addDropinOverrideConfiguration("dropins/simple.notxml"); + server.waitForConfigUpdateInLogUsingMark(null); + + test(server); + } finally { + server.setMarkToEndOfLog(); + server.deleteDropinDefaultConfiguration("simple.xml"); + server.waitForConfigUpdateInLogUsingMark(null); + server.setMarkToEndOfLog(); + server.deleteDropinOverrideConfiguration("simple.notxml"); + server.waitForConfigUpdateInLogUsingMark(null); + } + } + + @Test + @ExpectedFFDC("com.ibm.websphere.config.ConfigParserException") + public void testBrokenDropin() throws Exception { + try { + server.setMarkToEndOfLog(); + server.addDropinOverrideConfiguration("dropins/simple.xml"); + server.addDropinDefaultConfiguration("dropins/aBrokenFile.xml"); + server.addDropinOverrideConfiguration("dropins/aBrokenFile.xml"); + server.waitForConfigUpdateInLogUsingMark(null); + assertEquals("There should be two CWWKG0014E errors", 2, server.waitForMultipleStringsInLog(2, "CWWKG0014E")); + + test(server); + } finally { + server.setMarkToEndOfLog(); + server.deleteDropinOverrideConfiguration("simple.xml"); + server.deleteDropinDefaultConfiguration("aBrokenFile.xml"); + server.deleteDropinOverrideConfiguration("aBrokenFile.xml"); + server.waitForConfigUpdateInLogUsingMark(null); + } + } + + @Test + public void testSimpleDefaults() throws Exception { + try { + server.setMarkToEndOfLog(); + server.addDropinDefaultConfiguration("dropins/simple.xml"); + server.waitForConfigUpdateInLogUsingMark(null); + + test(server); + } finally { + server.setMarkToEndOfLog(); + server.deleteDropinDefaultConfiguration("simple.xml"); + server.waitForConfigUpdateInLogUsingMark(null); + } + } + + @Test + public void testSimpleOverrides() throws Exception { + try { + server.setMarkToEndOfLog(); + server.addDropinOverrideConfiguration("dropins/simple.xml"); + server.waitForConfigUpdateInLogUsingMark(null); + + test(server); + } finally { + server.setMarkToEndOfLog(); + server.deleteDropinOverrideConfiguration("simple.xml"); + server.waitForConfigUpdateInLogUsingMark(null); + } + } + + @Test + public void testSimpleOverrides2() throws Exception { + try { + server.setMarkToEndOfLog(); + server.addDropinOverrideConfiguration("dropins/simple.xml"); + server.waitForConfigUpdateInLogUsingMark(null); + server.setMarkToEndOfLog(); + server.addDropinOverrideConfiguration("dropins/simple2.xml"); + server.waitForConfigUpdateInLogUsingMark(null); + + test(server); + } finally { + server.setMarkToEndOfLog(); + server.deleteDropinOverrideConfiguration("simple.xml"); + server.waitForConfigUpdateInLogUsingMark(null); + server.setMarkToEndOfLog(); + server.deleteDropinOverrideConfiguration("simple2.xml"); + server.waitForConfigUpdateInLogUsingMark(null); + } + } + + @Test + public void testDefaultsOrdering() throws Exception { + try { + server.setMarkToEndOfLog(); + server.addDropinDefaultConfiguration("dropins/simple.xml"); + server.waitForConfigUpdateInLogUsingMark(null); + server.setMarkToEndOfLog(); + server.addDropinDefaultConfiguration("dropins/simple2.xml"); + server.waitForConfigUpdateInLogUsingMark(null); + + test(server); + } finally { + server.setMarkToEndOfLog(); + server.deleteDropinDefaultConfiguration("simple.xml"); + server.waitForConfigUpdateInLogUsingMark(null); + server.setMarkToEndOfLog(); + server.deleteDropinDefaultConfiguration("simple2.xml"); + server.waitForConfigUpdateInLogUsingMark(null); + } + } + + @Test + public void testOverridesOrdering() throws Exception { + try { + server.setMarkToEndOfLog(); + server.addDropinOverrideConfiguration("dropins/simple.xml"); + server.waitForConfigUpdateInLogUsingMark(null); + server.setMarkToEndOfLog(); + server.addDropinOverrideConfiguration("dropins/simple2.xml"); + server.waitForConfigUpdateInLogUsingMark(null); + + test(server); + } finally { + server.setMarkToEndOfLog(); + server.deleteDropinOverrideConfiguration("simple.xml"); + server.waitForConfigUpdateInLogUsingMark(null); + server.setMarkToEndOfLog(); + server.deleteDropinOverrideConfiguration("simple2.xml"); + server.waitForConfigUpdateInLogUsingMark(null); + } + } + + @Test + public void testNoServerValue1() throws Exception { + try { + server.setMarkToEndOfLog(); + server.addDropinDefaultConfiguration("dropins/alibrary.xml"); + server.waitForConfigUpdateInLogUsingMark(null); + + test(server); + } finally { + server.setMarkToEndOfLog(); + server.deleteDropinDefaultConfiguration("alibrary.xml"); + server.waitForConfigUpdateInLogUsingMark(null); + } + } + + @Test + public void testNoServerValue2() throws Exception { + try { + server.setMarkToEndOfLog(); + server.addDropinOverrideConfiguration("dropins/alibrary.xml"); + server.waitForConfigUpdateInLogUsingMark(null); + + test(server); + } finally { + server.setMarkToEndOfLog(); + server.deleteDropinOverrideConfiguration("alibrary.xml"); + server.waitForConfigUpdateInLogUsingMark(null); + } + } + + @Test + public void testNoServerValue3() throws Exception { + try { + server.setMarkToEndOfLog(); + server.addDropinDefaultConfiguration("dropins/alibrary.xml"); + server.waitForConfigUpdateInLogUsingMark(null); + server.setMarkToEndOfLog(); + server.addDropinOverrideConfiguration("dropins/blibrary.xml"); + server.waitForConfigUpdateInLogUsingMark(null); + + test(server); + } finally { + server.setMarkToEndOfLog(); + server.deleteDropinDefaultConfiguration("alibrary.xml"); + server.waitForConfigUpdateInLogUsingMark(null); + server.setMarkToEndOfLog(); + server.deleteDropinOverrideConfiguration("blibrary.xml"); + server.waitForConfigUpdateInLogUsingMark(null); + } + } + + @BeforeClass + public static void setUpForDropinsTests() throws Exception { + //copy the feature into the server features location + + server.copyFileToLibertyInstallRoot("lib/features", "internalFeatureForFat/configfatlibertyinternals-1.0.mf"); + + // Delete dropin configurations just in case + server.deleteAllDropinConfigurations(); + + server.startServer("configDropins.log"); + + //make sure the URL is available + assertNotNull(server.waitForStringInLog("CWWKT0016I.*" + CONTEXT_ROOT)); + assertNotNull(server.waitForStringInLog("CWWKF0011I")); + + } + + @AfterClass + public static void shutdown() throws Exception { + server.stopServer(); + server.deleteFileFromLibertyInstallRoot("lib/features/configfatlibertyinternals-1.0.mf"); + + } + +} diff --git a/dev/com.ibm.ws.config_fat/fat/src/test/server/config/FATSuite.java b/dev/com.ibm.ws.config_fat/fat/src/test/server/config/FATSuite.java new file mode 100755 index 00000000000..845f3c16802 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/fat/src/test/server/config/FATSuite.java @@ -0,0 +1,39 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package test.server.config; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +@RunWith(Suite.class) +@SuiteClasses({ + ServerConfigTest.class, + ConfigExtensionsTest.class, + ConfigValidatorTest.class, + ChildAliasTest.class, + ProductExtensionsTest.class, + BadConfigTests.class, + MergedConfigTests.class, + VariableMergeTests.class, + MetatypeProviderTest.class, + WSConfigurationHelperTest.class, + SchemaGeneratorMBeanTest.class, + FeaturelistGeneratorMBeanTest.class, + ServerXMLConfigurationMBeanTest.class, + DropinsTest.class, + DelayedVariableTests.class + +}) +public class FATSuite { + +} diff --git a/dev/com.ibm.ws.config_fat/fat/src/test/server/config/FeatureUpdateTests.java b/dev/com.ibm.ws.config_fat/fat/src/test/server/config/FeatureUpdateTests.java new file mode 100755 index 00000000000..64da2e209a9 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/fat/src/test/server/config/FeatureUpdateTests.java @@ -0,0 +1,107 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2014 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package test.server.config; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.Collections; +import java.util.Set; + +import org.junit.Test; + +import componenttest.topology.impl.LibertyServer; +import componenttest.topology.impl.LibertyServerFactory; + +/** + * + */ +public class FeatureUpdateTests { + private void test(LibertyServer server, String testUri) throws Exception { + HttpURLConnection con = null; + try { + URL url = new URL("http://" + server.getHostname() + ":" + server.getHttpDefaultPort() + testUri); + con = (HttpURLConnection) url.openConnection(); + con.setDoInput(true); + con.setDoOutput(true); + con.setUseCaches(false); + con.setRequestMethod("GET"); + InputStream is = con.getInputStream(); + assertNotNull(is); + + String output = read(is); + System.out.println(output); + assertTrue(output, output.trim().startsWith("Test Passed")); + } finally { + if (con != null) { + con.disconnect(); + } + } + } + + private static String read(InputStream in) throws IOException { + InputStreamReader isr = new InputStreamReader(in); + BufferedReader br = new BufferedReader(isr); + StringBuilder builder = new StringBuilder(); + String line; + while ((line = br.readLine()) != null) { + builder.append(line); + builder.append(System.getProperty("line.separator")); + } + return builder.toString(); + } + + private final Set emptySet = Collections.emptySet(); + + // Just make sure we don't get an FFDC when we remove a feature that something else has a reference to. + // In this test, the reference is also ibm:flat + @Test + public void testFeatureRemovalFlat() throws Exception { + LibertyServer server = LibertyServerFactory.getLibertyServer("com.ibm.ws.config.features"); + server.startServer("removeJDBCFeature.log"); + + try { + // switch to new configuration to remove jdbc-4.0 feature + server.setServerConfigurationFile("featureRemove/serverRemoveJDBC.xml"); + assertNotNull("The server configuration update should complete", + server.waitForConfigUpdateInLogUsingMark(emptySet)); + } finally { + server.stopServer(); + } + + } + + // Just make sure we don't get an FFDC when we remove a feature that something else has a reference to. + // In this test, the reference is not marked ibm:flat + // We're also removing the configuration that the OpenID feature config points to. + @Test + public void testFeatureRemoval() throws Exception { + LibertyServer server = LibertyServerFactory.getLibertyServer("com.ibm.ws.config.features"); + server.startServer("removeOpenIDFeature.log"); + + try { + // switch to new configuration to remove jdbc-4.0 feature + server.setServerConfigurationFile("featureRemove/serverRemoveOpenID.xml"); + assertNotNull("The server configuration update should complete", + server.waitForConfigUpdateInLogUsingMark(emptySet)); + } finally { + server.stopServer(); + } + + } +} diff --git a/dev/com.ibm.ws.config_fat/fat/src/test/server/config/FeaturelistGeneratorMBeanTest.java b/dev/com.ibm.ws.config_fat/fat/src/test/server/config/FeaturelistGeneratorMBeanTest.java new file mode 100755 index 00000000000..08210a096c2 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/fat/src/test/server/config/FeaturelistGeneratorMBeanTest.java @@ -0,0 +1,376 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2014 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package test.server.config; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.security.SecureRandom; +import java.security.cert.X509Certificate; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +import javax.management.JMX; +import javax.management.MBeanServerConnection; +import javax.management.ObjectName; +import javax.management.remote.JMXConnector; +import javax.management.remote.JMXConnectorFactory; +import javax.management.remote.JMXServiceURL; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSession; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.ibm.websphere.config.mbeans.FeatureListMBean; +import com.ibm.websphere.filetransfer.FileTransferMBean; +import com.ibm.websphere.simplicity.RemoteFile; +import com.ibm.websphere.simplicity.log.Log; +import com.ibm.ws.jmx.connector.client.rest.ClientProvider; +import componenttest.topology.impl.LibertyServer; +import componenttest.topology.impl.LibertyServerFactory; + +/** + * FAT-Tests to test the functionality of com.ibm.websphere.config.mbeans.FeatureListMBean + */ +public class FeaturelistGeneratorMBeanTest { + + private static Class logClass = FeaturelistGeneratorMBeanTest.class; + + private static LibertyServer server = LibertyServerFactory.getLibertyServer("com.ibm.ws.config.schemaGen.mbean"); + + private static String outputDir; + private static MBeanServerConnection connection; + private static JMXConnector jmxConnector; + + private static ObjectName featurelistGenObjName; + private static ObjectName fileTranObjectName; + + @BeforeClass + public static void setUp() throws Exception { + final String methodName = "setUp"; + Log.entering(logClass, methodName); + + outputDir = server.getServerRoot(); + Log.info(logClass, methodName, "serverRoot=" + outputDir); + + Log.info(logClass, methodName, "Starting server=" + server.getServerName()); + server.startServer(); + + Log.info(logClass, methodName, "Waiting for 'CWWKT0016I.*IBMJMXConnectorREST'"); + assertNotNull("'CWWKT0016I.*IBMJMXConnectorREST' was not received on server", + server.waitForStringInLog("CWWKT0016I.*IBMJMXConnectorREST")); + + Log.info(logClass, methodName, "Waiting for 'CWWKO0219I.*ssl'"); + assertNotNull("'CWWKO0219I.*ssl' was not recieved on server", + server.waitForStringInLog("CWWKO0219I.*ssl")); + + Log.info(logClass, methodName, "Waiting for 'CWPKI0803A.*ssl'"); + assertNotNull("'CWPKI0803A.*ssl' was not generated on server", + server.waitForStringInLog("CWPKI0803A")); + + Log.info(logClass, methodName, "Waiting for 'CWWKS0008I: The security service is ready'"); + assertNotNull("'CWWKS0008I: The security service is ready' was not generated on server", + server.waitForStringInLog("CWWKS0008I")); + + Log.info(logClass, methodName, "Waiting for 'CWWKS4105I: LTPA configuration is ready'"); + assertNotNull("'CWWKS4105I: LTPA configuration is ready' was not generated on server", + server.waitForStringInLog("CWWKS4105I")); + + // Set up the trust store + TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() { + @Override + public X509Certificate[] getAcceptedIssuers() { + return null; + } + + @Override + public void checkClientTrusted(X509Certificate[] certs, String authType) {} + + @Override + public void checkServerTrusted(X509Certificate[] certs, String authType) {} + } }; + + SSLContext sc = SSLContext.getInstance("SSL"); + sc.init(null, trustAllCerts, new SecureRandom()); + HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); + HostnameVerifier hv = new HostnameVerifier() { + @Override + public boolean verify(String urlHostName, SSLSession session) { + return true; + } + }; + HttpsURLConnection.setDefaultHostnameVerifier(hv); + + Map environment = new HashMap(); + environment.put("jmx.remote.protocol.provider.pkgs", "com.ibm.ws.jmx.connector.client"); + environment.put(JMXConnector.CREDENTIALS, new String[] { "theUser", "thePassword" }); + environment.put(ClientProvider.DISABLE_HOSTNAME_VERIFICATION, true); + environment.put(ClientProvider.READ_TIMEOUT, 2 * 60 * 1000); + JMXServiceURL url = new JMXServiceURL("REST", "localhost", getSSLPort(), "/IBMJMXConnectorREST"); + Log.info(logClass, methodName, "JMXServiceURL=" + url.toString()); + jmxConnector = JMXConnectorFactory.connect(url, environment); + assertNotNull("JMXConnector should not be null", jmxConnector); + connection = jmxConnector.getMBeanServerConnection(); + assertNotNull("MBeanServerConnection should not be null", connection); + + featurelistGenObjName = new ObjectName(FeatureListMBean.OBJECT_NAME); + fileTranObjectName = new ObjectName(FileTransferMBean.OBJECT_NAME); + + Log.exiting(logClass, "setUp"); + } + + @AfterClass + public static void cleanUp() throws Exception { + String methodName = "tearDown"; + Log.entering(logClass, methodName); + + if (server != null && server.isStarted()) { + Log.finer(logClass, methodName, "Server is up, stopping it"); + jmxConnector.close(); + server.stopServer(); + } + Log.exiting(logClass, methodName); + } + + /** + * Invoke FeaturelistMBean.generate method + * + * @param params + * @return response from MBean invoke + * @throws Exception + */ + private Map invokeFeatureListMBeanGenerate(Object[] params) throws Exception { + Log.entering(logClass, "invokeFeatureListMBeanGenerate", params); + String[] signature = new String[] { "java.lang.String", "java.lang.String", "java.lang.String" }; + + @SuppressWarnings("unchecked") + Map returnedMap = (Map) connection.invoke(featurelistGenObjName, "generate", params, signature); + Log.info(logClass, "invokeFeatureListMBeanGenerate", returnedMap.toString()); + Log.exiting(logClass, "invokeFeatureListMBeanGenerate", returnedMap); + return returnedMap; + } + + /** + * Invoke FileTransferMBean.downloadFile method + * + * @param params + * @throws Exception + */ + private void invokeFileTransferMBeanDownloadFile(Object[] params) throws Exception { + Log.entering(logClass, "invokeFileTransferMBeanDownloadFile", params); + String[] signature = new String[] { "java.lang.String", "java.lang.String" }; + connection.invoke(fileTranObjectName, "downloadFile", params, signature); + Log.exiting(logClass, "invokeFileTransferMBeanDownloadFile"); + } + + /** + * Invoke FileTransferMBean.deleteFile method + * + * @param params + * @throws Exception + */ + private void invokeFileTransferMBeanDeleteFile(Object[] params) throws Exception { + Log.entering(logClass, "invokeFileTransferMBeanDeleteFile", params); + String[] signature = new String[] { "java.lang.String" }; + connection.invoke(fileTranObjectName, "deleteFile", params, signature); + Log.exiting(logClass, "invokeFileTransferMBeanDeleteFile"); + } + + /** + * Invoke FeaturelistMBean.generate method + * + * @param encoding, locale, productExtension is empty + * @throws Exception + */ + @Test + public void testEmptyStrings() throws Exception { + //Invoke featureList generation + Object[] params = new String[] { "", "", "" }; //encoding, locale, productExtension + Map returnedMap = invokeFeatureListMBeanGenerate(params); + + //Check return code + assertTrue((Integer) returnedMap.get(FeatureListMBean.KEY_RETURN_CODE) == 0); + + //Ensure generated file is bigger than 0.1 MB + String filePath = returnedMap.get(FeatureListMBean.KEY_FILE_PATH).toString(); + File file = new File(filePath); + assertTrue("File is not expected size. File=" + file.getAbsolutePath(), file.length() > 100000); + } + + /** + * Invoke FeaturelistMBean.generate method + * + * @param encoding, locale, productExtension is empty + * @throws Exception + */ + @Test + public void testInvalidEncoding() throws Exception { + final String encodingValue = "en-Test"; + + Object[] params = new String[] { encodingValue, null, null }; //encoding, locale, productExtension + Map returnedMap = invokeFeatureListMBeanGenerate(params); + + //Check return code + assertTrue("Return Code should be 21 and not 0", (Integer) returnedMap.get(FeatureListMBean.KEY_RETURN_CODE) != 0); + + //Retrieve output + String output = (String) returnedMap.get(FeatureListMBean.KEY_OUTPUT); + assertTrue("Output does not contain expected UnsupportedEncodingException. output=" + output, output.contains("java.io.UnsupportedEncodingException: " + encodingValue)); + } + + /** + * Invoke FeaturelistMBean.generate method + * + * @param encoding, locale is invalid, productExtension + * @throws Exception + */ + @Test + public void testInvalidLocale() throws Exception { + final String localeValue = "localeTest"; + + Object[] params = new String[] { null, localeValue, null }; //encoding, locale, productExtension + Map returnedMap = invokeFeatureListMBeanGenerate(params); + + //Check return code + assertTrue("Return Code should be 0", (Integer) returnedMap.get(FeatureListMBean.KEY_RETURN_CODE) == 0); + + //Ensure generated file is bigger than 0.1 MB + String filePath = returnedMap.get(FeatureListMBean.KEY_FILE_PATH).toString(); + File file = new File(filePath); + assertTrue("File is not expected size. File=" + file.getAbsolutePath(), file.length() > 100000); + } + + /** + * Invoke FeaturelistMBean.generate method + * + * @param encoding, locale, productExtension is invalid + * @throws Exception + */ + @Test + public void testInvalidProductExt() throws Exception { + final String productExtValue = "productExt"; + + Object[] params = new String[] { null, null, productExtValue }; //encoding, locale, productExtension + Map returnedMap = invokeFeatureListMBeanGenerate(params); + + //Check return code + assertTrue("Return Code should be 21 and not 0", (Integer) returnedMap.get(FeatureListMBean.KEY_RETURN_CODE) == 21); + + //Retrieve output + String output = (String) returnedMap.get(FeatureListMBean.KEY_OUTPUT); + assertTrue("Output does not contain expected CWWKG0080E. output=" + output, + output.contains("CWWKG0080E")); + } + + /** + * Invoke FeaturelistMBean.generate method and using FileTransferMBean remotely to download + * feature list file and deletes it + * + * @param encoding, locale, productExtension is empty + * @throws Exception + */ + @Test + public void testGenerateDownloadAndDelete() throws Exception { + Object[] params = new String[] { "UTF-16", "fr", "" }; //encoding, locale, productExtension + Map returnedMap = invokeFeatureListMBeanGenerate(params); + + //Check return code + assertTrue((Integer) returnedMap.get(FeatureListMBean.KEY_RETURN_CODE) == 0); + + //Download generated file + String sourcePath = returnedMap.get(FeatureListMBean.KEY_FILE_PATH).toString(); + String targetPath = outputDir + "/download_target/featurelistNonDefault.xml"; + + params = new Object[] { sourcePath, targetPath }; + invokeFileTransferMBeanDownloadFile(params); + + //Ensure the file is bigger than 0.1 MB + File file = new File(targetPath); + assertTrue("File is not expected size. File=" + file.getAbsolutePath(), file.length() > 100000); + + // Remotely delete the generated featurelist file + RemoteFile remoteFile = server.getMachine().getFile(sourcePath); + + //first check if the file exists + assertTrue("Generated featurelist file should exist at this point. remoteFile=" + remoteFile.getAbsolutePath(), remoteFile.exists()); + + params = new Object[] { remoteFile.getAbsolutePath() }; + invokeFileTransferMBeanDeleteFile(params); + + //Verify the file is deleted + assertFalse("Generated featurelist file should have been deleted. remoteFile=" + remoteFile.getAbsolutePath(), remoteFile.exists()); + } + + /** + * Invoke FeaturelistMBean.generate method with correct parameters + * + * @param encoding, locale, productExtension + * @throws Exception + */ + @Test + public void testGenerateSuccessfulFeaturelist() throws Exception { + Object[] params = new String[] { "UTF-8", Locale.getDefault().toString(), null }; //encoding, locale, productExtension + Map returnedMap = invokeFeatureListMBeanGenerate(params); + + //Check return code + assertTrue((Integer) returnedMap.get(FeatureListMBean.KEY_RETURN_CODE) == 0); + + //Ensure generated file is bigger than 0.1 MB + String filePath = returnedMap.get(FeatureListMBean.KEY_FILE_PATH).toString(); + File file = new File(filePath); + assertTrue("File is not expected size. File=" + file.getAbsolutePath(), file.length() > 100000); + + } + + /** + * Invoke FeaturelistMBean.generate method using the JMX MBean API + * downloads the feature list and transfers it over using FileTransfer MBean + * + * @param encoding, locale, productExtension + * @throws Exception + */ + @Test + public void testFeaturelistGenMBeanCallAPI() throws Exception { + FeatureListMBean featurelistGenMbean = JMX.newMBeanProxy(connection, featurelistGenObjName, FeatureListMBean.class); + assertNotNull("We should have got access to the FeatureListMBean API", featurelistGenMbean); + + Map returnedMap = featurelistGenMbean.generate(null, null, null); //encoding, locale, productExtension + + //Check return code + assertTrue((Integer) returnedMap.get(FeatureListMBean.KEY_RETURN_CODE) == 0); + + //Download generated file + String sourcePath = returnedMap.get(FeatureListMBean.KEY_FILE_PATH).toString(); + String targetPath = outputDir + "/download_target/featurelistNonDefault.xml"; + + Object[] params = new Object[] { sourcePath, targetPath }; + invokeFileTransferMBeanDownloadFile(params); + + //Ensure the file is bigger than 0.1 MB + File file = new File(targetPath); + assertTrue("File is not expected size. File=" + file.getAbsolutePath(), file.length() > 100000); + } + + private static int getSSLPort() { + return Integer.valueOf(System.getProperty("HTTP_default.secure", "8020")); + } + +} diff --git a/dev/com.ibm.ws.config_fat/fat/src/test/server/config/MergedConfigTests.java b/dev/com.ibm.ws.config_fat/fat/src/test/server/config/MergedConfigTests.java new file mode 100755 index 00000000000..2d490b5b590 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/fat/src/test/server/config/MergedConfigTests.java @@ -0,0 +1,141 @@ +package test.server.config; + +import static org.junit.Assert.assertNotNull; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import componenttest.topology.impl.LibertyServer; +import componenttest.topology.impl.LibertyServerFactory; + +public class MergedConfigTests extends ServletRunner { + + private static final String CONTEXT_ROOT = "mergedconfig"; + private static final String ALL_IN_ONE_SERVER = "merge/allInOne.xml"; + private static final String IGNORE_SERVER = "merge/ignore.xml"; + private static final String REPLACE_SERVER = "merge/replace.xml"; + private static final String MERGE_SERVER = "merge/merge.xml"; + private static final String IGNORE_REPLACE_SERVER = "merge/ignoreReplace.xml"; + private static final String FOUR_LEVEL_REPLACE_SERVER = "merge/fourLevelReplace.xml"; + private static final String FOUR_LEVEL_IGNORE_SERVER = "merge/fourLevelIgnore.xml"; + + @Override + protected String getContextRoot() { + return CONTEXT_ROOT; + } + + @Override + protected String getServletMapping() { + return "mergedConfigTest"; + } + + private static LibertyServer server = LibertyServerFactory.getLibertyServer("com.ibm.ws.config.merging"); + + @Test + public void testMergedConfig() throws Exception { + server.setMarkToEndOfLog(); + server.setServerConfigurationFile(ALL_IN_ONE_SERVER); + server.waitForConfigUpdateInLogUsingMark(null); + + test(server); + + } + + @Test + public void testMergedIncludesReplace() throws Exception { + server.setMarkToEndOfLog(); + server.setServerConfigurationFile(REPLACE_SERVER); + server.waitForConfigUpdateInLogUsingMark(null); + + test(server); + } + + @Test + public void testMergedIncludesIgnore() throws Exception { + server.setMarkToEndOfLog(); + server.setServerConfigurationFile(IGNORE_SERVER); + server.waitForConfigUpdateInLogUsingMark(null); + + test(server); + } + + @Test + public void testMergedIncludesMerge() throws Exception { + server.setMarkToEndOfLog(); + server.setServerConfigurationFile(MERGE_SERVER); + server.waitForConfigUpdateInLogUsingMark(null); + + test(server); + } + + @Test + public void testMergedIncludesIgnoreReplace() throws Exception { + server.setMarkToEndOfLog(); + server.setServerConfigurationFile(IGNORE_REPLACE_SERVER); + server.waitForConfigUpdateInLogUsingMark(null); + + test(server); + } + + @Test + public void testMergedIncludesFourLevelReplace() throws Exception { + server.setMarkToEndOfLog(); + server.setServerConfigurationFile(FOUR_LEVEL_REPLACE_SERVER); + server.waitForConfigUpdateInLogUsingMark(null); + + test(server); + } + + @Test + public void testMergedIncludesFourLevelIgnore() throws Exception { + server.setMarkToEndOfLog(); + server.setServerConfigurationFile(FOUR_LEVEL_IGNORE_SERVER); + server.waitForConfigUpdateInLogUsingMark(null); + + test(server); + } + + @Test + public void testDefaultInstances1() throws Exception { + // Test that a normal defaultInstances file was read. This works with any of the server.xml files, so no need to + // update. + test(server); + } + + @Test + public void testDefaultInstances2() throws Exception { + // Verify onConflict="merge_when_exists". Works with any server.xml from these tests, so no need to update it. + test(server); + } + + @Test + public void testDefaultInstances3() throws Exception { + // Verify onConflict="merge_when_does_not_exist". Works with any server.xml from these tests, so no need to update it. + test(server); + } + + @BeforeClass + public static void setUpForMergedConfigTests() throws Exception { + //copy the feature into the server features location + server.copyFileToLibertyInstallRoot("lib/features", "internalFeatureForFat/mergedConfigTest-1.0.mf"); + server.copyFileToLibertyInstallRoot("lib/features", "internalFeatureForFat/configfatlibertyinternals-1.0.mf"); + + //copy the bundle into the server lib location + server.copyFileToLibertyInstallRoot("lib", "bundles/test.merged.config_1.0.0.jar"); + + server.startServer("mergedConfig.log"); + //make sure the URL is available + assertNotNull(server.waitForStringInLog("CWWKT0016I.*" + CONTEXT_ROOT)); + assertNotNull(server.waitForStringInLog("CWWKF0011I")); + } + + @AfterClass + public static void shutdown() throws Exception { + server.stopServer(); + server.deleteFileFromLibertyInstallRoot("lib/features/mergedConfigTest-1.0.mf"); + server.deleteFileFromLibertyInstallRoot("lib/test.merged.config_1.0.0.jar"); + server.deleteFileFromLibertyInstallRoot("lib/features/configfatlibertyinternals-1.0.mf"); + } + +} diff --git a/dev/com.ibm.ws.config_fat/fat/src/test/server/config/MetatypeProviderTest.java b/dev/com.ibm.ws.config_fat/fat/src/test/server/config/MetatypeProviderTest.java new file mode 100755 index 00000000000..702bbe38371 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/fat/src/test/server/config/MetatypeProviderTest.java @@ -0,0 +1,88 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012, 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package test.server.config; + +import static org.junit.Assert.assertNotNull; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import componenttest.topology.impl.LibertyServer; +import componenttest.topology.impl.LibertyServerFactory; + +//@Mode(TestMode.FULL) +public class MetatypeProviderTest extends ServletRunner { + + private static final String CONTEXT_ROOT = "metatypeprovider"; + private static final String NO_METATYPE_SERVER = "metatype/noMetatypeServer.xml"; + private static final String ORIGINAL_SERVER = "metatype/server.xml"; + + @Override + protected String getContextRoot() { + return CONTEXT_ROOT; + } + + @Override + protected String getServletMapping() { + return "providerTest"; + } + + private static LibertyServer testServer = LibertyServerFactory.getLibertyServer("com.ibm.ws.config.metatype.provider"); + + @BeforeClass + public static void setUpForMetatypeProviderTests() throws Exception { + //copy the feature into the server features location + testServer.copyFileToLibertyInstallRoot("lib/features", "internalFeatureForFat/metatypeProviderTest-1.0.mf"); + testServer.copyFileToLibertyInstallRoot("lib/features", "internalFeatureForFat/configfatlibertyinternals-1.0.mf"); + + //copy the bundle into the server lib location + testServer.copyFileToLibertyInstallRoot("lib", "bundles/test.metatype.provider_1.0.0.jar"); + + testServer.startServer(); + //make sure the URL is available + assertNotNull(testServer.waitForStringInLog("CWWKT0016I.*" + CONTEXT_ROOT)); + assertNotNull(testServer.waitForStringInLog("CWWKF0011I")); + } + + @AfterClass + public static void shutdown() throws Exception { + testServer.stopServer(); + testServer.deleteFileFromLibertyInstallRoot("lib/features/metatypeProviderTest-1.0.mf"); + testServer.deleteFileFromLibertyInstallRoot("lib/test.metatype.provider_1.0.0.jar"); + testServer.deleteFileFromLibertyInstallRoot("lib/features/configfatlibertyinternals-1.0.mf"); + } + + @Test + public void testMetatypeProvider1() throws Exception { + test(testServer); + } + + @Test + public void testMetatypeProvider2() throws Exception { + test(testServer); + } + + @Test + public void testMetatypeProvider3() throws Exception { + + testServer.setMarkToEndOfLog(); + testServer.setServerConfigurationFile(NO_METATYPE_SERVER); + testServer.waitForConfigUpdateInLogUsingMark(null); + + test(testServer); + + testServer.setMarkToEndOfLog(); + testServer.setServerConfigurationFile(ORIGINAL_SERVER); + testServer.waitForConfigUpdateInLogUsingMark(null); + } +} diff --git a/dev/com.ibm.ws.config_fat/fat/src/test/server/config/ProductExtensionsTest.java b/dev/com.ibm.ws.config_fat/fat/src/test/server/config/ProductExtensionsTest.java new file mode 100755 index 00000000000..314891cd122 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/fat/src/test/server/config/ProductExtensionsTest.java @@ -0,0 +1,384 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package test.server.config; + +import static org.junit.Assert.assertTrue; + +import java.io.BufferedReader; +import java.io.DataInputStream; +import java.io.File; +import java.io.InputStream; +import java.io.InputStreamReader; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.ibm.websphere.simplicity.ProgramOutput; +import com.ibm.websphere.simplicity.RemoteFile; +import com.ibm.websphere.simplicity.log.Log; +import componenttest.topology.impl.LibertyServer; +import componenttest.topology.impl.LibertyServerFactory; +import componenttest.topology.utils.HttpUtils; + +/** + * Schema product extension tests. + */ +public class ProductExtensionsTest { + public static final Class c = ProductExtensionsTest.class; + public static LibertyServer server = LibertyServerFactory.getLibertyServer("com.ibm.ws.config.product.extension"); + public static String javaExc; + public static String installRoot; + + // Product extension variables. + public static final String PRODUCT_FEATURE_PATH = "producttest/lib/features/"; + public static final String PRODUCT_BUNDLE_PATH = "producttest/lib/"; + public static final String PRODUCT_EXTENSIONS_PATH = "etc/extensions/"; + public static final String PRODUCT_EXT_NAME = "testproduct"; + public static final String PRODUCT_FEATURE_PROPERTIES_FILE = "productExtensions/propertiesFiles/testproduct.properties"; + public static final String PRODUCT_FEATURE_PRODTEST_MF = "productExtensions/features/prodtest1-1.0.mf"; + public static final String PRODUCT_FEATURE_PRODTEST_JAR = "bundles/test.prod.extensions_1.0.0.jar"; + public static final String PROD_EXT_CONTEXT_ROOT = "/product1-extensions-test"; + public static final String PRODUCT_CONFIG_ALIAS = "prodtest1Config"; + public static final String PRODUCT_SERVER_XML_INVALID = "productExtensions/config/prod.ext.invalid.server.xml"; + public static final String PRODUCT_SERVER_XML_VALID = "productExtensions/config/prod.ext.valid.server.xml"; + public static final String PRODUCT_SERVER_XML_USING_FACTORY_PID = "productExtensions/config/prod.ext.factory.pid.server.xml"; + + // User product extension variables. + public static final String USER_FEATURE_PATH = "usr/extension/lib/features/"; + public static final String USER_BUNDLE_PATH = "usr/extension/lib/"; + public static final String USER_FEATURE_PRODTEST_MF = "productExtensions/features/userProdtest1-1.0.mf"; + public static final String USER_BUNDLE_JAR = "bundles/test.user.prod.extensions_1.0.0.jar"; + public static final String USER_CONFIG_ALIAS = "userProdtest1Config"; + public static final String USER_PRODUCT_SERVER_XML_INVALID = "productExtensions/config/user.prod.ext.invalid.server.xml"; + public static final String USER_PRODUCT_SERVER_XML_VALID = "productExtensions/config/user.prod.ext.valid.server.xml"; + public static final String USER_PRODUCT_SERVER_XML_USING_FACTORY_PID = "productExtensions/config/user.prod.ext.factory.pid.server.xml"; + private static final String USER_PROD_EXT_CONTEXT_ROOT = "/user.product1-extensions-test"; + + // Other variables. + public static final String CORE_PRODUCT_NAME = "core"; + public static final String USR_PRODUCT_NAME = "usr"; + private static final String PASS_STRING = "TEST_PASSED"; + + /** + * Setup the environment. + * + * @param svr The server instance. + * + * @throws Exception + */ + @BeforeClass + public static void setupEnv() throws Exception { + final String METHOD_NAME = "setup"; + Log.entering(c, METHOD_NAME); + server = LibertyServerFactory.getLibertyServer("com.ibm.ws.config.product.extension"); + installRoot = server.getInstallRoot(); + javaExc = System.getProperty("java.home") + "/bin/java"; + Log.info(c, METHOD_NAME, "java: " + javaExc); + Log.info(c, METHOD_NAME, "installRoot: " + installRoot); + + // Install product extensions. + installProductExtension(); + installUserProductExtension(); + + // Create a directory to store the output files. + File toolsOutputDir = new File(installRoot + "/tool.output.dir"); + toolsOutputDir.mkdir(); + } + + /** + * Cleans up the installation from any files that may have been left around. + * + * @throws Exception + */ + @AfterClass + public static void AfterClassCleanup() throws Exception { + final String METHOD_NAME = "cleanup"; + Log.entering(c, METHOD_NAME); + + tidyup(); + + Log.exiting(c, METHOD_NAME); + } + + /** + * Tests that the ws-schema.jar tool accounts for product extensions. + * The test is expected successfully complete and the product names must be tagged appropriately in the + * serverType section of the generated schema. + * + * @throws Exception + */ + @Test + public void testSchemaGeneratorToolOutputForTaggedProdExtEntries() throws Exception { + final String METHOD_NAME = "testFeatureToolWithProdExtArgument"; + Log.entering(c, METHOD_NAME); + + String[] parms = new String[] { "-jar", installRoot + "/bin/tools/ws-schemagen.jar", installRoot + "/tool.output.dir/schema.xml" }; + ProgramOutput po = server.getMachine().execute(javaExc, parms, installRoot); + logInfo(po, "tool.output.dir/prodExtFeaturelist.xml"); + + RemoteFile rf = server.getFileFromLibertyInstallRoot("tool.output.dir/schema.xml"); + + InputStream in = rf.openForReading(); + DataInputStream dis = new DataInputStream(in); + BufferedReader br = new BufferedReader(new InputStreamReader(dis)); + String line; + + boolean foundUsrConfigElement = false; + boolean foundProdConfigElement = false; + int prefixedElementsCount = 0; + boolean foundServerTypeElement = false; + while ((line = br.readLine()) != null) { + if (!foundServerTypeElement && line.contains("name=\"serverType\"")) { + foundServerTypeElement = true; + } + + if (foundServerTypeElement) { + if (line.contains("name=\"" + USR_PRODUCT_NAME + "_" + USER_CONFIG_ALIAS + "\"")) { + prefixedElementsCount++; + foundUsrConfigElement = true; + } else if (line.contains("name=\"" + PRODUCT_EXT_NAME + "_" + PRODUCT_CONFIG_ALIAS + "\"")) { + prefixedElementsCount++; + foundProdConfigElement = true; + } + } + } + + assertTrue("There should have been only 2 elements prefixed with _", (prefixedElementsCount == 2)); + assertTrue("There should have been a " + USR_PRODUCT_NAME + "_" + USER_CONFIG_ALIAS + " element in the schemaOutput.", foundUsrConfigElement); + assertTrue("There should have been a " + PRODUCT_EXT_NAME + "_" + PRODUCT_CONFIG_ALIAS + " element in the schemaOutput.", foundProdConfigElement); + + Log.exiting(c, METHOD_NAME); + } + + /** + * Test a product extension installation with metatype configuration. + * The test is expected to successfully complete. + * + * @throws Exception + */ + @Test + public void testProductInstallWithMetatypeConfig() throws Exception { + String method = "testProductInstallWithMetatypeConfig"; + Log.entering(c, method); + + server.setServerConfigurationFile(PRODUCT_SERVER_XML_VALID); + server.startServer(); + try { + server.waitForStringInLog("CWWKT0016I.*" + PROD_EXT_CONTEXT_ROOT); + HttpUtils.findStringInUrl(server, PROD_EXT_CONTEXT_ROOT + "/test", PASS_STRING); + } finally { + server.stopServer(); + } + + Log.exiting(c, method); + } + + /** + * Test a product extension installation with the an invalid OCD alias configuration. + * + * @throws Exception + */ + @Test + public void testProductInstallWithInvalidAliasConfig() throws Exception { + String method = "testProductInstallWithInvalidAliasConfig"; + Log.entering(c, method); + + server.setServerConfigurationFile(PRODUCT_SERVER_XML_INVALID); + server.startServer(); + try { + server.waitForStringInLog("CWWKT0016I.*" + PROD_EXT_CONTEXT_ROOT); + HttpUtils.findStringInUrl(server, PROD_EXT_CONTEXT_ROOT + "/test", "TEST_FAILED: getAttribute1 returned: null"); + } finally { + server.stopServer(); + } + + Log.exiting(c, method); + } + + /** + * Test a user product extension installation with metatype configuration. + * The test is expected to successfully complete. + * + * @throws Exception + */ + @Test + public void testUserProductInstallWithMetatypeConfig() throws Exception { + String method = "testUserProductInstallWithMetatypeConfig"; + Log.entering(c, method); + + server.setServerConfigurationFile(USER_PRODUCT_SERVER_XML_VALID); + server.startServer(); + try { + server.waitForStringInLog("CWWKT0016I.*" + USER_PROD_EXT_CONTEXT_ROOT); + HttpUtils.findStringInUrl(server, USER_PROD_EXT_CONTEXT_ROOT + "/test", PASS_STRING); + } finally { + server.stopServer(); + } + + Log.exiting(c, method); + } + + /** + * Test a product extension installation with the an invalid OCD alias configuration. + * + * @throws Exception + */ + @Test + public void testUserProductInstallWithInvalidAliasConfig() throws Exception { + String method = "testUserProductInstallWithInvalidAliasConfig"; + Log.entering(c, method); + + server.setServerConfigurationFile(USER_PRODUCT_SERVER_XML_INVALID); + server.startServer(); + try { + server.waitForStringInLog("CWWKT0016I.*" + USER_PROD_EXT_CONTEXT_ROOT); + HttpUtils.findStringInUrl(server, USER_PROD_EXT_CONTEXT_ROOT + "/test", "TEST_FAILED: getAttribute1 returned: null"); + } finally { + server.stopServer(); + } + + Log.exiting(c, method); + } + + /** + * Test a product extension installation with metatype configuration using the factory pid + * The test is expected to successfully complete. + * + * @throws Exception + */ + @Test + public void testProductInstallWithMetatypeConfigUsingFactoryPid() throws Exception { + String method = "testProductInstallWithMetatypeConfigUsingFactoryPid"; + Log.entering(c, method); + + server.setServerConfigurationFile(PRODUCT_SERVER_XML_USING_FACTORY_PID); + server.startServer(); + try { + server.waitForStringInLog("CWWKT0016I.*" + PROD_EXT_CONTEXT_ROOT); + HttpUtils.findStringInUrl(server, PROD_EXT_CONTEXT_ROOT + "/test", PASS_STRING); + } finally { + server.stopServer(); + } + + Log.exiting(c, method); + } + + /** + * Test a user product extension installation with metatype configuration using the factory pid. + * The test is expected to successfully complete. + * + * @throws Exception + */ + @Test + public void testUserProductInstallWithMetatypeConfigUsingFactoryPid() throws Exception { + String method = "testUserProductInstallWithMetatypeConfigUsingFactoryPid"; + Log.entering(c, method); + + server.setServerConfigurationFile(USER_PRODUCT_SERVER_XML_USING_FACTORY_PID); + server.startServer(); + try { + server.waitForStringInLog("CWWKT0016I.*" + USER_PROD_EXT_CONTEXT_ROOT); + HttpUtils.findStringInUrl(server, USER_PROD_EXT_CONTEXT_ROOT + "/test", PASS_STRING); + } finally { + server.stopServer(); + } + + Log.exiting(c, method); + } + + /** + * Prints an extended debug output. + * + * @param po The programOutput + * @param fileName + * @throws Exception + */ + public void logInfo(ProgramOutput po, String fileName) throws Exception { + String methodName = "logInfo"; + Log.info(c, methodName, "Return Code: " + po.getReturnCode() + ". STDOUT: " + po.getStdout()); + + if (po.getReturnCode() != 0) { + Log.info(c, methodName, "STDERR: " + po.getStderr()); + RemoteFile rf = server.getFileFromLibertyInstallRoot(fileName); + BufferedReader br = new BufferedReader(new InputStreamReader(rf.openForReading())); + StringBuffer sb = new StringBuffer(); + String line = null; + while ((line = br.readLine()) != null) { + sb.append(line); + sb.append("\n"); + } + Log.info(c, methodName, "File " + fileName + " content:\n" + sb.toString()); + br.close(); + } + } + + /** + * Installs a specific product extension. + * + * @throws Exception + */ + public static void installProductExtension() throws Exception { + String method = "installProductExtension"; + Log.entering(c, method, "Intalling product extension: " + PRODUCT_EXT_NAME + "."); + + server.copyFileToLibertyInstallRoot(PRODUCT_FEATURE_PATH, PRODUCT_FEATURE_PRODTEST_MF); + assertTrue("Product feature: " + PRODUCT_FEATURE_PRODTEST_MF + " should have been copied to: " + PRODUCT_FEATURE_PATH, + server.fileExistsInLibertyInstallRoot(PRODUCT_FEATURE_PATH + "prodtest1-1.0.mf")); + + server.copyFileToLibertyInstallRoot(PRODUCT_BUNDLE_PATH, PRODUCT_FEATURE_PRODTEST_JAR); + assertTrue("Product bundle: " + PRODUCT_FEATURE_PRODTEST_JAR + " should have been copied to: " + PRODUCT_BUNDLE_PATH, + server.fileExistsInLibertyInstallRoot(PRODUCT_BUNDLE_PATH + "test.prod.extensions_1.0.0.jar")); + + server.copyFileToLibertyInstallRoot(PRODUCT_EXTENSIONS_PATH, PRODUCT_FEATURE_PROPERTIES_FILE); + assertTrue("Product extension props file: " + PRODUCT_FEATURE_PROPERTIES_FILE + " should have been copied to: " + PRODUCT_EXTENSIONS_PATH, + server.fileExistsInLibertyInstallRoot(PRODUCT_EXTENSIONS_PATH + "testproduct.properties")); + + Log.exiting(c, method, "Product extension: " + PRODUCT_EXT_NAME + " has been installed."); + + } + + /** + * Installs a specific product extension if the default USR location. + * + * @throws Exception + */ + public static void installUserProductExtension() throws Exception { + String method = "installUserProductExtension"; + Log.entering(c, method, "Intalling user product extension."); + + server.copyFileToLibertyInstallRoot(USER_FEATURE_PATH, USER_FEATURE_PRODTEST_MF); + assertTrue("User product feature: " + USER_FEATURE_PRODTEST_MF + " should have been copied to: " + USER_FEATURE_PATH, + server.fileExistsInLibertyInstallRoot(USER_FEATURE_PATH + "userProdtest1-1.0.mf")); + + server.copyFileToLibertyInstallRoot(USER_BUNDLE_PATH, USER_BUNDLE_JAR); + assertTrue("User product bundle: " + USER_BUNDLE_JAR + " should have been copied to: " + USER_BUNDLE_PATH, + server.fileExistsInLibertyInstallRoot(USER_BUNDLE_PATH + "test.user.prod.extensions_1.0.0.jar")); + + Log.exiting(c, method, "User product extension using feature: " + USER_FEATURE_PRODTEST_MF + " has been installed."); + } + + /** + * Cleans up the installation from any dirs/files that this test may have created. + * + * @throws Exception + */ + public static void tidyup() throws Exception { + if (server.isStarted()) + server.stopServer(); + + server.deleteDirectoryFromLibertyInstallRoot("producttest"); + server.deleteDirectoryFromLibertyInstallRoot("etc/extensions"); + server.deleteDirectoryFromLibertyInstallRoot("usr/extension/"); + server.deleteDirectoryFromLibertyInstallRoot("tool.output.dir"); + } +} diff --git a/dev/com.ibm.ws.config_fat/fat/src/test/server/config/SchemaGeneratorMBeanTest.java b/dev/com.ibm.ws.config_fat/fat/src/test/server/config/SchemaGeneratorMBeanTest.java new file mode 100755 index 00000000000..b89083a69bc --- /dev/null +++ b/dev/com.ibm.ws.config_fat/fat/src/test/server/config/SchemaGeneratorMBeanTest.java @@ -0,0 +1,455 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2014 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package test.server.config; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLEncoder; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +import javax.management.JMX; +import javax.management.MBeanServerConnection; +import javax.management.ObjectName; +import javax.management.remote.JMXConnector; +import javax.management.remote.JMXConnectorFactory; +import javax.management.remote.JMXServiceURL; +import javax.net.ssl.HttpsURLConnection; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.ibm.websphere.config.mbeans.ServerSchemaGenerator; +import com.ibm.websphere.filetransfer.FileTransferMBean; +import com.ibm.websphere.simplicity.RemoteFile; +import com.ibm.websphere.simplicity.log.Log; +import com.ibm.ws.jmx.connector.client.rest.ClientProvider; +import componenttest.annotation.ExpectedFFDC; +import componenttest.topology.impl.LibertyServer; +import componenttest.topology.impl.LibertyServerFactory; +import componenttest.topology.utils.HttpUtils; + +/** + * FAT-Tests to test the functionality of com.ibm.websphere.config.mbeans.ServerSchemaGenerator MBean + */ +public class SchemaGeneratorMBeanTest { + + private static Class logClass = SchemaGeneratorMBeanTest.class; + + private static LibertyServer server = LibertyServerFactory.getLibertyServer("com.ibm.ws.config.schemaGen.mbean"); + + private static final String SUCCESS_MESSAGE = "Setup completed successfully."; + private static final long MIN_FILE_SIZE = 500000; + private static final long SERVER_FILE_SIZE = 5000; + + private static String outputDir; + private static MBeanServerConnection connection; + private static JMXConnector jmxConnector; + + private static ObjectName schemaGenObjName; + private static ObjectName fileTranObjectName; + + @BeforeClass + public static void setUp() throws Exception { + final String methodName = "setUp"; + Log.entering(logClass, methodName); + + outputDir = server.getServerRoot(); + Log.info(logClass, methodName, "serverRoot=" + outputDir); + + Log.info(logClass, methodName, "Starting server=" + server.getServerName()); + server.startServer(); + + Log.info(logClass, methodName, "Waiting for 'CWWKT0016I.*IBMJMXConnectorREST'"); + assertNotNull("'CWWKT0016I.*IBMJMXConnectorREST' was not received on server", + server.waitForStringInLog("CWWKT0016I.*IBMJMXConnectorREST")); + + Log.info(logClass, methodName, "Waiting for 'CWWKO0219I.*ssl'"); + assertNotNull("'CWWKO0219I.*ssl' was not recieved on server", + server.waitForStringInLog("CWWKO0219I.*ssl")); + + // Set up the trust store + System.setProperty("javax.net.ssl.trustStore", outputDir + "/resources/security/key.jks"); + System.setProperty("javax.net.ssl.trustStorePassword", "Liberty"); + + Map environment = new HashMap(); + environment.put("jmx.remote.protocol.provider.pkgs", "com.ibm.ws.jmx.connector.client"); + environment.put(JMXConnector.CREDENTIALS, new String[] { "theUser", "thePassword" }); + environment.put(ClientProvider.DISABLE_HOSTNAME_VERIFICATION, true); + environment.put(ClientProvider.READ_TIMEOUT, 2 * 60 * 1000); + JMXServiceURL url = new JMXServiceURL("REST", "localhost", getSSLPort(), "/IBMJMXConnectorREST"); + Log.info(logClass, methodName, "JMXServiceURL=" + url.toString()); + jmxConnector = JMXConnectorFactory.connect(url, environment); + assertNotNull("JMXConnector should not be null", jmxConnector); + connection = jmxConnector.getMBeanServerConnection(); + assertNotNull("MBeanServerConnection should not be null", connection); + + schemaGenObjName = new ObjectName(ServerSchemaGenerator.OBJECT_NAME); + fileTranObjectName = new ObjectName(FileTransferMBean.OBJECT_NAME); + + Log.exiting(logClass, "setUp"); + } + + @AfterClass + public static void cleanUp() throws Exception { + String methodName = "tearDown"; + Log.entering(logClass, methodName); + + if (server != null && server.isStarted()) { + Log.finer(logClass, methodName, "Server is up, stopping it"); + jmxConnector.close(); + server.stopServer(); + } + Log.exiting(logClass, methodName); + } + + /** + * Invoke ServerSchemaGenerator.generateInstallSchema method + * + * @param params + * @return response from MBean invoke + * @throws Exception + */ + private Map invokeGenerateInstallSchema(Object[] params) throws Exception { + Log.entering(logClass, "invokeGenerateInstallSchema", params); + String[] signature = new String[] { "java.lang.String", "java.lang.String", "java.lang.String", "java.lang.String" }; + + @SuppressWarnings("unchecked") + Map returnedMap = (Map) connection.invoke(schemaGenObjName, "generateInstallSchema", params, signature); + + Log.exiting(logClass, "invokeGenerateInstallSchema", returnedMap); + return returnedMap; + } + + /** + * Invoke ServerSchemaGenerator.generateServerSchema method + * + * @param params + * @return response from MBean invoke + * @throws Exception + */ + private Map invokeGenerateServerSchema(Object[] params) throws Exception { + Log.entering(logClass, "invokeGenerateServerSchema", params); + String[] signature = new String[] { "java.lang.String", "java.lang.String", "java.lang.String", "java.lang.String" }; + + @SuppressWarnings("unchecked") + Map returnedMap = (Map) connection.invoke(schemaGenObjName, "generateServerSchema", params, signature); + + Log.exiting(logClass, "invokeGenerateServerSchema", returnedMap); + return returnedMap; + } + + /** + * Invoke ServerSchemaGenerator.generate method + * + * @param params + * @return response from MBean invoke + * @throws Exception + */ + private String invokeSchemaGenMBeanGenerate() throws Exception { + + Object[] params = new String[] {}; + String[] signature = new String[] {}; + + String response = (String) connection.invoke(schemaGenObjName, "generate", params, signature); + + Log.finest(logClass, "invokeSchemaGenMBeanGenerate", "response=" + response); + return response; + } + + /** + * Invoke FileTransferMBean.downloadFile method + * + * @param params + * @throws Exception + */ + private void invokeFileTransferMBeanDownloadFile(Object[] params) throws Exception { + Log.entering(logClass, "invokeFileTransferMBeanDownloadFile", params); + String[] signature = new String[] { "java.lang.String", "java.lang.String" }; + connection.invoke(fileTranObjectName, "downloadFile", params, signature); + Log.exiting(logClass, "invokeFileTransferMBeanDownloadFile"); + } + + /** + * Invoke FileTransferMBean.deleteFile method + * + * @param params + * @throws Exception + */ + private void invokeFileTransferMBeanDeleteFile(Object[] params) throws Exception { + Log.entering(logClass, "invokeFileTransferMBeanDeleteFile", params); + String[] signature = new String[] { "java.lang.String" }; + connection.invoke(fileTranObjectName, "deleteFile", params, signature); + Log.exiting(logClass, "invokeFileTransferMBeanDeleteFile"); + } + + @Test + public void testDefaultValuesRestartServer() throws Exception { + String methodName = "testDefaultValuesRestartServer"; + + //Invoke schema generation + Object[] params = new String[] { "1.0", "1", "UTF-8", Locale.getDefault().toString() }; //schemaVersion, outputVersion, encoding, locale + Map returnedMap = invokeGenerateInstallSchema(params); + + //Check return code + assertTrue((Integer) returnedMap.get(ServerSchemaGenerator.KEY_RETURN_CODE) == 0); + + //Download generated file + String sourcePath = (String) returnedMap.get(ServerSchemaGenerator.KEY_FILE_PATH); + String targetPath = outputDir + "/download_target/schemaDefaultValues.xsd"; + + params = new Object[] { sourcePath, targetPath }; + invokeFileTransferMBeanDownloadFile(params); + + //Ensure the file is bigger than expected minimum size + File file = new File(targetPath); + assertTrue("targetPath file is not expected size. File=" + file.getAbsolutePath() + " : size=" + file.length(), file.length() > MIN_FILE_SIZE); + + Log.info(logClass, methodName, "Restarting server"); + server.restartServer(); + + Log.info(logClass, methodName, "Waiting for 'CWWKT0016I.*IBMJMXConnectorREST'"); + assertNotNull("'CWWKT0016I.*IBMJMXConnectorREST' was not received on server", + server.waitForStringInLog("CWWKT0016I.*IBMJMXConnectorREST")); + + Log.info(logClass, methodName, "Waiting for 'CWWKO0219I.*ssl'"); + assertNotNull("'CWWKO0219I.*ssl' was not recieved on server", + server.waitForStringInLog("CWWKO0219I.*ssl")); + + // Verify that the file was cleaned up after server restart + assertFalse("Generated schema file was not deleted after server restart. File=" + sourcePath, new File(sourcePath).exists()); + } + + @Test + public void testEmptyStrings() throws Exception { + //Invoke schema generation + Object[] params = new String[] { "", "", "", "" }; //schemaVersion, outputVersion, encoding, locale + Map returnedMap = invokeGenerateInstallSchema(params); + + //Check return code + assertTrue((Integer) returnedMap.get(ServerSchemaGenerator.KEY_RETURN_CODE) == 0); + + //Ensure generated file is bigger than expected minimum size + String filePath = (String) returnedMap.get(ServerSchemaGenerator.KEY_FILE_PATH); + File file = new File(filePath); + assertTrue("File is not expected size. File=" + file.getAbsolutePath() + " : size=" + file.length(), file.length() > MIN_FILE_SIZE); + } + + @Test + public void testGenerateDownloadAndDelete() throws Exception { + Object[] params = new String[] { "1.1", "2", "UTF-16", "fr" }; //schemaVersion, outputVersion, encoding, locale + Map returnedMap = invokeGenerateInstallSchema(params); + + //Check return code + assertTrue((Integer) returnedMap.get(ServerSchemaGenerator.KEY_RETURN_CODE) == 0); + + //Download generated file + String sourcePath = (String) returnedMap.get(ServerSchemaGenerator.KEY_FILE_PATH); + String targetPath = outputDir + "/download_target/schemaNonDefault.xsd"; + + params = new Object[] { sourcePath, targetPath }; + invokeFileTransferMBeanDownloadFile(params); + + //Ensure the file is bigger than expected minimum size + File file = new File(targetPath); + assertTrue("File is not expected size. File=" + file.getAbsolutePath() + " : size=" + file.length(), file.length() > MIN_FILE_SIZE); + + // Remotely delete the generated schema file + RemoteFile remoteFile = server.getMachine().getFile(sourcePath); + + //first check if the file exists + assertTrue("Generated schema file should exist at this point. remoteFile=" + remoteFile.getAbsolutePath(), remoteFile.exists()); + + params = new Object[] { remoteFile.getAbsolutePath() }; + invokeFileTransferMBeanDeleteFile(params); + + //Verify the file is deleted + assertFalse("Generated schema file should have been deleted. remoteFile=" + remoteFile.getAbsolutePath() + " : size" + remoteFile.length(), remoteFile.exists()); + } + + @Test + public void testGenerateServerSchema() throws Exception { + Object[] params = new String[] { null, null, null, null }; //schemaVersion, outputVersion, encoding, locale + Map returnedMap = invokeGenerateServerSchema(params); + + //Check return code + assertTrue((Integer) returnedMap.get(ServerSchemaGenerator.KEY_RETURN_CODE) == 0); + //Download generated file + String sourcePath = (String) returnedMap.get(ServerSchemaGenerator.KEY_FILE_PATH); + String targetPath = outputDir + "/download_target/serverschema.xsd"; + + params = new Object[] { sourcePath, targetPath }; + invokeFileTransferMBeanDownloadFile(params); + + //Ensure the file is bigger than expected minimum size + File file = new File(targetPath); + assertTrue("File is not expected size. File=" + file.getAbsolutePath() + " : size=" + file.length(), file.length() > SERVER_FILE_SIZE); + + } + + @ExpectedFFDC("java.lang.IllegalArgumentException") + @Test + public void testInvalidSchemaVersion() throws Exception { + final String schemaVersion = "9876"; + Object[] params = new String[] { schemaVersion, null, null, null }; //schemaVersion, outputVersion, encoding, locale + Map returnedMap = invokeGenerateInstallSchema(params); + + //Check return code + assertTrue("Return code should not be 0", (Integer) returnedMap.get(ServerSchemaGenerator.KEY_RETURN_CODE) != 0); + + //Retrieve output + String output = (String) returnedMap.get(ServerSchemaGenerator.KEY_OUTPUT); + + assertTrue("Output does not contain expected IllegalArgumentException. output=" + output, output.contains("java.lang.IllegalArgumentException: " + schemaVersion)); + } + + @ExpectedFFDC("java.lang.IllegalArgumentException") + @Test + public void testInvalidOutputVersion() throws Exception { + final String outputVersion = "312"; + Object[] params = new String[] { null, outputVersion, null, null }; //schemaVersion, outputVersion, encoding, locale + Map returnedMap = invokeGenerateInstallSchema(params); + + //Check return code + assertTrue("Return code should not be 0", (Integer) returnedMap.get(ServerSchemaGenerator.KEY_RETURN_CODE) != 0); + + //Retrieve output + String output = (String) returnedMap.get(ServerSchemaGenerator.KEY_OUTPUT); + + assertTrue("Output does not contain expected IllegalArgumentException. output=" + output, output.contains("java.lang.IllegalArgumentException: " + outputVersion)); + } + + @Test + public void testInvalidEncoding() throws Exception { + final String encodingValue = "encodingABC"; + Object[] params = new String[] { null, null, encodingValue, null }; //schemaVersion, outputVersion, encoding, locale + Map returnedMap = invokeGenerateInstallSchema(params); + + //Check return code + assertTrue("Return code should not be 0", (Integer) returnedMap.get(ServerSchemaGenerator.KEY_RETURN_CODE) != 0); + + //Retrieve output + String output = (String) returnedMap.get(ServerSchemaGenerator.KEY_OUTPUT); + + assertTrue("Output does not contain expected UnsupportedEncodingException. output=" + output, output.contains("java.io.UnsupportedEncodingException: " + encodingValue)); + } + + /** + * Schema Generator replaces invalid locale with the default locale. So an output should be generated. + * + * @throws Exception + */ + @Test + public void testInvalidLocale() throws Exception { + //Invoke schema generation + final String localeValue = "localeXYZ"; + Object[] params = new String[] { null, null, null, localeValue }; //schemaVersion, outputVersion, encoding, locale + Map returnedMap = invokeGenerateInstallSchema(params); + + //Check return code + assertTrue((Integer) returnedMap.get(ServerSchemaGenerator.KEY_RETURN_CODE) == 0); + + //Ensure generated file is bigger than expected minimum size + String filePath = (String) returnedMap.get(ServerSchemaGenerator.KEY_FILE_PATH); + File file = new File(filePath); + assertTrue("File is not expected size. File=" + file.getAbsolutePath() + " : size=" + file.length(), file.length() > MIN_FILE_SIZE); + } + + @Test + public void testSchemaGenMBeanCallAPI() throws Exception { + ServerSchemaGenerator schemaGenMBean = JMX.newMBeanProxy(connection, schemaGenObjName, ServerSchemaGenerator.class); + assertNotNull("We should have got access to the ServerSchemaGenerator API", schemaGenMBean); + + Map returnedMap = schemaGenMBean.generateInstallSchema(null, null, null, null); //schemaVersion, outputVersion, encoding, locale + + //Check return code + assertTrue((Integer) returnedMap.get(ServerSchemaGenerator.KEY_RETURN_CODE) == 0); + + //Download generated file + String sourcePath = (String) returnedMap.get(ServerSchemaGenerator.KEY_FILE_PATH); + String targetPath = outputDir + "/download_target/schemaNonDefaultAPI.xsd"; + + Object[] params = new Object[] { sourcePath, targetPath }; + invokeFileTransferMBeanDownloadFile(params); + + //Ensure the file is bigger than expected minimum size + File file = new File(targetPath); + assertTrue("File is not expected size. File=" + file.getAbsolutePath() + " : size=" + file.length(), file.length() > MIN_FILE_SIZE); + } + + @Test + public void testInvokeGenerateMethod() throws Exception { + //Invoke schema generation using the ServerSchemaGenerator.generate method + String returnedVal = invokeSchemaGenMBeanGenerate(); + assertTrue(returnedVal != null && returnedVal.length() > 0); + } + + /** + * Calls a servlet that uses the JMX REST client to connect to the server + * and check a few MBeanServerConnection methods and MBean API calls. + */ + @Test + public void testSchemaGenAppClient() throws Exception { + // Call AppClientServletSchemaGen, check for good result + String encodedServerRoot = URLEncoder.encode(server.getServerRoot(), "UTF-8"); + URL url = new URL("https", server.getHostname(), server.getHttpDefaultSecurePort(), "/mbeans/appClient?serverRoot=" + encodedServerRoot); + HttpsURLConnection con = (HttpsURLConnection) HttpUtils.getHttpConnection(url, HttpURLConnection.HTTP_OK, 60); + HttpUtils.findStringInHttpConnection(con, SUCCESS_MESSAGE); + } + + private static int getSSLPort() { + return Integer.valueOf(System.getProperty("HTTP_default.secure", "8020")); + } + + /** + * Schema Generator for server throws illegalargument exception for a invalid locale. + * + * @throws Exception + */ + @Test + public void testServerSchemaInvalidLocale() throws Exception { + //Invoke schema generation + final String localeValue = "localeXYZ"; + Object[] params = new String[] { null, null, null, localeValue }; //schemaVersion, outputVersion, encoding, locale + try { + Map returnedMap = invokeGenerateServerSchema(params); + } catch (Exception ie) { + assertTrue(true); + } + + } + + @Test + @ExpectedFFDC("java.io.UnsupportedEncodingException") + public void testServerSchemaInvalidEncoding() throws Exception { + final String encodingValue = "encodingABC"; + Object[] params = new String[] { null, null, encodingValue, null }; //schemaVersion, outputVersion, encoding, locale + + Map returnedMap = invokeGenerateServerSchema(params); + + //Check return code + assertTrue("Return code should not be 0", (Integer) returnedMap.get(ServerSchemaGenerator.KEY_RETURN_CODE) != 0); + + //Retrieve output + String output = (String) returnedMap.get(ServerSchemaGenerator.KEY_OUTPUT); + + assertTrue("Output does not contain expected IOException. output=" + output, output.contains("java.io.IOException: " + encodingValue)); + } + +} diff --git a/dev/com.ibm.ws.config_fat/fat/src/test/server/config/ServerConfigTest.java b/dev/com.ibm.ws.config_fat/fat/src/test/server/config/ServerConfigTest.java new file mode 100755 index 00000000000..38de7b0016f --- /dev/null +++ b/dev/com.ibm.ws.config_fat/fat/src/test/server/config/ServerConfigTest.java @@ -0,0 +1,656 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011, 2014 + * + * The source code for this program is not published or other- + * wise divested of its trade secrets, irrespective of what has + * been deposited with the U.S. Copyright Office. + */ + +package test.server.config; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.List; + +import org.junit.Test; + +import com.ibm.websphere.simplicity.RemoteFile; +import com.ibm.websphere.simplicity.config.ConfigMonitorElement; +import com.ibm.websphere.simplicity.config.ServerConfiguration; + +import componenttest.exception.TopologyException; +import componenttest.topology.impl.LibertyFileManager; +import componenttest.topology.impl.LibertyServer; +import componenttest.topology.impl.LibertyServerFactory; + +public class ServerConfigTest { + + // Since we have tracing enabled give server longer timeout to start up. + private static final long SERVER_START_TIMEOUT = 30 * 1000; + + @Test + public void testRestart() throws Exception { + LibertyServer server = LibertyServerFactory.getLibertyServer("com.ibm.ws.config.restart"); + server.copyFileToLibertyInstallRoot("lib/features", "internalFeatureForFat/configfatlibertyinternals-1.0.mf"); + server.setServerStartTimeout(SERVER_START_TIMEOUT); + server.startServer("before.log"); + // Wait for the application to be installed before proceeding + assertNotNull("The restart application never came up", server.waitForStringInLog("CWWKF0008I")); // Feature update completed + assertNotNull("The restart application never came up", server.waitForStringInLog("CWWKZ0001I.* restart")); + + try { + // run the test one + test(server, "/restart/restart?testName=before"); + + server.stopServer(false); + + // switch to new configuration + server.copyFileToLibertyServerRoot("restart/server.xml"); + + server.startServer("after.log", false); + // Wait for the application to be installed before proceeding + assertNotNull("The restart application never came up the second time", server.waitForStringInLog("CWWKF0008I")); // Feature update completed + assertNotNull("The restart application never came up the second time", server.waitForStringInLog("CWWKZ0001I.* restart")); + + // run the test two + test(server, "/restart/restart?testName=after"); + } finally { + server.stopServer(); + server.deleteFileFromLibertyInstallRoot("lib/com.ibm.ws.config.metatype_1.0.jar"); + } + } + + @Test + public void testRefresh() throws Exception { + LibertyServer server = LibertyServerFactory.getLibertyServer("com.ibm.ws.config.refresh"); + server.copyFileToLibertyInstallRoot("lib/features", "internalFeatureForFat/configfatlibertyinternals-1.0.mf"); + server.setServerStartTimeout(SERVER_START_TIMEOUT); + server.startServer("refresh.log"); + + // Wait for the application to be installed before proceeding + assertNotNull("The restart application never came up", server.waitForStringInLog("CWWKZ0001I.* restart")); + + try { + // run the test one + test(server, "/restart/restart?testName=before"); + + // switch to new configuration + server.copyFileToLibertyServerRoot("refresh/server.xml"); + // Wait for the application to be installed before proceeding + assertNotNull("The restart application never came up", server.waitForStringInLog("CWWKZ0001I.* restart")); + + // cause configuration refresh + test(server, "/restart/restart?testName=refresh"); + // Wait for the application to be installed before proceeding + assertNotNull("The restart application never came up", server.waitForStringInLog("CWWKZ0001I.* restart")); + + // run the test two + test(server, "/restart/restart?testName=after"); + } finally { + server.stopServer(); + } + } + + @Test + public void testVariableRestart() throws Exception { + LibertyServer server = LibertyServerFactory.getLibertyServer("com.ibm.ws.config.restart.var"); + server.copyFileToLibertyInstallRoot("lib/features", "internalFeatureForFat/configfatlibertyinternals-1.0.mf"); + server.setServerStartTimeout(SERVER_START_TIMEOUT); + server.startServer("restart-var-before.log"); + // Wait for the application to be installed before proceeding + assertNotNull("The restart application never came up", server.waitForStringInLog("CWWKZ0001I.* restart")); + + try { + // run the test one + test(server, "/restart/restart?testName=beforeVariable"); + + server.stopServer(false); + + // switch to new bootstrap.properties + server.copyFileToLibertyServerRoot("restart.var/bootstrap.properties"); + + server.startServer("restart-var-after.log", false); + // Wait for the application to be installed before proceeding + assertNotNull("The restart application never came up", server.waitForStringInLog("CWWKZ0001I.* restart")); + + // run the test two + test(server, "/restart/restart?testName=afterVariable"); + } finally { + server.stopServer(); + } + } + + @Test + public void testValidate() throws Exception { + LibertyServer server = LibertyServerFactory.getLibertyServer("com.ibm.ws.config.validate"); + server.copyFileToLibertyInstallRoot("lib/features", "internalFeatureForFat/configfatlibertyinternals-1.0.mf"); + server.setServerStartTimeout(SERVER_START_TIMEOUT); + + server.copyFileToLibertyInstallRoot("lib/features", "metatype/metatype-1.0.mf"); + server.copyFileToLibertyInstallRoot("lib", "metatype/com.ibm.ws.config.metatype_1.0.jar"); + + server.startServer(); + + try { + assertStringsPresentInLog(server, new String[] { ".*CWWKG0011W.*person.*", ".*firstName.*Jane.*" }); + assertStringsPresentInLog(server, new String[] { ".*CWWKG0011W.*ejb.*threadPool.*", ".*minThreads.*5.*" }); + assertStringsPresentInLog(server, new String[] { ".*CWWKG0011W.*quickStartSecurity.*" }); + } finally { + server.stopServer(); + } + } + + @Test + public void testValidateUpdateFileTag() throws Exception { + LibertyServer server = LibertyServerFactory.getLibertyServer("com.ibm.ws.config.validateConfig"); + server.copyFileToLibertyInstallRoot("lib/features", "internalFeatureForFat/configfatlibertyinternals-1.0.mf"); + server.setServerStartTimeout(SERVER_START_TIMEOUT); + server.startServer(); + + try { + assertASCIIFileTag(server.getDefaultLogFile()); + } finally { + server.stopServer(); + } + } + + @Test + public void testRelativeImports() throws Exception { + LibertyServer server = LibertyServerFactory.getLibertyServer("com.ibm.ws.config.import"); + server.copyFileToLibertyInstallRoot("lib/features", "internalFeatureForFat/configfatlibertyinternals-1.0.mf"); + server.setServerStartTimeout(SERVER_START_TIMEOUT); + server.startServer("imports.log"); + // Wait for the application to be installed before proceeding + assertNotNull("The restart application never came up", server.waitForStringInLog("CWWKZ0001I.* restart")); + + try { + // run the test one + test(server, "/restart/restart?testName=checkImport"); + } finally { + server.stopServer(); + } + } + + @Test + public void testRefreshError() throws Exception { + LibertyServer server = LibertyServerFactory.getLibertyServer("com.ibm.ws.config.refresh.error"); + server.copyFileToLibertyInstallRoot("lib/features", "internalFeatureForFat/configfatlibertyinternals-1.0.mf"); + server.setServerStartTimeout(SERVER_START_TIMEOUT); + server.startServer("refresh-error.log"); + + // Wait for the application to be installed before proceeding + assertNotNull("The restart application never came up", server.waitForStringInLog("CWWKZ0001I.* restart")); + + try { + // run the test one + test(server, "/restart/restart?testName=before"); + + // switch to new (bad) configuration + server.setMarkToEndOfLog(); + server.setServerConfigurationFile("refresh/bad-server.xml"); + + // cause configuration refresh + test(server, "/restart/restart?testName=refresh"); + + // wait for error + assertNotNull("No refresh error", server.waitForStringInLog("CWWKG0014E.*")); + + // run the test one again since nothing has changed + test(server, "/restart/restart?testName=before"); + + // switch to new (good) configuration + server.setMarkToEndOfLog(); + server.setServerConfigurationFile("refresh/server.xml"); + + // cause configuration refresh + test(server, "/restart/restart?testName=refresh"); + + // run the test two + test(server, "/restart/restart?testName=after"); + } finally { + server.stopServer(); + } + } + + /** + * This test makes sure that you can update the server configuration and that the changes will be picked up when using a polled style of update trigger. It will then disable + * the polling to make sure changes are no longer picked up. + * + * @throws Exception + */ + @Test + public void testServerConfigUpdating() throws Exception { + LibertyServer server = LibertyServerFactory.getStartedLibertyServer("com.ibm.ws.config.update"); + + try { + // The server has no update trigger so first set one to polled. Polled is the default so this change should be picked up + ServerConfiguration config = server.getServerConfiguration(); + ConfigMonitorElement configMonitor = config.getConfig(); + configMonitor.setUpdateTrigger("polled"); + server.updateServerConfiguration(config); + assertNotNull("The server configuration was not updated when setting it to polled", server.waitForStringInLog("CWWKG0017I")); + + long startTime = System.currentTimeMillis(); + // Now update the server configuration to make sure that still works + server.setMarkToEndOfLog(); + config.addApplication("inexistent", ".", "war"); + server.updateServerConfiguration(config); + assertNotNull("The server configuration was not updated when adding a feature", server.waitForStringInLog("CWWKG0017I")); + + // Now turn off server config monitoring and make sure the updating stops + server.setMarkToEndOfLog(); + configMonitor.setUpdateTrigger("disabled"); + server.updateServerConfiguration(config); + assertNotNull("The server configuration was not updated for disabling monitoring", server.waitForStringInLog("CWWKG0017I")); + + /* + * Updating is now turned off so do another update and make sure that the message is NOT displayed in the log (we wait for 4 messages but expect 3). The default wait + * time for this is 30s which is a bit long but also machine specific so make a note of how long it took to update the config during the last 2 updates and wait for + * that long. + */ + long updateDuration = System.currentTimeMillis() - startTime; + server.setMarkToEndOfLog(); + config.removeApplicationsByName("inexistent"); + server.updateServerConfiguration(config); + assertNull("The server configuration was updated even though monitoring is disabled", server.waitForStringInLog("CWWKG0017I", updateDuration)); + } finally { + server.stopServer(); + } + } + + /** + * This test just makes sure that if the server config update trigger is set to mbean then it doesn't monitor the file. + * + * @throws Exception + */ + @Test + public void testMbeanConfigUpdate() throws Exception { + LibertyServer server = LibertyServerFactory.getStartedLibertyServer("com.ibm.ws.config.update.mbean"); + + try { + // This server has and update trigger set to mbean so the file should not be monitored, update it and make sure a config update isn't triggered + ServerConfiguration config = server.getServerConfiguration(); + config.getFeatureManager().getFeatures().add("servlet-3.0"); + server.updateServerConfiguration(config); + //we are waiting for a message not to appear in the log - 10 seconds is probably long enough instead of the default 2 min + // (note that, for whatever reason, LibertyServer doubles the timeout we pass in) + assertNull("The server configuration was updated when it shouldn't of been monitoring the file", server.waitForStringInLog("CWWKG0017I", 5000)); + } finally { + server.stopServer(); + } + } + + private void test(LibertyServer server, String testUri) throws Exception { + HttpURLConnection con = null; + try { + URL url = new URL("http://" + server.getHostname() + ":" + server.getHttpDefaultPort() + testUri); + con = (HttpURLConnection) url.openConnection(); + con.setDoInput(true); + con.setDoOutput(true); + con.setUseCaches(false); + con.setRequestMethod("GET"); + InputStream is = con.getInputStream(); + assertNotNull(is); + + String output = read(is); + System.out.println(output); + assertTrue(output, output.trim().startsWith("Test Passed")); + } finally { + if (con != null) { + con.disconnect(); + } + } + } + + private static String read(InputStream in) throws IOException { + InputStreamReader isr = new InputStreamReader(in); + BufferedReader br = new BufferedReader(isr); + StringBuilder builder = new StringBuilder(); + String line; + while ((line = br.readLine()) != null) { + builder.append(line); + builder.append(System.getProperty("line.separator")); + } + return builder.toString(); + } + + private void assertStringsPresentInLog(LibertyServer server, String[] patterns) throws IOException { + for (String pattern : patterns) { + String match = server.waitForStringInLog(pattern); + // Wait for the application to be installed before proceeding + assertNotNull("No lines found matching the pattern: " + pattern, match); + } + } + + private void assertASCIIFileTag(RemoteFile file) throws Exception { + + String systemOS = System.getProperty("os.name"); + if (systemOS.equals("z/OS")) { + String[] cmdArray = new String[] { "chtag", "-p", file.getAbsolutePath() }; + Process p = Runtime.getRuntime().exec(cmdArray); + p.waitFor(); + String line = ""; + StringBuffer exMsg = new StringBuffer(); + BufferedReader buferr = new BufferedReader(new InputStreamReader(p.getInputStream())); + while ((line = buferr.readLine()) != null) { + exMsg.append(line + ". "); + } + buferr.close(); + + String result[] = exMsg.toString().split("\\s"); + assertEquals("t", result[0]); + assertEquals("ISO8859-1", result[1]); + } + } + + @Test + public void testCaseSensitivity() throws Exception { + LibertyServer server = LibertyServerFactory.getLibertyServer("com.ibm.ws.config.casesensitivity"); + // shouldn't take long to fail but it should start pretty fast + server.setServerStartTimeout(5000); + try { + server.startServer("casesensitivity.log"); + } finally { + server.stopServer(); + } + } + + /** + * Test a bad required include () + * for startup and update. When the variable onError is set to FAIL, the runtime should + * bring down the server on startup and not recognize ANY config changes on update. + * + * @throws Exception + */ + @Test + public void testBadRequiredIncludeFAIL() throws Exception { + LibertyServer server = LibertyServerFactory.getLibertyServer("com.ibm.ws.config.import.error"); + server.copyFileToLibertyInstallRoot("lib/features", "internalFeatureForFat/configfatlibertyinternals-1.0.mf"); + LibertyFileManager.copyFileIntoLiberty(server.getMachine(), server.getServerRoot(), "bootstrap.properties", + server.pathToAutoFVTTestFiles + "/import.error/bootstrap-onError-FAIL.properties", false, + server.getServerRoot()); + server.setServerConfigurationFile("import.error/original.xml"); + server.setServerStartTimeout(SERVER_START_TIMEOUT); + + try { + // Start out with bad include and onError=FAIL + server.startServerExpectFailure("include-error.log", true, true); + + // Now swap in a valid server.xml to test dynamic config update with onError=FAIL + server.setServerConfigurationFile("import.error/server.xml"); + + server.startServer("include-update-error.log"); + + // Wait for the application to be installed before proceeding + assertNotNull("The restart application never came up", server.waitForStringInLog("CWWKZ0001I.* restart")); + + // ensure that the config elements work + test(server, "/restart/restart?testName=before"); + + // switch to new (bad) configuration to test a config update with a bad include + server.setMarkToEndOfLog(); + server.setServerConfigurationFile("import.error/bad-include-server2.xml"); + + // cause configuration refresh + test(server, "/restart/restart?testName=refresh"); + + // make sure that both errors messages are present, CWWKG0015E is the summary message + // that comes out on an update with errors and onError=FAIL + assertNotNull(server.waitForStringInLogUsingMark("CWWKG0015E")); + assertNotNull(server.waitForStringInLogUsingMark("CWWKG0090E")); + + // ensure that the config elements were not updated + test(server, "/restart/restart?testName=before"); + + } finally { + if (server.isStarted()) { + server.stopServer(); + } + } + } + + /** + * Test a bad required include () + * for startup and update. When the variable onError is not set to FAIL (i.e. INFO, WARN), + * the runtime should be tolerant and keep the server running while ignoring the bad + * required include. + * + * For a config update, all changes made to the config should be recognized and only + * the bad required include should be ignored. + * + * @throws Exception + */ + @Test + public void testBadRequiredIncludeWARN() throws Exception { + LibertyServer server = LibertyServerFactory.getLibertyServer("com.ibm.ws.config.import.error"); + server.copyFileToLibertyInstallRoot("lib/features", "internalFeatureForFat/configfatlibertyinternals-1.0.mf"); + server.setServerStartTimeout(SERVER_START_TIMEOUT); + + try { + // Change to default setting of onError=WARN, but swap in a server.xml that has + // malformed xml. + server.copyFileToLibertyServerRoot("import.error/bootstrap.properties"); + server.setServerConfigurationFile("import.error/malformed-server.xml"); + + // Start server with malformed xml and onError=WARN. The server will come up with no configuration, + // which results in an exception because timed exit isn't enabled. + boolean caught = false; + try { + server.startServer("malformed-xml.log", true, true); + } catch (TopologyException ex) { + caught = true; + server.stopServer(); + } + + assertTrue("There should be an exception because timedexit is not enabled", caught); + + // Now provide the original server.xml with a bad required include to ensure + // that the server comes up and reports the bad include. + server.setServerConfigurationFile("import.error/bad-include-server.xml"); + server.startServer("include-warn.log"); + + // Wait for the application to be installed before proceeding + assertNotNull("The restart application never came up", server.waitForStringInLog("CWWKZ0001I.* restart")); + + // find the warning in messages.log CWWKG0090E + List includeErrors = server.findStringsInLogs("CWWKG0090E"); + assertEquals("Should have only seen the include error 1 time upon server startup: " + includeErrors, 1, includeErrors.size()); + + // ensure that the config elements work + test(server, "/restart/restart?testName=before"); + + // switch to new (bad) configuration to test a config update with a bad include + server.setMarkToEndOfLog(); + server.setServerConfigurationFile("import.error/bad-include-server2.xml"); + + // cause configuration refresh + test(server, "/restart/restart?testName=refresh"); + + // ensure that the error message indicating a bad include was provided is there + includeErrors = server.findStringsInLogs("CWWKG0090E"); + assertEquals("Should have only seen the include error 2 times since starting the server: " + includeErrors, 2, includeErrors.size()); + + // ensure that the modified config elements work + test(server, "/restart/restart?testName=after"); + + } finally { + if (server.isStarted()) { + server.stopServer(); + } + } + } + + @Test + public void testBadRequiredIncludeModifyOnError() throws Exception { + LibertyServer server = LibertyServerFactory.getLibertyServer("com.ibm.ws.config.import.error"); + server.copyFileToLibertyInstallRoot("lib/features", "internalFeatureForFat/configfatlibertyinternals-1.0.mf"); + server.setServerStartTimeout(SERVER_START_TIMEOUT); + + try { + // Change to default setting of onError=WARN, but swap in a server.xml that has + // malformed xml. + server.copyFileToLibertyServerRoot("import.error/bootstrap.properties"); + + // Now provide the original server.xml with a bad required include to ensure + // that the server comes up and reports the bad include. + server.setServerConfigurationFile("import.error/bad-include-server.xml"); + server.startServer("include-warn.log"); + + // Wait for the application to be installed before proceeding + assertNotNull("The restart application never came up", server.waitForStringInLog("CWWKZ0001I.* restart")); + + // find the warning in messages.log CWWKG0090E + List includeErrors = server.findStringsInLogs("CWWKG0090E"); + assertEquals("Should have only seen the include error 1 time upon server startup: " + includeErrors, 1, includeErrors.size()); + + // ensure that the config elements work + test(server, "/restart/restart?testName=before"); + + // Update onError to IGNORE + server.setMarkToEndOfLog(); + server.setServerConfigurationFile("import.error/bad-include-server-onError-ignore.xml"); + + // cause configuration refresh + test(server, "/restart/restart?testName=refresh"); + + // ensure that the error message indicating a bad include was provided is there + includeErrors = server.findStringsInLogs("CWWKG0090E"); + assertEquals("Should have only seen the include error 2 times since starting the server: " + includeErrors, 2, includeErrors.size()); + + // switch to new (bad) configuration to test a config update with a bad include + server.setMarkToEndOfLog(); + server.setServerConfigurationFile("import.error/bad-include-server-onError-ignore2.xml"); + + // cause configuration refresh + test(server, "/restart/restart?testName=refresh"); + + // ensure that the error message indicating a bad include was provided is there + includeErrors = server.findStringsInLogs("CWWKG0090E"); + assertEquals("Should not see an include error with onError=IGNORE" + includeErrors, 2, includeErrors.size()); + + // ensure that the modified config elements work + test(server, "/restart/restart?testName=after"); + + } finally { + if (server.isStarted()) { + server.stopServer(); + } + } + } + + @Test + public void testVariableMissingName() throws Exception { + LibertyServer server = LibertyServerFactory.getLibertyServer("com.ibm.ws.config.import.error"); + server.copyFileToLibertyInstallRoot("lib/features", "internalFeatureForFat/configfatlibertyinternals-1.0.mf"); + server.setServerStartTimeout(SERVER_START_TIMEOUT); + + try { + LibertyFileManager.copyFileIntoLiberty(server.getMachine(), server.getServerRoot(), "bootstrap.properties", + server.pathToAutoFVTTestFiles + "/import.error/bootstrap-onError-FAIL.properties", false, + server.getServerRoot()); + server.setServerConfigurationFile("variable.error/missing-name.xml"); + + // With OnError=FAIL, the server should fail to start + server.startServerExpectFailure("variable-name-fail.log", true, true); + + // Change OnError to WARN and try again + server.copyFileToLibertyServerRoot("import.error/bootstrap.properties"); + + server.startServer("variable-name-warn.log", true, true); + + // Wait for the application to be installed before proceeding + assertNotNull("The restart application never came up", server.waitForStringInLog("CWWKZ0001I.* restart")); + + // find the warning in messages.log CWWKG0091E + List includeErrors = server.findStringsInLogs("CWWKG0091E"); + assertEquals("Should have only seen the include error 1 time upon server startup: " + includeErrors, 1, includeErrors.size()); + + // ensure that the config elements work + test(server, "/restart/restart?testName=before"); + + // switch to new (bad) configuration to test a config update with a bad variable + server.setMarkToEndOfLog(); + server.setServerConfigurationFile("variable.error/missing-name2.xml"); + + // cause configuration refresh + test(server, "/restart/restart?testName=refresh"); + + // ensure that the error message indicating a bad variable was provided is there + includeErrors = server.findStringsInLogs("CWWKG0091E"); + assertEquals("Should have only seen the include error 2 times since starting the server: " + includeErrors, 2, includeErrors.size()); + + // ensure that the modified config elements work + test(server, "/restart/restart?testName=after"); + + } finally { + if (server.isStarted()) { + server.stopServer(); + } + } + } + + @Test + public void testVariableMissingValue() throws Exception { + LibertyServer server = LibertyServerFactory.getLibertyServer("com.ibm.ws.config.import.error"); + server.copyFileToLibertyInstallRoot("lib/features", "internalFeatureForFat/configfatlibertyinternals-1.0.mf"); + server.setServerStartTimeout(SERVER_START_TIMEOUT); + + try { + LibertyFileManager.copyFileIntoLiberty(server.getMachine(), server.getServerRoot(), "bootstrap.properties", + server.pathToAutoFVTTestFiles + "/import.error/bootstrap-onError-FAIL.properties", false, + server.getServerRoot()); + server.setServerConfigurationFile("variable.error/missing-value.xml"); + + // With OnError=FAIL, the server should fail to start + server.startServerExpectFailure("variable-value-fail.log", true, true); + + // Change OnError to WARN and try again + server.copyFileToLibertyServerRoot("import.error/bootstrap.properties"); + + server.startServer("variable-name-warn.log", true, true); + + // Wait for the application to be installed before proceeding + assertNotNull("The restart application never came up", server.waitForStringInLog("CWWKZ0001I.* restart")); + + // find the warning in messages.log CWWKG0092E + List includeErrors = server.findStringsInLogs("CWWKG0092E"); + assertEquals("Should have only seen the include error 1 time upon server startup: " + includeErrors, 1, includeErrors.size()); + + // ensure that the config elements work + test(server, "/restart/restart?testName=before"); + + // switch to new (bad) configuration to test a config update with a bad variable + server.setMarkToEndOfLog(); + server.setServerConfigurationFile("variable.error/missing-value2.xml"); + + // cause configuration refresh + test(server, "/restart/restart?testName=refresh"); + + // ensure that the error message indicating a bad variable was provided is there + includeErrors = server.findStringsInLogs("CWWKG0092E"); + assertEquals("Should have only seen the include error 2 times since starting the server: " + includeErrors, 2, includeErrors.size()); + + // ensure that the modified config elements work + test(server, "/restart/restart?testName=after"); + + } finally { + if (server.isStarted()) { + server.stopServer(); + } + } + } + +} diff --git a/dev/com.ibm.ws.config_fat/fat/src/test/server/config/ServerXMLConfigurationMBeanTest.java b/dev/com.ibm.ws.config_fat/fat/src/test/server/config/ServerXMLConfigurationMBeanTest.java new file mode 100755 index 00000000000..5f46f8b83da --- /dev/null +++ b/dev/com.ibm.ws.config_fat/fat/src/test/server/config/ServerXMLConfigurationMBeanTest.java @@ -0,0 +1,171 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2014 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package test.server.config; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.security.SecureRandom; +import java.security.cert.X509Certificate; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import javax.management.JMX; +import javax.management.MBeanServerConnection; +import javax.management.ObjectName; +import javax.management.remote.JMXConnector; +import javax.management.remote.JMXConnectorFactory; +import javax.management.remote.JMXServiceURL; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSession; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.ibm.websphere.config.mbeans.ServerXMLConfigurationMBean; +import com.ibm.websphere.simplicity.log.Log; +import com.ibm.ws.jmx.connector.client.rest.ClientProvider; +import componenttest.topology.impl.LibertyServer; +import componenttest.topology.impl.LibertyServerFactory; + +/** + * Tests that ServerXMLConfigurationMBean can be accessed through a proxy. Note that the + * BVT tests that the configuration files can be downloaded through the FileTransferMBean + * so not going to include a redundant test for that here. + */ +public class ServerXMLConfigurationMBeanTest { + + private static Class logClass = ServerXMLConfigurationMBeanTest.class; + + private static LibertyServer server = LibertyServerFactory.getLibertyServer("com.ibm.ws.config.schemaGen.mbean"); + + private static String outputDir; + private static MBeanServerConnection connection; + private static JMXConnector jmxConnector; + + private static ObjectName serverXMLConfigurationMBeanObjName; + + @BeforeClass + public static void setUp() throws Exception { + final String methodName = "setUp"; + Log.entering(logClass, methodName); + + outputDir = server.getServerRoot(); + Log.info(logClass, methodName, "serverRoot=" + outputDir); + + Log.info(logClass, methodName, "Starting server=" + server.getServerName()); + server.startServer(); + + Log.info(logClass, methodName, "Waiting for 'CWWKT0016I.*IBMJMXConnectorREST'"); + assertNotNull("'CWWKT0016I.*IBMJMXConnectorREST' was not received on server", + server.waitForStringInLog("CWWKT0016I.*IBMJMXConnectorREST")); + + Log.info(logClass, methodName, "Waiting for 'CWWKO0219I.*ssl'"); + assertNotNull("'CWWKO0219I.*ssl' was not recieved on server", + server.waitForStringInLog("CWWKO0219I.*ssl")); + + Log.info(logClass, methodName, "Waiting for 'CWPKI0803A.*ssl'"); + assertNotNull("'CWPKI0803A.*ssl' was not generated on server", + server.waitForStringInLog("CWPKI0803A")); + + Log.info(logClass, methodName, "Waiting for 'CWWKS0008I: The security service is ready'"); + assertNotNull("'CWWKS0008I: The security service is ready' was not generated on server", + server.waitForStringInLog("CWWKS0008I")); + + Log.info(logClass, methodName, "Waiting for 'CWWKS4105I: LTPA configuration is ready'"); + assertNotNull("'CWWKS4105I: LTPA configuration is ready' was not generated on server", + server.waitForStringInLog("CWWKS4105I")); + + // Set up the trust store + TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() { + @Override + public X509Certificate[] getAcceptedIssuers() { + return null; + } + + @Override + public void checkClientTrusted(X509Certificate[] certs, String authType) {} + + @Override + public void checkServerTrusted(X509Certificate[] certs, String authType) {} + } }; + + SSLContext sc = SSLContext.getInstance("SSL"); + sc.init(null, trustAllCerts, new SecureRandom()); + HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); + HostnameVerifier hv = new HostnameVerifier() { + @Override + public boolean verify(String urlHostName, SSLSession session) { + return true; + } + }; + HttpsURLConnection.setDefaultHostnameVerifier(hv); + + Map environment = new HashMap(); + environment.put("jmx.remote.protocol.provider.pkgs", "com.ibm.ws.jmx.connector.client"); + environment.put(JMXConnector.CREDENTIALS, new String[] { "theUser", "thePassword" }); + environment.put(ClientProvider.DISABLE_HOSTNAME_VERIFICATION, true); + environment.put(ClientProvider.READ_TIMEOUT, 2 * 60 * 1000); + JMXServiceURL url = new JMXServiceURL("REST", "localhost", getSSLPort(), "/IBMJMXConnectorREST"); + Log.info(logClass, methodName, "JMXServiceURL=" + url.toString()); + jmxConnector = JMXConnectorFactory.connect(url, environment); + assertNotNull("JMXConnector should not be null", jmxConnector); + connection = jmxConnector.getMBeanServerConnection(); + assertNotNull("MBeanServerConnection should not be null", connection); + + serverXMLConfigurationMBeanObjName = new ObjectName(ServerXMLConfigurationMBean.OBJECT_NAME); + + Log.exiting(logClass, "setUp"); + } + + @AfterClass + public static void cleanUp() throws Exception { + String methodName = "tearDown"; + Log.entering(logClass, methodName); + + if (server != null && server.isStarted()) { + Log.finer(logClass, methodName, "Server is up, stopping it"); + jmxConnector.close(); + server.stopServer(); + } + Log.exiting(logClass, methodName); + } + + @Test + public void testServerXMLConfigurationMBeanCallAPI() throws Exception { + ServerXMLConfigurationMBean serverXMLConfigMBean = JMX.newMBeanProxy(connection, serverXMLConfigurationMBeanObjName, ServerXMLConfigurationMBean.class); + assertNotNull("ServerXMLConfigurationMBean is unexpectedly null.", serverXMLConfigMBean); + + Collection configFilePaths = serverXMLConfigMBean.fetchConfigurationFilePaths(); + assertNotNull("Configuration file path collection should not be null.", configFilePaths); + + // Check that the collection contains the expected file paths. + assertEquals("Config file path collection size is not 3.", 3, configFilePaths.size()); + assertTrue("server.xml is missing from the collection.", + configFilePaths.contains("${server.config.dir}/server.xml")); + assertTrue("fatTestPorts.xml is missing from the collection.", + configFilePaths.contains("${wlp.user.dir}/servers/fatTestPorts.xml")); + assertTrue("fatTestCommon.xml is missing from the collection.", + configFilePaths.contains("${wlp.user.dir}/servers/fatTestCommon.xml")); + } + + private static int getSSLPort() { + return Integer.valueOf(System.getProperty("HTTP_default.secure", "8020")); + } +} diff --git a/dev/com.ibm.ws.config_fat/fat/src/test/server/config/ServletRunner.java b/dev/com.ibm.ws.config_fat/fat/src/test/server/config/ServletRunner.java new file mode 100755 index 00000000000..e00fd760686 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/fat/src/test/server/config/ServletRunner.java @@ -0,0 +1,74 @@ +package test.server.config; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.rules.TestName; + +import componenttest.topology.impl.LibertyServer; + +public abstract class ServletRunner { + + /** + * Utility to set the method name as a String before the test + */ + @Rule + public TestName name = new TestName(); + + public String testName = ""; + + @Before + public void setTestName() { + // set the current test name + testName = name.getMethodName(); + } + + protected abstract String getContextRoot(); + + protected abstract String getServletMapping(); + + protected void test(LibertyServer server) throws Exception { + HttpURLConnection con = null; + try { + URL url = new URL("http://" + server.getHostname() + ":" + server.getHttpDefaultPort() + "/" + + getContextRoot() + "/" + getServletMapping() + "?" + "testName=" + testName); + con = (HttpURLConnection) url.openConnection(); + con.setDoInput(true); + con.setDoOutput(true); + con.setUseCaches(false); + con.setRequestMethod("GET"); + InputStream is = con.getInputStream(); + assertNotNull(is); + + String output = read(is); + System.out.println(output); + assertTrue(output, output.trim().startsWith("OK")); + } finally { + if (con != null) { + con.disconnect(); + } + } + } + + private static String read(InputStream in) throws IOException { + InputStreamReader isr = new InputStreamReader(in); + BufferedReader br = new BufferedReader(isr); + StringBuilder builder = new StringBuilder(); + String line; + while ((line = br.readLine()) != null) { + builder.append(line); + builder.append(System.getProperty("line.separator")); + } + return builder.toString(); + } + +} diff --git a/dev/com.ibm.ws.config_fat/fat/src/test/server/config/VariableMergeTests.java b/dev/com.ibm.ws.config_fat/fat/src/test/server/config/VariableMergeTests.java new file mode 100755 index 00000000000..fc2c188fca3 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/fat/src/test/server/config/VariableMergeTests.java @@ -0,0 +1,88 @@ +package test.server.config; + +import static org.junit.Assert.assertNotNull; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import componenttest.topology.impl.LibertyServer; +import componenttest.topology.impl.LibertyServerFactory; + +public class VariableMergeTests extends ServletRunner { + + private static final String CONTEXT_ROOT = "varmergedconfig"; + private static final String ALL_IN_ONE_SERVER = "varmerge/allInOne.xml"; + private static final String BREAK_SERVER = "varmerge/break.xml"; + private static final String BREAK_2_SERVER = "varmerge/break2.xml"; + private static final String IGNORE_SERVER = "varmerge/ignore.xml"; + private static final String REPLACE_SERVER = "varmerge/replace.xml"; + private static final String MERGE_SERVER = "varmerge/merge.xml"; + + @Override + protected String getContextRoot() { + return CONTEXT_ROOT; + } + + @Override + protected String getServletMapping() { + return "varMergeTest"; + } + + private static LibertyServer server = LibertyServerFactory.getLibertyServer("com.ibm.ws.config.varmerging"); + + @Test + public void testMergedVariables() throws Exception { + server.setMarkToEndOfLog(); + server.setServerConfigurationFile(ALL_IN_ONE_SERVER); + server.waitForConfigUpdateInLogUsingMark(null); + + test(server); + + } + + @Test + public void testMergedIncludesReplace() throws Exception { + server.setMarkToEndOfLog(); + server.setServerConfigurationFile(REPLACE_SERVER); + server.waitForConfigUpdateInLogUsingMark(null); + + test(server); + } + + @Test + public void testMergedIncludesIgnore() throws Exception { + server.setMarkToEndOfLog(); + server.setServerConfigurationFile(IGNORE_SERVER); + server.waitForConfigUpdateInLogUsingMark(null); + + test(server); + } + + @Test + public void testMergedIncludesMerge() throws Exception { + server.setMarkToEndOfLog(); + server.setServerConfigurationFile(MERGE_SERVER); + server.waitForConfigUpdateInLogUsingMark(null); + + test(server); + } + + @BeforeClass + public static void setUpForMergedConfigTests() throws Exception { + //copy the config feature into the server features location + server.copyFileToLibertyInstallRoot("lib/features", "internalFeatureForFat/configfatlibertyinternals-1.0.mf"); + + server.startServer("varmerge.log"); + //make sure the URL is available + assertNotNull(server.waitForStringInLog("CWWKT0016I.*" + CONTEXT_ROOT)); + assertNotNull(server.waitForStringInLog("CWWKF0011I")); + } + + @AfterClass + public static void shutdown() throws Exception { + server.stopServer(); + server.deleteFileFromLibertyInstallRoot("lib/features/configfatlibertyinternals-1.0.mf"); + } + +} diff --git a/dev/com.ibm.ws.config_fat/fat/src/test/server/config/WSConfigurationHelperTest.java b/dev/com.ibm.ws.config_fat/fat/src/test/server/config/WSConfigurationHelperTest.java new file mode 100755 index 00000000000..aa85dbe4da8 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/fat/src/test/server/config/WSConfigurationHelperTest.java @@ -0,0 +1,125 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package test.server.config; + +import static org.junit.Assert.assertNotNull; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import componenttest.custom.junit.runner.Mode; +import componenttest.custom.junit.runner.Mode.TestMode; +import componenttest.topology.impl.LibertyServer; +import componenttest.topology.impl.LibertyServerFactory; + +/** + * + */ + +@Mode(TestMode.FULL) +public class WSConfigurationHelperTest extends ServletRunner { + + private static final String CONTEXT_ROOT = "confighelper"; + + /* + * (non-Javadoc) + * + * @see test.server.config.ServletRunner#getContextRoot() + */ + @Override + protected String getContextRoot() { + return CONTEXT_ROOT; + } + + /* + * (non-Javadoc) + * + * @see test.server.config.ServletRunner#getServletMapping() + */ + @Override + protected String getServletMapping() { + return "helperTest"; + } + + @BeforeClass + public static void setUpForMetatypeProviderTests() throws Exception { + + // Use the feature/bundle from the merged config tests + server.copyFileToLibertyInstallRoot("lib/features", "internalFeatureForFat/mergedConfigTest-1.0.mf"); + server.copyFileToLibertyInstallRoot("lib", "bundles/test.merged.config_1.0.0.jar"); + server.copyFileToLibertyInstallRoot("lib/features", "internalFeatureForFat/configfatlibertyinternals-1.0.mf"); + + server.startServer("helperTest.log"); + //make sure the URL is available + assertNotNull(server.waitForStringInLog("CWWKT0016I.*" + CONTEXT_ROOT)); + assertNotNull(server.waitForStringInLog("CWWKF0011I")); + } + + @AfterClass + public static void shutdown() throws Exception { + server.stopServer(); + server.deleteFileFromLibertyInstallRoot("lib/features/configfatlibertyinternals-1.0.mf"); + } + + private static LibertyServer server = LibertyServerFactory.getLibertyServer("com.ibm.ws.config.helper"); + + @Test + public void testGetDefaultProperties() throws Exception { + test(server); + } + + @Test + public void testGetDefaultPropertiesWithRequired() throws Exception { + test(server); + } + + @Test + public void testAddDefaultConfiguration1() throws Exception { + test(server); + } + + @Test + public void testAddDefaultConfiguration2() throws Exception { + test(server); + } + + @Test + public void testAddDefaultConfiguration4() throws Exception { + test(server); + } + + @Test + public void testAddDefaultConfiguration3() throws Exception { + test(server); + } + + @Test + public void testAddDefaultConfiguration5() throws Exception { + test(server); + } + + @Test + public void testAddDefaultConfiguration6() throws Exception { + test(server); + } + + @Test + public void testAddDefaultConfiguration7() throws Exception { + test(server); + } + + @Test + public void testAddDefaultConfiguration8() throws Exception { + test(server); + } +} diff --git a/dev/com.ibm.ws.config_fat/publish/.gitignore b/dev/com.ibm.ws.config_fat/publish/.gitignore new file mode 100644 index 00000000000..0968b1bceb6 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/.gitignore @@ -0,0 +1 @@ +/bundles diff --git a/dev/com.ibm.ws.config_fat/publish/files/.gitignore b/dev/com.ibm.ws.config_fat/publish/files/.gitignore new file mode 100644 index 00000000000..d4a71b1abe0 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/.gitignore @@ -0,0 +1,7 @@ +/bundles +/childalias.zip +/confighelper.zip +/dropins.zip +/mergedconfig.zip +/metatypeprovider.zip +/varmerge.zip diff --git a/dev/com.ibm.ws.config_fat/publish/files/badconfig/UniqueValueConflict.xml b/dev/com.ibm.ws.config_fat/publish/files/badconfig/UniqueValueConflict.xml new file mode 100755 index 00000000000..b86b3047676 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/badconfig/UniqueValueConflict.xml @@ -0,0 +1,16 @@ + + + + + + + jsp-2.2 + jdbc-4.0 + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/files/badconfig/badHttp.xml b/dev/com.ibm.ws.config_fat/publish/files/badconfig/badHttp.xml new file mode 100755 index 00000000000..ba1cc2db551 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/badconfig/badHttp.xml @@ -0,0 +1,18 @@ + + + + + servlet-3.0 + osgiconsole-1.0 + timedexit-1.0 + + + + + + + + + + diff --git a/dev/com.ibm.ws.config_fat/publish/files/badconfig/badLogging.xml b/dev/com.ibm.ws.config_fat/publish/files/badconfig/badLogging.xml new file mode 100755 index 00000000000..82e64a44031 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/badconfig/badLogging.xml @@ -0,0 +1,13 @@ + + + + + + + servlet-3.0 + osgiconsole-1.0 + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/files/badconfig/goodConfig.xml b/dev/com.ibm.ws.config_fat/publish/files/badconfig/goodConfig.xml new file mode 100755 index 00000000000..d72781208d2 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/badconfig/goodConfig.xml @@ -0,0 +1,12 @@ + + + + + servlet-3.0 + osgiconsole-1.0 + timedexit-1.0 + + + + + diff --git a/dev/com.ibm.ws.config_fat/publish/files/childalias/server.xml b/dev/com.ibm.ws.config_fat/publish/files/childalias/server.xml new file mode 100755 index 00000000000..b866f31c32f --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/childalias/server.xml @@ -0,0 +1,42 @@ + + + + + + + jsp-2.2 + osgiconsole-1.0 + httpservice-2.2 + childAliasTest-1.0 + configfatlibertyinternals-1.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/files/childalias/serverB.xml b/dev/com.ibm.ws.config_fat/publish/files/childalias/serverB.xml new file mode 100755 index 00000000000..cb8acb009cb --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/childalias/serverB.xml @@ -0,0 +1,44 @@ + + + + + + + jsp-2.2 + osgiconsole-1.0 + httpservice-2.2 + childAliasTest-1.0 + childAliasTestB-1.0 + configfatlibertyinternals-1.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/files/childalias/serverC.xml b/dev/com.ibm.ws.config_fat/publish/files/childalias/serverC.xml new file mode 100755 index 00000000000..5c9503cdec5 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/childalias/serverC.xml @@ -0,0 +1,46 @@ + + + + + + + jsp-2.2 + osgiconsole-1.0 + httpservice-2.2 + childAliasTest-1.0 + childAliasTestB-1.0 + childAliasTestC-1.0 + configfatlibertyinternals-1.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/files/childalias/serverC2.xml b/dev/com.ibm.ws.config_fat/publish/files/childalias/serverC2.xml new file mode 100755 index 00000000000..8bb5e698aff --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/childalias/serverC2.xml @@ -0,0 +1,41 @@ + + + + + + + jsp-2.2 + osgiconsole-1.0 + httpservice-2.2 + childAliasTest-1.0 + childAliasTestB-1.0 + childAliasTestC-1.0 + configfatlibertyinternals-1.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/files/childalias/serverC3.xml b/dev/com.ibm.ws.config_fat/publish/files/childalias/serverC3.xml new file mode 100755 index 00000000000..ca75e6cc47a --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/childalias/serverC3.xml @@ -0,0 +1,44 @@ + + + + + + + jsp-2.2 + osgiconsole-1.0 + httpservice-2.2 + childAliasTest-1.0 + childAliasTestB-1.0 + childAliasTestC-1.0 + configfatlibertyinternals-1.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/files/childalias/serverC4.xml b/dev/com.ibm.ws.config_fat/publish/files/childalias/serverC4.xml new file mode 100755 index 00000000000..e8a3157c240 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/childalias/serverC4.xml @@ -0,0 +1,44 @@ + + + + + + + jsp-2.2 + osgiconsole-1.0 + httpservice-2.2 + childAliasTest-1.0 + childAliasTestB-1.0 + childAliasTestC-1.0 + configfatlibertyinternals-1.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/files/childalias/serverC5.xml b/dev/com.ibm.ws.config_fat/publish/files/childalias/serverC5.xml new file mode 100755 index 00000000000..8525e00c57e --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/childalias/serverC5.xml @@ -0,0 +1,42 @@ + + + + + + + jsp-2.2 + osgiconsole-1.0 + httpservice-2.2 + childAliasTest-1.0 + childAliasTestB-1.0 + childAliasTestC-1.0 + configfatlibertyinternals-1.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/files/childalias/serverC6.xml b/dev/com.ibm.ws.config_fat/publish/files/childalias/serverC6.xml new file mode 100755 index 00000000000..0eb20773e2f --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/childalias/serverC6.xml @@ -0,0 +1,44 @@ + + + + + + + jsp-2.2 + osgiconsole-1.0 + httpservice-2.2 + childAliasTest-1.0 + childAliasTestB-1.0 + childAliasTestC-1.0 + configfatlibertyinternals-1.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/files/childalias/serverC7.xml b/dev/com.ibm.ws.config_fat/publish/files/childalias/serverC7.xml new file mode 100755 index 00000000000..d6465ea0f46 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/childalias/serverC7.xml @@ -0,0 +1,44 @@ + + + + + + + jsp-2.2 + osgiconsole-1.0 + httpservice-2.2 + childAliasTest-1.0 + childAliasTestB-1.0 + childAliasTestC-1.0 + configfatlibertyinternals-1.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/files/dropins/aBrokenFile.xml b/dev/com.ibm.ws.config_fat/publish/files/dropins/aBrokenFile.xml new file mode 100755 index 00000000000..b35c826f3cf --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/dropins/aBrokenFile.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/files/dropins/alibrary.xml b/dev/com.ibm.ws.config_fat/publish/files/dropins/alibrary.xml new file mode 100755 index 00000000000..6b757cb4c21 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/dropins/alibrary.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/files/dropins/blibrary.xml b/dev/com.ibm.ws.config_fat/publish/files/dropins/blibrary.xml new file mode 100755 index 00000000000..4aec61a7f86 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/dropins/blibrary.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/files/dropins/simple.notxml b/dev/com.ibm.ws.config_fat/publish/files/dropins/simple.notxml new file mode 100755 index 00000000000..c68456f952b --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/dropins/simple.notxml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/files/dropins/simple.xml b/dev/com.ibm.ws.config_fat/publish/files/dropins/simple.xml new file mode 100755 index 00000000000..c68456f952b --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/dropins/simple.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/files/dropins/simple2.xml b/dev/com.ibm.ws.config_fat/publish/files/dropins/simple2.xml new file mode 100755 index 00000000000..50cab62ebae --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/dropins/simple2.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/files/extensions/server.xml b/dev/com.ibm.ws.config_fat/publish/files/extensions/server.xml new file mode 100755 index 00000000000..ae3c77b37c7 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/extensions/server.xml @@ -0,0 +1,29 @@ + + + + + + configExtensionsTest-1.0 + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/files/extensions/serverB1.xml b/dev/com.ibm.ws.config_fat/publish/files/extensions/serverB1.xml new file mode 100755 index 00000000000..83eff7671c6 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/extensions/serverB1.xml @@ -0,0 +1,13 @@ + + + + + + configExtensionsTestB-1.0 + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/files/extensions/serverB2.xml b/dev/com.ibm.ws.config_fat/publish/files/extensions/serverB2.xml new file mode 100755 index 00000000000..34236ecee93 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/extensions/serverB2.xml @@ -0,0 +1,14 @@ + + + + + + configExtensionsTest-1.0 + configExtensionsTestB-1.0 + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/files/extensions/serverSchemaGenerator.xml b/dev/com.ibm.ws.config_fat/publish/files/extensions/serverSchemaGenerator.xml new file mode 100755 index 00000000000..fb544c9ade2 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/extensions/serverSchemaGenerator.xml @@ -0,0 +1,11 @@ + + + + + + configExtensionsSchemaGeneratorTest-1.0 + configExtensionsTest-1.0 + configExtensionsTestB-1.0 + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/files/featureRemove/serverRemoveJDBC.xml b/dev/com.ibm.ws.config_fat/publish/files/featureRemove/serverRemoveJDBC.xml new file mode 100755 index 00000000000..a4730385b75 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/featureRemove/serverRemoveJDBC.xml @@ -0,0 +1,37 @@ + + + + + osgiConsole-1.0 + servlet-3.0 + localConnector-1.0 + oauth-2.0 + ssl-1.0 + openidConnectServer-1.0 + + + + + + + + + + + + + + + + + client01 + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/files/featureRemove/serverRemoveOpenID.xml b/dev/com.ibm.ws.config_fat/publish/files/featureRemove/serverRemoveOpenID.xml new file mode 100755 index 00000000000..2d1d54c9eee --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/featureRemove/serverRemoveOpenID.xml @@ -0,0 +1,27 @@ + + + + + osgiConsole-1.0 + servlet-3.0 + jdbc-4.0 + localConnector-1.0 + oauth-2.0 + ssl-1.0 + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/files/import.error/bad-include-server-onError-ignore.xml b/dev/com.ibm.ws.config_fat/publish/files/import.error/bad-include-server-onError-ignore.xml new file mode 100755 index 00000000000..c7168bfde9d --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/import.error/bad-include-server-onError-ignore.xml @@ -0,0 +1,28 @@ + + + + + + + + + servlet-3.0 + localConnector-1.0 + configfatlibertyinternals-1.0 + + + + + + + + + + + + + + + + diff --git a/dev/com.ibm.ws.config_fat/publish/files/import.error/bad-include-server-onError-ignore2.xml b/dev/com.ibm.ws.config_fat/publish/files/import.error/bad-include-server-onError-ignore2.xml new file mode 100755 index 00000000000..c6a27e52250 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/import.error/bad-include-server-onError-ignore2.xml @@ -0,0 +1,33 @@ + + + + + + + + + servlet-3.0 + localConnector-1.0 + configfatlibertyinternals-1.0 + + + + + + + + + + + + + + + + + diff --git a/dev/com.ibm.ws.config_fat/publish/files/import.error/bad-include-server.xml b/dev/com.ibm.ws.config_fat/publish/files/import.error/bad-include-server.xml new file mode 100755 index 00000000000..9585b789821 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/import.error/bad-include-server.xml @@ -0,0 +1,27 @@ + + + + + + + + + servlet-3.0 + localConnector-1.0 + configfatlibertyinternals-1.0 + + + + + + + + + + + + + + + diff --git a/dev/com.ibm.ws.config_fat/publish/files/import.error/bad-include-server2.xml b/dev/com.ibm.ws.config_fat/publish/files/import.error/bad-include-server2.xml new file mode 100755 index 00000000000..762079f99a7 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/import.error/bad-include-server2.xml @@ -0,0 +1,32 @@ + + + + + + + + + servlet-3.0 + localConnector-1.0 + configfatlibertyinternals-1.0 + + + + + + + + + + + + + + + + diff --git a/dev/com.ibm.ws.config_fat/publish/files/import.error/bootstrap-onError-FAIL.properties b/dev/com.ibm.ws.config_fat/publish/files/import.error/bootstrap-onError-FAIL.properties new file mode 100755 index 00000000000..a43b26d2a24 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/import.error/bootstrap-onError-FAIL.properties @@ -0,0 +1,4 @@ +com.ibm.ws.logging.trace.specification=config=all=enabled:*=info=enabled +bootstrap.include=../testports.properties +relativeLocation=relative.xml +onError=FAIL \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/files/import.error/bootstrap.properties b/dev/com.ibm.ws.config_fat/publish/files/import.error/bootstrap.properties new file mode 100755 index 00000000000..84bdd909d92 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/import.error/bootstrap.properties @@ -0,0 +1,3 @@ +com.ibm.ws.logging.trace.specification=config=all=enabled:*=info=enabled +bootstrap.include=../testports.properties +relativeLocation=relative.xml diff --git a/dev/com.ibm.ws.config_fat/publish/files/import.error/malformed-server.xml b/dev/com.ibm.ws.config_fat/publish/files/import.error/malformed-server.xml new file mode 100755 index 00000000000..9037d1d7cda --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/import.error/malformed-server.xml @@ -0,0 +1,23 @@ + + + + + + + + + servlet-3.0 + configfatlibertyinternals-1.0 + + + + + + + + + + < + + diff --git a/dev/com.ibm.ws.config_fat/publish/files/import.error/original.xml b/dev/com.ibm.ws.config_fat/publish/files/import.error/original.xml new file mode 100755 index 00000000000..654abb21f83 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/import.error/original.xml @@ -0,0 +1,21 @@ + + + + + + + + + servlet-3.0 + localConnector-1.0 + configfatlibertyinternals-1.0 + + + + + + + + + diff --git a/dev/com.ibm.ws.config_fat/publish/files/import.error/server.xml b/dev/com.ibm.ws.config_fat/publish/files/import.error/server.xml new file mode 100755 index 00000000000..030e6d88709 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/import.error/server.xml @@ -0,0 +1,23 @@ + + + + + + servlet-3.0 + localConnector-1.0 + configfatlibertyinternals-1.0 + + + + + + + + + + + + + + + diff --git a/dev/com.ibm.ws.config_fat/publish/files/internalFeatureForFat/childAliasTest-1.0.mf b/dev/com.ibm.ws.config_fat/publish/files/internalFeatureForFat/childAliasTest-1.0.mf new file mode 100755 index 00000000000..a1a5efb9249 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/internalFeatureForFat/childAliasTest-1.0.mf @@ -0,0 +1,6 @@ +Subsystem-ManifestVersion: 1 +Subsystem-SymbolicName: childAliasTest-1.0;visibility:=public +Subsystem-Version: 1.0.0 +Subsystem-Type: osgi.subsystem.feature +Subsystem-Content: test.config.childalias; version="[1,1.0.100)" +IBM-Feature-Version: 2 diff --git a/dev/com.ibm.ws.config_fat/publish/files/internalFeatureForFat/childAliasTestB-1.0.mf b/dev/com.ibm.ws.config_fat/publish/files/internalFeatureForFat/childAliasTestB-1.0.mf new file mode 100755 index 00000000000..8668eb7b1b4 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/internalFeatureForFat/childAliasTestB-1.0.mf @@ -0,0 +1,6 @@ +Subsystem-ManifestVersion: 1 +Subsystem-SymbolicName: childAliasTestB-1.0;visibility:=public +Subsystem-Version: 1.0.0 +Subsystem-Type: osgi.subsystem.feature +Subsystem-Content: test.config.childalias.b; version="[1,1.0.100)" +IBM-Feature-Version: 2 diff --git a/dev/com.ibm.ws.config_fat/publish/files/internalFeatureForFat/childAliasTestC-1.0.mf b/dev/com.ibm.ws.config_fat/publish/files/internalFeatureForFat/childAliasTestC-1.0.mf new file mode 100755 index 00000000000..52408615ef9 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/internalFeatureForFat/childAliasTestC-1.0.mf @@ -0,0 +1,6 @@ +Subsystem-ManifestVersion: 1 +Subsystem-SymbolicName: childAliasTestC-1.0;visibility:=public +Subsystem-Version: 1.0.0 +Subsystem-Type: osgi.subsystem.feature +Subsystem-Content: test.config.childalias.c; version="[1,1.0.100)" +IBM-Feature-Version: 2 diff --git a/dev/com.ibm.ws.config_fat/publish/files/internalFeatureForFat/configExtensionsSchemaGeneratorTest-1.0.mf b/dev/com.ibm.ws.config_fat/publish/files/internalFeatureForFat/configExtensionsSchemaGeneratorTest-1.0.mf new file mode 100755 index 00000000000..43f5edccc91 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/internalFeatureForFat/configExtensionsSchemaGeneratorTest-1.0.mf @@ -0,0 +1,6 @@ +Subsystem-ManifestVersion: 1 +Subsystem-SymbolicName: configExtensionsSchemaGeneratorTest-1.0;visibility:=public +Subsystem-Version: 1.0.0 +Subsystem-Type: osgi.subsystem.feature +Subsystem-Content: test.config.extensions.schema.generator; version="[1,1.0.100)" +IBM-Feature-Version: 2 diff --git a/dev/com.ibm.ws.config_fat/publish/files/internalFeatureForFat/configExtensionsTest-1.0.mf b/dev/com.ibm.ws.config_fat/publish/files/internalFeatureForFat/configExtensionsTest-1.0.mf new file mode 100755 index 00000000000..d953d105e9b --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/internalFeatureForFat/configExtensionsTest-1.0.mf @@ -0,0 +1,7 @@ +Subsystem-ManifestVersion: 1 +Subsystem-SymbolicName: configExtensionsTest-1.0;visibility:=public +Subsystem-Version: 1.0.0 +Subsystem-Type: osgi.subsystem.feature +Subsystem-Content: test.config.extensions; version="[1,1.0.100)", + com.ibm.wsspi.appserver.webBundle-1.0; type="osgi.subsystem.feature" +IBM-Feature-Version: 2 diff --git a/dev/com.ibm.ws.config_fat/publish/files/internalFeatureForFat/configExtensionsTestB-1.0.mf b/dev/com.ibm.ws.config_fat/publish/files/internalFeatureForFat/configExtensionsTestB-1.0.mf new file mode 100755 index 00000000000..0f458816a93 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/internalFeatureForFat/configExtensionsTestB-1.0.mf @@ -0,0 +1,7 @@ +Subsystem-ManifestVersion: 1 +Subsystem-SymbolicName: configExtensionsTestB-1.0;visibility:=public +Subsystem-Version: 1.0.0 +Subsystem-Type: osgi.subsystem.feature +Subsystem-Content: test.config.extensions.b; version="[1,1.0.100)", + com.ibm.wsspi.appserver.webBundle-1.0; type="osgi.subsystem.feature" +IBM-Feature-Version: 2 diff --git a/dev/com.ibm.ws.config_fat/publish/files/internalFeatureForFat/configfatlibertyinternals-1.0.mf b/dev/com.ibm.ws.config_fat/publish/files/internalFeatureForFat/configfatlibertyinternals-1.0.mf new file mode 100755 index 00000000000..602b7829359 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/internalFeatureForFat/configfatlibertyinternals-1.0.mf @@ -0,0 +1,12 @@ +Subsystem-ManifestVersion: 1 +Subsystem-SymbolicName: configfatlibertyinternals-1.0;visibility:=public +Subsystem-Version: 1.0.0 +Subsystem-Type: osgi.subsystem.feature +IBM-API-Package: org.osgi.service.cm; type="internal", + com.ibm.ws.jmx; type="internal", + org.osgi.framework; type="internal", + org.osgi.util.tracker; type="internal", + com.ibm.websphere.config; type="internal", + com.ibm.wsspi.kernel.service.utils; type="internal", + com.ibm.wsspi.kernel.service.location; type="internal" +IBM-Feature-Version: 2 diff --git a/dev/com.ibm.ws.config_fat/publish/files/internalFeatureForFat/delayedVariable-1.0.mf b/dev/com.ibm.ws.config_fat/publish/files/internalFeatureForFat/delayedVariable-1.0.mf new file mode 100755 index 00000000000..8c6dcd7ade9 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/internalFeatureForFat/delayedVariable-1.0.mf @@ -0,0 +1,6 @@ +Subsystem-ManifestVersion: 1 +Subsystem-SymbolicName: delayedVariable-1.0;visibility:=public +Subsystem-Version: 1.0.0 +Subsystem-Type: osgi.subsystem.feature +Subsystem-Content: test.config.variables; version="[1,1.0.100)" +IBM-Feature-Version: 2 diff --git a/dev/com.ibm.ws.config_fat/publish/files/internalFeatureForFat/mergedConfigTest-1.0.mf b/dev/com.ibm.ws.config_fat/publish/files/internalFeatureForFat/mergedConfigTest-1.0.mf new file mode 100755 index 00000000000..20e4f39e8d1 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/internalFeatureForFat/mergedConfigTest-1.0.mf @@ -0,0 +1,6 @@ +Subsystem-ManifestVersion: 1 +Subsystem-SymbolicName: mergedConfigTest-1.0;visibility:=public +Subsystem-Version: 1.0.0 +Subsystem-Type: osgi.subsystem.feature +Subsystem-Content: test.merged.config; version="[1,1.0.100)" +IBM-Feature-Version: 2 diff --git a/dev/com.ibm.ws.config_fat/publish/files/internalFeatureForFat/metatypeProviderTest-1.0.mf b/dev/com.ibm.ws.config_fat/publish/files/internalFeatureForFat/metatypeProviderTest-1.0.mf new file mode 100755 index 00000000000..f11c82b456d --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/internalFeatureForFat/metatypeProviderTest-1.0.mf @@ -0,0 +1,6 @@ +Subsystem-ManifestVersion: 1 +Subsystem-SymbolicName: metatypeProviderTest-1.0;visibility:=public +Subsystem-Version: 1.0.0 +Subsystem-Type: osgi.subsystem.feature +Subsystem-Content: test.metatype.provider; version="[1,1.0.100)" +IBM-Feature-Version: 2 diff --git a/dev/com.ibm.ws.config_fat/publish/files/merge/allInOne.xml b/dev/com.ibm.ws.config_fat/publish/files/merge/allInOne.xml new file mode 100755 index 00000000000..0a7f9edbf87 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/merge/allInOne.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/files/merge/break.xml b/dev/com.ibm.ws.config_fat/publish/files/merge/break.xml new file mode 100755 index 00000000000..e9a94c8b012 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/merge/break.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/files/merge/break2.xml b/dev/com.ibm.ws.config_fat/publish/files/merge/break2.xml new file mode 100755 index 00000000000..7f80e024f67 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/merge/break2.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/files/merge/fourLevelIgnore.xml b/dev/com.ibm.ws.config_fat/publish/files/merge/fourLevelIgnore.xml new file mode 100755 index 00000000000..7f9a98221c0 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/merge/fourLevelIgnore.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/files/merge/fourLevelReplace.xml b/dev/com.ibm.ws.config_fat/publish/files/merge/fourLevelReplace.xml new file mode 100755 index 00000000000..fdc4b5c5be1 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/merge/fourLevelReplace.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/files/merge/ignore.xml b/dev/com.ibm.ws.config_fat/publish/files/merge/ignore.xml new file mode 100755 index 00000000000..deeaa1b53e8 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/merge/ignore.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/files/merge/ignoreReplace.xml b/dev/com.ibm.ws.config_fat/publish/files/merge/ignoreReplace.xml new file mode 100755 index 00000000000..d130b7ba172 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/merge/ignoreReplace.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/files/merge/merge.xml b/dev/com.ibm.ws.config_fat/publish/files/merge/merge.xml new file mode 100755 index 00000000000..7e3c9e30ccd --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/merge/merge.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/files/merge/replace.xml b/dev/com.ibm.ws.config_fat/publish/files/merge/replace.xml new file mode 100755 index 00000000000..5d13ba07de9 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/merge/replace.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/files/metatype/.gitignore b/dev/com.ibm.ws.config_fat/publish/files/metatype/.gitignore new file mode 100644 index 00000000000..6070719c4e4 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/metatype/.gitignore @@ -0,0 +1 @@ +/com.ibm.ws.config.metatype_1.0.jar diff --git a/dev/com.ibm.ws.config_fat/publish/files/metatype/metatype-1.0.mf b/dev/com.ibm.ws.config_fat/publish/files/metatype/metatype-1.0.mf new file mode 100755 index 00000000000..0284236b04c --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/metatype/metatype-1.0.mf @@ -0,0 +1,7 @@ +Subsystem-ManifestVersion: 1 +IBM-ShortName: metatype-1.0 +Subsystem-SymbolicName: com.ibm.ws.config.metatype-1.0; visibility:=public +Subsystem-Version: 1.0.0 +Subsystem-Content: com.ibm.ws.config.metatype; location:="lib/com.ibm.ws.config.metatype_1.0.jar" +Subsystem-Type: osgi.subsystem.feature +IBM-Feature-Version: 2 diff --git a/dev/com.ibm.ws.config_fat/publish/files/metatype/noMetatypeServer.xml b/dev/com.ibm.ws.config_fat/publish/files/metatype/noMetatypeServer.xml new file mode 100755 index 00000000000..9ceeb7720fb --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/metatype/noMetatypeServer.xml @@ -0,0 +1,20 @@ + + + + + + + servlet-3.0 + osgiconsole-1.0 + httpservice-2.2 + configfatlibertyinternals-1.0 + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/files/metatype/server.xml b/dev/com.ibm.ws.config_fat/publish/files/metatype/server.xml new file mode 100755 index 00000000000..2fc260e93b7 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/metatype/server.xml @@ -0,0 +1,21 @@ + + + + + + + servlet-3.0 + osgiconsole-1.0 + httpservice-2.2 + metatypeProviderTest-1.0 + configfatlibertyinternals-1.0 + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/files/productExtensions/config/prod.ext.factory.pid.server.xml b/dev/com.ibm.ws.config_fat/publish/files/productExtensions/config/prod.ext.factory.pid.server.xml new file mode 100755 index 00000000000..02fd41b0235 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/productExtensions/config/prod.ext.factory.pid.server.xml @@ -0,0 +1,21 @@ + + + + + + + osgiconsole-1.0 + jsp-2.2 + testproduct:prodtest1-1.0 + + + + + + + + + diff --git a/dev/com.ibm.ws.config_fat/publish/files/productExtensions/config/prod.ext.invalid.server.xml b/dev/com.ibm.ws.config_fat/publish/files/productExtensions/config/prod.ext.invalid.server.xml new file mode 100755 index 00000000000..b0ccaa6c8ac --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/productExtensions/config/prod.ext.invalid.server.xml @@ -0,0 +1,22 @@ + + + + + + + osgiconsole-1.0 + jsp-2.2 + testproduct:prodtest1-1.0 + + + + + + + + + + diff --git a/dev/com.ibm.ws.config_fat/publish/files/productExtensions/config/prod.ext.valid.server.xml b/dev/com.ibm.ws.config_fat/publish/files/productExtensions/config/prod.ext.valid.server.xml new file mode 100755 index 00000000000..ea8d784ac47 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/productExtensions/config/prod.ext.valid.server.xml @@ -0,0 +1,21 @@ + + + + + + + osgiconsole-1.0 + jsp-2.2 + testproduct:prodtest1-1.0 + + + + + + + + + diff --git a/dev/com.ibm.ws.config_fat/publish/files/productExtensions/config/user.prod.ext.factory.pid.server.xml b/dev/com.ibm.ws.config_fat/publish/files/productExtensions/config/user.prod.ext.factory.pid.server.xml new file mode 100755 index 00000000000..a68ca5708fe --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/productExtensions/config/user.prod.ext.factory.pid.server.xml @@ -0,0 +1,21 @@ + + + + + + + osgiconsole-1.0 + jsp-2.2 + usr:userProdtest1-1.0 + + + + + + + + + diff --git a/dev/com.ibm.ws.config_fat/publish/files/productExtensions/config/user.prod.ext.invalid.server.xml b/dev/com.ibm.ws.config_fat/publish/files/productExtensions/config/user.prod.ext.invalid.server.xml new file mode 100755 index 00000000000..5a6ed9ab59a --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/productExtensions/config/user.prod.ext.invalid.server.xml @@ -0,0 +1,22 @@ + + + + + + + osgiconsole-1.0 + jsp-2.2 + usr:userProdtest1-1.0 + + + + + + + + + + diff --git a/dev/com.ibm.ws.config_fat/publish/files/productExtensions/config/user.prod.ext.valid.server.xml b/dev/com.ibm.ws.config_fat/publish/files/productExtensions/config/user.prod.ext.valid.server.xml new file mode 100755 index 00000000000..502875504bc --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/productExtensions/config/user.prod.ext.valid.server.xml @@ -0,0 +1,21 @@ + + + + + + + osgiconsole-1.0 + jsp-2.2 + usr:userProdtest1-1.0 + + + + + + + + + diff --git a/dev/com.ibm.ws.config_fat/publish/files/productExtensions/features/prodtest1-1.0.mf b/dev/com.ibm.ws.config_fat/publish/files/productExtensions/features/prodtest1-1.0.mf new file mode 100755 index 00000000000..151b88aa1a1 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/productExtensions/features/prodtest1-1.0.mf @@ -0,0 +1,7 @@ +Subsystem-ManifestVersion: 1 +Subsystem-SymbolicName: prodtest1-1.0;visibility:=public +Subsystem-Version: 1.0.0 +Subsystem-Content: test.prod.extensions; location:="lib/test.prod.extensions_1.0.0.jar", + com.ibm.wsspi.appserver.webBundle-1.0; type="osgi.subsystem.feature" +Subsystem-Type: osgi.subsystem.feature +IBM-Feature-Version: 2 \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/files/productExtensions/features/userProdtest1-1.0.mf b/dev/com.ibm.ws.config_fat/publish/files/productExtensions/features/userProdtest1-1.0.mf new file mode 100755 index 00000000000..86604b524a0 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/productExtensions/features/userProdtest1-1.0.mf @@ -0,0 +1,8 @@ +Subsystem-ManifestVersion: 1 +IBM-ShortName:userProdtest1-1.0 +Subsystem-SymbolicName: userProdtest1-1.0; visibility:=public +Subsystem-Version: 1.0.0 +Subsystem-Content: test.user.prod.extensions; version="[1,2)", + com.ibm.wsspi.appserver.webBundle-1.0; type="osgi.subsystem.feature" +Subsystem-Type: osgi.subsystem.feature +IBM-Feature-Version: 2 diff --git a/dev/com.ibm.ws.config_fat/publish/files/productExtensions/propertiesFiles/testproduct.properties b/dev/com.ibm.ws.config_fat/publish/files/productExtensions/propertiesFiles/testproduct.properties new file mode 100755 index 00000000000..1b80aa40d23 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/productExtensions/propertiesFiles/testproduct.properties @@ -0,0 +1,2 @@ +com.ibm.websphere.productId=bigProduct +com.ibm.websphere.productInstall=wlp/producttest/ diff --git a/dev/com.ibm.ws.config_fat/publish/files/refresh/bad-server.xml b/dev/com.ibm.ws.config_fat/publish/files/refresh/bad-server.xml new file mode 100755 index 00000000000..4d368c7d5eb --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/refresh/bad-server.xml @@ -0,0 +1,5 @@ + + + < + + diff --git a/dev/com.ibm.ws.config_fat/publish/files/refresh/server.xml b/dev/com.ibm.ws.config_fat/publish/files/refresh/server.xml new file mode 100755 index 00000000000..57f7a83ea64 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/refresh/server.xml @@ -0,0 +1,27 @@ + + + + + + servlet-3.0 + localConnector-1.0 + configfatlibertyinternals-1.0 + + + + + + + + + + + + + + + diff --git a/dev/com.ibm.ws.config_fat/publish/files/restart.var/bootstrap.properties b/dev/com.ibm.ws.config_fat/publish/files/restart.var/bootstrap.properties new file mode 100755 index 00000000000..f8560d4219d --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/restart.var/bootstrap.properties @@ -0,0 +1,3 @@ +com.ibm.ws.logging.trace.specification=config=all=enabled:*=info=enabled +bootstrap.include=../testports.properties +myHttpPort=5678 diff --git a/dev/com.ibm.ws.config_fat/publish/files/restart/server.xml b/dev/com.ibm.ws.config_fat/publish/files/restart/server.xml new file mode 100755 index 00000000000..2bdbb516161 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/restart/server.xml @@ -0,0 +1,26 @@ + + + + + + servlet-3.0 + configfatlibertyinternals-1.0 + + + + + + + + + + + + + + + diff --git a/dev/com.ibm.ws.config_fat/publish/files/validator/.gitignore b/dev/com.ibm.ws.config_fat/publish/files/validator/.gitignore new file mode 100644 index 00000000000..c50fb0152d1 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/validator/.gitignore @@ -0,0 +1 @@ +/com.ibm.ws.config.ext_1.0.*.jar diff --git a/dev/com.ibm.ws.config_fat/publish/files/validator/bad-signature.xml b/dev/com.ibm.ws.config_fat/publish/files/validator/bad-signature.xml new file mode 100755 index 00000000000..28042958e00 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/validator/bad-signature.xml @@ -0,0 +1,32 @@ + + + + + + + + + + ${minVersion} + ${maxVersion} + ${minVersion} - ${maxVersion} + ${jdkVersion} + ${myMaxVersion} + + v1 + v2 + v3,v4 + v\5 + + + + + + + + + + + + +5FUDKaf7vzcTb2J4Gf//7IzVvaw=Uv6vpn399+UxEt8ORk1EAbEilfULajdkZE8KPxiEvZRalYP2T6heP6pAtZ9edMAF4F3SfggLCSjtG/rsAs0xFfTL/YWjsDND6OSRyw077j7eB9jlvyytRvza1fKUQiHoci8R5bUDlhc73m4JGJVsk7uWnFvlJmff0rdAayqb/pGo6yH55umx1CBVlap3GwP1tNIlB3gBGZ3FPZKY0IRi0Hb3fyemfwlWgNs/2O2G10KtDQiDyGNhdiyq12h4Ms0j6mbVfSVhNYKCp2GCizb7bmv1BGBeCiYTyJvESE4AaODCKmaKdAeiWU2Zdwf+hBqu28195ISZZ7uZc7vQUp0x0w==CN=WebSphere Application Server Liberty Profile,OU=Software Group,O=IBM Corp.,L=Armonk,ST=New York,C=US \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/files/validator/dropins-enabled.xml b/dev/com.ibm.ws.config_fat/publish/files/validator/dropins-enabled.xml new file mode 100755 index 00000000000..ff26fbf8176 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/validator/dropins-enabled.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + ${minVersion} + ${maxVersion} + ${minVersion} - ${maxVersion} + ${jdkVersion} + ${myMaxVersion} + + v1 + v2 + v3,v4 + v\5 + + + + + + + + + + + +f+lmvF8PXX/4/eNTplGpqNSPaJ4=jnopKWvOoQocYPJYhoYZpjSNeJRH9IQaba2loveEuTJVaHKdY4LQmDfBF8uy+kzNjL84y6VtxrsQAjHRdvzSFckg2FZfA0EbryQNwYgIZlnWrmO/QbXlb+CuMA1ITu3hhjg0toIygphzJZEk3TgxpqzxxFLvYQJ1JSIVS5Jt0eYN6Tfi5MiL5aqG8xOfBUPVSZZoYHczUq+FfMNeoFl6DO8o/0EDnXAEz1r+iQbu+Uufjic3tvVvyQ14Yji4lc/IZdtodjUciCz9DHee8C7xq2kbomWXvXLzFLiWBZT7pdxOFIjaNPxPgnb+7vZc/D7yLnAyh0cSuIY8d/2FAlFCOA==CN=WebSphere Application Server Liberty Profile,OU=Software Group,O=IBM Corp.,L=Armonk,ST=New York,C=USMIIDqDCCApCgAwIBAgIEUMJaljANBgkqhkiG9w0BAQsFADCBlTELMAkGA1UEBhMCVVMxETAPBgNVBAgTCE5ldyBZb3JrMQ8wDQYDVQQHEwZBcm1vbmsxEjAQBgNVBAoTCUlCTSBDb3JwLjEXMBUGA1UECxMOU29mdHdhcmUgR3JvdXAxNTAzBgNVBAMTLFdlYlNwaGVyZSBBcHBsaWNhdGlvbiBTZXJ2ZXIgTGliZXJ0eSBQcm9maWxlMB4XDTEyMTIwNzIxMDczNFoXDTMyMTIwMjIxMDczNFowgZUxCzAJBgNVBAYTAlVTMREwDwYDVQQIEwhOZXcgWW9yazEPMA0GA1UEBxMGQXJtb25rMRIwEAYDVQQKEwlJQk0gQ29ycC4xFzAVBgNVBAsTDlNvZnR3YXJlIEdyb3VwMTUwMwYDVQQDEyxXZWJTcGhlcmUgQXBwbGljYXRpb24gU2VydmVyIExpYmVydHkgUHJvZmlsZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJ8l5a67C3jNwuS9g0rYYJ3dDjnykECQGXgQ7sP5i9ixF0Gg6NYesjn6VUBhf8ziC/4R4yrflPID+C1nM9SsUQld5QyAjbboRCXbW6+oIofzQKzWUHQQavXOXkH3i765GlsuME2qHYT+H8SQ0S0Z2ZMQGr8PXA8lzTSvExozx+oXRXaqG97cpfNDjVZVswxR9QL5h5GdZ7INtN6OcNiKalz5cF95G4VvL1sjtRkPaupNV7C09hnw+UzdPjmxmIOkw6BbS/J0gkE+NSDjQCt1O4EalCOy1ERKMZIb3QsKyYQvebaXCm7u3aEy/yszaCwIIldSjYjM15SUQw20L5vbn/UCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAeJICZmkkBYgMqcq17+GRTWaDvKkcmBdBaIi6DDuRM31FNI7AzB2uLX2vJzXrrxPW41YturXKAZf25uKbgZOikO8e3djjCUhiLYhIm4aTJxPlrh+MejaNAwAVeZBunNrZL9VI8jtU/a1Vd9bEdQ305yXWzt5c5mfJB3Yrn0LmwYKiSfG2pERy0TVnCpNLM6iQ7O2lQLVXXwlxNthWyOavEqlK54LR1GoklhC4k1r4d/5Cc2tjsoIi1y9gZj0qZptJCM2o1RtWf/xa+MgIavH+M/FqLzphvGOoxkPOqOfgpLPhM7bpLM6xqhiqexE5Xxq0JiNaxDi5iVUoDDxXG8ZslA== \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/files/variable.error/missing-name.xml b/dev/com.ibm.ws.config_fat/publish/files/variable.error/missing-name.xml new file mode 100755 index 00000000000..6f0f5cb813e --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/variable.error/missing-name.xml @@ -0,0 +1,26 @@ + + + + + + + + + servlet-3.0 + localConnector-1.0 + configfatlibertyinternals-1.0 + + + + + + + + + + + + + + + diff --git a/dev/com.ibm.ws.config_fat/publish/files/variable.error/missing-name2.xml b/dev/com.ibm.ws.config_fat/publish/files/variable.error/missing-name2.xml new file mode 100755 index 00000000000..8719b472107 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/variable.error/missing-name2.xml @@ -0,0 +1,28 @@ + + + + + + + + + servlet-3.0 + localConnector-1.0 + configfatlibertyinternals-1.0 + + + + + + + + + + + + + + + + diff --git a/dev/com.ibm.ws.config_fat/publish/files/variable.error/missing-value.xml b/dev/com.ibm.ws.config_fat/publish/files/variable.error/missing-value.xml new file mode 100755 index 00000000000..4bd1cfa4558 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/variable.error/missing-value.xml @@ -0,0 +1,26 @@ + + + + + + + + + servlet-3.0 + localConnector-1.0 + configfatlibertyinternals-1.0 + + + + + + + + + + + + + + + diff --git a/dev/com.ibm.ws.config_fat/publish/files/variable.error/missing-value2.xml b/dev/com.ibm.ws.config_fat/publish/files/variable.error/missing-value2.xml new file mode 100755 index 00000000000..dde0025c93f --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/variable.error/missing-value2.xml @@ -0,0 +1,28 @@ + + + + + + + + + servlet-3.0 + localConnector-1.0 + configfatlibertyinternals-1.0 + + + + + + + + + + + + + + + + diff --git a/dev/com.ibm.ws.config_fat/publish/files/varmerge/allInOne.xml b/dev/com.ibm.ws.config_fat/publish/files/varmerge/allInOne.xml new file mode 100755 index 00000000000..721fa5c2a4f --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/varmerge/allInOne.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/files/varmerge/break.xml b/dev/com.ibm.ws.config_fat/publish/files/varmerge/break.xml new file mode 100755 index 00000000000..f8e8688d41c --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/varmerge/break.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/files/varmerge/break2.xml b/dev/com.ibm.ws.config_fat/publish/files/varmerge/break2.xml new file mode 100755 index 00000000000..3160ed96667 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/varmerge/break2.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/files/varmerge/ignore.xml b/dev/com.ibm.ws.config_fat/publish/files/varmerge/ignore.xml new file mode 100755 index 00000000000..f6937e46137 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/varmerge/ignore.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/files/varmerge/merge.xml b/dev/com.ibm.ws.config_fat/publish/files/varmerge/merge.xml new file mode 100755 index 00000000000..7b5d41c8760 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/varmerge/merge.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/files/varmerge/replace.xml b/dev/com.ibm.ws.config_fat/publish/files/varmerge/replace.xml new file mode 100755 index 00000000000..62c4f51c15e --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/files/varmerge/replace.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.bad/server.xml b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.bad/server.xml new file mode 100755 index 00000000000..ba1cc2db551 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.bad/server.xml @@ -0,0 +1,18 @@ + + + + + servlet-3.0 + osgiconsole-1.0 + timedexit-1.0 + + + + + + + + + + diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.casesensitivity/server.xml b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.casesensitivity/server.xml new file mode 100755 index 00000000000..b9e7ee80807 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.casesensitivity/server.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.childalias/.gitignore b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.childalias/.gitignore new file mode 100644 index 00000000000..2b09f7ba1e1 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.childalias/.gitignore @@ -0,0 +1 @@ +/apps diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.childalias/bootstrap.properties b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.childalias/bootstrap.properties new file mode 100755 index 00000000000..95e4f6aa26f --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.childalias/bootstrap.properties @@ -0,0 +1,2 @@ +com.ibm.ws.logging.trace.specification=config=all=enabled:*=info=enabled +bootstrap.include=../testports.properties diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.childalias/server.xml b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.childalias/server.xml new file mode 100755 index 00000000000..b866f31c32f --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.childalias/server.xml @@ -0,0 +1,42 @@ + + + + + + + jsp-2.2 + osgiconsole-1.0 + httpservice-2.2 + childAliasTest-1.0 + configfatlibertyinternals-1.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.delayedVar/.gitignore b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.delayedVar/.gitignore new file mode 100644 index 00000000000..2b09f7ba1e1 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.delayedVar/.gitignore @@ -0,0 +1 @@ +/apps diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.delayedVar/bootstrap.properties b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.delayedVar/bootstrap.properties new file mode 100755 index 00000000000..95e4f6aa26f --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.delayedVar/bootstrap.properties @@ -0,0 +1,2 @@ +com.ibm.ws.logging.trace.specification=config=all=enabled:*=info=enabled +bootstrap.include=../testports.properties diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.delayedVar/server.xml b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.delayedVar/server.xml new file mode 100755 index 00000000000..09a8015de23 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.delayedVar/server.xml @@ -0,0 +1,20 @@ + + + + + + jsp-2.2 + osgiconsole-1.0 + configfatlibertyinternals-1.0 + delayedVariable-1.0 + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.dropins/.gitignore b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.dropins/.gitignore new file mode 100644 index 00000000000..2b09f7ba1e1 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.dropins/.gitignore @@ -0,0 +1 @@ +/apps diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.dropins/bootstrap.properties b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.dropins/bootstrap.properties new file mode 100755 index 00000000000..95e4f6aa26f --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.dropins/bootstrap.properties @@ -0,0 +1,2 @@ +com.ibm.ws.logging.trace.specification=config=all=enabled:*=info=enabled +bootstrap.include=../testports.properties diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.dropins/server.xml b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.dropins/server.xml new file mode 100755 index 00000000000..3a13b483a63 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.dropins/server.xml @@ -0,0 +1,22 @@ + + + + + + + jsp-2.2 + osgiconsole-1.0 + httpservice-2.2 + jdbc-4.0 + + + configfatlibertyinternals-1.0 + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.extensions/bootstrap.properties b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.extensions/bootstrap.properties new file mode 100755 index 00000000000..4f1ae5a2e10 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.extensions/bootstrap.properties @@ -0,0 +1 @@ +bootstrap.include=../testports.properties diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.features/bootstrap.properties b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.features/bootstrap.properties new file mode 100755 index 00000000000..95e4f6aa26f --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.features/bootstrap.properties @@ -0,0 +1,2 @@ +com.ibm.ws.logging.trace.specification=config=all=enabled:*=info=enabled +bootstrap.include=../testports.properties diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.features/server.xml b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.features/server.xml new file mode 100755 index 00000000000..ae5eafe0b2f --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.features/server.xml @@ -0,0 +1,38 @@ + + + + + osgiConsole-1.0 + servlet-3.0 + jdbc-4.0 + localConnector-1.0 + oauth-2.0 + ssl-1.0 + openidConnectServer-1.0 + + + + + + + + + + + + + + + + + client01 + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.helper/.gitignore b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.helper/.gitignore new file mode 100644 index 00000000000..2b09f7ba1e1 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.helper/.gitignore @@ -0,0 +1 @@ +/apps diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.helper/bootstrap.properties b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.helper/bootstrap.properties new file mode 100755 index 00000000000..95e4f6aa26f --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.helper/bootstrap.properties @@ -0,0 +1,2 @@ +com.ibm.ws.logging.trace.specification=config=all=enabled:*=info=enabled +bootstrap.include=../testports.properties diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.helper/server.xml b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.helper/server.xml new file mode 100755 index 00000000000..331d606b15b --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.helper/server.xml @@ -0,0 +1,25 @@ + + + + + + + jsp-2.2 + osgiconsole-1.0 + httpservice-2.2 + + + mergedConfigTest-1.0 + + + configfatlibertyinternals-1.0 + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import.error/.gitignore b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import.error/.gitignore new file mode 100644 index 00000000000..2b09f7ba1e1 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import.error/.gitignore @@ -0,0 +1 @@ +/apps diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import.error/bootstrap.properties b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import.error/bootstrap.properties new file mode 100755 index 00000000000..9449ad31bc2 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import.error/bootstrap.properties @@ -0,0 +1,4 @@ +com.ibm.ws.logging.trace.specification=config=all=enabled:*=info=enabled +bootstrap.include=../testports.properties +relativeLocation=relative.xml +onError=FAIL diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import.error/common/common.xml b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import.error/common/common.xml new file mode 100755 index 00000000000..eae2d7b79ce --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import.error/common/common.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import.error/common/relative.xml b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import.error/common/relative.xml new file mode 100755 index 00000000000..3135a5d29dd --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import.error/common/relative.xml @@ -0,0 +1,3 @@ + + + diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import.error/common/shared.xml b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import.error/common/shared.xml new file mode 100755 index 00000000000..46748c72e4a --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import.error/common/shared.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import.error/server.xml b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import.error/server.xml new file mode 100755 index 00000000000..654abb21f83 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import.error/server.xml @@ -0,0 +1,21 @@ + + + + + + + + + servlet-3.0 + localConnector-1.0 + configfatlibertyinternals-1.0 + + + + + + + + + diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import.error/shared.xml b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import.error/shared.xml new file mode 100755 index 00000000000..90be6e11040 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import.error/shared.xml @@ -0,0 +1,4 @@ + + + + diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import/.gitignore b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import/.gitignore new file mode 100644 index 00000000000..2b09f7ba1e1 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import/.gitignore @@ -0,0 +1 @@ +/apps diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import/bootstrap.properties b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import/bootstrap.properties new file mode 100755 index 00000000000..84bdd909d92 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import/bootstrap.properties @@ -0,0 +1,3 @@ +com.ibm.ws.logging.trace.specification=config=all=enabled:*=info=enabled +bootstrap.include=../testports.properties +relativeLocation=relative.xml diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import/common/common.xml b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import/common/common.xml new file mode 100755 index 00000000000..eae2d7b79ce --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import/common/common.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import/common/relative.xml b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import/common/relative.xml new file mode 100755 index 00000000000..3135a5d29dd --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import/common/relative.xml @@ -0,0 +1,3 @@ + + + diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import/common/shared.xml b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import/common/shared.xml new file mode 100755 index 00000000000..46748c72e4a --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import/common/shared.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import/server.xml b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import/server.xml new file mode 100755 index 00000000000..41bee0d180f --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import/server.xml @@ -0,0 +1,16 @@ + + + + + + servlet-3.0 + configfatlibertyinternals-1.0 + + + + + + + + + diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import/shared.xml b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import/shared.xml new file mode 100755 index 00000000000..90be6e11040 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.import/shared.xml @@ -0,0 +1,4 @@ + + + + diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.invalidJDBCoption/bootstrap.properties b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.invalidJDBCoption/bootstrap.properties new file mode 100755 index 00000000000..95e4f6aa26f --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.invalidJDBCoption/bootstrap.properties @@ -0,0 +1,2 @@ +com.ibm.ws.logging.trace.specification=config=all=enabled:*=info=enabled +bootstrap.include=../testports.properties diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.invalidJDBCoption/server.xml b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.invalidJDBCoption/server.xml new file mode 100755 index 00000000000..84857d23bf8 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.invalidJDBCoption/server.xml @@ -0,0 +1,22 @@ + + + + + + jdbc-4.0 + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.invalidOptionalInclude/server.xml b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.invalidOptionalInclude/server.xml new file mode 100755 index 00000000000..bca129e7c18 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.invalidOptionalInclude/server.xml @@ -0,0 +1,24 @@ + + + + + + + + + jdbc-4.0 + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.merging/.gitignore b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.merging/.gitignore new file mode 100644 index 00000000000..2b09f7ba1e1 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.merging/.gitignore @@ -0,0 +1 @@ +/apps diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.merging/bootstrap.properties b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.merging/bootstrap.properties new file mode 100755 index 00000000000..95e4f6aa26f --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.merging/bootstrap.properties @@ -0,0 +1,2 @@ +com.ibm.ws.logging.trace.specification=config=all=enabled:*=info=enabled +bootstrap.include=../testports.properties diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.merging/common.xml b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.merging/common.xml new file mode 100755 index 00000000000..e3b36e57ce7 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.merging/common.xml @@ -0,0 +1,22 @@ + + + + + + + jsp-2.2 + osgiconsole-1.0 + httpservice-2.2 + mergedConfigTest-1.0 + configfatlibertyinternals-1.0 + + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.merging/conflict.xml b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.merging/conflict.xml new file mode 100755 index 00000000000..938c46720b5 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.merging/conflict.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.merging/fourLevelB.xml b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.merging/fourLevelB.xml new file mode 100755 index 00000000000..34596140a85 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.merging/fourLevelB.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.merging/fourLevelB2.xml b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.merging/fourLevelB2.xml new file mode 100755 index 00000000000..b031d93067b --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.merging/fourLevelB2.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.merging/fourLevelC.xml b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.merging/fourLevelC.xml new file mode 100755 index 00000000000..fa48b6a6de1 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.merging/fourLevelC.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.merging/fourLevelC2.xml b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.merging/fourLevelC2.xml new file mode 100755 index 00000000000..df7c921921f --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.merging/fourLevelC2.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.merging/intermediateReplace.xml b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.merging/intermediateReplace.xml new file mode 100755 index 00000000000..af7b9f26f9e --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.merging/intermediateReplace.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.merging/noConflict.xml b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.merging/noConflict.xml new file mode 100755 index 00000000000..02a08e80505 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.merging/noConflict.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.merging/server.xml b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.merging/server.xml new file mode 100755 index 00000000000..7829758b305 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.merging/server.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.metatype.provider/.gitignore b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.metatype.provider/.gitignore new file mode 100644 index 00000000000..2b09f7ba1e1 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.metatype.provider/.gitignore @@ -0,0 +1 @@ +/apps diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.metatype.provider/bootstrap.properties b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.metatype.provider/bootstrap.properties new file mode 100755 index 00000000000..95e4f6aa26f --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.metatype.provider/bootstrap.properties @@ -0,0 +1,2 @@ +com.ibm.ws.logging.trace.specification=config=all=enabled:*=info=enabled +bootstrap.include=../testports.properties diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.metatype.provider/server.xml b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.metatype.provider/server.xml new file mode 100755 index 00000000000..2fc260e93b7 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.metatype.provider/server.xml @@ -0,0 +1,21 @@ + + + + + + + servlet-3.0 + osgiconsole-1.0 + httpservice-2.2 + metatypeProviderTest-1.0 + configfatlibertyinternals-1.0 + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.product.extension/bootstrap.properties b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.product.extension/bootstrap.properties new file mode 100755 index 00000000000..c554088bab6 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.product.extension/bootstrap.properties @@ -0,0 +1,2 @@ +osgi.console=localhost:5678 +bootstrap.include=../testports.properties \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.product.extension/server.xml b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.product.extension/server.xml new file mode 100755 index 00000000000..15ad3318664 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.product.extension/server.xml @@ -0,0 +1,9 @@ + + + + + osgiconsole-1.0 + jsp-2.2 + + + diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.refresh.error/.gitignore b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.refresh.error/.gitignore new file mode 100644 index 00000000000..2b09f7ba1e1 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.refresh.error/.gitignore @@ -0,0 +1 @@ +/apps diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.refresh.error/bootstrap.properties b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.refresh.error/bootstrap.properties new file mode 100755 index 00000000000..95e4f6aa26f --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.refresh.error/bootstrap.properties @@ -0,0 +1,2 @@ +com.ibm.ws.logging.trace.specification=config=all=enabled:*=info=enabled +bootstrap.include=../testports.properties diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.refresh.error/server.xml b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.refresh.error/server.xml new file mode 100755 index 00000000000..cac904e50da --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.refresh.error/server.xml @@ -0,0 +1,22 @@ + + + + + + servlet-3.0 + localConnector-1.0 + configfatlibertyinternals-1.0 + + + + + + + + + + + + + + diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.refresh/.gitignore b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.refresh/.gitignore new file mode 100644 index 00000000000..2b09f7ba1e1 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.refresh/.gitignore @@ -0,0 +1 @@ +/apps diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.refresh/bootstrap.properties b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.refresh/bootstrap.properties new file mode 100755 index 00000000000..95e4f6aa26f --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.refresh/bootstrap.properties @@ -0,0 +1,2 @@ +com.ibm.ws.logging.trace.specification=config=all=enabled:*=info=enabled +bootstrap.include=../testports.properties diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.refresh/server.xml b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.refresh/server.xml new file mode 100755 index 00000000000..cac904e50da --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.refresh/server.xml @@ -0,0 +1,22 @@ + + + + + + servlet-3.0 + localConnector-1.0 + configfatlibertyinternals-1.0 + + + + + + + + + + + + + + diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.restart.var/.gitignore b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.restart.var/.gitignore new file mode 100644 index 00000000000..2b09f7ba1e1 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.restart.var/.gitignore @@ -0,0 +1 @@ +/apps diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.restart.var/bootstrap.properties b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.restart.var/bootstrap.properties new file mode 100755 index 00000000000..6be023c0898 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.restart.var/bootstrap.properties @@ -0,0 +1,3 @@ +com.ibm.ws.logging.trace.specification=config=all=enabled:*=info=enabled +bootstrap.include=../testports.properties +myHttpPort=1234 diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.restart.var/server.xml b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.restart.var/server.xml new file mode 100755 index 00000000000..99b80c2053e --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.restart.var/server.xml @@ -0,0 +1,18 @@ + + + + + + servlet-3.0 + localConnector-1.0 + configfatlibertyinternals-1.0 + + + + + + + + + + diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.restart/.gitignore b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.restart/.gitignore new file mode 100644 index 00000000000..2b09f7ba1e1 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.restart/.gitignore @@ -0,0 +1 @@ +/apps diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.restart/bootstrap.properties b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.restart/bootstrap.properties new file mode 100755 index 00000000000..95e4f6aa26f --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.restart/bootstrap.properties @@ -0,0 +1,2 @@ +com.ibm.ws.logging.trace.specification=config=all=enabled:*=info=enabled +bootstrap.include=../testports.properties diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.restart/server.xml b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.restart/server.xml new file mode 100755 index 00000000000..d73ddfa9a3a --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.restart/server.xml @@ -0,0 +1,21 @@ + + + + + + servlet-3.0 + configfatlibertyinternals-1.0 + + + + + + + + + + + + + + diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.schemaGen.mbean/.gitignore b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.schemaGen.mbean/.gitignore new file mode 100644 index 00000000000..5c38c69748d --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.schemaGen.mbean/.gitignore @@ -0,0 +1,2 @@ +/download_target +/dropins diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.schemaGen.mbean/bootstrap.properties b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.schemaGen.mbean/bootstrap.properties new file mode 100755 index 00000000000..72a1c9ce337 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.schemaGen.mbean/bootstrap.properties @@ -0,0 +1,20 @@ +com.ibm.ws.logging.trace.specification=*=info=enabled:\ +com.ibm.ws.config.schemagen.internal.ServerSchemaGeneratorImpl=all=enabled :\ +com.ibm.ws.jmx.connector.client.*=all=enabled:\ +com.ibm.ws.filetransfer.*=all=enabled:\ +com.ibm.ws.security.*=all=enabled:\ +com.ibm.websphere.security.*=all=enabled:\ +com.ibm.ws.webcontainer.*=all=enabled:\ +com.ibm.ws.webcontainer.security.*=all=enabled:\ +com.ibm.ws.webcontainer.security.internal.*=all=enabled:\ +com.ibm.ws.ssl.*=all=enabled:\ +SSL=all=enabled:\ +jmx.rest.server.connector=all=enabled:\ +FileTransfer=all=enabled:\ +web.*=all=enabled:\ +jmx.rest.server.connector=all=enabled:\ +logservice=all=enabled + +com.ibm.ws.logging.max.file.size=0 + +bootstrap.include=../testports.properties diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.schemaGen.mbean/server.xml b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.schemaGen.mbean/server.xml new file mode 100755 index 00000000000..df41d8e53eb --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.schemaGen.mbean/server.xml @@ -0,0 +1,17 @@ + + + + restConnector-1.0 + servlet-3.0 + + + + + + + + + + ${server.output.dir} + + diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.uniquevalueconflict/server.xml b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.uniquevalueconflict/server.xml new file mode 100755 index 00000000000..366f01211da --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.uniquevalueconflict/server.xml @@ -0,0 +1,19 @@ + + + + + + + jsp-2.2 + jdbc-4.0 + + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.update.mbean/bootstrap.properties b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.update.mbean/bootstrap.properties new file mode 100755 index 00000000000..4f1ae5a2e10 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.update.mbean/bootstrap.properties @@ -0,0 +1 @@ +bootstrap.include=../testports.properties diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.update.mbean/server.xml b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.update.mbean/server.xml new file mode 100755 index 00000000000..f58a679c61d --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.update.mbean/server.xml @@ -0,0 +1,9 @@ + + + + localConnector-1.0 + servlet-3.0 + + + + diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.update/bootstrap.properties b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.update/bootstrap.properties new file mode 100755 index 00000000000..4f1ae5a2e10 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.update/bootstrap.properties @@ -0,0 +1 @@ +bootstrap.include=../testports.properties diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.update/server.xml b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.update/server.xml new file mode 100755 index 00000000000..1ff1cba56a8 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.update/server.xml @@ -0,0 +1,9 @@ + + + + localConnector-1.0 + + + + + diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.validate/bootstrap.properties b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.validate/bootstrap.properties new file mode 100755 index 00000000000..95e4f6aa26f --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.validate/bootstrap.properties @@ -0,0 +1,2 @@ +com.ibm.ws.logging.trace.specification=config=all=enabled:*=info=enabled +bootstrap.include=../testports.properties diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.validate/common/common.xml b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.validate/common/common.xml new file mode 100755 index 00000000000..e1b01a740cf --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.validate/common/common.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.validate/full.xml b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.validate/full.xml new file mode 100755 index 00000000000..1bd852b91f9 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.validate/full.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.validate/server.xml b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.validate/server.xml new file mode 100755 index 00000000000..0c4fe350831 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.validate/server.xml @@ -0,0 +1,22 @@ + + + + + + metatype-1.0 + configfatlibertyinternals-1.0 + servlet-3.0 + appSecurity-2.0 + + + + + + + + + + + + + diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.validateConfig/bootstrap.properties b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.validateConfig/bootstrap.properties new file mode 100755 index 00000000000..4f1ae5a2e10 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.validateConfig/bootstrap.properties @@ -0,0 +1 @@ +bootstrap.include=../testports.properties diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.validateConfig/server.xml b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.validateConfig/server.xml new file mode 100755 index 00000000000..9253415a30a --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.validateConfig/server.xml @@ -0,0 +1,10 @@ + + + + localConnector-1.0 + configfatlibertyinternals-1.0 + + + + + diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.validator/bootstrap.properties b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.validator/bootstrap.properties new file mode 100755 index 00000000000..95e4f6aa26f --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.validator/bootstrap.properties @@ -0,0 +1,2 @@ +com.ibm.ws.logging.trace.specification=config=all=enabled:*=info=enabled +bootstrap.include=../testports.properties diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.validator/server.xml b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.validator/server.xml new file mode 100755 index 00000000000..0ef4ffe19bd --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.validator/server.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + ${minVersion} + ${maxVersion} + ${minVersion} - ${maxVersion} + ${jdkVersion} + ${myMaxVersion} + + v1 + v2 + v3,v4 + v\5 + + + + + + + + + + + +p1oS139FKjDhhBuzB/5HicsDCYc=WQhTMFkWpJcuqaHGLRU4yL4yNm++CxJW4BkTQu71cQgSTSrOsCyYR3lzYqEntqI6vHoaiA1t/6yKzwQ0m9L0WkgkQeWwKjWa6xgQNa2oSar/KkPkXcMVTY3KqlfgL29Vlg0Ac0Ph3F9tRPLOp6SbVrGvvEHAApjMD/5YyDLtVIB127K18yrNTRhvMQ/bzqVLLFKjdiqXF4rMXG1urqD2HWx+CS8G5T1FOoDAP0BhROD4dXbDaiiIOlTAiSwEeddRVdi2HdShi423N3eE8o7iXSBk4yXk5nneYP02mb5vBlxjxHXpdBkcJ0fnR9OdFjpOiX96bOGK+VnVbQadfoYacg==CN=WebSphere Application Server Liberty Profile,OU=Software Group,O=IBM Corp.,L=Armonk,ST=New York,C=USMIIDqDCCApCgAwIBAgIEUMJaljANBgkqhkiG9w0BAQsFADCBlTELMAkGA1UEBhMCVVMxETAPBgNVBAgTCE5ldyBZb3JrMQ8wDQYDVQQHEwZBcm1vbmsxEjAQBgNVBAoTCUlCTSBDb3JwLjEXMBUGA1UECxMOU29mdHdhcmUgR3JvdXAxNTAzBgNVBAMTLFdlYlNwaGVyZSBBcHBsaWNhdGlvbiBTZXJ2ZXIgTGliZXJ0eSBQcm9maWxlMB4XDTEyMTIwNzIxMDczNFoXDTMyMTIwMjIxMDczNFowgZUxCzAJBgNVBAYTAlVTMREwDwYDVQQIEwhOZXcgWW9yazEPMA0GA1UEBxMGQXJtb25rMRIwEAYDVQQKEwlJQk0gQ29ycC4xFzAVBgNVBAsTDlNvZnR3YXJlIEdyb3VwMTUwMwYDVQQDEyxXZWJTcGhlcmUgQXBwbGljYXRpb24gU2VydmVyIExpYmVydHkgUHJvZmlsZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJ8l5a67C3jNwuS9g0rYYJ3dDjnykECQGXgQ7sP5i9ixF0Gg6NYesjn6VUBhf8ziC/4R4yrflPID+C1nM9SsUQld5QyAjbboRCXbW6+oIofzQKzWUHQQavXOXkH3i765GlsuME2qHYT+H8SQ0S0Z2ZMQGr8PXA8lzTSvExozx+oXRXaqG97cpfNDjVZVswxR9QL5h5GdZ7INtN6OcNiKalz5cF95G4VvL1sjtRkPaupNV7C09hnw+UzdPjmxmIOkw6BbS/J0gkE+NSDjQCt1O4EalCOy1ERKMZIb3QsKyYQvebaXCm7u3aEy/yszaCwIIldSjYjM15SUQw20L5vbn/UCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAeJICZmkkBYgMqcq17+GRTWaDvKkcmBdBaIi6DDuRM31FNI7AzB2uLX2vJzXrrxPW41YturXKAZf25uKbgZOikO8e3djjCUhiLYhIm4aTJxPlrh+MejaNAwAVeZBunNrZL9VI8jtU/a1Vd9bEdQ305yXWzt5c5mfJB3Yrn0LmwYKiSfG2pERy0TVnCpNLM6iQ7O2lQLVXXwlxNthWyOavEqlK54LR1GoklhC4k1r4d/5Cc2tjsoIi1y9gZj0qZptJCM2o1RtWf/xa+MgIavH+M/FqLzphvGOoxkPOqOfgpLPhM7bpLM6xqhiqexE5Xxq0JiNaxDi5iVUoDDxXG8ZslA== \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.varmerging/.gitignore b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.varmerging/.gitignore new file mode 100644 index 00000000000..2b09f7ba1e1 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.varmerging/.gitignore @@ -0,0 +1 @@ +/apps diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.varmerging/bootstrap.properties b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.varmerging/bootstrap.properties new file mode 100755 index 00000000000..95e4f6aa26f --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.varmerging/bootstrap.properties @@ -0,0 +1,2 @@ +com.ibm.ws.logging.trace.specification=config=all=enabled:*=info=enabled +bootstrap.include=../testports.properties diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.varmerging/common.xml b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.varmerging/common.xml new file mode 100755 index 00000000000..1bf222e9900 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.varmerging/common.xml @@ -0,0 +1,19 @@ + + + + + + + jsp-2.2 + osgiconsole-1.0 + httpservice-2.2 + configfatlibertyinternals-1.0 + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.varmerging/conflict.xml b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.varmerging/conflict.xml new file mode 100755 index 00000000000..d8293e3f6d6 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.varmerging/conflict.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.varmerging/noConflict.xml b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.varmerging/noConflict.xml new file mode 100755 index 00000000000..2cb9eb36fbd --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.varmerging/noConflict.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.varmerging/server.xml b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.varmerging/server.xml new file mode 100755 index 00000000000..7829758b305 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/publish/servers/com.ibm.ws.config.varmerging/server.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/test-applications/childalias/resources/META-INF/MANIFEST.MF b/dev/com.ibm.ws.config_fat/test-applications/childalias/resources/META-INF/MANIFEST.MF new file mode 100755 index 00000000000..dac908a02fb --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-applications/childalias/resources/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Bundle-ManifestVersion: 2 +Bundle-SymbolicName: test +Import-Packages: java.io, javax.servlet, javax.servlet.http, org.osgi.framework, org.osgi.service.cm diff --git a/dev/com.ibm.ws.config_fat/test-applications/childalias/resources/META-INF/permissions.xml b/dev/com.ibm.ws.config_fat/test-applications/childalias/resources/META-INF/permissions.xml new file mode 100755 index 00000000000..5888d2ec00d --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-applications/childalias/resources/META-INF/permissions.xml @@ -0,0 +1,69 @@ + + + + + + java.io.FilePermission + ALL FILES + read,write + + + + javax.management.MBeanServerPermission + createMBeanServer + + + + java.net.SocketPermission + * + connect,resolve + + + + java.util.PropertyPermission + * + read,write + + + + java.lang.RuntimePermission + * + * + + + + org.osgi.service.cm.ConfigurationPermission + * + configure + + + + javax.security.auth.AuthPermission + * + + + + org.osgi.framework.ServicePermission + * + register,get + + + + + org.osgi.framework.AdminPermission + * + * + + + + org.osgi.framework.AdaptPermission + * + adapt + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/test-applications/childalias/resources/WEB-INF/web.xml b/dev/com.ibm.ws.config_fat/test-applications/childalias/resources/WEB-INF/web.xml new file mode 100755 index 00000000000..95bbc2c1c95 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-applications/childalias/resources/WEB-INF/web.xml @@ -0,0 +1,15 @@ + + + + + ChildAliasTestServlet + test.server.config.childalias.ChildAliasTestServlet + + + + + ChildAliasTestServlet + /child-alias-test + + + diff --git a/dev/com.ibm.ws.config_fat/test-applications/childalias/src/test/server/config/childalias/ChildAliasTestServlet.java b/dev/com.ibm.ws.config_fat/test-applications/childalias/src/test/server/config/childalias/ChildAliasTestServlet.java new file mode 100755 index 00000000000..b1a6c01a2be --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-applications/childalias/src/test/server/config/childalias/ChildAliasTestServlet.java @@ -0,0 +1,443 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package test.server.config.childalias; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import java.io.IOException; +import java.io.PrintWriter; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Dictionary; +import java.util.List; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.Constants; +import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.InvalidSyntaxException; +import org.osgi.framework.ServiceReference; +import org.osgi.service.cm.Configuration; +import org.osgi.service.cm.ConfigurationAdmin; + +import com.ibm.ws.config.xml.internal.XMLConfigConstants; + +/** + * + */ +public class ChildAliasTestServlet extends HttpServlet { + + private static final String CHILD_1_PID = "test.config.childalias.child.1"; + private static final String CHILD_2_PID = "test.config.childalias.child.2"; + private static final String CHILD_3_PID = "test.config.childalias.child.3"; + private static final String CHILD_4_PID = "test.config.childalias.child.4"; + private static final String CHILD_5_PID = "test.config.childalias.child.5"; + private static final String CHILD_6_PID = "test.config.childalias.child.6"; + private static final String PARENT_1_PID = "test.config.childalias.parent.1"; + private static final String PARENT_2_PID = "test.config.childalias.parent.2"; + private static final String PARENT_3_PID = "test.config.childalias.parent.3"; + private static final String PARENT_4_PID = "test.config.childalias.parent.4"; + private static final String PARENT_5_PID = "test.config.childalias.parent.5"; + private static final String PARENT_6_PID = "test.config.childalias.parent.6"; + private static final String TOP_LEVEL_PID = "test.config.childalias.toplevel"; + + private final ArrayList references = new ArrayList(); + private BundleContext bundleContext; + + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + PrintWriter writer = response.getWriter(); + + String testName = request.getParameter("testName"); + assertNotNull("No testName parameter specified", testName); + + Bundle bundle = FrameworkUtil.getBundle(HttpServlet.class); + + this.bundleContext = bundle.getBundleContext(); + try { + if (testName.equals("dump")) { + // Just for debugging + dump(writer); + } else { + log("Begin test: " + testName); + invokeTest(testName); + writer.println("OK"); + } + } catch (NoSuchMethodException e) { + writer.println("FAILED - Invalid test name: " + testName); + } catch (InvocationTargetException e) { + writer.println("FAILED"); + e.getTargetException().printStackTrace(writer); + } catch (Throwable e) { + writer.println("FAILED"); + e.printStackTrace(writer); + } finally { + log("End test: " + testName); + for (ServiceReference ref : references) { + bundleContext.ungetService(ref); + } + references.clear(); + } + + writer.flush(); + writer.close(); + } + + /** + * Just for manual debugging + * + * @param writer + * @throws Exception + */ + private void dump(PrintWriter writer) throws Exception { + ConfigurationAdmin ca = getConfigurationAdmin(bundleContext, references); + Configuration[] configurations; + try { + configurations = ca.listConfigurations(null); + for (Configuration c : configurations) { + writer.print("

"); + String pid = c.getFactoryPid() == null ? c.getPid() : c.getFactoryPid(); + if (pid.startsWith("test")) { + writer.println(pid); + } + } + } catch (InvalidSyntaxException e1) { + throw new IOException(e1); + } + + } + + private void invokeTest(String testName) throws Exception { + Method method = getClass().getDeclaredMethod(testName); + method.invoke(this); + } + + private ConfigurationAdmin getConfigurationAdmin(BundleContext ctx, List references) throws Exception { + ServiceReference ref = ctx.getServiceReference(ConfigurationAdmin.class); + assertNotNull("No ConfigurationAdmin service", ref); + references.add(ref); + return ctx.getService(ref); + } + + private String getFilter(String pid, boolean isFactory) { + if (isFactory) { + return "(" + ConfigurationAdmin.SERVICE_FACTORYPID + "=" + pid + ")"; + } else { + return "(" + Constants.SERVICE_PID + "=" + pid + ")"; + } + } + + public void testChildAlias1() throws Exception { + ConfigurationAdmin ca = getConfigurationAdmin(bundleContext, references); + String filter = getFilter(CHILD_1_PID, true); + Configuration[] children1 = ca.listConfigurations(filter); + assertNotNull("The configuration for " + CHILD_1_PID + " should exist", children1); + assertEquals("There should only be one instance of PID " + CHILD_1_PID, 1, children1.length); + + Configuration child1 = children1[0]; + Dictionary childProperties = child1.getProperties(); + assertEquals("The attribute value should be the correct metatype translated value", + "defaultValue", childProperties.get("defaultAttribute")); + + filter = getFilter(PARENT_1_PID, true); + Configuration[] parents = ca.listConfigurations(filter); + assertNotNull("The configuration for " + PARENT_1_PID + " should exist", parents); + assertEquals("There should be only one instance of PID " + PARENT_1_PID, 1, parents.length); + Configuration parent = parents[0]; + Dictionary parentProperties = parent.getProperties(); + assertEquals("The child's parent PID should be equal to the parent's service pid", + parentProperties.get(XMLConfigConstants.CFG_SERVICE_PID), + childProperties.get(XMLConfigConstants.CFG_PARENT_PID)); + } + + public void testChildAlias2() throws Exception { + ConfigurationAdmin ca = getConfigurationAdmin(bundleContext, references); + String filter = getFilter(CHILD_2_PID, true); + Configuration[] children2 = ca.listConfigurations(filter); + assertNotNull("The configuration for " + CHILD_2_PID + " should exist", children2); + assertEquals("There should only be one instance of PID " + CHILD_2_PID, 1, children2.length); + + Configuration child2 = children2[0]; + Dictionary child2Properties = child2.getProperties(); + assertEquals("The attribute value should be the correct metatype translated value", + "square", child2Properties.get("shape")); + assertEquals("The attribute value should be the correct value from the config", + "orange", child2Properties.get("color")); + + filter = getFilter(PARENT_2_PID, true); + Configuration[] parents2 = ca.listConfigurations(filter); + assertNotNull("The configuration for " + PARENT_2_PID + " should exist", parents2); + assertEquals("There should be only one instance of PID " + PARENT_2_PID, 1, parents2.length); + Configuration parent2 = parents2[0]; + Dictionary parent2Properties = parent2.getProperties(); + assertEquals("The child's parent PID should be equal to the parent's service pid", + parent2Properties.get(XMLConfigConstants.CFG_SERVICE_PID), + child2Properties.get(XMLConfigConstants.CFG_PARENT_PID)); + } + + public void testChildAliasSingleton1() throws Exception { + ConfigurationAdmin ca = getConfigurationAdmin(bundleContext, references); + String filter = "(" + Constants.SERVICE_PID + "=" + CHILD_3_PID + ")"; + Configuration[] children3 = ca.listConfigurations(filter); + assertNotNull("The configuration for " + CHILD_3_PID + " should exist", children3); + assertEquals("There should only be one instance of PID " + CHILD_3_PID, 1, children3.length); + + Configuration child3 = children3[0]; + Dictionary childProperties = child3.getProperties(); + assertEquals("The attribute value should be the correct metatype translated value", + "coconut", childProperties.get("defaultAttribute")); + assertNull("There should be no contamination from other singletons", childProperties.get("state")); + + filter = "(" + Constants.SERVICE_PID + "=" + PARENT_3_PID + ")"; + Configuration[] parents = ca.listConfigurations(filter); + assertNotNull("The configuration for " + PARENT_3_PID + " should exist", parents); + assertEquals("There should be only one instance of PID " + PARENT_3_PID, 1, parents.length); + Configuration parent = parents[0]; + Dictionary parentProperties = parent.getProperties(); + assertEquals("The child's parent PID should be equal to the parent's service pid", + parentProperties.get(XMLConfigConstants.CFG_SERVICE_PID), + childProperties.get(XMLConfigConstants.CFG_PARENT_PID)); + } + + public void testChildAliasSingleton2() throws Exception { + ConfigurationAdmin ca = getConfigurationAdmin(bundleContext, references); + String filter = "(" + Constants.SERVICE_PID + "=" + CHILD_4_PID + ")"; + Configuration[] children4 = ca.listConfigurations(filter); + assertNotNull("The configuration for " + CHILD_4_PID + " should exist", children4); + assertEquals("There should only be one instance of PID " + CHILD_4_PID, 1, children4.length); + + Configuration child4 = children4[0]; + Dictionary childProperties = child4.getProperties(); + assertEquals("The attribute value should be the correct metatype translated value", + "washington", childProperties.get("state")); + assertNull("There should be no contamination from other singletons", childProperties.get("defaultAttribute")); + + filter = "(" + Constants.SERVICE_PID + "=" + PARENT_4_PID + ")"; + Configuration[] parents = ca.listConfigurations(filter); + assertNotNull("The configuration for " + PARENT_4_PID + " should exist", parents); + assertEquals("There should be only one instance of PID " + PARENT_4_PID, 1, parents.length); + Configuration parent = parents[0]; + Dictionary parentProperties = parent.getProperties(); + assertEquals("The child's parent PID should be equal to the parent's service pid", + parentProperties.get(XMLConfigConstants.CFG_SERVICE_PID), + childProperties.get(XMLConfigConstants.CFG_PARENT_PID)); + } + + /** + * Simulate bundle ordering issues by loading a new feature that forces a new bundle to load. + * + * Bundle B has a parent with an unloaded child and a child with an unloaded parent. At this point, + * nothing much will be resolved, but we can verify that there is no contamination with other child + * elements with the same childAlias. + * + * @throws Exception + */ + public void testBundleOrdering1() throws Exception { + ConfigurationAdmin ca = getConfigurationAdmin(bundleContext, references); + String filter = getFilter(CHILD_5_PID, true); + Configuration[] children5 = ca.listConfigurations(filter); + assertNull("The configuration for " + CHILD_5_PID + " should not exist", children5); + + filter = getFilter(PARENT_5_PID, true); + Configuration[] parents = ca.listConfigurations(filter); + assertNull("The configuration for " + PARENT_5_PID + " should not exist", parents); + + Configuration[] children6 = ca.listConfigurations(getFilter(CHILD_6_PID, true)); + assertNull("The configuration for " + CHILD_6_PID + " should not exist", children6); + + dump(new PrintWriter(System.out)); + + Configuration[] parents6 = ca.listConfigurations(getFilter(PARENT_6_PID, true)); + assertNotNull("The configuration for " + PARENT_6_PID + " should exist", parents6); + assertEquals("There should be only one instance of PID " + PARENT_6_PID, 1, parents6.length); + Configuration parent = parents6[0]; + Dictionary parentProperties = parent.getProperties(); + String[] child6Pids = (String[]) parentProperties.get("testCAChild"); + assertNotNull(PARENT_6_PID + " should have a child element testCAChild", child6Pids); + assertEquals("There should be 1 child pid", 1, child6Pids.length); + Configuration child6Config = ca.getConfiguration(child6Pids[0]); + assertNotNull("The child for " + PARENT_6_PID + " should be available in the configuration", child6Config); + Dictionary child6Props = child6Config.getProperties(); + assertEquals("The child should not be metatype processed", "Not Default", child6Props.get("testAttribute6")); + assertNull("The child should not be metatype processed", child6Props.get("defaultSix")); + assertEquals("The child's parent PID should be equal to the parent's service pid", + parentProperties.get(XMLConfigConstants.CFG_SERVICE_PID), + child6Props.get(XMLConfigConstants.CFG_PARENT_PID)); + } + + /** + * Simulate bundle ordering issues by loading a new feature that forces a new bundle to load. + * + * Bundle C has a parent with a child in Bundle B and a child with a parent in Bundle B. All + * elements should be resolved correctly at this point. + * + * @throws Exception + */ + public void testBundleOrdering2() throws Exception { + ConfigurationAdmin ca = getConfigurationAdmin(bundleContext, references); + String filter = getFilter(CHILD_5_PID, true); + Configuration[] children5 = ca.listConfigurations(filter); + assertNotNull("The configuration for " + CHILD_5_PID + " should exist", children5); + + filter = getFilter(PARENT_5_PID, true); + Configuration[] parents = ca.listConfigurations(filter); + assertNotNull("The configuration for " + PARENT_5_PID + " should exist", parents); + + Configuration[] children6 = ca.listConfigurations(getFilter(CHILD_6_PID, true)); + assertNotNull("The configuration for " + CHILD_6_PID + " should exist", children6); + + Configuration[] parents6 = ca.listConfigurations(getFilter(PARENT_6_PID, true)); + assertNotNull("The configuration for " + PARENT_6_PID + " should exist", parents6); + assertEquals("There should be only one instance of PID " + PARENT_6_PID, 1, parents6.length); + Configuration parent = parents6[0]; + Dictionary parentProperties = parent.getProperties(); + String[] child6Pids = (String[]) parentProperties.get("testCAChild"); + assertNotNull(PARENT_6_PID + " should have a child element testCAChild", child6Pids); + assertEquals("There should be only one child pid", 1, child6Pids.length); + Configuration child6Config = ca.getConfiguration(child6Pids[0]); + assertNotNull("The child for " + PARENT_6_PID + " should be available in the configuration", child6Config); + Dictionary child6Props = child6Config.getProperties(); + assertEquals("The child should have correct properties", "Not Default", child6Props.get("testAttribute6")); + assertEquals("The child should be metatype processed", "defaultValueSix", child6Props.get("defaultSix")); + assertEquals("The child's parent PID should be equal to the parent's service pid", + parentProperties.get(XMLConfigConstants.CFG_SERVICE_PID), + child6Props.get(XMLConfigConstants.CFG_PARENT_PID)); + } + + /** + * Same scenario as testBundleOrdering2, but asserting that there are no contamination issues between the + * top level element and the child alias elements. + * + * @throws Exception + */ + public void testBundleOrderingAliasConflict() throws Exception { + ConfigurationAdmin ca = getConfigurationAdmin(bundleContext, references); + String filter = getFilter(TOP_LEVEL_PID, true); + Configuration[] topLevel = ca.listConfigurations(filter); + assertNotNull("The configuration for " + TOP_LEVEL_PID + " should exist", topLevel); + assertEquals("There should be only one instance of PID " + TOP_LEVEL_PID, 1, topLevel.length); + Configuration topLevelConfig = topLevel[0]; + Dictionary topLevelProperties = topLevelConfig.getProperties(); + + assertEquals("The element should have correct properties", "topLevel", topLevelProperties.get("location")); + assertNull("The element should not have properties from different OCDs", topLevelProperties.get("testAttribute6")); + assertNull("The element should not have properties from different OCDs", topLevelProperties.get("defaultSix")); + assertNull("The element should not have properties from different OCDs", topLevelProperties.get("country")); + assertNull("The element should not have properties from different OCDs", topLevelProperties.get("state")); + assertNull("The element should not have properties from different OCDs", topLevelProperties.get("defaultAttribute")); + assertNull("The element should not have properties from different OCDs", topLevelProperties.get("testAttribute3")); + assertNull("The element should not have properties from different OCDs", topLevelProperties.get("color")); + assertNull("The element should not have properties from different OCDs", topLevelProperties.get("shape")); + assertNull("The element should not have properties from different OCDs", topLevelProperties.get("testAttribute1")); + + assertNull("The parent pid should be null", + topLevelProperties.get(XMLConfigConstants.CFG_PARENT_PID)); + } + + public void testRemoveChild() throws Exception { + ConfigurationAdmin ca = getConfigurationAdmin(bundleContext, references); + Configuration[] parents6 = ca.listConfigurations(getFilter(PARENT_6_PID, true)); + assertNull(PARENT_6_PID + " should be removed", parents6); + + Configuration[] children6 = ca.listConfigurations(getFilter(CHILD_6_PID, true)); + assertNull(CHILD_6_PID + " should be removed", children6); + } + + public void testAddNewChild() throws Exception { + ConfigurationAdmin ca = getConfigurationAdmin(bundleContext, references); + Configuration[] parents6 = ca.listConfigurations(getFilter(PARENT_6_PID, true)); + assertNotNull(PARENT_6_PID + " should be added", parents6); + assertEquals("There should be one parent", 1, parents6.length); + Configuration parent = parents6[0]; + Dictionary parentProperties = parent.getProperties(); + String[] child6Pids = (String[]) parentProperties.get("testCAChild"); + assertNotNull(PARENT_6_PID + " should have a child element testCAChild", child6Pids); + assertEquals("There should be only one child pid", 1, child6Pids.length); + Configuration child6Config = ca.getConfiguration(child6Pids[0]); + assertNotNull("The child for " + PARENT_6_PID + " should be available in the configuration", child6Config); + Dictionary child6Props = child6Config.getProperties(); + assertEquals("The child should have correct properties", "New Child", child6Props.get("testAttribute6")); + assertEquals("The child should be metatype processed", "defaultValueSix", child6Props.get("defaultSix")); + assertEquals("The child's parent PID should be equal to the parent's service pid", + parentProperties.get(XMLConfigConstants.CFG_SERVICE_PID), + child6Props.get(XMLConfigConstants.CFG_PARENT_PID)); + + } + + public void testUpdateChild() throws Exception { + ConfigurationAdmin ca = getConfigurationAdmin(bundleContext, references); + Configuration[] children6 = ca.listConfigurations(getFilter(CHILD_6_PID, true)); + assertNotNull("The child for " + PARENT_6_PID + " should be available in the configuration", children6); + assertEquals("There should be only one child pid", 1, children6.length); + Configuration child6Config = children6[0]; + Dictionary child6Props = child6Config.getProperties(); + assertEquals("The child should have correct properties", "Updated Child", child6Props.get("testAttribute6")); + assertEquals("The child should be metatype processed", "defaultValueSix", child6Props.get("defaultSix")); + } + + public void testRemoveSingletonChild() throws Exception { + ConfigurationAdmin ca = getConfigurationAdmin(bundleContext, references); + Configuration[] parents3 = ca.listConfigurations(getFilter(PARENT_3_PID, false)); + assertNotNull(PARENT_3_PID + " should exist", parents3); + assertEquals("There should be one parent", 1, parents3.length); + + Configuration[] children3 = ca.listConfigurations(getFilter(CHILD_3_PID, false)); + // CHILD_3 has defaults. Instead of a remove taking place, the defaults will be used + assertNotNull(CHILD_3_PID + " should not be removed", children3); + assertEquals("There should be one child", 1, children3.length); + Configuration child3 = children3[0]; + Dictionary properties = child3.getProperties(); + assertEquals("Default values should be used", "coconut", properties.get("defaultAttribute")); + assertEquals("Default values should be used", "Attribute 3", properties.get("testAttribute3")); + } + + public void testAddNewSingletonChild() throws Exception { + ConfigurationAdmin ca = getConfigurationAdmin(bundleContext, references); + Configuration[] parents3 = ca.listConfigurations(getFilter(PARENT_3_PID, false)); + assertNotNull(PARENT_3_PID + " should exist", parents3); + assertEquals("There should be one parent", 1, parents3.length); + Configuration parent = parents3[0]; + Dictionary parentProperties = parent.getProperties(); + String[] child3Pids = (String[]) parentProperties.get("testCAChild"); + assertNotNull(PARENT_3_PID + " should have a child element testCAChild", child3Pids); + assertEquals("There should be only one child pid", 1, child3Pids.length); + Configuration child3Config = ca.getConfiguration(child3Pids[0]); + assertNotNull("The child for " + PARENT_3_PID + " should be available in the configuration", child3Config); + Dictionary child3Props = child3Config.getProperties(); + assertEquals("The child should have correct properties", "New Singleton Child", child3Props.get("testAttribute3")); + assertEquals("The child should be metatype processed", "coconut", child3Props.get("defaultAttribute")); + assertEquals("The child's parent PID should be equal to the parent's service pid", + parentProperties.get(XMLConfigConstants.CFG_SERVICE_PID), + child3Props.get(XMLConfigConstants.CFG_PARENT_PID)); + + } + + public void testUpdateSingletonChild() throws Exception { + ConfigurationAdmin ca = getConfigurationAdmin(bundleContext, references); + Configuration[] children3 = ca.listConfigurations(getFilter(CHILD_3_PID, false)); + assertNotNull("The child for " + PARENT_3_PID + " should be available in the configuration", children3); + assertEquals("There should be only one child pid", 1, children3.length); + Configuration child3Config = children3[0]; + Dictionary child3Props = child3Config.getProperties(); + assertEquals("The child should have correct properties", "Updated Singleton Child", child3Props.get("testAttribute3")); + assertNull("The child should not be contaminated with other singletons", child3Props.get("testAttribute1")); + assertEquals("The child should be metatype processed", "coconut", child3Props.get("defaultAttribute")); + } +} diff --git a/dev/com.ibm.ws.config_fat/test-applications/confighelper/resources/META-INF/MANIFEST.MF b/dev/com.ibm.ws.config_fat/test-applications/confighelper/resources/META-INF/MANIFEST.MF new file mode 100755 index 00000000000..9fa09933ae2 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-applications/confighelper/resources/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Bundle-ManifestVersion: 2 +Bundle-SymbolicName: test +Import-Packages: java.io, javax.servlet, javax.servlet.http, org.osgi.framework, org.osgi.service.cm, com.ibm.websphere.config diff --git a/dev/com.ibm.ws.config_fat/test-applications/confighelper/resources/META-INF/permissions.xml b/dev/com.ibm.ws.config_fat/test-applications/confighelper/resources/META-INF/permissions.xml new file mode 100755 index 00000000000..5888d2ec00d --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-applications/confighelper/resources/META-INF/permissions.xml @@ -0,0 +1,69 @@ + + + + + + java.io.FilePermission + ALL FILES + read,write + + + + javax.management.MBeanServerPermission + createMBeanServer + + + + java.net.SocketPermission + * + connect,resolve + + + + java.util.PropertyPermission + * + read,write + + + + java.lang.RuntimePermission + * + * + + + + org.osgi.service.cm.ConfigurationPermission + * + configure + + + + javax.security.auth.AuthPermission + * + + + + org.osgi.framework.ServicePermission + * + register,get + + + + + org.osgi.framework.AdminPermission + * + * + + + + org.osgi.framework.AdaptPermission + * + adapt + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/test-applications/confighelper/resources/WEB-INF/web.xml b/dev/com.ibm.ws.config_fat/test-applications/confighelper/resources/WEB-INF/web.xml new file mode 100755 index 00000000000..acc50e1908c --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-applications/confighelper/resources/WEB-INF/web.xml @@ -0,0 +1,15 @@ + + + + + WSConfigurationHelperTestServlet + test.config.helper.WSConfigurationHelperTestServlet + + + + + WSConfigurationHelperTestServlet + /helperTest + + + diff --git a/dev/com.ibm.ws.config_fat/test-applications/confighelper/src/test/config/helper/WSConfigurationHelperTestServlet.java b/dev/com.ibm.ws.config_fat/test-applications/confighelper/src/test/config/helper/WSConfigurationHelperTestServlet.java new file mode 100755 index 00000000000..3d76cf52fc2 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-applications/confighelper/src/test/config/helper/WSConfigurationHelperTestServlet.java @@ -0,0 +1,483 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ + +package test.config.helper; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.fail; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.PrintWriter; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Dictionary; +import java.util.Hashtable; +import java.util.List; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.Constants; +import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.InvalidSyntaxException; +import org.osgi.framework.ServiceReference; +import org.osgi.service.cm.Configuration; +import org.osgi.service.cm.ConfigurationAdmin; + +import com.ibm.websphere.config.WSConfigurationHelper; +import com.ibm.wsspi.kernel.service.utils.OnErrorUtil.OnError; + +/** + * + */ +public class WSConfigurationHelperTestServlet extends HttpServlet { + + /** */ + private static final long serialVersionUID = 1L; + private final ArrayList> references = new ArrayList>(); + private BundleContext bundleContext; + + /* + * (non-Javadoc) + * + * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) + */ + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + PrintWriter writer = response.getWriter(); + + String testName = request.getParameter("testName"); + assertNotNull("No testName parameter specified", testName); + + Bundle bundle = FrameworkUtil.getBundle(HttpServlet.class); + + this.bundleContext = bundle.getBundleContext(); + try { + if (testName.equals("dump")) { + // Just for debugging + dump(writer); + } else { + log("Begin test: " + testName); + invokeTest(testName); + writer.println("OK"); + } + } catch (NoSuchMethodException e) { + writer.println("FAILED - Invalid test name: " + testName); + } catch (InvocationTargetException e) { + writer.println("FAILED"); + e.getTargetException().printStackTrace(writer); + } catch (Throwable e) { + writer.println("FAILED"); + e.printStackTrace(writer); + } finally { + log("End test: " + testName); + for (ServiceReference ref : references) { + bundleContext.ungetService(ref); + } + references.clear(); + } + + writer.flush(); + writer.close(); + } + + /** + * Just for manual debugging + * + * @param writer + * @throws Exception + */ + private void dump(PrintWriter writer) throws Exception { + ConfigurationAdmin ca = getConfigurationAdmin(bundleContext, references); + Configuration[] configurations; + try { + configurations = ca.listConfigurations(null); + for (Configuration c : configurations) { + writer.print("

"); + String pid = c.getFactoryPid() == null ? c.getPid() : c.getFactoryPid(); + if (pid.startsWith("test")) { + writer.println(pid); + } + } + } catch (InvalidSyntaxException e1) { + throw new IOException(e1); + } + + } + + private void invokeTest(String testName) throws Exception { + Method method = getClass().getDeclaredMethod(testName); + method.invoke(this); + } + + private ConfigurationAdmin getConfigurationAdmin(BundleContext ctx, List> references) throws Exception { + ServiceReference ref = ctx.getServiceReference(ConfigurationAdmin.class); + assertNotNull("No ConfigurationAdmin service", ref); + references.add(ref); + return ctx.getService(ref); + } + + private WSConfigurationHelper getHelper() { + ServiceReference ref = bundleContext.getServiceReference(WSConfigurationHelper.class); + if (ref == null) { + fail("Reference to WSConfigurationHelper not found"); + return null; + } else { + return bundleContext.getService(ref); + } + } + + public void testGetDefaultProperties() throws Exception { + + String factoryPid = "com.ibm.ws.config"; + + Dictionary dictionary = getHelper().getMetaTypeDefaultProperties(factoryPid); + assertEquals(new Long(500), dictionary.get("monitorInterval")); + assertEquals("polled", dictionary.get("updateTrigger")); + assertEquals(OnError.WARN, dictionary.get("onError")); + + } + + public void testGetDefaultPropertiesWithRequired() throws Exception { + String factoryPid = "com.ibm.ws.config.test.helper"; + + Dictionary dictionary = getHelper().getMetaTypeDefaultProperties(factoryPid); + assertEquals("hello", dictionary.get("defaultVal")); + assertNull(dictionary.get("requiredVal")); + + } + + /** + * Add a default singleton, replacing a "default" singleton (not specified in server.xml, but has all required metatype defaults) + * + * @throws Exception + */ + public void testAddDefaultConfiguration1() throws Exception { + String pid = "com.ibm.ws.config"; + + Dictionary dictionary = new Hashtable(); + dictionary.put("monitorInterval", "700"); + + getHelper().addDefaultConfiguration(pid, dictionary); + + ConfigurationAdmin ca = getConfigurationAdmin(bundleContext, references); + Configuration c = ca.getConfiguration(pid); + assertEquals(new Long(700), c.getProperties().get("monitorInterval")); + + // Remove the default config we added, see that the singleton has returned to the original + getHelper().removeDefaultConfiguration(pid); + c = ca.getConfiguration(pid); + assertEquals(new Long(500), c.getProperties().get("monitorInterval")); + } + + /** + * Add a default factory config for a pid that didn't previously exist + * + * @throws Exception + */ + public void testAddDefaultConfiguration2() throws Exception { + String factoryPid = "com.ibm.ws.config.test.helper"; + Dictionary dictionary = new Hashtable(); + dictionary.put("requiredVal", "goodbye"); + + getHelper().addDefaultConfiguration(factoryPid, dictionary); + + ConfigurationAdmin ca = getConfigurationAdmin(bundleContext, references); + Configuration[] configs = ca.listConfigurations(getFilter(factoryPid, true)); + assertEquals(1, configs.length); + Dictionary props = configs[0].getProperties(); + assertEquals("goodbye", props.get("requiredVal")); + assertEquals("hello", props.get("defaultVal")); + + // Remove the default configuration, verify that the config goes away + getHelper().removeDefaultConfiguration(factoryPid); + configs = ca.listConfigurations(getFilter(factoryPid, true)); + assertNull(configs); + + } + + /** + * Add a default factory config for a pid that did exist. Values should be merged + * + * @throws Exception + */ + public void testAddDefaultConfiguration3() throws Exception { + String factoryPid = "com.ibm.example.topLevelElement"; + + Dictionary dictionary = new Hashtable(); + dictionary.put("id", "top"); + dictionary.put("drink", "coffee"); + + getHelper().addDefaultConfiguration(factoryPid, dictionary); + + ConfigurationAdmin ca = getConfigurationAdmin(bundleContext, references); + Configuration[] configs = ca.listConfigurations(getFilter(factoryPid, true)); + assertEquals(1, configs.length); + Dictionary props = configs[0].getProperties(); + assertEquals("top", props.get("id")); + // From new default config + assertEquals("coffee", props.get("drink")); + // From server.xml + assertEquals("scone", props.get("food")); + // From metatype defaults, both instances + assertEquals("value", props.get("attribute")); + + // Remove the default configuration, see that the config has returned to the values in server.xml + getHelper().removeDefaultConfiguration(factoryPid); + + configs = ca.listConfigurations(getFilter(factoryPid, true)); + assertEquals(1, configs.length); + props = configs[0].getProperties(); + assertEquals("top", props.get("id")); + // From new default config + assertNull(props.get("drink")); + // From server.xml + assertEquals("scone", props.get("food")); + // From metatype defaults, both instances + assertEquals("value", props.get("attribute")); + } + + /** + * Add two default configurations, same pid, distinct ids + * + * @throws Exception + */ + public void testAddDefaultConfiguration4() throws Exception { + String factoryPid = "com.ibm.example.topLevelElement"; + + Dictionary dictionary = new Hashtable(); + dictionary.put("id", "top"); + dictionary.put("drink", "coffee"); + + WSConfigurationHelper helper = getHelper(); + helper.addDefaultConfiguration(factoryPid, dictionary); + dictionary.put("id", "top2"); + dictionary.put("drink", "tea"); + helper.addDefaultConfiguration(factoryPid, dictionary); + + ConfigurationAdmin ca = getConfigurationAdmin(bundleContext, references); + Configuration[] configs = ca.listConfigurations(getFilter(factoryPid, true)); + assertEquals(2, configs.length); + + for (Configuration config : configs) { + Dictionary props = config.getProperties(); + String id = (String) props.get("id"); + if ("top".equals(id)) { + // From new default config + assertEquals("coffee", props.get("drink")); + // From server.xml + assertEquals("scone", props.get("food")); + // From metatype defaults, both instances + assertEquals("value", props.get("attribute")); + } else if ("top2".equals(id)) { + assertEquals("tea", props.get("drink")); + assertNull(props.get("food")); + assertEquals("value", props.get("attribute")); + } else { + fail("Unrecognized id: " + id); + } + } + + // Remove the default configuration, see that the config has returned to the values in server.xml + getHelper().removeDefaultConfiguration(factoryPid); + + configs = ca.listConfigurations(getFilter(factoryPid, true)); + assertEquals(1, configs.length); + Dictionary props = configs[0].getProperties(); + assertEquals("top", props.get("id")); + // From new default config + assertNull(props.get("drink")); + // From server.xml + assertEquals("scone", props.get("food")); + // From metatype defaults, both instances + assertEquals("value", props.get("attribute")); + } + + /** + * Add factory pid with default id and ibm:extends + * + * @throws Exception + */ + public void testAddDefaultConfiguration5() throws Exception { + String factoryPid = "com.ibm.example.child.a"; + String superPid = "com.ibm.example.supertype"; + Dictionary dictionary = new Hashtable(); + dictionary.put("attrA1", "goodbye"); + + getHelper().addDefaultConfiguration(factoryPid, dictionary); + + ConfigurationAdmin ca = getConfigurationAdmin(bundleContext, references); + Configuration[] configs = ca.listConfigurations(getFilter(factoryPid, true)); + assertEquals(1, configs.length); + Dictionary props = configs[0].getProperties(); + assertEquals("goodbye", props.get("attrA1")); + assertEquals("value2", props.get("attrA2")); + + configs = ca.listConfigurations(getFilter(superPid, true)); + assertEquals(1, configs.length); + props = configs[0].getProperties(); + assertEquals("goodbye", props.get("attrA1")); + assertEquals("value2", props.get("attrA2")); + + // Remove the default configuration, verify that the config goes away + getHelper().removeDefaultConfiguration(factoryPid); + configs = ca.listConfigurations(getFilter(factoryPid, true)); + assertNull(configs); + configs = ca.listConfigurations(getFilter(superPid, true)); + assertNull(configs); + + } + + /** + * Add default configuration for a pid that doesn't have metatype. It shouldn't exist in + * config admin. Then remove the default configuration and verify that it still isn't there. + * + * @throws Exception + */ + public void testAddDefaultConfiguration6() throws Exception { + String factoryPid = "nonMetatype"; + Dictionary dictionary = new Hashtable(); + dictionary.put("attrA1", "goodbye"); + + getHelper().addDefaultConfiguration(factoryPid, dictionary); + + ConfigurationAdmin ca = getConfigurationAdmin(bundleContext, references); + Configuration[] configs = ca.listConfigurations(getFilter(factoryPid, true)); + assertNull("The non-metatype configuration should not exist", configs); + + // Remove the default configuration, verify that the config still doesn't exist + getHelper().removeDefaultConfiguration(factoryPid); + configs = ca.listConfigurations(getFilter(factoryPid, true)); + assertNull(configs); + } + + /** + * Add a default factory nested config for a parent that did exist. Values should be merged + * + * Using metatype from metatype-nested-merge.xml + * + * @throws Exception + */ + public void testAddDefaultConfiguration7() throws Exception { + String parentPid = "test.nestedmerge.parent.ONE"; + String childPid = "test.nestedmerge.child"; + + String xml = "" + + " " + + "" + + "" + + ""; + + ByteArrayInputStream bais = new ByteArrayInputStream(xml.getBytes()); + + getHelper().addDefaultConfiguration(bais); + + ConfigurationAdmin ca = getConfigurationAdmin(bundleContext, references); + Configuration[] configs = ca.listConfigurations(getFilter(childPid, true)); + assertNotNull("The child configuration should exist", configs); + assertEquals(1, configs.length); + Dictionary props = configs[0].getProperties(); + assertEquals("child", props.get("id")); + // From new default config + assertEquals("coffee", props.get("someAttr")); + + // Remove the default configuration, see that the config has returned to the values in server.xml + + getHelper().removeDefaultConfiguration(parentPid); + + configs = ca.listConfigurations(getFilter(parentPid, true)); + assertEquals(1, configs.length); + props = configs[0].getProperties(); + assertEquals("one", props.get("id")); + + assertNull("The child element should not exist as a property on the parent", props.get("child")); + + configs = ca.listConfigurations(getFilter(childPid, true)); + assertNull("The child element should not exist", configs); + } + + /** + * Add a default factory nested config for a parent that doesn't exist with the same id. An instance of the + * parent and child should be added by addDefaultConfiguration, and both should be removed by remove + * + * Using metatype from metatype-nested-merge.xml + * + * @throws Exception + */ + public void testAddDefaultConfiguration8() throws Exception { + String parentPid = "test.nestedmerge.parent.ONE"; + String childPid = "test.nestedmerge.child"; + + String xml = "" + + " " + + "" + + "" + + ""; + + ByteArrayInputStream bais = new ByteArrayInputStream(xml.getBytes()); + + getHelper().addDefaultConfiguration(bais); + + ConfigurationAdmin ca = getConfigurationAdmin(bundleContext, references); + Configuration[] configs = ca.listConfigurations(getFilter(parentPid, true)); + assertNotNull("the parent configurations should exist", configs); + assertEquals(2, configs.length); + + // Get the properties for the parent with id "two" + Dictionary props = configs[0].getProperties(); + if ("one".equals(props.get("id"))) + props = configs[1].getProperties(); + assertEquals("two", props.get("id")); + String childServicePid = (String) props.get("child"); + assertNotNull("The child should exist as a property on the parent", childServicePid); + + // Get the child configuration + configs = ca.listConfigurations(getFilter(childPid, true)); + assertNotNull("The child configuration should exist", configs); + assertEquals(1, configs.length); + props = configs[0].getProperties(); + assertEquals("child", props.get("id")); + // From new default config + assertEquals("coffee", props.get("someAttr")); + assertEquals(childServicePid, props.get("service.pid")); + + // Remove the default configuration, see that the config has returned to the values in server.xml + + getHelper().removeDefaultConfiguration(parentPid); + + configs = ca.listConfigurations(getFilter(parentPid, true)); + assertEquals(1, configs.length); + props = configs[0].getProperties(); + assertEquals("one", props.get("id")); + + assertNull("The child element should not exist as a property on the parent", props.get("child")); + + configs = ca.listConfigurations(getFilter(childPid, true)); + assertNull("The child element should not exist", configs); + } + + private String getFilter(String pid, boolean isFactory) { + if (isFactory) { + return "(" + ConfigurationAdmin.SERVICE_FACTORYPID + "=" + pid + ")"; + } else { + return "(" + Constants.SERVICE_PID + "=" + pid + ")"; + } + } +} diff --git a/dev/com.ibm.ws.config_fat/test-applications/dropins/resources/META-INF/MANIFEST.MF b/dev/com.ibm.ws.config_fat/test-applications/dropins/resources/META-INF/MANIFEST.MF new file mode 100755 index 00000000000..dac908a02fb --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-applications/dropins/resources/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Bundle-ManifestVersion: 2 +Bundle-SymbolicName: test +Import-Packages: java.io, javax.servlet, javax.servlet.http, org.osgi.framework, org.osgi.service.cm diff --git a/dev/com.ibm.ws.config_fat/test-applications/dropins/resources/META-INF/permissions.xml b/dev/com.ibm.ws.config_fat/test-applications/dropins/resources/META-INF/permissions.xml new file mode 100755 index 00000000000..5888d2ec00d --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-applications/dropins/resources/META-INF/permissions.xml @@ -0,0 +1,69 @@ + + + + + + java.io.FilePermission + ALL FILES + read,write + + + + javax.management.MBeanServerPermission + createMBeanServer + + + + java.net.SocketPermission + * + connect,resolve + + + + java.util.PropertyPermission + * + read,write + + + + java.lang.RuntimePermission + * + * + + + + org.osgi.service.cm.ConfigurationPermission + * + configure + + + + javax.security.auth.AuthPermission + * + + + + org.osgi.framework.ServicePermission + * + register,get + + + + + org.osgi.framework.AdminPermission + * + * + + + + org.osgi.framework.AdaptPermission + * + adapt + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/test-applications/dropins/resources/WEB-INF/web.xml b/dev/com.ibm.ws.config_fat/test-applications/dropins/resources/WEB-INF/web.xml new file mode 100755 index 00000000000..5b8510ae6c7 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-applications/dropins/resources/WEB-INF/web.xml @@ -0,0 +1,15 @@ + + + + + ConfigDropinsTestServlet + test.config.dropins.ConfigDropinsServlet + + + + + ConfigDropinsTestServlet + /dropinsTest + + + diff --git a/dev/com.ibm.ws.config_fat/test-applications/dropins/src/test/config/dropins/ConfigDropinsServlet.java b/dev/com.ibm.ws.config_fat/test-applications/dropins/src/test/config/dropins/ConfigDropinsServlet.java new file mode 100755 index 00000000000..d44face709c --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-applications/dropins/src/test/config/dropins/ConfigDropinsServlet.java @@ -0,0 +1,218 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ + +package test.config.dropins; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.IOException; +import java.io.PrintWriter; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Dictionary; +import java.util.List; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.Constants; +import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.InvalidSyntaxException; +import org.osgi.framework.ServiceReference; +import org.osgi.service.cm.Configuration; +import org.osgi.service.cm.ConfigurationAdmin; + +/** + * + */ +public class ConfigDropinsServlet extends HttpServlet { + + private static final String LIBRARY_PID = "com.ibm.ws.classloading.sharedlibrary"; + private final ArrayList> references = new ArrayList>(); + private BundleContext bundleContext; + + /* + * (non-Javadoc) + * + * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) + */ + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + PrintWriter writer = response.getWriter(); + + String testName = request.getParameter("testName"); + assertNotNull("No testName parameter specified", testName); + + Bundle bundle = FrameworkUtil.getBundle(HttpServlet.class); + + this.bundleContext = bundle.getBundleContext(); + try { + if (testName.equals("dump")) { + // Just for debugging + dump(writer); + } else { + log("Begin test: " + testName); + invokeTest(testName); + writer.println("OK"); + } + } catch (NoSuchMethodException e) { + writer.println("FAILED - Invalid test name: " + testName); + } catch (InvocationTargetException e) { + writer.println("FAILED"); + e.getTargetException().printStackTrace(writer); + } catch (Throwable e) { + writer.println("FAILED"); + e.printStackTrace(writer); + } finally { + log("End test: " + testName); + for (ServiceReference ref : references) { + bundleContext.ungetService(ref); + } + references.clear(); + } + + writer.flush(); + writer.close(); + } + + /** + * Just for manual debugging + * + * @param writer + * @throws Exception + */ + private void dump(PrintWriter writer) throws Exception { + ConfigurationAdmin ca = getConfigurationAdmin(bundleContext, references); + Configuration[] configurations; + try { + configurations = ca.listConfigurations(null); + for (Configuration c : configurations) { + writer.print("

"); + String pid = c.getFactoryPid() == null ? c.getPid() : c.getFactoryPid(); + if (pid.startsWith("test")) { + writer.println(pid); + } + } + } catch (InvalidSyntaxException e1) { + throw new IOException(e1); + } + + } + + private void invokeTest(String testName) throws Exception { + Method method = getClass().getDeclaredMethod(testName); + method.invoke(this); + } + + private ConfigurationAdmin getConfigurationAdmin(BundleContext ctx, List> references) throws Exception { + ServiceReference ref = ctx.getServiceReference(ConfigurationAdmin.class); + assertNotNull("No ConfigurationAdmin service", ref); + references.add(ref); + return ctx.getService(ref); + } + + private String getFilter(String pid, boolean isFactory) { + if (isFactory) { + return "(" + ConfigurationAdmin.SERVICE_FACTORYPID + "=" + pid + ")"; + } else { + return "(" + Constants.SERVICE_PID + "=" + pid + ")"; + } + } + + public void testNonXmlFile() throws Exception { + // Make sure that we don't load files with extensions other than .xml + checkLibraryValue(TEST1, SERVER); + } + + public void testBrokenDropin() throws Exception { + // We should continue to parse server.xml and dropins after encountering a broken file + checkLibraryValue(TEST1, SIMPLE); + } + + public void testSimpleDefaults() throws Exception { + // Value specified for library description in dropin defaults is overridden + checkLibraryValue(TEST1, SERVER); + } + + public void testSimpleOverrides() throws Exception { + // Value specified for library description in dropin overrides is used instead of server.xml + checkLibraryValue(TEST1, SIMPLE); + } + + public void testSimpleOverrides2() throws Exception { + // Value specified for library description in dropin overrides is used instead of server.xml or default dropins + checkLibraryValue(TEST1, SIMPLE2); + } + + public void testDefaultsOrdering() throws Exception { + // Value from server.xml is used. Not testing much here, just sanity. + checkLibraryValue(TEST1, SERVER); + } + + public void testOverridesOrdering() throws Exception { + // Value from simple2.xml in overrides is used rather than simple.xml from overrides or server.xml. + checkLibraryValue(TEST1, SIMPLE2); + } + + public void testNoServerValue1() throws Exception { + // File in defaults, no value in server.xml, use default value + checkLibraryValue(TEST2, A); + } + + public void testNoServerValue2() throws Exception { + // File in overrides, no value in server.xml, use overrides value + checkLibraryValue(TEST2, A); + } + + public void testNoServerValue3() throws Exception { + // Files in defaults and overrides, no value in server.xml, use overrides value + checkLibraryValue(TEST2, B); + } + + private void checkLibraryValue(String libraryID, String description) throws Exception { + + ConfigurationAdmin ca = getConfigurationAdmin(bundleContext, references); + Configuration[] configs = ca.listConfigurations(getFilter(LIBRARY_PID, true)); + if (configs == null) + fail("Could not find library configuration"); + + boolean found = false; + for (Configuration config : configs) { + Dictionary props = config.getProperties(); + String id = (String) props.get("id"); + if (libraryID.equals(id)) { + assertEquals("The description should be from simple.xml", description, props.get("description")); + found = true; + } + } + + assertTrue("The configuration for the library with ID testLibrary should exist", found); + + } + + private static final String TEST1 = "testLibrary"; + private static final String TEST2 = "testLibrary2"; + + private static final String SIMPLE = "Library From Simple.xml"; + private static final String SIMPLE2 = "Library from simple2.xml"; + private static final String SERVER = "Library from server.xml"; + private static final String A = "Library A"; + private static final String B = "Library B"; +} diff --git a/dev/com.ibm.ws.config_fat/test-applications/mbeans/resources/META-INF/MANIFEST.MF b/dev/com.ibm.ws.config_fat/test-applications/mbeans/resources/META-INF/MANIFEST.MF new file mode 100755 index 00000000000..5ff6e91bf81 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-applications/mbeans/resources/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Bundle-ManifestVersion: 2 +Bundle-SymbolicName: test +Import-Packages: java.io, javax.servlet, javax.servlet.http, java.net, javax.management, com.ibm.websphere.config.mbeans, com.ibm.ws.jmx.connector.client.rest diff --git a/dev/com.ibm.ws.config_fat/test-applications/mbeans/resources/META-INF/permissions.xml b/dev/com.ibm.ws.config_fat/test-applications/mbeans/resources/META-INF/permissions.xml new file mode 100755 index 00000000000..5888d2ec00d --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-applications/mbeans/resources/META-INF/permissions.xml @@ -0,0 +1,69 @@ + + + + + + java.io.FilePermission + ALL FILES + read,write + + + + javax.management.MBeanServerPermission + createMBeanServer + + + + java.net.SocketPermission + * + connect,resolve + + + + java.util.PropertyPermission + * + read,write + + + + java.lang.RuntimePermission + * + * + + + + org.osgi.service.cm.ConfigurationPermission + * + configure + + + + javax.security.auth.AuthPermission + * + + + + org.osgi.framework.ServicePermission + * + register,get + + + + + org.osgi.framework.AdminPermission + * + * + + + + org.osgi.framework.AdaptPermission + * + adapt + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/test-applications/mbeans/resources/WEB-INF/web.xml b/dev/com.ibm.ws.config_fat/test-applications/mbeans/resources/WEB-INF/web.xml new file mode 100755 index 00000000000..5ee7921067f --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-applications/mbeans/resources/WEB-INF/web.xml @@ -0,0 +1,16 @@ + + + + + AppClientServletSchemaGen + web.AppClientServletSchemaGen + + + + + AppClientServletSchemaGen + /appClient + + + + diff --git a/dev/com.ibm.ws.config_fat/test-applications/mbeans/src/web/AppClientServletSchemaGen.java b/dev/com.ibm.ws.config_fat/test-applications/mbeans/src/web/AppClientServletSchemaGen.java new file mode 100755 index 00000000000..155fb8fffe7 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-applications/mbeans/src/web/AppClientServletSchemaGen.java @@ -0,0 +1,163 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012, 2014 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package web; + +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.net.URLDecoder; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +import javax.management.JMX; +import javax.management.MBeanServerConnection; +import javax.management.ObjectName; +import javax.management.remote.JMXConnector; +import javax.management.remote.JMXConnectorFactory; +import javax.management.remote.JMXServiceURL; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.ibm.websphere.config.mbeans.ServerSchemaGenerator; +import com.ibm.websphere.filetransfer.FileTransferMBean; +import com.ibm.ws.jmx.connector.client.rest.ClientProvider; + +@SuppressWarnings("serial") +public class AppClientServletSchemaGen extends HttpServlet { + + private static MBeanServerConnection mbsc; + private static final String SUCCESS_MESSAGE = "Setup completed successfully."; + + private static final long MIN_FILE_SIZE = 500000; + + /** + * Uses the JMX REST connector client from within a user-application to test + * the functionality of com.ibm.websphere.config.mbeans.ServerSchemaGenerator + */ + @Override + protected void doGet(HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException { + boolean successful = false; + String failureMessage = null; + + try { + + String serverRoot = URLDecoder.decode(request.getParameter("serverRoot"), "UTF-8"); + System.out.println("Server root:" + serverRoot); + System.setProperty("javax.net.ssl.trustStore", serverRoot + "/resources/security/key.jks"); + System.setProperty("javax.net.ssl.trustStorePassword", "Liberty"); + Map environment = new HashMap(); + environment.put("jmx.remote.protocol.provider.pkgs", "com.ibm.ws.jmx.connector.client"); + environment.put(JMXConnector.CREDENTIALS, new String[] { "theUser", "thePassword" }); + environment.put(ClientProvider.DISABLE_HOSTNAME_VERIFICATION, true); + environment.put(ClientProvider.READ_TIMEOUT, 2 * 60 * 1000); + JMXServiceURL url = new JMXServiceURL("REST", request.getServerName(), request.getServerPort(), "/IBMJMXConnectorREST"); + JMXConnector jmxConnector = JMXConnectorFactory.connect(url, environment); + mbsc = jmxConnector.getMBeanServerConnection(); + + //---------------------------------------===== + // Invoke MBean using MBeanServerConnection + //---------------------------------------===== + + //Invoke schema generation + Object[] params = new String[] { "1.0", "1", "UTF-8", Locale.getDefault().toString() }; //schemaVersion, outputVersion, encoding, locale + String[] signature = new String[] { "java.lang.String", "java.lang.String", "java.lang.String", "java.lang.String" }; + + final ObjectName SCHEMA_GEN_MBEAN = new ObjectName(ServerSchemaGenerator.OBJECT_NAME); + + @SuppressWarnings("unchecked") + Map returnedMap = (Map) mbsc.invoke(SCHEMA_GEN_MBEAN, "generateInstallSchema", params, signature); + + //Check return code + if ((Integer) returnedMap.get(ServerSchemaGenerator.KEY_RETURN_CODE) != 0) { + throw new RuntimeException("Invoke MBean - Generate schema call did not return successful return_code"); + } + + //Ensure the file is bigger than expected minimum size + String filePath = (String) returnedMap.get(ServerSchemaGenerator.KEY_FILE_PATH); + File file = new File(filePath); + if (file.length() < MIN_FILE_SIZE) { + throw new RuntimeException("Invoke MBean - Generated schema file is less than expected size. File=" + file.getAbsolutePath() + + " : size=" + file.length()); + } + + //--------------------------------------- + // Call operations using the API + //--------------------------------------- + + ServerSchemaGenerator schemaGenMBean = JMX.newMBeanProxy(mbsc, SCHEMA_GEN_MBEAN, ServerSchemaGenerator.class); + returnedMap = schemaGenMBean.generateInstallSchema(null, null, null, null); //schemaVersion, outputVersion, encoding, locale + + if ((Integer) returnedMap.get(ServerSchemaGenerator.KEY_RETURN_CODE) != 0) { + throw new RuntimeException("MBean via API - Generate schema call did not return successful return_code"); + } + + //Ensure the file is bigger than expected minimum size + String sourcePath = (String) returnedMap.get(ServerSchemaGenerator.KEY_FILE_PATH); + file = new File(sourcePath); + + if (file.length() < MIN_FILE_SIZE) { + throw new RuntimeException("MBean via API - Generated schema file is less than expected size. File=" + file.getAbsolutePath() + + " : size=" + file.length()); + } + + //Download generated file (typical user operation) + String targetPath = serverRoot + "/download_target/schemaServletCallAPI.xsd"; + + final ObjectName FILE_TRN_MBEAN = new ObjectName(FileTransferMBean.OBJECT_NAME); + FileTransferMBean fileTrnMBean = JMX.newMBeanProxy(mbsc, FILE_TRN_MBEAN, FileTransferMBean.class); + fileTrnMBean.downloadFile(sourcePath, targetPath); + + //Ensure downloaded file is bigger than expected minimum size + file = new File(targetPath); + + if (file.length() < MIN_FILE_SIZE) { + throw new RuntimeException("MBean via API - Downloaded schema file is less than expected size. File=" + file.getAbsolutePath() + + " : size=" + file.length()); + } + + // Delete the source file under logs/state + file = new File(sourcePath); + + // First check if the file exists + if (!file.exists()) { + throw new RuntimeException("MBean via API - Generated schema file does not exist (before deletion). File=" + file.getAbsolutePath()); + } + + fileTrnMBean.deleteFile(sourcePath); + + //Verify the file is deleted + if (file.exists()) { + throw new RuntimeException("MBean via API - Generated schema file was not deleted. File=" + file.getAbsolutePath() + " : size=" + file.length()); + } + + jmxConnector.close(); + + successful = true; + + } catch (Throwable t) { + StringWriter sw = new StringWriter(); + t.printStackTrace(new PrintWriter(sw)); + failureMessage = sw.toString(); + } + + PrintWriter writer = response.getWriter(); + writer.println(successful ? SUCCESS_MESSAGE : failureMessage); + writer.flush(); + writer.close(); + } + +} diff --git a/dev/com.ibm.ws.config_fat/test-applications/mergedconfig/resources/META-INF/MANIFEST.MF b/dev/com.ibm.ws.config_fat/test-applications/mergedconfig/resources/META-INF/MANIFEST.MF new file mode 100755 index 00000000000..dac908a02fb --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-applications/mergedconfig/resources/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Bundle-ManifestVersion: 2 +Bundle-SymbolicName: test +Import-Packages: java.io, javax.servlet, javax.servlet.http, org.osgi.framework, org.osgi.service.cm diff --git a/dev/com.ibm.ws.config_fat/test-applications/mergedconfig/resources/META-INF/permissions.xml b/dev/com.ibm.ws.config_fat/test-applications/mergedconfig/resources/META-INF/permissions.xml new file mode 100755 index 00000000000..5888d2ec00d --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-applications/mergedconfig/resources/META-INF/permissions.xml @@ -0,0 +1,69 @@ + + + + + + java.io.FilePermission + ALL FILES + read,write + + + + javax.management.MBeanServerPermission + createMBeanServer + + + + java.net.SocketPermission + * + connect,resolve + + + + java.util.PropertyPermission + * + read,write + + + + java.lang.RuntimePermission + * + * + + + + org.osgi.service.cm.ConfigurationPermission + * + configure + + + + javax.security.auth.AuthPermission + * + + + + org.osgi.framework.ServicePermission + * + register,get + + + + + org.osgi.framework.AdminPermission + * + * + + + + org.osgi.framework.AdaptPermission + * + adapt + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/test-applications/mergedconfig/resources/WEB-INF/web.xml b/dev/com.ibm.ws.config_fat/test-applications/mergedconfig/resources/WEB-INF/web.xml new file mode 100755 index 00000000000..b19c07b70cb --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-applications/mergedconfig/resources/WEB-INF/web.xml @@ -0,0 +1,15 @@ + + + + + MergedConfigTestServlet + test.config.merged.MergedConfigTestServlet + + + + + MergedConfigTestServlet + /mergedConfigTest + + + diff --git a/dev/com.ibm.ws.config_fat/test-applications/mergedconfig/src/test/config/merged/MergedConfigTestServlet.java b/dev/com.ibm.ws.config_fat/test-applications/mergedconfig/src/test/config/merged/MergedConfigTestServlet.java new file mode 100755 index 00000000000..b194ec66d89 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-applications/mergedconfig/src/test/config/merged/MergedConfigTestServlet.java @@ -0,0 +1,304 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ + +package test.config.merged; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.fail; + +import java.io.IOException; +import java.io.PrintWriter; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Dictionary; +import java.util.List; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.Constants; +import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.InvalidSyntaxException; +import org.osgi.framework.ServiceReference; +import org.osgi.service.cm.Configuration; +import org.osgi.service.cm.ConfigurationAdmin; + +/** + * + */ +public class MergedConfigTestServlet extends HttpServlet { + + /** */ + private static final long serialVersionUID = 4084916808353306371L; + private final ArrayList> references = new ArrayList>(); + private BundleContext bundleContext; + + public static final String PARENT_PID = "com.ibm.example.topLevelElement"; + public static final String CHILD_A_PID = "com.ibm.example.child.a"; + public static final String CHILD_B_PID = "com.ibm.example.child.b"; + public static final String CHILD_C_PID = "com.ibm.example.child.c"; + public static final String PARENT_D_PID = "com.ibm.example.top.d"; + private static final String DEFAULT_PID = "com.ibm.example.default"; + private static final String DEFAULT_MISSING_PID = "com.ibm.example.default.missing"; + + /* + * (non-Javadoc) + * + * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) + */ + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + PrintWriter writer = response.getWriter(); + + String testName = request.getParameter("testName"); + assertNotNull("No testName parameter specified", testName); + + Bundle bundle = FrameworkUtil.getBundle(HttpServlet.class); + + this.bundleContext = bundle.getBundleContext(); + try { + if (testName.equals("dump")) { + // Just for debugging + dump(writer); + } else { + log("Begin test: " + testName); + invokeTest(testName); + writer.println("OK"); + } + } catch (NoSuchMethodException e) { + writer.println("FAILED - Invalid test name: " + testName); + } catch (InvocationTargetException e) { + writer.println("FAILED"); + e.getTargetException().printStackTrace(writer); + } catch (Throwable e) { + writer.println("FAILED"); + e.printStackTrace(writer); + } finally { + log("End test: " + testName); + for (ServiceReference ref : references) { + bundleContext.ungetService(ref); + } + references.clear(); + } + + writer.flush(); + writer.close(); + } + + /** + * Just for manual debugging + * + * @param writer + * @throws Exception + */ + private void dump(PrintWriter writer) throws Exception { + ConfigurationAdmin ca = getConfigurationAdmin(bundleContext, references); + Configuration[] configurations; + try { + configurations = ca.listConfigurations(null); + for (Configuration c : configurations) { + writer.print("

"); + String pid = c.getFactoryPid() == null ? c.getPid() : c.getFactoryPid(); + if (pid.startsWith("test")) { + writer.println(pid); + } + } + } catch (InvalidSyntaxException e1) { + throw new IOException(e1); + } + + } + + private void invokeTest(String testName) throws Exception { + Method method = getClass().getDeclaredMethod(testName); + method.invoke(this); + } + + private ConfigurationAdmin getConfigurationAdmin(BundleContext ctx, List> references) throws Exception { + ServiceReference ref = ctx.getServiceReference(ConfigurationAdmin.class); + assertNotNull("No ConfigurationAdmin service", ref); + references.add(ref); + return ctx.getService(ref); + } + + private String getFilter(String pid, boolean isFactory) { + if (isFactory) { + return "(" + ConfigurationAdmin.SERVICE_FACTORYPID + "=" + pid + ")"; + } else { + return "(" + Constants.SERVICE_PID + "=" + pid + ")"; + } + } + + private enum Behavior { + MERGE, REPLACE, IGNORE + } + + private void verify(Behavior behavior) throws Exception { + ConfigurationAdmin ca = getConfigurationAdmin(bundleContext, references); + String filter = getFilter(PARENT_PID, true); + Configuration[] parents = ca.listConfigurations(filter); + assertNotNull("The configuration for " + PARENT_PID + " should exist", parents); + + assertEquals("There should be four instances of PID " + PARENT_PID, 4, parents.length); + + for (Configuration parent : parents) { + Dictionary properties = parent.getProperties(); + String id = (String) properties.get("id"); + if ("a".equals(id)) { + String[] pids = (String[]) properties.get("child.a"); + assertNotNull("The child pids should exist", pids); + assertEquals("There should be one child pid", 1, pids.length); + Configuration child = ca.getConfiguration(pids[0]); + assertNotNull("The child should exist", child); + Dictionary childProps = child.getProperties(); + if (behavior == Behavior.MERGE || behavior == Behavior.REPLACE) { + assertEquals("a1", childProps.get("attrA1")); + } else { + assertNull(childProps.get("attrA1")); + } + if (behavior == Behavior.MERGE || behavior == Behavior.IGNORE) { + assertEquals("a2", childProps.get("attrA2")); + } else { + // We replaced the top level (attrA2=a2) with the include (attr1=a1), but attrA2 has a default value. + assertEquals("value2", childProps.get("attrA2")); + } + } else if ("b".equals(id)) { + String[] pids = (String[]) properties.get("child.b"); + assertNotNull("the child pids should exist", pids); + assertEquals("there should be one child pid", 1, pids.length); + Configuration child = ca.getConfiguration(pids[0]); + assertNotNull("The child should exist", child); + Dictionary childProps = child.getProperties(); + assertEquals("b1", childProps.get("attrB1")); + assertEquals("b2", childProps.get("attrB2")); + } else if ("c".equals(id) || "common".equals(id)) { + } else { + fail("Something went horribly wrong."); + } + } + } + + public void testMergedConfig() throws Exception { + // All config in one file, verify it's merged correctly. If this isn't working, fix this first, because + // whatever is broken here would break the other tests. + verify(Behavior.MERGE); + } + + public void testMergedIncludesMerge() throws Exception { + // Same set of assumptions as the all in one case + verify(Behavior.MERGE); + } + + public void testMergedIncludesBreak() throws Exception { + // The config doesn't get updated, so verify we're still using the all in one config + verify(Behavior.MERGE); + } + + public void testMergedIncludesBreak2() throws Exception { + // Test is arranged so that the assumptions here are the same as for merge.. What would normally be + // merged in is specified in the top level file. The included file has the non conflicting elements, which + // should all get added despite onConflict="break" + verify(Behavior.MERGE); + } + + public void testMergedIncludesReplace() throws Exception { + // Verify that the attribute in the top level file gets replaced by the include + verify(Behavior.REPLACE); + } + + public void testMergedIncludesIgnore() throws Exception { + // Verify that the attribute in the included file gets ignored + verify(Behavior.IGNORE); + + } + + public void testMergedIncludesIgnoreReplace() throws Exception { + // Verify that none of the level 3 (REPLACE) or level 2 (IGNORE) elements are used + verify(Behavior.IGNORE); + } + + public void testMergedIncludesFourLevelReplace() throws Exception { + // Conflict is between level 2 (fourLevelB.xml) and level 4 (conflict.xml). Verify that the "replace" behavior from + // level 2 is used instead of the "ignore" behavior from level 3. + verify(Behavior.REPLACE); + } + + public void testMergedIncludesFourLevelIgnore() throws Exception { + // Conflict is between level 2 (fourLevelB2.xml) and level 4 (conflict.xml). Verify that the "ignore" behavior from + // level 2 is used instead of the "replace" behavior from level 3. + verify(Behavior.IGNORE); + } + + public void testDefaultInstances1() throws Exception { + // Check to make sure a default instance marked requiresExisting=true gets merged into an existing + // configuration + ConfigurationAdmin ca = getConfigurationAdmin(bundleContext, references); + String filter = "(&(" + ConfigurationAdmin.SERVICE_FACTORYPID + "=" + PARENT_PID + ")(id=common))"; + Configuration[] parents = ca.listConfigurations(filter); + assertNotNull("The configuration for " + PARENT_PID + "with the ID 'common' should exist", parents); + assertEquals("There should be one instance " + PARENT_PID, 1, parents.length); + + Dictionary properties = parents[0].getProperties(); + String[] pids = (String[]) properties.get("child.a"); + assertNotNull("the child pid should exist", pids); + assertEquals("there should be one child pid", 1, pids.length); + + } + + public void testDefaultInstances2() throws Exception { + // Check to make sure that a default instance without a requiresExisting attribute gets merged in and that one + // with requiresExisting=true does not. + + ConfigurationAdmin ca = getConfigurationAdmin(bundleContext, references); + String filter = getFilter(DEFAULT_PID, true); + Configuration[] parents = ca.listConfigurations(filter); + assertNotNull("The configuration for " + DEFAULT_PID + " should exist", parents); + assertEquals("There should be one instance of PID " + DEFAULT_PID, 1, parents.length); + + Dictionary properties = parents[0].getProperties(); + String id = (String) properties.get("id"); + assertEquals("The ID should be 'two'", "two", id); + + } + + public void testDefaultInstances3() throws Exception { + // Check to make sure a default instance marked addIfMissing=true gets added when an existing + // configuration is not specified. Also checks that an instance does not get added when there is an existing configuration. + ConfigurationAdmin ca = getConfigurationAdmin(bundleContext, references); + String filter = getFilter(DEFAULT_MISSING_PID, true); + Configuration[] parents = ca.listConfigurations(filter); + assertNotNull("The configuration for " + DEFAULT_MISSING_PID + " should exist", parents); + assertEquals("There should be two instances of PID " + DEFAULT_MISSING_PID, 2, parents.length); + + for (Configuration config : parents) { + Dictionary properties = config.getProperties(); + String id = (String) properties.get("id"); + String someProperty = (String) properties.get("someProperty"); + if ("one".equals(id)) { + assertNull("someProperty should be null because the default instance should not be merged", someProperty); + } else if ("two".equals(id)) { + assertEquals("someProperty should be defined because the default instance should be merged", someProperty, "from default instances"); + } else { + fail("Something went horribly wrong -- default instance with ID " + id + " found when 'one' or 'two' was expected"); + } + } + + } + +} diff --git a/dev/com.ibm.ws.config_fat/test-applications/metatype/resources/META-INF/MANIFEST.MF b/dev/com.ibm.ws.config_fat/test-applications/metatype/resources/META-INF/MANIFEST.MF new file mode 100755 index 00000000000..826e67ac344 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-applications/metatype/resources/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Bundle-ManifestVersion: 2 +Bundle-SymbolicName: com.ibm.ws.config.metatype +Import-Packages: java.io, javax.servlet, javax.servlet.http, org.osgi.framework, org.osgi.service.cm diff --git a/dev/com.ibm.ws.config_fat/test-applications/metatype/resources/META-INF/permissions.xml b/dev/com.ibm.ws.config_fat/test-applications/metatype/resources/META-INF/permissions.xml new file mode 100755 index 00000000000..5888d2ec00d --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-applications/metatype/resources/META-INF/permissions.xml @@ -0,0 +1,69 @@ + + + + + + java.io.FilePermission + ALL FILES + read,write + + + + javax.management.MBeanServerPermission + createMBeanServer + + + + java.net.SocketPermission + * + connect,resolve + + + + java.util.PropertyPermission + * + read,write + + + + java.lang.RuntimePermission + * + * + + + + org.osgi.service.cm.ConfigurationPermission + * + configure + + + + javax.security.auth.AuthPermission + * + + + + org.osgi.framework.ServicePermission + * + register,get + + + + + org.osgi.framework.AdminPermission + * + * + + + + org.osgi.framework.AdaptPermission + * + adapt + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/test-applications/metatype/resources/OSGI-INF/metatype/metatype.xml b/dev/com.ibm.ws.config_fat/test-applications/metatype/resources/OSGI-INF/metatype/metatype.xml new file mode 100755 index 00000000000..da1f74436eb --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-applications/metatype/resources/OSGI-INF/metatype/metatype.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/com.ibm.ws.config_fat/test-applications/metatype/src/test/server/config/metatype/TestRunner.java b/dev/com.ibm.ws.config_fat/test-applications/metatype/src/test/server/config/metatype/TestRunner.java new file mode 100755 index 00000000000..f6a0f503ef0 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-applications/metatype/src/test/server/config/metatype/TestRunner.java @@ -0,0 +1,7 @@ +package test.server.config.metatype; + +// just a dummy class so that things get compiled + +public class TestRunner { + +} diff --git a/dev/com.ibm.ws.config_fat/test-applications/metatypeprovider/resources/META-INF/MANIFEST.MF b/dev/com.ibm.ws.config_fat/test-applications/metatypeprovider/resources/META-INF/MANIFEST.MF new file mode 100755 index 00000000000..dac908a02fb --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-applications/metatypeprovider/resources/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Bundle-ManifestVersion: 2 +Bundle-SymbolicName: test +Import-Packages: java.io, javax.servlet, javax.servlet.http, org.osgi.framework, org.osgi.service.cm diff --git a/dev/com.ibm.ws.config_fat/test-applications/metatypeprovider/resources/META-INF/permissions.xml b/dev/com.ibm.ws.config_fat/test-applications/metatypeprovider/resources/META-INF/permissions.xml new file mode 100755 index 00000000000..5888d2ec00d --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-applications/metatypeprovider/resources/META-INF/permissions.xml @@ -0,0 +1,69 @@ + + + + + + java.io.FilePermission + ALL FILES + read,write + + + + javax.management.MBeanServerPermission + createMBeanServer + + + + java.net.SocketPermission + * + connect,resolve + + + + java.util.PropertyPermission + * + read,write + + + + java.lang.RuntimePermission + * + * + + + + org.osgi.service.cm.ConfigurationPermission + * + configure + + + + javax.security.auth.AuthPermission + * + + + + org.osgi.framework.ServicePermission + * + register,get + + + + + org.osgi.framework.AdminPermission + * + * + + + + org.osgi.framework.AdaptPermission + * + adapt + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/test-applications/metatypeprovider/resources/WEB-INF/web.xml b/dev/com.ibm.ws.config_fat/test-applications/metatypeprovider/resources/WEB-INF/web.xml new file mode 100755 index 00000000000..c0aded3cc2d --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-applications/metatypeprovider/resources/WEB-INF/web.xml @@ -0,0 +1,15 @@ + + + + + MetatypeProviderTestServlet + test.metatype.provider.MetatypeProviderTestServlet + + + + + MetatypeProviderTestServlet + /providerTest + + + diff --git a/dev/com.ibm.ws.config_fat/test-applications/metatypeprovider/src/test/metatype/provider/MetatypeProviderTestServlet.java b/dev/com.ibm.ws.config_fat/test-applications/metatypeprovider/src/test/metatype/provider/MetatypeProviderTestServlet.java new file mode 100755 index 00000000000..7078d5c5ecf --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-applications/metatypeprovider/src/test/metatype/provider/MetatypeProviderTestServlet.java @@ -0,0 +1,198 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package test.metatype.provider; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import java.io.IOException; +import java.io.PrintWriter; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Dictionary; +import java.util.List; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.Constants; +import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.InvalidSyntaxException; +import org.osgi.framework.ServiceReference; +import org.osgi.service.cm.Configuration; +import org.osgi.service.cm.ConfigurationAdmin; + +/** + * + */ +public class MetatypeProviderTestServlet extends HttpServlet { + + /** */ + private static final String LIFESPAN_ATTRIBUTE = "lifespan"; + + /** */ + private static final String NAME_ATTRIBUTE = "name"; + + /** */ + private static final long serialVersionUID = -1977276153574893730L; + + private final ArrayList references = new ArrayList(); + private BundleContext bundleContext; + + public static final String PLANT_PID = "test.metatype.provider.plant"; + public static final String ANIMAL_PID = "test.metatype.provider.animal"; + + /* + * (non-Javadoc) + * + * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) + */ + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + PrintWriter writer = response.getWriter(); + + String testName = request.getParameter("testName"); + assertNotNull("No testName parameter specified", testName); + + Bundle bundle = FrameworkUtil.getBundle(HttpServlet.class); + + this.bundleContext = bundle.getBundleContext(); + try { + if (testName.equals("dump")) { + // Just for debugging + dump(writer); + } else { + log("Begin test: " + testName); + invokeTest(testName); + writer.println("OK"); + } + } catch (NoSuchMethodException e) { + writer.println("FAILED - Invalid test name: " + testName); + } catch (InvocationTargetException e) { + writer.println("FAILED"); + e.getTargetException().printStackTrace(writer); + } catch (Throwable e) { + writer.println("FAILED"); + e.printStackTrace(writer); + } finally { + log("End test: " + testName); + for (ServiceReference ref : references) { + bundleContext.ungetService(ref); + } + references.clear(); + } + + writer.flush(); + writer.close(); + } + + /** + * Just for manual debugging + * + * @param writer + * @throws Exception + */ + private void dump(PrintWriter writer) throws Exception { + ConfigurationAdmin ca = getConfigurationAdmin(bundleContext, references); + Configuration[] configurations; + try { + configurations = ca.listConfigurations(null); + for (Configuration c : configurations) { + writer.print("

"); + String pid = c.getFactoryPid() == null ? c.getPid() : c.getFactoryPid(); + if (pid.startsWith("test")) { + writer.println(pid); + } + } + } catch (InvalidSyntaxException e1) { + throw new IOException(e1); + } + + } + + private void invokeTest(String testName) throws Exception { + Method method = getClass().getDeclaredMethod(testName); + method.invoke(this); + } + + private ConfigurationAdmin getConfigurationAdmin(BundleContext ctx, List references) throws Exception { + ServiceReference ref = ctx.getServiceReference(ConfigurationAdmin.class); + assertNotNull("No ConfigurationAdmin service", ref); + references.add(ref); + return ctx.getService(ref); + } + + private String getFilter(String pid, boolean isFactory) { + if (isFactory) { + return "(" + ConfigurationAdmin.SERVICE_FACTORYPID + "=" + pid + ")"; + } else { + return "(" + Constants.SERVICE_PID + "=" + pid + ")"; + } + } + + public void testMetatypeProvider1() throws Exception { + ConfigurationAdmin ca = getConfigurationAdmin(bundleContext, references); + String filter = getFilter(PLANT_PID, true); + Configuration[] children1 = ca.listConfigurations(filter); + assertNotNull("The configuration for " + PLANT_PID + " should exist", children1); + assertEquals("There should only be one instance of PID " + PLANT_PID, 1, children1.length); + + } + + public void testMetatypeProvider2() throws Exception { + ConfigurationAdmin ca = getConfigurationAdmin(bundleContext, references); + String filter = getFilter(ANIMAL_PID, true); + Configuration[] children1 = ca.listConfigurations(filter); + assertNotNull("The configuration for " + ANIMAL_PID + " should exist", children1); + assertEquals("There should only be one instance of PID " + ANIMAL_PID, 1, children1.length); + + Configuration child = children1[0]; + Dictionary dictionary = child.getProperties(); + assertNotNull("The dictionary should exist", dictionary); + + Object lifespan = dictionary.get(LIFESPAN_ATTRIBUTE); + assertNotNull("The lifespan attribute should exist", lifespan); + + assertEquals("The lifespan attribute should be 1000 days", 86400000000L, lifespan); + + Object name = dictionary.get(NAME_ATTRIBUTE); + assertNotNull("The name attribute should exist", name); + assertEquals("The name should be marmot", "marmot", name); + } + + /** + * Test that metatype converted config is removed when its corresponding metatype is removed + * + * PLANT_PID should not exist in config admin even though it was specified using the full pid. + * We don't recreate the pre-metatype config when the metatype is removed. + * + * ANIMAL_PID should not exist. + * + * @throws Exception + */ + public void testMetatypeProvider3() throws Exception { + ConfigurationAdmin ca = getConfigurationAdmin(bundleContext, references); + String filter = getFilter(PLANT_PID, true); + Configuration[] children1 = ca.listConfigurations(filter); + assertNull("The configuration for " + PLANT_PID + " should not exist", children1); + + filter = getFilter(ANIMAL_PID, true); + children1 = ca.listConfigurations(filter); + assertNull("The configuration for " + ANIMAL_PID + " should not exist", children1); + } +} diff --git a/dev/com.ibm.ws.config_fat/test-applications/restart/resources/META-INF/MANIFEST.MF b/dev/com.ibm.ws.config_fat/test-applications/restart/resources/META-INF/MANIFEST.MF new file mode 100755 index 00000000000..dac908a02fb --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-applications/restart/resources/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Bundle-ManifestVersion: 2 +Bundle-SymbolicName: test +Import-Packages: java.io, javax.servlet, javax.servlet.http, org.osgi.framework, org.osgi.service.cm diff --git a/dev/com.ibm.ws.config_fat/test-applications/restart/resources/META-INF/permissions.xml b/dev/com.ibm.ws.config_fat/test-applications/restart/resources/META-INF/permissions.xml new file mode 100755 index 00000000000..5888d2ec00d --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-applications/restart/resources/META-INF/permissions.xml @@ -0,0 +1,69 @@ + + + + + + java.io.FilePermission + ALL FILES + read,write + + + + javax.management.MBeanServerPermission + createMBeanServer + + + + java.net.SocketPermission + * + connect,resolve + + + + java.util.PropertyPermission + * + read,write + + + + java.lang.RuntimePermission + * + * + + + + org.osgi.service.cm.ConfigurationPermission + * + configure + + + + javax.security.auth.AuthPermission + * + + + + org.osgi.framework.ServicePermission + * + register,get + + + + + org.osgi.framework.AdminPermission + * + * + + + + org.osgi.framework.AdaptPermission + * + adapt + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/test-applications/restart/resources/WEB-INF/web.xml b/dev/com.ibm.ws.config_fat/test-applications/restart/resources/WEB-INF/web.xml new file mode 100755 index 00000000000..d92e42649f3 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-applications/restart/resources/WEB-INF/web.xml @@ -0,0 +1,15 @@ + + + + + ConfigRestartTestServlet + test.server.config.restart.ConfigRestartTestServlet + + + + + ConfigRestartTestServlet + /restart + + + diff --git a/dev/com.ibm.ws.config_fat/test-applications/restart/src/test/server/config/restart/ConfigRestartTestServlet.java b/dev/com.ibm.ws.config_fat/test-applications/restart/src/test/server/config/restart/ConfigRestartTestServlet.java new file mode 100755 index 00000000000..83c989c7e8f --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-applications/restart/src/test/server/config/restart/ConfigRestartTestServlet.java @@ -0,0 +1,250 @@ +package test.server.config.restart; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.fail; + +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import javax.management.MBeanServer; +import javax.management.ObjectName; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.Constants; +import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.InvalidSyntaxException; +import org.osgi.framework.ServiceReference; +import org.osgi.service.cm.Configuration; +import org.osgi.service.cm.ConfigurationAdmin; +import org.osgi.util.tracker.ServiceTracker; + +import com.ibm.ws.jmx.PlatformMBeanService; + +@SuppressWarnings("serial") +public class ConfigRestartTestServlet extends HttpServlet { + + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + PrintWriter writer = response.getWriter(); + + String testName = request.getParameter("testName"); + assertNotNull("No testName parameter specified", testName); + + Bundle bundle = FrameworkUtil.getBundle(HttpServlet.class); + + List references = new ArrayList(); + BundleContext bundleContext = bundle.getBundleContext(); + try { + if ("before".equals(testName)) { + testConfigurationBefore(bundleContext, references); + } else if ("after".equals(testName)) { + testConfigurationAfter(bundleContext, references); + } else if ("beforeVariable".equals(testName)) { + testBeforeVariable(bundleContext, references); + } else if ("afterVariable".equals(testName)) { + testAfterVariable(bundleContext, references); + } else if ("checkImport".equals(testName)) { + testCheckImport(bundleContext, references); + } else if ("refresh".equals(testName)) { + testRefresh(bundleContext, references); + } else { + fail("Invalid test name: " + testName); + } + writer.println("Test Passed"); + } catch (Throwable e) { + e.printStackTrace(writer); + } finally { + for (ServiceReference ref : references) { + bundleContext.ungetService(ref); + } + } + + writer.flush(); + writer.close(); + } + + private void testConfigurationBefore(BundleContext ctx, List references) throws Exception { + ConfigurationAdmin ca = getConfigurationAdmin(ctx, references); + testSingletonBefore(ca); + testFactoryBefore(ca); + } + + private void testConfigurationAfter(BundleContext ctx, List references) throws Exception { + ConfigurationAdmin ca = getConfigurationAdmin(ctx, references); + testSingletonAfter(ca); + testFactoryAfter(ca); + } + + private void testSingletonBefore(ConfigurationAdmin ca) { + Configuration[] configs = null; + String filter = null; + + filter = "(" + Constants.SERVICE_PID + "=" + "singleton-one" + ")"; + configs = getConfiguration(ca, filter); + assertNotNull("There should be a configuration found for filter " + filter, configs); + assertEquals("There should be 1 configuration for filter " + filter, 1, configs.length); + assertEquals("Configuration value property", "abc", configs[0].getProperties().get("value")); + + filter = "(" + Constants.SERVICE_PID + "=" + "singleton-two" + ")"; + configs = getConfiguration(ca, filter); + assertNotNull("There should be a configuration found for filter " + filter, configs); + assertEquals("There should be 1 configuration for filter " + filter, 1, configs.length); + assertEquals("Configuration value property", "def", configs[0].getProperties().get("value")); + } + + private void testSingletonAfter(ConfigurationAdmin ca) { + Configuration[] configs = null; + String filter = null; + + // deleted after restart + filter = "(" + Constants.SERVICE_PID + "=" + "singleton-one" + ")"; + configs = getConfiguration(ca, filter); + assertNull("There should not be a configuration found for filter " + filter, configs); + + // unchanged after restart + filter = "(" + Constants.SERVICE_PID + "=" + "singleton-two" + ")"; + configs = getConfiguration(ca, filter); + assertNotNull("There should be a configuration found for filter " + filter, configs); + assertEquals("There should be 1 configuration for filter " + filter, 1, configs.length); + assertEquals("Configuration value property", "def", configs[0].getProperties().get("value")); + } + + private void testFactoryBefore(ConfigurationAdmin ca) { + Configuration[] configs = null; + String filter = null; + + filter = "(" + ConfigurationAdmin.SERVICE_FACTORYPID + "=" + "factory" + ")"; + configs = getConfiguration(ca, filter); + assertNotNull("There should be a configuration found for filter " + filter, configs); + assertEquals("There should be 2 configurations for filter " + filter, 2, configs.length); + + filter = "(&(" + ConfigurationAdmin.SERVICE_FACTORYPID + "=" + "factory" + ")(id=1))"; + configs = getConfiguration(ca, filter); + assertNotNull("There should be a configuration found for filter " + filter, configs); + assertEquals("There should be 1 configuration for filter " + filter, 1, configs.length); + assertEquals("Configuration name property", "one", configs[0].getProperties().get("name")); + + filter = "(&(" + ConfigurationAdmin.SERVICE_FACTORYPID + "=" + "factory" + ")(id=2))"; + configs = getConfiguration(ca, filter); + assertNotNull("There should be a configuration found for filter " + filter, configs); + assertEquals("There should be 1 configuration for filter " + filter, 1, configs.length); + assertEquals("Configuration name property", "two", configs[0].getProperties().get("name")); + } + + private void testFactoryAfter(ConfigurationAdmin ca) { + Configuration[] configs = null; + String filter = null; + + filter = "(" + ConfigurationAdmin.SERVICE_FACTORYPID + "=" + "factory" + ")"; + configs = getConfiguration(ca, filter); + assertNotNull("There should be a configuration found for filter " + filter, configs); + assertEquals("There should be 2 configurations for filter " + filter, 2, configs.length); + + filter = "(&(" + ConfigurationAdmin.SERVICE_FACTORYPID + "=" + "factory" + ")(id=1))"; + configs = getConfiguration(ca, filter); + assertNull("There should not be a configuration found for filter " + filter, configs); + + filter = "(&(" + ConfigurationAdmin.SERVICE_FACTORYPID + "=" + "factory" + ")(id=2))"; + configs = getConfiguration(ca, filter); + assertNotNull("There should be a configuration found for filter " + filter, configs); + assertEquals("There should be 1 configuration for filter " + filter, 1, configs.length); + assertEquals("Configuration name property", "two", configs[0].getProperties().get("name")); + + filter = "(&(" + ConfigurationAdmin.SERVICE_FACTORYPID + "=" + "factory" + ")(id=3))"; + configs = getConfiguration(ca, filter); + assertNotNull("There should be a configuration found for filter " + filter, configs); + assertEquals("There should be 1 configuration for filter " + filter, 1, configs.length); + assertEquals("Configuration name property", "three", configs[0].getProperties().get("name")); + + } + + private void testBeforeVariable(BundleContext ctx, List references) throws Exception { + ConfigurationAdmin ca = getConfigurationAdmin(ctx, references); + + Configuration[] configs = null; + String filter = null; + + filter = "(" + Constants.SERVICE_PID + "=" + "myPort" + ")"; + configs = getConfiguration(ca, filter); + assertNotNull("There should be a configuration found for filter " + filter, configs); + assertEquals("There should be 1 configuration for filter " + filter, 1, configs.length); + assertEquals("Configuration type property", "http", configs[0].getProperties().get("type")); + assertEquals("Configuration value property", "1234", configs[0].getProperties().get("value")); + } + + private void testAfterVariable(BundleContext ctx, List references) throws Exception { + ConfigurationAdmin ca = getConfigurationAdmin(ctx, references); + + Configuration[] configs = null; + String filter = null; + + filter = "(" + Constants.SERVICE_PID + "=" + "myPort" + ")"; + configs = getConfiguration(ca, filter); + assertNotNull("There should be a configuration found for filter " + filter, configs); + assertEquals("There should be 1 configuration for filter " + filter, 1, configs.length); + assertEquals("Configuration type property", "http", configs[0].getProperties().get("type")); + assertEquals("Configuration value property", "5678", configs[0].getProperties().get("value")); + } + + private void testCheckImport(BundleContext ctx, List references) throws Exception { + ConfigurationAdmin ca = getConfigurationAdmin(ctx, references); + + Configuration[] configs = null; + String filter = null; + + filter = "(" + Constants.SERVICE_PID + "=" + "person" + ")"; + configs = getConfiguration(ca, filter); + assertNotNull("There should be a configuration found for filter " + filter, configs); + assertEquals("There should be 1 configuration for filter " + filter, 1, configs.length); + assertEquals("Configuration firstName property", "Joe", configs[0].getProperties().get("firstName")); + assertEquals("Configuration lastName property", "Doe", configs[0].getProperties().get("lastName")); + } + + private ConfigurationAdmin getConfigurationAdmin(BundleContext ctx, List references) throws Exception { + ServiceReference ref = ctx.getServiceReference(ConfigurationAdmin.class); + assertNotNull("No ConfigurationAdmin service", ref); + references.add(ref); + return ctx.getService(ref); + } + + private Configuration[] getConfiguration(ConfigurationAdmin ca, String filter) { + try { + return ca.listConfigurations(filter); + } catch (InvalidSyntaxException e) { + throw new RuntimeException("Invalid filter: " + filter, e); + } catch (IOException e) { + throw new RuntimeException("Error listing configurations", e); + } + } + + private void testRefresh(BundleContext ctx, List references) throws Exception { + ServiceTracker tracker = new ServiceTracker(ctx, PlatformMBeanService.class.getName(), null); + tracker.open(); + try { + PlatformMBeanService service = (PlatformMBeanService) tracker.waitForService(60 * 1000); + assertNotNull("No Platform MBean service", service); + + List serverXML = new ArrayList(); + serverXML.add(new File("server.xml").getAbsolutePath()); + + MBeanServer server = service.getMBeanServer(); + ObjectName configServices = new ObjectName("WebSphere", "service", "com.ibm.ws.kernel.filemonitor.FileNotificationMBean"); + server.invoke(configServices, "notifyFileChanges", new Object[] { Collections.emptyList(), serverXML, Collections.EMPTY_LIST }, + new String[] { Collection.class.getName(), Collection.class.getName(), Collection.class.getName() }); + } finally { + tracker.close(); + } + } +} diff --git a/dev/com.ibm.ws.config_fat/test-applications/varmerge/resources/META-INF/MANIFEST.MF b/dev/com.ibm.ws.config_fat/test-applications/varmerge/resources/META-INF/MANIFEST.MF new file mode 100755 index 00000000000..f49fb55181f --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-applications/varmerge/resources/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Bundle-ManifestVersion: 2 +Bundle-SymbolicName: test +Import-Packages: java.io, javax.servlet, javax.servlet.http, org.osgi.framework, org.osgi.service.cm, com.ibm.wsspi.kernel.service.location diff --git a/dev/com.ibm.ws.config_fat/test-applications/varmerge/resources/META-INF/permissions.xml b/dev/com.ibm.ws.config_fat/test-applications/varmerge/resources/META-INF/permissions.xml new file mode 100755 index 00000000000..5888d2ec00d --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-applications/varmerge/resources/META-INF/permissions.xml @@ -0,0 +1,69 @@ + + + + + + java.io.FilePermission + ALL FILES + read,write + + + + javax.management.MBeanServerPermission + createMBeanServer + + + + java.net.SocketPermission + * + connect,resolve + + + + java.util.PropertyPermission + * + read,write + + + + java.lang.RuntimePermission + * + * + + + + org.osgi.service.cm.ConfigurationPermission + * + configure + + + + javax.security.auth.AuthPermission + * + + + + org.osgi.framework.ServicePermission + * + register,get + + + + + org.osgi.framework.AdminPermission + * + * + + + + org.osgi.framework.AdaptPermission + * + adapt + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/test-applications/varmerge/resources/WEB-INF/web.xml b/dev/com.ibm.ws.config_fat/test-applications/varmerge/resources/WEB-INF/web.xml new file mode 100755 index 00000000000..1b0ab41efc8 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-applications/varmerge/resources/WEB-INF/web.xml @@ -0,0 +1,26 @@ + + + + + VarMergeTestServlet + test.config.merged.VarMergeTestServlet + + + + + VarMergeTestServlet + /varMergeTest + + + + DelayedVariableTestServlet + test.config.merged.DelayedVariableTestServlet + + + + + DelayedVariableTestServlet + /delayedVarTests + + + diff --git a/dev/com.ibm.ws.config_fat/test-applications/varmerge/src/test/config/merged/DelayedVariableTestServlet.java b/dev/com.ibm.ws.config_fat/test-applications/varmerge/src/test/config/merged/DelayedVariableTestServlet.java new file mode 100755 index 00000000000..0a714c2dd15 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-applications/varmerge/src/test/config/merged/DelayedVariableTestServlet.java @@ -0,0 +1,138 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ + +package test.config.merged; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.io.IOException; +import java.io.PrintWriter; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Dictionary; +import java.util.List; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.Constants; +import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.ServiceReference; +import org.osgi.service.cm.Configuration; +import org.osgi.service.cm.ConfigurationAdmin; + +/** + * + */ +public class DelayedVariableTestServlet extends HttpServlet { + + /** */ + private static final long serialVersionUID = 6784264217930725272L; + private static final String DELAYED_VAR_PID = "com.ibm.ws.config.variable.delay"; + + private static final String DELAYED_VAR_ATTR = "delayedVariable"; + private static final String DELAYED_IBM_VAR_ATTR = "delayedIBMVar"; + private static final String IMMEDIATE_VAR_ATTR = "immediateVar"; + private static final String IMMEDIATE_VAR_TWO = "immediateVarTwo"; + + private static final String VARIABLE_STRING = "${variableDelayTest}"; + private static final String EVALUATED_VARIABLE = "evaluated"; + + private final ArrayList> references = new ArrayList>(); + private BundleContext bundleContext; + + /* + * (non-Javadoc) + * + * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) + */ + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + PrintWriter writer = response.getWriter(); + + String testName = request.getParameter("testName"); + assertNotNull("No testName parameter specified", testName); + + Bundle bundle = FrameworkUtil.getBundle(HttpServlet.class); + + this.bundleContext = bundle.getBundleContext(); + try { + + log("Begin test: " + testName); + invokeTest(testName); + writer.println("OK"); + + } catch (NoSuchMethodException e) { + writer.println("FAILED - Invalid test name: " + testName); + } catch (InvocationTargetException e) { + writer.println("FAILED"); + e.getTargetException().printStackTrace(writer); + } catch (Throwable e) { + writer.println("FAILED"); + e.printStackTrace(writer); + } finally { + log("End test: " + testName); + for (ServiceReference ref : references) { + bundleContext.ungetService(ref); + } + references.clear(); + } + + writer.flush(); + writer.close(); + } + + private void invokeTest(String testName) throws Exception { + Method method = getClass().getDeclaredMethod(testName); + method.invoke(this); + } + + private ConfigurationAdmin getConfigurationAdmin(BundleContext ctx, List> references) throws Exception { + ServiceReference ref = ctx.getServiceReference(ConfigurationAdmin.class); + assertNotNull("No ConfigurationAdmin service", ref); + references.add(ref); + return ctx.getService(ref); + } + + private String getFilter(String pid, boolean isFactory) { + if (isFactory) { + return "(" + ConfigurationAdmin.SERVICE_FACTORYPID + "=" + pid + ")"; + } else { + return "(" + Constants.SERVICE_PID + "=" + pid + ")"; + } + } + + public void testVariableDelay() throws Exception { + + ConfigurationAdmin ca = getConfigurationAdmin(bundleContext, references); + String filter = getFilter(DELAYED_VAR_PID, true); + Configuration[] varDelay = ca.listConfigurations(filter); + assertNotNull("The configuration for " + DELAYED_VAR_PID + " should exist", varDelay); + + assertEquals("There should be one instance of PID " + DELAYED_VAR_PID, 1, varDelay.length); + + Dictionary properties = varDelay[0].getProperties(); + + assertEquals(VARIABLE_STRING, properties.get(DELAYED_VAR_ATTR)); + assertEquals(VARIABLE_STRING, properties.get(DELAYED_IBM_VAR_ATTR)); + assertEquals(EVALUATED_VARIABLE, properties.get(IMMEDIATE_VAR_ATTR)); + assertEquals(EVALUATED_VARIABLE, properties.get(IMMEDIATE_VAR_TWO)); + + } + +} diff --git a/dev/com.ibm.ws.config_fat/test-applications/varmerge/src/test/config/merged/VarMergeTestServlet.java b/dev/com.ibm.ws.config_fat/test-applications/varmerge/src/test/config/merged/VarMergeTestServlet.java new file mode 100755 index 00000000000..3d3d0f0f964 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-applications/varmerge/src/test/config/merged/VarMergeTestServlet.java @@ -0,0 +1,137 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ + +package test.config.merged; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.io.IOException; +import java.io.PrintWriter; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.ServiceReference; + +import com.ibm.wsspi.kernel.service.location.WsLocationAdmin; + +/** + * + */ +public class VarMergeTestServlet extends HttpServlet { + + /** */ + private static final long serialVersionUID = 6784264217930725272L; + private final ArrayList> references = new ArrayList>(); + private BundleContext bundleContext; + + /* + * (non-Javadoc) + * + * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) + */ + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + PrintWriter writer = response.getWriter(); + + String testName = request.getParameter("testName"); + assertNotNull("No testName parameter specified", testName); + + Bundle bundle = FrameworkUtil.getBundle(HttpServlet.class); + + this.bundleContext = bundle.getBundleContext(); + try { + + log("Begin test: " + testName); + invokeTest(testName); + writer.println("OK"); + + } catch (NoSuchMethodException e) { + writer.println("FAILED - Invalid test name: " + testName); + } catch (InvocationTargetException e) { + writer.println("FAILED"); + e.getTargetException().printStackTrace(writer); + } catch (Throwable e) { + writer.println("FAILED"); + e.printStackTrace(writer); + } finally { + log("End test: " + testName); + for (ServiceReference ref : references) { + bundleContext.ungetService(ref); + } + references.clear(); + } + + writer.flush(); + writer.close(); + } + + private void invokeTest(String testName) throws Exception { + Method method = getClass().getDeclaredMethod(testName); + method.invoke(this); + } + + private enum Behavior { + MERGE, REPLACE, IGNORE + } + + private void verify(Behavior behavior) throws Exception { + + ServiceReference ref = bundleContext.getServiceReference(WsLocationAdmin.class); + assertNotNull("No location service", ref); + references.add(ref); + WsLocationAdmin locationAdmin = bundleContext.getService(ref); + + String value = locationAdmin.resolveString("${var1}"); + switch (behavior) { + case MERGE: + assertEquals("fromInclude", value); + break; + case REPLACE: + assertEquals("fromInclude", value); + break; + case IGNORE: + assertEquals("fromServerXml", value); + break; + + } + + } + + public void testMergedVariables() throws Exception { + verify(Behavior.MERGE); + } + + public void testMergedIncludesMerge() throws Exception { + verify(Behavior.MERGE); + } + + public void testMergedIncludesReplace() throws Exception { + verify(Behavior.REPLACE); + } + + public void testMergedIncludesIgnore() throws Exception { + // Verify that the attribute in the included file gets ignored + verify(Behavior.IGNORE); + + } + +} diff --git a/dev/com.ibm.ws.config_fat/test-bundles/test.config.childalias.b/bnd.bnd b/dev/com.ibm.ws.config_fat/test-bundles/test.config.childalias.b/bnd.bnd new file mode 100755 index 00000000000..be640d8c4ed --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-bundles/test.config.childalias.b/bnd.bnd @@ -0,0 +1,11 @@ +-include= ~../../../cnf/resources/bnd/bundle.props +bVersion=1.0.0 + +# For more information, see http://was.pok.ibm.com/xwiki/bin/view/Liberty/UsingBnd + +Bundle-Name: Test Config Child Alias B +Bundle-SymbolicName: test.config.childalias.b +Bundle-Description: Test bundle B for IBM childAlias extension, version=${bVersion} + +Include-Resource:\ + OSGI-INF/metatype/metatype-childalias-b.xml=resources/metatype-childalias-b.xml \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/test-bundles/test.config.childalias.b/resources/metatype-childalias-b.xml b/dev/com.ibm.ws.config_fat/test-bundles/test.config.childalias.b/resources/metatype-childalias-b.xml new file mode 100755 index 00000000000..81687352d66 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-bundles/test.config.childalias.b/resources/metatype-childalias-b.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/com.ibm.ws.config_fat/test-bundles/test.config.childalias.c/bnd.bnd b/dev/com.ibm.ws.config_fat/test-bundles/test.config.childalias.c/bnd.bnd new file mode 100755 index 00000000000..96c93b1d8a1 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-bundles/test.config.childalias.c/bnd.bnd @@ -0,0 +1,11 @@ +-include= ~../../../cnf/resources/bnd/bundle.props +bVersion=1.0.0 + +# For more information, see http://was.pok.ibm.com/xwiki/bin/view/Liberty/UsingBnd + +Bundle-Name: Test Config Child Alias C +Bundle-SymbolicName: test.config.childalias.c +Bundle-Description: Test bundle C for IBM childAlias extension, version=${bVersion} + +Include-Resource:\ + OSGI-INF/metatype/metatype-childalias-c.xml=resources/metatype-childalias-c.xml \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/test-bundles/test.config.childalias.c/resources/metatype-childalias-c.xml b/dev/com.ibm.ws.config_fat/test-bundles/test.config.childalias.c/resources/metatype-childalias-c.xml new file mode 100755 index 00000000000..54d7abce803 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-bundles/test.config.childalias.c/resources/metatype-childalias-c.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/com.ibm.ws.config_fat/test-bundles/test.config.childalias/bnd.bnd b/dev/com.ibm.ws.config_fat/test-bundles/test.config.childalias/bnd.bnd new file mode 100755 index 00000000000..b215a44ac08 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-bundles/test.config.childalias/bnd.bnd @@ -0,0 +1,11 @@ +-include= ~../../../cnf/resources/bnd/bundle.props +bVersion=1.0.0 + +# For more information, see http://was.pok.ibm.com/xwiki/bin/view/Liberty/UsingBnd + +Bundle-Name: Test Config Child Alias +Bundle-SymbolicName: test.config.childalias +Bundle-Description: Test bundle for IBM childAlias extension, version=${bVersion} + +Include-Resource:\ + OSGI-INF/metatype/metatype-childalias.xml=resources/metatype-childalias.xml \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/test-bundles/test.config.childalias/resources/metatype-childalias.xml b/dev/com.ibm.ws.config_fat/test-bundles/test.config.childalias/resources/metatype-childalias.xml new file mode 100755 index 00000000000..b1a27ca1227 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-bundles/test.config.childalias/resources/metatype-childalias.xml @@ -0,0 +1,153 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/com.ibm.ws.config_fat/test-bundles/test.config.extensions.b/bnd.bnd b/dev/com.ibm.ws.config_fat/test-bundles/test.config.extensions.b/bnd.bnd new file mode 100755 index 00000000000..ee9601e5052 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-bundles/test.config.extensions.b/bnd.bnd @@ -0,0 +1,11 @@ +-include= ~../../../cnf/resources/bnd/bundle.props +bVersion=1.0.0 + +# For more information, see http://was.pok.ibm.com/xwiki/bin/view/Liberty/UsingBnd + +Bundle-Name: Test Config Extensions B +Bundle-SymbolicName: test.config.extensions.b; singleton:=true +Bundle-Description: This bundle provides some services to use for testing; version=${bVersion} + +Include-Resource:\ + OSGI-INF/metatype/metatype-extensions-two.xml=resources/metatype-extensions-two.xml \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/test-bundles/test.config.extensions.b/resources/metatype-extensions-two.xml b/dev/com.ibm.ws.config_fat/test-bundles/test.config.extensions.b/resources/metatype-extensions-two.xml new file mode 100755 index 00000000000..fb6ec51a0f7 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-bundles/test.config.extensions.b/resources/metatype-extensions-two.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + diff --git a/dev/com.ibm.ws.config_fat/test-bundles/test.config.extensions.schema.generator/bnd.bnd b/dev/com.ibm.ws.config_fat/test-bundles/test.config.extensions.schema.generator/bnd.bnd new file mode 100755 index 00000000000..a58b3b7b92d --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-bundles/test.config.extensions.schema.generator/bnd.bnd @@ -0,0 +1,15 @@ +-include= ~../../../cnf/resources/bnd/bundle.props +bVersion=1.0.0 + +# For more information, see http://was.pok.ibm.com/xwiki/bin/view/Liberty/UsingBnd + +Bundle-Name: Test Schema Generator Config Extensions +Bundle-SymbolicName: test.config.extensions.schema.generator; singleton:=true +Bundle-Description: This bundle provides some services to use for testing; version=${bVersion} + +Private-Package: test.config.extensions.schema.generator + +Service-Component:\ + test.config.extensions.schema.generator;\ + implementation:=test.config.extensions.schema.generator.GeneratorTest;\ + schemaGenerator="com.ibm.websphere.metatype.SchemaGenerator" diff --git a/dev/com.ibm.ws.config_fat/test-bundles/test.config.extensions.schema.generator/src/test/config/extensions/schema/generator/GeneratorTest.java b/dev/com.ibm.ws.config_fat/test-bundles/test.config.extensions.schema.generator/src/test/config/extensions/schema/generator/GeneratorTest.java new file mode 100755 index 00000000000..cf43d467b59 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-bundles/test.config.extensions.schema.generator/src/test/config/extensions/schema/generator/GeneratorTest.java @@ -0,0 +1,59 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package test.config.extensions.schema.generator; + +import java.io.ByteArrayOutputStream; +import java.util.ArrayList; +import java.util.List; + +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.service.component.ComponentContext; + +import com.ibm.websphere.metatype.SchemaGenerator; +import com.ibm.websphere.metatype.SchemaGeneratorOptions; + +public class GeneratorTest { + + private SchemaGenerator schemaGenerator = null; + + public void activate(ComponentContext compContext) { + + BundleContext bundleContext = compContext.getBundleContext(); + List metatypeBundles = new ArrayList(); + for (Bundle bundle : bundleContext.getBundles()) { + if (bundle.getSymbolicName().startsWith("test.config.extensions")) + metatypeBundles.add(bundle); + } + + SchemaGeneratorOptions options = new SchemaGeneratorOptions(); + options.setEncoding("UTF-8"); + options.setBundles(metatypeBundles.toArray(new Bundle[] {})); + + // generate schema. We don't do anything with the generated schema, but use this to generate + // the error messages that + try { + if (schemaGenerator != null) + schemaGenerator.generate(new ByteArrayOutputStream(), options); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void deactivate(ComponentContext context) { + //NOP + } + + public void setSchemaGenerator(SchemaGenerator generator) { + this.schemaGenerator = generator; + } +} diff --git a/dev/com.ibm.ws.config_fat/test-bundles/test.config.extensions/bnd.bnd b/dev/com.ibm.ws.config_fat/test-bundles/test.config.extensions/bnd.bnd new file mode 100755 index 00000000000..4020ea77765 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-bundles/test.config.extensions/bnd.bnd @@ -0,0 +1,27 @@ +-include= ~../../../cnf/resources/bnd/bundle.props +bVersion=1.0.0 + +# For more information, see http://was.pok.ibm.com/xwiki/bin/view/Liberty/UsingBnd + +Bundle-Name: Test Config Extensions +Bundle-SymbolicName: test.config.extensions; singleton:=true +Bundle-Description: This bundle provides some services to use for testing; version=${bVersion} + +Web-ContextPath: config-extensions-test + +# export the interface packages +Export-Package: \ + test.config.extensions;provide:=true + +Service-Component:\ + test.config.extensions.super.component;\ + provide:='org.osgi.service.cm.ManagedServiceFactory,test.config.extensions.ConfigPropertiesProvider';\ + implementation:=test.config.extensions.ExtensionsTest;\ + properties:="service.pid=test.config.extensions.super,service.vendor=IBM",\ + test.config.extensions.internal.super.component;\ + provide:='org.osgi.service.cm.ManagedServiceFactory,test.config.extensions.ConfigPropertiesProvider';\ + implementation:=test.config.extensions.ExtensionsTest;\ + properties:="service.pid=test.config.extensions.internal.super,service.vendor=IBM" + +Include-Resource:\ + OSGI-INF/metatype/metatype-extensions.xml=resources/metatype-extensions.xml \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/test-bundles/test.config.extensions/resources/metatype-extensions.xml b/dev/com.ibm.ws.config_fat/test-bundles/test.config.extensions/resources/metatype-extensions.xml new file mode 100755 index 00000000000..54eb6ed20ff --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-bundles/test.config.extensions/resources/metatype-extensions.xml @@ -0,0 +1,147 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/com.ibm.ws.config_fat/test-bundles/test.config.extensions/src/test/config/extensions/ConfigPropertiesProvider.java b/dev/com.ibm.ws.config_fat/test-bundles/test.config.extensions/src/test/config/extensions/ConfigPropertiesProvider.java new file mode 100755 index 00000000000..efd177e7b7f --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-bundles/test.config.extensions/src/test/config/extensions/ConfigPropertiesProvider.java @@ -0,0 +1,26 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011, 2013 + * + * The source code for this program is not published or otherwise divested of + * its trade secrets, irrespective of what has been deposited with the U.S. + * Copyright Office. + */ +package test.config.extensions; + +import java.util.Dictionary; + +interface ConfigPropertiesProvider { + /** + * Waits for a call to the ManagedServiceFactory with + * the specified config id + * + * + * @param pidStartsWith + * @return the properties that the ManagedServiceFactory was called with + */ + Dictionary getPropertiesForId(String id); +} diff --git a/dev/com.ibm.ws.config_fat/test-bundles/test.config.extensions/src/test/config/extensions/ExtensionsTest.java b/dev/com.ibm.ws.config_fat/test-bundles/test.config.extensions/src/test/config/extensions/ExtensionsTest.java new file mode 100755 index 00000000000..b0aa1952b16 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-bundles/test.config.extensions/src/test/config/extensions/ExtensionsTest.java @@ -0,0 +1,90 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012, 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package test.config.extensions; + +import java.util.Dictionary; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.osgi.service.cm.ConfigurationException; +import org.osgi.service.cm.ManagedServiceFactory; + +/** + * + */ +public class ExtensionsTest implements ManagedServiceFactory, ConfigPropertiesProvider { + + //timeout if the service hasn't been called in 15 seconds + private final long TIMEOUT = 15000; + + Map> propSets = new ConcurrentHashMap>(); + + public Dictionary getPropertiesForId(String id) { + Dictionary props = getPropsForId(id); + synchronized (propSets) { + while (props == null) { + try { + propSets.wait(TIMEOUT); + props = getPropsForId(id); + } catch (InterruptedException e) { + throw new RuntimeException("Interrupted"); + } + if (props == null) + throw new RuntimeException("Extensions test timed out waiting for ManagedServiceFactory updated call starting with config id " + id); + } + } + return props; + } + + Dictionary getPropsForId(String id) { + return propSets.get(id); + } + + /* + * (non-Javadoc) + * + * @see org.osgi.service.cm.ManagedServiceFactory#deleted(java.lang.String) + */ + @Override + public void deleted(String pid) { + // TODO Auto-generated method stub + + } + + /* + * (non-Javadoc) + * + * @see org.osgi.service.cm.ManagedServiceFactory#updated(java.lang.String, java.util.Dictionary) + */ + @Override + public void updated(String pid, Dictionary properties) throws ConfigurationException { + System.out.println("ExtensionsTest (mock ManagedServiceFactory) updated called with pid: " + pid + " and properties: " + properties); + if (pid != null && properties != null) { + synchronized (propSets) { + String id; + propSets.put(((id = (String) properties.get("id")) == null) ? pid : id, properties); + propSets.notifyAll(); + } + } + } + + /* + * (non-Javadoc) + * + * @see org.osgi.service.cm.ManagedServiceFactory#getName() + */ + @Override + public String getName() { + // TODO Auto-generated method stub + return null; + } +} diff --git a/dev/com.ibm.ws.config_fat/test-bundles/test.config.extensions/src/test/config/extensions/TestResultsServlet.java b/dev/com.ibm.ws.config_fat/test-bundles/test.config.extensions/src/test/config/extensions/TestResultsServlet.java new file mode 100755 index 00000000000..0d87e0a34ef --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-bundles/test.config.extensions/src/test/config/extensions/TestResultsServlet.java @@ -0,0 +1,102 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012, 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package test.config.extensions; + +import java.io.IOException; +import java.util.Collection; +import java.util.Dictionary; +import java.util.HashSet; + +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.osgi.framework.BundleContext; +import org.osgi.framework.InvalidSyntaxException; +import org.osgi.framework.ServiceReference; + +import com.ibm.ws.config.xml.internal.XMLConfigConstants; + +/** + * + */ +@WebServlet(urlPatterns = { "test" }) +public class TestResultsServlet extends HttpServlet { + + /** */ + private static final long serialVersionUID = -4913608474531994493L; + private static final String servicePIDName = "service.pid"; + + /* + * (non-Javadoc) + * + * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) + */ + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + BundleContext ctxt = (BundleContext) req.getServletContext().getAttribute("osgi-bundlecontext"); + // Get the ManagedServiceFactory identifier so we can look up the correct service. + String servicePid = req.getParameter(servicePIDName); + Collection> refs = new HashSet>(); + ServiceReference ref = null; + + try { + + System.out.println("Looking up services with filter of (" + servicePIDName + "=" + servicePid + ")"); + // Find all services that match the relevant service.pid attr. There should only be one of these. + refs = ctxt.getServiceReferences(ConfigPropertiesProvider.class, "(" + servicePIDName + "=" + servicePid + ")"); + // If we don't find any then issue warning in the response. + if (!refs.isEmpty()) { + // There should only be one service, so pick the 1st one. + ref = refs.iterator().next(); + ConfigPropertiesProvider propsProvider = ctxt.getService(ref); + if (propsProvider != null) { + String id = req.getParameter("id"); + Dictionary props = propsProvider.getPropertiesForId(id); + if (props != null) { + String configId = (String) props.get(XMLConfigConstants.CFG_CONFIG_INSTANCE_ID); + if (configId != null && configId.startsWith(servicePid)) { + resp.getWriter().print("PASSED: test bundle was called with properties for ID " + id); + String propName; + if ((propName = req.getParameter("prop")) != null) { + resp.getWriter().print("Prop value: " + props.get(propName)); + } + resp.setStatus(HttpServletResponse.SC_OK); + return; + + } else { + resp.getWriter().print("FAILED: incorrect config.id in properties for ID " + id + ". Value: " + configId); + resp.setStatus(HttpServletResponse.SC_OK); + return; + } + } else { + resp.getWriter().print("FAILED: test bundle was not called with properties for PID starting with " + id); + resp.setStatus(HttpServletResponse.SC_OK); + return; + } + } + } else { + System.out.println("No service"); + resp.getWriter().print("FAILED: unable to find ConfigPropertiesProvider service"); + resp.setStatus(HttpServletResponse.SC_OK); + } + } catch (InvalidSyntaxException ise) { + resp.getWriter().print("Exception thrown whilst getting Config Property Provider service references: " + ise); + } finally { + // If the reference isn't null, release the service. + if (ref != null) + ctxt.ungetService(ref); + } + } +} diff --git a/dev/com.ibm.ws.config_fat/test-bundles/test.config.variables/bnd.bnd b/dev/com.ibm.ws.config_fat/test-bundles/test.config.variables/bnd.bnd new file mode 100755 index 00000000000..50b1b97f6ec --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-bundles/test.config.variables/bnd.bnd @@ -0,0 +1,12 @@ +-include= ~../../../cnf/resources/bnd/bundle.props +bVersion=1.0.0 + +# For more information, see http://was.pok.ibm.com/xwiki/bin/view/Liberty/UsingBnd + +Bundle-Name: Tests for variable behavior +Bundle-SymbolicName: test.config.variables +Bundle-Description: Test bundle for variable behavior, version=${bVersion} + + +Include-Resource: \ + OSGI-INF=resources/OSGI-INF diff --git a/dev/com.ibm.ws.config_fat/test-bundles/test.config.variables/resources/OSGI-INF/metatype/metatype-variables.xml b/dev/com.ibm.ws.config_fat/test-bundles/test.config.variables/resources/OSGI-INF/metatype/metatype-variables.xml new file mode 100755 index 00000000000..4343011b3f0 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-bundles/test.config.variables/resources/OSGI-INF/metatype/metatype-variables.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/test-bundles/test.merged.config/bnd.bnd b/dev/com.ibm.ws.config_fat/test-bundles/test.merged.config/bnd.bnd new file mode 100755 index 00000000000..e4a5a3e06a6 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-bundles/test.merged.config/bnd.bnd @@ -0,0 +1,15 @@ +-include= ~../../../cnf/resources/bnd/bundle.props +bVersion=1.0.0 + +# For more information, see http://was.pok.ibm.com/xwiki/bin/view/Liberty/UsingBnd + +Bundle-Name: Test Config Merging +Bundle-SymbolicName: test.merged.config +Bundle-Description: Test bundle for config merging, version=${bVersion} + +IBM-Default-Config: OSGI-INF/wlp/defaultInstances.xml, \ + OSGI-INF/wlp/defaultInstances2.xml; requireExisting=true, \ + OSGI-INF/wlp/defaultInstances3.xml; addIfMissing=true + +Include-Resource: \ + OSGI-INF=resources/OSGI-INF diff --git a/dev/com.ibm.ws.config_fat/test-bundles/test.merged.config/resources/OSGI-INF/metatype/metatype-mergedconfig.xml b/dev/com.ibm.ws.config_fat/test-bundles/test.merged.config/resources/OSGI-INF/metatype/metatype-mergedconfig.xml new file mode 100755 index 00000000000..7fd7305b577 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-bundles/test.merged.config/resources/OSGI-INF/metatype/metatype-mergedconfig.xml @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/test-bundles/test.merged.config/resources/OSGI-INF/wlp/defaultInstances.xml b/dev/com.ibm.ws.config_fat/test-bundles/test.merged.config/resources/OSGI-INF/wlp/defaultInstances.xml new file mode 100755 index 00000000000..e0a77cf718c --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-bundles/test.merged.config/resources/OSGI-INF/wlp/defaultInstances.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/test-bundles/test.merged.config/resources/OSGI-INF/wlp/defaultInstances2.xml b/dev/com.ibm.ws.config_fat/test-bundles/test.merged.config/resources/OSGI-INF/wlp/defaultInstances2.xml new file mode 100755 index 00000000000..f9ad45d4272 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-bundles/test.merged.config/resources/OSGI-INF/wlp/defaultInstances2.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/test-bundles/test.merged.config/resources/OSGI-INF/wlp/defaultInstances3.xml b/dev/com.ibm.ws.config_fat/test-bundles/test.merged.config/resources/OSGI-INF/wlp/defaultInstances3.xml new file mode 100755 index 00000000000..647420217a8 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-bundles/test.merged.config/resources/OSGI-INF/wlp/defaultInstances3.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/test-bundles/test.metatype.provider/bnd.bnd b/dev/com.ibm.ws.config_fat/test-bundles/test.metatype.provider/bnd.bnd new file mode 100755 index 00000000000..f448e82fefe --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-bundles/test.metatype.provider/bnd.bnd @@ -0,0 +1,16 @@ +-include= ~../../../cnf/resources/bnd/bundle.props +bVersion=1.0.0 + +# For more information, see http://was.pok.ibm.com/xwiki/bin/view/Liberty/UsingBnd + +Bundle-Name: Test MetatypeProvider +Bundle-SymbolicName: test.metatype.provider +Bundle-Description: Test bundle for MetatypeProvider, version=${bVersion} + +-dsannotations: com.ibm.ws.config.metatype.provider.Plant,\ + com.ibm.ws.config.metatype.provider.Animal,\ + com.ibm.ws.config.metatype.provider.AnimalToo + +Private-Package: com.ibm.ws.config.metatype.provider.* + +Import-Package: * diff --git a/dev/com.ibm.ws.config_fat/test-bundles/test.metatype.provider/src/com/ibm/ws/config/metatype/provider/Animal.java b/dev/com.ibm.ws.config_fat/test-bundles/test.metatype.provider/src/com/ibm/ws/config/metatype/provider/Animal.java new file mode 100755 index 00000000000..33139f3efbc --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-bundles/test.metatype.provider/src/com/ibm/ws/config/metatype/provider/Animal.java @@ -0,0 +1,157 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.config.metatype.provider; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Dictionary; +import java.util.List; + +import org.osgi.framework.Constants; +import org.osgi.service.cm.ConfigurationException; +import org.osgi.service.cm.ManagedServiceFactory; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.ConfigurationPolicy; +import org.osgi.service.component.annotations.Reference; +import org.osgi.service.component.annotations.ReferenceCardinality; +import org.osgi.service.metatype.AttributeDefinition; +import org.osgi.service.metatype.MetaTypeProvider; +import org.osgi.service.metatype.ObjectClassDefinition; + +import com.ibm.websphere.metatype.AttributeDefinitionProperties; +import com.ibm.websphere.metatype.MetaTypeFactory; +import com.ibm.websphere.metatype.ObjectClassDefinitionProperties; + +/** + * + */ +@Component(service = { Animal.class, ManagedServiceFactory.class, MetaTypeProvider.class }, immediate = true, + configurationPolicy = ConfigurationPolicy.IGNORE, + property = { Constants.SERVICE_VENDOR + "=" + "IBM", + Constants.SERVICE_PID + "=" + Animal.ANIMAL_PID }) +public class Animal implements ManagedServiceFactory, MetaTypeProvider { + + public static final String ANIMAL_PID = "test.metatype.provider.animal"; + private ObjectClassDefinition ocd; + private MetaTypeFactory metaTypeFactoryService; + + @Reference(service = MetaTypeFactory.class, + cardinality = ReferenceCardinality.MANDATORY) + protected void setMetaTypeFactoryService(MetaTypeFactory mtpService) { + this.metaTypeFactoryService = mtpService; + } + + /* + * (non-Javadoc) + * + * @see org.osgi.service.metatype.MetaTypeProvider#getLocales() + */ + @Override + public String[] getLocales() { + // TODO Auto-generated method stub + return null; + } + + /* + * (non-Javadoc) + * + * @see org.osgi.service.metatype.MetaTypeProvider#getObjectClassDefinition(java.lang.String, java.lang.String) + */ + @Override + public ObjectClassDefinition getObjectClassDefinition(String arg0, String arg1) { + if (this.ocd == null) { + AttributeDefinition nameAttr = new AnimalNameAttr(); + AttributeDefinition lifespanAttr = metaTypeFactoryService.createAttributeDefinition(getLifespanProps()); + AttributeDefinition eatsAttr = metaTypeFactoryService.createAttributeDefinition(getEatsProperties()); + List attributeList = new ArrayList(); + attributeList.add(lifespanAttr); + attributeList.add(nameAttr); + attributeList.add(eatsAttr); + this.ocd = metaTypeFactoryService.createObjectClassDefinition(getOCDProperties(), attributeList, Collections. emptyList()); + + } + + return this.ocd; + + } + + /** + * @return + */ + private AttributeDefinitionProperties getEatsProperties() { + AttributeDefinitionProperties props = new AttributeDefinitionProperties("eats"); + props.setName("eats"); + props.setDescription("What an animal eats"); + props.setType(MetaTypeFactory.PID_TYPE); + props.setReferencePid(Plant.PLANT_PID); + props.setCardinality(10); + return props; + } + + /** + * @return + */ + private AttributeDefinitionProperties getLifespanProps() { + AttributeDefinitionProperties props = new AttributeDefinitionProperties("lifespan"); + props.setName("Lifespan"); + props.setDescription("The animal's lifespan"); + props.setType(MetaTypeFactory.DURATION_TYPE); + props.setCardinality(0); + + return props; + } + + /** + * @param ocd2 + */ + private ObjectClassDefinitionProperties getOCDProperties() { + ObjectClassDefinitionProperties properties = new ObjectClassDefinitionProperties("test.metatype.provider.animal"); + properties.setDescription("An animal"); + properties.setName("test.metatype.provider.animal"); + properties.setAlias("animal"); + + return properties; + } + + /* + * (non-Javadoc) + * + * @see org.osgi.service.cm.ManagedServiceFactory#deleted(java.lang.String) + */ + @Override + public void deleted(String arg0) { + System.out.println("Deleted"); + + } + + /* + * (non-Javadoc) + * + * @see org.osgi.service.cm.ManagedServiceFactory#getName() + */ + @Override + public String getName() { + return "Animal MetatypeProvider"; + } + + /* + * (non-Javadoc) + * + * @see org.osgi.service.cm.ManagedServiceFactory#updated(java.lang.String, java.util.Dictionary) + */ + @Override + public void updated(String arg0, Dictionary arg1) throws ConfigurationException { + System.out.println("Updated"); + + } + +} diff --git a/dev/com.ibm.ws.config_fat/test-bundles/test.metatype.provider/src/com/ibm/ws/config/metatype/provider/AnimalNameAttr.java b/dev/com.ibm.ws.config_fat/test-bundles/test.metatype.provider/src/com/ibm/ws/config/metatype/provider/AnimalNameAttr.java new file mode 100755 index 00000000000..6612a203eef --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-bundles/test.metatype.provider/src/com/ibm/ws/config/metatype/provider/AnimalNameAttr.java @@ -0,0 +1,116 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.config.metatype.provider; + +import org.osgi.service.metatype.AttributeDefinition; + +import com.ibm.websphere.metatype.MetaTypeFactory; + +/** + * + */ +public class AnimalNameAttr implements AttributeDefinition { + + /** */ + public static final String ID_ATTRIBUTE = "name"; + + /* + * (non-Javadoc) + * + * @see org.osgi.service.metatype.AttributeDefinition#getCardinality() + */ + @Override + public int getCardinality() { + return 0; + } + + /* + * (non-Javadoc) + * + * @see org.osgi.service.metatype.AttributeDefinition#getDefaultValue() + */ + @Override + public String[] getDefaultValue() { + return null; + } + + /* + * (non-Javadoc) + * + * @see org.osgi.service.metatype.AttributeDefinition#getDescription() + */ + @Override + public String getDescription() { + return "The animal name"; + } + + /* + * (non-Javadoc) + * + * @see org.osgi.service.metatype.AttributeDefinition#getID() + */ + @Override + public String getID() { + return ID_ATTRIBUTE; + } + + /* + * (non-Javadoc) + * + * @see org.osgi.service.metatype.AttributeDefinition#getName() + */ + @Override + public String getName() { + return "Name"; + } + + /* + * (non-Javadoc) + * + * @see org.osgi.service.metatype.AttributeDefinition#getOptionLabels() + */ + @Override + public String[] getOptionLabels() { + return null; + } + + /* + * (non-Javadoc) + * + * @see org.osgi.service.metatype.AttributeDefinition#getOptionValues() + */ + @Override + public String[] getOptionValues() { + return null; + } + + /* + * (non-Javadoc) + * + * @see org.osgi.service.metatype.AttributeDefinition#getType() + */ + @Override + public int getType() { + return MetaTypeFactory.TOKEN_TYPE; + } + + /* + * (non-Javadoc) + * + * @see org.osgi.service.metatype.AttributeDefinition#validate(java.lang.String) + */ + @Override + public String validate(String arg0) { + return ""; + } + +} diff --git a/dev/com.ibm.ws.config_fat/test-bundles/test.metatype.provider/src/com/ibm/ws/config/metatype/provider/AnimalToo.java b/dev/com.ibm.ws.config_fat/test-bundles/test.metatype.provider/src/com/ibm/ws/config/metatype/provider/AnimalToo.java new file mode 100755 index 00000000000..287758ec60b --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-bundles/test.metatype.provider/src/com/ibm/ws/config/metatype/provider/AnimalToo.java @@ -0,0 +1,57 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2014 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.config.metatype.provider; + +import java.util.Map; + +import org.osgi.framework.Constants; +import org.osgi.service.cm.ConfigurationEvent; +import org.osgi.service.cm.ConfigurationListener; +import org.osgi.service.component.ComponentContext; +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Deactivate; +import org.osgi.service.component.annotations.Modified; + +/** + * + */ +@Component(service = { AnimalToo.class, ConfigurationListener.class }, immediate = true, + property = { Constants.SERVICE_VENDOR + "=" + "IBM" }) +public class AnimalToo implements ConfigurationListener { + + @Activate + protected void activate(ComponentContext ctx, Map config) { + System.out.println("Activate"); + } + + @Deactivate + protected void deactivate(ComponentContext ctx) { + System.out.println("Deactivate"); + } + + @Modified + protected void modified(Map config) { + System.out.println("MOdified"); + } + + /* + * (non-Javadoc) + * + * @see org.osgi.service.cm.ConfigurationListener#configurationEvent(org.osgi.service.cm.ConfigurationEvent) + */ + @Override + public void configurationEvent(ConfigurationEvent arg0) { + System.out.println("config event"); + + } +} diff --git a/dev/com.ibm.ws.config_fat/test-bundles/test.metatype.provider/src/com/ibm/ws/config/metatype/provider/Plant.java b/dev/com.ibm.ws.config_fat/test-bundles/test.metatype.provider/src/com/ibm/ws/config/metatype/provider/Plant.java new file mode 100755 index 00000000000..18868a4013c --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-bundles/test.metatype.provider/src/com/ibm/ws/config/metatype/provider/Plant.java @@ -0,0 +1,89 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.config.metatype.provider; + +import java.util.Dictionary; + +import org.osgi.framework.Constants; +import org.osgi.service.cm.ConfigurationException; +import org.osgi.service.cm.ManagedServiceFactory; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.ConfigurationPolicy; +import org.osgi.service.metatype.MetaTypeProvider; +import org.osgi.service.metatype.ObjectClassDefinition; + +/** + * + */ +@Component(service = { Plant.class, ManagedServiceFactory.class, MetaTypeProvider.class }, immediate = true, + configurationPolicy = ConfigurationPolicy.IGNORE, + property = { Constants.SERVICE_VENDOR + "=" + "IBM", + Constants.SERVICE_PID + "=" + Plant.PLANT_PID }) +public class Plant implements ManagedServiceFactory, MetaTypeProvider { + + public static final String PLANT_PID = "test.metatype.provider.plant"; + + /* + * (non-Javadoc) + * + * @see org.osgi.service.metatype.MetaTypeProvider#getLocales() + */ + @Override + public String[] getLocales() { + // TODO Auto-generated method stub + return null; + } + + /* + * (non-Javadoc) + * + * @see org.osgi.service.metatype.MetaTypeProvider#getObjectClassDefinition(java.lang.String, java.lang.String) + */ + @Override + public ObjectClassDefinition getObjectClassDefinition(String arg0, String arg1) { + return new PlantObjectClassDefinition(); + + } + + /* + * (non-Javadoc) + * + * @see org.osgi.service.cm.ManagedServiceFactory#deleted(java.lang.String) + */ + @Override + public void deleted(String arg0) { + System.out.println("Deleted"); + + } + + /* + * (non-Javadoc) + * + * @see org.osgi.service.cm.ManagedServiceFactory#getName() + */ + @Override + public String getName() { + return "Plant MetatypeProvider"; + } + + /* + * (non-Javadoc) + * + * @see org.osgi.service.cm.ManagedServiceFactory#updated(java.lang.String, java.util.Dictionary) + */ + @Override + public void updated(String arg0, Dictionary arg1) throws ConfigurationException { + System.out.println("Updated"); + + } + +} diff --git a/dev/com.ibm.ws.config_fat/test-bundles/test.metatype.provider/src/com/ibm/ws/config/metatype/provider/PlantNameAttr.java b/dev/com.ibm.ws.config_fat/test-bundles/test.metatype.provider/src/com/ibm/ws/config/metatype/provider/PlantNameAttr.java new file mode 100755 index 00000000000..5a699f6b277 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-bundles/test.metatype.provider/src/com/ibm/ws/config/metatype/provider/PlantNameAttr.java @@ -0,0 +1,111 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.config.metatype.provider; + +import org.osgi.service.metatype.AttributeDefinition; + +/** + * + */ +public class PlantNameAttr implements AttributeDefinition { + + /* + * (non-Javadoc) + * + * @see org.osgi.service.metatype.AttributeDefinition#getCardinality() + */ + @Override + public int getCardinality() { + return 0; + } + + /* + * (non-Javadoc) + * + * @see org.osgi.service.metatype.AttributeDefinition#getDefaultValue() + */ + @Override + public String[] getDefaultValue() { + return new String[] { "orchid" }; + } + + /* + * (non-Javadoc) + * + * @see org.osgi.service.metatype.AttributeDefinition#getDescription() + */ + @Override + public String getDescription() { + return "The plant name"; + } + + /* + * (non-Javadoc) + * + * @see org.osgi.service.metatype.AttributeDefinition#getID() + */ + @Override + public String getID() { + return "name"; + } + + /* + * (non-Javadoc) + * + * @see org.osgi.service.metatype.AttributeDefinition#getName() + */ + @Override + public String getName() { + return "Name"; + } + + /* + * (non-Javadoc) + * + * @see org.osgi.service.metatype.AttributeDefinition#getOptionLabels() + */ + @Override + public String[] getOptionLabels() { + return null; + } + + /* + * (non-Javadoc) + * + * @see org.osgi.service.metatype.AttributeDefinition#getOptionValues() + */ + @Override + public String[] getOptionValues() { + return null; + } + + /* + * (non-Javadoc) + * + * @see org.osgi.service.metatype.AttributeDefinition#getType() + */ + @Override + public int getType() { + return AttributeDefinition.STRING; + } + + /* + * (non-Javadoc) + * + * @see org.osgi.service.metatype.AttributeDefinition#validate(java.lang.String) + */ + @Override + public String validate(String arg0) { + return ""; + } + +} diff --git a/dev/com.ibm.ws.config_fat/test-bundles/test.metatype.provider/src/com/ibm/ws/config/metatype/provider/PlantObjectClassDefinition.java b/dev/com.ibm.ws.config_fat/test-bundles/test.metatype.provider/src/com/ibm/ws/config/metatype/provider/PlantObjectClassDefinition.java new file mode 100755 index 00000000000..fe9eb611913 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-bundles/test.metatype.provider/src/com/ibm/ws/config/metatype/provider/PlantObjectClassDefinition.java @@ -0,0 +1,77 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.config.metatype.provider; + +import java.io.IOException; +import java.io.InputStream; + +import org.osgi.service.metatype.AttributeDefinition; +import org.osgi.service.metatype.ObjectClassDefinition; + +/** + * + */ +public class PlantObjectClassDefinition implements ObjectClassDefinition { + + /* + * (non-Javadoc) + * + * @see org.osgi.service.metatype.ObjectClassDefinition#getAttributeDefinitions(int) + */ + @Override + public AttributeDefinition[] getAttributeDefinitions(int arg0) { + AttributeDefinition nameAttr = new PlantNameAttr(); + return new AttributeDefinition[] { nameAttr }; + } + + /* + * (non-Javadoc) + * + * @see org.osgi.service.metatype.ObjectClassDefinition#getDescription() + */ + @Override + public String getDescription() { + return "A Plant."; + } + + /* + * (non-Javadoc) + * + * @see org.osgi.service.metatype.ObjectClassDefinition#getID() + */ + @Override + public String getID() { + return "test.metatype.provider.plant"; + } + + /* + * (non-Javadoc) + * + * @see org.osgi.service.metatype.ObjectClassDefinition#getIcon(int) + */ + @Override + public InputStream getIcon(int arg0) throws IOException { + // TODO Auto-generated method stub + return null; + } + + /* + * (non-Javadoc) + * + * @see org.osgi.service.metatype.ObjectClassDefinition#getName() + */ + @Override + public String getName() { + return "test.metatype.provider.plant"; + } + +} diff --git a/dev/com.ibm.ws.config_fat/test-bundles/test.prod.extensions/bnd.bnd b/dev/com.ibm.ws.config_fat/test-bundles/test.prod.extensions/bnd.bnd new file mode 100755 index 00000000000..3819e8dc20f --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-bundles/test.prod.extensions/bnd.bnd @@ -0,0 +1,24 @@ +-include= ~../../../cnf/resources/bnd/bundle.props +bVersion=1.0.0 + +# For more information, see http://was.pok.ibm.com/xwiki/bin/view/Liberty/UsingBnd + +Bundle-Name: Test Config For Product Extensions +Bundle-SymbolicName: test.prod.extensions; singleton:=true +Bundle-Description: This bundle provides some services to use for testing; version=${bVersion} + +# export the interface packages +Export-Package: \ + test.prod.extensions;provide:=true + +Private-Package: test.prod.extensions.internal.* + +Web-ContextPath: product1-extensions-test + +Include-Resource:\ + OSGI-INF/metatype/metatype.xml=resources/metatype.xml + +Service-Component:\ + test.prod.extensions;\ + provide:='test.prod.extensions.ProductExtension1';\ + implementation:=test.prod.extensions.internal.ProductExtension1ServiceImpl \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/test-bundles/test.prod.extensions/resources/metatype.xml b/dev/com.ibm.ws.config_fat/test-bundles/test.prod.extensions/resources/metatype.xml new file mode 100755 index 00000000000..5ba90d49327 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-bundles/test.prod.extensions/resources/metatype.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/test-bundles/test.prod.extensions/src/test/prod/extensions/ProductExtension1.java b/dev/com.ibm.ws.config_fat/test-bundles/test.prod.extensions/src/test/prod/extensions/ProductExtension1.java new file mode 100755 index 00000000000..822dc1084d9 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-bundles/test.prod.extensions/src/test/prod/extensions/ProductExtension1.java @@ -0,0 +1,40 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package test.prod.extensions; + +/** + * Product extension service interface. + */ +public interface ProductExtension1 { + + /** + * Say Hello. + * + * @param input + * @return + */ + public String sayHello(String input); + + /** + * Retrieves configured attribute 1. + * + * @return A Long value. + */ + public Long getAttribute1(); + + /** + * Retrieves configured attribute 1. + * + * @return A String value. + */ + public String getAttribute2(); +} diff --git a/dev/com.ibm.ws.config_fat/test-bundles/test.prod.extensions/src/test/prod/extensions/ProductExtension1TestServlet.java b/dev/com.ibm.ws.config_fat/test-bundles/test.prod.extensions/src/test/prod/extensions/ProductExtension1TestServlet.java new file mode 100755 index 00000000000..7060f9df518 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-bundles/test.prod.extensions/src/test/prod/extensions/ProductExtension1TestServlet.java @@ -0,0 +1,124 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package test.prod.extensions; + +import java.io.IOException; +import java.lang.reflect.Method; + +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; + +/** + * ProductExtension1TestServlet. + */ +@WebServlet(urlPatterns = { "test" }) +public class ProductExtension1TestServlet extends HttpServlet { + + private static final long serialVersionUID = -4913608474531994493L; + public static final String SAY_HELLO_INPUT = "HelloYou"; + public static final String EXPECTED_SAY_HELLO = "you.said." + SAY_HELLO_INPUT + ".i.say." + SAY_HELLO_INPUT + ".back"; + public static final Long EXPECTED_ATTRB1 = 999999L; + public static final String EXPECTED_ATTRB2 = "HELLOWORLD"; + + /** + * doGet. + */ + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + ServiceReference prod1SvcRef = null; + BundleContext bundleContext = (BundleContext) req.getServletContext().getAttribute("osgi-bundlecontext"); + + // Unable to get bundle context. + if (bundleContext == null) { + String reply = "TEST_FAILED: Unable to obtain a bundle context reference."; + System.out.println(reply); + resp.getWriter().print(reply); + resp.setStatus(HttpServletResponse.SC_OK); + return; + } + + try { + prod1SvcRef = bundleContext.getServiceReference("test.prod.extensions.ProductExtension1"); + if (prod1SvcRef == null) { + printOutput(resp, "TEST_FAILED: Unable to get a UserProductExtension1 service reference."); + return; + } + + final Object prod1Svc = bundleContext.getService(prod1SvcRef); + if (prod1Svc != null) { + final Method sayHello_method = prod1Svc.getClass().getMethod("sayHello", String.class); + final Method getAtrib1Method = prod1Svc.getClass().getMethod("getAttribute1"); + final Method getAtrib2Method = prod1Svc.getClass().getMethod("getAttribute2"); + + if (sayHello_method == null || getAtrib1Method == null || getAtrib2Method == null) { + printOutput(resp, "TEST_FAILED: Unable get a method reference from the UserProductExtension1 service."); + return; + } + + // Call sayHello on the service. + String sayHelloOut = (String) sayHello_method.invoke(prod1Svc, SAY_HELLO_INPUT); + if (!sayHelloOut.equals(EXPECTED_SAY_HELLO)) { + printOutput(resp, "TEST_FAILED: sayHello returned: " + sayHelloOut + ". Expected: " + EXPECTED_SAY_HELLO); + return; + } + + // Call getAttribute1 on the service. + Long attrib1Out = (Long) getAtrib1Method.invoke(prod1Svc); + if (attrib1Out == null || attrib1Out.longValue() != EXPECTED_ATTRB1.longValue()) { + printOutput(resp, "TEST_FAILED: getAttribute1 returned: " + attrib1Out + ". Expected: " + EXPECTED_ATTRB1 + + ". Possible configuration error. The OCD alias under which attribute1 is defined must be prefixed by: \"productName_\"."); + return; + } + + // Call getAttribute2 on the service. + String attrib2Out = (String) getAtrib2Method.invoke(prod1Svc); + if (attrib2Out == null || !attrib2Out.equals(EXPECTED_ATTRB2)) { + printOutput(resp, "TEST_FAILED: getAttribute2 returned: " + attrib2Out + ". Expected: " + EXPECTED_ATTRB2 + + ". Possible configuration error. The OCD alias under which attribute2 is defined must be prefixed by: \"productName_\"."); + return; + } + + printOutput(resp, "TEST_PASSED: sayHello returned: " + sayHelloOut + ". getAttribute2 returned: " + attrib2Out); + } else { + printOutput(resp, "TEST_FAILED:Product1 service not found."); + } + } catch (Throwable t) { + printOutput(resp, "TEST_FAILED: Exception while processing test: " + t); + } finally { + if (prod1SvcRef != null) + bundleContext.ungetService(prod1SvcRef); + } + } + + /** + * Prints the output to the HTTP call. + * + * @param resp HttpServletResponse + * @param reply The repply. + */ + private void printOutput(HttpServletResponse resp, String reply) { + System.out.println(reply); + + try { + resp.getWriter().print(reply); + } catch (IOException ioe) { + System.out.println("Failed setting the reply in the HttpServletResponse" + ioe); + } + resp.setStatus(HttpServletResponse.SC_OK); + } +} diff --git a/dev/com.ibm.ws.config_fat/test-bundles/test.prod.extensions/src/test/prod/extensions/internal/ProductExtension1ServiceImpl.java b/dev/com.ibm.ws.config_fat/test-bundles/test.prod.extensions/src/test/prod/extensions/internal/ProductExtension1ServiceImpl.java new file mode 100755 index 00000000000..cf1e1182310 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-bundles/test.prod.extensions/src/test/prod/extensions/internal/ProductExtension1ServiceImpl.java @@ -0,0 +1,85 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package test.prod.extensions.internal; + +import java.util.Map; + +import org.osgi.framework.BundleContext; +import org.osgi.service.component.ComponentContext; + +import test.prod.extensions.ProductExtension1; + +/** + * Product Extension Service. + */ +public class ProductExtension1ServiceImpl implements ProductExtension1 { + + Long attribute1; + String attribute2; + + /** + * Declarative Services method to deactivate this component. + * Best practice: this should be a protected method, not public or private + * + * @param context context for this component + */ + protected void activate(BundleContext bundleContext, Map properties) { + System.out.println("@ed: attributeMap: " + properties.size()); + + for (Map.Entry entry : properties.entrySet()) { + System.out.println("key: " + entry.getKey() + ", value: " + entry.getValue()); + } + + attribute1 = (Long) properties.get("attribute1"); + System.out.println("@ed: attribute1: " + attribute1); + attribute2 = (String) properties.get("attribute2"); + System.out.println("@ed: attribute2: " + attribute2); + } + + /** + * Declarative Services method to deactivate this component. + * Best practice: this should be a protected method, not public or private + * + * @param context context for this component + */ + protected void deactivate(ComponentContext context) {} + + /* + * (non-Javadoc) + * + * @see test.prod.extensions.Product1#sayHello(java.lang.String) + */ + @Override + public String sayHello(String input) { + return "you.said." + input + ".i.say." + input + ".back"; + } + + /* + * (non-Javadoc) + * + * @see test.prod.extensions.Product1#getAttribute1() + */ + @Override + public Long getAttribute1() { + return attribute1; + } + + /* + * (non-Javadoc) + * + * @see test.prod.extensions.Product1#getAttribute1() + */ + @Override + public String getAttribute2() { + return attribute2; + } +} diff --git a/dev/com.ibm.ws.config_fat/test-bundles/test.user.prod.extensions/bnd.bnd b/dev/com.ibm.ws.config_fat/test-bundles/test.user.prod.extensions/bnd.bnd new file mode 100755 index 00000000000..695ffef979e --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-bundles/test.user.prod.extensions/bnd.bnd @@ -0,0 +1,24 @@ +-include= ~../../../cnf/resources/bnd/bundle.props +bVersion=1.0.0 + +# For more information, see http://was.pok.ibm.com/xwiki/bin/view/Liberty/UsingBnd + +Bundle-Name: Test Config For User Product Extensions +Bundle-SymbolicName: test.user.prod.extensions; singleton:=true +Bundle-Description: This bundle provides some services to use for testing; version=${bVersion} + +# export the interface packages +Export-Package: \ + test.user.prod.extensions;provide:=true + +Private-Package: test.user.prod.extensions.internal.* + +Web-ContextPath: user.product1-extensions-test + +Include-Resource:\ + OSGI-INF/metatype/metatype.xml=resources/metatype.xml + +Service-Component:\ + test.user.prod.extensions;\ + provide:='test.user.prod.extensions.UserProductExtension1';\ + implementation:=test.user.prod.extensions.internal.UserProductExtension1ServiceImpl \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/test-bundles/test.user.prod.extensions/resources/metatype.xml b/dev/com.ibm.ws.config_fat/test-bundles/test.user.prod.extensions/resources/metatype.xml new file mode 100755 index 00000000000..6e73ff6287e --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-bundles/test.user.prod.extensions/resources/metatype.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.config_fat/test-bundles/test.user.prod.extensions/src/test/user/prod/extensions/UserProductExtension1.java b/dev/com.ibm.ws.config_fat/test-bundles/test.user.prod.extensions/src/test/user/prod/extensions/UserProductExtension1.java new file mode 100755 index 00000000000..8e9410b57b0 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-bundles/test.user.prod.extensions/src/test/user/prod/extensions/UserProductExtension1.java @@ -0,0 +1,40 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package test.user.prod.extensions; + +/** + * User product extension service interface. + */ +public interface UserProductExtension1 { + + /** + * Say Hello. + * + * @param input + * @return + */ + public String sayHello(String input); + + /** + * Retrieves configured attribute 1. + * + * @return A Long value. + */ + public Long getAttribute1(); + + /** + * Retrieves configured attribute 1. + * + * @return A String value. + */ + public String getAttribute2(); +} diff --git a/dev/com.ibm.ws.config_fat/test-bundles/test.user.prod.extensions/src/test/user/prod/extensions/UserProductExtension1TestServlet.java b/dev/com.ibm.ws.config_fat/test-bundles/test.user.prod.extensions/src/test/user/prod/extensions/UserProductExtension1TestServlet.java new file mode 100755 index 00000000000..33cc2c7c312 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-bundles/test.user.prod.extensions/src/test/user/prod/extensions/UserProductExtension1TestServlet.java @@ -0,0 +1,123 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package test.user.prod.extensions; + +import java.io.IOException; +import java.lang.reflect.Method; + +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; + +/** + * UserProductExtension1TestServlet. + */ +@WebServlet(urlPatterns = { "test" }) +public class UserProductExtension1TestServlet extends HttpServlet { + private static final long serialVersionUID = -4913608474531994493L; + public static final String SAY_HELLO_INPUT = "HelloYou"; + public static final String EXPECTED_SAY_HELLO = "you.said." + SAY_HELLO_INPUT + ".i.say." + SAY_HELLO_INPUT + ".back"; + public static final Long EXPECTED_ATTRB1 = 999999L; + public static final String EXPECTED_ATTRB2 = "HELLOWORLD"; + + /** + * doGet. + */ + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + ServiceReference prod1SvcRef = null; + BundleContext bundleContext = (BundleContext) req.getServletContext().getAttribute("osgi-bundlecontext"); + + // Unable to get bundle context. + if (bundleContext == null) { + String reply = "TEST_FAILED: Unable to obtain a bundle context reference."; + System.out.println(reply); + resp.getWriter().print(reply); + resp.setStatus(HttpServletResponse.SC_OK); + return; + } + + try { + prod1SvcRef = bundleContext.getServiceReference("test.user.prod.extensions.UserProductExtension1"); + if (prod1SvcRef == null) { + printOutput(resp, "TEST_FAILED: Unable to get a UserProductExtension1 service reference."); + return; + } + + final Object prod1Svc = bundleContext.getService(prod1SvcRef); + if (prod1Svc != null) { + final Method sayHello_method = prod1Svc.getClass().getMethod("sayHello", String.class); + final Method getAtrib1Method = prod1Svc.getClass().getMethod("getAttribute1"); + final Method getAtrib2Method = prod1Svc.getClass().getMethod("getAttribute2"); + + if (sayHello_method == null || getAtrib1Method == null || getAtrib2Method == null) { + printOutput(resp, "TEST_FAILED: Unable get a method reference from the UserProductExtension1 service."); + return; + } + + // Call sayHello on the service. + String sayHelloOut = (String) sayHello_method.invoke(prod1Svc, SAY_HELLO_INPUT); + if (!sayHelloOut.equals(EXPECTED_SAY_HELLO)) { + printOutput(resp, "TEST_FAILED: sayHello returned: " + sayHelloOut + ". Expected: " + EXPECTED_SAY_HELLO); + return; + } + + // Call getAttribute1 on the service. + Long attrib1Out = (Long) getAtrib1Method.invoke(prod1Svc); + if (attrib1Out == null || attrib1Out.longValue() != EXPECTED_ATTRB1.longValue()) { + printOutput(resp, "TEST_FAILED: getAttribute1 returned: " + attrib1Out + ". Expected: " + EXPECTED_ATTRB1 + + ". Possible configuration error. The OCD alias under which attribute1 is defined must be prefixed by: \"productName_\"."); + return; + } + + // Call getAttribute2 on the service. + String attrib2Out = (String) getAtrib2Method.invoke(prod1Svc); + if (attrib2Out == null || !attrib2Out.equals(EXPECTED_ATTRB2)) { + printOutput(resp, "TEST_FAILED: getAttribute2 returned: " + attrib2Out + ". Expected: " + EXPECTED_ATTRB2 + + ". Possible configuration error. The OCD alias under which attribute2 is defined must be prefixed by: \"productName_\"."); + return; + } + + printOutput(resp, "TEST_PASSED: sayHello returned: " + sayHelloOut + ". getAttribute2 returned: " + attrib2Out); + } else { + printOutput(resp, "TEST_FAILED:Product1 service not found."); + } + } catch (Throwable t) { + printOutput(resp, "TEST_FAILED: Exception while processing test: " + t); + } finally { + if (prod1SvcRef != null) + bundleContext.ungetService(prod1SvcRef); + } + } + + /** + * Prints the output to the HTTP call. + * + * @param resp HttpServletResponse + * @param reply The repply. + */ + private void printOutput(HttpServletResponse resp, String reply) { + System.out.println(reply); + + try { + resp.getWriter().print(reply); + } catch (IOException ioe) { + System.out.println("Failed setting the reply in the HttpServletResponse" + ioe); + } + resp.setStatus(HttpServletResponse.SC_OK); + } +} diff --git a/dev/com.ibm.ws.config_fat/test-bundles/test.user.prod.extensions/src/test/user/prod/extensions/internal/UserProductExtension1ServiceImpl.java b/dev/com.ibm.ws.config_fat/test-bundles/test.user.prod.extensions/src/test/user/prod/extensions/internal/UserProductExtension1ServiceImpl.java new file mode 100755 index 00000000000..bebb0d80f22 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test-bundles/test.user.prod.extensions/src/test/user/prod/extensions/internal/UserProductExtension1ServiceImpl.java @@ -0,0 +1,77 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package test.user.prod.extensions.internal; + +import java.util.Map; + +import org.osgi.framework.BundleContext; +import org.osgi.service.component.ComponentContext; + +import test.user.prod.extensions.UserProductExtension1; + +/** + * User Product Extension Service. + */ +public class UserProductExtension1ServiceImpl implements UserProductExtension1 { + + Long attribute1; + String attribute2; + + /** + * Declarative Services method to deactivate this component. + * Best practice: this should be a protected method, not public or private + * + * @param context context for this component + */ + protected void activate(BundleContext bundleContext, Map properties) { + attribute1 = (Long) properties.get("attribute1"); + attribute2 = (String) properties.get("attribute2"); + } + + /** + * Declarative Services method to deactivate this component. + * Best practice: this should be a protected method, not public or private + * + * @param context context for this component + */ + protected void deactivate(ComponentContext context) {} + + /* + * (non-Javadoc) + * + * @see test.prod.extensions.Product1#sayHello(java.lang.String) + */ + @Override + public String sayHello(String input) { + return "you.said." + input + ".i.say." + input + ".back"; + } + + /* + * (non-Javadoc) + * + * @see test.prod.extensions.Product1#getAttribute1() + */ + @Override + public Long getAttribute1() { + return attribute1; + } + + /* + * (non-Javadoc) + * + * @see test.prod.extensions.Product1#getAttribute1() + */ + @Override + public String getAttribute2() { + return attribute2; + } +} diff --git a/dev/com.ibm.ws.config_fat/test/logging.properties b/dev/com.ibm.ws.config_fat/test/logging.properties new file mode 100755 index 00000000000..0b4c1bbfca6 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/test/logging.properties @@ -0,0 +1,76 @@ +############################################################ +# Logging Configuration File +# +# You can use a different file by specifying a filename +# with the java.util.logging.config.file system property. +# For example java -Djava.util.logging.config.file=myfile +############################################################ + +############################################################ +# Global properties +############################################################ + +# "handlers" specifies a comma separated list of log Handler +# classes. These handlers will be installed during VM startup. +# Note that these classes must be on the system classpath. +# By default we only configure a ConsoleHandler, which will only +# show messages at the INFO and above levels. +handlers=com.ibm.ws.fat.util.GenericHandler, java.util.logging.FileHandler + +# Default global logging level. +# This specifies which kinds of events are logged across +# all loggers. For any given facility this global level +# can be overriden by a facility specific level +# Note that the GenericHandler also has a separate level +# setting to limit messages printed to the underlying stream. +.level=INFO + +############################################################ +# Handler specific properties. +# Describes specific configuration info for Handlers. +############################################################ + +# The GenericHandler will log all messages printed at any logging level +com.ibm.ws.fat.util.GenericHandler.level=ALL +com.ibm.ws.fat.util.GenericHandler.formatter=com.ibm.ws.fat.util.GenericFormatter +com.ibm.ws.fat.util.GenericHandler.stream=system.out +com.ibm.ws.fat.util.GenericHandler.flush=true + +# The FileHandler will log all messages printed at any logging level to exactly one file located in results/output.txt +java.util.logging.FileHandler.level=ALL +java.util.logging.FileHandler.formatter=com.ibm.ws.fat.util.GenericFormatter +java.util.logging.FileHandler.limit=0 +java.util.logging.FileHandler.count=1 +java.util.logging.FileHandler.pattern=results/output.txt +java.util.logging.FileHandler.append=true + +############################################################ +# Formatter specific properties. +# Describes specific configuration info for Formatters. +############################################################ + +com.ibm.ws.fat.util.GenericFormatter.class.full=false +com.ibm.ws.fat.util.GenericFormatter.class.length=30 +com.ibm.ws.fat.util.GenericFormatter.class.log=true +com.ibm.ws.fat.util.GenericFormatter.level.log=true +com.ibm.ws.fat.util.GenericFormatter.method.length=30 +com.ibm.ws.fat.util.GenericFormatter.method.log=true +com.ibm.ws.fat.util.GenericFormatter.thread.length=3 +com.ibm.ws.fat.util.GenericFormatter.thread.log=true +com.ibm.ws.fat.util.GenericFormatter.time.format=[MM/dd/yyyy HH:mm:ss:SSS z] +com.ibm.ws.fat.util.GenericFormatter.time.log=true + +############################################################ +# Facility specific properties. +# Provides extra control for each logger. +############################################################ +com.ibm.ws.webcontainer.fvt.level=INFO +com.ibm.websphere.simplicity.level=INFO +com.ibm.ws.jmx.connector.client.level=FINEST +com.ibm.ws.jmx.connector.client.rest.internal.level=FINEST +com.ibm.ws.filetransfer.mbean.level=FINEST +test.server.config.level=FINER +#com.ibm.websphere.jiiws.level=FINER +#httpclient.wire.level=FINEST +#httpclient.wire.header.level=FINEST +#org.apache.commons.httpclient.level=FINEST diff --git a/dev/com.ibm.ws.config_fat/validator.exclude.xml b/dev/com.ibm.ws.config_fat/validator.exclude.xml new file mode 100644 index 00000000000..b8795817794 --- /dev/null +++ b/dev/com.ibm.ws.config_fat/validator.exclude.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/.classpath b/dev/com.ibm.ws.jmx.connector.client.rest/.classpath new file mode 100755 index 00000000000..2876090f903 --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/.classpath.gradle b/dev/com.ibm.ws.jmx.connector.client.rest/.classpath.gradle new file mode 100644 index 00000000000..2876090f903 --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/.classpath.gradle @@ -0,0 +1,7 @@ + + + + + + + diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/.gitignore b/dev/com.ibm.ws.jmx.connector.client.rest/.gitignore new file mode 100644 index 00000000000..57b341172a1 --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/.gitignore @@ -0,0 +1,2 @@ +/bin/ +/generated/ diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/.project b/dev/com.ibm.ws.jmx.connector.client.rest/.project new file mode 100755 index 00000000000..364b0f3a64a --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/.project @@ -0,0 +1,23 @@ + + + com.ibm.ws.jmx.connector.client.rest + + + + + + org.eclipse.jdt.core.javabuilder + + + + + bndtools.core.bndbuilder + + + + + + org.eclipse.jdt.core.javanature + bndtools.core.bndnature + + diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/.settings/org.eclipse.core.resources.prefs b/dev/com.ibm.ws.jmx.connector.client.rest/.settings/org.eclipse.core.resources.prefs new file mode 100755 index 00000000000..25d9425fe34 --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,4 @@ +#Ant properties +#Automatically generated by the ant prepare.settings.files task +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/.settings/org.eclipse.jdt.core.prefs b/dev/com.ibm.ws.jmx.connector.client.rest/.settings/org.eclipse.jdt.core.prefs new file mode 100755 index 00000000000..845c3083c7d --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,286 @@ +#Ant properties +#Automatically generated by the ant prepare.settings.files task +org.eclipse.jdt.core.codeComplete.argumentPrefixes= +org.eclipse.jdt.core.codeComplete.argumentSuffixes= +org.eclipse.jdt.core.codeComplete.fieldPrefixes= +org.eclipse.jdt.core.codeComplete.fieldSuffixes= +org.eclipse.jdt.core.codeComplete.localPrefixes= +org.eclipse.jdt.core.codeComplete.localSuffixes= +org.eclipse.jdt.core.codeComplete.staticFieldPrefixes= +org.eclipse.jdt.core.codeComplete.staticFieldSuffixes= +org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes= +org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes= +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.6 +org.eclipse.jdt.core.formatter.align_type_members_on_columns=false +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=0 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=18 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=2 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=2 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=18 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=2 +org.eclipse.jdt.core.formatter.alignment_for_assignment=0 +org.eclipse.jdt.core.formatter.alignment_for_binary_expression=18 +org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=0 +org.eclipse.jdt.core.formatter.alignment_for_enum_constants=16 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=18 +org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=18 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=18 +org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=0 +org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=20 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=4 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +org.eclipse.jdt.core.formatter.blank_lines_before_field=0 +org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 +org.eclipse.jdt.core.formatter.blank_lines_before_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 +org.eclipse.jdt.core.formatter.blank_lines_before_package=0 +org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 +org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 +org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false +org.eclipse.jdt.core.formatter.comment.format_block_comments=true +org.eclipse.jdt.core.formatter.comment.format_header=false +org.eclipse.jdt.core.formatter.comment.format_html=false +org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true +org.eclipse.jdt.core.formatter.comment.format_line_comments=false +org.eclipse.jdt.core.formatter.comment.format_source_code=true +org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true +org.eclipse.jdt.core.formatter.comment.indent_root_tags=true +org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert +org.eclipse.jdt.core.formatter.comment.line_length=180 +org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true +org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true +org.eclipse.jdt.core.formatter.compact_else_if=true +org.eclipse.jdt.core.formatter.continuation_indentation=4 +org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=4 +org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off +org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on +org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false +org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=false +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true +org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_empty_lines=false +org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true +org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true +org.eclipse.jdt.core.formatter.indentation.size=8 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert +org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.join_lines_in_comments=false +org.eclipse.jdt.core.formatter.join_wrapped_lines=false +org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false +org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false +org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false +org.eclipse.jdt.core.formatter.lineSplit=180 +org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=true +org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=true +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 +org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=false +org.eclipse.jdt.core.formatter.tabulation.char=space +org.eclipse.jdt.core.formatter.tabulation.size=4 +org.eclipse.jdt.core.formatter.use_on_off_tags=true +org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false +org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true +org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/.settings/org.eclipse.jdt.ui.prefs b/dev/com.ibm.ws.jmx.connector.client.rest/.settings/org.eclipse.jdt.ui.prefs new file mode 100755 index 00000000000..c874b581698 --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,117 @@ +#Ant properties +#Automatically generated by the ant prepare.settings.files task +cleanup.add_default_serial_version_id=false +cleanup.add_generated_serial_version_id=true +cleanup.add_missing_annotations=true +cleanup.add_missing_deprecated_annotations=true +cleanup.add_missing_methods=false +cleanup.add_missing_nls_tags=false +cleanup.add_missing_override_annotations=true +cleanup.add_missing_override_annotations_interface_methods=true +cleanup.add_serial_version_id=false +cleanup.always_use_blocks=true +cleanup.always_use_parentheses_in_expressions=false +cleanup.always_use_this_for_non_static_field_access=false +cleanup.always_use_this_for_non_static_method_access=false +cleanup.convert_to_enhanced_for_loop=false +cleanup.correct_indentation=true +cleanup.format_source_code=false +cleanup.format_source_code_changes_only=false +cleanup.make_local_variable_final=false +cleanup.make_parameters_final=true +cleanup.make_private_fields_final=false +cleanup.make_type_abstract_if_missing_method=false +cleanup.make_variable_declarations_final=false +cleanup.never_use_blocks=false +cleanup.never_use_parentheses_in_expressions=true +cleanup.organize_imports=false +cleanup.qualify_static_field_accesses_with_declaring_class=false +cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true +cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true +cleanup.qualify_static_member_accesses_with_declaring_class=true +cleanup.qualify_static_method_accesses_with_declaring_class=false +cleanup.remove_private_constructors=true +cleanup.remove_trailing_whitespaces=true +cleanup.remove_trailing_whitespaces_all=true +cleanup.remove_trailing_whitespaces_ignore_empty=false +cleanup.remove_unnecessary_casts=true +cleanup.remove_unnecessary_nls_tags=true +cleanup.remove_unused_imports=true +cleanup.remove_unused_local_variables=false +cleanup.remove_unused_private_fields=true +cleanup.remove_unused_private_members=false +cleanup.remove_unused_private_methods=true +cleanup.remove_unused_private_types=true +cleanup.sort_members=false +cleanup.sort_members_all=false +cleanup.use_blocks=true +cleanup.use_blocks_only_for_return_and_throw=false +cleanup.use_parentheses_in_expressions=true +cleanup.use_this_for_non_static_field_access=false +cleanup.use_this_for_non_static_field_access_only_if_necessary=true +cleanup.use_this_for_non_static_method_access=false +cleanup.use_this_for_non_static_method_access_only_if_necessary=true +eclipse.preferences.version=1 +editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true +org.eclipse.jdt.ui.exception.name=e +org.eclipse.jdt.ui.gettersetter.use.is=false +org.eclipse.jdt.ui.ignorelowercasenames=true +org.eclipse.jdt.ui.importorder=java;javax;org;com; +org.eclipse.jdt.ui.javadoc=true +org.eclipse.jdt.ui.keywordthis=false +org.eclipse.jdt.ui.ondemandthreshold=99 +org.eclipse.jdt.ui.overrideannotation=true +org.eclipse.jdt.ui.staticondemandthreshold=99 +org.eclipse.jdt.ui.text.custom_code_templates= +sp_cleanup.add_default_serial_version_id=true +sp_cleanup.add_generated_serial_version_id=false +sp_cleanup.add_missing_annotations=true +sp_cleanup.add_missing_deprecated_annotations=true +sp_cleanup.add_missing_methods=false +sp_cleanup.add_missing_nls_tags=false +sp_cleanup.add_missing_override_annotations=true +sp_cleanup.add_missing_override_annotations_interface_methods=true +sp_cleanup.add_serial_version_id=false +sp_cleanup.always_use_blocks=true +sp_cleanup.always_use_parentheses_in_expressions=false +sp_cleanup.always_use_this_for_non_static_field_access=false +sp_cleanup.always_use_this_for_non_static_method_access=false +sp_cleanup.convert_to_enhanced_for_loop=false +sp_cleanup.correct_indentation=false +sp_cleanup.format_source_code=true +sp_cleanup.format_source_code_changes_only=false +sp_cleanup.make_local_variable_final=false +sp_cleanup.make_parameters_final=false +sp_cleanup.make_private_fields_final=true +sp_cleanup.make_type_abstract_if_missing_method=false +sp_cleanup.make_variable_declarations_final=true +sp_cleanup.never_use_blocks=false +sp_cleanup.never_use_parentheses_in_expressions=true +sp_cleanup.on_save_use_additional_actions=true +sp_cleanup.organize_imports=true +sp_cleanup.qualify_static_field_accesses_with_declaring_class=false +sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_with_declaring_class=false +sp_cleanup.qualify_static_method_accesses_with_declaring_class=false +sp_cleanup.remove_private_constructors=true +sp_cleanup.remove_trailing_whitespaces=true +sp_cleanup.remove_trailing_whitespaces_all=true +sp_cleanup.remove_trailing_whitespaces_ignore_empty=false +sp_cleanup.remove_unnecessary_casts=true +sp_cleanup.remove_unnecessary_nls_tags=true +sp_cleanup.remove_unused_imports=true +sp_cleanup.remove_unused_local_variables=false +sp_cleanup.remove_unused_private_fields=true +sp_cleanup.remove_unused_private_members=false +sp_cleanup.remove_unused_private_methods=true +sp_cleanup.remove_unused_private_types=true +sp_cleanup.sort_members=false +sp_cleanup.sort_members_all=false +sp_cleanup.use_blocks=false +sp_cleanup.use_blocks_only_for_return_and_throw=false +sp_cleanup.use_parentheses_in_expressions=false +sp_cleanup.use_this_for_non_static_field_access=false +sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true +sp_cleanup.use_this_for_non_static_method_access=false +sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/bnd.bnd b/dev/com.ibm.ws.jmx.connector.client.rest/bnd.bnd new file mode 100755 index 00000000000..fc1d262a372 --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/bnd.bnd @@ -0,0 +1,35 @@ +-include= ~../cnf/resources/bnd/bundle.props +bVersion=1.0 + +Bundle-Name: JMX Connector Client +Bundle-SymbolicName: com.ibm.ws.jmx.connector.client.rest +Bundle-Description: JMX Connector Client and common converter code; version=${bVersion} + +Private-Package: \ + com.ibm.ws.jmx.connector.client.rest.internal.* + +Export-Package: \ + com.ibm.websphere.jmx.connector.rest, \ + com.ibm.ws.jmx.connector.client.rest;thread-context=true, \ + com.ibm.ws.jmx.connector.converter, \ + com.ibm.ws.jmx.connector.datatypes + +Import-Package: \ + javax.management.*, \ + com.ibm.json.java.*, \ + com.ibm.ws.ffdc.*, \ + com.ibm.websphere.ras.*, \ + com.ibm.ws.ssl.protocol, \ + javax.net.ssl + +Include-Resource: \ + META-INF=resources/META-INF + +-dsannotations: com.ibm.ws.jmx.connector.client.rest.internal.Activator + +instrument.disabled: true + +-buildpath: \ + com.ibm.wsspi.org.osgi.service.component.annotations.1.3.0,\ + com.ibm.websphere.appserver.api.json, \ + com.ibm.ws.org.osgi.annotation.versioning.1.0.0;version=latest diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/build.gradle b/dev/com.ibm.ws.jmx.connector.client.rest/build.gradle new file mode 100644 index 00000000000..e69de29bb2d diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/build.xml b/dev/com.ibm.ws.jmx.connector.client.rest/build.xml new file mode 100755 index 00000000000..01c35e90413 --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/build.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + Building ${clients.dir}/restConnector.jar with @{bnd} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/findbugs.exclude.xml b/dev/com.ibm.ws.jmx.connector.client.rest/findbugs.exclude.xml new file mode 100755 index 00000000000..9019b5841b7 --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/findbugs.exclude.xml @@ -0,0 +1,176 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/legal/copyright.properties b/dev/com.ibm.ws.jmx.connector.client.rest/legal/copyright.properties new file mode 100755 index 00000000000..c3eead2ff1e --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/legal/copyright.properties @@ -0,0 +1,13 @@ +#This properties describes files that have non-standard (i.e. non-OCO) copyright notices +# +#The name of property is the basename of the file (e.g., permissions.perm, MyJavaClass.java. +# +#The value of the property is why the file is non-standard: +# +# none - The file does not have or need a copyright notice +# apache - The file has an apache copyright notice +# sun - The file has a SUN copyright notice (which is valid as we are complying with the CDDL license) +# unclassified - The file is copyrighted by IBM, but is not Confidential or OCO +# restricted - This file is NOT OCO, but has the "Restricted Materials of IBM" notice +# +javax.management.remote.JMXConnectorProvider=none \ No newline at end of file diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/resources/META-INF/services/javax.management.remote.JMXConnectorProvider b/dev/com.ibm.ws.jmx.connector.client.rest/resources/META-INF/services/javax.management.remote.JMXConnectorProvider new file mode 100755 index 00000000000..84f96986bd3 --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/resources/META-INF/services/javax.management.remote.JMXConnectorProvider @@ -0,0 +1 @@ +com.ibm.ws.jmx.connector.client.rest.ClientProvider \ No newline at end of file diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages.nlsprops b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages.nlsprops new file mode 100755 index 00000000000..dc6e60b7ab0 --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages.nlsprops @@ -0,0 +1,55 @@ +# IBM Confidential OCO Source Material +# (C) COPYRIGHT International Business Machines Corp. 2011, 2014. +# The source code for this program is not published or otherwise divested +# of its trade secrets, irrespective of what has been deposited with the +# U.S. Copyright Office. +# ------------------------------------------------------------------------------------------------- +#CMVCPATHNAME com.ibm.ws.jmx.connector.client/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages.nlsprops +#COMPONENTPREFIX CWWKX +#COMPONENTNAMEFOR WebSphere Management File Transfer Client +#ISMESSAGEFILE TRUE +#NLS_MESSAGEFORMAT_VAR +#NLS_ENCODING=UNICODE +# ------------------------------------------------------------------------------------------------- + +# Message prefix block: CWWKX7951 - CWWKX7999 + +filetransfer.client.init=CWWKX7951I: A new file transfer client has connected with connection identifier {0}. +filetransfer.client.init.explanation=A new file transfer client has connected with the specified connection identifier. +filetransfer.client.init.useraction=This is an informational message, and no action is required. + +filetransfer.client.error=CWWKX7952E: A client-side error message "{0}" has occurred for connection {1}. +filetransfer.client.error.explanation=The client-side of the JMX REST connector encountered an error, and the specified message was generated. +filetransfer.client.error.useraction=Use the generated error message to identify, and correct the issue that caused this error, and rerun the operation. + +filetransfer.server.error=CWWKX7953E: Server-side error message "{0}" has occurred for connection {1}. +filetransfer.server.error.explanation=The server-side of the JMX REST connector encountered an error, and generated the specified message. +filetransfer.server.error.useraction=Use the generated error message to identify, and correct the issue that caused this error, and rerun the operation. + +filetransfer.client.bad.credentials=CWWKX7954E: The specified user name or password are not authorized. The server responded with code {0} and message "{1}" for connection {2}. +filetransfer.client.bad.credentials.explanation=The credentials provided when obtaining the connection are incorrect. The user may not exist, may not have authority to access the server, or the password may be incorrect. +filetransfer.client.bad.credentials.useraction=Correct the user name or password, then obtain a new connection. + +filetransfer.response.code.error=CWWKX7955E: The file transfer client received response code {0} with message "{1}" for connection {2}. +filetransfer.response.code.error.explanation=The file transfer client received an unexpected response code from the server. +filetransfer.response.code.error.useraction=Use the client response code to identify, and resolve the cause of this issue, and rerun the operation. + +filetransfer.download.file=CWWKX7956I: The request to download file {0} has been successful and its contents have been written into file {1} using connection {2}. +filetransfer.download.file.explanation=The download request of the specified file was successful. +filetransfer.download.file.useraction=This is an informational message, and no action is required. + +filetransfer.unsupported.operation=CWWKX7957E: The operation {0} is not supported by the file transfer client for connection {1}. +filetransfer.unsupported.operation.explanation=The specified operation is not supported by the file transfer client. +filetransfer.unsupported.operation.useraction=Request an operation that is supported by the file transfer client. + +filetransfer.upload.file=CWWKX7958I: The request to upload file {0} has been successful and its contents have been written into file {1} using connection {2}. +filetransfer.upload.file.explanation=The upload request of the specified file was successful. +filetransfer.upload.file.useraction=This is an informational message, and no action is required. + +filetransfer.delete.file=CWWKX7959I: The request to delete file {0} has been successful using connection {1}. +filetransfer.delete.file.explanation=The delete request of the specified file was successful. +filetransfer.delete.file.useraction=This is an informational message, and no action is required. + +filetransfer.delete.all=CWWKX7960I: The request to delete all files and folders from collection {0} succeeded using connection {1}. +filetransfer.delete.all.explanation=The delete request of the specified collection was successful. +filetransfer.delete.all.useraction=This is an informational message, and no action is required. diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_cs.nlsprops b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_cs.nlsprops new file mode 100755 index 00000000000..a785a8c4482 --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_cs.nlsprops @@ -0,0 +1,55 @@ +# IBM Confidential OCO Source Material +# (C) COPYRIGHT International Business Machines Corp. 2011, 2014. +# The source code for this program is not published or otherwise divested +# of its trade secrets, irrespective of what has been deposited with the +# U.S. Copyright Office. +# ------------------------------------------------------------------------------------------------- +#CMVCPATHNAME com.ibm.ws.jmx.connector.client/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages.nlsprops +#COMPONENTPREFIX CWWKX +#COMPONENTNAMEFOR WebSphere Management File Transfer Client +#ISMESSAGEFILE TRUE +#NLS_MESSAGEFORMAT_VAR +#NLS_ENCODING=UNICODE +# ------------------------------------------------------------------------------------------------- + +# Message prefix block: CWWKX7951 - CWWKX7999 + +filetransfer.client.init=CWWKX7951I: Nov\u00fd klient p\u0159enosu soubor\u016f se spojil s identifik\u00e1torem p\u0159ipojen\u00ed {0}. +filetransfer.client.init.explanation=Nov\u00fd klient p\u0159enosu soubor\u016f se spojil s ur\u010den\u00fdm identifik\u00e1torem p\u0159ipojen\u00ed. +filetransfer.client.init.useraction=Toto je informativn\u00ed zpr\u00e1va a nen\u00ed pot\u0159eba \u017e\u00e1dn\u00e1 akce. + +filetransfer.client.error=CWWKX7952E: Do\u0161lo k chybov\u00e1 zpr\u00e1v\u011b "{0}" na stran\u011b klienta pro p\u0159ipojen\u00ed {1}. +filetransfer.client.error.explanation=Do\u0161lo k chyb\u011b konektoru JMX REST na stran\u011b klienta a byla generov\u00e1na ur\u010den\u00e1 zpr\u00e1va. +filetransfer.client.error.useraction=Pomoc\u00ed generovan\u00e9 chybov\u00e9 zpr\u00e1vy identifikujte a opravte probl\u00e9m, kter\u00fd tuto chybu zp\u016fsobil, a spus\u0165te operaci znovu. + +filetransfer.server.error=CWWKX7953E: Do\u0161lo k chybov\u00e1 zpr\u00e1v\u011b "{0}" na stran\u011b serveru pro p\u0159ipojen\u00ed {1}. +filetransfer.server.error.explanation=Do\u0161lo k chyb\u011b konektoru JMX REST na stran\u011b serveru a byla generov\u00e1na uveden\u00e1 zpr\u00e1va. +filetransfer.server.error.useraction=Pomoc\u00ed generovan\u00e9 chybov\u00e9 zpr\u00e1vy identifikujte a opravte probl\u00e9m, kter\u00fd tuto chybu zp\u016fsobil, a spus\u0165te operaci znovu. + +filetransfer.client.bad.credentials=CWWKX7954E: Zadan\u00e9 u\u017eivatelsk\u00e9 jm\u00e9no a heslo nen\u00ed autorizovan\u00e9. Server odpov\u011bd\u011bl k\u00f3dem {0} a zpr\u00e1vou "{1}" pro p\u0159ipojen\u00ed {2}. +filetransfer.client.bad.credentials.explanation=Pov\u011b\u0159en\u00ed zadan\u00e1 p\u0159i z\u00edsk\u00e1v\u00e1n\u00ed p\u0159ipojen\u00ed jsou nespr\u00e1vn\u00e1. Je mo\u017en\u00e9, \u017ee u\u017eivatel neexistuje, nem\u00e1 opr\u00e1vn\u011bn\u00ed pro p\u0159\u00edstup na server nebo je nespr\u00e1vn\u00e9 heslo. +filetransfer.client.bad.credentials.useraction=Opravte jm\u00e9no u\u017eivatele nebo heslo a pot\u00e9 z\u00edskejte nov\u00e9 p\u0159ipojen\u00ed. + +filetransfer.response.code.error=CWWKX7955E: Klient p\u0159enosu soubor\u016f p\u0159ijal k\u00f3d odezvy {0} se zpr\u00e1vou "{1}" pro p\u0159ipojen\u00ed {2}. +filetransfer.response.code.error.explanation=Klient p\u0159enosu soubor\u016f p\u0159ijal neo\u010dek\u00e1van\u00fd k\u00f3d odezvy ze serveru. +filetransfer.response.code.error.useraction=Pomoc\u00ed k\u00f3du odezvy klienta ur\u010dete a vy\u0159e\u0161te p\u0159\u00ed\u010dinu tohoto probl\u00e9mu a spus\u0165te operaci znovu. + +filetransfer.download.file=CWWKX7956I: Po\u017eadavek na sta\u017een\u00ed souboru {0} byl \u00fasp\u011b\u0161n\u011b proveden a obsah byl zaps\u00e1n do souboru {1} pomoc\u00ed p\u0159ipojen\u00ed {2}. +filetransfer.download.file.explanation=Po\u017eadavek na sta\u017een\u00ed uveden\u00e9ho souboru byl \u00fasp\u011b\u0161n\u011b proveden. +filetransfer.download.file.useraction=Toto je informativn\u00ed zpr\u00e1va a nen\u00ed pot\u0159eba \u017e\u00e1dn\u00e1 akce. + +filetransfer.unsupported.operation=CWWKX7957E: Operaci {0} klient p\u0159enosu soubor\u016f nepodporuje pro p\u0159ipojen\u00ed {1}. +filetransfer.unsupported.operation.explanation=Uvedenou operaci klient p\u0159enosu soubor\u016f nepodporuje. +filetransfer.unsupported.operation.useraction=Vy\u017e\u00e1dejte si operaci, kterou klient p\u0159enosu soubor\u016f podporuje. + +filetransfer.upload.file=CWWKX7958I: Po\u017eadavek na odesl\u00e1n\u00ed souboru {0} byl \u00fasp\u011b\u0161n\u011b proveden a obsah byl zaps\u00e1n do souboru {1} pomoc\u00ed p\u0159ipojen\u00ed {2}. +filetransfer.upload.file.explanation=Po\u017eadavek na odesl\u00e1n\u00ed uveden\u00e9ho souboru byl \u00fasp\u011b\u0161n\u011b proveden. +filetransfer.upload.file.useraction=Toto je informativn\u00ed zpr\u00e1va a nen\u00ed pot\u0159eba \u017e\u00e1dn\u00e1 akce. + +filetransfer.delete.file=CWWKX7959I: Po\u017eadavek na odstran\u011bn\u00ed souboru {0} byl proveden \u00fasp\u011b\u0161n\u011b pomoc\u00ed p\u0159ipojen\u00ed {1}. +filetransfer.delete.file.explanation=Po\u017eadavek na odstran\u011bn\u00ed uveden\u00e9ho souboru byl \u00fasp\u011b\u0161n\u00fd. +filetransfer.delete.file.useraction=Toto je informativn\u00ed zpr\u00e1va a nen\u00ed pot\u0159eba \u017e\u00e1dn\u00e1 akce. + +filetransfer.delete.all=CWWKX7960I: Po\u017eadavek na odstran\u011bn\u00ed v\u0161ech soubor\u016f a slo\u017eek z kolekce {0} byl \u00fasp\u011b\u0161n\u011b proveden pomoc\u00ed p\u0159ipojen\u00ed {1}. +filetransfer.delete.all.explanation=Po\u017eadavek na odstran\u011bn\u00ed uveden\u00e9 kolekce byl \u00fasp\u011b\u0161n\u00fd. +filetransfer.delete.all.useraction=Toto je informativn\u00ed zpr\u00e1va a nen\u00ed pot\u0159eba \u017e\u00e1dn\u00e1 akce. diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_de.nlsprops b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_de.nlsprops new file mode 100755 index 00000000000..c734ddb8fc3 --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_de.nlsprops @@ -0,0 +1,55 @@ +# IBM Confidential OCO Source Material +# (C) COPYRIGHT International Business Machines Corp. 2011, 2014. +# The source code for this program is not published or otherwise divested +# of its trade secrets, irrespective of what has been deposited with the +# U.S. Copyright Office. +# ------------------------------------------------------------------------------------------------- +#CMVCPATHNAME com.ibm.ws.jmx.connector.client/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages.nlsprops +#COMPONENTPREFIX CWWKX +#COMPONENTNAMEFOR WebSphere Management File Transfer Client +#ISMESSAGEFILE TRUE +#NLS_MESSAGEFORMAT_VAR +#NLS_ENCODING=UNICODE +# ------------------------------------------------------------------------------------------------- + +# Message prefix block: CWWKX7951 - CWWKX7999 + +filetransfer.client.init=CWWKX7951I: Ein neuer Datei\u00fcbertragungsclient hat eine Verbindung mit der Verbindungs-ID {0} hergestellt. +filetransfer.client.init.explanation=Ein neuer Datei\u00fcbertragungsclient hat eine Verbindung mit der angegebenen Verbindungs-ID hergestellt. +filetransfer.client.init.useraction=Dies ist eine Informationsnachricht. Es ist keine Aktion erforderlich. + +filetransfer.client.error=CWWKX7952E: Der clientseitige Fehler "{0}" ist f\u00fcr die Verbindung {1} aufgetreten. +filetransfer.client.error.explanation=Auf der Clientseite des JMX-REST-Connectors ist ein Fehler aufgetreten, und es wurde die angegebene Nachricht generiert. +filetransfer.client.error.useraction=Verwenden Sie die generierte Fehlernachricht, um das Problem, das diesen Fehler verursacht, zu identifizieren und zu beheben, und f\u00fchren Sie anschlie\u00dfend die Operation erneut aus. + +filetransfer.server.error=CWWKX7953E: Der serverseitige Fehler "{0}" ist f\u00fcr die Verbindung {1} aufgetreten. +filetransfer.server.error.explanation=Auf der Serverseite des JMX-REST-Connectors ist ein Fehler aufgetreten, und es wurde die angegebene Nachricht generiert. +filetransfer.server.error.useraction=Verwenden Sie die generierte Fehlernachricht, um das Problem, das diesen Fehler verursacht, zu identifizieren und zu beheben, und f\u00fchren Sie anschlie\u00dfend die Operation erneut aus. + +filetransfer.client.bad.credentials=CWWKX7954E: Der angegebene Benutzername oder das angegebene Kennwort ist nicht berechtigt. Der Server hat mit dem Code {0} und der Nachricht "{1}" f\u00fcr die Verbindung {2} geantwortet. +filetransfer.client.bad.credentials.explanation=Die beim Anfordern der Verbindung angegebenen Berechtigungsnachweise sind nicht g\u00fcltig. M\u00f6glicherweise ist der Benutzer nicht vorhanden, oder er hat keine Berechtigung f\u00fcr den Zugriff auf den Server, oder das Kennwort ist ung\u00fcltig. +filetransfer.client.bad.credentials.useraction=Korrigieren Sie den Benutzernamen bzw. das Kennwort, und fordern Sie dann eine neue Verbindung an. + +filetransfer.response.code.error=CWWKX7955E: Der Datei\u00fcbertragungsclient hat den Antwortcode {0} mit der Nachricht "{1}" f\u00fcr die Verbindung {2} empfangen. +filetransfer.response.code.error.explanation=Der Datei\u00fcbertragungsclient hat einen unerwarteten Antwortcode vom Server empfangen. +filetransfer.response.code.error.useraction=Verwenden Sie den Antwortcode des Clients, um die Ursache f\u00fcr dieses Problem zu identifizieren und zu beheben, und f\u00fchren Sie anschlie\u00dfend die Operation erneut aus. + +filetransfer.download.file=CWWKX7956I: Die Anforderung zum Herunterladen der Datei {0} war erfolgreich, und der Inhalt der Datei wurde in die Datei {1} geschrieben. Die Verbindung {2} wurde daf\u00fcr verwendet. +filetransfer.download.file.explanation=Die Downloadanforderung f\u00fcr die angegebene Datei war erfolgreich. +filetransfer.download.file.useraction=Dies ist eine Informationsnachricht. Es ist keine Aktion erforderlich. + +filetransfer.unsupported.operation=CWWKX7957E: Die Operation {0} wird vom Datei\u00fcbertragungsclient f\u00fcr die Verbindung {1} nicht unterst\u00fctzt. +filetransfer.unsupported.operation.explanation=Die angegebene Operation wird vom Datei\u00fcbertragungsclient nicht unterst\u00fctzt. +filetransfer.unsupported.operation.useraction=Fordern Sie eine Operation an, die vom Datei\u00fcbertragungsclient unterst\u00fctzt wird. + +filetransfer.upload.file=CWWKX7958I: Die Anforderung zum Hochladen der Datei {0} war erfolgreich, und der Inhalt der Datei wurde in die Datei {1} geschrieben. Die Verbindung {2} wurde daf\u00fcr verwendet. +filetransfer.upload.file.explanation=Die Uploadanforderung f\u00fcr die angegebene Datei war erfolgreich. +filetransfer.upload.file.useraction=Dies ist eine Informationsnachricht. Es ist keine Aktion erforderlich. + +filetransfer.delete.file=CWWKX7959I: Die Anforderung zum L\u00f6schen der Datei {0} \u00fcber die Verbindung {1} war erfolgreich. +filetransfer.delete.file.explanation=Die Anforderung zum L\u00f6schen der angegebenen Datei war erfolgreich. +filetransfer.delete.file.useraction=Dies ist eine Informationsnachricht. Es ist keine Aktion erforderlich. + +filetransfer.delete.all=CWWKX7960I: Die Anforderung zum L\u00f6schen aller Dateien und Ordner aus der Sammlung {0} \u00fcber die Verbindung {1} war erfolgreich. +filetransfer.delete.all.explanation=Die L\u00f6schanforderung f\u00fcr die angegebene Sammlung war erfolgreich. +filetransfer.delete.all.useraction=Dies ist eine Informationsnachricht. Es ist keine Aktion erforderlich. diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_es.nlsprops b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_es.nlsprops new file mode 100755 index 00000000000..df6c915a4df --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_es.nlsprops @@ -0,0 +1,55 @@ +# IBM Confidential OCO Source Material +# (C) COPYRIGHT International Business Machines Corp. 2011, 2014. +# The source code for this program is not published or otherwise divested +# of its trade secrets, irrespective of what has been deposited with the +# U.S. Copyright Office. +# ------------------------------------------------------------------------------------------------- +#CMVCPATHNAME com.ibm.ws.jmx.connector.client/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages.nlsprops +#COMPONENTPREFIX CWWKX +#COMPONENTNAMEFOR WebSphere Management File Transfer Client +#ISMESSAGEFILE TRUE +#NLS_MESSAGEFORMAT_VAR +#NLS_ENCODING=UNICODE +# ------------------------------------------------------------------------------------------------- + +# Message prefix block: CWWKX7951 - CWWKX7999 + +filetransfer.client.init=CWWKX7951I: Un nuevo cliente de transferencia de archivos se ha conectado con el ID de conexi\u00f3n {0}. +filetransfer.client.init.explanation=Un nuevo cliente de transferencia de archivos se ha conectado con el ID de conexi\u00f3n especificado. +filetransfer.client.init.useraction=Este es un mensaje informativo y no es necesaria ninguna acci\u00f3n. + +filetransfer.client.error=CWWKX7952E: Se ha generado un mensaje de error del lado de cliente "{0}" para la conexi\u00f3n {1}. +filetransfer.client.error.explanation=El lado del cliente del conector JMX REST ha encontrado un error y se ha generado el mensaje especificado. +filetransfer.client.error.useraction=Utilice el mensaje de error generado para identificar y corregir el problema que ha provocado este error, y vuelva a ejecutar la operaci\u00f3n. + +filetransfer.server.error=CWWKX7953E: Se ha generado un mensaje de error del lado de servidor "{0}" para la conexi\u00f3n {1}. +filetransfer.server.error.explanation=El lado del servidor del conector JMX REST ha encontrado un error y se ha generado el mensaje especificado. +filetransfer.server.error.useraction=Utilice el mensaje de error generado para identificar y corregir el problema que ha provocado este error, y vuelva a ejecutar la operaci\u00f3n. + +filetransfer.client.bad.credentials=CWWKX7954E: El nombre de usuario o la contrase\u00f1a especificados no est\u00e1n autorizados. El servidor ha respondido con el c\u00f3digo {0} y el mensaje "{1}" para la conexi\u00f3n {2}. +filetransfer.client.bad.credentials.explanation=Las credenciales proporcionadas al obtener la conexi\u00f3n son incorrectas. El usuario puede que no exista, puede que no tenga autoridad para acceder al servidor o que la contrase\u00f1a sea incorrecta. +filetransfer.client.bad.credentials.useraction=Corrija el nombre de usuario o la contrase\u00f1a y despu\u00e9s obtenga una nueva conexi\u00f3n. + +filetransfer.response.code.error=CWWKX7955E: El cliente de transferencia de archivos ha recibido un c\u00f3digo de respuesta {0} con el mensaje "{1}" para la conexi\u00f3n {2}. +filetransfer.response.code.error.explanation=El cliente de transferencia de archivos ha recibido un c\u00f3digo de respuesta inesperado del servidor. +filetransfer.response.code.error.useraction=Utilice el c\u00f3digo de respuesta del cliente para identificar y resolver la causa del problema, y vuelva a ejecutar la operaci\u00f3n. + +filetransfer.download.file=CWWKX7956I: La solicitud de descarga del archivo {0} ha sido satisfactoria y su contenido se ha escrito en el archivo {1} utilizando la conexi\u00f3n {2}. +filetransfer.download.file.explanation=La solicitud de descarga del archivo especificado ha sido satisfactoria. +filetransfer.download.file.useraction=Este es un mensaje informativo y no es necesaria ninguna acci\u00f3n. + +filetransfer.unsupported.operation=CWWKX7957E: La operaci\u00f3n {0} no est\u00e1 soportada por el cliente de transferencia de archivos para la conexi\u00f3n {1}. +filetransfer.unsupported.operation.explanation=La operaci\u00f3n especificada no est\u00e1 soportada por el cliente de transferencia de archivos. +filetransfer.unsupported.operation.useraction=Solicite una operaci\u00f3n que est\u00e9 soportada por el cliente de transferencia de archivos. + +filetransfer.upload.file=CWWKX7958I: La solicitud de carga del archivo {0} ha sido satisfactoria y su contenido se ha escrito en el archivo {1} utilizando la conexi\u00f3n {2}. +filetransfer.upload.file.explanation=La solicitud de carga del archivo especificado ha sido satisfactoria. +filetransfer.upload.file.useraction=Este es un mensaje informativo y no es necesaria ninguna acci\u00f3n. + +filetransfer.delete.file=CWWKX7959I: La solicitud de supresi\u00f3n del archivo {0} ha sido satisfactoria utilizando conexi\u00f3n {1}. +filetransfer.delete.file.explanation=La solicitud de supresi\u00f3n del archivo especificado ha sido satisfactoria. +filetransfer.delete.file.useraction=Este es un mensaje informativo y no es necesaria ninguna acci\u00f3n. + +filetransfer.delete.all=CWWKX7960I: La solicitud de supresi\u00f3n de todos los archivos y carpetas de la colecci\u00f3n {0} ha sido satisfactoria utilizando la conexi\u00f3n {1}. +filetransfer.delete.all.explanation=La solicitud de supresi\u00f3n de la colecci\u00f3n especificada ha sido satisfactoria. +filetransfer.delete.all.useraction=Este es un mensaje informativo y no es necesaria ninguna acci\u00f3n. diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_fr.nlsprops b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_fr.nlsprops new file mode 100755 index 00000000000..d2c482d796f --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_fr.nlsprops @@ -0,0 +1,55 @@ +# IBM Confidential OCO Source Material +# (C) COPYRIGHT International Business Machines Corp. 2011, 2014. +# The source code for this program is not published or otherwise divested +# of its trade secrets, irrespective of what has been deposited with the +# U.S. Copyright Office. +# ------------------------------------------------------------------------------------------------- +#CMVCPATHNAME com.ibm.ws.jmx.connector.client/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages.nlsprops +#COMPONENTPREFIX CWWKX +#COMPONENTNAMEFOR WebSphere Management File Transfer Client +#ISMESSAGEFILE TRUE +#NLS_MESSAGEFORMAT_VAR +#NLS_ENCODING=UNICODE +# ------------------------------------------------------------------------------------------------- + +# Message prefix block: CWWKX7951 - CWWKX7999 + +filetransfer.client.init=CWWKX7951I: Un nouveau client de transfert de fichier a \u00e9t\u00e9 connect\u00e9 avec l''identificateur de connexion {0}. +filetransfer.client.init.explanation=Un nouveau client de transfert de fichier a \u00e9t\u00e9 connect\u00e9 avec l'identificateur de connexion indiqu\u00e9. +filetransfer.client.init.useraction=Il s'agit d'un message d'information et aucune action n'est requise. + +filetransfer.client.error=CWWKX7952E: Un message d''erreur "{0}" a \u00e9t\u00e9 g\u00e9n\u00e9r\u00e9 c\u00f4t\u00e9 client pour la connexion {1}. +filetransfer.client.error.explanation=Une erreur s'est produite pour le connecteur JMX REST c\u00f4t\u00e9 client et le message indiqu\u00e9 a \u00e9t\u00e9 g\u00e9n\u00e9r\u00e9. +filetransfer.client.error.useraction=Utilisez le message d'erreur g\u00e9n\u00e9r\u00e9 pour identifier et corriger le probl\u00e8me \u00e0 l'origine de cette erreur, puis relancez l'op\u00e9ration. + +filetransfer.server.error=CWWKX7953E: Le message d''erreur "{0}" a \u00e9t\u00e9 g\u00e9n\u00e9r\u00e9 c\u00f4t\u00e9 serveur pour la connexion {1}. +filetransfer.server.error.explanation=Une erreur s'est produite sur le connecteur JMX REST c\u00f4t\u00e9 serveur et a g\u00e9n\u00e9r\u00e9 le message indiqu\u00e9. +filetransfer.server.error.useraction=Utilisez le message d'erreur g\u00e9n\u00e9r\u00e9 pour identifier et corriger le probl\u00e8me \u00e0 l'origine de cette erreur, puis relancez l'op\u00e9ration. + +filetransfer.client.bad.credentials=CWWKX7954E: Le nom d''utilisateur ou le mot de passe indiqu\u00e9 n''est pas autoris\u00e9. Le serveur a r\u00e9pondu avec le code {0} et le message "{1}" pour la connexion {2}. +filetransfer.client.bad.credentials.explanation=Les donn\u00e9es d'identification fournies lors de l'obtention de la connexion sont incorrectes. L'utilisateur n'existe peut-\u00eatre pas, s'il existe, il n'a peut-\u00eatre pas le droit d'acc\u00e9der au serveur, ou le mot de passe indiqu\u00e9 est incorrect. +filetransfer.client.bad.credentials.useraction=Corrigez le nom d'utilisateur ou le mot de passe, puis obtenez une nouvelle connexion. + +filetransfer.response.code.error=CWWKX7955E: Le client de transfert de fichier a re\u00e7u un code de r\u00e9ponse {0} avec le message "{1}" pour la connexion {2}. +filetransfer.response.code.error.explanation=Le client du transfert de fichiers a re\u00e7u un code de r\u00e9ponse inattendu du serveur. +filetransfer.response.code.error.useraction=Utilisez la code de r\u00e9ponse client pour identifier et r\u00e9soudre ce probl\u00e8me, puis relancez l'op\u00e9ration. + +filetransfer.download.file=CWWKX7956I: La demande de t\u00e9l\u00e9chargement du fichier {0} a abouti et son contenu a \u00e9t\u00e9 \u00e9crit dans le fichier {1} \u00e0 l''aide de la connexion {2}. +filetransfer.download.file.explanation=La demande de t\u00e9l\u00e9chargement du fichier sp\u00e9cifi\u00e9 a abouti. +filetransfer.download.file.useraction=Il s'agit d'un message d'information et aucune action n'est requise. + +filetransfer.unsupported.operation=CWWKX7957E: L''op\u00e9ration {0} n''est pas prise en charge par le client de transfert de fichier pour la connexion {1}. +filetransfer.unsupported.operation.explanation=L'op\u00e9ration sp\u00e9cifi\u00e9e n'est pas prise en charge par le client du transfert de fichiers. +filetransfer.unsupported.operation.useraction=Demandez une op\u00e9ration qui est prise en charge par le client du transfert de fichiers. + +filetransfer.upload.file=CWWKX7958I: La demande de t\u00e9l\u00e9chargement du fichier {0} a abouti et son contenu a \u00e9t\u00e9 \u00e9crit dans le fichier {1} \u00e0 l''aide de la connexion {2}. +filetransfer.upload.file.explanation=La demande de t\u00e9l\u00e9chargement du fichier sp\u00e9cifi\u00e9 a abouti. +filetransfer.upload.file.useraction=Il s'agit d'un message d'information et aucune action n'est requise. + +filetransfer.delete.file=CWWKX7959I: La demande de suppression du fichier {0} \u00e0 l''aide de la connexion {1} a abouti. +filetransfer.delete.file.explanation=La demande de suppression du fichier indiqu\u00e9 a abouti. +filetransfer.delete.file.useraction=Il s'agit d'un message d'information et aucune action n'est requise. + +filetransfer.delete.all=CWWKX7960I: La demande de suppression de tous les fichiers et dossiers de la collection {0} a r\u00e9ussi via la connexion {1}. +filetransfer.delete.all.explanation=La demande de suppression de la collection sp\u00e9cifi\u00e9e a r\u00e9ussi. +filetransfer.delete.all.useraction=Il s'agit d'un message d'information et aucune action n'est requise. diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_hu.nlsprops b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_hu.nlsprops new file mode 100755 index 00000000000..b5afafc9697 --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_hu.nlsprops @@ -0,0 +1,55 @@ +# IBM Confidential OCO Source Material +# (C) COPYRIGHT International Business Machines Corp. 2011, 2014. +# The source code for this program is not published or otherwise divested +# of its trade secrets, irrespective of what has been deposited with the +# U.S. Copyright Office. +# ------------------------------------------------------------------------------------------------- +#CMVCPATHNAME com.ibm.ws.jmx.connector.client/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages.nlsprops +#COMPONENTPREFIX CWWKX +#COMPONENTNAMEFOR WebSphere Management File Transfer Client +#ISMESSAGEFILE TRUE +#NLS_MESSAGEFORMAT_VAR +#NLS_ENCODING=UNICODE +# ------------------------------------------------------------------------------------------------- + +# Message prefix block: CWWKX7951 - CWWKX7999 + +filetransfer.client.init=CWWKX7951I: \u00daj f\u00e1jl\u00e1tviteli \u00fcgyf\u00e9l csatlakozott {0} kapcsolatazonos\u00edt\u00f3val. +filetransfer.client.init.explanation=\u00daj f\u00e1jl\u00e1tviteli \u00fcgyf\u00e9l csatlakozott a megadott kapcsolatazonos\u00edt\u00f3val. +filetransfer.client.init.useraction=Ez inform\u00e1ci\u00f3s \u00fczenet, semmit sem kell tennie. + +filetransfer.client.error=CWWKX7952E: \u00dcgyf\u00e9loldali "{0}" hiba\u00fczenet a(z) {1} kapcsolat eset\u00e9ben. +filetransfer.client.error.explanation=A JMX REST csatol\u00f3 \u00fcgyf\u00e9l oldal\u00e1n hiba t\u00f6rt\u00e9nt, \u00e9s a megadott \u00fczenet j\u00f6tt l\u00e9tre. +filetransfer.client.error.useraction=Az el\u0151\u00e1ll\u00edtott hiba\u00fczenet seg\u00edts\u00e9g\u00e9vel azonos\u00edtsa \u00e9s jav\u00edtsa a hib\u00e1t okoz\u00f3 probl\u00e9m\u00e1t, majd futtassa \u00fajra a m\u0171veletet. + +filetransfer.server.error=CWWKX7953E: Kiszolg\u00e1l\u00f3 oldali "{0}" hiba\u00fczenet a(z) {1} kapcsolat eset\u00e9ben. +filetransfer.server.error.explanation=A JMX REST csatol\u00f3 kiszolg\u00e1l\u00f3 oldal\u00e1n hiba t\u00f6rt\u00e9nt, \u00e9s a megadott \u00fczenetet \u00e1ll\u00edtotta el\u0151. +filetransfer.server.error.useraction=Az el\u0151\u00e1ll\u00edtott hiba\u00fczenet seg\u00edts\u00e9g\u00e9vel azonos\u00edtsa \u00e9s jav\u00edtsa a hib\u00e1t okoz\u00f3 probl\u00e9m\u00e1t, majd futtassa \u00fajra a m\u0171veletet. + +filetransfer.client.bad.credentials=CWWKX7954E: A megadottfelhaszn\u00e1l\u00f3n\u00e9v \u00e9s jelsz\u00f3 nem jogosult. A kiszolg\u00e1l\u00f3 a(z) {0} k\u00f3ddal \u00e9s"{1}" \u00fczenettel v\u00e1laszolt a(z) {2} kapcsolat eset\u00e9ben. +filetransfer.client.bad.credentials.explanation=A kapcsolat l\u00e9trehoz\u00e1sakor megadott hiteles\u00edt\u00e9si adatok helytelenek. Lehet, hogy a felhaszn\u00e1l\u00f3 nem l\u00e9tezik, nincs jogosults\u00e1ga a kiszolg\u00e1l\u00f3 el\u00e9r\u00e9s\u00e9hez, vagy helytelen a jelsz\u00f3. +filetransfer.client.bad.credentials.useraction=Jav\u00edtsa ki a felhaszn\u00e1l\u00f3nevet vagy jelsz\u00f3t, majd hozzon l\u00e9tre \u00faj kapcsolatot. + +filetransfer.response.code.error=CWWKX7955E: A f\u00e1jl\u00e1tviteli \u00fcgyf\u00e9l {0} v\u00e1laszk\u00f3dot kapott "{1}" \u00fczenettel a(z) {2} kapcsolat eset\u00e9ben. +filetransfer.response.code.error.explanation=A f\u00e1jl\u00e1tviteli \u00fcgyf\u00e9l nem v\u00e1rt v\u00e1laszk\u00f3dot kapott a kiszolg\u00e1l\u00f3t\u00f3l. +filetransfer.response.code.error.useraction=Az \u00fcgyf\u00e9l v\u00e1laszk\u00f3ddal azonos\u00edtsa \u00e9s oldja meg a probl\u00e9ma ok\u00e1t, majd futtassa \u00fajra a m\u0171veletet. + +filetransfer.download.file=CWWKX7956I: A(z) {0} f\u00e1jl let\u00f6lt\u00e9s\u00e9re vonatkoz\u00f3 k\u00e9r\u00e9s sikeres volt, \u00e9s a tartalma a(z) {1} f\u00e1jlba lett \u00edrva a(z) {2} kapcsolat alkalmaz\u00e1s\u00e1val. +filetransfer.download.file.explanation=A megadott f\u00e1jl let\u00f6lt\u00e9si k\u00e9r\u00e9se sikeres volt. +filetransfer.download.file.useraction=Ez inform\u00e1ci\u00f3s \u00fczenet, semmit sem kell tennie. + +filetransfer.unsupported.operation=CWWKX7957E: A(z) {0} m\u0171veletet a f\u00e1jl\u00e1tviteli \u00fcgyf\u00e9l nem t\u00e1mogatja a(z) {1} kapcsolat eset\u00e9ben. +filetransfer.unsupported.operation.explanation=A megadott m\u0171veletet nem t\u00e1mogatja a f\u00e1jl\u00e1tviteli \u00fcgyf\u00e9l. +filetransfer.unsupported.operation.useraction=K\u00e9rjen olyan m\u0171veletet, amelyet a f\u00e1jl\u00e1tviteli \u00fcgyf\u00e9l t\u00e1mogat. + +filetransfer.upload.file=CWWKX7958I: A(z) {0} f\u00e1jl felt\u00f6lt\u00e9s\u00e9re vonatkoz\u00f3 k\u00e9r\u00e9s sikeres volt, \u00e9s a tartalma a(z) {1} f\u00e1jlba lett \u00edrva a(z) {2} kapcsolat alkalmaz\u00e1s\u00e1val. +filetransfer.upload.file.explanation=A megadott f\u00e1jl felt\u00f6lt\u00e9si k\u00e9r\u00e9se sikeres volt. +filetransfer.upload.file.useraction=Ez inform\u00e1ci\u00f3s \u00fczenet, semmit sem kell tennie. + +filetransfer.delete.file=CWWKX7959I: A(z) {0} f\u00e1jl t\u00f6rl\u00e9s\u00e9re vonatkoz\u00f3 k\u00e9r\u00e9s sikeres volt a(z) {1} kapcsolat felhaszn\u00e1l\u00e1s\u00e1val. +filetransfer.delete.file.explanation=A megadott f\u00e1jl t\u00f6rl\u00e9si k\u00e9r\u00e9se sikeres volt. +filetransfer.delete.file.useraction=Ez inform\u00e1ci\u00f3s \u00fczenet, semmit sem kell tennie. + +filetransfer.delete.all=CWWKX7960I: A(z) {0} gy\u0171jtem\u00e9nyben l\u00e9v\u0151 \u00f6sszes f\u00e1jl \u00e9s mappa t\u00f6rl\u00e9s\u00e9re vonatkoz\u00f3 k\u00e9r\u00e9s siker\u00fclt a(z) {1} kapcsolat haszn\u00e1lat\u00e1val. +filetransfer.delete.all.explanation=A megadott gy\u0171jtem\u00e9ny t\u00f6rl\u00e9si k\u00e9r\u00e9se sikeres volt. +filetransfer.delete.all.useraction=Ez inform\u00e1ci\u00f3s \u00fczenet, semmit sem kell tennie. diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_it.nlsprops b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_it.nlsprops new file mode 100755 index 00000000000..be4711857d0 --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_it.nlsprops @@ -0,0 +1,55 @@ +# IBM Confidential OCO Source Material +# (C) COPYRIGHT International Business Machines Corp. 2011, 2014. +# The source code for this program is not published or otherwise divested +# of its trade secrets, irrespective of what has been deposited with the +# U.S. Copyright Office. +# ------------------------------------------------------------------------------------------------- +#CMVCPATHNAME com.ibm.ws.jmx.connector.client/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages.nlsprops +#COMPONENTPREFIX CWWKX +#COMPONENTNAMEFOR WebSphere Management File Transfer Client +#ISMESSAGEFILE TRUE +#NLS_MESSAGEFORMAT_VAR +#NLS_ENCODING=UNICODE +# ------------------------------------------------------------------------------------------------- + +# Message prefix block: CWWKX7951 - CWWKX7999 + +filetransfer.client.init=CWWKX7951I: Un nuovo client di trasferimento file si \u00e8 connesso con l''identificativo di connessione {0}. +filetransfer.client.init.explanation=Un nuovo client di trasferimento file si \u00e8 connesso con l'identificativo di connessione specificato. +filetransfer.client.init.useraction=Si tratta di un messaggio informativo, non \u00e8 richiesta alcuna azione. + +filetransfer.client.error=CWWKX7952E: Si \u00e8 verificato un messaggio di errore lato client "{0}" per la connessione {1}. +filetransfer.client.error.explanation=Il connettore REST JMX lato client ha rilevato un errore ed \u00e8 stato generato il messaggio specificato. +filetransfer.client.error.useraction=Utilizzare il messaggio di errore generato per identificare e risolvere il problema che ha causato questo errore ed eseguire di nuovo l'operazione. + +filetransfer.server.error=CWWKX7953E: Si \u00e8 verificato un messaggio di errore lato server "{0}" per la connessione {1}. +filetransfer.server.error.explanation=Il connettore REST JMX lato server ha rilevato un errore ed \u00e8 stato generato il messaggio specificato. +filetransfer.server.error.useraction=Utilizzare il messaggio di errore generato per identificare e risolvere il problema che ha causato questo errore ed eseguire di nuovo l'operazione. + +filetransfer.client.bad.credentials=CWWKX7954E: Il nome utente o la password specificati non sono autorizzati. Il server ha risposto con il codice {0} e il messaggio "{1}" per la connessione {2}. +filetransfer.client.bad.credentials.explanation=Le credenziali fornite durante il tentativo di ottenere la connessione non sono corrette. Probabilmente l'utente non esiste, non dispone dell'autorizzazione per accedere al server oppure la password non \u00e8 corretta. +filetransfer.client.bad.credentials.useraction=Correggere il nome utente o la password, quindi ottenere la connessione. + +filetransfer.response.code.error=CWWKX7955E: Il client di trasferimento file ha ricevuto il codice di risposta {0} con il messaggio "{1}" per la connessione {2}. +filetransfer.response.code.error.explanation=Il client di trasferimento file ha ricevuto un codice di risposta imprevisto dal server. +filetransfer.response.code.error.useraction=Utilizzare il codice di risposta del client per identificare e risolvere la causa di questo problema, ed eseguire di nuovo l'operazione. + +filetransfer.download.file=CWWKX7956I: La richiesta di scaricamento del file {0} \u00e8 riuscita e il suo contenuto \u00e8 stato scritto nel file {1} utilizzando la connessione {2}. +filetransfer.download.file.explanation=La richiesta di scaricamento del file specificato \u00e8 riuscita. +filetransfer.download.file.useraction=Si tratta di un messaggio informativo, non \u00e8 richiesta alcuna azione. + +filetransfer.unsupported.operation=CWWKX7957E: L''operazione {0} non \u00e8 supportata dal client di trasferimento file per la connessione {1}. +filetransfer.unsupported.operation.explanation=L'operazione specificata non \u00e8 supportata dal client di trasferimento file. +filetransfer.unsupported.operation.useraction=Richiedere un'operazione supportata dal client di trasferimento file. + +filetransfer.upload.file=CWWKX7958I: La richiesta di caricamento del file {0} \u00e8 riuscita e il suo contenuto \u00e8 stato scritto nel file {1} utilizzando la connessione {2}. +filetransfer.upload.file.explanation=La richiesta di caricamento del file specificato \u00e8 riuscita. +filetransfer.upload.file.useraction=Si tratta di un messaggio informativo, non \u00e8 richiesta alcuna azione. + +filetransfer.delete.file=CWWKX7959I: La richiesta di eliminazione del file {0} \u00e8 riuscita utilizzando la connessione {1}. +filetransfer.delete.file.explanation=La richiesta di eliminazione del file specificato \u00e8 riuscita. +filetransfer.delete.file.useraction=Si tratta di un messaggio informativo, non \u00e8 richiesta alcuna azione. + +filetransfer.delete.all=CWWKX7960I: Richiesta di eliminazione di tutti i file e cartelle dalla raccolta {0} riuscita con la connessione {1}. +filetransfer.delete.all.explanation=La richiesta di eliminazione della raccolta specificata \u00e8 riuscita. +filetransfer.delete.all.useraction=Si tratta di un messaggio informativo, non \u00e8 richiesta alcuna azione. diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_ja.nlsprops b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_ja.nlsprops new file mode 100755 index 00000000000..73608fc0076 --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_ja.nlsprops @@ -0,0 +1,55 @@ +# IBM Confidential OCO Source Material +# (C) COPYRIGHT International Business Machines Corp. 2011, 2014. +# The source code for this program is not published or otherwise divested +# of its trade secrets, irrespective of what has been deposited with the +# U.S. Copyright Office. +# ------------------------------------------------------------------------------------------------- +#CMVCPATHNAME com.ibm.ws.jmx.connector.client/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages.nlsprops +#COMPONENTPREFIX CWWKX +#COMPONENTNAMEFOR WebSphere Management File Transfer Client +#ISMESSAGEFILE TRUE +#NLS_MESSAGEFORMAT_VAR +#NLS_ENCODING=UNICODE +# ------------------------------------------------------------------------------------------------- + +# Message prefix block: CWWKX7951 - CWWKX7999 + +filetransfer.client.init=CWWKX7951I: \u65b0\u898f\u30d5\u30a1\u30a4\u30eb\u8ee2\u9001\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u304c\u3001\u63a5\u7d9a ID {0} \u3092\u7528\u3044\u3066\u63a5\u7d9a\u3055\u308c\u307e\u3057\u305f\u3002 +filetransfer.client.init.explanation=\u65b0\u898f\u30d5\u30a1\u30a4\u30eb\u8ee2\u9001\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u304c\u3001\u793a\u3055\u308c\u305f\u63a5\u7d9a ID \u3092\u7528\u3044\u3066\u63a5\u7d9a\u3055\u308c\u307e\u3057\u305f\u3002 +filetransfer.client.init.useraction=\u3053\u308c\u306f\u901a\u77e5\u30e1\u30c3\u30bb\u30fc\u30b8\u3067\u3042\u308a\u3001\u51e6\u7f6e\u306f\u4e0d\u8981\u3067\u3059\u3002 + +filetransfer.client.error=CWWKX7952E: \u63a5\u7d9a {1} \u306b\u5bfe\u3057\u3066\u3001\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u30fb\u30b5\u30a4\u30c9\u306e\u30a8\u30e9\u30fc\u30fb\u30e1\u30c3\u30bb\u30fc\u30b8\u300c{0}\u300d\u304c\u51fa\u3055\u308c\u307e\u3057\u305f\u3002 +filetransfer.client.error.explanation=JMX REST \u30b3\u30cd\u30af\u30bf\u30fc\u306e\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u30fb\u30b5\u30a4\u30c9\u304c\u30a8\u30e9\u30fc\u3092\u691c\u51fa\u3057\u3001\u793a\u3055\u308c\u305f\u30e1\u30c3\u30bb\u30fc\u30b8\u304c\u751f\u6210\u3055\u308c\u307e\u3057\u305f\u3002 +filetransfer.client.error.useraction=\u751f\u6210\u3055\u308c\u305f\u30a8\u30e9\u30fc\u30fb\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u4f7f\u7528\u3057\u3066\u3053\u306e\u30a8\u30e9\u30fc\u3092\u5f15\u304d\u8d77\u3053\u3057\u305f\u554f\u984c\u3092\u7279\u5b9a\u3057\u3001\u4fee\u6b63\u3057\u3066\u3001\u64cd\u4f5c\u3092\u518d\u5b9f\u884c\u3057\u3066\u304f\u3060\u3055\u3044\u3002 + +filetransfer.server.error=CWWKX7953E: \u63a5\u7d9a {1} \u306b\u5bfe\u3057\u3066\u3001\u30b5\u30fc\u30d0\u30fc\u30fb\u30b5\u30a4\u30c9\u306e\u30a8\u30e9\u30fc\u30fb\u30e1\u30c3\u30bb\u30fc\u30b8\u300c{0}\u300d\u304c\u51fa\u3055\u308c\u307e\u3057\u305f\u3002 +filetransfer.server.error.explanation=JMX REST \u30b3\u30cd\u30af\u30bf\u30fc\u306e\u30b5\u30fc\u30d0\u30fc\u30fb\u30b5\u30a4\u30c9\u304c\u30a8\u30e9\u30fc\u3092\u691c\u51fa\u3057\u3001\u793a\u3055\u308c\u305f\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u751f\u6210\u3057\u307e\u3057\u305f\u3002 +filetransfer.server.error.useraction=\u751f\u6210\u3055\u308c\u305f\u30a8\u30e9\u30fc\u30fb\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u4f7f\u7528\u3057\u3066\u3053\u306e\u30a8\u30e9\u30fc\u3092\u5f15\u304d\u8d77\u3053\u3057\u305f\u554f\u984c\u3092\u7279\u5b9a\u3057\u3001\u4fee\u6b63\u3057\u3066\u3001\u64cd\u4f5c\u3092\u518d\u5b9f\u884c\u3057\u3066\u304f\u3060\u3055\u3044\u3002 + +filetransfer.client.bad.credentials=CWWKX7954E: \u6307\u5b9a\u3055\u308c\u305f\u30e6\u30fc\u30b6\u30fc\u540d\u307e\u305f\u306f\u30d1\u30b9\u30ef\u30fc\u30c9\u306f\u8a31\u53ef\u3055\u308c\u307e\u305b\u3093\u3002\u30b5\u30fc\u30d0\u30fc\u306f\u3001\u63a5\u7d9a {2} \u306b\u3064\u3044\u3066\u30b3\u30fc\u30c9 {0}\u3001\u30e1\u30c3\u30bb\u30fc\u30b8\u300c{1}\u300d\u3067\u5fdc\u7b54\u3057\u307e\u3057\u305f\u3002 +filetransfer.client.bad.credentials.explanation=\u63a5\u7d9a\u306e\u53d6\u5f97\u6642\u306b\u6307\u5b9a\u3057\u305f\u8cc7\u683c\u60c5\u5831\u306b\u8aa4\u308a\u304c\u3042\u308a\u307e\u3059\u3002 \u30e6\u30fc\u30b6\u30fc\u304c\u5b58\u5728\u3057\u306a\u3044\u304b\u3001\u30e6\u30fc\u30b6\u30fc\u306b\u30b5\u30fc\u30d0\u30fc\u3078\u306e\u30a2\u30af\u30bb\u30b9\u6a29\u9650\u304c\u306a\u3044\u304b\u3001\u307e\u305f\u306f\u30d1\u30b9\u30ef\u30fc\u30c9\u306b\u8aa4\u308a\u304c\u3042\u308b\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002 +filetransfer.client.bad.credentials.useraction=\u30e6\u30fc\u30b6\u30fc\u540d\u307e\u305f\u306f\u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u8a02\u6b63\u3057\u3066\u304b\u3089\u65b0\u898f\u63a5\u7d9a\u3092\u53d6\u5f97\u3057\u3066\u304f\u3060\u3055\u3044\u3002 + +filetransfer.response.code.error=CWWKX7955E: \u30d5\u30a1\u30a4\u30eb\u8ee2\u9001\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u304c\u3001\u63a5\u7d9a {2} \u306b\u3064\u3044\u3066\u3001\u5fdc\u7b54\u30b3\u30fc\u30c9 {0} \u304a\u3088\u3073\u30e1\u30c3\u30bb\u30fc\u30b8\u300c{1}\u300d\u3092\u53d7\u3051\u53d6\u308a\u307e\u3057\u305f\u3002 +filetransfer.response.code.error.explanation=\u30d5\u30a1\u30a4\u30eb\u8ee2\u9001\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u304c\u3001\u30b5\u30fc\u30d0\u30fc\u304b\u3089\u4e88\u671f\u3057\u306a\u3044\u5fdc\u7b54\u30b3\u30fc\u30c9\u3092\u53d7\u4fe1\u3057\u307e\u3057\u305f\u3002 +filetransfer.response.code.error.useraction=\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u306e\u5fdc\u7b54\u30b3\u30fc\u30c9\u3092\u4f7f\u7528\u3057\u3066\u3053\u306e\u554f\u984c\u306e\u539f\u56e0\u3092\u7279\u5b9a\u3057\u3001\u89e3\u6c7a\u3057\u3066\u3001\u64cd\u4f5c\u3092\u518d\u5b9f\u884c\u3057\u3066\u304f\u3060\u3055\u3044\u3002 + +filetransfer.download.file=CWWKX7956I: \u30d5\u30a1\u30a4\u30eb {0} \u306e\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u8981\u6c42\u304c\u6b63\u5e38\u306b\u884c\u308f\u308c\u3001\u63a5\u7d9a {2} \u3092\u4f7f\u7528\u3057\u3066\u305d\u306e\u5185\u5bb9\u304c\u30d5\u30a1\u30a4\u30eb {1} \u306b\u66f8\u304d\u8fbc\u307e\u308c\u307e\u3057\u305f\u3002 +filetransfer.download.file.explanation=\u793a\u3055\u308c\u305f\u30d5\u30a1\u30a4\u30eb\u306e\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u8981\u6c42\u304c\u6b63\u5e38\u306b\u884c\u308f\u308c\u307e\u3057\u305f\u3002 +filetransfer.download.file.useraction=\u3053\u308c\u306f\u901a\u77e5\u30e1\u30c3\u30bb\u30fc\u30b8\u3067\u3042\u308a\u3001\u51e6\u7f6e\u306f\u4e0d\u8981\u3067\u3059\u3002 + +filetransfer.unsupported.operation=CWWKX7957E: \u64cd\u4f5c {0} \u306f\u3001\u63a5\u7d9a {1} \u3067\u306f\u30d5\u30a1\u30a4\u30eb\u8ee2\u9001\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u306b\u3088\u3063\u3066\u30b5\u30dd\u30fc\u30c8\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002 +filetransfer.unsupported.operation.explanation=\u793a\u3055\u308c\u305f\u64cd\u4f5c\u306f\u3001\u30d5\u30a1\u30a4\u30eb\u8ee2\u9001\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u306b\u3088\u3063\u3066\u30b5\u30dd\u30fc\u30c8\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002 +filetransfer.unsupported.operation.useraction=\u30d5\u30a1\u30a4\u30eb\u8ee2\u9001\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u306b\u3088\u3063\u3066\u30b5\u30dd\u30fc\u30c8\u3055\u308c\u308b\u64cd\u4f5c\u3092\u8981\u6c42\u3057\u3066\u304f\u3060\u3055\u3044\u3002 + +filetransfer.upload.file=CWWKX7958I: \u30d5\u30a1\u30a4\u30eb {0} \u306e\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u8981\u6c42\u304c\u6b63\u5e38\u306b\u884c\u308f\u308c\u3001\u63a5\u7d9a {2} \u3092\u4f7f\u7528\u3057\u3066\u305d\u306e\u5185\u5bb9\u304c\u30d5\u30a1\u30a4\u30eb {1} \u306b\u66f8\u304d\u8fbc\u307e\u308c\u307e\u3057\u305f\u3002 +filetransfer.upload.file.explanation=\u793a\u3055\u308c\u305f\u30d5\u30a1\u30a4\u30eb\u306e\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u8981\u6c42\u304c\u6b63\u5e38\u306b\u884c\u308f\u308c\u307e\u3057\u305f\u3002 +filetransfer.upload.file.useraction=\u3053\u308c\u306f\u901a\u77e5\u30e1\u30c3\u30bb\u30fc\u30b8\u3067\u3042\u308a\u3001\u51e6\u7f6e\u306f\u4e0d\u8981\u3067\u3059\u3002 + +filetransfer.delete.file=CWWKX7959I: \u30d5\u30a1\u30a4\u30eb {0} \u306e\u524a\u9664\u8981\u6c42\u304c\u3001\u63a5\u7d9a {1} \u3092\u4f7f\u7528\u3057\u3066\u6b63\u5e38\u306b\u884c\u308f\u308c\u307e\u3057\u305f\u3002 +filetransfer.delete.file.explanation=\u793a\u3055\u308c\u305f\u30d5\u30a1\u30a4\u30eb\u306e\u524a\u9664\u8981\u6c42\u304c\u6b63\u5e38\u306b\u884c\u308f\u308c\u307e\u3057\u305f\u3002 +filetransfer.delete.file.useraction=\u3053\u308c\u306f\u901a\u77e5\u30e1\u30c3\u30bb\u30fc\u30b8\u3067\u3042\u308a\u3001\u51e6\u7f6e\u306f\u4e0d\u8981\u3067\u3059\u3002 + +filetransfer.delete.all=CWWKX7960I: \u30b3\u30ec\u30af\u30b7\u30e7\u30f3 {0} \u304b\u3089\u306e\u3059\u3079\u3066\u306e\u30d5\u30a1\u30a4\u30eb\u304a\u3088\u3073\u30d5\u30a9\u30eb\u30c0\u30fc\u306e\u524a\u9664\u8981\u6c42\u304c\u3001\u63a5\u7d9a {1} \u3092\u4f7f\u7528\u3057\u3066\u6b63\u5e38\u306b\u884c\u308f\u308c\u307e\u3057\u305f\u3002 +filetransfer.delete.all.explanation=\u793a\u3055\u308c\u305f\u30b3\u30ec\u30af\u30b7\u30e7\u30f3\u306e\u524a\u9664\u8981\u6c42\u304c\u6b63\u5e38\u306b\u884c\u308f\u308c\u307e\u3057\u305f\u3002 +filetransfer.delete.all.useraction=\u3053\u308c\u306f\u901a\u77e5\u30e1\u30c3\u30bb\u30fc\u30b8\u3067\u3042\u308a\u3001\u51e6\u7f6e\u306f\u4e0d\u8981\u3067\u3059\u3002 diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_ko.nlsprops b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_ko.nlsprops new file mode 100755 index 00000000000..32f9315d626 --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_ko.nlsprops @@ -0,0 +1,55 @@ +# IBM Confidential OCO Source Material +# (C) COPYRIGHT International Business Machines Corp. 2011, 2014. +# The source code for this program is not published or otherwise divested +# of its trade secrets, irrespective of what has been deposited with the +# U.S. Copyright Office. +# ------------------------------------------------------------------------------------------------- +#CMVCPATHNAME com.ibm.ws.jmx.connector.client/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages.nlsprops +#COMPONENTPREFIX CWWKX +#COMPONENTNAMEFOR WebSphere Management File Transfer Client +#ISMESSAGEFILE TRUE +#NLS_MESSAGEFORMAT_VAR +#NLS_ENCODING=UNICODE +# ------------------------------------------------------------------------------------------------- + +# Message prefix block: CWWKX7951 - CWWKX7999 + +filetransfer.client.init=CWWKX7951I: \uc0c8 \ud30c\uc77c \uc804\uc1a1 \ud074\ub77c\uc774\uc5b8\ud2b8\uac00 \uc5f0\uacb0 ID {0}\uacfc(\uc640) \uc5f0\uacb0\ub418\uc5c8\uc2b5\ub2c8\ub2e4. +filetransfer.client.init.explanation=\uc0c8 \ud30c\uc77c \uc804\uc1a1 \ud074\ub77c\uc774\uc5b8\ud2b8\uac00 \uc9c0\uc815\ub41c \uc5f0\uacb0 ID\uc640 \uc5f0\uacb0\ub418\uc5c8\uc2b5\ub2c8\ub2e4. +filetransfer.client.init.useraction=\uc774\uac83\uc740 \uc815\ubcf4 \uba54\uc2dc\uc9c0\uc774\ubbc0\ub85c \uc870\uce58\uac00 \ud544\uc694\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. + +filetransfer.client.error=CWWKX7952E: \uc5f0\uacb0 {1}\uc5d0 \ub300\ud55c \ud074\ub77c\uc774\uc5b8\ud2b8\uce21 \uc624\ub958 \uba54\uc2dc\uc9c0 "{0}"\uc774(\uac00) \ubc1c\uc0dd\ud588\uc2b5\ub2c8\ub2e4. +filetransfer.client.error.explanation=JMX REST \ucee4\ub125\ud130\uc758 \ud074\ub77c\uc774\uc5b8\ud2b8\uce21\uc5d0\uc11c \uc624\ub958\uac00 \ubc1c\uc0dd\ud588\uc73c\uba70 \uc9c0\uc815\ub41c \uba54\uc2dc\uc9c0\uac00 \uc0dd\uc131\ub418\uc5c8\uc2b5\ub2c8\ub2e4. +filetransfer.client.error.useraction=\uc0dd\uc131\ub41c \uc624\ub958 \uba54\uc2dc\uc9c0\ub97c \uc0ac\uc6a9\ud558\uc5ec \uc774 \uc624\ub958\uc758 \uc6d0\uc778\uc774 \ub418\ub294 \ubb38\uc81c\ub97c \uc2dd\ubcc4\ud558\uace0 \uc815\uc815\ud55c \ud6c4 \uc870\uc791\uc744 \ub2e4\uc2dc \uc2e4\ud589\ud569\ub2c8\ub2e4. + +filetransfer.server.error=CWWKX7953E: \uc5f0\uacb0 {1}\uc5d0 \ub300\ud55c \uc11c\ubc84\uce21 \uc624\ub958 \uba54\uc2dc\uc9c0 "{0}"\uc774(\uac00) \ubc1c\uc0dd\ud588\uc2b5\ub2c8\ub2e4. +filetransfer.server.error.explanation=JMX REST \ucee4\ub125\ud130\uc758 \uc11c\ubc84\uce21\uc5d0 \uc624\ub958\uac00 \ubc1c\uc0dd\ud588\uc73c\uba70 \uc9c0\uc815\ub41c \uba54\uc2dc\uc9c0\uac00 \ud45c\uc2dc\ub429\ub2c8\ub2e4. +filetransfer.server.error.useraction=\uc0dd\uc131\ub41c \uc624\ub958 \uba54\uc2dc\uc9c0\ub97c \uc0ac\uc6a9\ud558\uc5ec \uc774 \uc624\ub958\uc758 \uc6d0\uc778\uc774 \ub418\ub294 \ubb38\uc81c\ub97c \uc2dd\ubcc4\ud558\uace0 \uc815\uc815\ud55c \ud6c4 \uc870\uc791\uc744 \ub2e4\uc2dc \uc2e4\ud589\ud569\ub2c8\ub2e4. + +filetransfer.client.bad.credentials=CWWKX7954E: \uc9c0\uc815\ub41c \uc0ac\uc6a9\uc790 \uc774\ub984\uc774\ub098 \ube44\ubc00\ubc88\ud638\uac00 \uc778\uc99d\ub418\uc9c0 \uc54a\uc558\uc2b5\ub2c8\ub2e4. \uc11c\ubc84\uac00 {2} \uc5f0\uacb0\uc5d0 \ub300\ud574 {0} \ucf54\ub4dc \ubc0f "{1}" \uba54\uc2dc\uc9c0\ub85c \uc751\ub2f5\ud569\ub2c8\ub2e4. +filetransfer.client.bad.credentials.explanation=\uc5f0\uacb0\uc744 \uc5bb\uc744 \ub54c \uc81c\uacf5\ub41c \uc2e0\uc784 \uc815\ubcf4\uac00 \uc62c\ubc14\ub974\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. \uc0ac\uc6a9\uc790\uac00 \uc5c6\uac70\ub098 \uc11c\ubc84\uc5d0 \uc561\uc138\uc2a4\ud560 \uad8c\ud55c\uc774 \uc5c6\uc2b5\ub2c8\ub2e4. \ub610\ub294 \ube44\ubc00\ubc88\ud638\uac00 \uc62c\ubc14\ub974\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. +filetransfer.client.bad.credentials.useraction=\uc0ac\uc6a9\uc790 \uc774\ub984 \ub610\ub294 \ube44\ubc00\ubc88\ud638\ub97c \uc815\uc815\ud55c \ub2e4\uc74c \uc0c8 \uc5f0\uacb0\uc744 \uc5bb\uc73c\uc2ed\uc2dc\uc624. + +filetransfer.response.code.error=CWWKX7955E: \ud30c\uc77c \uc804\uc1a1 \ud074\ub77c\uc774\uc5b8\ud2b8\uac00 {2} \uc5f0\uacb0\uc5d0 \ub300\ud574 "{1}" \uba54\uc2dc\uc9c0\uc640 \ud568\uaed8 {0} \uc751\ub2f5 \ucf54\ub4dc\ub97c \uc218\uc2e0\ud588\uc2b5\ub2c8\ub2e4. +filetransfer.response.code.error.explanation=\ud30c\uc77c \uc804\uc1a1 \ud074\ub77c\uc774\uc5b8\ud2b8\uac00 \uc11c\ubc84\uc5d0\uc11c \uc608\uc0c1\uce58 \uc54a\uc740 \uc751\ub2f5 \ucf54\ub4dc\ub97c \uc218\uc2e0\ud588\uc2b5\ub2c8\ub2e4. +filetransfer.response.code.error.useraction=\ud074\ub77c\uc774\uc5b8\ud2b8 \uc751\ub2f5 \ucf54\ub4dc\ub97c \uc0ac\uc6a9\ud558\uc5ec \uc774 \ubb38\uc81c\uc758 \uc6d0\uc778\uc744 \uc2dd\ubcc4\ud558\uace0 \ud574\uacb0\ud55c \ub2e4\uc74c \uc870\uc791\uc744 \ub2e4\uc2dc \uc2e4\ud589\ud569\ub2c8\ub2e4. + +filetransfer.download.file=CWWKX7956I: {0} \ud30c\uc77c \ub2e4\uc6b4\ub85c\ub4dc \uc694\uccad\uc774 \uc644\ub8cc\ub418\uc5c8\uc73c\uba70 {2} \uc5f0\uacb0\uc744 \uc0ac\uc6a9\ud558\uc5ec \ud574\ub2f9 \ucee8\ud150\uce20\uac00 {1} \ud30c\uc77c\uc5d0 \uc791\uc131\ub418\uc5c8\uc2b5\ub2c8\ub2e4. +filetransfer.download.file.explanation=\uc9c0\uc815\ub41c \ud30c\uc77c\uc758 \ub2e4\uc6b4\ub85c\ub4dc \uc694\uccad\uc774 \uc644\ub8cc\ub418\uc5c8\uc2b5\ub2c8\ub2e4. +filetransfer.download.file.useraction=\uc774\uac83\uc740 \uc815\ubcf4 \uba54\uc2dc\uc9c0\uc774\ubbc0\ub85c \uc870\uce58\uac00 \ud544\uc694\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. + +filetransfer.unsupported.operation=CWWKX7957E: {1} \uc5f0\uacb0\uc5d0 \uc0ac\uc6a9\ud558\ub294 \ud30c\uc77c \uc804\uc1a1 \ud074\ub77c\uc774\uc5b8\ud2b8\uc5d0\uc11c ''{0}'' \uc870\uc791\uc774 \uc9c0\uc6d0\ub418\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. +filetransfer.unsupported.operation.explanation=\ud30c\uc77c \uc804\uc1a1 \ud074\ub77c\uc774\uc5b8\ud2b8\uc5d0\uc11c \uc9c0\uc815\ub41c \uc870\uc791\uc774 \uc9c0\uc6d0\ub418\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. +filetransfer.unsupported.operation.useraction=\ud30c\uc77c \uc804\uc1a1 \ud074\ub77c\uc774\uc5b8\ud2b8\uc5d0\uc11c \uc9c0\uc6d0\ub418\ub294 \uc870\uc791\uc744 \uc694\uccad\ud558\uc2ed\uc2dc\uc624. + +filetransfer.upload.file=CWWKX7958I: {0} \ud30c\uc77c \uc5c5\ub85c\ub4dc \uc694\uccad\uc774 \uc644\ub8cc\ub418\uc5c8\uc73c\uba70 {2} \uc5f0\uacb0\uc744 \uc0ac\uc6a9\ud558\uc5ec \ud574\ub2f9 \ucee8\ud150\uce20\uac00 {1} \ud30c\uc77c\uc5d0 \uc791\uc131\ub418\uc5c8\uc2b5\ub2c8\ub2e4. +filetransfer.upload.file.explanation=\uc9c0\uc815\ub41c \ud30c\uc77c\uc758 \uc5c5\ub85c\ub4dc \uc694\uccad\uc774 \uc644\ub8cc\ub418\uc5c8\uc2b5\ub2c8\ub2e4. +filetransfer.upload.file.useraction=\uc774\uac83\uc740 \uc815\ubcf4 \uba54\uc2dc\uc9c0\uc774\ubbc0\ub85c \uc870\uce58\uac00 \ud544\uc694\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. + +filetransfer.delete.file=CWWKX7959I: {0} \ud30c\uc77c \uc0ad\uc81c \uc694\uccad\uc774 {1} \uc5f0\uacb0\uc744 \uc0ac\uc6a9\ud558\uc5ec \uc644\ub8cc\ub418\uc5c8\uc2b5\ub2c8\ub2e4. +filetransfer.delete.file.explanation=\uc9c0\uc815\ub41c \ud30c\uc77c\uc758 \uc0ad\uc81c \uc694\uccad\uc774 \uc644\ub8cc\ub418\uc5c8\uc2b5\ub2c8\ub2e4. +filetransfer.delete.file.useraction=\uc774\uac83\uc740 \uc815\ubcf4 \uba54\uc2dc\uc9c0\uc774\ubbc0\ub85c \uc870\uce58\uac00 \ud544\uc694\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. + +filetransfer.delete.all=CWWKX7960I: {0} \ucf5c\ub809\uc158\uc5d0\uc11c \ubaa8\ub4e0 \ud30c\uc77c\uacfc \ud3f4\ub354\ub97c \uc0ad\uc81c\ud558\ub294 \uc694\uccad\uc774 {1} \uc5f0\uacb0\uc744 \uc0ac\uc6a9\ud558\uc5ec \uc815\uc0c1\uc801\uc73c\ub85c \uc644\ub8cc\ub418\uc5c8\uc2b5\ub2c8\ub2e4. +filetransfer.delete.all.explanation=\uc9c0\uc815\ub41c \ucf5c\ub809\uc158\uc5d0 \ub300\ud55c \uc0ad\uc81c \uc694\uccad\uc774 \uc644\ub8cc\ub418\uc5c8\uc2b5\ub2c8\ub2e4. +filetransfer.delete.all.useraction=\uc774\uac83\uc740 \uc815\ubcf4 \uba54\uc2dc\uc9c0\uc774\ubbc0\ub85c \uc870\uce58\uac00 \ud544\uc694\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_pl.nlsprops b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_pl.nlsprops new file mode 100755 index 00000000000..77bb0becdc9 --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_pl.nlsprops @@ -0,0 +1,55 @@ +# IBM Confidential OCO Source Material +# (C) COPYRIGHT International Business Machines Corp. 2011, 2014. +# The source code for this program is not published or otherwise divested +# of its trade secrets, irrespective of what has been deposited with the +# U.S. Copyright Office. +# ------------------------------------------------------------------------------------------------- +#CMVCPATHNAME com.ibm.ws.jmx.connector.client/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages.nlsprops +#COMPONENTPREFIX CWWKX +#COMPONENTNAMEFOR WebSphere Management File Transfer Client +#ISMESSAGEFILE TRUE +#NLS_MESSAGEFORMAT_VAR +#NLS_ENCODING=UNICODE +# ------------------------------------------------------------------------------------------------- + +# Message prefix block: CWWKX7951 - CWWKX7999 + +filetransfer.client.init=CWWKX7951I: Nowy klient przesy\u0142ania plik\u00f3w nawi\u0105za\u0142 po\u0142\u0105czenie o identyfikatorze {0}. +filetransfer.client.init.explanation=Nowy klient przesy\u0142ania plik\u00f3w nawi\u0105za\u0142 po\u0142\u0105czenie o okre\u015blonym identyfikatorze. +filetransfer.client.init.useraction=To jest komunikat informacyjny i nie jest wymagana \u017cadna czynno\u015b\u0107. + +filetransfer.client.error=CWWKX7952E: Wyst\u0105pi\u0142 komunikat o b\u0142\u0119dzie po stronie klienta {0} dla po\u0142\u0105czenia {1}. +filetransfer.client.error.explanation=Konektor JMX REST po stronie klienta napotka\u0142 b\u0142\u0105d i zosta\u0142 wygenerowany okre\u015blony komunikat. +filetransfer.client.error.useraction=U\u017cyj wygenerowanego komunikatu o b\u0142\u0119dzie, aby zidenytfikowa\u0107 i rozwi\u0105za\u0107 problem spowodowany b\u0142\u0119dem, a nast\u0119pnie uruchom ponownie operacj\u0119. + +filetransfer.server.error=CWWKX7953E: Wyst\u0105pi\u0142 komunikat o b\u0142\u0119dzie po stronie serwera ({0}) dla po\u0142\u0105czenia {1}. +filetransfer.server.error.explanation=Konektor JMX REST po stronie serwera napotka\u0142 b\u0142\u0105d i wygenerowa\u0142 podany komunikat. +filetransfer.server.error.useraction=U\u017cyj wygenerowanego komunikatu o b\u0142\u0119dzie, aby zidenytfikowa\u0107 i rozwi\u0105za\u0107 problem spowodowany b\u0142\u0119dem, a nast\u0119pnie uruchom ponownie operacj\u0119. + +filetransfer.client.bad.credentials=CWWKX7954E: Podana nazwa u\u017cytkownika lub has\u0142o nie zosta\u0142y autoryzowane. Serwer zwr\u00f3ci\u0142 kod {0} i komunikat \u201e{1}\u201d dla po\u0142\u0105czenia {2}. +filetransfer.client.bad.credentials.explanation=Referencje podane podczas nawi\u0105zywania po\u0142\u0105czenia s\u0105 niepoprawne. Prawdopodobnie u\u017cytkownik nie istnieje, nie ma uprawnie\u0144 niezb\u0119dnych do uzyskania dost\u0119pu do serwera lub has\u0142o jest niepoprawne. +filetransfer.client.bad.credentials.useraction=Popraw nazw\u0119 u\u017cytkownika lub has\u0142o, a nast\u0119pnie nawi\u0105\u017c nowe po\u0142\u0105czenie. + +filetransfer.response.code.error=CWWKX7955E: Klient przesy\u0142ania plik\u00f3w odebra\u0142 kod odpowiedzi {0} z komunikatem \u201e{1}\u201d dla po\u0142\u0105czenia {2}. +filetransfer.response.code.error.explanation=Klient przesy\u0142ania plik\u00f3w odebra\u0142 nieoczekiwany kod odpowiedzi z serwera. +filetransfer.response.code.error.useraction=U\u017cyj kodu odpowiedzi klienta, aby zidentyfikowa\u0107 i usun\u0105\u0107 przyczyn\u0119 problemu, a nast\u0119pnie uruchom ponownie operacj\u0119. + +filetransfer.download.file=CWWKX7956I: \u017b\u0105danie pobrania pliku {0} zosta\u0142o wykonane pomy\u015blnie, a jego zawarto\u015b\u0107 zosta\u0142a zapisana w pliku {1} przy u\u017cyciu po\u0142\u0105czenia {2}. +filetransfer.download.file.explanation=\u017b\u0105danie pobrania podanego pliku zako\u0144czy\u0142o si\u0119 powodzeniem. +filetransfer.download.file.useraction=To jest komunikat informacyjny i nie jest wymagana \u017cadna czynno\u015b\u0107. + +filetransfer.unsupported.operation=CWWKX7957E: Operacja {0} nie jest obs\u0142ugiwana przez klient przesy\u0142ania plik\u00f3w dla po\u0142\u0105czenia {1}. +filetransfer.unsupported.operation.explanation=Okre\u015blona operacja nie jest obs\u0142ugiwana przez klient przesy\u0142ania plik\u00f3w. +filetransfer.unsupported.operation.useraction=Za\u017c\u0105daj operacji, kt\u00f3ra jest obs\u0142ugiwana przez klient przesy\u0142ania plik\u00f3w. + +filetransfer.upload.file=CWWKX7958I: \u017b\u0105danie przes\u0142ania pliku {0} zosta\u0142o wykonane pomy\u015blnie, a jego zawarto\u015b\u0107 zosta\u0142a zapisana w pliku {1} przy u\u017cyciu po\u0142\u0105czenia {2}. +filetransfer.upload.file.explanation=\u017b\u0105danie przes\u0142ania podanego pliku zako\u0144czy\u0142o si\u0119 powodzeniem. +filetransfer.upload.file.useraction=To jest komunikat informacyjny i nie jest wymagana \u017cadna czynno\u015b\u0107. + +filetransfer.delete.file=CWWKX7959I: \u017b\u0105danie usuni\u0119cia pliku {0} zosta\u0142o wykonane pomy\u015blnie przy u\u017cyciu po\u0142\u0105czenia {1}. +filetransfer.delete.file.explanation=\u017b\u0105danie usuni\u0119cia podanego pliku zako\u0144czy\u0142o si\u0119 powodzeniem. +filetransfer.delete.file.useraction=To jest komunikat informacyjny i nie jest wymagana \u017cadna czynno\u015b\u0107. + +filetransfer.delete.all=CWWKX7960I: \u017b\u0105danie usuni\u0119cia wszystkich plik\u00f3w i folder\u00f3w z kolekcji {0} zosta\u0142o wykonane pomy\u015blnie przy u\u017cyciu po\u0142\u0105czenia {1}. +filetransfer.delete.all.explanation=\u017b\u0105danie usuni\u0119cia podanej kolekcji zako\u0144czy\u0142o si\u0119 powodzeniem. +filetransfer.delete.all.useraction=To jest komunikat informacyjny i nie jest wymagana \u017cadna czynno\u015b\u0107. diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_pt_BR.nlsprops b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_pt_BR.nlsprops new file mode 100755 index 00000000000..09725d28561 --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_pt_BR.nlsprops @@ -0,0 +1,55 @@ +# IBM Confidential OCO Source Material +# (C) COPYRIGHT International Business Machines Corp. 2011, 2014. +# The source code for this program is not published or otherwise divested +# of its trade secrets, irrespective of what has been deposited with the +# U.S. Copyright Office. +# ------------------------------------------------------------------------------------------------- +#CMVCPATHNAME com.ibm.ws.jmx.connector.client/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages.nlsprops +#COMPONENTPREFIX CWWKX +#COMPONENTNAMEFOR WebSphere Management File Transfer Client +#ISMESSAGEFILE TRUE +#NLS_MESSAGEFORMAT_VAR +#NLS_ENCODING=UNICODE +# ------------------------------------------------------------------------------------------------- + +# Message prefix block: CWWKX7951 - CWWKX7999 + +filetransfer.client.init=CWWKX7951I: Um novo cliente de transfer\u00eancia de arquivos conectou-se ao identificador de conex\u00e3o {0}. +filetransfer.client.init.explanation=Um novo cliente de transfer\u00eancia de arquivos conectou-se ao identificador de conex\u00e3o especificado. +filetransfer.client.init.useraction=Esta \u00e9 uma mensagem informativa e nenhuma a\u00e7\u00e3o ser\u00e1 necess\u00e1ria. + +filetransfer.client.error=CWWKX7952E: Ocorreu uma mensagem de erro "{0}" do lado do cliente para a conex\u00e3o {1}. +filetransfer.client.error.explanation=O lado do cliente do conector JMX REST encontrou um erro e a mensagem especificada foi gerada. +filetransfer.client.error.useraction=Use a mensagem de erro gerada para identificar e corrigir o problema que causou esse erro e execute novamente a opera\u00e7\u00e3o. + +filetransfer.server.error=CWWKX7953E: Ocorreu uma mensagem de erro "{0}" do lado do servidor para a conex\u00e3o {1}. +filetransfer.server.error.explanation=O lado do servidor do conector JMX REST encontrou um erro e gerou a mensagem especificada. +filetransfer.server.error.useraction=Use a mensagem de erro gerada para identificar e corrigir o problema que causou esse erro e execute novamente a opera\u00e7\u00e3o. + +filetransfer.client.bad.credentials=CWWKX7954E: O nome de usu\u00e1rio ou a senha especificados n\u00e3o est\u00e3o autorizados. O servidor respondeu com o c\u00f3digo {0} e a mensagem "{1}" para a conex\u00e3o {2}. +filetransfer.client.bad.credentials.explanation=As credenciais fornecidas ao obter a conex\u00e3o s\u00e3o incorretas. O usu\u00e1rio pode n\u00e3o existir, n\u00e3o ter autoridade para acessar o servidor, ou a senha pode ser incorreta. +filetransfer.client.bad.credentials.useraction=Corrija o nome de usu\u00e1rio ou a senha e, em seguida, obtenha uma nova conex\u00e3o. + +filetransfer.response.code.error=CWWKX7955E: O cliente de transfer\u00eancia de arquivos recebeu o c\u00f3digo de resposta {0} com a mensagem "{1}" para a conex\u00e3o {2}. +filetransfer.response.code.error.explanation=O cliente de transfer\u00eancia de arquivos recebeu um c\u00f3digo de resposta inesperado do servidor. +filetransfer.response.code.error.useraction=Use o c\u00f3digo de resposta do cliente para identificar e resolver a causa desse problema e execute novamente a opera\u00e7\u00e3o. + +filetransfer.download.file=CWWKX7956I: A solicita\u00e7\u00e3o para fazer o download do arquivo {0} foi bem-sucedida e seu conte\u00fado foi gravado no arquivo {1} usando a conex\u00e3o {2}. +filetransfer.download.file.explanation=A solicita\u00e7\u00e3o de download do arquivo especificado obteve \u00eaxito. +filetransfer.download.file.useraction=Esta \u00e9 uma mensagem informativa e nenhuma a\u00e7\u00e3o ser\u00e1 necess\u00e1ria. + +filetransfer.unsupported.operation=CWWKX7957E: A opera\u00e7\u00e3o {0} n\u00e3o \u00e9 suportada pelo cliente de transfer\u00eancia de arquivos para a conex\u00e3o {1}. +filetransfer.unsupported.operation.explanation=A opera\u00e7\u00e3o especificada n\u00e3o \u00e9 suportada pelo cliente de transfer\u00eancia de arquivos. +filetransfer.unsupported.operation.useraction=Solicite uma opera\u00e7\u00e3o que seja suportada pelo cliente de transfer\u00eancia de arquivos. + +filetransfer.upload.file=CWWKX7958I: A solicita\u00e7\u00e3o para fazer o upload do arquivo {0} foi bem-sucedida e seu conte\u00fado foi gravado no arquivo {1} usando a conex\u00e3o {2}. +filetransfer.upload.file.explanation=A solicita\u00e7\u00e3o de upload do arquivo especificado obteve \u00eaxito. +filetransfer.upload.file.useraction=Esta \u00e9 uma mensagem informativa e nenhuma a\u00e7\u00e3o ser\u00e1 necess\u00e1ria. + +filetransfer.delete.file=CWWKX7959I: A solicita\u00e7\u00e3o para excluir o arquivo {0} foi bem-sucedida usando a conex\u00e3o {1}. +filetransfer.delete.file.explanation=A solicita\u00e7\u00e3o de exclus\u00e3o do arquivo especificado obteve \u00eaxito. +filetransfer.delete.file.useraction=Esta \u00e9 uma mensagem informativa e nenhuma a\u00e7\u00e3o ser\u00e1 necess\u00e1ria. + +filetransfer.delete.all=CWWKX7960I: A solicita\u00e7\u00e3o para excluir todos os arquivos e pastas da cole\u00e7\u00e3o {0} foi bem-sucedida usando a conex\u00e3o {1}. +filetransfer.delete.all.explanation=A solicita\u00e7\u00e3o de exclus\u00e3o da cole\u00e7\u00e3o especificada foi bem-sucedida. +filetransfer.delete.all.useraction=Esta \u00e9 uma mensagem informativa e nenhuma a\u00e7\u00e3o ser\u00e1 necess\u00e1ria. diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_ro.nlsprops b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_ro.nlsprops new file mode 100755 index 00000000000..db396c86498 --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_ro.nlsprops @@ -0,0 +1,55 @@ +# IBM Confidential OCO Source Material +# (C) COPYRIGHT International Business Machines Corp. 2011, 2014. +# The source code for this program is not published or otherwise divested +# of its trade secrets, irrespective of what has been deposited with the +# U.S. Copyright Office. +# ------------------------------------------------------------------------------------------------- +#CMVCPATHNAME com.ibm.ws.jmx.connector.client/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages.nlsprops +#COMPONENTPREFIX CWWKX +#COMPONENTNAMEFOR WebSphere Management File Transfer Client +#ISMESSAGEFILE TRUE +#NLS_MESSAGEFORMAT_VAR +#NLS_ENCODING=UNICODE +# ------------------------------------------------------------------------------------------------- + +# Message prefix block: CWWKX7951 - CWWKX7999 + +filetransfer.client.init=CWWKX7951I: Un nou client de transfer de fi\u015fiere s-a conectat cu identificatorul de conexiune {0}. +filetransfer.client.init.explanation=Un nou client de transfer de fi\u015fiere s-a conectat cu identificatorul de conexiune specificat. +filetransfer.client.init.useraction=Acesta este un mesaj informa\u0163ional \u015fi nu este necesar\u0103 nici o ac\u0163iune. + +filetransfer.client.error=CWWKX7952E: A ap\u0103rut un mesaj de eroare pe partea de client "{0}" pentru conexiunea {1}. +filetransfer.client.error.explanation=Partea de client a conectorului JMX REST a \u00eent\u00e2lnit o eroare \u015fi s-a generat mesajul specificat. +filetransfer.client.error.useraction=Folosi\u0163i mesajul de eroare generat pentru a identifica \u015fi a corecta problema care a cauzat eroarea, apoi rula\u0163i din nou opera\u0163ia. + +filetransfer.server.error=CWWKX7953E: A ap\u0103rut un mesaj de eroare pe partea de server "{0}" pentru conexiunea {1}. +filetransfer.server.error.explanation=Partea de server a conectorului JMX REST a \u00eent\u00e2lnit o eroare \u015fi s-a generat mesajul specificat. +filetransfer.server.error.useraction=Folosi\u0163i mesajul de eroare generat pentru a identifica \u015fi a corecta problema care a cauzat eroarea, apoi rula\u0163i din nou opera\u0163ia. + +filetransfer.client.bad.credentials=CWWKX7954E: Numele de utilizator sau parola specificat(\u0103) nu este autorizat(\u0103). Serverul a r\u0103spuns cu codul {0} \u015fi mesajul "{1}" pentru conexiunea {2}. +filetransfer.client.bad.credentials.explanation=Acredit\u0103rile furnizate la ob\u0163inerea conexiunii sunt incorecte. Utilizatorul s-ar putea s\u0103 nu existe, s-ar putea s\u0103 nu aib\u0103 autoriza\u0163ia de accesare a serverului sau parola ar putea fi incorect\u0103. +filetransfer.client.bad.credentials.useraction=Corecta\u0163i numele utilizator sau parola, apoi ob\u0163ine\u0163i o nou\u0103 conexiune. + +filetransfer.response.code.error=CWWKX7955E: Clientul de transfer de fi\u015fiere a primi codul de r\u0103spuns {0} cu mesajul "{1}" pentru conexiunea {2}. +filetransfer.response.code.error.explanation=Clientul de transfer de fi\u015fiere a primit un cod de r\u0103spuns nea\u015fteptat de la server. +filetransfer.response.code.error.useraction=Folosi\u0163i codul de r\u0103spuns client pentru a identifica \u015fi a rezolva cauza acestei probleme, apoi rula\u0163i din nou opera\u0163ia. + +filetransfer.download.file=CWWKX7956I: Cererea de desc\u0103rcare a fi\u015fierului {0} a avt succes \u015fi con\u0163inutul s\u0103u a fost scris \u00een fi\u015fierul {1} folosind conexiunea {2}. +filetransfer.download.file.explanation=Cererea de desc\u0103rcare a fi\u015fierului specificat a avut succes. +filetransfer.download.file.useraction=Acesta este un mesaj informa\u0163ional \u015fi nu este necesar\u0103 nici o ac\u0163iune. + +filetransfer.unsupported.operation=CWWKX7957E: Opera\u0163ia {0} nu este suportat\u0103 de clientul de transfer de fi\u015fiere pentru conexiunea {1}. +filetransfer.unsupported.operation.explanation=Opera\u0163ia specificat\u0103 nu este suportat\u0103 de clientul de transfer de fi\u015fiere. +filetransfer.unsupported.operation.useraction=Cere\u0163i o opera\u0163ie care este suportat\u0103 de clientul de transfer de fi\u015fiere. + +filetransfer.upload.file=CWWKX7958I: Cererea de \u00eenc\u0103rcare a fi\u015fierului {0} a avut succes \u015fi con\u0163inutul s\u0103u a fost scris \u00een fi\u015fierul {1} folosind conexiunea {2}. +filetransfer.upload.file.explanation=Cererea de \u00eenc\u0103rcare a fi\u015fierului specificat a avut succes. +filetransfer.upload.file.useraction=Acesta este un mesaj informa\u0163ional \u015fi nu este necesar\u0103 nici o ac\u0163iune. + +filetransfer.delete.file=CWWKX7959I: Cererea de \u015ftergere a fi\u015fierului {0} a avut succes folosind conexiunea {1}. +filetransfer.delete.file.explanation=Cererea de \u015ftergere a fi\u015fierului specificat a avut succes. +filetransfer.delete.file.useraction=Acesta este un mesaj informa\u0163ional \u015fi nu este necesar\u0103 nici o ac\u0163iune. + +filetransfer.delete.all=CWWKX7960I: Cererea de \u015ftergere a tuturor fi\u015fierelor \u015fi folderelor din colec\u0163ia {0} a reu\u015fit prin utilizarea conexiunii {1}. +filetransfer.delete.all.explanation=Cererea de \u015ftergere a colec\u0163iei specificate a avut succes. +filetransfer.delete.all.useraction=Acesta este un mesaj informa\u0163ional \u015fi nu este necesar\u0103 nici o ac\u0163iune. diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_ru.nlsprops b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_ru.nlsprops new file mode 100755 index 00000000000..6ddbb0cf18e --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_ru.nlsprops @@ -0,0 +1,55 @@ +# IBM Confidential OCO Source Material +# (C) COPYRIGHT International Business Machines Corp. 2011, 2014. +# The source code for this program is not published or otherwise divested +# of its trade secrets, irrespective of what has been deposited with the +# U.S. Copyright Office. +# ------------------------------------------------------------------------------------------------- +#CMVCPATHNAME com.ibm.ws.jmx.connector.client/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages.nlsprops +#COMPONENTPREFIX CWWKX +#COMPONENTNAMEFOR WebSphere Management File Transfer Client +#ISMESSAGEFILE TRUE +#NLS_MESSAGEFORMAT_VAR +#NLS_ENCODING=UNICODE +# ------------------------------------------------------------------------------------------------- + +# Message prefix block: CWWKX7951 - CWWKX7999 + +filetransfer.client.init=CWWKX7951I: \u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043b\u0441\u044f \u043d\u043e\u0432\u044b\u0439 \u043a\u043b\u0438\u0435\u043d\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0444\u0430\u0439\u043b\u043e\u0432 \u0441 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u043c \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f {0}. +filetransfer.client.init.explanation=\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043b\u0441\u044f \u043d\u043e\u0432\u044b\u0439 \u043a\u043b\u0438\u0435\u043d\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0444\u0430\u0439\u043b\u043e\u0432 \u0441 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u043c\u0438 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u043c \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f. +filetransfer.client.init.useraction=\u042d\u0442\u043e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435, \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f. + +filetransfer.client.error=CWWKX7952E: \u041e\u0448\u0438\u0431\u043a\u0430 \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0441 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435\u043c "{0}" \u0434\u043b\u044f \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f {1}. +filetransfer.client.error.explanation=\u041d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u043a\u043e\u043d\u043d\u0435\u043a\u0442\u043e\u0440\u0430 REST JMX \u0432\u043e\u0437\u043d\u0438\u043a\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430, \u0438 \u0432\u044b\u0434\u0430\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435. +filetransfer.client.error.useraction=\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0435 \u043f\u0440\u0438\u0447\u0438\u043d\u0443 \u043d\u0435\u043f\u043e\u043b\u0430\u0434\u043a\u0438 \u043f\u043e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u0432 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0438 \u043e\u0431 \u043e\u0448\u0438\u0431\u043a\u0435, \u0443\u0441\u0442\u0440\u0430\u043d\u0438\u0442\u0435 \u0435\u0435 \u0438 \u043f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044e. + +filetransfer.server.error=CWWKX7953E: \u041e\u0448\u0438\u0431\u043a\u0430 \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0441 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435\u043c "{0}" \u0434\u043b\u044f \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f {1}. +filetransfer.server.error.explanation=\u041d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043a\u043e\u043d\u043d\u0435\u043a\u0442\u043e\u0440\u0430 REST JMX \u0432\u043e\u0437\u043d\u0438\u043a\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430, \u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435. +filetransfer.server.error.useraction=\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0435 \u043f\u0440\u0438\u0447\u0438\u043d\u0443 \u043d\u0435\u043f\u043e\u043b\u0430\u0434\u043a\u0438 \u043f\u043e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u0432 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0438 \u043e\u0431 \u043e\u0448\u0438\u0431\u043a\u0435, \u0443\u0441\u0442\u0440\u0430\u043d\u0438\u0442\u0435 \u0435\u0435 \u0438 \u043f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044e. + +filetransfer.client.bad.credentials=CWWKX7954E: \u0423\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u043c\u0443 \u0438\u043c\u0435\u043d\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438\u043b\u0438 \u043f\u0430\u0440\u043e\u043b\u044e \u043d\u0435 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u044b \u043f\u0440\u0430\u0432\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u0430. \u0421\u0435\u0440\u0432\u0435\u0440 \u0432\u0435\u0440\u043d\u0443\u043b \u043a\u043e\u0434 {0} \u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 "{1}" \u0434\u043b\u044f \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f {2}. +filetransfer.client.bad.credentials.explanation=\u041f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u0431\u044b\u043b\u0438 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d\u044b \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0435 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435. \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442, \u043d\u0435 \u0438\u043c\u0435\u0435\u0442 \u043f\u0440\u0430\u0432 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0443 \u0438\u043b\u0438 \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u043b \u043f\u0430\u0440\u043e\u043b\u044c. +filetransfer.client.bad.credentials.useraction=\u0418\u0441\u043f\u0440\u0430\u0432\u044c\u0442\u0435 \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438\u043b\u0438 \u043f\u0430\u0440\u043e\u043b\u044c \u0438 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u0435\u0449\u0435 \u0440\u0430\u0437 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435. + +filetransfer.response.code.error=CWWKX7955E: \u041a\u043b\u0438\u0435\u043d\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0444\u0430\u0439\u043b\u043e\u0432 \u043f\u043e\u043b\u0443\u0447\u0438\u043b \u043a\u043e\u0434 \u043e\u0442\u0432\u0435\u0442\u0430 {0} \u0441 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435\u043c "{1}" \u0434\u043b\u044f \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f {2}. +filetransfer.response.code.error.explanation=\u041a\u043b\u0438\u0435\u043d\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0444\u0430\u0439\u043b\u043e\u0432 \u043f\u043e\u043b\u0443\u0447\u0438\u043b \u043e\u0442\u0432\u0435\u0442 \u0441 \u043d\u0435\u043f\u0440\u0435\u0434\u0432\u0438\u0434\u0435\u043d\u043d\u044b\u043c \u043a\u043e\u0434\u043e\u043c \u043e\u0442\u0432\u0435\u0442\u0430 \u043e\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0430. +filetransfer.response.code.error.useraction=\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0435 \u043f\u0440\u0438\u0447\u0438\u043d\u0443 \u043d\u0435\u043f\u043e\u043b\u0430\u0434\u043a\u0438 \u043f\u043e \u043a\u043e\u0434\u0443 \u043e\u0442\u0432\u0435\u0442\u0430, \u0443\u0441\u0442\u0440\u0430\u043d\u0438\u0442\u0435 \u0435\u0435 \u0438 \u043f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044e. + +filetransfer.download.file=CWWKX7956I: \u0417\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u0444\u0430\u0439\u043b\u0430 {0} \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d, \u0438 \u0435\u0433\u043e \u0434\u0430\u043d\u043d\u044b\u0435 \u0437\u0430\u043f\u0438\u0441\u0430\u043d\u044b \u0432 \u0444\u0430\u0439\u043b {1} \u0447\u0435\u0440\u0435\u0437 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 {2}. +filetransfer.download.file.explanation=\u0417\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430 \u0431\u044b\u043b \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d \u0443\u0441\u043f\u0435\u0448\u043d\u043e. +filetransfer.download.file.useraction=\u042d\u0442\u043e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435, \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f. + +filetransfer.unsupported.operation=CWWKX7957E: \u041e\u043f\u0435\u0440\u0430\u0446\u0438\u044f {0} \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u043c \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0444\u0430\u0439\u043b\u043e\u0432 \u0434\u043b\u044f \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f {1}. +filetransfer.unsupported.operation.explanation=\u0423\u043a\u0430\u0437\u0430\u043d\u043d\u0430\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u043c \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0444\u0430\u0439\u043b\u043e\u0432. +filetransfer.unsupported.operation.useraction=\u0417\u0430\u043f\u0440\u043e\u0441\u0438\u0442\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u043c \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0444\u0430\u0439\u043b\u043e\u0432. + +filetransfer.upload.file=CWWKX7958I: \u0417\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0432\u044b\u0433\u0440\u0443\u0437\u043a\u0443 \u0444\u0430\u0439\u043b\u0430 {0} \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d, \u0435\u0433\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u0437\u0430\u043f\u0438\u0441\u0430\u043d\u043e \u0432 \u0444\u0430\u0439\u043b {1} \u0447\u0435\u0440\u0435\u0437 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 {2}. +filetransfer.upload.file.explanation=\u0417\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0432\u044b\u0433\u0440\u0443\u0437\u043a\u0443 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430 \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d. +filetransfer.upload.file.useraction=\u042d\u0442\u043e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435, \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f. + +filetransfer.delete.file=CWWKX7959I: \u0417\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u0430 {0} \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d \u0447\u0435\u0440\u0435\u0437 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 {1}. +filetransfer.delete.file.explanation=\u0417\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430 \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d. +filetransfer.delete.file.useraction=\u042d\u0442\u043e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435, \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f. + +filetransfer.delete.all=CWWKX7960I: \u0417\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0432\u0441\u0435\u0445 \u0444\u0430\u0439\u043b\u043e\u0432 \u0438 \u043f\u0430\u043f\u043e\u043a \u0438\u0437 \u043d\u0430\u0431\u043e\u0440\u0430 {0} \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f {1}. +filetransfer.delete.all.explanation=\u0417\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0433\u043e \u043d\u0430\u0431\u043e\u0440\u0430 \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d. +filetransfer.delete.all.useraction=\u042d\u0442\u043e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435, \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f. diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_zh.nlsprops b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_zh.nlsprops new file mode 100755 index 00000000000..6e14a160637 --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_zh.nlsprops @@ -0,0 +1,55 @@ +# IBM Confidential OCO Source Material +# (C) COPYRIGHT International Business Machines Corp. 2011, 2014. +# The source code for this program is not published or otherwise divested +# of its trade secrets, irrespective of what has been deposited with the +# U.S. Copyright Office. +# ------------------------------------------------------------------------------------------------- +#CMVCPATHNAME com.ibm.ws.jmx.connector.client/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages.nlsprops +#COMPONENTPREFIX CWWKX +#COMPONENTNAMEFOR WebSphere Management File Transfer Client +#ISMESSAGEFILE TRUE +#NLS_MESSAGEFORMAT_VAR +#NLS_ENCODING=UNICODE +# ------------------------------------------------------------------------------------------------- + +# Message prefix block: CWWKX7951 - CWWKX7999 + +filetransfer.client.init=CWWKX7951I: \u5df2\u8fde\u63a5\u5176\u8fde\u63a5\u6807\u8bc6\u4e3a {0} \u7684\u65b0\u6587\u4ef6\u4f20\u8f93\u5ba2\u6237\u673a\u3002 +filetransfer.client.init.explanation=\u5df2\u8fde\u63a5\u5e26\u6709\u6307\u5b9a\u8fde\u63a5\u6807\u8bc6\u7684\u65b0\u6587\u4ef6\u4f20\u8f93\u5ba2\u6237\u673a\u3002 +filetransfer.client.init.useraction=\u8fd9\u662f\u4e00\u6761\u53c2\u8003\u6d88\u606f\uff0c\u4e0d\u9700\u8981\u6267\u884c\u4efb\u4f55\u64cd\u4f5c\u3002 + +filetransfer.client.error=CWWKX7952E: \u8fde\u63a5 {1} \u51fa\u73b0\u4e86\u5ba2\u6237\u7aef\u9519\u8bef\u6d88\u606f\u201c{0}\u201d\u3002 +filetransfer.client.error.explanation=JMX REST \u8fde\u63a5\u5668\u7684\u5ba2\u6237\u7aef\u9047\u5230\u4e86\u9519\u8bef\uff0c\u751f\u6210\u4e86\u6307\u5b9a\u6d88\u606f\u3002 +filetransfer.client.error.useraction=\u8bf7\u4f7f\u7528\u751f\u6210\u7684\u9519\u8bef\u6d88\u606f\u6765\u6807\u8bc6\u6b64\u9519\u8bef\uff0c\u66f4\u6b63\u5bfc\u81f4\u6b64\u9519\u8bef\u7684\u95ee\u9898\u5e76\u91cd\u65b0\u8fd0\u884c\u8be5\u64cd\u4f5c\u3002 + +filetransfer.server.error=CWWKX7953E: \u8fde\u63a5 {1} \u51fa\u73b0\u4e86\u670d\u52a1\u5668\u7aef\u9519\u8bef\u6d88\u606f\u201c{0}\u201d\u3002 +filetransfer.server.error.explanation=JMX REST \u8fde\u63a5\u5668\u7684\u670d\u52a1\u5668\u7aef\u9047\u5230\u4e86\u9519\u8bef\uff0c\u5e76\u751f\u6210\u4e86\u6307\u5b9a\u6d88\u606f\u3002 +filetransfer.server.error.useraction=\u8bf7\u4f7f\u7528\u751f\u6210\u7684\u9519\u8bef\u6d88\u606f\u6765\u6807\u8bc6\u6b64\u9519\u8bef\uff0c\u66f4\u6b63\u5bfc\u81f4\u6b64\u9519\u8bef\u7684\u95ee\u9898\u5e76\u91cd\u65b0\u8fd0\u884c\u8be5\u64cd\u4f5c\u3002 + +filetransfer.client.bad.credentials=CWWKX7954E: \u6307\u5b9a\u7684\u7528\u6237\u540d\u6216\u5bc6\u7801\u672a\u88ab\u6388\u6743\u3002\u5bf9\u4e8e\u8fde\u63a5 {2}\uff0c\u670d\u52a1\u5668\u4ee5\u4ee3\u7801 {0} \u548c\u6d88\u606f\u201c{1}\u201d\u4f5c\u4e3a\u54cd\u5e94\u3002 +filetransfer.client.bad.credentials.explanation=\u83b7\u53d6\u8fde\u63a5\u65f6\u63d0\u4f9b\u7684\u51ed\u8bc1\u4e0d\u6b63\u786e\u3002\u7528\u6237\u53ef\u80fd\u4e0d\u5b58\u5728\u6216\u4e0d\u5177\u6709\u8bbf\u95ee\u670d\u52a1\u5668\u7684\u6743\u9650\uff0c\u6216\u8005\u5bc6\u7801\u53ef\u80fd\u4e0d\u6b63\u786e\u3002 +filetransfer.client.bad.credentials.useraction=\u66f4\u6b63\u7528\u6237\u540d\u6216\u5bc6\u7801\uff0c\u7136\u540e\u83b7\u53d6\u4e00\u4e2a\u65b0\u8fde\u63a5\u3002 + +filetransfer.response.code.error=CWWKX7955E: \u5bf9\u4e8e\u8fde\u63a5 {2}\uff0c\u6587\u4ef6\u4f20\u8f93\u5ba2\u6237\u673a\u63a5\u6536\u5230\u5e26\u6709\u6d88\u606f\u201c{1}\u201d\u7684\u54cd\u5e94\u4ee3\u7801 {0}\u3002 +filetransfer.response.code.error.explanation=\u6587\u4ef6\u4f20\u8f93\u5ba2\u6237\u673a\u4ece\u670d\u52a1\u5668\u63a5\u6536\u5230\u610f\u5916\u54cd\u5e94\u4ee3\u7801\u3002 +filetransfer.response.code.error.useraction=\u8bf7\u4f7f\u7528\u5ba2\u6237\u673a\u54cd\u5e94\u4ee3\u7801\u6765\u6807\u8bc6\u6b64\u95ee\u9898\u5e76\u89e3\u51b3\u5bfc\u81f4\u6b64\u95ee\u9898\u7684\u539f\u56e0\uff0c\u7136\u540e\u91cd\u65b0\u8fd0\u884c\u8be5\u64cd\u4f5c\u3002 + +filetransfer.download.file=CWWKX7956I: \u4e0b\u8f7d\u6587\u4ef6 {0} \u7684\u8bf7\u6c42\u5df2\u6210\u529f\uff0c\u5df2\u4f7f\u7528\u8fde\u63a5 {2} \u5c06\u5176\u5185\u5bb9\u5199\u5165\u6587\u4ef6 {1}\u3002 +filetransfer.download.file.explanation=\u6307\u5b9a\u6587\u4ef6\u7684\u4e0b\u8f7d\u8bf7\u6c42\u5df2\u6210\u529f\u3002 +filetransfer.download.file.useraction=\u8fd9\u662f\u4e00\u6761\u53c2\u8003\u6d88\u606f\uff0c\u4e0d\u9700\u8981\u6267\u884c\u4efb\u4f55\u64cd\u4f5c\u3002 + +filetransfer.unsupported.operation=CWWKX7957E: \u5bf9\u4e8e\u8fde\u63a5 {1}\uff0c\u6587\u4ef6\u4f20\u8f93\u5ba2\u6237\u673a\u4e0d\u652f\u6301\u64cd\u4f5c {0}\u3002 +filetransfer.unsupported.operation.explanation=\u6587\u4ef6\u4f20\u8f93\u5ba2\u6237\u673a\u4e0d\u652f\u6301\u6307\u5b9a\u64cd\u4f5c\u3002 +filetransfer.unsupported.operation.useraction=\u8bf7\u8bf7\u6c42\u6587\u4ef6\u4f20\u8f93\u5ba2\u6237\u673a\u652f\u6301\u7684\u64cd\u4f5c\u3002 + +filetransfer.upload.file=CWWKX7958I: \u4e0a\u8f7d\u6587\u4ef6 {0} \u7684\u8bf7\u6c42\u5df2\u6210\u529f\uff0c\u5df2\u4f7f\u7528\u8fde\u63a5 {2} \u5c06\u5176\u5185\u5bb9\u5199\u5165\u6587\u4ef6 {1}\u3002 +filetransfer.upload.file.explanation=\u6307\u5b9a\u6587\u4ef6\u7684\u4e0a\u8f7d\u8bf7\u6c42\u5df2\u6210\u529f\u3002 +filetransfer.upload.file.useraction=\u8fd9\u662f\u4e00\u6761\u53c2\u8003\u6d88\u606f\uff0c\u4e0d\u9700\u8981\u6267\u884c\u4efb\u4f55\u64cd\u4f5c\u3002 + +filetransfer.delete.file=CWWKX7959I: \u5df2\u6210\u529f\u4f7f\u7528\u8fde\u63a5 {1} \u6267\u884c\u5220\u9664\u6587\u4ef6 {0} \u7684\u8bf7\u6c42\u3002 +filetransfer.delete.file.explanation=\u6307\u5b9a\u6587\u4ef6\u7684\u5220\u9664\u8bf7\u6c42\u5df2\u6210\u529f\u3002 +filetransfer.delete.file.useraction=\u8fd9\u662f\u4e00\u6761\u53c2\u8003\u6d88\u606f\uff0c\u4e0d\u9700\u8981\u6267\u884c\u4efb\u4f55\u64cd\u4f5c\u3002 + +filetransfer.delete.all=CWWKX7960I: \u5df2\u6210\u529f\u4f7f\u7528\u8fde\u63a5 {1} \u6267\u884c\u5220\u9664\u96c6\u5408 {0} \u4e2d\u6240\u6709\u6587\u4ef6\u548c\u6587\u4ef6\u5939\u7684\u8bf7\u6c42\u3002 +filetransfer.delete.all.explanation=\u6307\u5b9a\u96c6\u5408\u7684\u5220\u9664\u8bf7\u6c42\u5df2\u6210\u529f\u3002 +filetransfer.delete.all.useraction=\u8fd9\u662f\u4e00\u6761\u53c2\u8003\u6d88\u606f\uff0c\u4e0d\u9700\u8981\u6267\u884c\u4efb\u4f55\u64cd\u4f5c\u3002 diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_zh_TW.nlsprops b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_zh_TW.nlsprops new file mode 100755 index 00000000000..feb4fc13064 --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages_zh_TW.nlsprops @@ -0,0 +1,55 @@ +# IBM Confidential OCO Source Material +# (C) COPYRIGHT International Business Machines Corp. 2011, 2014. +# The source code for this program is not published or otherwise divested +# of its trade secrets, irrespective of what has been deposited with the +# U.S. Copyright Office. +# ------------------------------------------------------------------------------------------------- +#CMVCPATHNAME com.ibm.ws.jmx.connector.client/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessages.nlsprops +#COMPONENTPREFIX CWWKX +#COMPONENTNAMEFOR WebSphere Management File Transfer Client +#ISMESSAGEFILE TRUE +#NLS_MESSAGEFORMAT_VAR +#NLS_ENCODING=UNICODE +# ------------------------------------------------------------------------------------------------- + +# Message prefix block: CWWKX7951 - CWWKX7999 + +filetransfer.client.init=CWWKX7951I: \u65b0\u7684\u6a94\u6848\u50b3\u9001\u7528\u6236\u7aef\u5df2\u5229\u7528\u9023\u7dda ID {0} \u9032\u884c\u9023\u7dda\u3002 +filetransfer.client.init.explanation=\u65b0\u7684\u6a94\u6848\u50b3\u9001\u7528\u6236\u7aef\u5df2\u5229\u7528\u6307\u5b9a\u7684\u9023\u7dda ID \u9032\u884c\u9023\u7dda\u3002 +filetransfer.client.init.useraction=\u9019\u662f\u4e00\u5247\u53c3\u8003\u8a0a\u606f\uff0c\u4e0d\u9700\u8981\u4efb\u4f55\u52d5\u4f5c\u3002 + +filetransfer.client.error=CWWKX7952E: {1} \u9023\u7dda\u51fa\u73fe\u7528\u6236\u7aef\u932f\u8aa4\u8a0a\u606f "{0}"\u3002 +filetransfer.client.error.explanation=JMX REST \u9023\u63a5\u5668\u7684\u7528\u6236\u7aef\u767c\u73fe\u932f\u8aa4\uff0c\u7522\u751f\u6307\u5b9a\u7684\u8a0a\u606f\u3002 +filetransfer.client.error.useraction=\u8acb\u5229\u7528\u7522\u751f\u7684\u932f\u8aa4\u8a0a\u606f\u4f86\u8b58\u5225\u53ca\u66f4\u6b63\u9020\u6210\u9019\u500b\u932f\u8aa4\u7684\u554f\u984c\uff0c\u7136\u5f8c\u91cd\u65b0\u57f7\u884c\u4f5c\u696d\u3002 + +filetransfer.server.error=CWWKX7953E: {1} \u9023\u7dda\u51fa\u73fe\u4f3a\u670d\u5668\u7aef\u932f\u8aa4\u8a0a\u606f "{0}"\u3002 +filetransfer.server.error.explanation=JMX REST \u9023\u63a5\u5668\u7684\u4f3a\u670d\u5668\u7aef\u767c\u73fe\u932f\u8aa4\uff0c\u7522\u751f\u6307\u5b9a\u7684\u8a0a\u606f\u3002 +filetransfer.server.error.useraction=\u8acb\u5229\u7528\u7522\u751f\u7684\u932f\u8aa4\u8a0a\u606f\u4f86\u8b58\u5225\u53ca\u66f4\u6b63\u9020\u6210\u9019\u500b\u932f\u8aa4\u7684\u554f\u984c\uff0c\u7136\u5f8c\u91cd\u65b0\u57f7\u884c\u4f5c\u696d\u3002 + +filetransfer.client.bad.credentials=CWWKX7954E: \u6307\u5b9a\u7684\u4f7f\u7528\u8005\u540d\u7a31\u6216\u5bc6\u78bc\u672a\u7372\u6388\u6b0a\u3002\u4f3a\u670d\u5668\u91dd\u5c0d {2} \u9023\u7dda\u7684\u56de\u61c9\u78bc\u662f {0}\uff0c\u8a0a\u606f\u662f {1}\u3002 +filetransfer.client.bad.credentials.explanation=\u5728\u53d6\u5f97\u9023\u7dda\u6642\u6240\u63d0\u4f9b\u7684\u8a8d\u8b49\u4e0d\u6b63\u78ba\u3002\u53ef\u80fd\u662f\u4f7f\u7528\u8005\u4e0d\u5b58\u5728\u3001\u4e0d\u5177\u5099\u5b58\u53d6\u4f3a\u670d\u5668\u7684\u6b0a\u9650\uff0c\u6216\u8005\u5bc6\u78bc\u4e0d\u6b63\u78ba\u3002 +filetransfer.client.bad.credentials.useraction=\u8acb\u66f4\u6b63\u4f7f\u7528\u8005\u540d\u7a31\u6216\u5bc6\u78bc\uff0c\u7136\u5f8c\u53d6\u5f97\u65b0\u9023\u7dda\u3002 + +filetransfer.response.code.error=CWWKX7955E: \u6a94\u6848\u50b3\u9001\u7528\u6236\u7aef\u91dd\u5c0d {2} \u9023\u7dda\u6536\u5230\u542b\u6709 {1} \u8a0a\u606f\u7684\u56de\u61c9\u78bc {0}\u3002 +filetransfer.response.code.error.explanation=\u6a94\u6848\u50b3\u9001\u7528\u6236\u7aef\u5f9e\u4f3a\u670d\u5668\u63a5\u6536\u5230\u975e\u9810\u671f\u7684\u56de\u61c9\u78bc\u3002 +filetransfer.response.code.error.useraction=\u8acb\u5229\u7528\u7528\u6236\u7aef\u56de\u61c9\u7a0b\u5f0f\u78bc\u4f86\u8b58\u5225\u53ca\u89e3\u6c7a\u9019\u500b\u554f\u984c\u7684\u539f\u56e0\uff0c\u7136\u5f8c\u91cd\u65b0\u57f7\u884c\u4f5c\u696d\u3002 + +filetransfer.download.file=CWWKX7956I: \u4e0b\u8f09 {0} \u6a94\u7684\u8981\u6c42\u5df2\u9806\u5229\u5b8c\u6210\uff0c\u5df2\u5229\u7528 {2} \u9023\u7dda\u5c07\u5176\u5167\u5bb9\u5beb\u5165 {1} \u6a94\u4e2d\u3002 +filetransfer.download.file.explanation=\u4e0b\u8f09\u6307\u5b9a\u6a94\u6848\u7684\u8981\u6c42\u5df2\u6210\u529f\u3002 +filetransfer.download.file.useraction=\u9019\u662f\u4e00\u5247\u53c3\u8003\u8a0a\u606f\uff0c\u4e0d\u9700\u8981\u4efb\u4f55\u52d5\u4f5c\u3002 + +filetransfer.unsupported.operation=CWWKX7957E: {1} \u9023\u7dda\u7684\u6a94\u6848\u50b3\u9001\u7528\u6236\u7aef\u4e0d\u652f\u63f4 {0} \u4f5c\u696d\u3002 +filetransfer.unsupported.operation.explanation=\u6a94\u6848\u50b3\u9001\u7528\u6236\u7aef\u4e0d\u652f\u63f4\u6307\u5b9a\u7684\u4f5c\u696d\u3002 +filetransfer.unsupported.operation.useraction=\u8acb\u8981\u6c42\u6a94\u6848\u50b3\u9001\u7528\u6236\u7aef\u652f\u63f4\u7684\u4f5c\u696d\u3002 + +filetransfer.upload.file=CWWKX7958I: \u4e0a\u50b3 {0} \u6a94\u7684\u8981\u6c42\u5df2\u9806\u5229\u5b8c\u6210\uff0c\u5df2\u5229\u7528 {2} \u9023\u7dda\u5c07\u5176\u5167\u5bb9\u5beb\u5165 {1} \u6a94\u4e2d\u3002 +filetransfer.upload.file.explanation=\u4e0a\u50b3\u6307\u5b9a\u6a94\u6848\u7684\u8981\u6c42\u5df2\u6210\u529f\u3002 +filetransfer.upload.file.useraction=\u9019\u662f\u4e00\u5247\u53c3\u8003\u8a0a\u606f\uff0c\u4e0d\u9700\u8981\u4efb\u4f55\u52d5\u4f5c\u3002 + +filetransfer.delete.file=CWWKX7959I: \u5df2\u5229\u7528 {1} \u9023\u7dda\u9806\u5229\u5b8c\u6210\u522a\u9664 {0} \u6a94\u7684\u8981\u6c42\u3002 +filetransfer.delete.file.explanation=\u522a\u9664\u6307\u5b9a\u6a94\u6848\u7684\u8981\u6c42\u5df2\u6210\u529f\u3002 +filetransfer.delete.file.useraction=\u9019\u662f\u4e00\u5247\u53c3\u8003\u8a0a\u606f\uff0c\u4e0d\u9700\u8981\u4efb\u4f55\u52d5\u4f5c\u3002 + +filetransfer.delete.all=CWWKX7960I: \u5f9e\u96c6\u5408 {0} \u522a\u9664\u6240\u6709\u6a94\u6848\u548c\u8cc7\u6599\u593e\u7684\u8981\u6c42\u5df2\u4f7f\u7528 {1} \u9023\u7dda\u9806\u5229\u5b8c\u6210\u3002 +filetransfer.delete.all.explanation=\u522a\u9664\u6307\u5b9a\u96c6\u5408\u7684\u8981\u6c42\u5df2\u6210\u529f\u3002 +filetransfer.delete.all.useraction=\u9019\u662f\u4e00\u5247\u53c3\u8003\u8a0a\u606f\uff0c\u4e0d\u9700\u8981\u4efb\u4f55\u52d5\u4f5c\u3002 diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages.nlsprops b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages.nlsprops new file mode 100755 index 00000000000..88b290eb885 --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages.nlsprops @@ -0,0 +1,146 @@ +# IBM Confidential +# +# OCO Source Materials +# +# Copyright IBM Corp. 2012 +# +# The source code for this program is not published or otherwise divested +# of its trade secrets, irrespective of what has been deposited with the +# U.S. Copyright Office. +# +#CMVCPATHNAME com.ibm.ws.jmx.connector.client/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages.nlsprops +#ISMESSAGEFILE TRUE +#NLS_ENCODING=UNICODE +# +#COMPONENTPREFIX CWWKX +#COMPONENTNAMEFOR CWWKX JMX REST Client +# +# NLS_MESSAGEFORMAT_VAR +# +# Strings in this file which contain replacement variables are processed by the MessageFormat +# class (single quote must be coded as 2 consecutive single quotes ''). Strings in this file +# which do NOT contain replacement variables are NOT processed by the MessageFormat class +# (single quote must be coded as one single quote '). + +# Message prefix block: CWWKX0200-CWWKX0259 + +jmx.rest.client.request.error=CWWKX0201E: The WebSphere Java Management Extensions REST client encountered an error while preparing the request to the server for URL {0} on connection {1} +jmx.rest.client.request.error.explanation=The WebSphere Java Management Extensions REST client encountered an error while preparing a request for the server +jmx.rest.client.request.error.useraction=Examine the server logs for further information. + +jmx.rest.client.response.error=CWWKX0202E: The WebSphere Java Management Extensions REST client was unable to process the response from the server for URL {0} on connection {1} +jmx.rest.client.response.error.explanation=The WebSphere Java Management Extensions REST client was unable to process a response from the server +jmx.rest.client.response.error.useraction=Examine the server logs for further information. + +jmx.rest.client.response.code.error=CWWKX0203E: The WebSphere Java Management Extensions REST client received an unexpected response code {0} with message ''{1}'' from the server for URL {2} on connection {3} +jmx.rest.client.response.code.error.explanation=The WebSphere Java Management Extensions REST client received an unexpected response code from the server +jmx.rest.client.response.code.error.useraction=Examine the server logs for further information. + +jmx.rest.client.server.throwable.exception=CWWKX0204E: Unable to parse Throwable from server error stream. +jmx.rest.client.server.throwable.exception.explanation=The server raised an exception handling the client request, but the client could not parse a Throwable object from the server error stream. The class of the Throwable object may not be available to the client. +jmx.rest.client.server.throwable.exception.useraction=Examine the server logs for further information. + +jmx.rest.client.not.connected=CWWKX0206E: The client is not connected to the server. +jmx.rest.client.not.connected.explanation=The connection to the server or was closed or has failed. +jmx.rest.client.not.connected.useraction=Check that the REST connector feature is enabled on the server and obtain a new connection to the server. + +jmx.rest.client.url.not.found=CWWKX0207E: The server reported that the URL requested by the client was not found. +jmx.rest.client.url.not.found.explanation=The client may have out-of-date information or the REST connector feature on the server may have been disabled. +jmx.rest.client.url.not.found.useraction=Check that the REST connector feature is enabled on the server and obtain a new connection to the server. + +jmx.rest.client.class.name.null=CWWKX0208E: The class name argument was null. +jmx.rest.client.class.name.null.explanation=The class name argument must not be null. +jmx.rest.client.class.name.null.useraction=Provide a non-null class name when calling the method. + +jmx.rest.client.attribute.name.null=CWWKX0209E: The attribute name argument was null. +jmx.rest.client.attribute.name.null.explanation=The attribute name argument must not be null. +jmx.rest.client.attribute.name.null.useraction=Provide a non-null attribute name when calling the method. + +jmx.rest.client.attribute.names.null=CWWKX0210E: The argument containing an array of attribute names was null. +jmx.rest.client.attribute.names.null.explanation=The argument containing an array of attribute names must not be null. +jmx.rest.client.attribute.names.null.useraction=Provide a non-null array of attribute names when calling the method. + +jmx.rest.client.attribute.null=CWWKX0211E: The Attribute argument was null. +jmx.rest.client.attribute.null.explanation=The Attribute argument must not be null. +jmx.rest.client.attribute.null.useraction=Provide a non-null Attribute when calling the method. + +jmx.rest.client.attribute.list.null=CWWKX0212E: The AttributeList argument was null. +jmx.rest.client.attribute.list.null.explanation=The AttributeList argument must not be null. +jmx.rest.client.attribute.list.null.useraction=Provide a non-null AttributeList when calling the method. + +jmx.rest.client.object.name.null=CWWKX0213E: The ObjectName argument was null. +jmx.rest.client.object.name.null.explanation=The ObjectName argument must not be null. +jmx.rest.client.object.name.null.useraction=Provide a non-null ObjectName when calling the method. + +jmx.rest.client.unexpected.server.throwable=CWWKX0214E: An unexpected Throwable object was returned from the server. +jmx.rest.client.unexpected.server.throwable.explanation=The exception wraps a Throwable object returned from the server that is not normally expected for this operation. +jmx.rest.client.unexpected.server.throwable.useraction=Examine the server logs for further information. + +jmx.rest.client.bad.credentials=CWWKX0215E: There was a problem with the user name or password provided. The server responded with code {0} and message ''{1}'' +jmx.rest.client.bad.credentials.explanation=The credentials provided when obtaining the connection were incorrect. The user may not exist or may not have authority to access the server, or the password may be incorrect. +jmx.rest.client.bad.credentials.useraction=Correct the user name or password, then obtain a new connection. + +jmx.rest.client.object.name.pattern=CWWKX0216E: The ObjectName argument ''{0}'' is a pattern." +jmx.rest.client.object.name.pattern.explanation=The ObjectName argument is a pattern but the method requires an ObjectName matching exactly one MBean. +jmx.rest.client.object.name.pattern.useraction=Provide an ObjectName argument without wildcards that will match exactly one MBean. + +jmx.rest.client.instance.not.found=CWWKX0217E: No MBean is currently registered with the given ObjectName ''{0}'' +jmx.rest.client.instance.not.found.explanation=The operation requires a registered MBean, but no MBean with the given ObjectName was registered. +jmx.rest.client.instance.not.found.useraction=Ensure the MBean is registered before attempting to perform management operations on it. + +jmx.rest.client.attribute.not.found=CWWKX0218E: The MBean ''{0}'' does not have an attribute by the name ''{1}'' +jmx.rest.client.attribute.not.found.explanation=The MBean does not provide an attribute of the given name. +jmx.rest.client.attribute.not.found.useraction=Obtain the MBean information to confirm which attributes the MBean provides. + +jmx.rest.client.operation.not.found=CWWKX0219E: The MBean ''{0}'' does not have an operation by the name ''{1}'' +jmx.rest.client.operation.not.found.explanation=The MBean does not provide an operation of the given name. +jmx.rest.client.operation.not.found.useraction=Obtain the MBean information to confirm which operations the MBean provides. + +jmx.rest.client.listener.not.found=CWWKX0220E: The given NotificationListener is not currently registered to receive notifications from MBean ''{0}'' +jmx.rest.client.listener.not.found.explanation=The NotificationListener was not added or has already been removed and is not currently registered to receive notifications from the given MBean. +jmx.rest.client.listener.not.found.useraction=Make sure the calling code tracks which NotificationListeners have been added and removed or catch and handle the exception. + +jmx.rest.client.notification.lost=CWWKX0221I: The notification could not be delivered. +jmx.rest.client.notification.lost.explanation=A notification could not be delivered to one or more NotificationListeners because a registered NotificationListener was not found or there was an exception during delivery of the notification. +jmx.rest.client.notification.lost.useraction=If the notification should have been delivered to a registered NotificationListener, check the logs for exceptions. + +jmx.rest.client.connection.failed=CWWKX0222I: The connection to the server has failed. +jmx.rest.client.connection.failed.explanation=The server became unavailable and did not become available again within the configured maximum time allowable. +jmx.rest.client.connection.failed.useraction=Check the network connection and ensure that the server is running with the REST connector feature enabled. + +jmx.rest.client.connection.temporarily.lost=CWWKX0223I: The connection to the server has been temporarily lost. +jmx.rest.client.connection.temporarily.lost.explanation=The server has become unavailable, but the client will attempt to restore the connection for the duration of the configured maximum time allowable. +jmx.rest.client.connection.temporarily.lost.useraction=If the server is intentionally restarting, no action is required. Otherwise, check the network connection and ensure that the server is running with the REST connector feature enabled. + +jmx.rest.client.connection.restored.with.exceptions=CWWKX0224I: The connection was restored but exceptions were encountered when adding NotificationListeners. +jmx.rest.client.connection.restored.with.exceptions.explanation=The connection to the server was temporarily lost but has been restored successfully. Exceptions were encountered while adding NotificationListeners, so some notifications may not be received. +jmx.rest.client.connection.restored.with.exceptions.useraction=Check the exceptions included with the notification and re-register NotificationListeners after correcting the problems. + +jmx.rest.client.connection.restored=CWWKX0225I: The connection was restored successfully. +jmx.rest.client.connection.restored.explanation=The connection to the server was temporarily lost but has been restored successfully. Any registered NotificationListeners will continue to receive notifications. +jmx.rest.client.connection.restored.useraction=None + +jmx.rest.client.connection.illegal.argument=CWWKX0226E: The parameter of type JMXServiceURL cannot be null. +jmx.rest.client.connection.illegal.argument.explanation=The value for the parameter 'serviceURL' cannot be null. +jmx.rest.client.connection.illegal.argument.useraction=Re-connect to the JMX REST Connector using a non-null JMXServiceURL value. + +jmx.rest.client.connection.invalid.endpoint=CWWKX0227E: The following is not a valid endpoint value: {0} +jmx.rest.client.connection.invalid.endpoint.explanation=The specified endpoint value is not valid. +jmx.rest.client.connection.invalid.endpoint.useraction=Re-connect to the JMX REST Connector using a valid endpoint value that is of type String and has the format "host:port". + +jmx.rest.client.connection.no.endpoints=CWWKX0228E: Could not find any available endpoints to initialize the connector. +jmx.rest.client.connection.no.endpoints.explanation=None of the specified endpoints were available during the JMX REST Connector's initialization. +jmx.rest.client.connection.no.endpoints.useraction=Re-connect to the JMX REST Connector using at least 1 available endpoint. + +jmx.rest.client.bad.user.credentials=CWWKX0229E: There was a problem with the user credentials provided. The server responded with code {0} and message ''{1}'' +jmx.rest.client.bad.user.credentials.explanation=The credentials provided are incorrect, expired, incomplete, or denied authorization. +jmx.rest.client.bad.user.credentials.useraction=Verify that the user credentials have correct authentication and authorization, then obtain a new connection. + +jmx.rest.client.connection.connect=CWWKX0230I: The collective member opened JMX client to the collective controller: {0} +jmx.rest.client.connection.connect.explanation=The member connected to the controller. +jmx.rest.client.connection.connect.useraction=No action required. + +jmx.rest.client.connection.disconnect=CWWKX0231I: The collective member closed JMX client from the collective controller: {0} +jmx.rest.client.connection.disconnect.explanation=The member disconnected from the controller. +jmx.rest.client.connection.disconnect.useraction=No action required. + diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_cs.nlsprops b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_cs.nlsprops new file mode 100755 index 00000000000..53a93c9de66 --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_cs.nlsprops @@ -0,0 +1,146 @@ +# IBM Confidential +# +# OCO Source Materials +# +# Copyright IBM Corp. 2012 +# +# The source code for this program is not published or otherwise divested +# of its trade secrets, irrespective of what has been deposited with the +# U.S. Copyright Office. +# +#CMVCPATHNAME com.ibm.ws.jmx.connector.client/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages.nlsprops +#ISMESSAGEFILE TRUE +#NLS_ENCODING=UNICODE +# +#COMPONENTPREFIX CWWKX +#COMPONENTNAMEFOR CWWKX JMX REST Client +# +# NLS_MESSAGEFORMAT_VAR +# +# Strings in this file which contain replacement variables are processed by the MessageFormat +# class (single quote must be coded as 2 consecutive single quotes ''). Strings in this file +# which do NOT contain replacement variables are NOT processed by the MessageFormat class +# (single quote must be coded as one single quote '). + +# Message prefix block: CWWKX0200-CWWKX0259 + +jmx.rest.client.request.error=CWWKX0201E: Klient REST WebSphere Java Management Extensions zjistil chybu p\u0159i p\u0159\u00edprav\u011b po\u017eadavku na server pro adresu URL {0} na p\u0159ipojen\u00ed {1} +jmx.rest.client.request.error.explanation=Klient REST WebSphere Java Management Extensions zjistil chybu p\u0159i p\u0159\u00edprav\u011b po\u017eadavku na server +jmx.rest.client.request.error.useraction=Zkontrolujte protokoly serveru, zda neobsahuj\u00ed dal\u0161\u00ed informace. + +jmx.rest.client.response.error=CWWKX0202E: Klientovi REST WebSphere Java Management Extensions se nezda\u0159ilo zpracovat odezvu ze serveru pro adresu URL {0} na p\u0159ipojen\u00ed {1} +jmx.rest.client.response.error.explanation=Klientovi REST WebSphere Java Management Extensions se nezda\u0159ilo zpracovat odezvu ze serveru +jmx.rest.client.response.error.useraction=Zkontrolujte protokoly serveru, zda neobsahuj\u00ed dal\u0161\u00ed informace. + +jmx.rest.client.response.code.error=CWWKX0203E: Klient REST WebSphere Java Management Extensions p\u0159ijal od serveru pro adresu URL {2} na p\u0159ipojen\u00ed {3} neo\u010dek\u00e1van\u00fd k\u00f3d odezvy {0} se zpr\u00e1vou ''{1}'' +jmx.rest.client.response.code.error.explanation=Klient REST WebSphere Java Management Extensions p\u0159ijal od serveru neo\u010dek\u00e1van\u00fd k\u00f3d odezvy +jmx.rest.client.response.code.error.useraction=Zkontrolujte protokoly serveru, zda neobsahuj\u00ed dal\u0161\u00ed informace. + +jmx.rest.client.server.throwable.exception=CWWKX0204E: Nelze analyzovat objekt Throwable z proudu chyb serveru. +jmx.rest.client.server.throwable.exception.explanation=Server vr\u00e1til v\u00fdjimku p\u0159i zpracov\u00e1n\u00ed \u017e\u00e1dosti klienta, ale klient nedok\u00e1zat analyzovat objekt Throwable z proudu chyb serveru. Mo\u017en\u00e1 nen\u00ed t\u0159\u00edda objekt\u016f Throwable pro klienta dostupn\u00e1. +jmx.rest.client.server.throwable.exception.useraction=Zkontrolujte protokoly serveru, zda neobsahuj\u00ed dal\u0161\u00ed informace. + +jmx.rest.client.not.connected=CWWKX0206E: Klient nen\u00ed p\u0159ipojen k serveru. +jmx.rest.client.not.connected.explanation=P\u0159ipojen\u00ed k serveru bylo uzav\u0159eno nebo se nezda\u0159ilo. +jmx.rest.client.not.connected.useraction=Zkontrolujte, zda je na serveru povolena funkce konektoru REST, a z\u00edskejte nov\u00e9 p\u0159ipojen\u00ed k serveru. + +jmx.rest.client.url.not.found=CWWKX0207E: Server ohl\u00e1sil, \u017ee adresa URL, kterou klient po\u017eaduje, nebyla nalezena. +jmx.rest.client.url.not.found.explanation=Mo\u017en\u00e1 m\u00e1 klient zastaral\u00e9 informace nebo m\u016f\u017ee b\u00fdt na serveru zak\u00e1z\u00e1na funkce konektoru REST. +jmx.rest.client.url.not.found.useraction=Zkontrolujte, zda je na serveru povolena funkce konektoru REST, a z\u00edskejte nov\u00e9 p\u0159ipojen\u00ed k serveru. + +jmx.rest.client.class.name.null=CWWKX0208E: Argument n\u00e1zev t\u0159\u00eddy m\u011bl hodnotu null. +jmx.rest.client.class.name.null.explanation=Argument n\u00e1zev t\u0159\u00eddy nesm\u00ed m\u00edt hodnotu null. +jmx.rest.client.class.name.null.useraction=P\u0159i vol\u00e1n\u00ed t\u00e9to metody zadejte n\u00e1zev t\u0159\u00eddy s jinou hodnotou ne\u017e null. + +jmx.rest.client.attribute.name.null=CWWKX0209E: Argument n\u00e1zev atributu m\u011bl hodnotu null. +jmx.rest.client.attribute.name.null.explanation=Argument n\u00e1zev atributu nesm\u00ed m\u00edt hodnotu null. +jmx.rest.client.attribute.name.null.useraction=P\u0159i vol\u00e1n\u00ed t\u00e9to metody zadejte n\u00e1zev atributu s jinou hodnotou ne\u017e null. + +jmx.rest.client.attribute.names.null=CWWKX0210E: Argument obsahuj\u00edc\u00ed pole s n\u00e1zvy atribut\u016f m\u011bl hodnotu null. +jmx.rest.client.attribute.names.null.explanation=Argument obsahuj\u00edc\u00ed pole s n\u00e1zvy atribut\u016f nesm\u00ed m\u00edt hodnotu null. +jmx.rest.client.attribute.names.null.useraction=P\u0159i vol\u00e1n\u00ed t\u00e9to metody zadejte pole s n\u00e1zvy atribut\u016f s jinou hodnotou ne\u017e null. + +jmx.rest.client.attribute.null=CWWKX0211E: Argument Attribute m\u011bl hodnotu null. +jmx.rest.client.attribute.null.explanation=Argument Attribute nesm\u00ed m\u00edt hodnotu null. +jmx.rest.client.attribute.null.useraction=P\u0159i vol\u00e1n\u00ed t\u00e9to metody zadejte argument Attribute s jinou hodnotou ne\u017e null. + +jmx.rest.client.attribute.list.null=CWWKX0212E: Argument AttributeList m\u011bl hodnotu null. +jmx.rest.client.attribute.list.null.explanation=Argument AttributeList nesm\u00ed m\u00edt hodnotu null. +jmx.rest.client.attribute.list.null.useraction=P\u0159i vol\u00e1n\u00ed t\u00e9to metody zadejte argument AttributeList s jinou hodnotou ne\u017e null. + +jmx.rest.client.object.name.null=CWWKX0213E: Argument ObjectName m\u011bl hodnotu null. +jmx.rest.client.object.name.null.explanation=Argument ObjectName nesm\u00ed m\u00edt hodnotu null. +jmx.rest.client.object.name.null.useraction=P\u0159i vol\u00e1n\u00ed t\u00e9to metody zadejte argument ObjectName s jinou hodnotou ne\u017e null. + +jmx.rest.client.unexpected.server.throwable=CWWKX0214E: Ze serveru se vr\u00e1til neo\u010dek\u00e1van\u00fd objekt Throwable. +jmx.rest.client.unexpected.server.throwable.explanation=Ve v\u00fdjimce je zabalen objekt Throwable vr\u00e1cen\u00fd ze serveru, kter\u00fd u t\u00e9to operace obvykle nen\u00ed o\u010dek\u00e1v\u00e1n. +jmx.rest.client.unexpected.server.throwable.useraction=Zkontrolujte protokoly serveru, zda neobsahuj\u00ed dal\u0161\u00ed informace. + +jmx.rest.client.bad.credentials=CWWKX0215E: Do\u0161lo k probl\u00e9mu se zadan\u00fdm jm\u00e9nem u\u017eivatele nebo heslem. Server odpov\u011bd\u011bl k\u00f3dem {0} a zpr\u00e1vou ''{1}''. +jmx.rest.client.bad.credentials.explanation=Pov\u011b\u0159en\u00ed uveden\u00e1 p\u0159i z\u00edsk\u00e1v\u00e1n\u00ed p\u0159ipojen\u00ed byla chybn\u00e1. Mo\u017en\u00e1 u\u017eivatel neexistuje, nem\u00e1 opr\u00e1vn\u011bn\u00ed pro p\u0159\u00edstup k serveru nebo je \u0161patn\u00e9 heslo. +jmx.rest.client.bad.credentials.useraction=Opravte jm\u00e9no u\u017eivatele nebo heslo a pot\u00e9 z\u00edskejte nov\u00e9 p\u0159ipojen\u00ed. + +jmx.rest.client.object.name.pattern=CWWKX0216E: Argument ObjectName ''{0}'' je vzor." +jmx.rest.client.object.name.pattern.explanation=Argument ObjectName je vzor, ale tato metoda vy\u017eaduje ObjectName odpov\u00eddaj\u00edc\u00ed pr\u00e1v\u011b jednomu objektu typu MBean. +jmx.rest.client.object.name.pattern.useraction=Zadejte argument ObjectName bez z\u00e1stupn\u00fdch znak\u016f, kter\u00fd odpov\u00edd\u00e1 pr\u00e1v\u011b jednomu objektu typu MBean. + +jmx.rest.client.instance.not.found=CWWKX0217E: Aktu\u00e1ln\u011b nen\u00ed registrovan\u00fd \u017e\u00e1dn\u00fd objekt typu MBean s dan\u00fdm atributem ObjectName ''{0}''. +jmx.rest.client.instance.not.found.explanation=Operace vy\u017eaduje registrovan\u00fd objekt typu MBean, ale \u017e\u00e1dn\u00fd objekt typu MBean s uveden\u00fdm atributem ObjectName nebyl zaregistrov\u00e1n. +jmx.rest.client.instance.not.found.useraction=Ne\u017e se pokus\u00edte prov\u00e1d\u011bt na objektu typu MBean operace spr\u00e1vy, zajist\u011bte, aby byl zaregistrovan\u00fd. + +jmx.rest.client.attribute.not.found=CWWKX0218E: Objekt typu MBean ''{0}'' nem\u00e1 atribut s n\u00e1zvem ''{1}''. +jmx.rest.client.attribute.not.found.explanation=Objekt typu MBean nem\u00e1 atribut s dan\u00fdm n\u00e1zvem. +jmx.rest.client.attribute.not.found.useraction=Z\u00edskejte informace o objektu typu MBean a ov\u011b\u0159te, jak\u00e9 atributy tento objekt typu MBean m\u00e1. + +jmx.rest.client.operation.not.found=CWWKX0219E: Objekt typu MBean ''{0}'' nem\u00e1 operaci s n\u00e1zvem ''{1}''. +jmx.rest.client.operation.not.found.explanation=Objekt typu MBean nem\u00e1 operaci s dan\u00fdm n\u00e1zvem. +jmx.rest.client.operation.not.found.useraction=Z\u00edskejte informace o objektu typu MBean a ov\u011b\u0159te, jak\u00e9 operace tento objekt typu MBean m\u00e1. + +jmx.rest.client.listener.not.found=CWWKX0220E: Dan\u00fd modul NotificationListener nen\u00ed v sou\u010dasn\u00e9 dob\u011b registrovan\u00fd pro p\u0159\u00edjem ozn\u00e1men\u00ed z objektu typu MBean ''{0}''. +jmx.rest.client.listener.not.found.explanation=Modul NotificationListener nebyl p\u0159id\u00e1n nebo ji\u017e byl odebr\u00e1n a v sou\u010dasnosti nen\u00ed registrov\u00e1n pro p\u0159\u00edjem ozn\u00e1men\u00ed z dan\u00e9ho objektu typu MBean. +jmx.rest.client.listener.not.found.useraction=Ujist\u011bte se, \u017ee k\u00f3d vol\u00e1n\u00ed sleduje, kter\u00e9 moduly NotificationListener byly p\u0159id\u00e1ny a odebr\u00e1ny, nebo tuto v\u00fdjimku zachy\u0165te a o\u0161et\u0159ete. + +jmx.rest.client.notification.lost=CWWKX0221I: Ozn\u00e1men\u00ed nebylo mo\u017en\u00e9 doru\u010dit. +jmx.rest.client.notification.lost.explanation=Nebylo mo\u017en\u00e9 doru\u010dit ozn\u00e1men\u00ed nejm\u00e9n\u011b jednomu modulu NotificationListener, proto\u017ee nebyl nalezen registrovan\u00fd modul NotificationListener nebo p\u0159i doru\u010dov\u00e1n\u00ed ozn\u00e1men\u00ed do\u0161lo k v\u00fdjimce. +jmx.rest.client.notification.lost.useraction=Pokud m\u011blo b\u00fdt ozn\u00e1men\u00ed doru\u010deno registrovan\u00e9mu modulu NotificationListener, zkontrolujte, zda protokoly neobsahuj\u00ed v\u00fdjimky. + +jmx.rest.client.connection.failed=CWWKX0222I: P\u0159ipojen\u00ed k serveru se nezda\u0159ilo. +jmx.rest.client.connection.failed.explanation=Server se stal nedostupn\u00fdm a v nakonfigurovan\u00e9m maxim\u00e1ln\u00edm povolen\u00e9m \u010dase nebyl znovu dostupn\u00fd. +jmx.rest.client.connection.failed.useraction=Zkontrolujte s\u00ed\u0165ov\u00e9 p\u0159ipojen\u00ed a ujist\u011bte se, \u017ee je server spu\u0161t\u011bn a je povolena funkce konektoru REST. + +jmx.rest.client.connection.temporarily.lost=CWWKX0223I: P\u0159ipojen\u00ed k serveru bylo do\u010dasn\u011b ztraceno. +jmx.rest.client.connection.temporarily.lost.explanation=Server se stal nedostupn\u00fdm, ale klient se bude pokou\u0161et obnovit p\u0159ipojen\u00ed po dobu nakonfigurovan\u00e9ho maxim\u00e1ln\u00edho povolen\u00e9ho \u010dasu. +jmx.rest.client.connection.temporarily.lost.useraction=Pokud je server \u00famysln\u011b restartov\u00e1n, nen\u00ed pot\u0159eba \u017e\u00e1dn\u00e1 akce. Jinak zkontrolujte s\u00ed\u0165ov\u00e9 p\u0159ipojen\u00ed a ujist\u011bte se, \u017ee je server spu\u0161t\u011bn a je povolena funkce konektoru REST. + +jmx.rest.client.connection.restored.with.exceptions=CWWKX0224I: P\u0159ipojen\u00ed bylo obnoveno, ale p\u0159i p\u0159id\u00e1v\u00e1n\u00ed modul\u016f NotificationListener se vyskytly v\u00fdjimky. +jmx.rest.client.connection.restored.with.exceptions.explanation=P\u0159ipojen\u00ed k serveru bylo do\u010dasn\u011b ztraceno, ale bylo \u00fasp\u011b\u0161n\u011b obnoveno. P\u0159i p\u0159id\u00e1v\u00e1n\u00ed modul\u016f NotificationListener se vyskytly v\u00fdjimky, tak\u017ee mo\u017en\u00e1 nebudou p\u0159ijata n\u011bkter\u00e1 ozn\u00e1men\u00ed. +jmx.rest.client.connection.restored.with.exceptions.useraction=Zkontrolujte v\u00fdjimky uveden\u00e9 u ozn\u00e1men\u00ed a po opraven\u00ed probl\u00e9m\u016f znovu zaregistrujte moduly NotificationListener. + +jmx.rest.client.connection.restored=CWWKX0225I: P\u0159ipojen\u00ed bylo \u00fasp\u011b\u0161n\u011b obnoveno. +jmx.rest.client.connection.restored.explanation=P\u0159ipojen\u00ed k serveru bylo do\u010dasn\u011b ztraceno, ale bylo \u00fasp\u011b\u0161n\u011b obnoveno. V\u0161echny zaregistrovan\u00e9 moduly NotificationListener budou i nad\u00e1le p\u0159ij\u00edmat ozn\u00e1men\u00ed. +jmx.rest.client.connection.restored.useraction=Nen\u00ed + +jmx.rest.client.connection.illegal.argument=CWWKX0226E: Parametr typu JMXServiceURL nem\u016f\u017ee b\u00fdt null. +jmx.rest.client.connection.illegal.argument.explanation=Hodnota parametru 'serviceURL' nem\u016f\u017ee b\u00fdt null. +jmx.rest.client.connection.illegal.argument.useraction=Znovu se p\u0159ipojte ke konektoru JMX REST Connector pomoc\u00ed nenulov\u00e9 hodnoty JMXServiceURL. + +jmx.rest.client.connection.invalid.endpoint=CWWKX0227E: D\u00e1le uveden\u00e9 nen\u00ed platnou hodnotou koncov\u00e9ho bodu: {0} +jmx.rest.client.connection.invalid.endpoint.explanation=Ur\u010den\u00e1 hodnota koncov\u00e9ho bodu nen\u00ed platn\u00e1. +jmx.rest.client.connection.invalid.endpoint.useraction=Znovu se p\u0159ipojte ke konektoru JMX REST Connector pomoc\u00ed platn\u00e9 hodnoty koncov\u00e9ho bodu, kter\u00e1 je typem String a je ve form\u00e1tu "host:port". + +jmx.rest.client.connection.no.endpoints=CWWKX0228E: Nelze naj\u00edt \u017e\u00e1dn\u00e9 dostupn\u00e9 koncov\u00e9 body pro inicializaci konektoru. +jmx.rest.client.connection.no.endpoints.explanation=\u017d\u00e1dn\u00fd z uveden\u00fdch koncov\u00fdch bod\u016f nebyl k dispozici b\u011bhem inicializace konektoru JMX REST Connector. +jmx.rest.client.connection.no.endpoints.useraction=Znovu se p\u0159ipojte ke konektoru JMX REST Connector pomoc\u00ed alespo\u0148 1 dostupn\u00e9ho koncov\u00e9ho bodu. + +jmx.rest.client.bad.user.credentials=CWWKX0229E: Do\u0161lo k probl\u00e9mu se zadan\u00fdmi u\u017eivatelsk\u00fdmi pov\u011b\u0159en\u00edmi. Server odpov\u011bd\u011bl k\u00f3dem {0} a zpr\u00e1vou ''{1}''. +jmx.rest.client.bad.user.credentials.explanation=Zadan\u00e1 pov\u011b\u0159en\u00ed jsou chybn\u00e1, vypr\u0161ela platnost, ne\u00fapln\u00e1 nebo byl odep\u0159ena autorizace. +jmx.rest.client.bad.user.credentials.useraction=Ov\u011b\u0159te, \u017ee u\u017eivatelsk\u00e1 pov\u011b\u0159en\u00ed maj\u00ed spr\u00e1vn\u00e9 ov\u011b\u0159en\u00ed a autorizaci, potom z\u00edskejte nov\u00e9 p\u0159ipojen\u00ed. + +jmx.rest.client.connection.connect=CWWKX0230I: \u010clen kolektivu otev\u0159el klienta JMX ke kolektivn\u00edmu \u0159adi\u010di: {0} +jmx.rest.client.connection.connect.explanation=\u010clen p\u0159ipojen\u00fd k \u0159adi\u010di. +jmx.rest.client.connection.connect.useraction=Nen\u00ed pot\u0159eba \u017e\u00e1dn\u00e1 akce. + +jmx.rest.client.connection.disconnect=CWWKX0231I: \u010clen kolektivu zav\u0159el klienta JMX z kolektivn\u00edho \u0159adi\u010de: {0} +jmx.rest.client.connection.disconnect.explanation=\u010clen odpojen\u00fd od \u0159adi\u010de. +jmx.rest.client.connection.disconnect.useraction=Nen\u00ed pot\u0159eba \u017e\u00e1dn\u00e1 akce. + diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_de.nlsprops b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_de.nlsprops new file mode 100755 index 00000000000..39cfc72695d --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_de.nlsprops @@ -0,0 +1,145 @@ +# IBM Confidential +# +# OCO Source Materials +# +# Copyright IBM Corp. 2012 +# +# The source code for this program is not published or otherwise divested +# of its trade secrets, irrespective of what has been deposited with the +# U.S. Copyright Office. +# +#CMVCPATHNAME com.ibm.ws.jmx.connector.client/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages.nlsprops +#ISMESSAGEFILE TRUE +#NLS_ENCODING=UNICODE +# +#COMPONENTPREFIX CWWKX +#COMPONENTNAMEFOR CWWKX JMX REST Client +# +# NLS_MESSAGEFORMAT_VAR +# +# Strings in this file which contain replacement variables are processed by the MessageFormat +# class (single quote must be coded as 2 consecutive single quotes ''). Strings in this file +# which do NOT contain replacement variables are NOT processed by the MessageFormat class +# (single quote must be coded as one single quote '). + +# Message prefix block: CWWKX0200-CWWKX0259 + +jmx.rest.client.request.error=CWWKX0201E: Im REST-Client von WebSphere Java Management Extensions ist beim Vorbereiten der Anforderung an den Server f\u00fcr den URL {0} in der Verbindung {1} ein Fehler aufgetreten. +jmx.rest.client.request.error.explanation=Im REST-Client von WebSphere Java Management Extensions ist beim Vorbereiten einer Anforderung f\u00fcr den Server ein Fehler aufgetreten. +jmx.rest.client.request.error.useraction=Suchen Sie in den Serverprotokollen nach weiteren Informationen. + +jmx.rest.client.response.error=CWWKX0202E: Der REST-Client von WebSphere Java Management Extensions konnte die Antwort des Servers f\u00fcr den URL {0} in der Verbindung {1} nicht verarbeiten. +jmx.rest.client.response.error.explanation=Der REST-Client von WebSphere Java Management Extensions konnte eine Antwort des Servers nicht verarbeiten. +jmx.rest.client.response.error.useraction=Suchen Sie in den Serverprotokollen nach weiteren Informationen. + +jmx.rest.client.response.code.error=CWWKX0203E: Der REST-Client von WebSphere Java Management Extensions hat den unerwarteten Antwortcode {0} mit der Nachricht ''{1}'' vom Server f\u00fcr den URL {2} in der Verbindung {3} empfangen. +jmx.rest.client.response.code.error.explanation=Der REST-Client von WebSphere Java Management Extensions hat einen unerwarteten Antwortcode vom Server empfangen. +jmx.rest.client.response.code.error.useraction=Suchen Sie in den Serverprotokollen nach weiteren Informationen. + +jmx.rest.client.server.throwable.exception=CWWKX0204E: Throwable aus Fehlerdatenstrom des Servers kann nicht geparst werden. +jmx.rest.client.server.throwable.exception.explanation=Der Server hat bei der Verarbeitung der Clientanforderung eine Ausnahme ausgel\u00f6st, aber der Client konnte ein Throwable-Objekt aus dem Fehlerdatenstrom des Servers nicht parsen. Die Klasse des Throwable-Objekts steht dem Client m\u00f6glicherweise nicht zur Verf\u00fcgung. +jmx.rest.client.server.throwable.exception.useraction=Suchen Sie in den Serverprotokollen nach weiteren Informationen. + +jmx.rest.client.not.connected=CWWKX0206E: Der Client ist nicht mit dem Server verbunden. +jmx.rest.client.not.connected.explanation=Die Verbindung zum Server wurde geschlossen oder ist fehlgeschlagen. +jmx.rest.client.not.connected.useraction=Vergewissern Sie sich, dass das REST-Connector-Feature im Server aktiviert ist, und fordern Sie eine neue Verbindung zum Server an. + +jmx.rest.client.url.not.found=CWWKX0207E: Der Server hat gemeldet, dass der vom Client angeforderte URL nicht gefunden wurde. +jmx.rest.client.url.not.found.explanation=Der Client hat m\u00f6glicherweise Informationen, die nicht auf dem neuesten Stand sind, oder das REST-Connector-Feature im Server wurde aktiviert. +jmx.rest.client.url.not.found.useraction=Vergewissern Sie sich, dass das REST-Connector-Feature im Server aktiviert ist, und fordern Sie eine neue Verbindung zum Server an. +jmx.rest.client.class.name.null=CWWKX0208E: Das Argument f\u00fcr den Klassennamen ist null. +jmx.rest.client.class.name.null.explanation=Das Argument f\u00fcr den Klassennamen darf nicht null sein. +jmx.rest.client.class.name.null.useraction=Geben Sie einen Klassennamen ungleich null beim Aufruf der Methode an. + +jmx.rest.client.attribute.name.null=CWWKX0209E: Das Argument f\u00fcr den Attributnamen ist null. +jmx.rest.client.attribute.name.null.explanation=Das Argument f\u00fcr den Attributnamen darf nicht null sein. +jmx.rest.client.attribute.name.null.useraction=Geben Sie einen Attributnamen ungleich null beim Aufruf der Methode an. + +jmx.rest.client.attribute.names.null=CWWKX0210E: Das Argument, das ein Array von Attributnamen enth\u00e4lt, ist null. +jmx.rest.client.attribute.names.null.explanation=Das Argument, das ein Array von Attributnamen enth\u00e4lt, darf nicht null sein. +jmx.rest.client.attribute.names.null.useraction=Geben Sie ein Array mit Attributnamen ungleich null beim Aufruf der Methode an. + +jmx.rest.client.attribute.null=CWWKX0211E: Das Argument Attribute ist null. +jmx.rest.client.attribute.null.explanation=Das Argument Attribute darf nicht null sein. +jmx.rest.client.attribute.null.useraction=Geben Sie ein Argument Attribute ungleich null beim Aufruf der Methode an. + +jmx.rest.client.attribute.list.null=CWWKX0212E: Das Argument AttributeList ist null. +jmx.rest.client.attribute.list.null.explanation=Das Argument AttributeList darf nicht null sein. +jmx.rest.client.attribute.list.null.useraction=Geben Sie ein Argument AttributeList ungleich null beim Aufruf der Methode an. + +jmx.rest.client.object.name.null=CWWKX0213E: Das Argument ObjectName ist null. +jmx.rest.client.object.name.null.explanation=Das Argument ObjectName darf nicht null sein. +jmx.rest.client.object.name.null.useraction=Geben Sie ein Argument ObjectName ungleich null beim Aufruf der Methode an. + +jmx.rest.client.unexpected.server.throwable=CWWKX0214E: Es wurde ein nicht erwartetes Throwable-Objekt vom Server zur\u00fcckgegeben. +jmx.rest.client.unexpected.server.throwable.explanation=Die Ausnahme schlie\u00dft ein vom Server zur\u00fcckgegebenes Throwable-Objekt ein, das f\u00fcr diese Operation normalerweise nicht erwartet wird. +jmx.rest.client.unexpected.server.throwable.useraction=Suchen Sie in den Serverprotokollen nach weiteren Informationen. + +jmx.rest.client.bad.credentials=CWWKX0215E: Es liegt ein Problem mit dem angegebenen Benutzernamen oder Kennwort vor. Der Server hat mit dem Code {0} und der Nachricht ''{1}'' geantwortet. +jmx.rest.client.bad.credentials.explanation=Die beim Anfordern der Verbindung angegebenen Berechtigungsnachweise sind nicht g\u00fcltig. M\u00f6glicherweise ist der Benutzer nicht vorhanden, oder er hat keine Berechtigung f\u00fcr den Zugriff auf den Server, oder das Kennwort ist ung\u00fcltig. +jmx.rest.client.bad.credentials.useraction=Korrigieren Sie den Benutzernamen bzw. das Kennwort, und fordern Sie dann eine neue Verbindung an. + +jmx.rest.client.object.name.pattern=CWWKX0216E: Das ObjectName-Argument ''{0}'' ist ein Muster. +jmx.rest.client.object.name.pattern.explanation=Das ObjectName-Argument ist ein Muster, aber die Methode erfordert ein ObjectName-Argument, das einer einzigen MBean entspricht. +jmx.rest.client.object.name.pattern.useraction=Geben Sie ein ObjectName-Argument ohne Platzhalterzeichen ein, das einer einzigen MBean entspricht. + +jmx.rest.client.instance.not.found=CWWKX0217E: Es ist momentan keine MBean mit dem angegebenen ObjectName ''{0}'' registriert. +jmx.rest.client.instance.not.found.explanation=Die Operation erfordert eine registrierte MBean, aber es wurde keine MBean mit dem angegebenen ObjectName registriert. +jmx.rest.client.instance.not.found.useraction=Stellen Sie sicher, dass die MBean registriert ist, bevor Sie versuchen, Verwaltungsoperationen f\u00fcr die MBean auszuf\u00fchren. + +jmx.rest.client.attribute.not.found=CWWKX0218E: Die MBean ''{0}'' hat kein Attribut mit dem Namen ''{1}''. +jmx.rest.client.attribute.not.found.explanation=Die MBean hat kein Attribut mit dem angegebenen Namen. +jmx.rest.client.attribute.not.found.useraction=Fordern Sie die MBean-Informationen an, um festzustellen, welche Attribute die MBean enth\u00e4lt. + +jmx.rest.client.operation.not.found=CWWKX0219E: Die MBean ''{0}'' hat keine Operation mit dem Namen ''{1}''. +jmx.rest.client.operation.not.found.explanation=Die MBean hat keine Operation mit dem angegebenen Namen. +jmx.rest.client.operation.not.found.useraction=Fordern Sie die MBean-Informationen an, um festzustellen, welche Operationen die MBean enth\u00e4lt. + +jmx.rest.client.listener.not.found=CWWKX0220E: Der angegebene NotificationListener ist momentan nicht f\u00fcr den Empfang von Benachrichtigungen von der MBean ''{0}'' registriert. +jmx.rest.client.listener.not.found.explanation=Der NotificationListener wurde nicht hinzugef\u00fcgt oder bereits entfernt und ist momentan nicht f\u00fcr den Empfang von Benachrichtigungen von der angegebenen MBean registriert. +jmx.rest.client.listener.not.found.useraction=Stellen Sie sicher, dass der aufrufende Code \u00fcberwacht, welche NotificationListener hinzugef\u00fcgt und entfernt werden, bzw. die Ausnahme abf\u00e4ngt und behandelt. + +jmx.rest.client.notification.lost=CWWKX0221I: Die Benachrichtigung konnte nicht zugestellt werden. +jmx.rest.client.notification.lost.explanation=Eine Benachrichtigung konnte mindestens einem NotificationListener nicht zugestellt werden, weil der registrierte NotificationListener nicht gefunden wurde oder weil w\u00e4hrend der Zustellung der Benachrichtigung eine Ausnahme eingetreten ist. +jmx.rest.client.notification.lost.useraction=Wenn die Benachrichtigung einem registrierten NotificationListener h\u00e4tte zugestellt werden m\u00fcssen, suchen Sie in den Protokollen nach Ausnahmen. + +jmx.rest.client.connection.failed=CWWKX0222I: Die Verbindung zum Server ist fehlgeschlagen. +jmx.rest.client.connection.failed.explanation=Der Server war nicht verf\u00fcgbar und wurde auch nicht innerhalb des konfigurierten maximal zul\u00e4ssigen Zeitraums wiederhergestellt. +jmx.rest.client.connection.failed.useraction=\u00dcberpr\u00fcfen Sie die Netzverbindung, und stellen Sie sicher, dass der Server mit aktiviertem REST-Connector-Feature aktiv ist. + +jmx.rest.client.connection.temporarily.lost=CWWKX0223I: Die Verbindung zum Server ist vor\u00fcbergehend nicht mehr vorhanden. +jmx.rest.client.connection.temporarily.lost.explanation=Der Server ist nicht verf\u00fcgbar, aber der Client versucht, die Verbindung innerhalb der konfigurierten maximal zul\u00e4ssigen Zeit wiederherzustellen. +jmx.rest.client.connection.temporarily.lost.useraction=Wenn der Server absichtlich erneut gestartet wird, ist keine Aktion erforderlich. War der Neustart nicht beabsichtigt, \u00fcberpr\u00fcfen Sie die Netzverbindung, und stellen Sie sicher, dass der Server mit aktiviertem REST-Connector-Feature aktiv ist. + +jmx.rest.client.connection.restored.with.exceptions=CWWKX0224I: Die Verbindung wurde wiederhergestellt, aber beim Hinzuf\u00fcgen der NotificationListener sind Ausnahmen eingetreten. +jmx.rest.client.connection.restored.with.exceptions.explanation=Die Verbindung zum Server war vor\u00fcbergehend nicht mehr vorhanden, wurde aber erfolgreich wiederhergestellt. Beim Hinzuf\u00fcgen der NotificationListeners sind Ausnahmen eingetreten, und deshalb wurden m\u00f6glicherweise einige Benachrichtigungen nicht empfangen. +jmx.rest.client.connection.restored.with.exceptions.useraction=\u00dcberpr\u00fcfen Sie die Ausnahmen, die in der Benachrichtigung enthalten sind, und registrieren Sie die NotificationListener erneut, nachdem Sie die Probleme behoben haben. + +jmx.rest.client.connection.restored=CWWKX0225I: Die Verbindung wurde erfolgreich wiederhergestellt. +jmx.rest.client.connection.restored.explanation=Die Verbindung zum Server war vor\u00fcbergehend nicht mehr vorhanden, wurde aber erfolgreich wiederhergestellt. Alle registrierten NotificationListener empfangen wieder Benachrichtigungen. +jmx.rest.client.connection.restored.useraction=Keine. + +jmx.rest.client.connection.illegal.argument=CWWKX0226E: Der Parameter des Typs JMXServiceURL darf nicht null sein. +jmx.rest.client.connection.illegal.argument.explanation=Der Wert f\u00fcr den Parameter 'serviceURL' darf nicht null sein. +jmx.rest.client.connection.illegal.argument.useraction=Wiederholen Sie die Herstellung der Verbindung zum JMX-REST-Connector mit einem JMXServiceURL-Wert ungleich null. + +jmx.rest.client.connection.invalid.endpoint=CWWKX0227E: Der folgende Endpunktwert ist nicht g\u00fcltig: {0} +jmx.rest.client.connection.invalid.endpoint.explanation=Der angegebene Endpunktwert ist nicht g\u00fcltig. +jmx.rest.client.connection.invalid.endpoint.useraction=Wiederholen Sie die Herstellung der Verbindung zum JMX-REST-Connector mit einem g\u00fcltigen Endpunktwert, der den Datentyp String und das Format "Host:Port" hat. + +jmx.rest.client.connection.no.endpoints=CWWKX0228E: Es wurden keine verf\u00fcgbaren Endpunkte f\u00fcr die Initalisierung des Connectors gefunden. +jmx.rest.client.connection.no.endpoints.explanation=Keiner der angegebenen Endpunkte war w\u00e4hrend der Initialisierung des JMX-REST-Connectors verf\u00fcgbar. +jmx.rest.client.connection.no.endpoints.useraction=Wiederholen Sie die Herstellung der Verbindung zum JMX-REST-Connector mit mindestens einem verf\u00fcgbaren Endpunkt. + +jmx.rest.client.bad.user.credentials=CWWKX0229E: Es liegt ein Problem mit den angegebenen Benutzerberechtigungsnachweisen vor. Der Server hat mit dem Code {0} und der Nachricht ''{1}'' geantwortet. +jmx.rest.client.bad.user.credentials.explanation=Die angegebenen Berechtigungsnachweise sind falsch, abgelaufen, unvollst\u00e4ndig oder die Berechtigung wurde verweigert. +jmx.rest.client.bad.user.credentials.useraction=Vergewissern Sie sich, dass die Benutzerberechtigungsnachweise die ordnungsgem\u00e4\u00dfe Authentifizierung und Berechtigung haben, und stellen Sie anschlie\u00dfend eine neue Verbindung her. + +jmx.rest.client.connection.connect=CWWKX0230I: Das Verbundmember hat den JMX-Client zum Verbundcontroller ge\u00f6ffnet: {0} +jmx.rest.client.connection.connect.explanation=Das Member hat eine Verbindung zum Controller hergestellt. +jmx.rest.client.connection.connect.useraction=Es ist keine Aktion erforderlich. + +jmx.rest.client.connection.disconnect=CWWKX0231I: Das Verbundmember hat den JMX-Client zum Verbundcontroller geschlossen: {0} +jmx.rest.client.connection.disconnect.explanation=Das Member hat die Verbindung zum Controller getrennt. +jmx.rest.client.connection.disconnect.useraction=Es ist keine Aktion erforderlich. + diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_es.nlsprops b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_es.nlsprops new file mode 100755 index 00000000000..721b1580b0d --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_es.nlsprops @@ -0,0 +1,146 @@ +# IBM Confidential +# +# OCO Source Materials +# +# Copyright IBM Corp. 2012 +# +# The source code for this program is not published or otherwise divested +# of its trade secrets, irrespective of what has been deposited with the +# U.S. Copyright Office. +# +#CMVCPATHNAME com.ibm.ws.jmx.connector.client/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages.nlsprops +#ISMESSAGEFILE TRUE +#NLS_ENCODING=UNICODE +# +#COMPONENTPREFIX CWWKX +#COMPONENTNAMEFOR CWWKX JMX REST Client +# +# NLS_MESSAGEFORMAT_VAR +# +# Strings in this file which contain replacement variables are processed by the MessageFormat +# class (single quote must be coded as 2 consecutive single quotes ''). Strings in this file +# which do NOT contain replacement variables are NOT processed by the MessageFormat class +# (single quote must be coded as one single quote '). + +# Message prefix block: CWWKX0200-CWWKX0259 + +jmx.rest.client.request.error=CWWKX0201E: El cliente REST de WebSphere Java Management Extensions ha encontrado un error mientras preparaba la solicitud en el servidor para el URL {0} en la conexi\u00f3n {1} +jmx.rest.client.request.error.explanation=El cliente REST de WebSphere Java Management Extensions ha encontrado un error mientras preparaba una solicitud para el servidor +jmx.rest.client.request.error.useraction=Examine los registros del servidor para obtener m\u00e1s informaci\u00f3n. + +jmx.rest.client.response.error=CWWKX0202E: El cliente REST de WebSphere Java Management Extensions no ha podido procesar la respuesta del servidor para el URL {0} en la conexi\u00f3n {1} +jmx.rest.client.response.error.explanation=El cliente REST de WebSphere Java Management Extensions no ha podido procesar una respuesta del servidor +jmx.rest.client.response.error.useraction=Examine los registros del servidor para obtener m\u00e1s informaci\u00f3n. + +jmx.rest.client.response.code.error=CWWKX0203E: El cliente REST de WebSphere Java Management Extensions ha recibido un c\u00f3digo de respuesta inesperado {0} con el mensaje ''{1}'' del servidor para el URL {2} en la conexi\u00f3n {3} +jmx.rest.client.response.code.error.explanation=El cliente REST de WebSphere Java Management Extensions ha recibido un c\u00f3digo de respuesta inesperado del servidor +jmx.rest.client.response.code.error.useraction=Examine los registros del servidor para obtener m\u00e1s informaci\u00f3n. + +jmx.rest.client.server.throwable.exception=CWWKX0204E: No se puede analizar Throwable de la corriente de error del servidor. +jmx.rest.client.server.throwable.exception.explanation=El servidor ha generado una excepci\u00f3n al manejar la solicitud del cliente, pero el cliente no ha podido analizar un objeto Throwable de la corriente de error del servidor. Es posible que la clase del objeto Throwable no est\u00e9 disponible para el cliente. +jmx.rest.client.server.throwable.exception.useraction=Examine los registros del servidor para obtener m\u00e1s informaci\u00f3n. + +jmx.rest.client.not.connected=CWWKX0206E: El cliente no est\u00e1 conectado al servidor. +jmx.rest.client.not.connected.explanation=La conexi\u00f3n con el servidor se ha cerrado o ha fallado. +jmx.rest.client.not.connected.useraction=Compruebe que la caracter\u00edstica del conector REST est\u00e9 habilitada en el servidor y obtenga una nueva conexi\u00f3n con el servidor. + +jmx.rest.client.url.not.found=CWWKX0207E: El servidor inform\u00f3 que no ha encontrado el URL solicitado por el cliente. +jmx.rest.client.url.not.found.explanation=Es posible que el cliente tenga informaci\u00f3n no actualizada o que la caracter\u00edstica del conector REST del servidor no est\u00e9 habilitada. +jmx.rest.client.url.not.found.useraction=Compruebe que la caracter\u00edstica del conector REST est\u00e9 habilitada en el servidor y obtenga una nueva conexi\u00f3n con el servidor. + +jmx.rest.client.class.name.null=CWWKX0208E: El argumento de nombre de clase era nulo. +jmx.rest.client.class.name.null.explanation=El argumento de nombre de clase no debe ser nulo. +jmx.rest.client.class.name.null.useraction=Proporcione un nombre de clase no nulo cuando llame al m\u00e9todo. + +jmx.rest.client.attribute.name.null=CWWKX0209E: El argumento de nombre de atributo era nulo. +jmx.rest.client.attribute.name.null.explanation=El argumento de nombre de atributo no debe ser nulo. +jmx.rest.client.attribute.name.null.useraction=Proporcione un nombre de atributo no nulo cuando llame al m\u00e9todo. + +jmx.rest.client.attribute.names.null=CWWKX0210E: El argumento que contiene una matriz de nombres de atributo era nulo. +jmx.rest.client.attribute.names.null.explanation=El argumento que contiene una matriz de nombres de atributo no debe ser nulo. +jmx.rest.client.attribute.names.null.useraction=Proporcione una matriz no nula de nombres de atributo cuando llame al m\u00e9todo. + +jmx.rest.client.attribute.null=CWWKX0211E: El argumento Attribute era nulo. +jmx.rest.client.attribute.null.explanation=El argumento Attribute no debe ser nulo. +jmx.rest.client.attribute.null.useraction=Proporcione un Attribute no nulo cuando llame al m\u00e9todo. + +jmx.rest.client.attribute.list.null=CWWKX0212E: El argumento AttributeList era nulo. +jmx.rest.client.attribute.list.null.explanation=El argumento AttributeList no debe ser nulo. +jmx.rest.client.attribute.list.null.useraction=Proporcione un AttributeList no nulo cuando llame al m\u00e9todo. + +jmx.rest.client.object.name.null=CWWKX0213E: El argumento ObjectName era nulo. +jmx.rest.client.object.name.null.explanation=El argumento ObjectName no debe ser nulo. +jmx.rest.client.object.name.null.useraction=Proporcione un ObjectName no nulo cuando llame al m\u00e9todo. + +jmx.rest.client.unexpected.server.throwable=CWWKX0214E: El servidor ha devuelto un objeto Throwable inesperado. +jmx.rest.client.unexpected.server.throwable.explanation=La excepci\u00f3n incluye un objeto Throwable devuelto desde el servidor que no se espera normalmente para esta operaci\u00f3n. +jmx.rest.client.unexpected.server.throwable.useraction=Examine los registros del servidor para obtener m\u00e1s informaci\u00f3n. + +jmx.rest.client.bad.credentials=CWWKX0215E: Ha habido un problema con el nombre de usuario o contrase\u00f1a especificados. El servidor respondi\u00f3 con el c\u00f3digo {0} y el mensaje ''{1}'' +jmx.rest.client.bad.credentials.explanation=Las credenciales proporcionadas al obtener la conexi\u00f3n eran incorrectas. Es posible que el usuario no exista o que no tenga autoridad para acceder al servidor, o que la contrase\u00f1a sea incorrecta. +jmx.rest.client.bad.credentials.useraction=Corrija el nombre de usuario o la contrase\u00f1a y despu\u00e9s obtenga una nueva conexi\u00f3n. + +jmx.rest.client.object.name.pattern=CWWKX0216E: El argumento ObjectName ''{0}'' es un patr\u00f3n. " +jmx.rest.client.object.name.pattern.explanation=El argumento ObjectName es un patr\u00f3n pero el m\u00e9todo requiere un ObjectName que coincida exactamente con un MBean. +jmx.rest.client.object.name.pattern.useraction=Proporcione un argumento ObjectName sin comodines y que coincida exactamente con un MBean. + +jmx.rest.client.instance.not.found=CWWKX0217E: Actualmente no hay registrado ning\u00fan MBean con el ObjectName ''{0}'' indicado +jmx.rest.client.instance.not.found.explanation=La operaci\u00f3n requiere un MBean registrado, pero no se ha registrado ning\u00fan MBean con el ObjectName indicado. +jmx.rest.client.instance.not.found.useraction=Aseg\u00farese de que el MBean est\u00e9 registrado antes de intentar realizar operaciones de gesti\u00f3n en \u00e9l. + +jmx.rest.client.attribute.not.found=CWWKX0218E: El MBean ''{0}'' no tiene ning\u00fan atributo con el nombre ''{1}'' +jmx.rest.client.attribute.not.found.explanation=El MBean no proporciona ning\u00fan atributo del nombre indicado. +jmx.rest.client.attribute.not.found.useraction=Obtenga la informaci\u00f3n del MBean para confirmar qu\u00e9 atributos proporciona el MBean. + +jmx.rest.client.operation.not.found=CWWKX0219E: El MBean ''{0}'' no tiene ninguna operaci\u00f3n con el nombre ''{1}'' +jmx.rest.client.operation.not.found.explanation=El MBean no proporciona ninguna operaci\u00f3n del nombre indicado. +jmx.rest.client.operation.not.found.useraction=Obtenga la informaci\u00f3n del MBean para confirmar qu\u00e9 operaciones proporciona el MBean. + +jmx.rest.client.listener.not.found=CWWKX0220E: El NotificationListener indicado no est\u00e1 actualmente registrado para recibir notificaciones del MBean ''{0}'' +jmx.rest.client.listener.not.found.explanation=No se ha a\u00f1adido el NotificationListener o se ha eliminado y no est\u00e1 registrado actualmente para recibir notificaciones del MBean indicado. +jmx.rest.client.listener.not.found.useraction=Aseg\u00farese de que el c\u00f3digo de llamada hace un seguimiento de qu\u00e9 NotificationListeners se ha a\u00f1adido y eliminado o que capture y gestione la excepci\u00f3n. + +jmx.rest.client.notification.lost=CWWKX0221I: No se ha podido entregar la notificaci\u00f3n. +jmx.rest.client.notification.lost.explanation=No se ha podido entregar la notificaci\u00f3n a uno o m\u00e1s NotificationListeners porque no se ha encontrado un NotificationListener registrado o se ha producido una excepci\u00f3n durante la entrega de la notificaci\u00f3n. +jmx.rest.client.notification.lost.useraction=Si la notificaci\u00f3n deber\u00eda haberse entregado a un NotificationListener registrado busque excepciones en los registros. + +jmx.rest.client.connection.failed=CWWKX0222I: Ha fallado la conexi\u00f3n con el servidor. +jmx.rest.client.connection.failed.explanation=El servidor ha dejado de estar disponible y no ha vuelto a estar disponible dentro del tiempo m\u00e1ximo configurado permitido. +jmx.rest.client.connection.failed.useraction=Compruebe la conexi\u00f3n de red y aseg\u00farese de que el servidor est\u00e9 en ejecuci\u00f3n con la caracter\u00edstica del conector REST habilitada. + +jmx.rest.client.connection.temporarily.lost=CWWKX0223I: Se ha perdido temporalmente la conexi\u00f3n con el servidor. +jmx.rest.client.connection.temporarily.lost.explanation=El servidor ha dejado de estar disponible, pero el cliente intentar\u00e1 restablecer la conexi\u00f3n durante el tiempo m\u00e1ximo configurado permitido. +jmx.rest.client.connection.temporarily.lost.useraction=Si el servidor se est\u00e1 reiniciando de manera intencionada, no hay que realizar ninguna acci\u00f3n. En caso contrario, compruebe la conexi\u00f3n de red y aseg\u00farese de que el servidor est\u00e9 en ejecuci\u00f3n con la caracter\u00edstica del conector REST habilitada. + +jmx.rest.client.connection.restored.with.exceptions=CWWKX0224I: Se ha restablecido la conexi\u00f3n pero se han encontrado excepciones al a\u00f1adir los NotificationListeners. +jmx.rest.client.connection.restored.with.exceptions.explanation=Se hab\u00eda perdido temporalmente la conexi\u00f3n con el servidor pero se restableci\u00f3 satisfactoriamente. Se encontraron excepciones al a\u00f1adir los NotificationListeners, por lo que es posible que algunas notificaciones no se hayan recibido. +jmx.rest.client.connection.restored.with.exceptions.useraction=Compruebe las excepciones incluidas con la notificaci\u00f3n y vuelva a registrar los NotificationListeners despu\u00e9s de corregir los problemas. + +jmx.rest.client.connection.restored=CWWKX0225I: La conexi\u00f3n se ha restablecido satisfactoriamente. +jmx.rest.client.connection.restored.explanation=Se hab\u00eda perdido temporalmente la conexi\u00f3n con el servidor pero se restableci\u00f3 satisfactoriamente. Los NotificationListeners registrados seguir\u00e1n recibiendo notificaciones. +jmx.rest.client.connection.restored.useraction=Ninguna. + +jmx.rest.client.connection.illegal.argument=CWWKX0226E: El par\u00e1metro de tipo JMXServiceURL no puede ser nulo. +jmx.rest.client.connection.illegal.argument.explanation=El valor del par\u00e1metro 'serviceURL' no puede ser nulo. +jmx.rest.client.connection.illegal.argument.useraction=Vuelva a conectar con JMX REST Connector utilizando un valor JMXServiceURL no nulo. + +jmx.rest.client.connection.invalid.endpoint=CWWKX0227E: El siguiente valor no es un valor de punto final v\u00e1lido: {0} +jmx.rest.client.connection.invalid.endpoint.explanation=El valor de punto final especificado no es v\u00e1lido. +jmx.rest.client.connection.invalid.endpoint.useraction=Vuelva a conectar con JMX REST Connector utilizando un valor de punto final v\u00e1lido que sea de tipo String y tenga el formato "host:puerto". + +jmx.rest.client.connection.no.endpoints=CWWKX0228E: No se ha podido encontrar ning\u00fan punto final disponible para inicializar el conector. +jmx.rest.client.connection.no.endpoints.explanation=Ninguno de los puntos finales especificados estaba disponible durante la inicializaci\u00f3n de JMX REST Connector. +jmx.rest.client.connection.no.endpoints.useraction=Vuelva a conectar con JMX REST Connector utilizando al menos un punto final disponible. + +jmx.rest.client.bad.user.credentials=CWWKX0229E: Ha habido un problema con las credenciales de usuario proporcionadas. El servidor respondi\u00f3 con el c\u00f3digo {0} y el mensaje ''{1}'' +jmx.rest.client.bad.user.credentials.explanation=Las credenciales proporcionadas son incorrectas, caducadas, incompletas o se ha rechazado la autorizaci\u00f3n. +jmx.rest.client.bad.user.credentials.useraction=Verifique que las credenciales de usuario tengan la autenticaci\u00f3n y la autorizaci\u00f3n correctas y, a continuaci\u00f3n obtenga una nueva conexi\u00f3n. + +jmx.rest.client.connection.connect=CWWKX0230I: El miembro de colectivo ha abierto el cliente JMX al controlador colectivo: {0} +jmx.rest.client.connection.connect.explanation=El miembro se ha conectado al controlador. +jmx.rest.client.connection.connect.useraction=No se requiere ninguna acci\u00f3n. + +jmx.rest.client.connection.disconnect=CWWKX0231I: El miembro de colectivo ha cerrado el cliente JMX del controlador colectivo: {0} +jmx.rest.client.connection.disconnect.explanation=El miembro se ha desconectado del controlador. +jmx.rest.client.connection.disconnect.useraction=No se requiere ninguna acci\u00f3n. + diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_fr.nlsprops b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_fr.nlsprops new file mode 100755 index 00000000000..a2726a64fab --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_fr.nlsprops @@ -0,0 +1,146 @@ +# IBM Confidential +# +# OCO Source Materials +# +# Copyright IBM Corp. 2012 +# +# The source code for this program is not published or otherwise divested +# of its trade secrets, irrespective of what has been deposited with the +# U.S. Copyright Office. +# +#CMVCPATHNAME com.ibm.ws.jmx.connector.client/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages.nlsprops +#ISMESSAGEFILE TRUE +#NLS_ENCODING=UNICODE +# +#COMPONENTPREFIX CWWKX +#COMPONENTNAMEFOR CWWKX JMX REST Client +# +# NLS_MESSAGEFORMAT_VAR +# +# Strings in this file which contain replacement variables are processed by the MessageFormat +# class (single quote must be coded as 2 consecutive single quotes ''). Strings in this file +# which do NOT contain replacement variables are NOT processed by the MessageFormat class +# (single quote must be coded as one single quote '). + +# Message prefix block: CWWKX0200-CWWKX0259 + +jmx.rest.client.request.error=CWWKX0201E: Le client REST WebSphere Java Management Extensions a d\u00e9tect\u00e9 une erreur lors de la pr\u00e9paration de la demande au serveur de l''URL {0} sur la connexion {1} +jmx.rest.client.request.error.explanation=Le client REST WebSphere Java Management Extensions a d\u00e9tect\u00e9 une erreur lors de la pr\u00e9paration d'une demande pour le serveur +jmx.rest.client.request.error.useraction=Examinez les journaux du serveur pour plus d'informations. + +jmx.rest.client.response.error=CWWKX0202E: Le client REST WebSphere Java Management Extensions n''a pas pu traiter la r\u00e9ponse du serveur pour l''URL {0} sur la connexion {1} +jmx.rest.client.response.error.explanation=Le client REST WebSphere Java Management Extensions n'a pas pu traiter une r\u00e9ponse du serveur +jmx.rest.client.response.error.useraction=Examinez les journaux du serveur pour plus d'informations. + +jmx.rest.client.response.code.error=CWWKX0203E: Le client REST WebSphere Java Management Extensions a re\u00e7u un code de r\u00e9ponse inattendu {0} avec le message ''{1}'' du serveur pour l''URL {2} sur la connexion {3} +jmx.rest.client.response.code.error.explanation=Le client REST WebSphere Java Management Extensions a re\u00e7u un code de r\u00e9ponse inattendu du serveur +jmx.rest.client.response.code.error.useraction=Examinez les journaux du serveur pour plus d'informations. + +jmx.rest.client.server.throwable.exception=CWWKX0204E: Impossible d'interpr\u00e9ter un objet Throwable dans le flux d'erreurs du serveur. +jmx.rest.client.server.throwable.exception.explanation=Le serveur a lev\u00e9 une exception en traitant la demande du client, mais le client n'a pas pu interpr\u00e9ter un objet Throwable \u00e0 partir du flux d'erreurs du serveur. Il est possible que le client ne dispose pas de la classe de l'objet Throwable. +jmx.rest.client.server.throwable.exception.useraction=Examinez les journaux du serveur pour plus d'informations. + +jmx.rest.client.not.connected=CWWKX0206E: Le client n'est pas connect\u00e9 au serveur. +jmx.rest.client.not.connected.explanation=La connexion au serveur a \u00e9t\u00e9 ferm\u00e9e ou a \u00e9chou\u00e9. +jmx.rest.client.not.connected.useraction=V\u00e9rifiez que la fonction connecteur REST est activ\u00e9e sur le serveur, puis obtenez une nouvelle connexion au serveur. + +jmx.rest.client.url.not.found=CWWKX0207E: Le serveur signale que l'URL demand\u00e9e par le client est introuvable. +jmx.rest.client.url.not.found.explanation=Les informations dont dispose le client sont peut-\u00eatre obsol\u00e8tes, ou bien la fonction connecteur REST sur le serveur a peut-\u00eatre \u00e9t\u00e9 d\u00e9sactiv\u00e9e. +jmx.rest.client.url.not.found.useraction=V\u00e9rifiez que la fonction connecteur REST est activ\u00e9e sur le serveur, puis obtenez une nouvelle connexion au serveur. + +jmx.rest.client.class.name.null=CWWKX0208E: L'argument de nom de classe \u00e9tait Null. +jmx.rest.client.class.name.null.explanation=L'argument de nom de classe ne doit pas \u00eatre Null. +jmx.rest.client.class.name.null.useraction=Fournissez un nom de classe non Null lorsque vous appelez la m\u00e9thode. + +jmx.rest.client.attribute.name.null=CWWKX0209E: L'argument de nom d'attribut \u00e9tait Null. +jmx.rest.client.attribute.name.null.explanation=L'argument de nom d'attribut ne doit pas \u00eatre Null. +jmx.rest.client.attribute.name.null.useraction=Fournissez un nom d'attribut non Null lorsque vous appelez la m\u00e9thode. + +jmx.rest.client.attribute.names.null=CWWKX0210E: L'argument suppos\u00e9 contenir un tableau de noms d'attribut \u00e9tait Null. +jmx.rest.client.attribute.names.null.explanation=L'argument suppos\u00e9 contenir un tableau de noms d'attribut ne doit pas \u00eatre Null. +jmx.rest.client.attribute.names.null.useraction=Fournissez un tableau non Null de noms d'attribut lorsque vous appelez la m\u00e9thode. + +jmx.rest.client.attribute.null=CWWKX0211E: L'argument Attribute \u00e9tait Null. +jmx.rest.client.attribute.null.explanation=L'argument Attribute ne doit pas \u00eatre Null. +jmx.rest.client.attribute.null.useraction=Fournissez un argument Attribute non Null lorsque vous appelez la m\u00e9thode. + +jmx.rest.client.attribute.list.null=CWWKX0212E: L'argument AttributeList \u00e9tait Null. +jmx.rest.client.attribute.list.null.explanation=L'argument AttributeList ne doit pas \u00eatre Null. +jmx.rest.client.attribute.list.null.useraction=Fournissez un argument AttributeList non Null lorsque vous appelez la m\u00e9thode. + +jmx.rest.client.object.name.null=CWWKX0213E: L'argument ObjectName \u00e9tait Null. +jmx.rest.client.object.name.null.explanation=L'argument ObjectName ne doit pas \u00eatre Null. +jmx.rest.client.object.name.null.useraction=Fournissez un argument ObjectName non Null lorsque vous appelez la m\u00e9thode. + +jmx.rest.client.unexpected.server.throwable=CWWKX0214E: Un objet Throwable inattendu a \u00e9t\u00e9 renvoy\u00e9 par le serveur. +jmx.rest.client.unexpected.server.throwable.explanation=L'exception encapsule un objet Throwable renvoy\u00e9 par le serveur qui n'est normalement pas pr\u00e9vu pour cette op\u00e9ration. +jmx.rest.client.unexpected.server.throwable.useraction=Examinez les journaux du serveur pour plus d'informations. + +jmx.rest.client.bad.credentials=CWWKX0215E: Un probl\u00e8me est survenu avec le nom d''utilisateur ou le mot de passe fourni. Le serveur a r\u00e9pondu avec le code {0} et le message ''{1}'' +jmx.rest.client.bad.credentials.explanation=Les donn\u00e9es d'identification fournies lors de l'obtention de la connexion \u00e9taient incorrectes. L'utilisateur n'existe peut-\u00eatre pas ; ou alors, s'il existe, il n'a peut-\u00eatre pas le droit d'acc\u00e9der au serveur ou le mot de passe indiqu\u00e9 est incorrect. +jmx.rest.client.bad.credentials.useraction=Corrigez le nom d'utilisateur ou le mot de passe, puis obtenez une nouvelle connexion. + +jmx.rest.client.object.name.pattern=CWWKX0216E: L''argument ObjectName ''{0}'' est un masque g\u00e9n\u00e9rique. +jmx.rest.client.object.name.pattern.explanation=L'argument ObjectName est un masque g\u00e9n\u00e9rique alors que la m\u00e9thode requiert un ObjectName correspondant pr\u00e9cis\u00e9ment \u00e0 un unique bean g\u00e9r\u00e9 (MBean). +jmx.rest.client.object.name.pattern.useraction=Fournissez un argument ObjectName sans partie g\u00e9n\u00e9rique afin de d\u00e9signer pr\u00e9cis\u00e9ment un unique MBean. + +jmx.rest.client.instance.not.found=CWWKX0217E: Aucun MBean n''est actuellement enregistr\u00e9 avec l''ObjectName indiqu\u00e9, ''{0}'' +jmx.rest.client.instance.not.found.explanation=L'op\u00e9ration n\u00e9cessite un MBean enregistr\u00e9, mais aucun ne l'a \u00e9t\u00e9 avec l'ObjectName indiqu\u00e9. +jmx.rest.client.instance.not.found.useraction=Assurez-vous que le MBean est bien enregistr\u00e9 avant de tenter toute op\u00e9ration de gestion dessus. + +jmx.rest.client.attribute.not.found=CWWKX0218E: Le MBean ''{0}'' n''a pas d''attribut nomm\u00e9 ''{1}'' +jmx.rest.client.attribute.not.found.explanation=Le MBean ne fournit pas d'attribut portant le nom indiqu\u00e9. +jmx.rest.client.attribute.not.found.useraction=Obtenez les informations du MBean afin de d\u00e9terminer quels attributs il fournit. + +jmx.rest.client.operation.not.found=CWWKX0219E: Le MBean ''{0}'' n''a pas d''op\u00e9ration nomm\u00e9e ''{1}'' +jmx.rest.client.operation.not.found.explanation=Le MBean ne fournit pas d'op\u00e9ration portant le nom indiqu\u00e9. +jmx.rest.client.operation.not.found.useraction=Obtenez les informations du MBean afin de d\u00e9terminer quelles op\u00e9rations il fournit. + +jmx.rest.client.listener.not.found=CWWKX0220E: Le NotificationListener fourni n''est pas actuellement enregistr\u00e9 pour recevoir des notifications du MBean ''{0}'' +jmx.rest.client.listener.not.found.explanation=Le NotificationListener n'a pas \u00e9t\u00e9 ajout\u00e9, ou bien s'il l'a \u00e9t\u00e9, il est d\u00e9j\u00e0 retir\u00e9 et n'est donc pas actuellement enregistr\u00e9 pour recevoir des notifications du MBean indiqu\u00e9. +jmx.rest.client.listener.not.found.useraction=Assurez-vous que le code appelant tient \u00e0 jour la liste des NotificationListeners ayant \u00e9t\u00e9 ajout\u00e9s et retir\u00e9s ou que l'exception est intercept\u00e9e (catch) et trait\u00e9e. + +jmx.rest.client.notification.lost=CWWKX0221I: La notification n'a pas pu \u00eatre livr\u00e9e. +jmx.rest.client.notification.lost.explanation=Une notification n'a pas pu \u00eatre livr\u00e9e \u00e0 un ou plusieurs NotificationListeners car aucun NotificationListener enregistr\u00e9 n'a \u00e9t\u00e9 trouv\u00e9 ou bien une exception s'est produite lors de la livraison de la notification. +jmx.rest.client.notification.lost.useraction=Si la notification aurait due \u00eatre envoy\u00e9e \u00e0 un programme d'\u00e9coute NotificationListener enregistr\u00e9, recherchez des exceptions dans les journaux. + +jmx.rest.client.connection.failed=CWWKX0222I: La connexion au serveur a \u00e9chou\u00e9. +jmx.rest.client.connection.failed.explanation=Le serveur est devenu indisponible et sa disponibilit\u00e9 n'a pas \u00e9t\u00e9 r\u00e9tablie dans le d\u00e9lai imparti configur\u00e9. +jmx.rest.client.connection.failed.useraction=V\u00e9rifiez la connexion r\u00e9seau et assurez-vous que le serveur est ex\u00e9cut\u00e9 avec la fonction connecteur REST activ\u00e9e. + +jmx.rest.client.connection.temporarily.lost=CWWKX0223I: La connexion au serveur a \u00e9t\u00e9 temporairement perdue. +jmx.rest.client.connection.temporarily.lost.explanation=Le serveur est devenu indisponible, mais le client va tenter de restaurer la connexion dans le d\u00e9lai imparti configur\u00e9. +jmx.rest.client.connection.temporarily.lost.useraction=Si le serveur red\u00e9marre intentionnellement, aucune action n'est requise. Sinon, v\u00e9rifiez la connexion r\u00e9seau et assurez-vous que le serveur est ex\u00e9cut\u00e9 avec la fonction connecteur REST activ\u00e9e. + +jmx.rest.client.connection.restored.with.exceptions=CWWKX0224I: La connexion a \u00e9t\u00e9 restaur\u00e9e, mais des exceptions ont \u00e9t\u00e9 rencontr\u00e9es lors de l'ajout des NotificationListeners. +jmx.rest.client.connection.restored.with.exceptions.explanation=La connexion au serveur a \u00e9t\u00e9 perdue temporairement, mais elle a ensuite \u00e9t\u00e9 correctement r\u00e9tablie. Des exceptions ont toutefois \u00e9t\u00e9 rencontr\u00e9es lors de l'ajout des NotificationListeners, de sorte que certaines notifications risquent de ne pas \u00eatre re\u00e7ues. +jmx.rest.client.connection.restored.with.exceptions.useraction=V\u00e9rifiez les exceptions incluses avec la notification et, une fois les probl\u00e8mes corrig\u00e9s, r\u00e9enregistrez les NotificationListeners. + +jmx.rest.client.connection.restored=CWWKX0225I: La connexion a \u00e9t\u00e9 restaur\u00e9e correctement. +jmx.rest.client.connection.restored.explanation=La connexion au serveur a \u00e9t\u00e9 perdue temporairement, mais elle a ensuite \u00e9t\u00e9 correctement r\u00e9tablie. Tous les NotificationListeners enregistr\u00e9s continueront \u00e0 recevoir les notifications. +jmx.rest.client.connection.restored.useraction=Aucun + +jmx.rest.client.connection.illegal.argument=CWWKX0226E: Le param\u00e8tre de type JMXServiceURL ne peut pas avoir la valeur NULL. +jmx.rest.client.connection.illegal.argument.explanation=La valeur du param\u00e8tre 'serviceURL' ne peut pas \u00eatre NULL. +jmx.rest.client.connection.illegal.argument.useraction=Connectez-vous \u00e0 nouveau au connecteur JMX REST \u00e0 l'aide d'une valeur JMXServiceURL non NULL. + +jmx.rest.client.connection.invalid.endpoint=CWWKX0227E: La valeur de noeud final suivante n''est pas valide : {0} +jmx.rest.client.connection.invalid.endpoint.explanation=La valeur de noeud final indiqu\u00e9e n'est pas valide. +jmx.rest.client.connection.invalid.endpoint.useraction=Connectez-vous \u00e0 nouveau au connecteur JMX REST \u00e0 l'aide d'une valeur de noeud final valide de type cha\u00eene et au format "h\u00f4te:port". + +jmx.rest.client.connection.no.endpoints=CWWKX0228E: Aucun noeud final disponible ne peut \u00eatre localis\u00e9 pour initialiser le connecteur. +jmx.rest.client.connection.no.endpoints.explanation=Aucun des noeuds finaux indiqu\u00e9s n'\u00e9tait disponible pendant l'initialisation du connecteur JMX REST. +jmx.rest.client.connection.no.endpoints.useraction=Connectez-vous \u00e0 nouveau au connecteur JMX REST \u00e0 l'aide d'au moins un noeud final disponible. + +jmx.rest.client.bad.user.credentials=CWWKX0229E: Un probl\u00e8me est survenu avec les donn\u00e9es d''identification de l''utilisateur fournies. Le serveur a r\u00e9pondu avec le code {0} et le message ''{1}'' +jmx.rest.client.bad.user.credentials.explanation=Les donn\u00e9es d'identification fournies sont incorrectes, expir\u00e9es, incompl\u00e8tes ou non autoris\u00e9es. +jmx.rest.client.bad.user.credentials.useraction=V\u00e9rifiez que les donn\u00e9es d'identification de l'utilisateur disposent d'une authentification et d'une autorisation correctes, puis obtenez une nouvelle connexion. + +jmx.rest.client.connection.connect=CWWKX0230I: Le membre de collectivit\u00e9 a ouvert le client JMX dans le contr\u00f4leur de collectivit\u00e9 : {0} +jmx.rest.client.connection.connect.explanation=Le membre est connect\u00e9 au contr\u00f4leur. +jmx.rest.client.connection.connect.useraction=Aucune action n'est requise. + +jmx.rest.client.connection.disconnect=CWWKX0231I: Le membre de collectivit\u00e9 a ferm\u00e9 le client JMX dans le contr\u00f4leur de collectivit\u00e9 : {0} +jmx.rest.client.connection.disconnect.explanation=Le membre est d\u00e9connect\u00e9 du contr\u00f4leur. +jmx.rest.client.connection.disconnect.useraction=Aucune action n'est requise. + diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_hu.nlsprops b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_hu.nlsprops new file mode 100755 index 00000000000..b0e0c628dc2 --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_hu.nlsprops @@ -0,0 +1,146 @@ +# IBM Confidential +# +# OCO Source Materials +# +# Copyright IBM Corp. 2012 +# +# The source code for this program is not published or otherwise divested +# of its trade secrets, irrespective of what has been deposited with the +# U.S. Copyright Office. +# +#CMVCPATHNAME com.ibm.ws.jmx.connector.client/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages.nlsprops +#ISMESSAGEFILE TRUE +#NLS_ENCODING=UNICODE +# +#COMPONENTPREFIX CWWKX +#COMPONENTNAMEFOR CWWKX JMX REST Client +# +# NLS_MESSAGEFORMAT_VAR +# +# Strings in this file which contain replacement variables are processed by the MessageFormat +# class (single quote must be coded as 2 consecutive single quotes ''). Strings in this file +# which do NOT contain replacement variables are NOT processed by the MessageFormat class +# (single quote must be coded as one single quote '). + +# Message prefix block: CWWKX0200-CWWKX0259 + +jmx.rest.client.request.error=CWWKX0201E: A WebSphere Java Management Extensions REST \u00fcgyf\u00e9l hib\u00e1ba \u00fctk\u00f6z\u00f6tt, mik\u00f6zben el\u0151k\u00e9sz\u00edtette a kiszolg\u00e1l\u00f3hoz k\u00fcldend\u0151 k\u00e9r\u00e9st a(z) {1} kapcsolaton tal\u00e1lhat\u00f3 {0} URL eset\u00e9ben +jmx.rest.client.request.error.explanation=A WebSphere Java Management Extensions REST \u00fcgyf\u00e9l hib\u00e1ba \u00fctk\u00f6z\u00f6tt, mik\u00f6zben el\u0151k\u00e9sz\u00edtette a kiszolg\u00e1l\u00f3hoz k\u00fcldend\u0151 k\u00e9r\u00e9st +jmx.rest.client.request.error.useraction=Tov\u00e1bbi inform\u00e1ci\u00f3k\u00e9rt vizsg\u00e1lja meg a kiszolg\u00e1l\u00f3napl\u00f3kat. + +jmx.rest.client.response.error=CWWKX0202E: A WebSphere Java Management Extensions REST \u00fcgyf\u00e9l nem tudta feldolgozni a kiszolg\u00e1l\u00f3t\u00f3l \u00e9rkezett v\u00e1laszt a(z) {1} kapcsolaton tal\u00e1lhat\u00f3 {0} URL eset\u00e9ben +jmx.rest.client.response.error.explanation=A WebSphere Java Management Extensions REST \u00fcgyf\u00e9l nem tudott feldolgozni egy kiszolg\u00e1l\u00f3t\u00f3l \u00e9rkezett v\u00e1laszt +jmx.rest.client.response.error.useraction=Tov\u00e1bbi inform\u00e1ci\u00f3k\u00e9rt vizsg\u00e1lja meg a kiszolg\u00e1l\u00f3napl\u00f3kat. + +jmx.rest.client.response.code.error=CWWKX0203E: A WebSphere Java Management Extensions REST \u00fcgyf\u00e9l a(z) {0} v\u00e1ratlan v\u00e1laszk\u00f3dot kapta a(z) "{1}" \u00fczenettel a kiszolg\u00e1l\u00f3t\u00f3l a(z) {3} kapcsolaton tal\u00e1lhat\u00f3 {2} URL eset\u00e9ben +jmx.rest.client.response.code.error.explanation=A WebSphere Java Management Extensions REST \u00fcgyf\u00e9l egy v\u00e1ratlan v\u00e1laszk\u00f3dot kapta a kiszolg\u00e1l\u00f3t\u00f3l +jmx.rest.client.response.code.error.useraction=Tov\u00e1bbi inform\u00e1ci\u00f3k\u00e9rt vizsg\u00e1lja meg a kiszolg\u00e1l\u00f3napl\u00f3kat. + +jmx.rest.client.server.throwable.exception=CWWKX0204E: Nem lehet \u00e9rtelmezni egy Throwable objektumot a kiszolg\u00e1l\u00f3 hibafolyam\u00e1b\u00f3l. +jmx.rest.client.server.throwable.exception.explanation=A kiszolg\u00e1l\u00f3 kiv\u00e9telt adott az \u00fcgyf\u00e9lk\u00e9r\u00e9s kezel\u00e9sekor, de az \u00fcgyf\u00e9l nem tudott \u00e9rtelmezni egy Throwable objektumot a kiszolg\u00e1l\u00f3 hibafolyam\u00e1b\u00f3l. Lehet, hogy a Throwable objektum oszt\u00e1lya nem el\u00e9rhet\u0151 az \u00fcgyf\u00e9l sz\u00e1m\u00e1ra. +jmx.rest.client.server.throwable.exception.useraction=Tov\u00e1bbi inform\u00e1ci\u00f3k\u00e9rt vizsg\u00e1lja meg a kiszolg\u00e1l\u00f3napl\u00f3kat. + +jmx.rest.client.not.connected=CWWKX0206E: Az \u00fcgyf\u00e9l nem kapcsol\u00f3dik a kiszolg\u00e1l\u00f3hoz. +jmx.rest.client.not.connected.explanation=A kapcsolat a kiszolg\u00e1l\u00f3val megszakadt vagy sikertelen. +jmx.rest.client.not.connected.useraction=Ellen\u0151rizze, hogy enged\u00e9lyezve van-e a REST csatol\u00f3 szolg\u00e1ltat\u00e1s a kiszolg\u00e1l\u00f3n, \u00e9s hozzon l\u00e9tre \u00faj kapcsolatot a kiszolg\u00e1l\u00f3val. + +jmx.rest.client.url.not.found=CWWKX0207E: A kiszolg\u00e1l\u00f3 jelezte, hogy az \u00fcgyf\u00e9l \u00e1ltal k\u00e9rt URL nem tal\u00e1lhat\u00f3. +jmx.rest.client.url.not.found.explanation=Lehet, hogy az \u00fcgyf\u00e9l elavult inform\u00e1ci\u00f3kkal rendelkezik vagy a REST csatol\u00f3 funkci\u00f3 a kiszolg\u00e1l\u00f3n le van tiltva. +jmx.rest.client.url.not.found.useraction=Ellen\u0151rizze, hogy enged\u00e9lyezve van-e a REST csatol\u00f3 szolg\u00e1ltat\u00e1s a kiszolg\u00e1l\u00f3n, \u00e9s hozzon l\u00e9tre \u00faj kapcsolatot a kiszolg\u00e1l\u00f3val. + +jmx.rest.client.class.name.null=CWWKX0208E: Az oszt\u00e1lyn\u00e9v argumentum null \u00e9rt\u00e9k\u0171 volt. +jmx.rest.client.class.name.null.explanation=Az oszt\u00e1lyn\u00e9v argumentum nem lehet null \u00e9rt\u00e9k\u0171. +jmx.rest.client.class.name.null.useraction=Adjon meg nem null \u00e9rt\u00e9k\u0171 oszt\u00e1lynevet a met\u00f3dus h\u00edv\u00e1sakor. + +jmx.rest.client.attribute.name.null=CWWKX0209E: Az attrib\u00fatumn\u00e9v argumentum null \u00e9rt\u00e9k\u0171 volt. +jmx.rest.client.attribute.name.null.explanation=Az attrib\u00fatumn\u00e9v argumentum nem lehet null \u00e9rt\u00e9k\u0171. +jmx.rest.client.attribute.name.null.useraction=Adjon meg nem null \u00e9rt\u00e9k\u0171 attrib\u00fatumnevet a met\u00f3dus h\u00edv\u00e1sakor. + +jmx.rest.client.attribute.names.null=CWWKX0210E: Az attrib\u00fatumneveket tartalmaz\u00f3 argumentum null \u00e9rt\u00e9k\u0171 volt. +jmx.rest.client.attribute.names.null.explanation=Az attrib\u00fatumneveket tartalmaz\u00f3 argumentum nem lehet null \u00e9rt\u00e9k\u0171. +jmx.rest.client.attribute.names.null.useraction=Adjon meg nem null \u00e9rt\u00e9k\u0171 attrib\u00fatumn\u00e9v t\u00f6mb\u00f6t a met\u00f3dus h\u00edv\u00e1sakor. + +jmx.rest.client.attribute.null=CWWKX0211E: Az Attribute argumentum null \u00e9rt\u00e9k\u0171 volt. +jmx.rest.client.attribute.null.explanation=Az Attribute argumentum nem lehet null \u00e9rt\u00e9k\u0171. +jmx.rest.client.attribute.null.useraction=Adjon meg nem null \u00e9rt\u00e9k\u0171 Attribute argumentumot a met\u00f3dus h\u00edv\u00e1sakor. + +jmx.rest.client.attribute.list.null=CWWKX0212E: Az AttributeList argumentum null \u00e9rt\u00e9k\u0171 volt. +jmx.rest.client.attribute.list.null.explanation=Az AttributeList argumentum nem lehet null \u00e9rt\u00e9k\u0171. +jmx.rest.client.attribute.list.null.useraction=Adjon meg nem null \u00e9rt\u00e9k\u0171 AttributeList argumentumot a met\u00f3dus h\u00edv\u00e1sakor. + +jmx.rest.client.object.name.null=CWWKX0213E: Az ObjectName argumentum null \u00e9rt\u00e9k\u0171 volt. +jmx.rest.client.object.name.null.explanation=Az ObjectName argumentum nem lehet null \u00e9rt\u00e9k\u0171. +jmx.rest.client.object.name.null.useraction=Adjon meg nem null \u00e9rt\u00e9k\u0171 ObjectName argumentumot a met\u00f3dus h\u00edv\u00e1sakor. + +jmx.rest.client.unexpected.server.throwable=CWWKX0214E: Nem v\u00e1rt Throwable objektumot adott vissza a program. +jmx.rest.client.unexpected.server.throwable.explanation=A kiv\u00e9tel a m\u0171velethez a kiszolg\u00e1l\u00f3r\u00f3l visszaadott nem v\u00e1rt Throwable objektumot tartalmaz. +jmx.rest.client.unexpected.server.throwable.useraction=Tov\u00e1bbi inform\u00e1ci\u00f3k\u00e9rt vizsg\u00e1lja meg a kiszolg\u00e1l\u00f3napl\u00f3kat. + +jmx.rest.client.bad.credentials=CWWKX0215E: Probl\u00e9ma volt a megadott felhaszn\u00e1l\u00f3n\u00e9vvel vagy jelsz\u00f3val. A kiszolg\u00e1l\u00f3 {0} k\u00f3ddal \u00e9s ''{1}'' \u00fczenettel v\u00e1laszolt. +jmx.rest.client.bad.credentials.explanation=A kapcsolat l\u00e9trehoz\u00e1sakor megadott hiteles\u00edt\u00e9si adatok helytelenek voltak. Lehet, hogy a felhaszn\u00e1l\u00f3 nem l\u00e9tezik vagy nincs jogosults\u00e1ga a kiszolg\u00e1l\u00f3 el\u00e9r\u00e9s\u00e9hez, vagy helytelen a jelsz\u00f3. +jmx.rest.client.bad.credentials.useraction=Jav\u00edtsa ki a felhaszn\u00e1l\u00f3nevet vagy jelsz\u00f3t, majd hozzon l\u00e9tre \u00faj kapcsolatot. + +jmx.rest.client.object.name.pattern=CWWKX0216E: A(z) ''{0}'' ObjectName argumentum egy minta." +jmx.rest.client.object.name.pattern.explanation=Az ObjectName argumentum egy minta, de a met\u00f3dus sz\u00e1m\u00e1ra pontosan egy MBean elemmel egyez\u0151 ObjectName sz\u00fcks\u00e9ges. +jmx.rest.client.object.name.pattern.useraction=Adjon meg helyettes\u00edt\u0151 karakterek n\u00e9lk\u00fcl egy ObjectName argumentumot, ami pontosan egy MBean elemmel egyezik. + +jmx.rest.client.instance.not.found=CWWKX0217E: Jelenleg nincs MBean regisztr\u00e1lva a megadott ''{0}'' ObjectName argumentummal. +jmx.rest.client.instance.not.found.explanation=A m\u0171velethez regisztr\u00e1lt MBean sz\u00fcks\u00e9ges, de a megadott ObjectName argumentummal nem volt MBean regisztr\u00e1lva. +jmx.rest.client.instance.not.found.useraction=Gondoskodjon arr\u00f3l, hogy az MBean regisztr\u00e1lva legyen, miel\u0151tt kezel\u00e9si m\u0171veleteket pr\u00f3b\u00e1l meg v\u00e9grehajtani rajta. + +jmx.rest.client.attribute.not.found=CWWKX0218E: A(z) ''{0}'' MBean nem rendelkezik ''{1}'' nev\u0171 attrib\u00fatummal. +jmx.rest.client.attribute.not.found.explanation=Az MBean nem biztos\u00edtja a megadott nev\u0171 attrib\u00fatumot. +jmx.rest.client.attribute.not.found.useraction=Az MBean inform\u00e1ci\u00f3i megszerz\u00e9s\u00e9vel gy\u0151z\u0151dj\u00f6n meg arr\u00f3l, hogy milyen attrib\u00fatumokat biztos\u00edt az MBean. + +jmx.rest.client.operation.not.found=CWWKX0219E: A(z) ''{0}'' MBean nem rendelkezik ''{1}'' nev\u0171 m\u0171velettel. +jmx.rest.client.operation.not.found.explanation=Az MBean nem biztos\u00edtja a megadott nev\u0171 m\u0171veletet. +jmx.rest.client.operation.not.found.useraction=Az MBean inform\u00e1ci\u00f3i megszerz\u00e9s\u00e9vel gy\u0151z\u0151dj\u00f6n meg arr\u00f3l, hogy milyen m\u0171veleteket biztos\u00edt az MBean. + +jmx.rest.client.listener.not.found=CWWKX0220E: A megadott NotificationListener jelenleg nincs regisztr\u00e1lva, hogy \u00e9rtes\u00edt\u00e9seket fogadjon ''{0}'' MBean \u00f6sszetev\u0151t\u0151l. +jmx.rest.client.listener.not.found.explanation=A NotificationListener nem lett hozz\u00e1adva vagy m\u00e1r el lett t\u00e1vol\u00edtva, \u00e9s jelenleg nincs regisztr\u00e1lva \u00e9rtes\u00edt\u00e9sek fogad\u00e1s\u00e1ra a megadott MBean \u00f6sszetev\u0151t\u0151l. +jmx.rest.client.listener.not.found.useraction=Gondoskodjon arr\u00f3l, hogy a h\u00edv\u00f3 k\u00f3d nyomon k\u00f6vesse, hogy melyik NotificationListener \u00f6sszetev\u0151k lettek hozz\u00e1adva \u00e9s elt\u00e1vol\u00edtva, vagy fogja el \u00e9s kezelje a kiv\u00e9telt. + +jmx.rest.client.notification.lost=CWWKX0221I: Az \u00e9rtes\u00edt\u00e9st nem lehetett k\u00e9zbes\u00edteni. +jmx.rest.client.notification.lost.explanation=Egy \u00e9rtes\u00edt\u00e9st nem lehetett k\u00e9zbes\u00edteni n\u00e9h\u00e1ny NotificationListener sz\u00e1m\u00e1ra, mert egy regisztr\u00e1lt NotificationListener nem volt megtal\u00e1lhat\u00f3 vagy kiv\u00e9tel t\u00f6rt\u00e9nt az \u00e9rtes\u00edt\u00e9s k\u00e9zbes\u00edt\u00e9se sor\u00e1n. +jmx.rest.client.notification.lost.useraction=Ha az \u00e9rtes\u00edt\u00e9st k\u00e9zbes\u00edteni kellett volna egy regisztr\u00e1lt NotificationListener sz\u00e1m\u00e1ra, akkor ellen\u0151rizze a napl\u00f3kban a kiv\u00e9teleket. + +jmx.rest.client.connection.failed=CWWKX0222I: A kapcsolat a kiszolg\u00e1l\u00f3val sikertelen. +jmx.rest.client.connection.failed.explanation=A kiszolg\u00e1l\u00f3 el\u00e9rhetetlenn\u00e9 v\u00e1lt, \u00e9s nem lett \u00fajb\u00f3l el\u00e9rhet\u0151 a be\u00e1ll\u00edtott rendelkez\u00e9sre \u00e1ll\u00f3 maxim\u00e1lis id\u0151n bel\u00fcl. +jmx.rest.client.connection.failed.useraction=Ellen\u0151rizze a h\u00e1l\u00f3zati kapcsolatot, \u00e9s gondoskodjon arr\u00f3l, hogy a kiszolg\u00e1l\u00f3 enged\u00e9lyezett REST csatol\u00f3 funkci\u00f3val fusson. + +jmx.rest.client.connection.temporarily.lost=CWWKX0223I: A kapcsolat a kiszolg\u00e1l\u00f3val ideiglenesen elveszett. +jmx.rest.client.connection.temporarily.lost.explanation=A kiszolg\u00e1l\u00f3 el\u00e9rhetetlenn\u00e9 v\u00e1lt, de az \u00fcgyf\u00e9l megpr\u00f3b\u00e1lja vissza\u00e1ll\u00edtani a kapcsolatot a be\u00e1ll\u00edtott rendelkez\u00e9sre \u00e1ll\u00f3 maxim\u00e1lis id\u0151n bel\u00fcl. +jmx.rest.client.connection.temporarily.lost.useraction=Ha a kiszolg\u00e1l\u00f3 sz\u00e1nd\u00e9kosan indul \u00fajra, akkor nincs teend\u0151. Ellenkez\u0151 esetben ellen\u0151rizze a h\u00e1l\u00f3zati kapcsolatot, \u00e9s gondoskodjon arr\u00f3l, hogy a kiszolg\u00e1l\u00f3 enged\u00e9lyezett REST csatol\u00f3 funkci\u00f3val fusson. + +jmx.rest.client.connection.restored.with.exceptions=CWWKX0224I: A kapcsolat vissza\u00e1llt, de kiv\u00e9telek fordultak el\u0151 a NotificationListener elemek hozz\u00e1ad\u00e1sakor. +jmx.rest.client.connection.restored.with.exceptions.explanation=A kapcsolat a kiszolg\u00e1l\u00f3val ideiglenesen elveszett, de sikeresen helyre\u00e1llt. Kiv\u00e9telek fordultak el\u0151 a NotificationListener elemek hozz\u00e1ad\u00e1sakor, ez\u00e9rt lehet, hogy n\u00e9h\u00e1ny \u00e9rtes\u00edt\u00e9st nem lehetett fogadni. +jmx.rest.client.connection.restored.with.exceptions.useraction=Ellen\u0151rizze az \u00e9rtes\u00edt\u00e9s tartalmazott kiv\u00e9teleit, \u00e9s regisztr\u00e1lja \u00fajra a NotificationListener elemeket a probl\u00e9m\u00e1k kijav\u00edt\u00e1sa ut\u00e1n. + +jmx.rest.client.connection.restored=CWWKX0225I: A kapcsolat helyre\u00e1ll\u00edt\u00e1sa siker\u00fclt. +jmx.rest.client.connection.restored.explanation=A kapcsolat a kiszolg\u00e1l\u00f3val ideiglenesen elveszett, de sikeresen helyre\u00e1llt. A regisztr\u00e1lt NotificationListener elemek tov\u00e1bbra is kapnak \u00e9rtes\u00edt\u00e9seket. +jmx.rest.client.connection.restored.useraction=Nincs + +jmx.rest.client.connection.illegal.argument=CWWKX0226E: A JMXServiceURL t\u00edpus\u00fa param\u00e9ter nem lehet null\u00e9rt\u00e9k. +jmx.rest.client.connection.illegal.argument.explanation=A 'serviceURL' param\u00e9ter \u00e9rt\u00e9ke nem lehet null\u00e9rt\u00e9k. +jmx.rest.client.connection.illegal.argument.useraction=Csatlakozzon \u00fajra a JMX REST csatol\u00f3hoz nem null\u00e9rt\u00e9k\u0171 JMXServiceURL \u00e9rt\u00e9kkel. + +jmx.rest.client.connection.invalid.endpoint=CWWKX0227E: A k\u00f6vetkez\u0151 nem \u00e9rv\u00e9nyes v\u00e9gpont\u00e9rt\u00e9k: {0} +jmx.rest.client.connection.invalid.endpoint.explanation=A megadott v\u00e9gpont\u00e9rt\u00e9k \u00e9rv\u00e9nytelen. +jmx.rest.client.connection.invalid.endpoint.useraction=Csatlakozzon \u00fajra a JMX REST csatol\u00f3hoz karaktersorozat t\u00edpus\u00fa, "hoszt:port" form\u00e1tum\u00fa \u00e9rv\u00e9nyes v\u00e9gpont\u00e9rt\u00e9kkel. + +jmx.rest.client.connection.no.endpoints=CWWKX0228E: A csatol\u00f3 inicializ\u00e1l\u00e1s\u00e1hoz nem tal\u00e1lhat\u00f3 el\u00e9rhet\u0151 v\u00e9gpont. +jmx.rest.client.connection.no.endpoints.explanation=A JMX REST csatol\u00f3 inicializ\u00e1l\u00e1sa sor\u00e1n egyik megadott v\u00e9gpont sem \u00e9rhet\u0151 el. +jmx.rest.client.connection.no.endpoints.useraction=Csatlakozzon \u00fajra a JMX REST csatol\u00f3hoz legal\u00e1bb 1 el\u00e9rhet\u0151 v\u00e9gpont haszn\u00e1lat\u00e1val. + +jmx.rest.client.bad.user.credentials=CWWKX0229E: Probl\u00e9ma volt a megadott felhaszn\u00e1l\u00f3 hiteles\u00edt\u00e9si adatokkal. A kiszolg\u00e1l\u00f3 {0} k\u00f3ddal \u00e9s ''{1}'' \u00fczenettel v\u00e1laszolt. +jmx.rest.client.bad.user.credentials.explanation=A megadott hiteles\u00edt\u00e9si adatok helytelenek, lej\u00e1rtak vagy jogosults\u00e1guk megtagad\u00e1sra ker\u00fclt. +jmx.rest.client.bad.user.credentials.useraction=Gy\u0151z\u0151dj\u00f6n meg r\u00f3la, hogy a felhaszn\u00e1l\u00f3 hiteles\u00edt\u00e9si adatok hiteles\u00edt\u00e9se \u00e9s jogosults\u00e1ga helyes, majd alak\u00edtson ki \u00faj kapcsolatot. + +jmx.rest.client.connection.connect=CWWKX0230I: Az egy\u00fcttes tag megnyitotta az JMX \u00fcgyfelet az egy\u00fcttes vez\u00e9rl\u0151h\u00f6z: {0} +jmx.rest.client.connection.connect.explanation=A tag csatlakoztat\u00e1sra ker\u00fclt a vez\u00e9rl\u0151h\u00f6z. +jmx.rest.client.connection.connect.useraction=Semmit sem kell tennie. + +jmx.rest.client.connection.disconnect=CWWKX0231I: Az egy\u00fcttes tag lez\u00e1rta az JMX \u00fcgyfelet az egy\u00fcttes vez\u00e9rl\u0151vel: {0} +jmx.rest.client.connection.disconnect.explanation=A tag vez\u00e9rl\u0151h\u00f6z val\u00f3 csatlakoz\u00e1sa megsz\u0171nt. +jmx.rest.client.connection.disconnect.useraction=Semmit sem kell tennie. + diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_it.nlsprops b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_it.nlsprops new file mode 100755 index 00000000000..f127d779fc3 --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_it.nlsprops @@ -0,0 +1,146 @@ +# IBM Confidential +# +# OCO Source Materials +# +# Copyright IBM Corp. 2012 +# +# The source code for this program is not published or otherwise divested +# of its trade secrets, irrespective of what has been deposited with the +# U.S. Copyright Office. +# +#CMVCPATHNAME com.ibm.ws.jmx.connector.client/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages.nlsprops +#ISMESSAGEFILE TRUE +#NLS_ENCODING=UNICODE +# +#COMPONENTPREFIX CWWKX +#COMPONENTNAMEFOR CWWKX JMX REST Client +# +# NLS_MESSAGEFORMAT_VAR +# +# Strings in this file which contain replacement variables are processed by the MessageFormat +# class (single quote must be coded as 2 consecutive single quotes ''). Strings in this file +# which do NOT contain replacement variables are NOT processed by the MessageFormat class +# (single quote must be coded as one single quote '). + +# Message prefix block: CWWKX0200-CWWKX0259 + +jmx.rest.client.request.error=CWWKX0201E: Il client REST WebSphere Java Management Extensions ha rilevato un errore durante la preparazione della richiesta al server per l''URL {0} sulla connessione {1} +jmx.rest.client.request.error.explanation=Il client REST WebSphere Java Management Extensions ha rilevato un errore durante la preparazione di una richiesta per il server. +jmx.rest.client.request.error.useraction=Per ulteriori informazioni, esaminare i log del server. + +jmx.rest.client.response.error=CWWKX0202E: Il client REST WebSphere Java Management Extensions non \u00e8 riuscito ad elaborare la risposta dal server per l''URL {0} sulla connessione {1} +jmx.rest.client.response.error.explanation=Il client REST WebSphere Java Management Extensions non \u00e8 riuscito ad elaborare una risposta dal server +jmx.rest.client.response.error.useraction=Per ulteriori informazioni, esaminare i log del server. + +jmx.rest.client.response.code.error=CWWKX0203E: Il client REST WebSphere Java Management Extensions ha ricevuto un codice di risposta imprevisto {0} con il messaggio ''{1}'' dal server per l''URL {2} sulla connessione {3} +jmx.rest.client.response.code.error.explanation=Il client REST WebSphere Java Management Extensions ha ricevuto un codice di risposta imprevisto dal server +jmx.rest.client.response.code.error.useraction=Per ulteriori informazioni, esaminare i log del server. + +jmx.rest.client.server.throwable.exception=CWWKX0204E: Impossibile analizzare l'oggetto Throwable dal flusso di errori del server. +jmx.rest.client.server.throwable.exception.explanation=Il server ha generato un'eccezione durante la gestione della richiesta del client, ma il client non \u00e8 stato in grado di analizzare l'oggetto Throwable proveniente dal flusso di errori del server. La classe dell'oggetto Throwable potrebbe non essere disponibile per il client. +jmx.rest.client.server.throwable.exception.useraction=Per ulteriori informazioni, esaminare i log del server. + +jmx.rest.client.not.connected=CWWKX0206E: Il client non \u00e8 connesso al server. +jmx.rest.client.not.connected.explanation=La connessione al server \u00e8 stata chiusa o ha avuto esito negativo. +jmx.rest.client.not.connected.useraction=Controllare che la funzione connettore REST sia abilitata sul server e ottenere una nuova connessione al server. + +jmx.rest.client.url.not.found=CWWKX0207E: Il server ha notificato che l'URL richiesto dal client non \u00e8 stato trovato. +jmx.rest.client.url.not.found.explanation=\u00c8 possibile che il client abbia informazioni non aggiornate o che la funzione connettore REST sul server sia stata disabilitata. +jmx.rest.client.url.not.found.useraction=Controllare che la funzione connettore REST sia abilitata sul server e ottenere una nuova connessione al server. + +jmx.rest.client.class.name.null=CWWKX0208E: L'argomento nome classe \u00e8 null. +jmx.rest.client.class.name.null.explanation=L'argomento nome classe non deve essere null. +jmx.rest.client.class.name.null.useraction=Fornire un nome classe che non sia null durante la chiamata del metodo. + +jmx.rest.client.attribute.name.null=CWWKX0209E: L'argomento nome attributo \u00e8 null. +jmx.rest.client.attribute.name.null.explanation=L'argomento nome attributo non deve essere null. +jmx.rest.client.attribute.name.null.useraction=Fornire un nome attributo che non sia null durante la chiamata del metodo. + +jmx.rest.client.attribute.names.null=CWWKX0210E: L'argomento contenente un array di nomi attributo \u00e8 null. +jmx.rest.client.attribute.names.null.explanation=L'argomento contenente un array di nomi attributo non deve essere null. +jmx.rest.client.attribute.names.null.useraction=Fornire un array non null di nomi attributo durante la chiamata del metodo. + +jmx.rest.client.attribute.null=CWWKX0211E: L'argomento Attribute \u00e8 null. +jmx.rest.client.attribute.null.explanation=L'argomento Attribute non deve essere null. +jmx.rest.client.attribute.null.useraction=Fornire un argomento Attribute che non sia null durante la chiamata del metodo. + +jmx.rest.client.attribute.list.null=CWWKX0212E: L'argomento AttributeList \u00e8 null. +jmx.rest.client.attribute.list.null.explanation=L'argomento AttributeList non deve essere null. +jmx.rest.client.attribute.list.null.useraction=Fornire un argomento AttributeList che non sia null durante la chiamata del metodo. + +jmx.rest.client.object.name.null=CWWKX0213E: L'argomento ObjectName \u00e8 null. +jmx.rest.client.object.name.null.explanation=L'argomento ObjectName non deve essere null. +jmx.rest.client.object.name.null.useraction=Fornire un argomento ObjectName che non sia null durante la chiamata del metodo. + +jmx.rest.client.unexpected.server.throwable=CWWKX0214E: Un oggetto Throwable imprevisto \u00e8 stato restituito dal server. +jmx.rest.client.unexpected.server.throwable.explanation=L'eccezione include un oggetto Throwable restituito dal server che normalmente non \u00e8 previsto per questa operazione. +jmx.rest.client.unexpected.server.throwable.useraction=Per ulteriori informazioni, esaminare i log del server. + +jmx.rest.client.bad.credentials=CWWKX0215E: Si \u00e8 verificato un problema con il nome utente o la password forniti. Il server ha risposto con il codice {0} e il messaggio ''{1}'' +jmx.rest.client.bad.credentials.explanation=Le credenziali fornite durante il tentativo di ottenere una connessione non erano corrette. L'utente non esiste o non dispone dell'autorizzazione per accedere al server, oppure la password non \u00e8 corretta. +jmx.rest.client.bad.credentials.useraction=Correggere il nome utente o la password, quindi ottenere la connessione. + +jmx.rest.client.object.name.pattern=CWWKX0216E: L''argomento ObjectName ''{0}'' \u00e8 un pattern." +jmx.rest.client.object.name.pattern.explanation=L'argomento ObjectName \u00e8 un pattern, ma il metodo richiede un ObjectName che corrisponda esattamente a un MBean. +jmx.rest.client.object.name.pattern.useraction=Fornire un argomento ObjectName, senza caratteri jolly, che corrisponda esattamente a un MBean. + +jmx.rest.client.instance.not.found=CWWKX0217E: Nessun MBean correntemente registrato con l''ObjectName fornito ''{0}'' +jmx.rest.client.instance.not.found.explanation=L'operazione richiede un MBean registrato, ma non \u00e8 stato registrato alcun MBean con l'ObjectName fornito. +jmx.rest.client.instance.not.found.useraction=Verificare che l'MBean sia registrato prima di tentare di eseguire operazioni di gestione su esso. + +jmx.rest.client.attribute.not.found=CWWKX0218E: L''MBean ''{0}'' non dispone di un attributo con il nome ''{1}'' +jmx.rest.client.attribute.not.found.explanation=L'MBean non fornisce un attributo con il nome indicato. +jmx.rest.client.attribute.not.found.useraction=Richiamare le informazioni dell'MBean per verificare quali attributi fornisce. + +jmx.rest.client.operation.not.found=CWWKX0219E: L''MBean ''{0}'' non dispone di un''operazione con il nome ''{1}'' +jmx.rest.client.operation.not.found.explanation=L'MBean non fornisce un'operazione con il nome indicato. +jmx.rest.client.operation.not.found.useraction=Richiamare le informazioni dell'MBean per verificare quali operazioni fornisce. + +jmx.rest.client.listener.not.found=CWWKX0220E: Il NotificationListener fornito non \u00e8 correntemente registrato per ricevere notifiche dall''MBean ''{0}'' +jmx.rest.client.listener.not.found.explanation=Il NotificationListener non \u00e8 stato aggiunto o \u00e8 gi\u00e0 stato rimosso e non \u00e8 correntemente registrato per ricevere notifiche dall'MBean indicato. +jmx.rest.client.listener.not.found.useraction=Assicurarsi che il codice chiamante tenga traccia di quali NotificationListener sono stati aggiunti e rimossi o catturi e gestisca l'eccezione. + +jmx.rest.client.notification.lost=CWWKX0221I: Impossibile consegnare la notifica. +jmx.rest.client.notification.lost.explanation=Non \u00e8 stato possibile consegnare una notifica a uno o pi\u00f9 NotificationListener perch\u00e9 non \u00e8 stato trovato un NotificationListener registrato o si \u00e8 verificata un'eccezione durante la consegna della notifica. +jmx.rest.client.notification.lost.useraction=Se la notifica doveva essere consegnata a un NotificationListener registrato, cercare eventuali eccezioni nei log. + +jmx.rest.client.connection.failed=CWWKX0222I: La connessione al server ha avuto esito negativo. +jmx.rest.client.connection.failed.explanation=Il server \u00e8 diventato indisponibile e non \u00e8 tornato disponibile entro il tempo massimo consentito configurato. +jmx.rest.client.connection.failed.useraction=Controllare la connessione di rete e assicurarsi che il server sia in esecuzione con la funzione connettore REST abilitata. + +jmx.rest.client.connection.temporarily.lost=CWWKX0223I: La connessione al server \u00e8 stata temporaneamente persa. +jmx.rest.client.connection.temporarily.lost.explanation=Il server \u00e8 diventato indisponibile, ma il client tenter\u00e0 di ripristinare la connessione per la durata del tempo massimo consentito configurato. +jmx.rest.client.connection.temporarily.lost.useraction=Se il riavvio del server \u00e8 intenzionale, non sono richieste azioni. In caso contrario, controllare la connessione di rete e assicurarsi che il server sia in esecuzione con la funzione connettore REST abilitata. + +jmx.rest.client.connection.restored.with.exceptions=CWWKX0224I: La connessione \u00e8 stata ripristinata, ma si sono verificate eccezioni durante l'aggiunta dei NotificationListener. +jmx.rest.client.connection.restored.with.exceptions.explanation=La connessione al server \u00e8 stata temporaneamente persa, ma \u00e8 stata correttamente ripristinata. Si sono verificate eccezioni durante l'aggiunta dei NotificationListener, quindi \u00e8 possibile che non si ricevano alcune notifiche. +jmx.rest.client.connection.restored.with.exceptions.useraction=Controllare le eccezioni incluse con la notifica e registrare nuovamente i NotificationListener dopo aver risolto i problemi. + +jmx.rest.client.connection.restored=CWWKX0225I: La connessione \u00e8 stata ripristinata correttamente. +jmx.rest.client.connection.restored.explanation=La connessione al server \u00e8 stata temporaneamente persa, ma \u00e8 stata correttamente ripristinata. Tutti i NotificationListener registrati continueranno a ricevere le notifiche. +jmx.rest.client.connection.restored.useraction=Nessuno + +jmx.rest.client.connection.illegal.argument=CWWKX0226E: Il parametro di tipo JMXServiceURL non pu\u00f2 essere null. +jmx.rest.client.connection.illegal.argument.explanation=Il valore per il parametro 'serviceURL' non pu\u00f2 essere null. +jmx.rest.client.connection.illegal.argument.useraction=Ripetere la connessione al connettore REST JMX utilizzando un valore JMXServiceURL che non sia null. + +jmx.rest.client.connection.invalid.endpoint=CWWKX0227E: Il seguente valore endpoint non \u00e8 valido: {0} +jmx.rest.client.connection.invalid.endpoint.explanation=Il valore endpoint specificato non \u00e8 valido. +jmx.rest.client.connection.invalid.endpoint.useraction=Ripetere la connessione al connettore REST JMX utilizzando un valore endpoint valido di tipo stringa e nel formato "host:porta". + +jmx.rest.client.connection.no.endpoints=CWWKX0228E: Impossibile trovare endpoint disponibili per inizializzare il connettore. +jmx.rest.client.connection.no.endpoints.explanation=Nessuno degli endpoint specificati era disponibile durante l'inizializzazione del connettore REST JMX. +jmx.rest.client.connection.no.endpoints.useraction=Ripetere la connessione al connettore REST JMX utilizzando almeno un endpoint disponibile. + +jmx.rest.client.bad.user.credentials=CWWKX0229E: Si \u00e8 verificato un problema con le credenziali utente fornite. Il server ha risposto con il codice {0} e il messaggio ''{1}'' +jmx.rest.client.bad.user.credentials.explanation=Le credenziali utente fornite non sono corrette, sono scadute, incomplete oppure non dispongono dell'autorizzazione. +jmx.rest.client.bad.user.credentials.useraction=Verificare che le credenziali utente dispongano dell'autenticazione e dell'autorizzazione corrette, quindi ottenere una nuova connessione. + +jmx.rest.client.connection.connect=CWWKX0230I: Il membro collective ha aperto il client JMX sul collective controller: {0} +jmx.rest.client.connection.connect.explanation=Il membro \u00e8 connesso al controllore. +jmx.rest.client.connection.connect.useraction=Nessuna azione richiesta. + +jmx.rest.client.connection.disconnect=CWWKX0231I: Il membro collective ha chiuso il client JMX dal collective controller: {0} +jmx.rest.client.connection.disconnect.explanation=Il membro \u00e8 disconnesso dal controllore. +jmx.rest.client.connection.disconnect.useraction=Nessuna azione richiesta. + diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_ja.nlsprops b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_ja.nlsprops new file mode 100755 index 00000000000..fd285d2741d --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_ja.nlsprops @@ -0,0 +1,146 @@ +# IBM Confidential +# +# OCO Source Materials +# +# Copyright IBM Corp. 2012 +# +# The source code for this program is not published or otherwise divested +# of its trade secrets, irrespective of what has been deposited with the +# U.S. Copyright Office. +# +#CMVCPATHNAME com.ibm.ws.jmx.connector.client/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages.nlsprops +#ISMESSAGEFILE TRUE +#NLS_ENCODING=UNICODE +# +#COMPONENTPREFIX CWWKX +#COMPONENTNAMEFOR CWWKX JMX REST Client +# +# NLS_MESSAGEFORMAT_VAR +# +# Strings in this file which contain replacement variables are processed by the MessageFormat +# class (single quote must be coded as 2 consecutive single quotes ''). Strings in this file +# which do NOT contain replacement variables are NOT processed by the MessageFormat class +# (single quote must be coded as one single quote '). + +# Message prefix block: CWWKX0200-CWWKX0259 + +jmx.rest.client.request.error=CWWKX0201E: WebSphere Java Management Extensions REST \u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u304c\u3001\u63a5\u7d9a {1} \u4e0a\u306e URL {0} \u306b\u95a2\u3059\u308b\u30b5\u30fc\u30d0\u30fc\u3078\u306e\u8981\u6c42\u306e\u6e96\u5099\u4e2d\u306b\u30a8\u30e9\u30fc\u3092\u691c\u51fa\u3057\u307e\u3057\u305f\u3002 +jmx.rest.client.request.error.explanation=WebSphere Java Management Extensions REST \u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u304c\u3001\u30b5\u30fc\u30d0\u30fc\u3078\u306e\u8981\u6c42\u306e\u6e96\u5099\u4e2d\u306b\u30a8\u30e9\u30fc\u3092\u691c\u51fa\u3057\u307e\u3057\u305f\u3002 +jmx.rest.client.request.error.useraction=\u3055\u3089\u306a\u308b\u60c5\u5831\u304c\u306a\u3044\u304b\u3001\u30b5\u30fc\u30d0\u30fc\u30fb\u30ed\u30b0\u3092\u8abf\u3079\u3066\u304f\u3060\u3055\u3044\u3002 + +jmx.rest.client.response.error=CWWKX0202E: WebSphere Java Management Extensions REST \u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u304c\u3001\u63a5\u7d9a {1} \u4e0a\u306e URL {0} \u306b\u95a2\u3059\u308b\u30b5\u30fc\u30d0\u30fc\u304b\u3089\u306e\u5fdc\u7b54\u3092\u51e6\u7406\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +jmx.rest.client.response.error.explanation=WebSphere Java Management Extensions REST \u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u304c\u3001\u30b5\u30fc\u30d0\u30fc\u304b\u3089\u306e\u5fdc\u7b54\u3092\u51e6\u7406\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +jmx.rest.client.response.error.useraction=\u3055\u3089\u306a\u308b\u60c5\u5831\u304c\u306a\u3044\u304b\u3001\u30b5\u30fc\u30d0\u30fc\u30fb\u30ed\u30b0\u3092\u8abf\u3079\u3066\u304f\u3060\u3055\u3044\u3002 + +jmx.rest.client.response.code.error=CWWKX0203E: WebSphere Java Management Extensions REST \u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u304c\u3001\u30b5\u30fc\u30d0\u30fc\u304b\u3089\u63a5\u7d9a {3} \u4e0a\u306e URL {2} \u306b\u95a2\u3059\u308b\u30e1\u30c3\u30bb\u30fc\u30b8 ''{1}'' \u4ed8\u304d\u306e\u4e88\u671f\u3057\u306a\u3044\u5fdc\u7b54\u30b3\u30fc\u30c9 {0} \u3092\u53d7\u4fe1\u3057\u307e\u3057\u305f\u3002 +jmx.rest.client.response.code.error.explanation=WebSphere Java Management Extensions REST \u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u304c\u3001\u30b5\u30fc\u30d0\u30fc\u304b\u3089\u4e88\u671f\u3057\u306a\u3044\u5fdc\u7b54\u30b3\u30fc\u30c9\u3092\u53d7\u4fe1\u3057\u307e\u3057\u305f\u3002 +jmx.rest.client.response.code.error.useraction=\u3055\u3089\u306a\u308b\u60c5\u5831\u304c\u306a\u3044\u304b\u3001\u30b5\u30fc\u30d0\u30fc\u30fb\u30ed\u30b0\u3092\u8abf\u3079\u3066\u304f\u3060\u3055\u3044\u3002 + +jmx.rest.client.server.throwable.exception=CWWKX0204E: \u30b5\u30fc\u30d0\u30fc\u30fb\u30a8\u30e9\u30fc\u30fb\u30b9\u30c8\u30ea\u30fc\u30e0\u304b\u3089 Throwable \u3092\u89e3\u6790\u3067\u304d\u307e\u305b\u3093\u3002 +jmx.rest.client.server.throwable.exception.explanation=\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u8981\u6c42\u306e\u51e6\u7406\u4e2d\u306b\u30b5\u30fc\u30d0\u30fc\u3067\u4f8b\u5916\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u304c\u3001\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u306f\u30b5\u30fc\u30d0\u30fc\u30fb\u30a8\u30e9\u30fc\u30fb\u30b9\u30c8\u30ea\u30fc\u30e0\u304b\u3089 Throwable \u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u3092\u89e3\u6790\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 Throwable \u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306e\u30af\u30e9\u30b9\u304c\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u3067\u4f7f\u7528\u3067\u304d\u306a\u3044\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002 +jmx.rest.client.server.throwable.exception.useraction=\u3055\u3089\u306a\u308b\u60c5\u5831\u304c\u306a\u3044\u304b\u3001\u30b5\u30fc\u30d0\u30fc\u30fb\u30ed\u30b0\u3092\u8abf\u3079\u3066\u304f\u3060\u3055\u3044\u3002 + +jmx.rest.client.not.connected=CWWKX0206E: \u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u306f\u30b5\u30fc\u30d0\u30fc\u306b\u63a5\u7d9a\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002 +jmx.rest.client.not.connected.explanation=\u30b5\u30fc\u30d0\u30fc\u3078\u306e\u63a5\u7d9a\u304c\u30af\u30ed\u30fc\u30ba\u3057\u305f\u304b\u3001\u307e\u305f\u306f\u5931\u6557\u3057\u307e\u3057\u305f\u3002 +jmx.rest.client.not.connected.useraction=REST \u30b3\u30cd\u30af\u30bf\u30fc\u30fb\u30d5\u30a3\u30fc\u30c1\u30e3\u30fc\u304c\u30b5\u30fc\u30d0\u30fc\u4e0a\u3067\u4f7f\u7528\u53ef\u80fd\u306b\u306a\u3063\u3066\u3044\u308b\u3053\u3068\u3092\u78ba\u8a8d\u3057\u3001\u30b5\u30fc\u30d0\u30fc\u3078\u306e\u65b0\u898f\u63a5\u7d9a\u3092\u53d6\u5f97\u3057\u3066\u304f\u3060\u3055\u3044\u3002 + +jmx.rest.client.url.not.found=CWWKX0207E: \u30b5\u30fc\u30d0\u30fc\u3067\u3001\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u306b\u3088\u3063\u3066\u8981\u6c42\u3055\u308c\u305f URL \u304c\u898b\u3064\u304b\u3089\u306a\u3044\u3053\u3068\u304c\u5831\u544a\u3055\u308c\u307e\u3057\u305f\u3002 +jmx.rest.client.url.not.found.explanation=\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u306b\u53e4\u3044\u60c5\u5831\u304c\u4fdd\u6301\u3055\u308c\u3066\u3044\u308b\u304b\u3001\u307e\u305f\u306f\u30b5\u30fc\u30d0\u30fc\u4e0a\u306e REST \u30b3\u30cd\u30af\u30bf\u30fc\u30fb\u30d5\u30a3\u30fc\u30c1\u30e3\u30fc\u304c\u4f7f\u7528\u4e0d\u53ef\u306b\u306a\u3063\u3066\u3044\u308b\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002 +jmx.rest.client.url.not.found.useraction=REST \u30b3\u30cd\u30af\u30bf\u30fc\u30fb\u30d5\u30a3\u30fc\u30c1\u30e3\u30fc\u304c\u30b5\u30fc\u30d0\u30fc\u4e0a\u3067\u4f7f\u7528\u53ef\u80fd\u306b\u306a\u3063\u3066\u3044\u308b\u3053\u3068\u3092\u78ba\u8a8d\u3057\u3001\u30b5\u30fc\u30d0\u30fc\u3078\u306e\u65b0\u898f\u63a5\u7d9a\u3092\u53d6\u5f97\u3057\u3066\u304f\u3060\u3055\u3044\u3002 + +jmx.rest.client.class.name.null=CWWKX0208E: \u30af\u30e9\u30b9\u540d\u5f15\u6570\u304c NULL \u3067\u3057\u305f\u3002 +jmx.rest.client.class.name.null.explanation=\u30af\u30e9\u30b9\u540d\u5f15\u6570\u3092 NULL \u306b\u3059\u308b\u3053\u3068\u306f\u3067\u304d\u307e\u305b\u3093\u3002 +jmx.rest.client.class.name.null.useraction=\u30e1\u30bd\u30c3\u30c9\u306e\u547c\u3073\u51fa\u3057\u6642\u306b NULL \u4ee5\u5916\u306e\u30af\u30e9\u30b9\u540d\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002 + +jmx.rest.client.attribute.name.null=CWWKX0209E: \u5c5e\u6027\u540d\u5f15\u6570\u304c NULL \u3067\u3057\u305f\u3002 +jmx.rest.client.attribute.name.null.explanation=\u5c5e\u6027\u540d\u5f15\u6570\u3092 NULL \u306b\u3059\u308b\u3053\u3068\u306f\u3067\u304d\u307e\u305b\u3093\u3002 +jmx.rest.client.attribute.name.null.useraction=\u30e1\u30bd\u30c3\u30c9\u306e\u547c\u3073\u51fa\u3057\u6642\u306b NULL \u4ee5\u5916\u306e\u5c5e\u6027\u540d\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002 + +jmx.rest.client.attribute.names.null=CWWKX0210E: \u5c5e\u6027\u540d\u306e\u914d\u5217\u3092\u542b\u3080\u5f15\u6570\u304c NULL \u3067\u3057\u305f\u3002 +jmx.rest.client.attribute.names.null.explanation=\u5c5e\u6027\u540d\u306e\u914d\u5217\u3092\u542b\u3080\u5f15\u6570\u3092 NULL \u306b\u3059\u308b\u3053\u3068\u306f\u3067\u304d\u307e\u305b\u3093\u3002 +jmx.rest.client.attribute.names.null.useraction=\u30e1\u30bd\u30c3\u30c9\u306e\u547c\u3073\u51fa\u3057\u6642\u306b NULL \u4ee5\u5916\u306e\u5c5e\u6027\u540d\u306e\u914d\u5217\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002 + +jmx.rest.client.attribute.null=CWWKX0211E: Attribute \u5f15\u6570\u304c NULL \u3067\u3057\u305f\u3002 +jmx.rest.client.attribute.null.explanation=Attribute \u5f15\u6570\u3092 NULL \u306b\u3059\u308b\u3053\u3068\u306f\u3067\u304d\u307e\u305b\u3093\u3002 +jmx.rest.client.attribute.null.useraction=\u30e1\u30bd\u30c3\u30c9\u306e\u547c\u3073\u51fa\u3057\u6642\u306b NULL \u4ee5\u5916\u306e Attribute \u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002 + +jmx.rest.client.attribute.list.null=CWWKX0212E: AttributeList \u5f15\u6570\u304c NULL \u3067\u3057\u305f\u3002 +jmx.rest.client.attribute.list.null.explanation=AttributeList \u5f15\u6570\u3092 NULL \u306b\u3059\u308b\u3053\u3068\u306f\u3067\u304d\u307e\u305b\u3093\u3002 +jmx.rest.client.attribute.list.null.useraction=\u30e1\u30bd\u30c3\u30c9\u306e\u547c\u3073\u51fa\u3057\u6642\u306b NULL \u4ee5\u5916\u306e AttributeList \u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002 + +jmx.rest.client.object.name.null=CWWKX0213E: ObjectName \u5f15\u6570\u304c NULL \u3067\u3057\u305f\u3002 +jmx.rest.client.object.name.null.explanation=ObjectName \u5f15\u6570\u3092 NULL \u306b\u3059\u308b\u3053\u3068\u306f\u3067\u304d\u307e\u305b\u3093\u3002 +jmx.rest.client.object.name.null.useraction=\u30e1\u30bd\u30c3\u30c9\u306e\u547c\u3073\u51fa\u3057\u6642\u306b NULL \u4ee5\u5916\u306e ObjectName \u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002 + +jmx.rest.client.unexpected.server.throwable=CWWKX0214E: \u30b5\u30fc\u30d0\u30fc\u304b\u3089\u4e88\u671f\u3057\u306a\u3044 Throwable \u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u304c\u8fd4\u3055\u308c\u307e\u3057\u305f\u3002 +jmx.rest.client.unexpected.server.throwable.explanation=\u30b5\u30fc\u30d0\u30fc\u304b\u3089\u8fd4\u3055\u308c\u305f\u3001\u3053\u306e\u64cd\u4f5c\u306b\u5bfe\u3057\u3066\u901a\u5e38\u306f\u4e88\u671f\u3055\u308c\u306a\u3044 Throwable \u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u304c\u4f8b\u5916\u306b\u3088\u308a\u30e9\u30c3\u30d7\u3055\u308c\u3066\u3044\u307e\u3059\u3002 +jmx.rest.client.unexpected.server.throwable.useraction=\u3055\u3089\u306a\u308b\u60c5\u5831\u304c\u306a\u3044\u304b\u3001\u30b5\u30fc\u30d0\u30fc\u30fb\u30ed\u30b0\u3092\u8abf\u3079\u3066\u304f\u3060\u3055\u3044\u3002 + +jmx.rest.client.bad.credentials=CWWKX0215E: \u6307\u5b9a\u3057\u305f\u30e6\u30fc\u30b6\u30fc\u540d\u307e\u305f\u306f\u30d1\u30b9\u30ef\u30fc\u30c9\u306b\u554f\u984c\u304c\u3042\u308a\u307e\u3059\u3002 \u30b5\u30fc\u30d0\u30fc\u306f\u3001\u30b3\u30fc\u30c9 {0}\u3001\u30e1\u30c3\u30bb\u30fc\u30b8 ''{1}'' \u3067\u5fdc\u7b54\u3057\u307e\u3057\u305f +jmx.rest.client.bad.credentials.explanation=\u63a5\u7d9a\u306e\u53d6\u5f97\u6642\u306b\u6307\u5b9a\u3057\u305f\u8cc7\u683c\u60c5\u5831\u306b\u8aa4\u308a\u304c\u3042\u308a\u307e\u3057\u305f\u3002 \u30e6\u30fc\u30b6\u30fc\u304c\u5b58\u5728\u3057\u306a\u3044\u304b\u3001\u30e6\u30fc\u30b6\u30fc\u306b\u30b5\u30fc\u30d0\u30fc\u3078\u306e\u30a2\u30af\u30bb\u30b9\u6a29\u9650\u304c\u306a\u3044\u304b\u3001\u307e\u305f\u306f\u30d1\u30b9\u30ef\u30fc\u30c9\u306b\u8aa4\u308a\u304c\u3042\u308b\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002 +jmx.rest.client.bad.credentials.useraction=\u30e6\u30fc\u30b6\u30fc\u540d\u307e\u305f\u306f\u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u8a02\u6b63\u3057\u3066\u304b\u3089\u65b0\u898f\u63a5\u7d9a\u3092\u53d6\u5f97\u3057\u3066\u304f\u3060\u3055\u3044\u3002 + +jmx.rest.client.object.name.pattern=CWWKX0216E: ObjectName \u5f15\u6570 ''{0}'' \u306f\u30d1\u30bf\u30fc\u30f3\u3067\u3059\u3002 +jmx.rest.client.object.name.pattern.explanation=ObjectName \u5f15\u6570\u304c\u30d1\u30bf\u30fc\u30f3\u306b\u306a\u3063\u3066\u3044\u307e\u3059\u304c\u3001\u30e1\u30bd\u30c3\u30c9\u306b\u306f\u30011 \u3064\u306e MBean \u3068\u5b8c\u5168\u306b\u4e00\u81f4\u3059\u308b ObjectName \u304c\u5fc5\u8981\u3067\u3059\u3002 +jmx.rest.client.object.name.pattern.useraction=1 \u3064\u306e MBean \u3068\u5b8c\u5168\u306b\u4e00\u81f4\u3059\u308b\u3001\u30ef\u30a4\u30eb\u30c9\u30ab\u30fc\u30c9\u306a\u3057\u306e ObjectName \u5f15\u6570\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002 + +jmx.rest.client.instance.not.found=CWWKX0217E: \u6307\u5b9a\u3055\u308c\u305f ObjectName ''{0}'' \u306b\u73fe\u5728\u767b\u9332\u6e08\u307f\u306e MBean \u306f\u3042\u308a\u307e\u305b\u3093 +jmx.rest.client.instance.not.found.explanation=\u3053\u306e\u64cd\u4f5c\u306b\u306f\u767b\u9332\u6e08\u307f\u306e MBean \u304c\u5fc5\u8981\u3067\u3059\u304c\u3001\u6307\u5b9a\u3055\u308c\u305f ObjectName \u306e MBean \u306f\u767b\u9332\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +jmx.rest.client.instance.not.found.useraction=MBean \u304c\u767b\u9332\u6e08\u307f\u3067\u3042\u308b\u3053\u3068\u3092\u78ba\u8a8d\u3057\u3066\u304b\u3089\u3001\u3053\u308c\u306b\u5bfe\u3059\u308b\u7ba1\u7406\u64cd\u4f5c\u3092\u5b9f\u884c\u3057\u3066\u307f\u3066\u304f\u3060\u3055\u3044\u3002 + +jmx.rest.client.attribute.not.found=CWWKX0218E: MBean ''{0}'' \u306b ''{1}'' \u3068\u3044\u3046\u540d\u524d\u306e\u5c5e\u6027\u306f\u3042\u308a\u307e\u305b\u3093 +jmx.rest.client.attribute.not.found.explanation=\u6307\u5b9a\u3055\u308c\u305f\u540d\u524d\u306e\u5c5e\u6027\u306f MBean \u3067\u306f\u63d0\u4f9b\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002 +jmx.rest.client.attribute.not.found.useraction=MBean \u60c5\u5831\u3092\u53d6\u5f97\u3057\u3066\u3001MBean \u304c\u63d0\u4f9b\u3059\u308b\u5c5e\u6027\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002 + +jmx.rest.client.operation.not.found=CWWKX0219E: MBean ''{0}'' \u306b ''{1}'' \u3068\u3044\u3046\u540d\u524d\u306e\u64cd\u4f5c\u306f\u3042\u308a\u307e\u305b\u3093 +jmx.rest.client.operation.not.found.explanation=\u6307\u5b9a\u3055\u308c\u305f\u540d\u524d\u306e\u64cd\u4f5c\u306f MBean \u3067\u306f\u63d0\u4f9b\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002 +jmx.rest.client.operation.not.found.useraction=MBean \u60c5\u5831\u3092\u53d6\u5f97\u3057\u3066\u3001MBean \u304c\u63d0\u4f9b\u3059\u308b\u64cd\u4f5c\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002 + +jmx.rest.client.listener.not.found=CWWKX0220E: \u6307\u5b9a\u3055\u308c\u305f NotificationListener \u306f\u73fe\u5728\u3001MBean ''{0}'' \u304b\u3089\u306e\u901a\u77e5\u3092\u53d7\u3051\u53d6\u308b\u3088\u3046\u306b\u767b\u9332\u3055\u308c\u3066\u3044\u307e\u305b\u3093 +jmx.rest.client.listener.not.found.explanation=NotificationListener \u304c\u8ffd\u52a0\u3055\u308c\u3066\u3044\u306a\u3044\u304b\u3001\u307e\u305f\u306f\u65e2\u306b\u524a\u9664\u3055\u308c\u3066\u3044\u308b\u305f\u3081\u3001\u73fe\u5728\u3001\u6307\u5b9a\u3055\u308c\u305f MBean \u304b\u3089\u306e\u901a\u77e5\u3092\u53d7\u3051\u53d6\u308b\u3088\u3046\u306b\u767b\u9332\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002 +jmx.rest.client.listener.not.found.useraction=\u547c\u3073\u51fa\u3057\u30b3\u30fc\u30c9\u3067\u3001\u3069\u306e NotificationListener \u304c\u8ffd\u52a0\u304a\u3088\u3073\u524a\u9664\u3055\u308c\u305f\u304b\u3092\u8ffd\u8de1\u3059\u308b\u3088\u3046\u306b\u3059\u308b\u304b\u3001\u307e\u305f\u306f\u4f8b\u5916\u3092\u30ad\u30e3\u30c3\u30c1\u3057\u3066\u51e6\u7406\u3057\u3066\u304f\u3060\u3055\u3044\u3002 + +jmx.rest.client.notification.lost=CWWKX0221I: \u901a\u77e5\u3092\u9001\u4fe1\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +jmx.rest.client.notification.lost.explanation=\u767b\u9332\u6e08\u307f\u306e NotificationListener \u304c\u898b\u3064\u304b\u3089\u306a\u304b\u3063\u305f\u304b\u3001\u901a\u77e5\u306e\u9001\u4fe1\u4e2d\u306b\u4f8b\u5916\u304c\u767a\u751f\u3057\u305f\u305f\u3081\u30011 \u3064\u4ee5\u4e0a\u306e NotificationListener \u306b\u3053\u306e\u901a\u77e5\u3092\u9001\u4fe1\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +jmx.rest.client.notification.lost.useraction=\u767b\u9332\u6e08\u307f\u306e NotificationListener \u306b\u901a\u77e5\u304c\u9001\u4fe1\u3055\u308c\u3066\u3044\u306a\u3051\u308c\u3070\u306a\u3089\u306a\u3044\u5834\u5408\u306f\u3001\u4f8b\u5916\u304c\u306a\u3044\u304b\u30ed\u30b0\u3092\u8abf\u3079\u3066\u304f\u3060\u3055\u3044\u3002 + +jmx.rest.client.connection.failed=CWWKX0222I: \u30b5\u30fc\u30d0\u30fc\u3078\u306e\u63a5\u7d9a\u304c\u5931\u6557\u3057\u307e\u3057\u305f\u3002 +jmx.rest.client.connection.failed.explanation=\u30b5\u30fc\u30d0\u30fc\u304c\u4f7f\u7528\u4e0d\u53ef\u306b\u306a\u308a\u3001\u3055\u3089\u306b\u3001\u69cb\u6210\u6e08\u307f\u306e\u6700\u5927\u8a31\u5bb9\u6642\u9593\u5185\u306b\u518d\u5ea6\u4f7f\u7528\u53ef\u80fd\u306b\u306a\u308a\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +jmx.rest.client.connection.failed.useraction=\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u63a5\u7d9a\u3092\u78ba\u8a8d\u3057\u3001REST \u30b3\u30cd\u30af\u30bf\u30fc\u30fb\u30d5\u30a3\u30fc\u30c1\u30e3\u30fc\u304c\u4f7f\u7528\u53ef\u80fd\u306a\u72b6\u614b\u3067\u30b5\u30fc\u30d0\u30fc\u304c\u7a3c\u50cd\u3057\u3066\u3044\u308b\u3053\u3068\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002 + +jmx.rest.client.connection.temporarily.lost=CWWKX0223I: \u30b5\u30fc\u30d0\u30fc\u3078\u306e\u63a5\u7d9a\u304c\u4e00\u6642\u7684\u306b\u5931\u308f\u308c\u307e\u3057\u305f\u3002 +jmx.rest.client.connection.temporarily.lost.explanation=\u30b5\u30fc\u30d0\u30fc\u306f\u4f7f\u7528\u4e0d\u53ef\u306b\u306a\u308a\u307e\u3057\u305f\u304c\u3001\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u306f\u69cb\u6210\u6e08\u307f\u306e\u6700\u5927\u8a31\u5bb9\u6642\u9593\u4e2d\u306b\u63a5\u7d9a\u306e\u5fa9\u5143\u3092\u8a66\u884c\u3057\u307e\u3059\u3002 +jmx.rest.client.connection.temporarily.lost.useraction=\u30b5\u30fc\u30d0\u30fc\u304c\u610f\u56f3\u7684\u306b\u518d\u59cb\u52d5\u3057\u3066\u3044\u308b\u5834\u5408\u3001\u51e6\u7f6e\u306f\u4e0d\u8981\u3067\u3059\u3002 \u305d\u308c\u4ee5\u5916\u306e\u5834\u5408\u306b\u306f\u3001\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u63a5\u7d9a\u3092\u78ba\u8a8d\u3057\u3001REST \u30b3\u30cd\u30af\u30bf\u30fc\u30fb\u30d5\u30a3\u30fc\u30c1\u30e3\u30fc\u304c\u4f7f\u7528\u53ef\u80fd\u306a\u72b6\u614b\u3067\u30b5\u30fc\u30d0\u30fc\u304c\u7a3c\u50cd\u3057\u3066\u3044\u308b\u3053\u3068\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002 + +jmx.rest.client.connection.restored.with.exceptions=CWWKX0224I: \u63a5\u7d9a\u306f\u5fa9\u5143\u3055\u308c\u307e\u3057\u305f\u304c\u3001NotificationListener \u306e\u8ffd\u52a0\u6642\u306b\u4f8b\u5916\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +jmx.rest.client.connection.restored.with.exceptions.explanation=\u30b5\u30fc\u30d0\u30fc\u3078\u306e\u63a5\u7d9a\u306f\u4e00\u6642\u7684\u306b\u5931\u308f\u308c\u307e\u3057\u305f\u304c\u3001\u6b63\u5e38\u306b\u5fa9\u5143\u3055\u308c\u307e\u3057\u305f\u3002 NotificationListener \u306e\u8ffd\u52a0\u6642\u306b\u4f8b\u5916\u304c\u767a\u751f\u3057\u305f\u305f\u3081\u3001\u4e00\u90e8\u306e\u901a\u77e5\u304c\u53d7\u3051\u53d6\u3089\u308c\u3066\u3044\u306a\u3044\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002 +jmx.rest.client.connection.restored.with.exceptions.useraction=\u901a\u77e5\u306b\u542b\u307e\u308c\u3066\u3044\u308b\u4f8b\u5916\u3092\u78ba\u8a8d\u3057\u3001\u554f\u984c\u306e\u8a02\u6b63\u5f8c\u306b NotificationListener \u3092\u518d\u767b\u9332\u3057\u3066\u304f\u3060\u3055\u3044\u3002 + +jmx.rest.client.connection.restored=CWWKX0225I: \u63a5\u7d9a\u304c\u6b63\u5e38\u306b\u5fa9\u5143\u3055\u308c\u307e\u3057\u305f\u3002 +jmx.rest.client.connection.restored.explanation=\u30b5\u30fc\u30d0\u30fc\u3078\u306e\u63a5\u7d9a\u306f\u4e00\u6642\u7684\u306b\u5931\u308f\u308c\u307e\u3057\u305f\u304c\u3001\u6b63\u5e38\u306b\u5fa9\u5143\u3055\u308c\u307e\u3057\u305f\u3002 \u767b\u9332\u6e08\u307f\u306e NotificationListener \u306f\u5f15\u304d\u7d9a\u304d\u901a\u77e5\u306e\u53d7\u3051\u53d6\u308a\u3092\u884c\u3044\u307e\u3059\u3002 +jmx.rest.client.connection.restored.useraction=\u306a\u3057 + +jmx.rest.client.connection.illegal.argument=CWWKX0226E: \u30bf\u30a4\u30d7 JMXServiceURL \u306e\u30d1\u30e9\u30e1\u30fc\u30bf\u30fc\u306f\u30cc\u30eb\u306b\u3059\u308b\u3053\u3068\u306f\u3067\u304d\u307e\u305b\u3093\u3002 +jmx.rest.client.connection.illegal.argument.explanation=\u30d1\u30e9\u30e1\u30fc\u30bf\u30fc\u300cserviceURL\u300d\u306e\u5024\u3092\u30cc\u30eb\u306b\u3059\u308b\u3053\u3068\u306f\u3067\u304d\u307e\u305b\u3093\u3002 +jmx.rest.client.connection.illegal.argument.useraction=\u30cc\u30eb\u4ee5\u5916\u306e JMXServiceURL \u306e\u5024\u3092\u4f7f\u7528\u3057\u3066 JMX REST \u30b3\u30cd\u30af\u30bf\u30fc\u306b\u518d\u63a5\u7d9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002 + +jmx.rest.client.connection.invalid.endpoint=CWWKX0227E: \u6b21\u306e\u5024\u306f\u6709\u52b9\u306a\u30a8\u30f3\u30c9\u30dd\u30a4\u30f3\u30c8\u5024\u3067\u306f\u3042\u308a\u307e\u305b\u3093: {0} +jmx.rest.client.connection.invalid.endpoint.explanation=\u6307\u5b9a\u3055\u308c\u305f\u30a8\u30f3\u30c9\u30dd\u30a4\u30f3\u30c8\u5024\u304c\u7121\u52b9\u3067\u3059\u3002 +jmx.rest.client.connection.invalid.endpoint.useraction=\u30bf\u30a4\u30d7\u304c\u30b9\u30c8\u30ea\u30f3\u30b0\u3067\u3001\u300chost:port\u300d\u306e\u5f62\u5f0f\u306e\u6709\u52b9\u306a\u30a8\u30f3\u30c9\u30dd\u30a4\u30f3\u30c8\u5024\u3092\u4f7f\u7528\u3057\u3066 JMX REST \u30b3\u30cd\u30af\u30bf\u30fc\u306b\u518d\u63a5\u7d9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002 + +jmx.rest.client.connection.no.endpoints=CWWKX0228E: \u30b3\u30cd\u30af\u30bf\u30fc\u3092\u521d\u671f\u8a2d\u5b9a\u3059\u308b\u305f\u3081\u306b\u4f7f\u7528\u53ef\u80fd\u306a\u30a8\u30f3\u30c9\u30dd\u30a4\u30f3\u30c8\u3092\u898b\u3064\u3051\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +jmx.rest.client.connection.no.endpoints.explanation=\u6307\u5b9a\u3055\u308c\u305f\u30a8\u30f3\u30c9\u30dd\u30a4\u30f3\u30c8\u306f\u3001JMX REST \u30b3\u30cd\u30af\u30bf\u30fc\u306e\u521d\u671f\u8a2d\u5b9a\u6642\u306b\u3044\u305a\u308c\u3082\u4f7f\u7528\u53ef\u80fd\u3067\u3042\u308a\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +jmx.rest.client.connection.no.endpoints.useraction=\u4f7f\u7528\u53ef\u80fd\u306a\u30a8\u30f3\u30c9\u30dd\u30a4\u30f3\u30c8\u3092\u5c11\u306a\u304f\u3068\u3082 1 \u3064\u4f7f\u7528\u3057\u3066 JMX REST \u30b3\u30cd\u30af\u30bf\u30fc\u306b\u518d\u63a5\u7d9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002 + +jmx.rest.client.bad.user.credentials=CWWKX0229E: \u6307\u5b9a\u3057\u305f\u30e6\u30fc\u30b6\u30fc\u8cc7\u683c\u60c5\u5831\u306b\u554f\u984c\u304c\u3042\u308a\u307e\u3057\u305f\u3002 \u30b5\u30fc\u30d0\u30fc\u306f\u3001\u30b3\u30fc\u30c9 {0}\u3001\u30e1\u30c3\u30bb\u30fc\u30b8 ''{1}'' \u3067\u5fdc\u7b54\u3057\u307e\u3057\u305f +jmx.rest.client.bad.user.credentials.explanation=\u6307\u5b9a\u3055\u308c\u305f\u8cc7\u683c\u60c5\u5831\u306f\u3001\u8aa4\u3063\u3066\u3044\u308b\u304b\u3001\u6709\u52b9\u671f\u9650\u304c\u5207\u308c\u3066\u3044\u308b\u304b\u3001\u4e0d\u5b8c\u5168\u3067\u3042\u308b\u304b\u3001\u307e\u305f\u306f\u8a31\u53ef\u304c\u62d2\u5426\u3055\u308c\u3066\u3044\u307e\u3059\u3002 +jmx.rest.client.bad.user.credentials.useraction=\u30e6\u30fc\u30b6\u30fc\u8cc7\u683c\u60c5\u5831\u304c\u3001\u6b63\u3057\u304f\u8a8d\u8a3c\u304a\u3088\u3073\u8a31\u53ef\u3055\u308c\u308b\u3082\u306e\u3067\u3042\u308b\u3053\u3068\u3092\u78ba\u8a8d\u3057\u3066\u304b\u3089\u3001\u65b0\u898f\u63a5\u7d9a\u3092\u53d6\u5f97\u3057\u3066\u304f\u3060\u3055\u3044\u3002 + +jmx.rest.client.connection.connect=CWWKX0230I: \u96c6\u5408\u30e1\u30f3\u30d0\u30fc\u306f\u3001\u96c6\u5408\u30b3\u30f3\u30c8\u30ed\u30fc\u30e9\u30fc\u306b\u5bfe\u3057\u3066 JMX \u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u3092\u958b\u304d\u307e\u3057\u305f: {0} +jmx.rest.client.connection.connect.explanation=\u30e1\u30f3\u30d0\u30fc\u304c\u30b3\u30f3\u30c8\u30ed\u30fc\u30e9\u30fc\u306b\u63a5\u7d9a\u3057\u307e\u3057\u305f\u3002 +jmx.rest.client.connection.connect.useraction=\u30a2\u30af\u30b7\u30e7\u30f3\u306f\u4e0d\u8981\u3067\u3059\u3002 + +jmx.rest.client.connection.disconnect=CWWKX0231I: \u96c6\u5408\u30e1\u30f3\u30d0\u30fc\u306f\u3001\u96c6\u5408\u30b3\u30f3\u30c8\u30ed\u30fc\u30e9\u30fc\u304b\u3089\u306e JMX \u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u3092\u9589\u3058\u307e\u3057\u305f: {0} +jmx.rest.client.connection.disconnect.explanation=\u30e1\u30f3\u30d0\u30fc\u304c\u30b3\u30f3\u30c8\u30ed\u30fc\u30e9\u30fc\u3068\u306e\u63a5\u7d9a\u3092\u5207\u65ad\u3057\u307e\u3057\u305f\u3002 +jmx.rest.client.connection.disconnect.useraction=\u30a2\u30af\u30b7\u30e7\u30f3\u306f\u4e0d\u8981\u3067\u3059\u3002 + diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_ko.nlsprops b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_ko.nlsprops new file mode 100755 index 00000000000..5b0b222d7fb --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_ko.nlsprops @@ -0,0 +1,144 @@ +# IBM Confidential +# +# OCO Source Materials +# +# Copyright IBM Corp. 2012 +# +# The source code for this program is not published or otherwise divested +# of its trade secrets, irrespective of what has been deposited with the +# U.S. Copyright Office. +# +#CMVCPATHNAME com.ibm.ws.jmx.connector.client/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages.nlsprops +#ISMESSAGEFILE TRUE +#NLS_ENCODING=UNICODE +# +#COMPONENTPREFIX CWWKX +#COMPONENTNAMEFOR CWWKX JMX REST Client +# +# NLS_MESSAGEFORMAT_VAR +# +# Strings in this file which contain replacement variables are processed by the MessageFormat +# class (single quote must be coded as 2 consecutive single quotes ''). Strings in this file +# which do NOT contain replacement variables are NOT processed by the MessageFormat class +# (single quote must be coded as one single quote '). + +# Message prefix block: CWWKX0200-CWWKX0259 + +jmx.rest.client.request.error=CWWKX0201E: WebSphere Java Management Extensions REST \ud074\ub77c\uc774\uc5b8\ud2b8\uac00 \uc5f0\uacb0 {1}\uc5d0\uc11c URL {0}\uc758 \uc11c\ubc84\ub85c \uc694\uccad\uc744 \uc900\ube44\ud558\ub294 \ub3d9\uc548 \uc624\ub958\uac00 \ubc1c\uc0dd\ud588\uc2b5\ub2c8\ub2e4. +jmx.rest.client.request.error.explanation=WebSphere Java Management Extensions REST \ud074\ub77c\uc774\uc5b8\ud2b8\uac00 \uc11c\ubc84\uc758 \uc694\uccad\uc744 \uc900\ube44\ud558\ub294 \ub3d9\uc548 \uc624\ub958\uac00 \ubc1c\uc0dd\ud588\uc2b5\ub2c8\ub2e4. +jmx.rest.client.request.error.useraction=\uc790\uc138\ud55c \uc815\ubcf4\ub294 \uc11c\ubc84 \ub85c\uadf8\ub97c \uc0b4\ud3b4\ubcf4\uc2ed\uc2dc\uc624. + +jmx.rest.client.response.error=CWWKX0202E: WebSphere Java Management Extensions REST \ud074\ub77c\uc774\uc5b8\ud2b8\uac00 \uc5f0\uacb0 {1}\uc5d0\uc11c URL {0}\uc758 \uc11c\ubc84\uc5d0\uc11c \uc751\ub2f5\uc744 \ucc98\ub9ac\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. +jmx.rest.client.response.error.explanation=WebSphere Java Management Extensions REST \ud074\ub77c\uc774\uc5b8\ud2b8\uac00 \uc11c\ubc84\uc5d0\uc11c \uc751\ub2f5\uc744 \ucc98\ub9ac\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. +jmx.rest.client.response.error.useraction=\uc790\uc138\ud55c \uc815\ubcf4\ub294 \uc11c\ubc84 \ub85c\uadf8\ub97c \uc0b4\ud3b4\ubcf4\uc2ed\uc2dc\uc624. + +jmx.rest.client.response.code.error=CWWKX0203E: WebSphere Java Management Extensions REST \ud074\ub77c\uc774\uc5b8\ud2b8\uac00 \uc5f0\uacb0 {3}\uc5d0\uc11c URL {2}\uc758 \uc11c\ubc84\uc5d0\uc11c \uba54\uc2dc\uc9c0 ''{1}''\uc774(\uac00) \ud45c\uc2dc\ub418\ub294 \uc608\uc0c1\uce58 \uc54a\uc740 \uc751\ub2f5 \ucf54\ub4dc{0}\uc744(\ub97c) \uc218\uc2e0\ud588\uc2b5\ub2c8\ub2e4. +jmx.rest.client.response.code.error.explanation=WebSphere Java Management Extensions REST \ud074\ub77c\uc774\uc5b8\ud2b8\uac00 \uc11c\ubc84\uc5d0\uc11c \uc608\uc0c1\uce58 \uc54a\uc740 \uc751\ub2f5 \ucf54\ub4dc\ub97c \uc218\uc2e0\ud588\uc2b5\ub2c8\ub2e4. +jmx.rest.client.response.code.error.useraction=\uc790\uc138\ud55c \uc815\ubcf4\ub294 \uc11c\ubc84 \ub85c\uadf8\ub97c \uc0b4\ud3b4\ubcf4\uc2ed\uc2dc\uc624. + +jmx.rest.client.server.throwable.exception=CWWKX0204E: \uc11c\ubc84 \uc624\ub958 \uc2a4\ud2b8\ub9bc\uc5d0\uc11c Throwable\uc744 \uad6c\ubb38 \ubd84\uc11d\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. +jmx.rest.client.server.throwable.exception.explanation=\uc11c\ubc84\uc5d0\uc11c \ud074\ub77c\uc774\uc5b8\ud2b8 \uc694\uccad\uc744 \ucc98\ub9ac\ud558\ub294 \uc911\uc5d0 \uc608\uc678\uac00 \ubc1c\uc0dd\ud588\uc9c0\ub9cc \ud074\ub77c\uc774\uc5b8\ud2b8\uac00 \uc11c\ubc84 \uc624\ub958 \uc2a4\ud2b8\ub9bc\uc5d0\uc11c Throwable \uc624\ube0c\uc81d\ud2b8\ub97c \uad6c\ubb38 \ubd84\uc11d\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. \ud074\ub77c\uc774\uc5b8\ud2b8\uc5d0\uc11c Throwable \uc624\ube0c\uc81d\ud2b8\uc758 \ud074\ub798\uc2a4\uac00 \uc0ac\uc6a9 \uac00\ub2a5\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. +jmx.rest.client.server.throwable.exception.useraction=\uc790\uc138\ud55c \uc815\ubcf4\ub294 \uc11c\ubc84 \ub85c\uadf8\ub97c \uc0b4\ud3b4\ubcf4\uc2ed\uc2dc\uc624. + +jmx.rest.client.not.connected=CWWKX0206E: \ud074\ub77c\uc774\uc5b8\ud2b8\uac00 \uc11c\ubc84\uc5d0 \uc5f0\uacb0\ub418\uc9c0 \uc54a\uc558\uc2b5\ub2c8\ub2e4. +jmx.rest.client.not.connected.explanation=\uc11c\ubc84\uc5d0 \ub300\ud55c \uc5f0\uacb0\uc774 \ub2eb\ud614\uac70\ub098 \uc2e4\ud328\ud588\uc2b5\ub2c8\ub2e4. +jmx.rest.client.not.connected.useraction=\uc11c\ubc84\uc5d0\uc11c REST \ucee4\ub125\ud130 \uae30\ub2a5\uc774 \uc0ac\uc6a9 \uac00\ub2a5\ud55c\uc9c0 \ud655\uc778\ud558\uace0 \uc11c\ubc84\uc5d0 \ub300\ud55c \uc0c8 \uc5f0\uacb0\uc744 \uc5bb\uc73c\uc2ed\uc2dc\uc624. + +jmx.rest.client.url.not.found=CWWKX0207E: \uc11c\ubc84\ub294 \ud074\ub77c\uc774\uc5b8\ud2b8\uac00 \uc694\uccad\ud55c URL\uc744 \ucc3e\uc744 \uc218 \uc5c6\ub2e4\uace0 \ubcf4\uace0\ud569\ub2c8\ub2e4. +jmx.rest.client.url.not.found.explanation=\ud074\ub77c\uc774\uc5b8\ud2b8\uc758 \uc815\ubcf4\uac00 \uc720\ud6a8 \uae30\uac04\uc774 \uc9c0\ub0ac\uac70\ub098 \uc11c\ubc84\uc758 REST \ucee4\ub125\ud130 \uae30\ub2a5\uc744 \uc0ac\uc6a9 \uc548\ud569\ub2c8\ub2e4. +jmx.rest.client.url.not.found.useraction=\uc11c\ubc84\uc5d0\uc11c REST \ucee4\ub125\ud130 \uae30\ub2a5\uc774 \uc0ac\uc6a9 \uac00\ub2a5\ud55c\uc9c0 \ud655\uc778\ud558\uace0 \uc11c\ubc84\uc5d0 \ub300\ud55c \uc0c8 \uc5f0\uacb0\uc744 \uc5bb\uc73c\uc2ed\uc2dc\uc624. +jmx.rest.client.class.name.null=CWWKX0208E: \ud074\ub798\uc2a4 \uc774\ub984 \uc778\uc218\uac00 \ub110\uc785\ub2c8\ub2e4. +jmx.rest.client.class.name.null.explanation=\ud074\ub798\uc2a4 \uc774\ub984 \uc778\uc218\ub294 \ub110\uc774 \uc544\ub2c8\uc5b4\uc57c \ud569\ub2c8\ub2e4. +jmx.rest.client.class.name.null.useraction=\uba54\uc18c\ub4dc\ub97c \ud638\ucd9c\ud560 \ub54c \ub110\uc774 \uc544\ub2cc \ud074\ub798\uc2a4 \uc774\ub984\uc744 \uc81c\uacf5\ud558\uc2ed\uc2dc\uc624. + +jmx.rest.client.attribute.name.null=CWWKX0209E: \uc18d\uc131 \uc774\ub984 \uc778\uc218\uac00 \ub110\uc785\ub2c8\ub2e4. +jmx.rest.client.attribute.name.null.explanation=\uc18d\uc131 \uc774\ub984 \uc778\uc218\ub294 \ub110\uc774 \uc544\ub2c8\uc5b4\uc57c \ud569\ub2c8\ub2e4. +jmx.rest.client.attribute.name.null.useraction=\uba54\uc18c\ub4dc\ub97c \ud638\ucd9c\ud560 \ub54c \ub110\uc774 \uc544\ub2cc \uc18d\uc131 \uc774\ub984\uc744 \uc81c\uacf5\ud558\uc2ed\uc2dc\uc624. + +jmx.rest.client.attribute.names.null=CWWKX0210E: \uc18d\uc131 \uc774\ub984 \ubc30\uc5f4\uc744 \ud3ec\ud568\ud558\ub294 \uc778\uc218\uac00 \ub110\uc785\ub2c8\ub2e4. +jmx.rest.client.attribute.names.null.explanation=\uc18d\uc131 \uc774\ub984 \ubc30\uc5f4\uc744 \ud3ec\ud568\ud558\ub294 \uc778\uc218\ub294 \ub110\uc774 \uc544\ub2c8\uc5b4\uc57c \ud569\ub2c8\ub2e4. +jmx.rest.client.attribute.names.null.useraction=\uba54\uc18c\ub4dc\ub97c \ud638\ucd9c\ud560 \ub54c \ub110\uc774 \uc544\ub2cc \uc18d\uc131 \uc774\ub984 \ubc30\uc5f4\uc744 \uc81c\uacf5\ud558\uc2ed\uc2dc\uc624. + +jmx.rest.client.attribute.null=CWWKX0211E: \uc18d\uc131 \uc778\uc218\uac00 \ub110\uc785\ub2c8\ub2e4. +jmx.rest.client.attribute.null.explanation=\uc18d\uc131 \uc778\uc218\ub294 \ub110\uc774 \uc544\ub2c8\uc5b4\uc57c \ud569\ub2c8\ub2e4. +jmx.rest.client.attribute.null.useraction=\uba54\uc18c\ub4dc\ub97c \ud638\ucd9c\ud560 \ub54c \ub110\uc774 \uc544\ub2cc \uc18d\uc131\uc744 \uc81c\uacf5\ud558\uc2ed\uc2dc\uc624. + +jmx.rest.client.attribute.list.null=CWWKX0212E: AttributeList \uc778\uc218\uac00 \ub110\uc785\ub2c8\ub2e4. +jmx.rest.client.attribute.list.null.explanation=AttributeList \uc778\uc218\ub294 \ub110\uc774 \uc544\ub2c8\uc5b4\uc57c \ud569\ub2c8\ub2e4. +jmx.rest.client.attribute.list.null.useraction=\uba54\uc18c\ub4dc\ub97c \ud638\ucd9c\ud560 \ub54c \ub110\uc774 \uc544\ub2cc AttributeList\ub97c \uc81c\uacf5\ud558\uc2ed\uc2dc\uc624. + +jmx.rest.client.object.name.null=CWWKX0213E: ObjectName \uc778\uc218\uac00 \ub110\uc785\ub2c8\ub2e4. +jmx.rest.client.object.name.null.explanation=ObjectName \uc778\uc218\ub294 \ub110\uc774 \uc544\ub2c8\uc5b4\uc57c \ud569\ub2c8\ub2e4. +jmx.rest.client.object.name.null.useraction=\uba54\uc18c\ub4dc\ub97c \ud638\ucd9c\ud560 \ub54c \ub110\uc774 \uc544\ub2cc ObjectName\uc744 \uc81c\uacf5\ud558\uc2ed\uc2dc\uc624. + +jmx.rest.client.unexpected.server.throwable=CWWKX0214E: \uc11c\ubc84\uc5d0\uc11c \uc608\uae30\uce58 \ubabb\ud55c Throwable \uc624\ube0c\uc81d\ud2b8\uac00 \ub9ac\ud134\ub418\uc5c8\uc2b5\ub2c8\ub2e4. +jmx.rest.client.unexpected.server.throwable.explanation=\uc608\uc678\uac00 \uc11c\ubc84\uc5d0\uc11c \ub9ac\ud134\ub41c Throwable \uc624\ube0c\uc81d\ud2b8(\uc77c\ubc18\uc801\uc73c\ub85c \uc774 \uc870\uc791\uc5d0\ub294 \ubc1c\uc0dd\ud558\uc9c0 \uc54a\uc74c)\ub97c \ub7a9\ud551\ud569\ub2c8\ub2e4. +jmx.rest.client.unexpected.server.throwable.useraction=\uc790\uc138\ud55c \uc815\ubcf4\ub294 \uc11c\ubc84 \ub85c\uadf8\ub97c \uc0b4\ud3b4\ubcf4\uc2ed\uc2dc\uc624. + +jmx.rest.client.bad.credentials=CWWKX0215E: \uc81c\uacf5\ub41c \uc0ac\uc6a9\uc790 \uc774\ub984 \ub610\ub294 \ube44\ubc00\ubc88\ud638\uc5d0 \ubb38\uc81c\uc810\uc774 \uc788\uc2b5\ub2c8\ub2e4. \uc11c\ubc84\uac00 \ucf54\ub4dc {0} \ubc0f ''{1}'' \uba54\uc2dc\uc9c0\ub85c \uc751\ub2f5\ud569\ub2c8\ub2e4. +jmx.rest.client.bad.credentials.explanation=\uc5f0\uacb0\uc744 \uc5bb\uc744 \ub54c \uc81c\uacf5\ub41c \uc2e0\uc784 \uc815\ubcf4\uac00 \uc62c\ubc14\ub974\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. \uc0ac\uc6a9\uc790\uac00 \uc5c6\uac70\ub098 \uc11c\ubc84\uc5d0 \uc561\uc138\uc2a4\ud560 \uad8c\ud55c\uc774 \uc5c6\uc2b5\ub2c8\ub2e4. \ub610\ub294 \ube44\ubc00\ubc88\ud638\uac00 \uc62c\ubc14\ub974\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. +jmx.rest.client.bad.credentials.useraction=\uc0ac\uc6a9\uc790 \uc774\ub984 \ub610\ub294 \ube44\ubc00\ubc88\ud638\ub97c \uc815\uc815\ud55c \ub2e4\uc74c \uc0c8 \uc5f0\uacb0\uc744 \uc5bb\uc73c\uc2ed\uc2dc\uc624. + +jmx.rest.client.object.name.pattern=CWWKX0216E: ObjectName \uc778\uc218 ''{0}''\uc774(\uac00) \ud328\ud134\uc785\ub2c8\ub2e4." +jmx.rest.client.object.name.pattern.explanation=ObjectName \uc778\uc218\uac00 \ud328\ud134\uc785\ub2c8\ub2e4. \uadf8\ub7ec\ub098 \uba54\uc18c\ub4dc\uc5d0\ub294 \ub2e8 \ud558\ub098\uc758 MBean\uacfc \uc77c\uce58\ud558\ub294 ObjectName\uc774 \uc788\uc5b4\uc57c \ud569\ub2c8\ub2e4. +jmx.rest.client.object.name.pattern.useraction=\ub2e8 \ud558\ub098\uc758 MBean\uacfc \uc77c\uce58\ud558\ub3c4\ub85d \uc640\uc77c\ub4dc\uce74\ub4dc\uac00 \uc5c6\ub294 ObjectName \uc778\uc218\ub97c \uc81c\uacf5\ud558\uc2ed\uc2dc\uc624. + +jmx.rest.client.instance.not.found=CWWKX0217E: \ud604\uc7ac \uc9c0\uc815\ub41c ObjectName ''{0}''(\uc73c)\ub85c \ub4f1\ub85d\ub41c MBean\uc774 \uc5c6\uc2b5\ub2c8\ub2e4. +jmx.rest.client.instance.not.found.explanation=\uc870\uc791\uc744 \uc218\ud589\ud558\ub824\uba74 \ub4f1\ub85d\ub41c MBean\uc774 \ud544\uc694\ud558\uc9c0\ub9cc \uc9c0\uc815\ub41c ObjectName\uc73c\ub85c \ub4f1\ub85d\ub41c MBean\uc774 \uc5c6\uc2b5\ub2c8\ub2e4. +jmx.rest.client.instance.not.found.useraction=\uad00\ub9ac \uc870\uc791\uc744 \uc218\ud589\ud558\uae30 \uc804\uc5d0 MBean\uc774 \ub4f1\ub85d\ub418\uc5c8\ub294\uc9c0 \ud655\uc778\ud558\uc2ed\uc2dc\uc624. + +jmx.rest.client.attribute.not.found=CWWKX0218E: MBean ''{0}''\uc5d0 ''{1}''(\uc774)\ub77c\ub294 \uc18d\uc131\uc774 \uc5c6\uc2b5\ub2c8\ub2e4. +jmx.rest.client.attribute.not.found.explanation=MBean\uc774 \uc9c0\uc815\ub41c \uc774\ub984\uc758 \uc18d\uc131\uc744 \uc81c\uacf5\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. +jmx.rest.client.attribute.not.found.useraction=MBean\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \uc18d\uc131\uc744 \ud655\uc778\ud558\ub824\uba74 MBean \uc815\ubcf4\ub97c \uc5bb\uc73c\uc2ed\uc2dc\uc624. + +jmx.rest.client.operation.not.found=CWWKX0219E: MBean ''{0}''\uc5d0 ''{1}''(\uc774)\ub77c\ub294 \uc870\uc791\uc774 \uc5c6\uc2b5\ub2c8\ub2e4. +jmx.rest.client.operation.not.found.explanation=MBean\uc774 \uc9c0\uc815\ub41c \uc774\ub984\uc758 \uc870\uc791\uc744 \uc81c\uacf5\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. +jmx.rest.client.operation.not.found.useraction=MBean\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \uc870\uc791\uc744 \ud655\uc778\ud558\ub824\uba74 MBean \uc815\ubcf4\ub97c \uc5bb\uc73c\uc2ed\uc2dc\uc624. + +jmx.rest.client.listener.not.found=CWWKX0220E: \ud604\uc7ac \uc9c0\uc815\ub41c NotificationListener\uac00 MBean ''{0}''\uc5d0\uc11c \uc54c\ub9bc\uc744 \uc218\uc2e0\ud558\ub3c4\ub85d \ub4f1\ub85d\ub418\uc9c0 \uc54a\uc558\uc2b5\ub2c8\ub2e4. +jmx.rest.client.listener.not.found.explanation=NotificationListener\uac00 \ucd94\uac00\ub418\uc9c0 \uc54a\uc558\uac70\ub098 \uc774\ubbf8 \uc81c\uac70\ub418\uc5c8\uc73c\uba70 \ud604\uc7ac \uc9c0\uc815\ub41c MBean\uc5d0\uc11c \uc54c\ub9bc\uc744 \uc218\uc2e0\ud558\ub3c4\ub85d \ub4f1\ub85d\ub418\uc9c0 \uc54a\uc558\uc2b5\ub2c8\ub2e4. +jmx.rest.client.listener.not.found.useraction=\ud638\ucd9c \ucf54\ub4dc\uac00 \ucd94\uac00 \ubc0f \uc81c\uac70\ub41c NotificationListener\ub97c \ucd94\uc801\ud558\uac70\ub098 \uc608\uc678\ub97c \ubc1c\uacac\ud558\uace0 \ucc98\ub9ac\ud558\ub3c4\ub85d \ud558\uc2ed\uc2dc\uc624. + +jmx.rest.client.notification.lost=CWWKX0221I: \uc54c\ub9bc\uc744 \uc804\ub2ec\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. +jmx.rest.client.notification.lost.explanation=\ub4f1\ub85d\ub41c NotificationListener\ub97c \ucc3e\uc744 \uc218 \uc5c6\uac70\ub098 \uc54c\ub9bc\uc744 \uc804\ub2ec\ud558\ub294 \uc911\uc5d0 \uc608\uc678\uac00 \ubc1c\uc0dd\ud588\uc73c\ubbc0\ub85c \uc54c\ub9bc\uc744 \ud558\ub098 \uc774\uc0c1\uc758 NotificationListener\uc5d0 \uc804\ub2ec\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. +jmx.rest.client.notification.lost.useraction=\ub4f1\ub85d\ub41c NotificationListener\uc5d0 \uc54c\ub9bc\uc744 \uc804\ub2ec\ud588\uc5b4\uc57c \ud558\ub294 \uacbd\uc6b0 \uc608\uc678\uc5d0 \ub300\ud55c \ub85c\uadf8\ub97c \ucc38\uc870\ud558\uc2ed\uc2dc\uc624. + +jmx.rest.client.connection.failed=CWWKX0222I: \uc11c\ubc84\uc5d0 \uc5f0\uacb0\ud558\ub294 \ub370 \uc2e4\ud328\ud588\uc2b5\ub2c8\ub2e4. +jmx.rest.client.connection.failed.explanation=\uc11c\ubc84\uac00 \uc0ac\uc6a9 \ubd88\uac00\ub2a5\ud558\uac8c \ub418\uc5c8\uac70\ub098 \ud5c8\uc6a9 \uac00\ub2a5\ud558\ub3c4\ub85d \uad6c\uc131\ub41c \ucd5c\ub300 \uc2dc\uac04 \uc548\uc5d0 \ub2e4\uc2dc \uc0ac\uc6a9 \uac00\ub2a5\ud558\uac8c \ub418\uc9c0 \uc54a\uc558\uc2b5\ub2c8\ub2e4. +jmx.rest.client.connection.failed.useraction=\ub124\ud2b8\uc6cc\ud06c \uc5f0\uacb0\uc744 \ud655\uc778\ud558\uace0 \uc11c\ubc84\uac00 REST \ucee4\ub125\ud130 \uae30\ub2a5\uc774 \uc0ac\uc6a9\ub418\uc5b4 \uc2e4\ud589 \uc911\uc778\uc9c0 \ud655\uc778\ud558\uc2ed\uc2dc\uc624. + +jmx.rest.client.connection.temporarily.lost=CWWKX0223I: \uc11c\ubc84\uc5d0 \ub300\ud55c \uc5f0\uacb0\uc774 \uc784\uc2dc\ub85c \uc720\uc2e4\ub418\uc5c8\uc2b5\ub2c8\ub2e4. +jmx.rest.client.connection.temporarily.lost.explanation=\uc11c\ubc84\uac00 \uc0ac\uc6a9 \ubd88\uac00\ub2a5\ud558\uc9c0\ub9cc \ud074\ub77c\uc774\uc5b8\ud2b8\uac00 \ud5c8\uc6a9 \uac00\ub2a5\ud558\ub3c4\ub85d \uad6c\uc131\ub41c \ucd5c\ub300 \uc2dc\uac04 \ub3d9\uc548 \uc5f0\uacb0\uc744 \ubcf5\uc6d0\ud558\ub824\uace0 \uc2dc\ub3c4\ud569\ub2c8\ub2e4. +jmx.rest.client.connection.temporarily.lost.useraction=\uc11c\ubc84\ub97c \uc758\ub3c4\uc801\uc73c\ub85c \ub2e4\uc2dc \uc2dc\uc791\ud558\ub294 \uacbd\uc6b0 \uc870\uce58\uac00 \ud544\uc694\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. \uadf8\ub807\uc9c0 \uc54a\uc73c\uba74 \ub124\ud2b8\uc6cc\ud06c \uc5f0\uacb0\uc744 \ud655\uc778\ud558\uace0 \uc11c\ubc84\uac00 REST \ucee4\ub125\ud130 \uae30\ub2a5\uc774 \uc0ac\uc6a9\ub418\uc5b4 \uc2e4\ud589 \uc911\uc778\uc9c0 \ud655\uc778\ud558\uc2ed\uc2dc\uc624. + +jmx.rest.client.connection.restored.with.exceptions=CWWKX0224I: \uc5f0\uacb0\uc774 \ubcf5\uc6d0\ub418\uc5c8\uc9c0\ub9cc NotificationListener\ub97c \ucd94\uac00\ud560 \ub54c \uc608\uc678\uac00 \ubc1c\uc0dd\ud588\uc2b5\ub2c8\ub2e4. +jmx.rest.client.connection.restored.with.exceptions.explanation=\uc11c\ubc84\uc5d0 \ub300\ud55c \uc5f0\uacb0\uc774 \uc784\uc2dc\ub85c \uc720\uc2e4\ub418\uc5c8\uc9c0\ub9cc \uc131\uacf5\uc801\uc73c\ub85c \ubcf5\uc6d0\ub418\uc5c8\uc2b5\ub2c8\ub2e4. NotificationListener\ub97c \ucd94\uac00\ud558\ub294 \uc911\uc5d0 \uc608\uc678\uac00 \ubc1c\uc0dd\ud588\uc73c\ubbc0\ub85c \uc77c\ubd80 \uc54c\ub9bc\uc740 \uc218\uc2e0\ub418\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. +jmx.rest.client.connection.restored.with.exceptions.useraction=\uc54c\ub9bc\uc5d0 \ud3ec\ud568\ub41c \uc608\uc678\ub97c \ud655\uc778\ud558\uace0 \ubb38\uc81c\uc810\uc744 \uc815\uc815\ud55c \ub2e4\uc74c NotificationListener\ub97c \ub2e4\uc2dc \ub4f1\ub85d\ud558\uc2ed\uc2dc\uc624. + +jmx.rest.client.connection.restored=CWWKX0225I: \uc5f0\uacb0\uc774 \ubcf5\uc6d0\ub418\uc5c8\uc2b5\ub2c8\ub2e4. +jmx.rest.client.connection.restored.explanation=\uc11c\ubc84\uc5d0 \ub300\ud55c \uc5f0\uacb0\uc774 \uc784\uc2dc\ub85c \uc720\uc2e4\ub418\uc5c8\uc9c0\ub9cc \uc131\uacf5\uc801\uc73c\ub85c \ubcf5\uc6d0\ub418\uc5c8\uc2b5\ub2c8\ub2e4. \ub4f1\ub85d\ub41c \ubaa8\ub4e0 NotificationListener\uac00 \uacc4\uc18d \uc54c\ub9bc\uc744 \uc218\uc2e0\ud569\ub2c8\ub2e4. +jmx.rest.client.connection.restored.useraction=\uc5c6\uc74c + +jmx.rest.client.connection.illegal.argument=CWWKX0226E: JMXServiceURL \uc720\ud615\uc758 \ub9e4\uac1c\ubcc0\uc218\ub294 \ub110\uc77c \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. +jmx.rest.client.connection.illegal.argument.explanation='serviceURL' \ub9e4\uac1c\ubcc0\uc218 \uac12\uc740 \ub110\uc77c \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. +jmx.rest.client.connection.illegal.argument.useraction=\ub110\uc774 \uc544\ub2cc JMXServiceURL \uac12\uc744 \uc0ac\uc6a9\ud558\uc5ec JMX REST Connector\uc5d0 \ub2e4\uc2dc \uc5f0\uacb0\ud558\uc2ed\uc2dc\uc624. + +jmx.rest.client.connection.invalid.endpoint=CWWKX0227E: \ub2e4\uc74c\uc740 \uc720\ud6a8\ud55c \uc5d4\ub4dc\ud3ec\uc778\ud2b8 \uac12\uc774 \uc544\ub2d9\ub2c8\ub2e4. {0} +jmx.rest.client.connection.invalid.endpoint.explanation=\uc9c0\uc815\ub41c \uc5d4\ub4dc\ud3ec\uc778\ud2b8 \uac12\uc774 \uc720\ud6a8\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. +jmx.rest.client.connection.invalid.endpoint.useraction=\ubb38\uc790\uc5f4 \uc720\ud615\uc774\uace0 "host:port" \ud615\uc2dd\uc744 \uac00\uc9c0\ub294 \uc720\ud6a8\ud55c \uc5d4\ub4dc\ud3ec\uc778\ud2b8 \uac12\uc744 \uc0ac\uc6a9\ud558\uc5ec JMX REST Connector\uc5d0 \ub2e4\uc2dc \uc5f0\uacb0\ud558\uc2ed\uc2dc\uc624. + +jmx.rest.client.connection.no.endpoints=CWWKX0228E: \ucee4\ub125\ud130\ub97c \ucd08\uae30\ud654\ud560 \uc0ac\uc6a9 \uac00\ub2a5\ud55c \uc5d4\ub4dc\ud3ec\uc778\ud2b8\ub97c \ucc3e\uc744 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. +jmx.rest.client.connection.no.endpoints.explanation=JMX REST Connector\uc758 \ucd08\uae30\ud654 \uc911\uc5d0, \uc9c0\uc815\ub41c \uc5d4\ud2b8\ud3ec\uc778\ud2b8\uac00 \uc0ac\uc6a9 \uac00\ub2a5\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. +jmx.rest.client.connection.no.endpoints.useraction=\ud558\ub098 \uc774\uc0c1\uc758 \uc0ac\uc6a9 \uac00\ub2a5\ud55c \uc5d4\ub4dc\ud3ec\uc778\ud2b8\ub97c \uc0ac\uc6a9\ud558\uc5ec JMX REST Connector\uc5d0 \ub2e4\uc2dc \uc5f0\uacb0\ud558\uc2ed\uc2dc\uc624. + +jmx.rest.client.bad.user.credentials=CWWKX0229E: \uc81c\uacf5\ub41c \uc0ac\uc6a9\uc790 \uc2e0\uc784 \uc815\ubcf4\uc5d0 \ubb38\uc81c\uc810\uc774 \uc788\uc2b5\ub2c8\ub2e4. \uc11c\ubc84\uac00 \ucf54\ub4dc {0} \ubc0f ''{1}'' \uba54\uc2dc\uc9c0\ub85c \uc751\ub2f5\ud569\ub2c8\ub2e4. +jmx.rest.client.bad.user.credentials.explanation=\uc81c\uacf5\ub41c \uc2e0\uc784 \uc815\ubcf4\uac00 \uc62c\ubc14\ub974\uc9c0 \uc54a\uace0 \ub9cc\uae30\ub418\uc5c8\uac70\ub098 \ubd88\uc644\uc804\ud558\uba70 \ub610\ub294 \uad8c\ud55c\uc774 \uac70\ubd80\ub418\uc5c8\uc2b5\ub2c8\ub2e4. +jmx.rest.client.bad.user.credentials.useraction=\uc0ac\uc6a9\uc790 \uc2e0\uc784 \uc815\ubcf4\uc5d0 \uc62c\ubc14\ub978 \uc778\uc99d \ubc0f \uad8c\ud55c\uc774 \uc788\ub294\uc9c0 \ud655\uc778\ud55c \ub2e4\uc74c \uc0c8 \uc5f0\uacb0\uc744 \uc5bb\uc73c\uc2ed\uc2dc\uc624. + +jmx.rest.client.connection.connect=CWWKX0230I: Collective \uba64\ubc84\uac00 Collective \uc81c\uc5b4\uae30\uc5d0 JMX \ud074\ub77c\uc774\uc5b8\ud2b8\ub97c \uc5f4\uc5c8\uc2b5\ub2c8\ub2e4. {0} +jmx.rest.client.connection.connect.explanation=\uba64\ubc84\uac00 \uc81c\uc5b4\uae30\uc5d0 \uc5f0\uacb0\ub418\uc5c8\uc2b5\ub2c8\ub2e4. +jmx.rest.client.connection.connect.useraction=\uc870\uce58\uac00 \ud544\uc694\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. +jmx.rest.client.connection.disconnect=CWWKX0231I: Collective \uba64\ubc84\uac00 Collective \uc81c\uc5b4\uae30\uc5d0\uc11c JMX \ud074\ub77c\uc774\uc5b8\ud2b8\ub97c \ub2eb\uc558\uc2b5\ub2c8\ub2e4. {0} +jmx.rest.client.connection.disconnect.explanation=\uba64\ubc84\uac00 \uc81c\uc5b4\uae30\uc5d0\uc11c \uc5f0\uacb0 \ud574\uc81c\ub418\uc5c8\uc2b5\ub2c8\ub2e4. +jmx.rest.client.connection.disconnect.useraction=\uc870\uce58\uac00 \ud544\uc694\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. + diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_pl.nlsprops b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_pl.nlsprops new file mode 100755 index 00000000000..8babd6083d8 --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_pl.nlsprops @@ -0,0 +1,146 @@ +# IBM Confidential +# +# OCO Source Materials +# +# Copyright IBM Corp. 2012 +# +# The source code for this program is not published or otherwise divested +# of its trade secrets, irrespective of what has been deposited with the +# U.S. Copyright Office. +# +#CMVCPATHNAME com.ibm.ws.jmx.connector.client/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages.nlsprops +#ISMESSAGEFILE TRUE +#NLS_ENCODING=UNICODE +# +#COMPONENTPREFIX CWWKX +#COMPONENTNAMEFOR CWWKX JMX REST Client +# +# NLS_MESSAGEFORMAT_VAR +# +# Strings in this file which contain replacement variables are processed by the MessageFormat +# class (single quote must be coded as 2 consecutive single quotes ''). Strings in this file +# which do NOT contain replacement variables are NOT processed by the MessageFormat class +# (single quote must be coded as one single quote '). + +# Message prefix block: CWWKX0200-CWWKX0259 + +jmx.rest.client.request.error=CWWKX0201E: Klient REST produktu WebSphere Java Management Extensions napotka\u0142 b\u0142\u0105d podczas przygotowywania \u017c\u0105dania dla serwera zwi\u0105zanego z adresem URL {0} w po\u0142\u0105czeniu {1} +jmx.rest.client.request.error.explanation=Klient REST produktu WebSphere Java Management Extensions napotka\u0142 b\u0142\u0105d podczas przygotowywania \u017c\u0105dania dla serwera +jmx.rest.client.request.error.useraction=Dodatkowe informacje s\u0105 zawarte w plikach dziennik\u00f3w serwera. + +jmx.rest.client.response.error=CWWKX0202E: Klient REST produktu WebSphere Java Management Extensions nie m\u00f3g\u0142 przetworzy\u0107 \u017c\u0105dania z serwera zwi\u0105zanego z adresem URL {0} w po\u0142\u0105czeniu {1} +jmx.rest.client.response.error.explanation=Klient REST produktu WebSphere Java Management Extensions nie m\u00f3g\u0142 przetworzy\u0107 \u017c\u0105dania z serwera +jmx.rest.client.response.error.useraction=Dodatkowe informacje s\u0105 zawarte w plikach dziennik\u00f3w serwera. + +jmx.rest.client.response.code.error=CWWKX0203E: Klient REST produktu WebSphere Java Management Extensions odebra\u0142 nieoczekiwany kod odpowiedzi {0} z komunikatem {1} od serwera zwi\u0105zanego z adresem URL {2} w po\u0142\u0105czeniu {3} +jmx.rest.client.response.code.error.explanation=Klient REST produktu WebSphere Java Management Extensions odebra\u0142 nieoczekiwany kod odpowiedzi od serwera +jmx.rest.client.response.code.error.useraction=Dodatkowe informacje s\u0105 zawarte w plikach dziennik\u00f3w serwera. + +jmx.rest.client.server.throwable.exception=CWWKX0204E: Nie mo\u017cna przeanalizowa\u0107 wyj\u0105tku Throwable ze strumienia b\u0142\u0119d\u00f3w serwera. +jmx.rest.client.server.throwable.exception.explanation=Serwer zg\u0142osi\u0142 wyj\u0105tek podczas obs\u0142ugiwania \u017c\u0105dania klienta, ale klient nie mo\u017ce przeanalizowa\u0107 obiektu Throwable ze strumienia b\u0142\u0119d\u00f3w serwera. Klasa obiektu Throwable mo\u017ce by\u0107 niedost\u0119pna dla klienta. +jmx.rest.client.server.throwable.exception.useraction=Dodatkowe informacje s\u0105 zawarte w plikach dziennik\u00f3w serwera. + +jmx.rest.client.not.connected=CWWKX0206E: Klient nie jest po\u0142\u0105czony z serwerem. +jmx.rest.client.not.connected.explanation=Po\u0142\u0105czenie z serwerem zosta\u0142o zamkni\u0119te lub utracone. +jmx.rest.client.not.connected.useraction=Sprawd\u017a, czy na serwerze w\u0142\u0105czono funkcj\u0119 konektora REST i nawi\u0105\u017c nowe po\u0142\u0105czenie z serwerem. + +jmx.rest.client.url.not.found=CWWKX0207E: Serwer zg\u0142osi\u0142 brak mo\u017cliwo\u015bci znalezienia adresu URL za\u017c\u0105danego przez klient. +jmx.rest.client.url.not.found.explanation=Klient ma nieaktualne informacje lub funkcja konektora REST na serwerze zosta\u0142a wy\u0142\u0105czona. +jmx.rest.client.url.not.found.useraction=Sprawd\u017a, czy na serwerze w\u0142\u0105czono funkcj\u0119 konektora REST i nawi\u0105\u017c nowe po\u0142\u0105czenie z serwerem. + +jmx.rest.client.class.name.null=CWWKX0208E: Argument nazwy klasy ma warto\u015b\u0107 NULL. +jmx.rest.client.class.name.null.explanation=Argument nazwy klasy nie mo\u017ce mie\u0107 warto\u015bci NULL. +jmx.rest.client.class.name.null.useraction=Podczas wywo\u0142ywania metody podaj nazw\u0119 klasy inn\u0105 ni\u017c NULL. + +jmx.rest.client.attribute.name.null=CWWKX0209E: Argument nazwy atrybutu ma warto\u015b\u0107 NULL. +jmx.rest.client.attribute.name.null.explanation=Argument nazwy atrybutu nie mo\u017ce mie\u0107 warto\u015bci NULL. +jmx.rest.client.attribute.name.null.useraction=Podczas wywo\u0142ywania metody podaj nazw\u0119 atrybutu inn\u0105 ni\u017c NULL. + +jmx.rest.client.attribute.names.null=CWWKX0210E: Argument zawieraj\u0105cy tablic\u0119 nazw atrybut\u00f3w ma warto\u015b\u0107 NULL. +jmx.rest.client.attribute.names.null.explanation=Argument zawieraj\u0105cy tablic\u0119 nazw atrybut\u00f3w nie mo\u017ce mie\u0107 warto\u015bci NULL. +jmx.rest.client.attribute.names.null.useraction=Podczas wywo\u0142ywania metody podaj tablic\u0119 nazw atrybut\u00f3w o warto\u015bci innej ni\u017c NULL. + +jmx.rest.client.attribute.null=CWWKX0211E: Argument Attribute ma warto\u015b\u0107 NULL. +jmx.rest.client.attribute.null.explanation=Argument Attribute nie mo\u017ce mie\u0107 warto\u015bci NULL. +jmx.rest.client.attribute.null.useraction=Podczas wywo\u0142ywania metody podaj argument Attribute o warto\u015bci innej ni\u017c NULL. + +jmx.rest.client.attribute.list.null=CWWKX0212E: Argument AttributeList ma warto\u015b\u0107 NULL. +jmx.rest.client.attribute.list.null.explanation=Argument AttributeList nie mo\u017ce mie\u0107 warto\u015bci NULL. +jmx.rest.client.attribute.list.null.useraction=Podczas wywo\u0142ywania metody podaj argument AttributeList o warto\u015bci innej ni\u017c NULL. + +jmx.rest.client.object.name.null=CWWKX0213E: Argument ObjectName ma warto\u015b\u0107 NULL. +jmx.rest.client.object.name.null.explanation=Argument ObjectName nie mo\u017ce mie\u0107 warto\u015bci NULL. +jmx.rest.client.object.name.null.useraction=Podczas wywo\u0142ywania metody podaj argument ObjectName o warto\u015bci innej ni\u017c NULL. + +jmx.rest.client.unexpected.server.throwable=CWWKX0214E: Serwer zwr\u00f3ci\u0142 nieoczekiwany obiekt Throwable. +jmx.rest.client.unexpected.server.throwable.explanation=Wyj\u0105tek opakowuje obiekt Throwable zwr\u00f3cony przez serwer, kt\u00f3ry nie jest normalnie oczekiwany dla tej operacji. +jmx.rest.client.unexpected.server.throwable.useraction=Dodatkowe informacje s\u0105 zawarte w plikach dziennik\u00f3w serwera. + +jmx.rest.client.bad.credentials=CWWKX0215E: Wyst\u0105pi\u0142 problem dotycz\u0105cy podanej nazwy u\u017cytkownika lub has\u0142a. Odpowied\u017a serwera to kod {0} i komunikat {1}. +jmx.rest.client.bad.credentials.explanation=Referencje podane podczas nawi\u0105zywania po\u0142\u0105czenia by\u0142y niepoprawne. U\u017cytkownik nie istnieje lub nie ma uprawnie\u0144 niezb\u0119dnych do uzyskania dost\u0119pu do serwera albo has\u0142o jest niepoprawne. +jmx.rest.client.bad.credentials.useraction=Popraw nazw\u0119 u\u017cytkownika lub has\u0142o, a nast\u0119pnie nawi\u0105\u017c nowe po\u0142\u0105czenie. + +jmx.rest.client.object.name.pattern=CWWKX0216E: Argument ObjectName {0} to wzorzec. +jmx.rest.client.object.name.pattern.explanation=Argument ObjectName to wzorzec, a metoda wymaga argumentu ObjectName zgodnego z dok\u0142adnie jednym komponentem MBean. +jmx.rest.client.object.name.pattern.useraction=Podaj argument ObjectName bez znak\u00f3w wieloznacznych, kt\u00f3ry b\u0119dzie zgodny z dok\u0142adnie jednym komponentem MBean. + +jmx.rest.client.instance.not.found=CWWKX0217E: \u017baden komponent MBean nie zosta\u0142 zarejestrowany przy u\u017cyciu nazwy obiektu {0} +jmx.rest.client.instance.not.found.explanation=Operacja wymaga zarejestrowanego komponentu MBean, ale nie zarejestrowano \u017cadnego komponentu MBean o podanej nazwie obiektu. +jmx.rest.client.instance.not.found.useraction=Upewnij si\u0119, \u017ce komponent MBean jest zarejestrowany przed podj\u0119ciem pr\u00f3by wykonania wzgl\u0119dem niego operacji zarz\u0105dzania. + +jmx.rest.client.attribute.not.found=CWWKX0218E: Komponent MBean {0} nie zawiera atrybutu o nazwie {1} +jmx.rest.client.attribute.not.found.explanation=Komponent MBean nie udost\u0119pnia atrybutu o podanej nazwie. +jmx.rest.client.attribute.not.found.useraction=Uzyskaj informacje o komponencie MBean, aby okre\u015bli\u0107 atrybuty, kt\u00f3re udost\u0119pnia. + +jmx.rest.client.operation.not.found=CWWKX0219E: Komponent MBean {0} nie zawiera operacji o nazwie {1} +jmx.rest.client.operation.not.found.explanation=Komponent MBean nie udost\u0119pnia operacji o podanej nazwie. +jmx.rest.client.operation.not.found.useraction=Uzyskaj informacje o komponencie MBean, aby okre\u015bli\u0107 operacje, kt\u00f3re udost\u0119pnia. + +jmx.rest.client.listener.not.found=CWWKX0220E: Obiekt NotificationListener nie jest obecnie zarejestrowany do otrzymywania powiadomie\u0144 od komponentu MBean {0} +jmx.rest.client.listener.not.found.explanation=Obiekt NotificationListener nie zosta\u0142 dodany lub zosta\u0142 ju\u017c usuni\u0119ty i nie jest obecnie zarejestrowany do otrzymywania powiadomie\u0144 od danego komponentu MBean. +jmx.rest.client.listener.not.found.useraction=Upewnij si\u0119, \u017ce kod wywo\u0142uj\u0105cy \u015bledzi, kt\u00f3re obiekty NotificationListener s\u0105 dodawane i usuwane, lub przechwy\u0107 i obs\u0142u\u017c wyj\u0105tek. + +jmx.rest.client.notification.lost=CWWKX0221I: Nie mo\u017cna dostarczy\u0107 powiadomienia. +jmx.rest.client.notification.lost.explanation=Powiadomienie nie mo\u017ce zosta\u0107 dostarczone do co najmniej jednego obiektu NotificationListener, poniewa\u017c nie znaleziono zarejestrowanego obiektu NotificationListener lub wyst\u0105pi\u0142 wyj\u0105tek podczas dostarczania powiadomienia. +jmx.rest.client.notification.lost.useraction=Je\u015bli powiadomienie powinno zosta\u0107 dostarczone do zarejestrowanego obiektu NotificationListener, sprawd\u017a, czy w dzienniku zosta\u0142y zarejestrowane wyj\u0105tki. + +jmx.rest.client.connection.failed=CWWKX0222I: Po\u0142\u0105czenie z serwerem zosta\u0142o utracone. +jmx.rest.client.connection.failed.explanation=Serwer sta\u0142 si\u0119 niedost\u0119pny i w skonfigurowanym maksymalnym dozwolonym czasie jego dost\u0119pno\u015b\u0107 nie zosta\u0142a przywr\u00f3cona. +jmx.rest.client.connection.failed.useraction=Sprawd\u017a po\u0142\u0105czenie sieciowe i upewnij si\u0119, \u017ce serwer dzia\u0142a oraz \u017ce w\u0142\u0105czono na nim funkcj\u0119 konektora REST. + +jmx.rest.client.connection.temporarily.lost=CWWKX0223I: Po\u0142\u0105czenie z serwerem zosta\u0142o tymczasowo utracone. +jmx.rest.client.connection.temporarily.lost.explanation=Serwer sta\u0142 si\u0119 niedost\u0119pny, ale klient b\u0119dzie podejmowa\u0142 pr\u00f3by przywr\u00f3cenia po\u0142\u0105czenia przez skonfigurowany maksymalny dozwolony czas. +jmx.rest.client.connection.temporarily.lost.useraction=Je\u015bli serwer jest planowo restartowany, nie jest wymagana \u017cadna czynno\u015b\u0107. W przeciwnym razie sprawd\u017a po\u0142\u0105czenie sieciowe i upewnij si\u0119, \u017ce serwer dzia\u0142a oraz \u017ce w\u0142\u0105czono na nim funkcj\u0119 konektora REST. + +jmx.rest.client.connection.restored.with.exceptions=CWWKX0224I: Po\u0142\u0105czenie zosta\u0142o przywr\u00f3cone, ale napotkano wyj\u0105tki podczas dodawania obiekt\u00f3w NotificationListener. +jmx.rest.client.connection.restored.with.exceptions.explanation=Po\u0142\u0105czenie z serwerem zosta\u0142o tymczasowo utracone, a nast\u0119pnie pomy\u015blnie przywr\u00f3cone. Podczas dodawania obiekt\u00f3w NotificationListener napotkano wyj\u0105tki, wi\u0119c niekt\u00f3re powiadomienia mog\u0105 nie zosta\u0107 odebrane. +jmx.rest.client.connection.restored.with.exceptions.useraction=Sprawd\u017a wyj\u0105tki do\u0142\u0105czone do powiadomienia i ponownie zarejestruj obiekty NotificationListener po usuni\u0119ciu problem\u00f3w. + +jmx.rest.client.connection.restored=CWWKX0225I: Po\u0142\u0105czenie zosta\u0142o pomy\u015blnie przywr\u00f3cone. +jmx.rest.client.connection.restored.explanation=Po\u0142\u0105czenie z serwerem zosta\u0142o tymczasowo utracone, a nast\u0119pnie pomy\u015blnie przywr\u00f3cone. Wszystkie zarejestrowane obiekty NotificationListener b\u0119d\u0105 nadal odbiera\u0107 powiadomienia. +jmx.rest.client.connection.restored.useraction=Brak. + +jmx.rest.client.connection.illegal.argument=CWWKX0226E: Parametr typu JMXServiceURL nie mo\u017ce mie\u0107 warto\u015bci NULL. +jmx.rest.client.connection.illegal.argument.explanation=Warto\u015bci\u0105 parametru serviceURL nie mo\u017ce by\u0107 warto\u015b\u0107 NULL. +jmx.rest.client.connection.illegal.argument.useraction=Nawi\u0105\u017c ponownie po\u0142\u0105czenie z konektorem us\u0142ug REST JMX przy u\u017cyciu warto\u015bci JMXServiceURL innej ni\u017c NULL. + +jmx.rest.client.connection.invalid.endpoint=CWWKX0227E: Nast\u0119puj\u0105ca warto\u015b\u0107 nie jest poprawn\u0105 warto\u015bci\u0105 punktu ko\u0144cowego: {0} +jmx.rest.client.connection.invalid.endpoint.explanation=Okre\u015blona warto\u015b\u0107 punktu ko\u0144cowego jest niepoprawna. +jmx.rest.client.connection.invalid.endpoint.useraction=Nawi\u0105\u017c ponownie po\u0142\u0105czenie z konektorem us\u0142ug REST JMX przy u\u017cyciu poprawnej warto\u015bci punktu ko\u0144cowego, kt\u00f3ra ma typ String i format host:port. + +jmx.rest.client.connection.no.endpoints=CWWKX0228E: Nie mo\u017cna znale\u017a\u0107 \u017cadnych dost\u0119pnych punkt\u00f3w ko\u0144cowych na potrzeby inicjowania konektora. +jmx.rest.client.connection.no.endpoints.explanation=\u017baden z okre\u015blonych punkt\u00f3w ko\u0144cowych nie by\u0142 dost\u0119pny podczas inicjowania konektora us\u0142ug REST JMX. +jmx.rest.client.connection.no.endpoints.useraction=Nawi\u0105\u017c ponownie po\u0142\u0105czenie z konektorem us\u0142ug REST JMX przy u\u017cyciu co najmniej jednego dost\u0119pnego punktu ko\u0144cowego. + +jmx.rest.client.bad.user.credentials=CWWKX0229E: Wyst\u0105pi\u0142 problem dotycz\u0105cy podanych referencji u\u017cytkownika. Odpowied\u017a serwera to kod {0} i komunikat {1}. +jmx.rest.client.bad.user.credentials.explanation=Podane referencje s\u0105 niepoprawne, niekompletne, utraci\u0142y wa\u017cno\u015b\u0107 lub odm\u00f3wiono ich autoryzacji. +jmx.rest.client.bad.user.credentials.useraction=Sprawd\u017a, czy referencje u\u017cytkownika maj\u0105 odpowiednie uwierzytelnienie i autoryzacj\u0119, a nast\u0119pnie nawi\u0105\u017c nowe po\u0142\u0105czenie. + +jmx.rest.client.connection.connect=CWWKX0230I: W elemencie kolektywu zosta\u0142 otwarty klient JMX dla kontrolera kolektywu: {0} +jmx.rest.client.connection.connect.explanation=Element zosta\u0142 po\u0142\u0105czony z kontrolerem. +jmx.rest.client.connection.connect.useraction=Nie jest wymagana \u017cadna czynno\u015b\u0107. + +jmx.rest.client.connection.disconnect=CWWKX0231I: W elemencie zosta\u0142 zamkni\u0119ty klient JMX z kontrolera kolektywu: {0} +jmx.rest.client.connection.disconnect.explanation=Element zosta\u0142 roz\u0142\u0105czony z kontrolerem. +jmx.rest.client.connection.disconnect.useraction=Nie jest wymagana \u017cadna czynno\u015b\u0107. + diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_pt_BR.nlsprops b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_pt_BR.nlsprops new file mode 100755 index 00000000000..c9fe250acfb --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_pt_BR.nlsprops @@ -0,0 +1,146 @@ +# IBM Confidential +# +# OCO Source Materials +# +# Copyright IBM Corp. 2012 +# +# The source code for this program is not published or otherwise divested +# of its trade secrets, irrespective of what has been deposited with the +# U.S. Copyright Office. +# +#CMVCPATHNAME com.ibm.ws.jmx.connector.client/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages.nlsprops +#ISMESSAGEFILE TRUE +#NLS_ENCODING=UNICODE +# +#COMPONENTPREFIX CWWKX +#COMPONENTNAMEFOR CWWKX JMX REST Client +# +# NLS_MESSAGEFORMAT_VAR +# +# Strings in this file which contain replacement variables are processed by the MessageFormat +# class (single quote must be coded as 2 consecutive single quotes ''). Strings in this file +# which do NOT contain replacement variables are NOT processed by the MessageFormat class +# (single quote must be coded as one single quote '). + +# Message prefix block: CWWKX0200-CWWKX0259 + +jmx.rest.client.request.error=CWWKX0201E: O cliente REST do Java Management Extensions do WebSphere encontrou um erro ao preparar a solicita\u00e7\u00e3o para o servidor para a URL {0} na conex\u00e3o {1} +jmx.rest.client.request.error.explanation=O cliente REST do Java Management Extensions do WebSphere encontrou um erro ao preparar uma solicita\u00e7\u00e3o para o servidor +jmx.rest.client.request.error.useraction=Examine os logs do servidor para obter informa\u00e7\u00f5es adicionais. + +jmx.rest.client.response.error=CWWKX0202E: O cliente REST do Java Management Extensions do WebSphere n\u00e3o conseguiu processar a resposta do servidor para a URL {0} na conex\u00e3o {1} +jmx.rest.client.response.error.explanation=O cliente REST do Java Management Extensions do WebSphere n\u00e3o conseguiu processar uma resposta do servidor +jmx.rest.client.response.error.useraction=Examine os logs do servidor para obter informa\u00e7\u00f5es adicionais. + +jmx.rest.client.response.code.error=CWWKX0203E: O cliente REST do Java Management Extensions do WebSphere recebeu um c\u00f3digo de resposta {0} inesperado com a mensagem ''{1}'' a partir do servidor para a URL {2} na conex\u00e3o {3} +jmx.rest.client.response.code.error.explanation=O cliente REST do Java Management Extensions do WebSphere recebeu um c\u00f3digo de resposta inesperado do servidor +jmx.rest.client.response.code.error.useraction=Examine os logs do servidor para obter informa\u00e7\u00f5es adicionais. + +jmx.rest.client.server.throwable.exception=CWWKX0204E: N\u00e3o \u00e9 poss\u00edvel analisar Lan\u00e7\u00e1vel a partir do fluxo de erros do servidor. +jmx.rest.client.server.throwable.exception.explanation=O servidor emitiu uma exce\u00e7\u00e3o ao manipular a solicita\u00e7\u00e3o do cliente, mas o cliente n\u00e3o p\u00f4de analisar um objeto Lan\u00e7\u00e1vel a partir do fluxo de erros do servidor. A classe do objeto Lan\u00e7\u00e1vel pode n\u00e3o estar dispon\u00edvel ao cliente. +jmx.rest.client.server.throwable.exception.useraction=Examine os logs do servidor para obter informa\u00e7\u00f5es adicionais. + +jmx.rest.client.not.connected=CWWKX0206E: O cliente n\u00e3o est\u00e1 conectado ao servidor. +jmx.rest.client.not.connected.explanation=A conex\u00e3o com o servidor foi fechada ou falhou. +jmx.rest.client.not.connected.useraction=Verifique se o recurso do conector REST est\u00e1 ativado no servidor e obtenha uma nova conex\u00e3o com o servidor. + +jmx.rest.client.url.not.found=CWWKX0207E: O servidor relatou que a URL solicitada pelo cliente n\u00e3o foi localizada. +jmx.rest.client.url.not.found.explanation=O cliente pode ter informa\u00e7\u00f5es desatualizadas ou o recurso do conector REST no servidor pode ter sido desativado. +jmx.rest.client.url.not.found.useraction=Verifique se o recurso do conector REST est\u00e1 ativado no servidor e obtenha uma nova conex\u00e3o com o servidor. + +jmx.rest.client.class.name.null=CWWKX0208E: O argumento de nome de classe era nulo. +jmx.rest.client.class.name.null.explanation=O argumento de nome de classe n\u00e3o deve ser nulo. +jmx.rest.client.class.name.null.useraction=Forne\u00e7a um nome de classe n\u00e3o nulo ao chamar o m\u00e9todo. + +jmx.rest.client.attribute.name.null=CWWKX0209E: O argumento de nome do atributo era nulo. +jmx.rest.client.attribute.name.null.explanation=O argumento de nome do atributo n\u00e3o deve ser nulo. +jmx.rest.client.attribute.name.null.useraction=Forne\u00e7a um nome de atributo n\u00e3o nulo ao chamar o m\u00e9todo. + +jmx.rest.client.attribute.names.null=CWWKX0210E: O argumento que cont\u00e9m uma matriz de nomes de atributo era nulo. +jmx.rest.client.attribute.names.null.explanation=O argumento que cont\u00e9m uma matriz de nomes de atributo n\u00e3o deve ser nulo. +jmx.rest.client.attribute.names.null.useraction=Forne\u00e7a uma matriz n\u00e3o nula de nomes de atributo ao chamar o m\u00e9todo. + +jmx.rest.client.attribute.null=CWWKX0211E: O argumento Atributo era nulo. +jmx.rest.client.attribute.null.explanation=O argumento Atributo n\u00e3o deve ser nulo. +jmx.rest.client.attribute.null.useraction=Forne\u00e7a um Atributo n\u00e3o nulo ao chamar o m\u00e9todo. + +jmx.rest.client.attribute.list.null=CWWKX0212E: O argumento AttributeList era nulo. +jmx.rest.client.attribute.list.null.explanation=O argumento AttributeList n\u00e3o deve ser nulo. +jmx.rest.client.attribute.list.null.useraction=Forne\u00e7a um AttributeList n\u00e3o nulo ao chamar o m\u00e9todo. + +jmx.rest.client.object.name.null=CWWKX0213E: O argumento ObjectName era nulo. +jmx.rest.client.object.name.null.explanation=O argumento ObjectName n\u00e3o deve ser nulo. +jmx.rest.client.object.name.null.useraction=Forne\u00e7a um ObjectName n\u00e3o nulo ao chamar o m\u00e9todo. + +jmx.rest.client.unexpected.server.throwable=CWWKX0214E: Um objeto Lan\u00e7\u00e1vel inesperado foi retornado do servidor. +jmx.rest.client.unexpected.server.throwable.explanation=A exce\u00e7\u00e3o agrupa um objeto Lan\u00e7\u00e1vel retornado do servidor que n\u00e3o \u00e9 esperado normalmente para esta opera\u00e7\u00e3o. +jmx.rest.client.unexpected.server.throwable.useraction=Examine os logs do servidor para obter informa\u00e7\u00f5es adicionais. + +jmx.rest.client.bad.credentials=CWWKX0215E: Houve um problema com o nome de usu\u00e1rio ou senha fornecida. O servidor respondeu com o c\u00f3digo {0} e a mensagem ''{1}'' +jmx.rest.client.bad.credentials.explanation=As credenciais fornecidas ao obter a conex\u00e3o estavam incorretas. O usu\u00e1rio pode n\u00e3o existir ou pode n\u00e3o ter autoridade para acessar o servidor, ou a senha pode estar incorreta. +jmx.rest.client.bad.credentials.useraction=Corrija o nome de usu\u00e1rio ou a senha e, em seguida, obtenha uma nova conex\u00e3o. + +jmx.rest.client.object.name.pattern=CWWKX0216E: O argumento ObjectName ''{0}'' \u00e9 um padr\u00e3o". +jmx.rest.client.object.name.pattern.explanation=O argumento ObjectName \u00e9 um padr\u00e3o, mas o m\u00e9todo requer um ObjectName que corresponda exatamente a um MBean. +jmx.rest.client.object.name.pattern.useraction=Forne\u00e7a um argumento ObjectName sem curingas que corresponda exatamente a um MBean. + +jmx.rest.client.instance.not.found=CWWKX0217E: Nenhum MBean est\u00e1 registrado atualmente com o ObjectName ''{0}'' determinado +jmx.rest.client.instance.not.found.explanation=A opera\u00e7\u00e3o requer um MBean registrado, mas nenhum MBean com o ObjectName determinado foi registrado. +jmx.rest.client.instance.not.found.useraction=Assegure-se de que o MBean esteja registrado antes de tentar executar opera\u00e7\u00f5es de gerenciamento nele. + +jmx.rest.client.attribute.not.found=CWWKX0218E: O MBean ''{0}'' n\u00e3o possui um atributo com o nome ''{1}'' +jmx.rest.client.attribute.not.found.explanation=O MBean n\u00e3o fornece um atributo com o nome determinado. +jmx.rest.client.attribute.not.found.useraction=Obtenha as informa\u00e7\u00f5es do MBean para confirmar quais atributos ele fornece. + +jmx.rest.client.operation.not.found=CWWKX0219E: O MBean ''{0}'' n\u00e3o possui uma opera\u00e7\u00e3o com o nome ''{1}'' +jmx.rest.client.operation.not.found.explanation=O MBean n\u00e3o fornece uma opera\u00e7\u00e3o com o nome determinado. +jmx.rest.client.operation.not.found.useraction=Obtenha as informa\u00e7\u00f5es do MBean para confirmar quais opera\u00e7\u00f5es ele fornece. + +jmx.rest.client.listener.not.found=CWWKX0220E: O NotificationListener determinado n\u00e3o est\u00e1 registrado atualmente para receber notifica\u00e7\u00f5es do MBean ''{0}'' +jmx.rest.client.listener.not.found.explanation=O NotificationListener n\u00e3o foi inclu\u00eddo ou j\u00e1 foi removido e n\u00e3o est\u00e1 registrado atualmente para receber notifica\u00e7\u00f5es do MBean determinado. +jmx.rest.client.listener.not.found.useraction=Certifique-se de que o c\u00f3digo de chamada controle quais NotificationListeners foram inclu\u00eddos e removidos ou capture e manipule a exce\u00e7\u00e3o. + +jmx.rest.client.notification.lost=CWWKX0221I: N\u00e3o foi poss\u00edvel entregar a notifica\u00e7\u00e3o. +jmx.rest.client.notification.lost.explanation=Uma notifica\u00e7\u00e3o n\u00e3o p\u00f4de ser entregue a um ou mais NotificationListeners porque um NotificationListener registrado n\u00e3o foi localizado ou houve uma exce\u00e7\u00e3o durante a entrega da notifica\u00e7\u00e3o. +jmx.rest.client.notification.lost.useraction=Se a notifica\u00e7\u00e3o deveria ter sido entregue para um NotificationListener registrado, verifique os logs para exce\u00e7\u00f5es. + +jmx.rest.client.connection.failed=CWWKX0222I: A conex\u00e3o com o servidor falhou. +jmx.rest.client.connection.failed.explanation=O servidor ficou indispon\u00edvel e n\u00e3o foi disponibilizado novamente no tempo m\u00e1ximo configurado permitido. +jmx.rest.client.connection.failed.useraction=Verifique a conex\u00e3o de rede e assegure-se de que o servidor esteja em execu\u00e7\u00e3o com o recurso de conector REST ativado. + +jmx.rest.client.connection.temporarily.lost=CWWKX0223I: A conex\u00e3o com o servidor foi perdida temporariamente. +jmx.rest.client.connection.temporarily.lost.explanation=O servidor ficou indispon\u00edvel, mas o cliente tentar\u00e1 restaurar a conex\u00e3o durante o tempo m\u00e1ximo configurado permitido. +jmx.rest.client.connection.temporarily.lost.useraction=Se o servidor estiver sendo reiniciado intencionalmente, nenhuma a\u00e7\u00e3o ser\u00e1 necess\u00e1ria. Caso contr\u00e1rio, verifique a conex\u00e3o de rede e assegure-se de que o servidor esteja em execu\u00e7\u00e3o com o recurso de conector REST ativado. + +jmx.rest.client.connection.restored.with.exceptions=CWWKX0224I: A conex\u00e3o foi restaurada, mas foram encontradas exce\u00e7\u00f5es ao incluir NotificationListeners. +jmx.rest.client.connection.restored.with.exceptions.explanation=A conex\u00e3o com o servidor foi perdida temporariamente, mas foi restaurada com sucesso. Foram encontradas exce\u00e7\u00f5es ao incluir NotificationListeners, portanto, algumas notifica\u00e7\u00f5es podem n\u00e3o ter sido recebidas. +jmx.rest.client.connection.restored.with.exceptions.useraction=Verifique as exce\u00e7\u00f5es inclu\u00eddas com a notifica\u00e7\u00e3o e registre NotificationListeners novamente depois de corrigir os problemas. + +jmx.rest.client.connection.restored=CWWKX0225I: A conex\u00e3o foi restaurada com sucesso. +jmx.rest.client.connection.restored.explanation=A conex\u00e3o com o servidor foi perdida temporariamente, mas foi restaurada com sucesso. Todos os NotificationListeners registrados continuar\u00e3o a receber notifica\u00e7\u00f5es. +jmx.rest.client.connection.restored.useraction=Nenhuma + +jmx.rest.client.connection.illegal.argument=CWWKX0226E: O par\u00e2metro do tipo JMXServiceURL n\u00e3o pode ser nulo. +jmx.rest.client.connection.illegal.argument.explanation=O valor para o par\u00e2metro 'serviceURL' n\u00e3o pode ser nulo. +jmx.rest.client.connection.illegal.argument.useraction=Reconecte-se ao Conector JMX REST usando um valor JMXServiceURL n\u00e3o nulo. + +jmx.rest.client.connection.invalid.endpoint=CWWKX0227E: O seguinte n\u00e3o \u00e9 um valor de terminal v\u00e1lido: {0} +jmx.rest.client.connection.invalid.endpoint.explanation=O valor de terminal especificado n\u00e3o \u00e9 v\u00e1lido. +jmx.rest.client.connection.invalid.endpoint.useraction=Reconecte-se ao Conector JMX REST usando um valor de terminal v\u00e1lido que seja do tipo Sequ\u00eancia e tenha o formato "host:porta". + +jmx.rest.client.connection.no.endpoints=CWWKX0228E: N\u00e3o foi poss\u00edvel localizar nenhum terminal dispon\u00edvel para inicializar o conector. +jmx.rest.client.connection.no.endpoints.explanation=Nenhum dos terminais especificados estava dispon\u00edvel durante a inicializa\u00e7\u00e3o do Conector JMX REST. +jmx.rest.client.connection.no.endpoints.useraction=Reconecte-se ao Conector JMX REST usando pelo menos 1 terminal dispon\u00edvel. + +jmx.rest.client.bad.user.credentials=CWWKX0229E: Houve um problema com as credenciais dos usu\u00e1rios fornecidas. O servidor respondeu com o c\u00f3digo {0} e a mensagem ''{1}'' +jmx.rest.client.bad.user.credentials.explanation=As credenciais fornecidas s\u00e3o autoriza\u00e7\u00f5es incorretas, expiradas, incompletas ou negadas. +jmx.rest.client.bad.user.credentials.useraction=Verifique se as credenciais do usu\u00e1rio possuem autentica\u00e7\u00e3o e autoriza\u00e7\u00e3o corretas, em seguida obtenha uma nova conex\u00e3o. + +jmx.rest.client.connection.connect=CWWKX0230I: O membro coletivo abriu o cliente JMX para o controlador coletivo: {0} +jmx.rest.client.connection.connect.explanation=O membro conectado ao controlador. +jmx.rest.client.connection.connect.useraction=Nenhuma a\u00e7\u00e3o \u00e9 necess\u00e1ria. + +jmx.rest.client.connection.disconnect=CWWKX0231I: O membro coletivo fechou o cliente JMX do controlador coletivo: {0} +jmx.rest.client.connection.disconnect.explanation=O membro desconectado do controlador. +jmx.rest.client.connection.disconnect.useraction=Nenhuma a\u00e7\u00e3o \u00e9 necess\u00e1ria. + diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_ro.nlsprops b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_ro.nlsprops new file mode 100755 index 00000000000..65f278d7703 --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_ro.nlsprops @@ -0,0 +1,146 @@ +# IBM Confidential +# +# OCO Source Materials +# +# Copyright IBM Corp. 2012 +# +# The source code for this program is not published or otherwise divested +# of its trade secrets, irrespective of what has been deposited with the +# U.S. Copyright Office. +# +#CMVCPATHNAME com.ibm.ws.jmx.connector.client/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages.nlsprops +#ISMESSAGEFILE TRUE +#NLS_ENCODING=UNICODE +# +#COMPONENTPREFIX CWWKX +#COMPONENTNAMEFOR CWWKX JMX REST Client +# +# NLS_MESSAGEFORMAT_VAR +# +# Strings in this file which contain replacement variables are processed by the MessageFormat +# class (single quote must be coded as 2 consecutive single quotes ''). Strings in this file +# which do NOT contain replacement variables are NOT processed by the MessageFormat class +# (single quote must be coded as one single quote '). + +# Message prefix block: CWWKX0200-CWWKX0259 + +jmx.rest.client.request.error=CWWKX0201E: Clientul WebSphere Java Management Extensions REST a \u00eent\u00e2lnit o eroare \u00een timpul preg\u0103tirii cererii la serverul pentru URL-ul {0} pe conexiunea {1} +jmx.rest.client.request.error.explanation=Clientul WebSphere Java Management Extensions REST a \u00eent\u00e2lnit o eroare \u00een timpul preg\u0103tirii cererii la serverul +jmx.rest.client.request.error.useraction=Pentru informa\u0163ii suplimentare examina\u0163i istoricele de server. + +jmx.rest.client.response.error=CWWKX0202E: Clientul WebSphere Java Management Extensions REST nu a putut procesa r\u0103spunsul de la serverul pentru URL-ul {0} pe conexiunea {1} +jmx.rest.client.response.error.explanation=Clientul WebSphere Java Management Extensions REST nu a putut procesa un r\u0103spuns de la server +jmx.rest.client.response.error.useraction=Pentru informa\u0163ii suplimentare examina\u0163i istoricele de server. + +jmx.rest.client.response.code.error=CWWKX0203E: Clientul WebSphere Java Management Extensions REST a primit un cod r\u0103spuns nea\u015fteptat {0} cu mesajul ''{1}'' de la server pentru URL-ul {2} pe conexiunea {3} +jmx.rest.client.response.code.error.explanation=Clientul WebSphere Java Management Extensions REST a primit un cod r\u0103spuns nea\u015fteptat de la server +jmx.rest.client.response.code.error.useraction=Pentru informa\u0163ii suplimentare examina\u0163i istoricele de server. + +jmx.rest.client.server.throwable.exception=CWWKX0204E: Nu se poate analiza Throwable din fluxul de erori de server. +jmx.rest.client.server.throwable.exception.explanation=Serverul a ridicat o excep\u0163ie la instrumentarea cererii de client, dar clientul nu a putut analiza un obiect Throwable din fluxul de erori de server. Clasa obiectului Throwable poate s\u0103 nu fie disponibil\u0103 pentru client. +jmx.rest.client.server.throwable.exception.useraction=Pentru informa\u0163ii suplimentare examina\u0163i istoricele de server. + +jmx.rest.client.not.connected=CWWKX0206E: Clientul nu este conectat la server. +jmx.rest.client.not.connected.explanation=Conexiunea la server fie a fost \u00eenchis\u0103, fie a e\u015fuat. +jmx.rest.client.not.connected.useraction=Verifica\u0163i c\u0103 este activat\u0103 caracteristica de conector REST pe server \u015fi ob\u0163ine\u0163i o nou\u0103 conexiune la server. + +jmx.rest.client.url.not.found=CWWKX0207E: Serverul a raportat c\u0103 URL-ul cerut de client nu a fost g\u0103sit. +jmx.rest.client.url.not.found.explanation=Clientul poate avea informa\u0163ii dep\u0103\u015fite sau caracteristica REST de conector pe server poate fi dezactivat\u0103. +jmx.rest.client.url.not.found.useraction=Verifica\u0163i c\u0103 este activat\u0103 caracerostica de conector REST pe server \u015fi ob\u0163ine\u0163i o nou\u0103 conexiune la server. + +jmx.rest.client.class.name.null=CWWKX0208E: Argumentul de nume de clas\u0103 a fost nul. +jmx.rest.client.class.name.null.explanation=Argumentul de nume de clas\u0103 nu trebuie s\u0103 fie nul. +jmx.rest.client.class.name.null.useraction=Furniza\u0163i un nume de clas\u0103 nenul c\u00e2nd apela\u0163i metoda. + +jmx.rest.client.attribute.name.null=CWWKX0209E: Argumentul de nume de atribut a fost nul. +jmx.rest.client.attribute.name.null.explanation=Argumentul de nume de atribut nu trebuie s\u0103 fie nul. +jmx.rest.client.attribute.name.null.useraction=Furniza\u0163i un nume de atribut nenul c\u00e2nd apela\u0163i metoda. + +jmx.rest.client.attribute.names.null=CWWKX0210E: Argumentul care con\u0163ine o matrice de nume de atribute a fost nul. +jmx.rest.client.attribute.names.null.explanation=Argumentul care con\u0163ine o matrice de nume de atribute nu trebuie s\u0103 fie nul. +jmx.rest.client.attribute.names.null.useraction=Furniza\u0163i o matrice nenul\u0103 de nume de atribute c\u00e2nd apela\u0163i metoda. + +jmx.rest.client.attribute.null=CWWKX0211E: Argumentul Atribut a fost nul. +jmx.rest.client.attribute.null.explanation=Argumentul Atribut nu trebuie s\u0103 fie nul. +jmx.rest.client.attribute.null.useraction=Furniza\u0163i un Atribut nenul c\u00e2nd apela\u0163i metoda. + +jmx.rest.client.attribute.list.null=CWWKX0212E: Argumentul AttributeList a fost nul. +jmx.rest.client.attribute.list.null.explanation=Argumentul AttributeList nu trebuie s\u0103 fie nul. +jmx.rest.client.attribute.list.null.useraction=Furniza\u0163i un AttributeList nenul c\u00e2nd apela\u0163i metoda. + +jmx.rest.client.object.name.null=CWWKX0213E: Argumentul ObjectName a fost nul. +jmx.rest.client.object.name.null.explanation=Argumentul ObjectName nu trebuie s\u0103 fie nul. +jmx.rest.client.object.name.null.useraction=Furniza\u0163i un ObjectName nenul c\u00e2nd apela\u0163i metoda. + +jmx.rest.client.unexpected.server.throwable=CWWKX0214E: A fost returnat un obiect Throwable nea\u015fteptat de la server. +jmx.rest.client.unexpected.server.throwable.explanation=Excep\u0163ia \u00eenf\u0103\u015foar\u0103 un obiect Throwable returnat de la server care nu este \u00een mod normal a\u015fteptat\u0103 pentru aceast\u0103 opera\u0163ie. +jmx.rest.client.unexpected.server.throwable.useraction=Pentru informa\u0163ii suplimentare examina\u0163i istoricele de server. + +jmx.rest.client.bad.credentials=CWWKX0215E: A existat o problem\u0103 cu numele utilizator sau parola furnizate. Serverul a r\u0103spuns cu cod {0} \u015fi mesaj ''{1}'' +jmx.rest.client.bad.credentials.explanation=Acredit\u0103rile furnizate la ob\u0163inerea conexiunii au fost incorecte. Utilizatorul poate s\u0103 nu existe sau s\u0103 nu aib\u0103 autoritatea de a accesa serverul, sau parola poate fi incorect\u0103. +jmx.rest.client.bad.credentials.useraction=Corecta\u0163i numele utilizator sau parola, apoi ob\u0163ine\u0163i o nou\u0103 conexiune. + +jmx.rest.client.object.name.pattern=CWWKX0216E: Argumentul ObjectName ''{0}'' este un model." +jmx.rest.client.object.name.pattern.explanation=Argumentul ObjectName este un model dar metoda cere un ObjectName care s\u0103 se potriveasc\u0103 exact cu un MBean. +jmx.rest.client.object.name.pattern.useraction=Furniza\u0163i un argument ObjectName f\u0103r\u0103 metacaractere care se va potrivi exact cu un MBean. + +jmx.rest.client.instance.not.found=CWWKX0217E: Nu este \u00eenregistrat niciun MBean cu ObjectName ''{0}'' dat. +jmx.rest.client.instance.not.found.explanation=Opera\u0163ia cere un MBean \u00eenregistrat, dar nu a fost \u00eenregistrat niciun MBean cu ObjectName dat. +jmx.rest.client.instance.not.found.useraction=Asigura\u0163i-v\u0103 c\u0103 MBean-ul este \u00eenregistrat \u00eenainte de a \u00eencerca s\u0103 face\u0163i opera\u0163ii de gestiune pa el. + +jmx.rest.client.attribute.not.found=CWWKX0218E: MBean-ul ''{0}'' nu are un atribut cu numele ''{1}'' +jmx.rest.client.attribute.not.found.explanation=MBean-ul nu furnizeaz\u0103 un atribut cu numele dat. +jmx.rest.client.attribute.not.found.useraction=Ob\u0163ine\u0163i informa\u0163ii de MBean pentru a confirma ce atribute furnizeaz\u0103 MBean-ul. + +jmx.rest.client.operation.not.found=CWWKX0219E: MBean-ul ''{0}'' nu are o opera\u0163ie cu numele ''{1}'' +jmx.rest.client.operation.not.found.explanation=MBean-ul nu furnizeaz\u0103 o opera\u0163ie cu numele dat. +jmx.rest.client.operation.not.found.useraction=Ob\u0163ine\u0163i informa\u0163ii de MBean pentru a confirma ce opera\u0163ii furnizeaz\u0103 MBean-ul. + +jmx.rest.client.listener.not.found=CWWKX0220E: NotificationListener-ul dat nu este \u00eenregistrat curent pentru a primi notific\u0103ri de la MBean-ul ''{0}'' +jmx.rest.client.listener.not.found.explanation=NotificationListener-ul nu a fost ad\u0103ugat sau a fost deja \u00eenl\u0103turat \u015fi nu este \u00eenregistrat curent pentru a primi notific\u0103ri de la MBean-ul dat. +jmx.rest.client.listener.not.found.useraction=Asigura\u0163i-v\u0103 c\u0103 codul de apelare urm\u0103re\u015fte ce NotificationListener-e au fost ad\u0103ugate \u015fi \u00eenl\u0103turate sau capta\u0163i \u015fi instrumenta\u0163i excep\u0163ia. + +jmx.rest.client.notification.lost=CWWKX0221I: Notificarea nu a putut fi livrat\u0103. +jmx.rest.client.notification.lost.explanation=O notificare nu a putut fi livrat\u0103 unuia sau mai multor ascult\u0103toare de notific\u0103ri, deoarece NotificationListener \u00eenregistrat nu a fost g\u0103sit sau exista o excep\u0163ie \u00een timpul livr\u0103rii notific\u0103rii. +jmx.rest.client.notification.lost.useraction=Dac\u0103 notificarea trebuia livrat\u0103 la un NotificationListener (ascult\u0103tor de notific\u0103ri) existent, verifica\u0163i istoricele pentru excep\u0163ii. + +jmx.rest.client.connection.failed=CWWKX0222I: A e\u015fuat conexiunea la server. +jmx.rest.client.connection.failed.explanation=Serverul a devenit indisponibil \u015fi nu a devenit disponibil din nou \u00een intervalul maxim permisibil configurat. +jmx.rest.client.connection.failed.useraction=Verifica\u0163i conexiunea de re\u0163ea \u015fi asigura\u0163i-v\u0103 c\u0103 serverul ruleaz\u0103 cu caracteristica de conector REST activat\u0103. + +jmx.rest.client.connection.temporarily.lost=CWWKX0223I: S-a pierdut temporar conexiunea la server. +jmx.rest.client.connection.temporarily.lost.explanation=Serverul a devenit indisponibil, dar clientul va \u00eencerca s\u0103 restaureze conexiunea pe durata intervalului de timp maxim permisibil configurat. +jmx.rest.client.connection.temporarily.lost.useraction=Dac\u0103 serverul este repornit inten\u0163ionat, nu este necesar\u0103 nici o ac\u0163iune. Altfel, verifica\u0163i conexiunea de re\u0163ea \u015fi asigura\u0163i-v\u0103 c\u0103 serverul ruleaz\u0103 cu caracteristica de conector REST activat\u0103. + +jmx.rest.client.connection.restored.with.exceptions=CWWKX0224I: Conexiunea a fost restaurat\u0103 dar excep\u0163iile au ap\u0103rut la ad\u0103ugarea NotificationListener-ilor. +jmx.rest.client.connection.restored.with.exceptions.explanation=Conexiunea la server s-a pierdut temporar dar a fost restaurat\u0103 cu succes. Excep\u0163iile au ap\u0103rut la ad\u0103ugarea NotificationListener-ilor, deci unele notific\u0103ri pot lipsi. +jmx.rest.client.connection.restored.with.exceptions.useraction=Verifica\u0163i c\u0103 excep\u0163iile au inclus notificarea \u015fi re-\u00eenregistra\u0163i NotificationListener-ii dup\u0103 corectarea problemelor. + +jmx.rest.client.connection.restored=CWWKX0225I: Conexiunea a fost restaurat\u0103 cu succes. +jmx.rest.client.connection.restored.explanation=Conexiunea la server s-a pierdut temporar dar a fost restaurat\u0103 cu succes. To\u0163i NotificationListener-ii \u00eenregistra\u0163i vor continua s\u0103 primeasc\u0103 notific\u0103ri. +jmx.rest.client.connection.restored.useraction=F\u0103r\u0103 + +jmx.rest.client.connection.illegal.argument=CWWKX0226E: Parametrul de tipul JMXServiceURL nu poate fi null. +jmx.rest.client.connection.illegal.argument.explanation=Valoarea parametrului 'serviceURL' nu poate fi null. +jmx.rest.client.connection.illegal.argument.useraction=Reconecta\u0163i-v\u0103 la JMX REST Connector folosind o valoare JMXServiceURL non-null. + +jmx.rest.client.connection.invalid.endpoint=CWWKX0227E: Urm\u0103toarea nu este o valoare de punct final valid\u0103: {0} +jmx.rest.client.connection.invalid.endpoint.explanation=Valoarea de punct final specificat\u0103 nu este valid\u0103. +jmx.rest.client.connection.invalid.endpoint.useraction=Reconecta\u0163i-v\u0103 la JMX REST Connector folosind o valoare de punct final valid\u0103 care este de tipul String \u015fi are formatul "host:port". + +jmx.rest.client.connection.no.endpoints=CWWKX0228E: Nu s-au g\u0103sit puncte finale disponibile pentru ini\u0163ializarea conectorului. +jmx.rest.client.connection.no.endpoints.explanation=Niciunul din punctele finale specificate nu este disponibil \u00een timpul ini\u0163ializ\u0103rii pentru JMX REST Connector. +jmx.rest.client.connection.no.endpoints.useraction=Reconecta\u0163i-v\u0103 la JMX REST Connector folosind cel pu\u0163in un punct final disponibil. + +jmx.rest.client.bad.user.credentials=CWWKX0229E: A existat o problem\u0103 cu acredit\u0103rile de utilizator furnizate. Serverul a r\u0103spuns cu codul {0} \u015fi mesajul ''{1}'' +jmx.rest.client.bad.user.credentials.explanation=Acredit\u0103rile furnizate sunt incorecte, expirate, incomplete sau cu autorizare refuzat\u0103. +jmx.rest.client.bad.user.credentials.useraction=Verifica\u0163i c\u0103 acredit\u0103rile de utilizator au autentificare \u015fi autoriza\u0163ie corecte, apoi ob\u0163ine\u0163i o nou\u0103 conexiune. + +jmx.rest.client.connection.connect=CWWKX0230I: Membrul colectiv a deschis clientul JMX pentru controlerul colectiv: {0} +jmx.rest.client.connection.connect.explanation=Membrul conectat la controler. +jmx.rest.client.connection.connect.useraction=Nu este necesar\u0103 nicio ac\u0163iune. + +jmx.rest.client.connection.disconnect=CWWKX0231I: Membrul colectiv a \u00eenchis clientul JMX pentru controlerul colectiv: {0} +jmx.rest.client.connection.disconnect.explanation=Membrul s-a deconectat de la controler. +jmx.rest.client.connection.disconnect.useraction=Nu este necesar\u0103 nicio ac\u0163iune. + diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_ru.nlsprops b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_ru.nlsprops new file mode 100755 index 00000000000..a169f12238f --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_ru.nlsprops @@ -0,0 +1,146 @@ +# IBM Confidential +# +# OCO Source Materials +# +# Copyright IBM Corp. 2012 +# +# The source code for this program is not published or otherwise divested +# of its trade secrets, irrespective of what has been deposited with the +# U.S. Copyright Office. +# +#CMVCPATHNAME com.ibm.ws.jmx.connector.client/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages.nlsprops +#ISMESSAGEFILE TRUE +#NLS_ENCODING=UNICODE +# +#COMPONENTPREFIX CWWKX +#COMPONENTNAMEFOR CWWKX JMX REST Client +# +# NLS_MESSAGEFORMAT_VAR +# +# Strings in this file which contain replacement variables are processed by the MessageFormat +# class (single quote must be coded as 2 consecutive single quotes ''). Strings in this file +# which do NOT contain replacement variables are NOT processed by the MessageFormat class +# (single quote must be coded as one single quote '). + +# Message prefix block: CWWKX0200-CWWKX0259 + +jmx.rest.client.request.error=CWWKX0201E: \u0412 \u043a\u043b\u0438\u0435\u043d\u0442\u0435 REST WebSphere Java Management Extensions \u0432\u043e\u0437\u043d\u0438\u043a\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0443 \u0441 URL {0} \u0432 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0438 {1} +jmx.rest.client.request.error.explanation=\u0412 \u043a\u043b\u0438\u0435\u043d\u0442\u0435 REST WebSphere Java Management Extensions \u0432\u043e\u0437\u043d\u0438\u043a\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0443 +jmx.rest.client.request.error.useraction=\u0421\u043c. \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u044b \u0441\u0435\u0440\u0432\u0435\u0440\u0430. + +jmx.rest.client.response.error=CWWKX0202E: \u041a\u043b\u0438\u0435\u043d\u0442\u0443 REST WebSphere Java Management Extensions \u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043e\u0442\u0432\u0435\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0441 URL {0} \u0432 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0438 {1} +jmx.rest.client.response.error.explanation=\u041a\u043b\u0438\u0435\u043d\u0442\u0443 REST WebSphere Java Management Extensions \u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043e\u0442\u0432\u0435\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 +jmx.rest.client.response.error.useraction=\u0421\u043c. \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u044b \u0441\u0435\u0440\u0432\u0435\u0440\u0430. + +jmx.rest.client.response.code.error=CWWKX0203E: \u041a\u043b\u0438\u0435\u043d\u0442 REST WebSphere Java Management Extensions \u043f\u043e\u043b\u0443\u0447\u0438\u043b \u043e\u0442\u0432\u0435\u0442 \u0441 \u043d\u0435\u043f\u0440\u0435\u0434\u0432\u0438\u0434\u0435\u043d\u043d\u044b\u043c \u043a\u043e\u0434\u043e\u043c {0} \u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435\u043c ''{1}'' \u043e\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0441 URL {2} \u0432 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0438 {3} +jmx.rest.client.response.code.error.explanation=\u041a\u043b\u0438\u0435\u043d\u0442 REST WebSphere Java Management Extensions \u043f\u043e\u043b\u0443\u0447\u0438\u043b \u043e\u0442\u0432\u0435\u0442 \u0441 \u043d\u0435\u043f\u0440\u0435\u0434\u0432\u0438\u0434\u0435\u043d\u043d\u044b\u043c \u043a\u043e\u0434\u043e\u043c \u043e\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 +jmx.rest.client.response.code.error.useraction=\u0421\u043c. \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u044b \u0441\u0435\u0440\u0432\u0435\u0440\u0430. + +jmx.rest.client.server.throwable.exception=CWWKX0204E: \u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043f\u0440\u043e\u0430\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c Throwable \u0438\u0437 \u043f\u043e\u0442\u043e\u043a\u0430 \u043e\u0448\u0438\u0431\u043e\u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0430. +jmx.rest.client.server.throwable.exception.explanation=\u0421\u0435\u0440\u0432\u0435\u0440 \u0441\u043e\u043e\u0431\u0449\u0438\u043b \u043e\u0431 \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u0438 \u043f\u0440\u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u043d\u043e \u043a\u043b\u0438\u0435\u043d\u0442\u0443 \u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043f\u0440\u043e\u0430\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442 Throwable \u0438\u0437 \u043f\u043e\u0442\u043e\u043a\u0430 \u043e\u0448\u0438\u0431\u043e\u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0430. \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u043a\u043b\u0430\u0441\u0441 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 Throwable \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u0434\u043b\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u0430. +jmx.rest.client.server.throwable.exception.useraction=\u0421\u043c. \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u044b \u0441\u0435\u0440\u0432\u0435\u0440\u0430. + +jmx.rest.client.not.connected=CWWKX0206E: \u041a\u043b\u0438\u0435\u043d\u0442 \u043d\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d \u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0443. +jmx.rest.client.not.connected.explanation=\u0421\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c \u0437\u0430\u043a\u0440\u044b\u0442\u043e \u0438\u043b\u0438 \u043d\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e. +jmx.rest.client.not.connected.useraction=\u0423\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043a\u043e\u043d\u043d\u0435\u043a\u0442\u043e\u0440\u0430 REST \u0438 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u0437\u0430\u043d\u043e\u0432\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c. + +jmx.rest.client.url.not.found=CWWKX0207E: \u0421\u0435\u0440\u0432\u0435\u0440 \u0441\u043e\u043e\u0431\u0449\u0438\u043b, \u0447\u0442\u043e \u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043d\u0430\u0439\u0442\u0438 URL, \u0437\u0430\u043f\u0440\u043e\u0448\u0435\u043d\u043d\u044b\u0439 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u043c. +jmx.rest.client.url.not.found.explanation=\u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0443 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0443\u0441\u0442\u0430\u0440\u0435\u0432\u0448\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f, \u0438\u043b\u0438 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043a\u043e\u043d\u043d\u0435\u043a\u0442\u043e\u0440\u0430 REST. +jmx.rest.client.url.not.found.useraction=\u0423\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043a\u043e\u043d\u043d\u0435\u043a\u0442\u043e\u0440\u0430 REST \u0438 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u0437\u0430\u043d\u043e\u0432\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c. + +jmx.rest.client.class.name.null=CWWKX0208E: \u0410\u0440\u0433\u0443\u043c\u0435\u043d\u0442 \u0438\u043c\u0435\u043d\u0438 \u043a\u043b\u0430\u0441\u0441\u0430 \u043f\u0443\u0441\u0442. +jmx.rest.client.class.name.null.explanation=\u0410\u0440\u0433\u0443\u043c\u0435\u043d\u0442 \u0438\u043c\u0435\u043d\u0438 \u043a\u043b\u0430\u0441\u0441\u0430 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0443\u0441\u0442\u044b\u043c. +jmx.rest.client.class.name.null.useraction=\u041f\u0440\u0438 \u0432\u044b\u0437\u043e\u0432\u0435 \u043c\u0435\u0442\u043e\u0434\u0430 \u0443\u043a\u0430\u0436\u0438\u0442\u0435 \u043d\u0435\u043f\u0443\u0441\u0442\u043e\u0435 \u0438\u043c\u044f \u043a\u043b\u0430\u0441\u0441\u0430. + +jmx.rest.client.attribute.name.null=CWWKX0209E: \u0410\u0440\u0433\u0443\u043c\u0435\u043d\u0442 \u0438\u043c\u0435\u043d\u0438 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430 \u043f\u0443\u0441\u0442. +jmx.rest.client.attribute.name.null.explanation=\u0410\u0440\u0433\u0443\u043c\u0435\u043d\u0442 \u0438\u043c\u0435\u043d\u0438 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0443\u0441\u0442\u044b\u043c. +jmx.rest.client.attribute.name.null.useraction=\u041f\u0440\u0438 \u0432\u044b\u0437\u043e\u0432\u0435 \u043c\u0435\u0442\u043e\u0434\u0430 \u0443\u043a\u0430\u0436\u0438\u0442\u0435 \u043d\u0435\u043f\u0443\u0441\u0442\u043e\u0435 \u0438\u043c\u044f \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430. + +jmx.rest.client.attribute.names.null=CWWKX0210E: \u0410\u0440\u0433\u0443\u043c\u0435\u043d\u0442, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0439 \u043c\u0430\u0441\u0441\u0438\u0432 \u0438\u043c\u0435\u043d \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432, \u043f\u0443\u0441\u0442. +jmx.rest.client.attribute.names.null.explanation=\u0410\u0440\u0433\u0443\u043c\u0435\u043d\u0442, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0439 \u043c\u0430\u0441\u0441\u0438\u0432 \u0438\u043c\u0435\u043d \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432, \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0443\u0441\u0442\u044b\u043c. +jmx.rest.client.attribute.names.null.useraction=\u041f\u0440\u0438 \u0432\u044b\u0437\u043e\u0432\u0435 \u043c\u0435\u0442\u043e\u0434\u0430 \u0443\u043a\u0430\u0436\u0438\u0442\u0435 \u043d\u0435\u043f\u0443\u0441\u0442\u043e\u0439 \u043c\u0430\u0441\u0441\u0438\u0432 \u0438\u043c\u0435\u043d \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432. + +jmx.rest.client.attribute.null=CWWKX0211E: \u0410\u0440\u0433\u0443\u043c\u0435\u043d\u0442 Attribute \u043f\u0443\u0441\u0442. +jmx.rest.client.attribute.null.explanation=\u0410\u0440\u0433\u0443\u043c\u0435\u043d\u0442 Attribute \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0443\u0441\u0442\u044b\u043c. +jmx.rest.client.attribute.null.useraction=\u041f\u0440\u0438 \u0432\u044b\u0437\u043e\u0432\u0435 \u043c\u0435\u0442\u043e\u0434\u0430 \u0443\u043a\u0430\u0436\u0438\u0442\u0435 \u043d\u0435\u043f\u0443\u0441\u0442\u043e\u0439 Attribute. + +jmx.rest.client.attribute.list.null=CWWKX0212E: \u0410\u0440\u0433\u0443\u043c\u0435\u043d\u0442 AttributeList \u043f\u0443\u0441\u0442. +jmx.rest.client.attribute.list.null.explanation=\u0410\u0440\u0433\u0443\u043c\u0435\u043d\u0442 AttributeList \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0443\u0441\u0442\u044b\u043c. +jmx.rest.client.attribute.list.null.useraction=\u041f\u0440\u0438 \u0432\u044b\u0437\u043e\u0432\u0435 \u043c\u0435\u0442\u043e\u0434\u0430 \u0443\u043a\u0430\u0436\u0438\u0442\u0435 \u043d\u0435\u043f\u0443\u0441\u0442\u043e\u0439 AttributeList. + +jmx.rest.client.object.name.null=CWWKX0213E: \u0410\u0440\u0433\u0443\u043c\u0435\u043d\u0442 ObjectName \u043f\u0443\u0441\u0442. +jmx.rest.client.object.name.null.explanation=\u0410\u0440\u0433\u0443\u043c\u0435\u043d\u0442 ObjectName \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0443\u0441\u0442\u044b\u043c. +jmx.rest.client.object.name.null.useraction=\u041f\u0440\u0438 \u0432\u044b\u0437\u043e\u0432\u0435 \u043c\u0435\u0442\u043e\u0434\u0430 \u0443\u043a\u0430\u0436\u0438\u0442\u0435 \u043d\u0435\u043f\u0443\u0441\u0442\u043e\u0439 ObjectName. + +jmx.rest.client.unexpected.server.throwable=CWWKX0214E: \u0421\u0435\u0440\u0432\u0435\u0440 \u0432\u0435\u0440\u043d\u0443\u043b \u043d\u0435\u043e\u0436\u0438\u0434\u0430\u043d\u043d\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 Throwable. +jmx.rest.client.unexpected.server.throwable.explanation=\u041f\u0440\u0438\u0447\u0438\u043d\u043e\u0439 \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u0438 \u0441\u0442\u0430\u043b \u043e\u0431\u044a\u0435\u043a\u0442 Throwable, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0435\u043d\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c: \u043f\u0440\u0438 \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0438 \u044d\u0442\u043e\u0439 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0442\u0430\u043a\u043e\u0433\u043e \u0431\u044b\u0442\u044c \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u043e. +jmx.rest.client.unexpected.server.throwable.useraction=\u0421\u043c. \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u044b \u0441\u0435\u0440\u0432\u0435\u0440\u0430. + +jmx.rest.client.bad.credentials=CWWKX0215E: \u0412\u043e\u0437\u043d\u0438\u043a\u043b\u0430 \u043d\u0435\u043f\u043e\u043b\u0430\u0434\u043a\u0430 \u0441 \u0438\u043c\u0435\u043d\u0435\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438\u043b\u0438 \u043f\u0430\u0440\u043e\u043b\u0435\u043c. \u0412 \u043e\u0442\u0432\u0435\u0442\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0431\u044b\u043b \u0443\u043a\u0430\u0437\u0430\u043d \u043a\u043e\u0434 {0} \u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 ''{1}'' +jmx.rest.client.bad.credentials.explanation=\u041f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u0431\u044b\u043b\u0438 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d\u044b \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0435 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435. \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442, \u043d\u0435 \u0438\u043c\u0435\u0435\u0442 \u043f\u0440\u0430\u0432 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0443 \u0438\u043b\u0438 \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u043b \u043f\u0430\u0440\u043e\u043b\u044c. +jmx.rest.client.bad.credentials.useraction=\u0418\u0441\u043f\u0440\u0430\u0432\u044c\u0442\u0435 \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438\u043b\u0438 \u043f\u0430\u0440\u043e\u043b\u044c \u0438 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u0435\u0449\u0435 \u0440\u0430\u0437 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435. + +jmx.rest.client.object.name.pattern=CWWKX0216E: \u0410\u0440\u0433\u0443\u043c\u0435\u043d\u0442 ObjectName ''{0}'' \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u043c." +jmx.rest.client.object.name.pattern.explanation=\u0410\u0440\u0433\u0443\u043c\u0435\u043d\u0442 ObjectName \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u043c, \u043d\u043e \u043c\u0435\u0442\u043e\u0434 \u0442\u0440\u0435\u0431\u0443\u0435\u0442, \u0447\u0442\u043e\u0431\u044b ObjectName \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u043e\u0432\u0430\u043b \u0440\u043e\u0432\u043d\u043e \u043e\u0434\u043d\u043e\u043c\u0443 MBean. +jmx.rest.client.object.name.pattern.useraction=\u0423\u043a\u0430\u0436\u0438\u0442\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442 ObjectName \u0431\u0435\u0437 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 \u043f\u043e\u0434\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u043e\u0432\u0430\u043b \u0431\u044b \u0440\u043e\u0432\u043d\u043e \u043e\u0434\u043d\u043e\u043c\u0443 MBean. + +jmx.rest.client.instance.not.found=CWWKX0217E: \u0414\u043b\u044f \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u0433\u043e ObjectName ''{0}'' \u043d\u0435 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d \u043d\u0438 \u043e\u0434\u0438\u043d MBean +jmx.rest.client.instance.not.found.explanation=\u0414\u043b\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 MBean, \u043d\u043e \u0441 \u0437\u0430\u0434\u0430\u043d\u043d\u044b\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u043c ObjectName \u043d\u0435 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d \u043d\u0438 \u043e\u0434\u0438\u043d MBean. +jmx.rest.client.instance.not.found.useraction=\u041f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u043f\u044b\u0442\u0430\u0442\u044c\u0441\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f, \u0443\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u0432\u044b \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043b\u0438 MBean. + +jmx.rest.client.attribute.not.found=CWWKX0218E: \u0412 MBean ''{0}'' \u043d\u0435\u0442 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430 \u0441 \u0438\u043c\u0435\u043d\u0435\u043c ''{1}'' +jmx.rest.client.attribute.not.found.explanation=\u0412 MBean \u043d\u0435\u0442 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430 \u0441 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u043c \u0438\u043c\u0435\u043d\u0435\u043c. +jmx.rest.client.attribute.not.found.useraction=\u041f\u043e\u043b\u0443\u0447\u0438\u0442\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e MBean \u0438 \u0432\u044b\u044f\u0441\u043d\u0438\u0442\u0435, \u043a\u0430\u043a\u0438\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b \u0432 \u043d\u0435\u043c \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u044b. + +jmx.rest.client.operation.not.found=CWWKX0219E: \u0412 MBean ''{0}'' \u043d\u0435\u0442 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0441 \u0438\u043c\u0435\u043d\u0435\u043c ''{1}'' +jmx.rest.client.operation.not.found.explanation=\u0412 MBean \u043d\u0435\u0442 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0441 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u043c \u0438\u043c\u0435\u043d\u0435\u043c. +jmx.rest.client.operation.not.found.useraction=\u041f\u043e\u043b\u0443\u0447\u0438\u0442\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e MBean \u0438 \u0432\u044b\u044f\u0441\u043d\u0438\u0442\u0435, \u043a\u0430\u043a\u0438\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0432 \u043d\u0435\u043c \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u044b. + +jmx.rest.client.listener.not.found=CWWKX0220E: \u041d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0439 NotificationListener \u043d\u0435 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439 \u043e\u0442 MBean ''{0}'' +jmx.rest.client.listener.not.found.explanation=\u041e\u0431\u044a\u0435\u043a\u0442 NotificationListener \u043d\u0435 \u0431\u044b\u043b \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d \u0438\u043b\u0438 \u0443\u0436\u0435 \u0431\u044b\u043b \u0443\u0434\u0430\u043b\u0435\u043d, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u043e\u043d \u043d\u0435 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439 \u043e\u0442 \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u0433\u043e MBean. +jmx.rest.client.listener.not.found.useraction=\u0423\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u0432 \u043a\u043e\u0434\u0435 \u0432\u044b\u0437\u043e\u0432\u0430 \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0432\u0441\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 NotificationListener, \u0438\u043b\u0438 \u043f\u043e\u043f\u044b\u0442\u0430\u0439\u0442\u0435\u0441\u044c \u0443\u0441\u0442\u0440\u0430\u043d\u0438\u0442\u044c \u043d\u0435\u043f\u043e\u043b\u0430\u0434\u043a\u0443 \u043f\u043e \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u0438. + +jmx.rest.client.notification.lost=CWWKX0221I: \u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435. +jmx.rest.client.notification.lost.explanation=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 \u043e\u0434\u043d\u043e\u043c\u0443 \u0438\u043b\u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c NotificationListener, \u0442\u0430\u043a \u043a\u0430\u043a \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 NotificationListener \u0438\u043b\u0438 \u0432 \u0445\u043e\u0434\u0435 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0432\u043e\u0437\u043d\u0438\u043a\u043b\u0430 \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044f. +jmx.rest.client.notification.lost.useraction=\u0415\u0441\u043b\u0438 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043e \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u043c\u0443 NotificationListener, \u043f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435 \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u043e\u0431 \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044f\u0445 \u0432 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430\u0445. + +jmx.rest.client.connection.failed=CWWKX0222I: \u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c. +jmx.rest.client.connection.failed.explanation=\u0421\u0435\u0440\u0432\u0435\u0440 \u0441\u0442\u0430\u043b \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u043c \u0438 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u0434\u043e \u0442\u0435\u0445 \u043f\u043e\u0440, \u043f\u043e\u043a\u0430 \u043d\u0435 \u0438\u0441\u0442\u0435\u0447\u0435\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u043e\u0435 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f. +jmx.rest.client.connection.failed.useraction=\u041f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0441 \u0441\u0435\u0442\u044c\u044e \u0438 \u0443\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043a\u043e\u043d\u043d\u0435\u043a\u0442\u043e\u0440\u0430 REST. + +jmx.rest.client.connection.temporarily.lost=CWWKX0223I: \u0421\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u043f\u043e\u0442\u0435\u0440\u044f\u043d\u043e. +jmx.rest.client.connection.temporarily.lost.explanation=\u0421\u0435\u0440\u0432\u0435\u0440 \u0441\u0442\u0430\u043b \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u043c, \u043d\u043e \u043a\u043b\u0438\u0435\u043d\u0442 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0442\u044c \u043f\u043e\u043f\u044b\u0442\u043a\u0438 \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435, \u043f\u043e\u043a\u0430 \u043d\u0435 \u0438\u0441\u0442\u0435\u0447\u0435\u0442 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0435 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f. +jmx.rest.client.connection.temporarily.lost.useraction=\u0415\u0441\u043b\u0438 \u0441\u0435\u0440\u0432\u0435\u0440 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u043f\u043b\u0430\u043d\u043e\u0432\u043e\u0439 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438, \u0442\u043e \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f. \u0412 \u043f\u0440\u043e\u0442\u0438\u0432\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435 \u0441\u0435\u0442\u0435\u0432\u043e\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0438 \u0443\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043a\u043e\u043d\u043d\u0435\u043a\u0442\u043e\u0440\u0430 REST. + +jmx.rest.client.connection.restored.with.exceptions=CWWKX0224I: \u0421\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e, \u043d\u043e \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 NotificationListener \u0432\u043e\u0437\u043d\u0438\u043a\u043b\u0438 \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u0438. +jmx.rest.client.connection.restored.with.exceptions.explanation=\u0421\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c \u0431\u044b\u043b\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u043f\u043e\u0442\u0435\u0440\u044f\u043d\u043e, \u043d\u043e \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e. \u0422\u0430\u043a \u043a\u0430\u043a \u0432 \u0445\u043e\u0434\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 NotificationListener \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u043b\u0438 \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u0438, \u043c\u043e\u0433\u043b\u0438 \u0431\u044b\u0442\u044c \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u044b \u043d\u0435 \u0432\u0441\u0435 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f. +jmx.rest.client.connection.restored.with.exceptions.useraction=\u041f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u0442\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043e\u0431 \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044f\u0445, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u044b \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f, \u0438 \u043f\u043e\u0441\u043b\u0435 \u0443\u0441\u0442\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043d\u0435\u043f\u043e\u043b\u0430\u0434\u043e\u043a \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0439\u0442\u0435 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b NotificationListener. + +jmx.rest.client.connection.restored=CWWKX0225I: \u0421\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e. +jmx.rest.client.connection.restored.explanation=\u0421\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c \u0431\u044b\u043b\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u043f\u043e\u0442\u0435\u0440\u044f\u043d\u043e, \u043d\u043e \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e. \u0412\u0441\u0435 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b NotificationListener \u0431\u0443\u0434\u0443\u0442 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0442\u044c \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f. +jmx.rest.client.connection.restored.useraction=\u041d\u0435\u0442 + +jmx.rest.client.connection.illegal.argument=CWWKX0226E: \u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u0441 \u0442\u0438\u043f\u043e\u043c JMXServiceURL \u043d\u0435 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u043d\u0443\u043b\u0435\u0432\u044b\u043c. +jmx.rest.client.connection.illegal.argument.explanation=\u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 'serviceURL' \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u043d\u0443\u043b\u0435\u0432\u044b\u043c. +jmx.rest.client.connection.illegal.argument.useraction=\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u0441\u044c \u043a \u043a\u043e\u043d\u043d\u0435\u043a\u0442\u043e\u0440\u0443 JMX REST \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e, \u0443\u043a\u0430\u0437\u0430\u0432 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 JMXServiceURL, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0443\u043b\u0435\u0432\u044b\u043c. + +jmx.rest.client.connection.invalid.endpoint=CWWKX0227E: \u0414\u0430\u043d\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0435\u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0439 \u0442\u043e\u0447\u043a\u0438: {0} +jmx.rest.client.connection.invalid.endpoint.explanation=\u0423\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0439 \u0442\u043e\u0447\u043a\u0438 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0435\u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u043c. +jmx.rest.client.connection.invalid.endpoint.useraction=\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u0441\u044c \u043a \u043a\u043e\u043d\u043d\u0435\u043a\u0442\u043e\u0440\u0443 JMX REST \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e, \u0443\u043a\u0430\u0437\u0430\u0432 \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0441 \u0442\u0438\u043f\u043e\u043c String \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 "\u0445\u043e\u0441\u0442:\u043f\u043e\u0440\u0442". + +jmx.rest.client.connection.no.endpoints=CWWKX0228E: \u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043d\u0430\u0439\u0442\u0438 \u043d\u0438 \u043e\u0434\u043d\u043e\u0439 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0439 \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0439 \u0442\u043e\u0447\u043a\u0438 \u0434\u043b\u044f \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043a\u043e\u043d\u043d\u0435\u043a\u0442\u043e\u0440\u0430. +jmx.rest.client.connection.no.endpoints.explanation=\u041d\u0438 \u043e\u0434\u043d\u0430 \u0438\u0437 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0445 \u043a\u043e\u043d\u0435\u0447\u043d\u044b\u0445 \u0442\u043e\u0447\u0435\u043a \u043d\u0435 \u0431\u044b\u043b\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0439 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043a\u043e\u043d\u043d\u0435\u043a\u0442\u043e\u0440\u0430 JMX REST. +jmx.rest.client.connection.no.endpoints.useraction=\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u0441\u044c \u043a \u043a\u043e\u043d\u043d\u0435\u043a\u0442\u043e\u0440\u0443 JMX REST \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e, \u0443\u043a\u0430\u0437\u0430\u0432 \u043f\u043e \u043a\u0440\u0430\u0439\u043d\u0435\u0439 \u043c\u0435\u0440\u0435 1 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0443\u044e \u043a\u043e\u043d\u0435\u0447\u043d\u0443\u044e \u0442\u043e\u0447\u043a\u0443. + +jmx.rest.client.bad.user.credentials=CWWKX0229E: \u0412\u043e\u0437\u043d\u0438\u043a\u043b\u0430 \u043d\u0435\u043f\u043e\u043b\u0430\u0434\u043a\u0430 \u0441 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u043c\u0438 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438. \u0412 \u043e\u0442\u0432\u0435\u0442\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0431\u044b\u043b \u0443\u043a\u0430\u0437\u0430\u043d \u043a\u043e\u0434 {0} \u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 ''{1}'' +jmx.rest.client.bad.user.credentials.explanation=\u0418\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0443\u043a\u0430\u0437\u0430\u043d\u044b \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e, \u0443\u0441\u0442\u0430\u0440\u0435\u043b\u0438, \u043d\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u044b \u0438\u043b\u0438 \u043a \u043d\u0438\u043c \u0437\u0430\u043f\u0440\u0435\u0449\u0435\u043d \u0434\u043e\u0441\u0442\u0443\u043f. +jmx.rest.client.bad.user.credentials.useraction=\u0423\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c \u0432 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u044c\u0442\u0435 \u043d\u043e\u0432\u043e\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435. + +jmx.rest.client.connection.connect=CWWKX0230I: \u042d\u043b\u0435\u043c\u0435\u043d\u0442 \u0433\u0440\u0443\u043f\u043f\u044b \u043e\u0442\u043a\u0440\u044b\u043b \u043a\u043b\u0438\u0435\u043d\u0442 JMX \u0434\u043b\u044f \u0433\u0440\u0443\u043f\u043f\u043e\u0432\u043e\u0433\u043e \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430: {0} +jmx.rest.client.connection.connect.explanation=\u042d\u043b\u0435\u043c\u0435\u043d\u0442 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043b\u0441\u044f \u043a \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0443. +jmx.rest.client.connection.connect.useraction=\u041d\u0438\u043a\u0430\u043a\u0438\u0445 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f. + +jmx.rest.client.connection.disconnect=CWWKX0231I: \u042d\u043b\u0435\u043c\u0435\u043d\u0442 \u0433\u0440\u0443\u043f\u043f\u044b \u0437\u0430\u043a\u0440\u044b\u043b \u043a\u043b\u0438\u0435\u043d\u0442 JMX \u0434\u043b\u044f \u0433\u0440\u0443\u043f\u043f\u043e\u0432\u043e\u0433\u043e \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430: {0} +jmx.rest.client.connection.disconnect.explanation=\u042d\u043b\u0435\u043c\u0435\u043d\u0442 \u043e\u0442\u043a\u043b\u044e\u0447\u0438\u043b\u0441\u044f \u043e\u0442 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430. +jmx.rest.client.connection.disconnect.useraction=\u041d\u0438\u043a\u0430\u043a\u0438\u0445 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f. + diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_zh.nlsprops b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_zh.nlsprops new file mode 100755 index 00000000000..94beef54688 --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_zh.nlsprops @@ -0,0 +1,144 @@ +# IBM Confidential +# +# OCO Source Materials +# +# Copyright IBM Corp. 2012 +# +# The source code for this program is not published or otherwise divested +# of its trade secrets, irrespective of what has been deposited with the +# U.S. Copyright Office. +# +#CMVCPATHNAME com.ibm.ws.jmx.connector.client/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages.nlsprops +#ISMESSAGEFILE TRUE +#NLS_ENCODING=UNICODE +# +#COMPONENTPREFIX CWWKX +#COMPONENTNAMEFOR CWWKX JMX REST Client +# +# NLS_MESSAGEFORMAT_VAR +# +# Strings in this file which contain replacement variables are processed by the MessageFormat +# class (single quote must be coded as 2 consecutive single quotes ''). Strings in this file +# which do NOT contain replacement variables are NOT processed by the MessageFormat class +# (single quote must be coded as one single quote '). + +# Message prefix block: CWWKX0200-CWWKX0259 + +jmx.rest.client.request.error=CWWKX0201E: \u51c6\u5907\u5728\u8fde\u63a5 {1} \u4e0a\u4e3a URL {0} \u8bf7\u6c42\u670d\u52a1\u5668\u65f6\uff0cWebSphere Java Management Extensions REST \u5ba2\u6237\u673a\u9047\u5230\u9519\u8bef\u3002 +jmx.rest.client.request.error.explanation=\u51c6\u5907\u8bf7\u6c42\u670d\u52a1\u5668\u65f6\uff0cWebSphere Java Management Extensions REST \u5ba2\u6237\u673a\u9047\u5230\u9519\u8bef\u3002 +jmx.rest.client.request.error.useraction=\u8bf7\u68c0\u67e5\u670d\u52a1\u5668\u65e5\u5fd7\u4ee5\u83b7\u53d6\u66f4\u591a\u4fe1\u606f\u3002 + +jmx.rest.client.response.error=CWWKX0202E: WebSphere Java Management Extensions REST \u5ba2\u6237\u673a\u65e0\u6cd5\u5728\u8fde\u63a5 {1} \u4e0a\u4e3a URL {0} \u5904\u7406\u6765\u81ea\u670d\u52a1\u5668\u7684\u54cd\u5e94\u3002 +jmx.rest.client.response.error.explanation=WebSphere Java Management Extensions REST \u5ba2\u6237\u673a\u65e0\u6cd5\u5904\u7406\u6765\u81ea\u670d\u52a1\u5668\u7684\u54cd\u5e94\u3002 +jmx.rest.client.response.error.useraction=\u8bf7\u68c0\u67e5\u670d\u52a1\u5668\u65e5\u5fd7\u4ee5\u83b7\u53d6\u66f4\u591a\u4fe1\u606f\u3002 + +jmx.rest.client.response.code.error=CWWKX0203E: WebSphere Java Management Extensions REST \u5ba2\u6237\u673a\u5728\u8fde\u63a5 {3} \u4e0a\u4e3a URL {2} \u4ece\u670d\u52a1\u5668\u63a5\u6536\u5230\u5e26\u6709\u6d88\u606f\u201c{1}\u201d\u7684\u610f\u5916\u54cd\u5e94\u4ee3\u7801 {0}\u3002 +jmx.rest.client.response.code.error.explanation=WebSphere Java Management Extensions REST \u5ba2\u6237\u673a\u4ece\u670d\u52a1\u5668\u63a5\u6536\u5230\u610f\u5916\u54cd\u5e94\u4ee3\u7801\u3002 +jmx.rest.client.response.code.error.useraction=\u8bf7\u68c0\u67e5\u670d\u52a1\u5668\u65e5\u5fd7\u4ee5\u83b7\u53d6\u66f4\u591a\u4fe1\u606f\u3002 + +jmx.rest.client.server.throwable.exception=CWWKX0204E: \u65e0\u6cd5\u89e3\u6790\u670d\u52a1\u5668\u9519\u8bef\u6d41\u4e2d\u7684 Throwable\u3002 +jmx.rest.client.server.throwable.exception.explanation=\u670d\u52a1\u5668\u5728\u5904\u7406\u5ba2\u6237\u673a\u8bf7\u6c42\u65f6\u629b\u51fa\u4e86\u5f02\u5e38\uff0c\u4f46\u662f\u5ba2\u6237\u673a\u65e0\u6cd5\u89e3\u6790\u670d\u52a1\u5668\u9519\u8bef\u6d41\u4e2d\u7684 Throwable \u5bf9\u8c61\u3002Throwable \u5bf9\u8c61\u7684\u7c7b\u53ef\u80fd\u5bf9\u5ba2\u6237\u673a\u4e0d\u53ef\u7528\u3002 +jmx.rest.client.server.throwable.exception.useraction=\u8bf7\u68c0\u67e5\u670d\u52a1\u5668\u65e5\u5fd7\u4ee5\u83b7\u53d6\u66f4\u591a\u4fe1\u606f\u3002 + +jmx.rest.client.not.connected=CWWKX0206E: \u5ba2\u6237\u673a\u672a\u8fde\u63a5\u5230\u670d\u52a1\u5668\u3002 +jmx.rest.client.not.connected.explanation=\u4e0e\u670d\u52a1\u5668\u7684\u8fde\u63a5\u5df2\u5173\u95ed\u6216\u5df2\u5931\u8d25\u3002 +jmx.rest.client.not.connected.useraction=\u8bf7\u68c0\u67e5\u670d\u52a1\u5668\u4e0a\u662f\u5426\u5df2\u542f\u7528 REST \u8fde\u63a5\u5668\u529f\u80fd\u90e8\u4ef6\u5e76\u83b7\u53d6\u4e0e\u670d\u52a1\u5668\u7684\u65b0\u8fde\u63a5\u3002 + +jmx.rest.client.url.not.found=CWWKX0207E: \u670d\u52a1\u5668\u62a5\u544a\u672a\u627e\u5230\u5ba2\u6237\u673a\u6240\u8bf7\u6c42\u7684 URL\u3002 +jmx.rest.client.url.not.found.explanation=\u5ba2\u6237\u673a\u5177\u6709\u7684\u4fe1\u606f\u53ef\u80fd\u5df2\u8fc7\u65f6\uff0c\u6216\u8005\u53ef\u80fd\u5728\u670d\u52a1\u5668\u4e0a\u5df2\u7981\u7528 REST \u8fde\u63a5\u5668\u529f\u80fd\u90e8\u4ef6\u3002 +jmx.rest.client.url.not.found.useraction=\u8bf7\u68c0\u67e5\u670d\u52a1\u5668\u4e0a\u662f\u5426\u5df2\u542f\u7528 REST \u8fde\u63a5\u5668\u529f\u80fd\u90e8\u4ef6\u5e76\u83b7\u53d6\u4e0e\u670d\u52a1\u5668\u7684\u65b0\u8fde\u63a5\u3002 +jmx.rest.client.class.name.null=CWWKX0208E: \u7c7b\u540d\u81ea\u53d8\u91cf\u4e3a null\u3002 +jmx.rest.client.class.name.null.explanation=\u7c7b\u540d\u81ea\u53d8\u91cf\u4e0d\u5f97\u4e3a null\u3002 +jmx.rest.client.class.name.null.useraction=\u5728\u8c03\u7528\u65b9\u6cd5\u65f6\uff0c\u8bf7\u63d0\u4f9b\u975e null \u7c7b\u540d\u3002 + +jmx.rest.client.attribute.name.null=CWWKX0209E: \u5c5e\u6027\u540d\u81ea\u53d8\u91cf\u4e3a null\u3002 +jmx.rest.client.attribute.name.null.explanation=\u5c5e\u6027\u540d\u81ea\u53d8\u91cf\u4e0d\u5f97\u4e3a null\u3002 +jmx.rest.client.attribute.name.null.useraction=\u5728\u8c03\u7528\u65b9\u6cd5\u65f6\uff0c\u8bf7\u63d0\u4f9b\u975e null \u5c5e\u6027\u540d\u3002 + +jmx.rest.client.attribute.names.null=CWWKX0210E: \u5305\u542b\u4e00\u7cfb\u5217\u5c5e\u6027\u540d\u7684\u81ea\u53d8\u91cf\u4e3a null\u3002 +jmx.rest.client.attribute.names.null.explanation=\u5305\u542b\u4e00\u7cfb\u5217\u5c5e\u6027\u540d\u7684\u81ea\u53d8\u91cf\u4e0d\u5f97\u4e3a null\u3002 +jmx.rest.client.attribute.names.null.useraction=\u5728\u8c03\u7528\u65b9\u6cd5\u65f6\uff0c\u8bf7\u63d0\u4f9b\u4e00\u7ec4\u975e null \u5c5e\u6027\u540d\u3002 + +jmx.rest.client.attribute.null=CWWKX0211E: \u5c5e\u6027\u81ea\u53d8\u91cf\u4e3a null\u3002 +jmx.rest.client.attribute.null.explanation=\u5c5e\u6027\u81ea\u53d8\u91cf\u4e0d\u5f97\u4e3a null\u3002 +jmx.rest.client.attribute.null.useraction=\u5728\u8c03\u7528\u65b9\u6cd5\u65f6\uff0c\u8bf7\u63d0\u4f9b\u975e null \u5c5e\u6027\u3002 + +jmx.rest.client.attribute.list.null=CWWKX0212E: \u5c5e\u6027\u5217\u8868\u81ea\u53d8\u91cf\u4e3a null\u3002 +jmx.rest.client.attribute.list.null.explanation=\u5c5e\u6027\u5217\u8868\u81ea\u53d8\u91cf\u4e0d\u80fd\u4e3a null\u3002 +jmx.rest.client.attribute.list.null.useraction=\u5728\u8c03\u7528\u65b9\u6cd5\u65f6\uff0c\u8bf7\u63d0\u4f9b\u975e null \u5c5e\u6027\u5217\u8868\u3002 + +jmx.rest.client.object.name.null=CWWKX0213E: \u5bf9\u8c61\u540d\u81ea\u53d8\u91cf\u4e3a null\u3002 +jmx.rest.client.object.name.null.explanation=\u5bf9\u8c61\u540d\u81ea\u53d8\u91cf\u4e0d\u80fd\u4e3a null\u3002 +jmx.rest.client.object.name.null.useraction=\u5728\u8c03\u7528\u65b9\u6cd5\u65f6\uff0c\u8bf7\u63d0\u4f9b\u975e null \u5bf9\u8c61\u540d\u3002 + +jmx.rest.client.unexpected.server.throwable=CWWKX0214E: \u4ece\u670d\u52a1\u5668\u8fd4\u56de\u4e86\u610f\u5916\u7684 Throwable \u5bf9\u8c61\u3002 +jmx.rest.client.unexpected.server.throwable.explanation=\u6b64\u5f02\u5e38\u5305\u542b\u4ece\u670d\u52a1\u5668\u8fd4\u56de\u7684 Throwable \u5bf9\u8c61\uff0c\u6b64\u5bf9\u8c61\u901a\u67e5\u4e0d\u662f\u6b64\u64cd\u4f5c\u6240\u671f\u671b\u7684\u3002 +jmx.rest.client.unexpected.server.throwable.useraction=\u8bf7\u68c0\u67e5\u670d\u52a1\u5668\u65e5\u5fd7\u4ee5\u83b7\u53d6\u66f4\u591a\u4fe1\u606f\u3002 + +jmx.rest.client.bad.credentials=CWWKX0215E: \u63d0\u4f9b\u7684\u7528\u6237\u540d\u6216\u5bc6\u7801\u5b58\u5728\u95ee\u9898\u3002\u670d\u52a1\u5668\u4ee5\u4ee3\u7801 {0} \u548c\u6d88\u606f\u201c{1}\u201d\u4f5c\u4e3a\u54cd\u5e94 +jmx.rest.client.bad.credentials.explanation=\u83b7\u53d6\u8fde\u63a5\u65f6\u63d0\u4f9b\u7684\u51ed\u8bc1\u4e0d\u6b63\u786e\u3002\u7528\u6237\u53ef\u80fd\u4e0d\u5b58\u5728\u6216\u4e0d\u5177\u6709\u8bbf\u95ee\u670d\u52a1\u5668\u7684\u6743\u9650\uff0c\u6216\u8005\u5bc6\u7801\u53ef\u80fd\u4e0d\u6b63\u786e\u3002 +jmx.rest.client.bad.credentials.useraction=\u66f4\u6b63\u7528\u6237\u540d\u6216\u5bc6\u7801\uff0c\u7136\u540e\u83b7\u53d6\u4e00\u4e2a\u65b0\u8fde\u63a5\u3002 + +jmx.rest.client.object.name.pattern=CWWKX0216E: \u5bf9\u8c61\u540d\u81ea\u53d8\u91cf\u201c{0}\u201d\u662f\u4e00\u4e2a\u6a21\u5f0f\u3002" +jmx.rest.client.object.name.pattern.explanation=\u5bf9\u8c61\u540d\u81ea\u53d8\u91cf\u662f\u4e00\u4e2a\u6a21\u5f0f\uff0c\u4f46\u65b9\u6cd5\u9700\u8981\u7684\u662f\u4e0e\u4e00\u4e2a MBean \u5b8c\u5168\u5339\u914d\u7684\u5bf9\u8c61\u540d\u3002 +jmx.rest.client.object.name.pattern.useraction=\u8bf7\u63d0\u4f9b\u4e00\u4e2a\u4e0d\u5305\u542b\u901a\u914d\u7b26\u4e14\u4e0e\u4e00\u4e2a MBean \u5b8c\u5168\u5339\u914d\u7684\u5bf9\u8c61\u540d\u81ea\u53d8\u91cf\u3002 + +jmx.rest.client.instance.not.found=CWWKX0217E: \u5f53\u524d\u672a\u6ce8\u518c\u5177\u6709\u7ed9\u5b9a\u7684\u5bf9\u8c61\u540d\u201c {0}\u201d\u7684 MBean\u3002 +jmx.rest.client.instance.not.found.explanation=\u64cd\u4f5c\u9700\u8981\u6ce8\u518c\u7684 MBean\uff0c\u4f46\u662f\u672a\u6ce8\u518c\u5177\u6709\u7ed9\u5b9a\u7684\u5bf9\u8c61\u540d\u7684 MBean\u3002 +jmx.rest.client.instance.not.found.useraction=\u8bf7\u786e\u4fdd\u5728\u5c1d\u8bd5\u5bf9 MBean \u6267\u884c\u7ba1\u7406\u64cd\u4f5c\u524d\uff0c\u5df2\u5bf9\u5176\u8fdb\u884c\u6ce8\u518c\u3002 + +jmx.rest.client.attribute.not.found=CWWKX0218E: MBean\u201c{0}\u201d\u4e0d\u5177\u6709\u540d\u79f0\u4e3a\u201c{1}\u201d\u7684\u5c5e\u6027 +jmx.rest.client.attribute.not.found.explanation=MBean \u672a\u63d0\u4f9b\u5177\u6709\u7ed9\u5b9a\u540d\u79f0\u7684\u5c5e\u6027\u3002 +jmx.rest.client.attribute.not.found.useraction=\u83b7\u53d6 MBean \u4fe1\u606f\u4ee5\u786e\u8ba4 MBean \u6240\u63d0\u4f9b\u7684\u5c5e\u6027\u3002 + +jmx.rest.client.operation.not.found=CWWKX0219E: MBean\u201c{0}\u201d\u4e0d\u5177\u6709\u540d\u79f0\u4e3a\u201c{1}\u201d\u7684\u64cd\u4f5c +jmx.rest.client.operation.not.found.explanation=MBean \u672a\u63d0\u4f9b\u5177\u6709\u7ed9\u5b9a\u540d\u79f0\u7684\u64cd\u4f5c\u3002 +jmx.rest.client.operation.not.found.useraction=\u83b7\u53d6 MBean \u4fe1\u606f\u4ee5\u786e\u8ba4 MBean \u6240\u63d0\u4f9b\u7684\u64cd\u4f5c\u3002 + +jmx.rest.client.listener.not.found=CWWKX0220E: \u7ed9\u5b9a\u7684\u901a\u77e5\u4fa6\u542c\u5668\u5f53\u524d\u672a\u6ce8\u518c\u4e3a\u63a5\u6536\u6765\u81ea MBean\u201c{0}\u201d\u7684\u901a\u77e5 +jmx.rest.client.listener.not.found.explanation=\u672a\u6dfb\u52a0\u901a\u77e5\u4fa6\u542c\u5668\u6216\u8005\u5df2\u5c06\u5176\u9664\u53bb\uff0c\u5e76\u4e14\u901a\u77e5\u4fa6\u542c\u5668\u5f53\u524d\u672a\u6ce8\u518c\u4e3a\u63a5\u6536\u6765\u81ea\u7ed9\u5b9a\u7684 MBean \u7684\u901a\u77e5\u3002 +jmx.rest.client.listener.not.found.useraction=\u8bf7\u786e\u4fdd\u8c03\u7528\u4ee3\u7801\u8ddf\u8e2a\u6dfb\u52a0\u548c\u9664\u53bb\u7684\u901a\u77e5\u4fa6\u542c\u5668\u6216\u83b7\u53d6\u548c\u5904\u7406\u5f02\u5e38\u3002 + +jmx.rest.client.notification.lost=CWWKX0221I: \u65e0\u6cd5\u4f20\u9012\u901a\u77e5. +jmx.rest.client.notification.lost.explanation=\u65e0\u6cd5\u5c06\u901a\u77e5\u4f20\u9012\u7ed9\u4e00\u4e2a\u6216\u591a\u4e2a\u901a\u77e5\u4fa6\u542c\u5668\uff0c\u56e0\u4e3a\u672a\u627e\u5230\u5df2\u6ce8\u518c\u901a\u77e5\u4fa6\u542c\u5668\u6216\u5728\u4f20\u9012\u901a\u77e5\u65f6\u53d1\u751f\u4e86\u5f02\u5e38\u3002 +jmx.rest.client.notification.lost.useraction=\u5982\u679c\u901a\u77e5\u5e94\u4f20\u9012\u7ed9\u5df2\u6ce8\u518c\u901a\u77e5\u4fa6\u542c\u5668\uff0c\u8bf7\u68c0\u67e5\u65e5\u5fd7\u4ee5\u67e5\u627e\u5f02\u5e38\u3002 + +jmx.rest.client.connection.failed=CWWKX0222I: \u4e0e\u670d\u52a1\u5668\u7684\u8fde\u63a5\u5df2\u5931\u8d25\u3002 +jmx.rest.client.connection.failed.explanation=\u670d\u52a1\u5668\u53d8\u5f97\u4e0d\u53ef\u7528\uff0c\u5e76\u4e14\u5728\u914d\u7f6e\u7684\u6700\u5927\u5141\u8bb8\u65f6\u95f4\u5185\u4e0d\u4f1a\u518d\u6b21\u53d8\u5f97\u53ef\u7528\u3002 +jmx.rest.client.connection.failed.useraction=\u8bf7\u68c0\u67e5\u7f51\u7edc\u8fde\u63a5\u5e76\u786e\u4fdd\u670d\u52a1\u5668\u6b63\u5728\u8fd0\u884c\uff08\u5df2\u542f\u7528 REST \u8fde\u63a5\u5668\u529f\u80fd\u90e8\u4ef6\uff09\u3002 + +jmx.rest.client.connection.temporarily.lost=CWWKX0223I: \u4e0e\u670d\u52a1\u5668\u7684\u8fde\u63a5\u6682\u65f6\u5df2\u65ad\u5f00\u3002 +jmx.rest.client.connection.temporarily.lost.explanation=\u670d\u52a1\u5668\u5df2\u53d8\u5f97\u4e0d\u53ef\u7528\uff0c\u4f46\u662f\u5ba2\u6237\u673a\u5c06\u5728\u914d\u7f6e\u7684\u6700\u5927\u5141\u8bb8\u65f6\u95f4\u5185\u5c1d\u8bd5\u590d\u539f\u94fe\u63a5\u3002 +jmx.rest.client.connection.temporarily.lost.useraction=\u5982\u679c\u6b63\u5728\u6709\u610f\u5730\u91cd\u65b0\u542f\u52a8\u670d\u52a1\u5668\uff0c\u90a3\u4e48\u4e0d\u9700\u8981\u6267\u884c\u4efb\u4f55\u64cd\u4f5c\u3002\u5426\u5219\uff0c\u8bf7\u68c0\u67e5\u7f51\u7edc\u8fde\u63a5\u5e76\u786e\u4fdd\u670d\u52a1\u5668\u6b63\u5728\u8fd0\u884c\uff08\u5df2\u542f\u7528 REST \u8fde\u63a5\u5668\u529f\u80fd\u90e8\u4ef6\uff09\u3002 + +jmx.rest.client.connection.restored.with.exceptions=CWWKX0224I: \u8fde\u63a5\u5df2\u590d\u539f\uff0c\u4f46\u5728\u6dfb\u52a0\u901a\u77e5\u4fa6\u542c\u5668\u65f6\u53d1\u751f\u4e86\u5f02\u5e38\u3002 +jmx.rest.client.connection.restored.with.exceptions.explanation=\u4e0e\u670d\u52a1\u5668\u7684\u8fde\u63a5\u4e34\u65f6\u65ad\u5f00\uff0c\u4f46\u5df2\u6210\u529f\u590d\u539f\u3002\u6dfb\u52a0\u901a\u77e5\u4fa6\u542c\u5668\u65f6\u53d1\u751f\u4e86\u5f02\u5e38\uff0c\u56e0\u6b64\u53ef\u80fd\u4e0d\u4f1a\u63a5\u6536\u5230\u67d0\u4e9b\u901a\u77e5\u3002 +jmx.rest.client.connection.restored.with.exceptions.useraction=\u8bf7\u68c0\u67e5\u901a\u77e5\u4e2d\u5305\u542b\u7684\u5f02\u5e38\u5e76\u5728\u66f4\u6b63\u95ee\u9898\u540e\u91cd\u65b0\u6ce8\u518c\u901a\u77e5\u4fa6\u542c\u5668\u3002 + +jmx.rest.client.connection.restored=CWWKX0225I: \u8fde\u63a5\u5df2\u6210\u529f\u590d\u539f\u3002 +jmx.rest.client.connection.restored.explanation=\u4e0e\u670d\u52a1\u5668\u7684\u8fde\u63a5\u4e34\u65f6\u65ad\u5f00\uff0c\u4f46\u5df2\u6210\u529f\u590d\u539f\u3002\u4efb\u4f55\u5df2\u6ce8\u518c\u901a\u77e5\u76d1\u89c6\u5668\u5c06\u7ee7\u7eed\u6536\u5230\u901a\u77e5\u3002 +jmx.rest.client.connection.restored.useraction=\u65e0 + +jmx.rest.client.connection.illegal.argument=CWWKX0226E: \u7c7b\u578b\u4e3a JMXServiceURL \u7684\u53c2\u6570\u4e0d\u80fd\u4e3a null\u3002 +jmx.rest.client.connection.illegal.argument.explanation=\u53c2\u6570\u201cserviceURL\u201d\u7684\u503c\u4e0d\u80fd\u4e3a null\u3002 +jmx.rest.client.connection.illegal.argument.useraction=\u8bf7\u4f7f\u7528\u975e\u7a7a JMXServiceURL \u503c\u91cd\u65b0\u8fde\u63a5\u81f3 JMX REST \u8fde\u63a5\u5668\u3002 + +jmx.rest.client.connection.invalid.endpoint=CWWKX0227E: \u4ee5\u4e0b\u7aef\u70b9\u503c\u65e0\u6548\uff1a{0} +jmx.rest.client.connection.invalid.endpoint.explanation=\u6307\u5b9a\u7684\u7aef\u70b9\u503c\u65e0\u6548\u3002 +jmx.rest.client.connection.invalid.endpoint.useraction=\u8bf7\u4f7f\u7528\u7c7b\u578b\u4e3a\u201c\u5b57\u7b26\u4e32\u201d\u4e14\u683c\u5f0f\u4e3a\u201chost:port\u201d\u7684\u6709\u6548\u7aef\u70b9\u503c\u91cd\u65b0\u8fde\u63a5\u81f3 JMX REST \u8fde\u63a5\u5668\u3002 + +jmx.rest.client.connection.no.endpoints=CWWKX0228E: \u627e\u4e0d\u5230\u4efb\u4f55\u53ef\u7528\u4e8e\u521d\u59cb\u5316\u8fde\u63a5\u5668\u7684\u7aef\u70b9\u3002 +jmx.rest.client.connection.no.endpoints.explanation=JMX REST \u8fde\u63a5\u5668\u521d\u59cb\u5316\u521d\u59cb\u5316\u671f\u95f4\u6ca1\u6709\u4efb\u4f55\u4e00\u4e2a\u6307\u5b9a\u7aef\u70b9\u53ef\u7528\u3002 +jmx.rest.client.connection.no.endpoints.useraction=\u8bf7\u81f3\u5c11\u4f7f\u7528 1 \u4e2a\u53ef\u7528\u7aef\u70b9\u91cd\u65b0\u8fde\u63a5\u81f3 JMX REST \u8fde\u63a5\u5668\u3002 + +jmx.rest.client.bad.user.credentials=CWWKX0229E: \u63d0\u4f9b\u7684\u7528\u6237\u51ed\u8bc1\u5b58\u5728\u95ee\u9898\u3002\u670d\u52a1\u5668\u4ee5\u4ee3\u7801 {0} \u548c\u6d88\u606f\u201c{1}\u201d\u4f5c\u4e3a\u54cd\u5e94 +jmx.rest.client.bad.user.credentials.explanation=\u63d0\u4f9b\u7684\u51ed\u8bc1\u4e0d\u6b63\u786e\u3001\u5df2\u5230\u671f\u3001\u4e0d\u5b8c\u6574\u6216\u4e3a\u62d2\u7edd\u7684\u6388\u6743\u3002 +jmx.rest.client.bad.user.credentials.useraction=\u9a8c\u8bc1\u7528\u6237\u51ed\u8bc1\u662f\u5426\u5177\u6709\u6b63\u786e\u8ba4\u8bc1\u548c\u6388\u6743\uff0c\u7136\u540e\u83b7\u53d6\u65b0\u8fde\u63a5\u3002 + +jmx.rest.client.connection.connect=CWWKX0230I: \u96c6\u5408\u4f53\u6210\u5458\u6253\u5f00\u4e86 JMX \u5ba2\u6237\u673a\u5230\u96c6\u5408\u4f53\u63a7\u5236\u5668\uff1a{0} +jmx.rest.client.connection.connect.explanation=\u6210\u5458\u5df2\u8fde\u63a5\u81f3\u63a7\u5236\u5668\u3002 +jmx.rest.client.connection.connect.useraction=\u4e0d\u9700\u8981\u6267\u884c\u4efb\u4f55\u64cd\u4f5c\u3002 +jmx.rest.client.connection.disconnect=CWWKX0231I: \u96c6\u5408\u4f53\u6210\u5458\u4ece\u96c6\u5408\u4f53\u63a7\u5236\u5668\u5173\u95ed\u4e86 JMX \u5ba2\u6237\u673a\uff1a{0} +jmx.rest.client.connection.disconnect.explanation=\u6210\u5458\u5df2\u4e0e\u63a7\u5236\u5668\u65ad\u5f00\u8fde\u63a5\u3002 +jmx.rest.client.connection.disconnect.useraction=\u4e0d\u9700\u8981\u6267\u884c\u4efb\u4f55\u64cd\u4f5c\u3002 + diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_zh_TW.nlsprops b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_zh_TW.nlsprops new file mode 100755 index 00000000000..d2f4d3951ea --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages_zh_TW.nlsprops @@ -0,0 +1,143 @@ +# IBM Confidential +# +# OCO Source Materials +# +# Copyright IBM Corp. 2012 +# +# The source code for this program is not published or otherwise divested +# of its trade secrets, irrespective of what has been deposited with the +# U.S. Copyright Office. +# +#CMVCPATHNAME com.ibm.ws.jmx.connector.client/resources/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessages.nlsprops +#ISMESSAGEFILE TRUE +#NLS_ENCODING=UNICODE +# +#COMPONENTPREFIX CWWKX +#COMPONENTNAMEFOR CWWKX JMX REST Client +# +# NLS_MESSAGEFORMAT_VAR +# +# Strings in this file which contain replacement variables are processed by the MessageFormat +# class (single quote must be coded as 2 consecutive single quotes ''). Strings in this file +# which do NOT contain replacement variables are NOT processed by the MessageFormat class +# (single quote must be coded as one single quote '). + +# Message prefix block: CWWKX0200-CWWKX0259 + +jmx.rest.client.request.error=CWWKX0201E: WebSphere Java Management Extensions REST \u7528\u6236\u7aef\u5728\u6e96\u5099\u5c0d\u9023\u7dda {1} \u4e0a URL {0} \u7684\u4f3a\u670d\u5668\u63d0\u51fa\u8981\u6c42\u6642\uff0c\u767c\u73fe\u932f\u8aa4 +jmx.rest.client.request.error.explanation=WebSphere Java Management Extensions REST \u7528\u6236\u7aef\u5728\u6e96\u5099\u4f3a\u670d\u5668\u7684\u8981\u6c42\u6642\uff0c\u767c\u73fe\u932f\u8aa4 +jmx.rest.client.request.error.useraction=\u8acb\u6aa2\u67e5\u4f3a\u670d\u5668\u65e5\u8a8c\uff0c\u4ee5\u53d6\u5f97\u9032\u4e00\u6b65\u8cc7\u8a0a\u3002 + +jmx.rest.client.response.error=CWWKX0202E: WebSphere Java Management Extensions REST \u7528\u6236\u7aef\u7121\u6cd5\u8655\u7406\u4f86\u81ea\u4f3a\u670d\u5668\u91dd\u5c0d\u9023\u7dda {1} \u4e0a\u7684 URL {0} \u7684\u56de\u61c9 +jmx.rest.client.response.error.explanation=WebSphere Java Management Extensions REST \u7528\u6236\u7aef\u7121\u6cd5\u8655\u7406\u4f86\u81ea\u4f3a\u670d\u5668\u7684\u56de\u61c9 +jmx.rest.client.response.error.useraction=\u8acb\u6aa2\u67e5\u4f3a\u670d\u5668\u65e5\u8a8c\uff0c\u4ee5\u53d6\u5f97\u9032\u4e00\u6b65\u8cc7\u8a0a\u3002 + +jmx.rest.client.response.code.error=CWWKX0203E: WebSphere Java Management Extensions REST \u7528\u6236\u7aef\u63a5\u6536\u5230\u4f86\u81ea\u4f3a\u670d\u5668\u91dd\u5c0d\u9023\u7dda {3} \u4e0a\u7684 URL {2} \u7684\u975e\u9810\u671f\u56de\u61c9\u78bc {0}\uff0c\u5e36\u6709\u8a0a\u606f ''{1}'' +jmx.rest.client.response.code.error.explanation=WebSphere Java Management Extensions REST \u7528\u6236\u7aef\u63a5\u6536\u5230\u4f86\u81ea\u4f3a\u670d\u5668\u7684\u975e\u9810\u671f\u56de\u61c9\u78bc +jmx.rest.client.response.code.error.useraction=\u8acb\u6aa2\u67e5\u4f3a\u670d\u5668\u65e5\u8a8c\uff0c\u4ee5\u53d6\u5f97\u9032\u4e00\u6b65\u8cc7\u8a0a\u3002 + +jmx.rest.client.server.throwable.exception=CWWKX0204E: \u7121\u6cd5\u5f9e\u4f3a\u670d\u5668\u932f\u8aa4\u4e32\u6d41\u4f86\u5256\u6790 Throwable\u3002 +jmx.rest.client.server.throwable.exception.explanation=\u4f3a\u670d\u5668\u5728\u8655\u7406\u7528\u6236\u7aef\u8981\u6c42\u6642\uff0c\u5f15\u767c\u7570\u5e38\u72c0\u6cc1\uff0c\u4f46\u662f\u7528\u6236\u7aef\u7121\u6cd5\u5f9e\u4f3a\u670d\u5668\u932f\u8aa4\u4e32\u6d41\u4f86\u5256\u6790 Throwable \u7269\u4ef6\u3002\u7528\u6236\u7aef\u53ef\u80fd\u7121\u6cd5\u4f7f\u7528 Throwable \u7269\u4ef6\u7684\u985e\u5225\u3002 +jmx.rest.client.server.throwable.exception.useraction=\u8acb\u6aa2\u67e5\u4f3a\u670d\u5668\u65e5\u8a8c\uff0c\u4ee5\u53d6\u5f97\u9032\u4e00\u6b65\u8cc7\u8a0a\u3002 + +jmx.rest.client.not.connected=CWWKX0206E: \u7528\u6236\u7aef\u6c92\u6709\u9023\u63a5\u4f3a\u670d\u5668\u3002 +jmx.rest.client.not.connected.explanation=\u4f3a\u670d\u5668\u9023\u7dda\u5df2\u95dc\u9589\u6216\u5931\u6557\u3002 +jmx.rest.client.not.connected.useraction=\u8acb\u6aa2\u67e5\u4f3a\u670d\u5668\u4e0a\u662f\u5426\u5df2\u555f\u7528 REST \u9023\u63a5\u5668\u7279\u6027\uff0c\u4e26\u53d6\u5f97\u65b0\u7684\u4f3a\u670d\u5668\u9023\u7dda\u3002 + +jmx.rest.client.url.not.found=CWWKX0207E: \u4f3a\u670d\u5668\u5831\u544a\u627e\u4e0d\u5230\u7528\u6236\u7aef\u6240\u8981\u6c42\u7684 URL\u3002 +jmx.rest.client.url.not.found.explanation=\u7528\u6236\u7aef\u7684\u8cc7\u8a0a\u5df2\u904e\u671f\uff0c\u6216\u8005\u4f3a\u670d\u5668\u4e0a\u7684 REST \u9023\u63a5\u5668\u7279\u6027\u53ef\u80fd\u5df2\u505c\u7528\u3002 +jmx.rest.client.url.not.found.useraction=\u8acb\u6aa2\u67e5\u4f3a\u670d\u5668\u4e0a\u662f\u5426\u5df2\u555f\u7528 REST \u9023\u63a5\u5668\u7279\u6027\uff0c\u4e26\u53d6\u5f97\u65b0\u7684\u4f3a\u670d\u5668\u9023\u7dda\u3002 +jmx.rest.client.class.name.null=CWWKX0208E: \u985e\u5225\u540d\u7a31\u5f15\u6578\u70ba\u7a7a\u503c\u3002 +jmx.rest.client.class.name.null.explanation=\u985e\u5225\u540d\u7a31\u5f15\u6578\u4e0d\u5f97\u70ba\u7a7a\u503c\u3002 +jmx.rest.client.class.name.null.useraction=\u8acb\u5728\u547c\u53eb\u65b9\u6cd5\u6642\uff0c\u63d0\u4f9b\u975e\u7a7a\u503c\u7684\u985e\u5225\u540d\u7a31\u3002 + +jmx.rest.client.attribute.name.null=CWWKX0209E: \u5c6c\u6027\u540d\u7a31\u5f15\u6578\u70ba\u7a7a\u503c\u3002 +jmx.rest.client.attribute.name.null.explanation=\u5c6c\u6027\u540d\u7a31\u5f15\u6578\u4e0d\u5f97\u70ba\u7a7a\u503c\u3002 +jmx.rest.client.attribute.name.null.useraction=\u8acb\u5728\u547c\u53eb\u65b9\u6cd5\u6642\uff0c\u63d0\u4f9b\u975e\u7a7a\u503c\u7684\u5c6c\u6027\u540d\u7a31\u3002 + +jmx.rest.client.attribute.names.null=CWWKX0210E: \u5305\u542b\u5c6c\u6027\u540d\u7a31\u9663\u5217\u7684\u5f15\u6578\u70ba\u7a7a\u503c\u3002 +jmx.rest.client.attribute.names.null.explanation=\u5305\u542b\u5c6c\u6027\u540d\u7a31\u9663\u5217\u7684\u5f15\u6578\u4e0d\u5f97\u70ba\u7a7a\u503c\u3002 +jmx.rest.client.attribute.names.null.useraction=\u8acb\u5728\u547c\u53eb\u65b9\u6cd5\u6642\uff0c\u63d0\u4f9b\u975e\u7a7a\u503c\u7684\u5c6c\u6027\u540d\u7a31\u9663\u5217\u3002 + +jmx.rest.client.attribute.null=CWWKX0211E: Attribute \u5f15\u6578\u70ba\u7a7a\u503c\u3002 +jmx.rest.client.attribute.null.explanation=Attribute \u5f15\u6578\u4e0d\u5f97\u70ba\u7a7a\u503c\u3002 +jmx.rest.client.attribute.null.useraction=\u8acb\u5728\u547c\u53eb\u65b9\u6cd5\u6642\uff0c\u63d0\u4f9b\u975e\u7a7a\u503c\u7684 Attribute\u3002 + +jmx.rest.client.attribute.list.null=CWWKX0212E: AttributeList \u5f15\u6578\u70ba\u7a7a\u503c\u3002 +jmx.rest.client.attribute.list.null.explanation=AttributeList \u5f15\u6578\u4e0d\u5f97\u70ba\u7a7a\u503c\u3002 +jmx.rest.client.attribute.list.null.useraction=\u8acb\u5728\u547c\u53eb\u65b9\u6cd5\u6642\uff0c\u63d0\u4f9b\u975e\u7a7a\u503c\u7684 AttributeList\u3002 + +jmx.rest.client.object.name.null=CWWKX0213E: ObjectName \u5f15\u6578\u70ba\u7a7a\u503c\u3002 +jmx.rest.client.object.name.null.explanation=ObjectName \u5f15\u6578\u4e0d\u5f97\u70ba\u7a7a\u503c\u3002 +jmx.rest.client.object.name.null.useraction=\u8acb\u5728\u547c\u53eb\u65b9\u6cd5\u6642\uff0c\u63d0\u4f9b\u975e\u7a7a\u503c\u7684 ObjectName\u3002 + +jmx.rest.client.unexpected.server.throwable=CWWKX0214E: \u4f3a\u670d\u5668\u50b3\u56de\u975e\u9810\u671f\u7684 Throwable \u7269\u4ef6\u3002 +jmx.rest.client.unexpected.server.throwable.explanation=\u7570\u5e38\u72c0\u6cc1\u542b\u62ec\u4e00\u500b\u4f3a\u670d\u5668\u6240\u50b3\u56de\u7684 Throwable \u7269\u4ef6\uff0c\u5c0d\u9019\u9805\u4f5c\u696d\u4f86\u8aaa\uff0c\u9019\u901a\u5e38\u4e0d\u662f\u6240\u9810\u671f\u7684\u3002 +jmx.rest.client.unexpected.server.throwable.useraction=\u8acb\u6aa2\u67e5\u4f3a\u670d\u5668\u65e5\u8a8c\uff0c\u4ee5\u53d6\u5f97\u9032\u4e00\u6b65\u8cc7\u8a0a\u3002 + +jmx.rest.client.bad.credentials=CWWKX0215E: \u6240\u63d0\u4f9b\u7684\u4f7f\u7528\u8005\u540d\u7a31\u6216\u5bc6\u78bc\u6709\u554f\u984c\u3002\u4f3a\u670d\u5668\u7684\u56de\u61c9\u78bc\u662f {0}\uff0c\u8a0a\u606f\u662f ''{1}'' +jmx.rest.client.bad.credentials.explanation=\u5728\u53d6\u5f97\u9023\u7dda\u6642\u6240\u63d0\u4f9b\u7684\u8a8d\u8b49\u4e0d\u6b63\u78ba\u3002\u53ef\u80fd\u662f\u4f7f\u7528\u8005\u4e0d\u5b58\u5728\u3001\u4e0d\u5177\u5099\u4f3a\u670d\u5668\u7684\u5b58\u53d6\u6b0a\uff0c\u6216\u8005\u5bc6\u78bc\u4e0d\u6b63\u78ba\u3002 +jmx.rest.client.bad.credentials.useraction=\u8acb\u66f4\u6b63\u4f7f\u7528\u8005\u540d\u7a31\u6216\u5bc6\u78bc\uff0c\u7136\u5f8c\u53d6\u5f97\u65b0\u9023\u7dda\u3002 + +jmx.rest.client.object.name.pattern=CWWKX0216E: ObjectName \u5f15\u6578 ''{0}'' \u662f\u4e00\u500b\u578b\u6a23\u3002 +jmx.rest.client.object.name.pattern.explanation=ObjectName \u5f15\u6578\u662f\u578b\u6a23\uff0c\u4f46\u662f\u65b9\u6cd5\u6240\u9700\u8981\u7684 ObjectName \u5fc5\u9808\u53ea\u7b26\u5408\u4e00\u500b MBean\u3002 +jmx.rest.client.object.name.pattern.useraction=\u8acb\u63d0\u4f9b\u6c92\u6709\u842c\u7528\u5b57\u5143\u4e14\u53ea\u7b26\u5408\u4e00\u500b MBean \u7684 ObjectName \u5f15\u6578\u3002 + +jmx.rest.client.instance.not.found=CWWKX0217E: \u76ee\u524d\u672a\u767b\u9304\u4efb\u4f55\u4e00\u500b\u4f7f\u7528\u7d66\u5b9a ObjectName ''{0}'' \u7684 MBean +jmx.rest.client.instance.not.found.explanation=\u4f5c\u696d\u9700\u8981\u5df2\u767b\u9304\u7684 MBean\uff0c\u4f46\u537b\u672a\u767b\u9304\u4efb\u4f55\u4f7f\u7528\u7d66\u5b9a ObjectName \u7684 MBean\u3002 +jmx.rest.client.instance.not.found.useraction=\u8acb\u5148\u78ba\u5b9a\u5df2\u767b\u9304 MBean\uff0c\u518d\u5617\u8a66\u5c0d\u5b83\u57f7\u884c\u7ba1\u7406\u4f5c\u696d\u3002 + +jmx.rest.client.attribute.not.found=CWWKX0218E: MBean ''{0}'' \u6c92\u6709\u4e00\u500b\u540d\u7a31\u70ba ''{1}'' \u7684\u5c6c\u6027 +jmx.rest.client.attribute.not.found.explanation=MBean \u6c92\u6709\u63d0\u4f9b\u7d66\u5b9a\u540d\u7a31\u7684\u5c6c\u6027\u3002 +jmx.rest.client.attribute.not.found.useraction=\u8acb\u53d6\u5f97 MBean \u8cc7\u8a0a\uff0c\u4ee5\u78ba\u8a8d MBean \u6240\u63d0\u4f9b\u7684\u5c6c\u6027\u3002 + +jmx.rest.client.operation.not.found=CWWKX0219E: MBean ''{0}'' \u6c92\u6709\u4e00\u500b\u540d\u7a31\u70ba ''{1}'' \u7684\u4f5c\u696d +jmx.rest.client.operation.not.found.explanation=MBean \u6c92\u6709\u63d0\u4f9b\u7d66\u5b9a\u540d\u7a31\u7684\u4f5c\u696d\u3002 +jmx.rest.client.operation.not.found.useraction=\u8acb\u53d6\u5f97 MBean \u8cc7\u8a0a\uff0c\u4ee5\u78ba\u8a8d MBean \u6240\u63d0\u4f9b\u7684\u4f5c\u696d\u3002 + +jmx.rest.client.listener.not.found=CWWKX0220E: \u76ee\u524d\u672a\u767b\u9304\u7d66\u5b9a NotificationListener\uff0c\u4ee5\u4fbf\u63a5\u6536\u4f86\u81ea MBean ''{0}'' \u7684\u901a\u77e5 +jmx.rest.client.listener.not.found.explanation=NotificationListener \u672a\u65b0\u589e\u6216\u8005\u5df2\u79fb\u9664\uff0c\u4e14\u76ee\u524d\u672a\u767b\u9304\u4f86\u63a5\u53d7\u4f86\u81ea\u7d66\u5b9a MBean \u7684\u901a\u77e5\u3002 +jmx.rest.client.listener.not.found.useraction=\u8acb\u78ba\u5b9a\u547c\u53eb\u7a0b\u5f0f\u78bc\u6703\u8ffd\u8e64\u5df2\u65b0\u589e\u8207\u79fb\u9664\u4e86\u54ea\u4e9b NotificationListener\uff0c\u6216\u662f\u6355\u6349\u6216\u8655\u7406\u7570\u5e38\u72c0\u6cc1\u3002 + +jmx.rest.client.notification.lost=CWWKX0221I: \u7121\u6cd5\u905e\u9001\u901a\u77e5\u3002 +jmx.rest.client.notification.lost.explanation=\u7121\u6cd5\u5c07\u901a\u77e5\u905e\u9001\u7d66\u4e00\u6216\u591a\u500b NotificationListener\uff0c\u56e0\u70ba\u627e\u4e0d\u5230\u5df2\u767b\u9304\u7684 NotificationListener\uff0c\u6216\u8005\u5728\u905e\u9001\u901a\u77e5\u671f\u9593\uff0c\u767c\u751f\u7570\u5e38\u72c0\u6cc1\u3002 +jmx.rest.client.notification.lost.useraction=\u5982\u679c\u901a\u77e5\u61c9\u5df2\u905e\u9001\u7d66\u5df2\u767b\u9304\u7684 NotificationListener\uff0c\u8acb\u6aa2\u67e5\u65e5\u8a8c\u4e2d\u662f\u5426\u6709\u7570\u5e38\u72c0\u6cc1\u3002 + +jmx.rest.client.connection.failed=CWWKX0222I: \u9023\u63a5\u4f3a\u670d\u5668\u5931\u6557\u3002 +jmx.rest.client.connection.failed.explanation=\u4f3a\u670d\u5668\u8b8a\u6210\u7121\u6cd5\u4f7f\u7528\uff0c\u4e14\u5728\u6240\u914d\u7f6e\u7684\u5bb9\u8a31\u6642\u9593\u4e0a\u9650\u4e4b\u5167\uff0c\u7121\u6cd5\u91cd\u65b0\u8b8a\u6210\u53ef\u7528\u7684\u3002 +jmx.rest.client.connection.failed.useraction=\u8acb\u6aa2\u67e5\u7db2\u8def\u9023\u7dda\uff0c\u4e26\u78ba\u5b9a\u4f3a\u670d\u5668\u6b63\u5728\u57f7\u884c\uff0c\u4e14\u5df2\u555f\u7528\u4e86 REST \u9023\u63a5\u5668\u7279\u6027\u3002 + +jmx.rest.client.connection.temporarily.lost=CWWKX0223I: \u4f3a\u670d\u5668\u9023\u7dda\u66ab\u6642\u907a\u5931\u3002 +jmx.rest.client.connection.temporarily.lost.explanation=\u4f3a\u670d\u5668\u8b8a\u6210\u7121\u6cd5\u4f7f\u7528\uff0c\u4f46\u662f\u7528\u6236\u7aef\u5617\u8a66\u5728\u6240\u914d\u7f6e\u7684\u5bb9\u8a31\u6642\u9593\u4e0a\u9650\u671f\u9593\u9084\u539f\u9023\u7dda\u3002 +jmx.rest.client.connection.temporarily.lost.useraction=\u5982\u679c\u4f3a\u670d\u5668\u6b63\u5728\u81ea\u767c\u5730\u91cd\u65b0\u555f\u52d5\uff0c\u5247\u4e0d\u9700\u57f7\u884c\u4efb\u4f55\u52d5\u4f5c\u3002\u5426\u5247\uff0c\u8acb\u6aa2\u67e5\u7db2\u8def\u9023\u7dda\uff0c\u4e26\u78ba\u5b9a\u4f3a\u670d\u5668\u6b63\u5728\u57f7\u884c\uff0c\u4e14\u5df2\u555f\u7528\u4e86 REST \u9023\u63a5\u5668\u7279\u6027\u3002 +jmx.rest.client.connection.restored.with.exceptions=CWWKX0224I: \u9023\u7dda\u5df2\u9084\u539f\uff0c\u4f46\u662f\u5728\u65b0\u589e NotificationListener \u6642\uff0c\u767c\u73fe\u7570\u5e38\u72c0\u6cc1\u3002 +jmx.rest.client.connection.restored.with.exceptions.explanation=\u4f3a\u670d\u5668\u9023\u7dda\u66ab\u6642\u907a\u5931\uff0c\u4f46\u662f\u5df2\u9806\u5229\u9084\u539f\u3002\u5728\u65b0\u589e NotificationListener \u671f\u9593\uff0c\u767c\u73fe\u7570\u5e38\u72c0\u6cc1\uff0c\u56e0\u6b64\u53ef\u80fd\u6c92\u6709\u6536\u5230\u67d0\u4e9b\u901a\u77e5\u3002 +jmx.rest.client.connection.restored.with.exceptions.useraction=\u8acb\u6aa2\u67e5\u901a\u77e5\u96a8\u9644\u7684\u7570\u5e38\u72c0\u6cc1\uff0c\u4e26\u5728\u66f4\u6b63\u554f\u984c\u4e4b\u5f8c\uff0c\u91cd\u65b0\u767b\u9304 NotificationListener\u3002 + +jmx.rest.client.connection.restored=CWWKX0225I: \u5df2\u9806\u5229\u9084\u539f\u9023\u7dda\u3002 +jmx.rest.client.connection.restored.explanation=\u4f3a\u670d\u5668\u9023\u7dda\u66ab\u6642\u907a\u5931\uff0c\u4f46\u662f\u5df2\u9806\u5229\u9084\u539f\u3002\u4efb\u4f55\u5df2\u767b\u9304\u7684 NotificationListener \u90fd\u5c07\u7e7c\u7e8c\u63a5\u6536\u901a\u77e5\u3002 +jmx.rest.client.connection.restored.useraction=\u7121 + +jmx.rest.client.connection.illegal.argument=CWWKX0226E: \u985e\u578b JMXServiceURL \u7684\u53c3\u6578\u4e0d\u5f97\u70ba\u7a7a\u503c\u3002 +jmx.rest.client.connection.illegal.argument.explanation=\u53c3\u6578 'serviceURL' \u7684\u503c\u4e0d\u5f97\u70ba\u7a7a\u503c\u3002 +jmx.rest.client.connection.illegal.argument.useraction=\u4f7f\u7528\u975e\u7a7a\u503c\u7684 JMXServiceURL \u503c\u4f86\u91cd\u65b0\u9023\u63a5\u5230\u300cJMX REST \u9023\u63a5\u5668\u300d\u3002 + +jmx.rest.client.connection.invalid.endpoint=CWWKX0227E: \u4ee5\u4e0b\u4e0d\u662f\u6709\u6548\u7684\u7aef\u9ede\u503c\uff1a{0} +jmx.rest.client.connection.invalid.endpoint.explanation=\u6307\u5b9a\u7684\u7aef\u9ede\u503c\u7121\u6548\u3002 +jmx.rest.client.connection.invalid.endpoint.useraction=\u4f7f\u7528\u5c6c\u65bc\u985e\u578b\u300c\u5b57\u4e32\u300d\u4e14\u683c\u5f0f\u70ba "host:port" \u7684\u6709\u6548\u7aef\u9ede\u503c\u4f86\u91cd\u65b0\u9023\u63a5\u5230\u300cJMX REST \u9023\u63a5\u5668\u300d\u3002 + +jmx.rest.client.connection.no.endpoints=CWWKX0228E: \u627e\u4e0d\u5230\u4efb\u4f55\u53ef\u7528\u7684\u7aef\u9ede\u4f86\u8d77\u59cb\u8a2d\u5b9a\u9023\u63a5\u5668\u3002 +jmx.rest.client.connection.no.endpoints.explanation=\u5728\u8d77\u59cb\u8a2d\u5b9a\u300cJMX REST \u9023\u63a5\u5668\u300d\u671f\u9593\uff0c\u6c92\u6709\u4efb\u4f55\u6307\u5b9a\u7684\u7aef\u9ede\u53ef\u7528\u3002 +jmx.rest.client.connection.no.endpoints.useraction=\u4f7f\u7528\u81f3\u5c11\u4e00\u500b\u53ef\u7528\u7684\u7aef\u9ede\u4f86\u91cd\u65b0\u9023\u63a5\u5230\u300cJMX REST \u9023\u63a5\u5668\u300d\u3002 + +jmx.rest.client.bad.user.credentials=CWWKX0229E: \u6240\u63d0\u4f9b\u7684\u4f7f\u7528\u8005\u8a8d\u8b49\u6709\u554f\u984c\u3002\u4f3a\u670d\u5668\u7684\u56de\u61c9\u78bc\u662f {0}\uff0c\u8a0a\u606f\u662f ''{1}'' +jmx.rest.client.bad.user.credentials.explanation=\u63d0\u4f9b\u7684\u8a8d\u8b49\u4e0d\u6b63\u78ba\u3001\u5df2\u904e\u671f\u3001\u4e0d\u5b8c\u6574\u6216\u6388\u6b0a\u88ab\u62d2\u3002 +jmx.rest.client.bad.user.credentials.useraction=\u8acb\u78ba\u8a8d\u4f7f\u7528\u8005\u8a8d\u8b49\u6709\u6b63\u78ba\u7684\u9451\u5225\u8207\u6388\u6b0a\uff0c\u7136\u5f8c\u53d6\u5f97\u65b0\u9023\u7dda\u3002 + +jmx.rest.client.connection.connect=CWWKX0230I: \u7fa4\u9ad4\u6210\u54e1\u5df2\u958b\u555f JMX \u7528\u6236\u7aef\uff0c\u4e26\u6307\u5411\u7fa4\u9ad4\u63a7\u5236\u5668\uff1a{0} +jmx.rest.client.connection.connect.explanation=\u6210\u54e1\u5df2\u9023\u63a5\u81f3\u63a7\u5236\u5668\u3002 +jmx.rest.client.connection.connect.useraction=\u4e0d\u9700\u63a1\u53d6\u4efb\u4f55\u52d5\u4f5c\u3002 +jmx.rest.client.connection.disconnect=CWWKX0231I: \u7fa4\u9ad4\u6210\u54e1\u5df2\u5f9e\u7fa4\u9ad4\u63a7\u5236\u5668 {0} \u95dc\u9589 JMX \u7528\u6236\u7aef +jmx.rest.client.connection.disconnect.explanation=\u6210\u54e1\u5df2\u5207\u65b7\u63a7\u5236\u5668\u9023\u7dda\u3002 +jmx.rest.client.connection.disconnect.useraction=\u4e0d\u9700\u63a1\u53d6\u4efb\u4f55\u52d5\u4f5c\u3002 + diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/restConnector-headers.bnd b/dev/com.ibm.ws.jmx.connector.client.rest/restConnector-headers.bnd new file mode 100755 index 00000000000..e5f924c8d01 --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/restConnector-headers.bnd @@ -0,0 +1,9 @@ +Private-Package: \ + com.ibm.json.*, \ + com.ibm.websphere.jmx.connector.rest, \ + com.ibm.ws.jmx.connector.client.rest.*, \ + com.ibm.ws.jmx.connector.converter, \ + com.ibm.ws.jmx.connector.datatypes + +Include-Resource: \ + META-INF=resources/META-INF diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/restConnector.bnd b/dev/com.ibm.ws.jmx.connector.client.rest/restConnector.bnd new file mode 100755 index 00000000000..fc4f5c2087c --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/restConnector.bnd @@ -0,0 +1,8 @@ +-include = \ + ~../cnf/resources/bnd/jar.props, \ + restConnector-headers.bnd + +bVersion=1.0 + +Client-Name: REST Connector Client JAR +Client-Description: REST Connector Client JAR; version=${bVersion} diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/websphere/jmx/connector/rest/ConnectorSettings.java b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/websphere/jmx/connector/rest/ConnectorSettings.java new file mode 100755 index 00000000000..ffd1f24d293 --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/websphere/jmx/connector/rest/ConnectorSettings.java @@ -0,0 +1,283 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012,2014 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.websphere.jmx.connector.rest; + +import javax.management.remote.JMXConnector; +import javax.management.remote.JMXConnectorFactory; +import javax.management.remote.JMXServiceURL; + +import com.ibm.ws.jmx.connector.client.rest.ClientProvider; + +/** + * Provides constants for connection settings of the Liberty profile JMX REST connector client. + * The settings can be adjusted in 2 ways: + *

+ *

    + *
  1. Globally, by setting a system property with the desired value. For example, to set READ_TIMEOUT to 2 minutes (120000 milliseconds), use the Java option: + *

    + * + *

    + * -Dcom.ibm.ws.jmx.connector.client.rest.readTimeout=120000
    + * 
    + * + *
  2. + *
  3. On a per connection basis, by adding an entry to the environment Map parameter of the + * {@link JMXConnectorFactory#newJMXConnector(javax.management.remote.JMXServiceURL, java.util.Map)} or {@link JMXConnector#connect(java.util.Map)} method. + *

    + * + *

    + * 
    + * HashMap environment = new HashMap();
    + * environment.put("jmx.remote.protocol.provider.pkgs", "com.ibm.ws.jmx.connector.client");
    + * environment.put(JMXConnector.CREDENTIALS, new String[] { "bob", "bobpassword" });
    + * environment.put(ConnectorSettings.MAX_SERVER_WAIT_TIME, 120000);
    + *
    + * JMXServiceURL url = new JMXServiceURL("service:jmx:rest://<host>:<port>/IBMJMXConnectorREST");
    + * JMXConnector connector = JMXConnectorFactory.newJMXConnector(url, environment);
    + * connector.connect(environment);
    + * 
    + * 
    + * + *
  4. + *
+ * + * @ibm-api + */ +public interface ConnectorSettings { + + /** + * Boolean setting that when enabled disables hostname verification on the client connections. This can be useful for environments where the hostname used does not match the + * one specified in the server certificate. + */ + public static final String DISABLE_HOSTNAME_VERIFICATION = ClientProvider.CLIENT_DOMAIN + ".disableURLHostnameVerification"; + + /** + * Integer setting for the maximum amount of time in milliseconds that the server waits for new notifications before responding to a request for notifications from the client. + * A larger value results in better notification delivery times because less time is spent establishing new connections. Normally it is not necessary to adjust this value. + */ + public static final String NOTIFICATION_DELIVERY_INTERVAL = ClientProvider.REST_CLIENT_DOMAIN + ".notificationDeliveryInterval"; + + /** + * Integer setting for the amount of time in milliseconds that the server waits before discarding notification registrations if the client has not checked for new + * notifications. Normally it is not necessary to adjust this value. + */ + public static final String NOTIFICATION_INBOX_EXPIRY = ClientProvider.REST_CLIENT_DOMAIN + ".notificationInboxExpiry"; + + /** + * Integer setting for the amount of time in milliseconds that the client waits before making a new request to fetch notifications. + */ + public static final String NOTIFICATION_FETCH_INTERVAL = ClientProvider.REST_CLIENT_DOMAIN + ".notificationFetchInterval"; + + /** + * Integer setting for the read timeout in milliseconds for all client communications with the server, except notification fetching. Adjust this value if the client throws read + * timeout exceptions because of a slow connection or client or server process. + */ + public static final String READ_TIMEOUT = ClientProvider.REST_CLIENT_DOMAIN + ".readTimeout"; + + /** + * Integer setting for the read timeout in milliseconds for notification fetching. Because the server might wait up to NOTIFICATION_DELIVERY_INTERVAL before responding, this + * value must be somewhat larger, though normally it is not necessary to adjust this value. + */ + public static final String NOTIFICATION_READ_TIMEOUT = ClientProvider.REST_CLIENT_DOMAIN + ".notificationReadTimeout"; + + /** + * Integer setting for the amount of time in milliseconds that the client waits between checks that the server is still available. To disable this behaviour, set the value to + * a negative integer. + * + * This value is overridden by {@link ConnectorSettings.NOTIFICATION_FETCH_INTERVAL} whenever there are notification listeners registered with this client. + */ + public static final String SERVER_FAILOVER_INTERVAL = ClientProvider.REST_CLIENT_DOMAIN + ".failoverInterval"; + + /** + * Integer setting for the amount of time in milliseconds that the client waits for the server to become available before the JMX connection fails and a new connection must be + * created. If the connection is restored, any previous notification listeners are registered again. To disable this behavior, set the value to zero. + */ + public static final String MAX_SERVER_WAIT_TIME = ClientProvider.REST_CLIENT_DOMAIN + ".maxServerWaitTime"; + + /** + * Integer setting for the amount of time in milliseconds that the client waits between checks that the server is available again when MAX_SERVER_WAIT_TIME is non-zero. + * Normally it is not necessary to adjust this value. + */ + public static final String SERVER_STATUS_POLLING_INTERVAL = ClientProvider.REST_CLIENT_DOMAIN + ".serverStatusPollingInterval"; + + /** + * Indicates that the {@link JMXConnector.CREDENTIALS} will be handled by SSL certificate based authentication. + */ + public static final String CERTIFICATE_AUTHENTICATION = ClientProvider.CLIENT_DOMAIN + ".CLIENT_CERT_AUTH"; + + /** + * Indicates that all JMX connections will use the specified SSLSocketFactory + */ + public static final String CUSTOM_SSLSOCKETFACTORY = ClientProvider.CLIENT_DOMAIN + ".CUSTOM_SSLSOCKETFACTORY"; + + /** + *

Work Load Management Endpoints

+ * List of Strings setting to indicate which endpoints, in addition + * to the host and port in the {@link JMXServiceURL}, are valid for + * establishing a connection. An endpoint is defined as "host:port". + *

+ * When the work load management endpoint list is set, the initial + * connection is made using one of the endpoints in the complete set of + * available endpoints. The complete set of endpoints is the host and port + * specified to the {@link JMXServiceURL} as well as the contents of the + * work load management endpoint list. + *

+ * This property is only supported in the programmatic JMX environment. + * + *

+     * 
+     * List<String> endpoints = new ArrayList<String>
+     * endpoints.add("<host2>:<port>");
+     *
+     * HashMap environment = new HashMap();
+     * environment.put("jmx.remote.protocol.provider.pkgs", "com.ibm.ws.jmx.connector.client");
+     * environment.put(JMXConnector.CREDENTIALS, new String[] { "bob", "bobpassword" });
+     * environment.put(ConnectorSettings.WLM_ENDPOINTS, endpoints);
+     *
+     * JMXServiceURL url = new JMXServiceURL("service:jmx:rest://<host>:<port>/IBMJMXConnectorREST");
+     * JMXConnector connector = JMXConnectorFactory.newJMXConnector(url, environment);
+     * connector.connect(environment);
+     * 
+     * 
+ * + * The preceding code would establish the available endpoint set as host:port + * and host2:port. + *

+ * No ordering guarantees are made regarding which endpoint is ultimately + * used for the connection, but all endpoints will be tried in order to + * establish a connection. Only when all endpoints in the complete set are + * inaccessible is a connection considered to be unobtainable. + *

+ * Fail-over retry will occur if the invoked operation could not be + * started. If the connection is lost during an operation, no retry will + * be done so as to not issue the same command twice. In other words, if + * we loose the connection before the operation can report success, an + * IOException will be thrown and the operation will not be re-tried. + */ + public static final String WLM_ENDPOINTS = ClientProvider.CLIENT_DOMAIN + ".wlm.endpoints"; + + /** + * This parameter represents the host name to be used in a routing context. + * + * This parameter is not applicable to the settings passed into the client-side of the JMX REST connector. + * It is used only by the file transfer RESTful endpoint and the Routing MBean, exposed by the server-side of the JMX REST connector. + */ + public static final String ROUTING_KEY_HOST_NAME = "com.ibm.websphere.jmx.connector.rest.routing.hostName"; + + /** + * This parameter represents the server name to be used in a routing context. + * + * This parameter is not applicable to the settings passed into the client-side of the JMX REST connector. + * It is used only by the file transfer RESTful endpoint and the Routing MBean, exposed by the server-side of the JMX REST connector. + */ + public static final String ROUTING_KEY_SERVER_NAME = "com.ibm.websphere.jmx.connector.rest.routing.serverName"; + + /** + * This parameter represents the server user directory to be used in a routing context. + * + * This parameter is not applicable to the settings passed into the client-side of the JMX REST connector. + * It is used only by the file transfer RESTful endpoint and the Routing MBean, exposed by the server-side of the JMX REST connector. + */ + public static final String ROUTING_KEY_SERVER_USER_DIR = "com.ibm.websphere.jmx.connector.rest.routing.serverUserDir"; + + /** + * This parameter represents a comma-separated list of host names within the collective. + * + * This parameter is not applicable to the settings passed into the client-side of the JMX REST connector. + * It is used only by the file transfer RESTful endpoint, exposed by the server-side of the JMX REST connector. + */ + public static final String COLLECTIVE_HOST_NAMES = "com.ibm.websphere.collective.hostNames"; + + /** + * This parameter represents a request for an asynchronous execution within the collective. + * + * This parameter is not applicable to the settings passed into the client-side of the JMX REST connector. + * It is used only by the file transfer RESTful endpoint, exposed by the server-side of the JMX REST connector. + */ + public static final String ASYNC_EXECUTION = "com.ibm.websphere.jmx.connector.rest.asyncExecution"; + + /** + * This parameter represents the set of credentials to be used for the transfer action. + * The payload of the header is a JSON object with attributes from the CollectiveRegistrationMBean. + * Only credentials (user name, password, keys) are defined. The host and port attributes are not supported. + * + * This parameter is not applicable to the settings passed into the client-side of the JMX REST connector. + * It is used only by the file transfer RESTful endpoint, exposed by the server-side of the JMX REST connector. + */ + public static final String TRANSFER_CREDENTIALS = "com.ibm.websphere.jmx.connector.rest.transferCredentials"; + + /** + * This parameter represents the request for a pre transfer action within the collective. + * + * This parameter is not applicable to the settings passed into the client-side of the JMX REST connector. + * It is used only by the file transfer RESTful endpoint, exposed by the server-side of the JMX REST connector. + */ + public static final String PRE_TRANSFER_ACTION = "com.ibm.websphere.jmx.connector.rest.preTransferAction"; + + /** + * This parameter represents the request for a post transfer action within the collective. + * + * This parameter is not applicable to the settings passed into the client-side of the JMX REST connector. + * It is used only by the file transfer RESTful endpoint, exposed by the server-side of the JMX REST connector. + */ + public static final String POST_TRANSFER_ACTION = "com.ibm.websphere.jmx.connector.rest.postTransferAction"; + + /** + * This parameter represents the default value for the collective pre-transfer-action. + * + * This parameter is not applicable to the settings passed into the client-side of the JMX REST connector. + * It is used only by the file transfer RESTful endpoint, exposed by the server-side of the JMX REST connector. + */ + public static final String PRE_TRANSFER_ACTION_DEFAULT = "com.ibm.websphere.jmx.connector.rest.preTransferAction.remove"; + + /** + * This parameter represents the default value for the collective post-transfer-action. + * + * This parameter is not applicable to the settings passed into the client-side of the JMX REST connector. + * It is used only by the file transfer RESTful endpoint, exposed by the server-side of the JMX REST connector. + */ + public static final String POST_TRANSFER_ACTION_DEFAULT = "com.ibm.websphere.jmx.connector.rest.postTransferAction.join"; + + /** + * This parameter represents the action of extarcting a severName from a Liberty zip package for the collective post-transfer-action. + * + * This parameter is not applicable to the settings passed into the client-side of the JMX REST connector. + * It is used only by the file transfer RESTful endpoint, exposed by the server-side of the JMX REST connector. + */ + public static final String POST_TRANSFER_ACTION_FIND_SERVER_NAME = "com.ibm.websphere.jmx.connector.rest.postTransferAction.findServerName"; + + /** + * This parameter represents the options pertaining to the collective pre-transfer-action. + * + * This parameter is not applicable to the settings passed into the client-side of the JMX REST connector. + * It is used only by the file transfer RESTful endpoint, exposed by the server-side of the JMX REST connector. + */ + public static final String PRE_TRANSFER_ACTION_OPTIONS = "com.ibm.websphere.jmx.connector.rest.preTransferAction.options"; + + /** + * This parameter represents the options pertaining to the collective post-transfer-action. + * + * This parameter is not applicable to the settings passed into the client-side of the JMX REST connector. + * It is used only by the file transfer RESTful endpoint, exposed by the server-side of the JMX REST connector. + */ + public static final String POST_TRANSFER_ACTION_OPTIONS = "com.ibm.websphere.jmx.connector.rest.postTransferAction.options"; + + /** + * This parameter represents a set of environment variables and their corresponding values. + * The payload of the header is a JSON object that has envKey : envValue pairs. + * + * This parameter is not applicable to the settings passed into the client-side of the JMX REST connector. + * It is used only by the file transfer RESTful endpoint, exposed by the server-side of the JMX REST connector. + */ + public static final String TRANSFER_ENV_VARS = "com.ibm.websphere.jmx.connector.rest.transferEnvVars"; + +} diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/websphere/jmx/connector/rest/package-info.java b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/websphere/jmx/connector/rest/package-info.java new file mode 100755 index 00000000000..8f227398e47 --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/websphere/jmx/connector/rest/package-info.java @@ -0,0 +1,16 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2014 + * + * The source code for this program is not published or other- + * wise divested of its trade secrets, irrespective of what has + * been deposited with the U.S. Copyright Office. + */ +/** + * @version 1.4 + */ +@org.osgi.annotation.versioning.Version("1.4") +package com.ibm.websphere.jmx.connector.rest; diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/ClientProvider.java b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/ClientProvider.java new file mode 100755 index 00000000000..b2eec76c36e --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/ClientProvider.java @@ -0,0 +1,58 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jmx.connector.client.rest; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.util.Map; + +import javax.management.remote.JMXConnector; +import javax.management.remote.JMXConnectorProvider; +import javax.management.remote.JMXServiceURL; + +import com.ibm.websphere.jmx.connector.rest.ConnectorSettings; +import com.ibm.ws.jmx.connector.client.rest.internal.Connector; + +public class ClientProvider implements JMXConnectorProvider, ConnectorSettings { + + public static final String REST_PROTOCOL = "rest"; + + public static final String CLIENT_DOMAIN = "com.ibm.ws.jmx.connector.client"; + public static final String REST_CLIENT_DOMAIN = "com.ibm.ws.jmx.connector.client.rest"; + + public static final String CONNECTION_TEMPORARILY_LOST = REST_CLIENT_DOMAIN + ".connectionTemporarilyLost"; + public static final String CONNECTION_RESTORED = REST_CLIENT_DOMAIN + ".connectionRestored"; + public static final String CONNECTION_RESTORED_WITH_EXCEPTIONS = REST_CLIENT_DOMAIN + ".connectionRestoredWithExceptions"; + + public static final String CONNECTION_ROUTING_DOMAIN = "WebSphere"; + public static final String CONNECTION_ROUTING_NAME = "RoutingContext"; + public static final String CONNECTION_ROUTING_OPERATION_ASSIGN_SERVER = "assignServerContext"; + public static final String CONNECTION_ROUTING_OPERATION_ASSIGN_HOST = "assignHostContext"; + + public static final String FILE_TRANSFER_DOMAIN = "WebSphere"; + public static final String FILE_TRANSFER_NAME = "FileTransfer"; + + /* + * (non-Javadoc) + * + * @see javax.management.remote.JMXConnectorProvider#newJMXConnector(javax.management.remote.JMXServiceURL, java.util.Map) + */ + @Override + public JMXConnector newJMXConnector(JMXServiceURL serviceURL, Map environment) throws IOException { + if (serviceURL == null || environment == null) + throw new NullPointerException(); + if (!ClientProvider.REST_PROTOCOL.equals(serviceURL.getProtocol())) + throw new MalformedURLException(); + return new Connector(serviceURL, environment); + } + +} diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/internal/Activator.java b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/internal/Activator.java new file mode 100755 index 00000000000..06fab68c4d9 --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/internal/Activator.java @@ -0,0 +1,59 @@ +/* +* IBM Confidential +* +* OCO Source Materials +* +* WLP Copyright IBM Corp. 2016 +* +* The source code for this program is not published or otherwise divested +* of its trade secrets, irrespective of what has been deposited with the +* U.S. Copyright Office. +*/ +package com.ibm.ws.jmx.connector.client.rest.internal; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.ConfigurationPolicy; +import org.osgi.service.component.annotations.Deactivate; + +@Component(configurationPolicy = ConfigurationPolicy.IGNORE) +public class Activator { + + private final static String PKGS_KEY = "jmx.remote.protocol.provider.pkgs"; + private final static String PKGS = "com.ibm.ws.jmx.connector.client"; + private final static Pattern P = Pattern.compile("(?:\\A|,)" + PKGS + "(?:\\z|,)"); + + @Activate + protected void activate() { + + String jmx = System.getProperty(PKGS_KEY); + System.setProperty(PKGS_KEY, add(jmx)); + } + + @Deactivate + protected void deactivate() { + String jmx = System.getProperty(PKGS_KEY); + if (PKGS.equals(jmx)) { + System.clearProperty(PKGS_KEY); + } else { + System.setProperty(PKGS_KEY, remove(jmx)); + } + } + + static String add(String jmx) { + if (jmx == null) { + return PKGS; + } else { + return jmx + "," + PKGS; + } + } + + static String remove(String jmx) { + Matcher m = P.matcher(jmx); + return m.replaceAll(""); + } + +} diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/internal/ClientConstants.java b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/internal/ClientConstants.java new file mode 100755 index 00000000000..b3c038bc61e --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/internal/ClientConstants.java @@ -0,0 +1,43 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ + +package com.ibm.ws.jmx.connector.client.rest.internal; + +class ClientConstants { + + enum HttpMethod { + GET, POST, PUT, DELETE, + HEAD, OPTIONS, TRACE + }; + + static final String JSON_MIME_TYPE = "application/json"; + + static final boolean DISABLE_HOSTNAME_VERIFICATION_DEFAULT = false; + + static final int NOTIFICATION_DELIVERY_INTERVAL_DEFAULT = 0; + + static final int NOTIFICATION_FETCH_INTERVAL_DEFAULT = 1000; + + static final int NOTIFICATION_INBOX_EXPIRY_DEFAULT = 5 * 60 * 1000; + + static final int SERVER_FAILOVER_INTERVAL_DEFAULT = 30 * 1000; + + static final int READ_TIMEOUT_DEFAULT = 60 * 1000; + + static final int MAX_SERVER_WAIT_TIME_DEFAULT = 120 * 1000; + + static final int SERVER_STATUS_POLLING_INTERVAL_DEFAULT = 4 * 1000; + + static final String CONNECTOR_URI = "IBMJMXConnectorREST"; + + static final String ROUTER_URI = CONNECTOR_URI + "/router"; +} diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/internal/Connector.java b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/internal/Connector.java new file mode 100755 index 00000000000..ef422240d5d --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/internal/Connector.java @@ -0,0 +1,619 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012, 2017 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jmx.connector.client.rest.internal; + +import java.io.IOException; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.management.ListenerNotFoundException; +import javax.management.MBeanServerConnection; +import javax.management.Notification; +import javax.management.NotificationFilter; +import javax.management.NotificationListener; +import javax.management.remote.JMXConnectionNotification; +import javax.management.remote.JMXConnector; +import javax.management.remote.JMXServiceURL; +import javax.net.ssl.SSLSocketFactory; +import javax.security.auth.Subject; + +import com.ibm.websphere.jmx.connector.rest.ConnectorSettings; +import com.ibm.ws.jmx.connector.client.rest.ClientProvider; +import com.ibm.ws.jmx.connector.client.rest.internal.resources.RESTClientMessagesUtil; +import com.ibm.ws.jmx.connector.converter.JSONConverter; +import com.ibm.ws.jmx.connector.datatypes.ConversionException; + +public class Connector implements JMXConnector { + + private static final Logger logger = Logger.getLogger(Connector.class.getName()); + + private final JMXServiceURL serviceURL; + private Map environment; + private long connectionId; + + private List wlmList; + + private String currentEndpoint; + + private boolean hostnameVerificationDisabled; + private int notificationDeliveryInterval, notificationFetchInterval, notificationInboxExpiry, readTimeout, notificationReadTimeout, serverFailoverInterval, maxServerWaitTime, + serverStatusPollingInterval; + private String user; + private String basicAuthHeader = null; + + private RESTMBeanServerConnection connection = null; + private boolean closed = false; + + private List connectionListeners = null; + + private static long nextConnectionNumber = 1; + + private SSLSocketFactory customSSLSocketFactory = null; + + private boolean isCollectiveUtilConnection = false; + private boolean logFailovers = false; + + /** + * @return the customSSLSocketFactory + */ + public SSLSocketFactory getCustomSSLSocketFactory() { + return customSSLSocketFactory; + } + + /** + * @param customSSLSocketFactory the customSSLSocketFactory to set + */ + public void setCustomSSLSocketFactory(SSLSocketFactory customSSLSocketFactory) { + this.customSSLSocketFactory = customSSLSocketFactory; + } + + private synchronized static long getConnectionNumber() { + return nextConnectionNumber++; + } + + private static long nextNotificationNumber = 1; + + private static long getNotificationNumber() { + synchronized (Connector.class) { + return nextNotificationNumber++; + } + } + + public Connector(JMXServiceURL serviceURL, Map environment) { + this.serviceURL = serviceURL; + this.environment = environment; + this.isCollectiveUtilConnection = getBooleanSetting("isCollectiveUtil", false); + this.logFailovers = getBooleanSetting("logFailovers", false); + + if (serviceURL == null) { + throw new IllegalArgumentException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.NULL_SERVICE_URL)); + } + + //We initialize our WLM list to have the connecting URL. In non-WLM cases, this is our only URL. + this.wlmList = new ArrayList(); + this.wlmList.add(serviceURL.getHost() + ":" + serviceURL.getPort()); + } + + /** {@inheritDoc} */ + @Override + public void connect() throws IOException { + connect(null); + } + + private Object getCredentials() { + Object credentials = environment.get(JMXConnector.CREDENTIALS); + if (credentials != null) { + //We found a non-null key in our map, so that's the credentials we'll use + return credentials; + } + + //Our map was empty, but before we fail, check if we can fetch a String from the system properties + credentials = AccessController.doPrivileged(new PrivilegedAction() { + @Override + public String run() { + return System.getProperty(JMXConnector.CREDENTIALS); + } + }); + + return credentials; + } + + private boolean getBooleanSetting(final String key, boolean defaultValue) { + // Check environment first for per-connection setting + if (environment != null) { + Object setting = environment.get(key); + if (setting != null && setting instanceof Boolean) + return (Boolean) setting; + } + + // Next, check system property for global setting + String setting = AccessController.doPrivileged(new PrivilegedAction() { + @Override + public String run() { + return System.getProperty(key); + } + }); + if (setting != null) { + return Boolean.parseBoolean(setting); + } + + // Otherwise, return default value + return defaultValue; + } + + private int getIntegerSetting(final String key, int defaultValue) { + // Check environment first for per-connection setting + if (environment != null) { + Object setting = environment.get(key); + if (setting != null && setting instanceof Integer) + return (Integer) setting; + } + + // Next, check system property for global setting + String setting = AccessController.doPrivileged(new PrivilegedAction() { + @Override + public String run() { + return System.getProperty(key); + } + }); + if (setting != null) { + try { + return Integer.parseInt(setting); + } catch (NumberFormatException nfe) { + // ignore value + } + } + + // Otherwise, return default value + return defaultValue; + } + + /** + * Validate the possible endpoint String. + * + * @param possibleEndpoint + * @throws IllegalArgumentException if the String is not a valid endpoint + */ + private void validatePossibleEndpoint(String possibleEndpoint) throws IllegalArgumentException { + if (!possibleEndpoint.contains(":")) { + throw new IllegalArgumentException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.INVALID_ENDPOINT, possibleEndpoint)); + } + String[] components = possibleEndpoint.split(":"); + if (components.length != 2) { + throw new IllegalArgumentException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.INVALID_ENDPOINT, possibleEndpoint)); + } + try { + Integer.valueOf(components[1]); + } catch (NumberFormatException e) { + throw new IllegalArgumentException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.INVALID_ENDPOINT, possibleEndpoint)); + } + } + + /** + * Validates the list contains nothing but Strings, and that those Strings + * are in the endpoint format. If the List contains non-String elements, + * or a String that does not follow the endpoint host:port format, + * an IllegalArgumentException will be thrown. + * + * @param list A generic List of Objects to be validated + * @throws IllegalArgumentException if the List contains a non-String + * element or if the String is not in endpoint format + */ + private void validateEndpointList(List list) throws IllegalArgumentException { + if (list.isEmpty()) { + return; + } + + for (Object element : list) { + if (element == null) { + throw new IllegalArgumentException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.INVALID_ENDPOINT, "null")); + } else if (element instanceof String) { + String elemStr = (String) element; + validatePossibleEndpoint((String) element); + //Add endpoint to our list. Filter duplicates. + if (!wlmList.contains(elemStr)) { + wlmList.add(elemStr); + } + } else { + throw new IllegalArgumentException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.INVALID_ENDPOINT, element.toString())); + } + } + + //Randomize the list if we have more than 1 element. This is our basic load balancer. + if (wlmList.size() > 1) { + Collections.shuffle(wlmList, new Random(System.currentTimeMillis())); + } + + //We don't want anybody changing our list of endpoints from this point forward + this.wlmList = Collections.unmodifiableList(this.wlmList); + + } + + /** + * Return the configured List of endpoints + */ + List getEndpointList() { + return this.wlmList; + } + + /** {@inheritDoc} */ + @Override + public synchronized void connect(Map env) throws IOException { + // Connector can only be used once + if (closed) + throw new IOException(); + + // connect has no effect if already connected + if (connection != null) + return; + + if (env != null) + environment = env; + + // User credentials will either be available as a String[] for basic auth, OR + //as a String (equals to ConnectorSettings.CERTIFICATE_AUTHENTICATION), which could also come from a system property + Object credentials = getCredentials(); + if (!areRequiedCredentialsSet(credentials)) { + throw new IOException(JMXConnector.CREDENTIALS + " not provided. Set to a String[2] {user,password}."); + } + // If the credentials are not certificate, extract and set the basicAuthHeader + if (!ConnectorSettings.CERTIFICATE_AUTHENTICATION.equals(credentials)) { + String[] userPass = (String[]) credentials; + user = userPass[0]; + JSONConverter converter = JSONConverter.getConverter(); + try { + basicAuthHeader = "Basic " + converter.encodeStringAsBase64(user + ":" + userPass[1]); + } catch (ConversionException ce) { + throw new IOException("Failure encoding credentials", ce); + } finally { + JSONConverter.returnConverter(converter); + } + } + + hostnameVerificationDisabled = getBooleanSetting(ConnectorSettings.DISABLE_HOSTNAME_VERIFICATION, ClientConstants.DISABLE_HOSTNAME_VERIFICATION_DEFAULT); + notificationDeliveryInterval = getIntegerSetting(ConnectorSettings.NOTIFICATION_DELIVERY_INTERVAL, ClientConstants.NOTIFICATION_DELIVERY_INTERVAL_DEFAULT); + notificationFetchInterval = getIntegerSetting(ConnectorSettings.NOTIFICATION_FETCH_INTERVAL, ClientConstants.NOTIFICATION_FETCH_INTERVAL_DEFAULT); + notificationInboxExpiry = getIntegerSetting(ConnectorSettings.NOTIFICATION_INBOX_EXPIRY, ClientConstants.NOTIFICATION_INBOX_EXPIRY_DEFAULT); + readTimeout = getIntegerSetting(ConnectorSettings.READ_TIMEOUT, ClientConstants.READ_TIMEOUT_DEFAULT); + notificationReadTimeout = getIntegerSetting(ConnectorSettings.NOTIFICATION_READ_TIMEOUT, + notificationDeliveryInterval > 0 ? 2 * notificationDeliveryInterval : ClientConstants.READ_TIMEOUT_DEFAULT); + serverFailoverInterval = getIntegerSetting(ConnectorSettings.SERVER_FAILOVER_INTERVAL, ClientConstants.SERVER_FAILOVER_INTERVAL_DEFAULT); + maxServerWaitTime = getIntegerSetting(ConnectorSettings.MAX_SERVER_WAIT_TIME, ClientConstants.MAX_SERVER_WAIT_TIME_DEFAULT); + serverStatusPollingInterval = getIntegerSetting(ConnectorSettings.SERVER_STATUS_POLLING_INTERVAL, ClientConstants.SERVER_STATUS_POLLING_INTERVAL_DEFAULT); + + //Validate endpoints if applicable + Object list = environment.get(ConnectorSettings.WLM_ENDPOINTS); + if (list != null && list instanceof List) { + validateEndpointList((List) list); + } + + // -- Logging + if (logger.isLoggable(Level.FINER)) { + StringBuilder sb = new StringBuilder(); + sb.append("Endpoints:"); + for (String endpoint : wlmList) { + sb.append(endpoint); + sb.append(" "); + } + logger.logp(Level.FINER, logger.getName(), "connect", sb.toString()); + + if (logger.isLoggable(Level.FINEST)) { + sb = new StringBuilder(); + sb.append("notificationDeliveryInterval"); + sb.append("="); + sb.append(notificationDeliveryInterval); + sb.append("\n"); + + sb.append("notificationFetchInterval"); + sb.append("="); + sb.append(notificationFetchInterval); + sb.append("\n"); + + sb.append("notificationInboxExpiry"); + sb.append("="); + sb.append(notificationInboxExpiry); + sb.append("\n"); + + sb.append("readTimeout"); + sb.append("="); + sb.append(readTimeout); + sb.append("\n"); + + sb.append("notificationReadTimeout"); + sb.append("="); + sb.append(notificationReadTimeout); + sb.append("\n"); + + sb.append("serverFailoverInterval"); + sb.append("="); + sb.append(serverFailoverInterval); + sb.append("\n"); + + sb.append("maxServerWaitTime"); + sb.append("="); + sb.append(maxServerWaitTime); + sb.append("\n"); + + sb.append("serverStatusPollingInterval"); + sb.append("="); + sb.append(serverStatusPollingInterval); + sb.append("\n"); + + logger.logp(Level.FINEST, logger.getName(), "connect", sb.toString()); + } + } + + connectionId = getConnectionNumber(); + + Object o = environment.get(ConnectorSettings.CUSTOM_SSLSOCKETFACTORY); + if (o != null && o instanceof SSLSocketFactory) { + SSLSocketFactory sslf = (SSLSocketFactory) o; + this.setCustomSSLSocketFactory(sslf); + } + + // No longer need environment + environment = null; + + connection = new RESTMBeanServerConnection(this); + + connectionOpened(); + } + + /** + * @param credentials + * @return + */ + private boolean areRequiedCredentialsSet(Object credentials) { + if (credentials == null) { + return false; + } + if (ConnectorSettings.CERTIFICATE_AUTHENTICATION.equals(credentials)) { + return true; + } + if ((credentials instanceof String[]) && (((String[]) credentials).length == 2)) { + return true; + } + return false; + } + + /** {@inheritDoc} */ + @Override + public synchronized MBeanServerConnection getMBeanServerConnection() throws IOException { + // if not yet connected, throw IOException + if (connection == null) + throw new IOException(); + + return connection; + } + + /** {@inheritDoc} */ + @Override + public MBeanServerConnection getMBeanServerConnection(Subject delegationSubject) throws IOException { + // this use-case not supported + throw new IOException(); + } + + /** {@inheritDoc} */ + @Override + public synchronized void close() throws IOException { + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), "close", "Closing connector"); + } + + if (!closed) { + // It is possible for close to be called prior to connecting. + // If so, we behave as a no-op. + if (connection != null) { + connection.close(); + } + connection = null; + closed = true; + if (connectionListeners != null) { + JMXConnectionNotification notification = new JMXConnectionNotification(JMXConnectionNotification.CLOSED, this, getConnectionId(), getNotificationNumber(), null, null); + for (NotificationListenerEntry entry : connectionListeners) + entry.handleNotification(notification); + } + } + } + + synchronized void connectionOpened() { + if (connectionListeners != null) { + JMXConnectionNotification notification = new JMXConnectionNotification(JMXConnectionNotification.OPENED, this, getConnectionId(), getNotificationNumber(), null, null); + for (NotificationListenerEntry entry : connectionListeners) + entry.handleNotification(notification); + } + } + + synchronized void connectionFailed(Throwable t) { + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), "connectionFailed", "Failed connection: " + t); + } + closed = true; + if (connectionListeners != null) { + JMXConnectionNotification notification = new JMXConnectionNotification(JMXConnectionNotification.FAILED, this, getConnectionId(), getNotificationNumber(), RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.CONNECTION_FAILED), t); + for (NotificationListenerEntry entry : connectionListeners) + entry.handleNotification(notification); + } + } + + synchronized void notificationLost(Notification n) { + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), "notificationLost", "Lost notification: " + n); + } + + if (connectionListeners != null) { + JMXConnectionNotification notification = new JMXConnectionNotification(JMXConnectionNotification.NOTIFS_LOST, this, getConnectionId(), getNotificationNumber(), RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.NOTIFICATION_LOST), n); + for (NotificationListenerEntry entry : connectionListeners) + entry.handleNotification(notification); + } + } + + synchronized void connectionTemporarilyLost(Throwable t) { + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), "connectionTemporarilyLost", "Lost connection:" + t.getMessage()); + } + + if (connectionListeners != null) { + JMXConnectionNotification notification = new JMXConnectionNotification(ClientProvider.CONNECTION_TEMPORARILY_LOST, this, getConnectionId(), getNotificationNumber(), RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.CONNECTION_TEMPORARILY_LOST), t); + for (NotificationListenerEntry entry : connectionListeners) + entry.handleNotification(notification); + } + } + + synchronized void connectionRestored(Exception[] exceptions) { + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), "connectionRestored", "Connection restored"); + } + + if (connectionListeners != null) { + JMXConnectionNotification notification; + if (exceptions != null) { + notification = new JMXConnectionNotification(ClientProvider.CONNECTION_RESTORED_WITH_EXCEPTIONS, this, getConnectionId(), getNotificationNumber(), RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.CONNECTION_RESTORED_WITH_EXCEPTIONS), exceptions); + } else { + notification = new JMXConnectionNotification(ClientProvider.CONNECTION_RESTORED, this, getConnectionId(), getNotificationNumber(), RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.CONNECTION_RESTORED), null); + } + for (NotificationListenerEntry entry : connectionListeners) + entry.handleNotification(notification); + } + } + + /** {@inheritDoc} */ + @Override + public synchronized void addConnectionNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) { + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), "addConnectionNotificationListener", "listener: " + listener + " | filter: " + filter + " | handback: " + handback); + } + + if (connectionListeners == null) + connectionListeners = new ArrayList(); + + connectionListeners.add(new NotificationListenerEntry(listener, filter, handback)); + } + + /** {@inheritDoc} */ + @Override + public synchronized void removeConnectionNotificationListener(NotificationListener listener) throws ListenerNotFoundException { + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), "removeConnectionNotificationListener", "listener: " + listener); + } + + boolean listenerFound = false; + if (connectionListeners != null) { + Iterator entryIterator = connectionListeners.iterator(); + while (entryIterator.hasNext()) { + if (entryIterator.next().listener == listener) { + listenerFound = true; + entryIterator.remove(); + } + } + } + + if (!listenerFound) + throw new ListenerNotFoundException(); + } + + /** {@inheritDoc} */ + @Override + public synchronized void removeConnectionNotificationListener(NotificationListener l, NotificationFilter f, Object handback) throws ListenerNotFoundException { + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), "removeConnectionNotificationListener", "listener: " + l + " | filter: " + f + " | handback: " + handback); + } + boolean listenerFound = false; + if (connectionListeners != null) { + listenerFound = connectionListeners.remove(new NotificationListenerEntry(l, f, handback)); + } + + if (!listenerFound) + throw new ListenerNotFoundException(); + } + + /** {@inheritDoc} */ + @Override + public synchronized String getConnectionId() { + return serviceURL.getProtocol() + ":" + getCurrentEndpoint() + " " + user + " " + connectionId; + } + + JMXServiceURL getServiceURL() { + return serviceURL; + } + + boolean isHostnameVerificationDisabled() { + return hostnameVerificationDisabled; + } + + int getNotificationDeliveryInterval() { + return notificationDeliveryInterval; + } + + int getNotificationFetchInterval() { + return notificationFetchInterval; + } + + int getNotificationInboxExpiry() { + return notificationInboxExpiry; + } + + int getReadTimeout() { + return readTimeout; + } + + int getNotificationReadTimeout() { + return notificationReadTimeout; + } + + int getMaxServerWaitTime() { + return maxServerWaitTime; + } + + int getServerFailoverInterval() { + return serverFailoverInterval; + } + + int getServerStatusPollingInterval() { + return serverStatusPollingInterval; + } + + String getBasicAuthHeader() { + return basicAuthHeader; + } + + String getCurrentEndpoint() { + return currentEndpoint; + } + + boolean isCollectiveUtilConnection() { + return isCollectiveUtilConnection; + } + + void setCurrentEndpoint(String currentEndpoint) { + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), "setCurrentEndpoint", "Changing endpoint from " + this.currentEndpoint + " to " + currentEndpoint); + } + this.currentEndpoint = currentEndpoint; + } + + /** + * @return the logFailovers + */ + public boolean logFailovers() { + return logFailovers; + } + +} diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/internal/DynamicURL.java b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/internal/DynamicURL.java new file mode 100755 index 00000000000..857b69e6fec --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/internal/DynamicURL.java @@ -0,0 +1,45 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jmx.connector.client.rest.internal; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.logging.Level; +import java.util.logging.Logger; + +class DynamicURL { + + private static final Logger logger = Logger.getLogger(DynamicURL.class.getName()); + + private final String name; + private final Connector connector; + + DynamicURL(Connector connector, String name) { + this.name = name; + this.connector = connector; + } + + URL getURL() throws MalformedURLException { + String[] endpoint = RESTMBeanServerConnection.splitEndpoint(connector.getCurrentEndpoint()); + URL retURL = new URL("https", endpoint[0], Integer.valueOf(endpoint[1]), getName()); + + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), "getURL", "URL: " + retURL.toString()); + } + + return retURL; + } + + String getName() { + return name; + } +} diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/internal/FileTransferClient.java b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/internal/FileTransferClient.java new file mode 100755 index 00000000000..7cff1cfd7c5 --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/internal/FileTransferClient.java @@ -0,0 +1,619 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012, 2015 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jmx.connector.client.rest.internal; + +import java.io.Closeable; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.RandomAccessFile; +import java.net.ConnectException; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLEncoder; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.zip.GZIPInputStream; +import java.util.zip.GZIPOutputStream; + +import javax.net.ssl.HttpsURLConnection; + +import com.ibm.json.java.JSONArray; +import com.ibm.json.java.JSONObject; +import com.ibm.ws.jmx.connector.client.rest.ClientProvider; +import com.ibm.ws.jmx.connector.client.rest.internal.ClientConstants.HttpMethod; +import com.ibm.ws.jmx.connector.client.rest.internal.resources.FileTransferClientMessagesUtil; +import com.ibm.ws.jmx.connector.converter.JSONConverter; + +/** + * This class provides the client-side file transfer support. It uses artifacts from the jmx rest connector client, such as the root URL and + * security credentials. New URLs are appended to the file transfer REST calls, so that it maps to a different jax-rs resource on the server-side. + */ +class FileTransferClient { + + private static final Logger logger = Logger.getLogger(FileTransferClient.class.getName()); + + private static final String OPERATION_DOWNLOAD = "downloadFile"; + private static final String OPERATION_UPLOAD = "uploadFile"; + private static final String OPERATION_DELETE = "deleteFile"; + private static final String OPERATION_DELETE_ALL = "deleteAll"; + private static final String QUERY_PARAM_UPLOAD_EXPAND = "expandOnCompletion"; + private static final String QUERY_PARAM_START_OFFSET = "startOffset"; + private static final String QUERY_PARAM_END_OFFSET = "endOffset"; + + private static final String FILE_TRANSFER_URL_V2 = "/fileTransfer"; + private static final String FILE_TRANSFER_ROUTER_URL_V2 = FILE_TRANSFER_URL_V2 + "/router"; + + private static final String COLLECTION_URL = "/collection"; + private static final String COLLECTION_OPERATION_DELETE = "delete"; + + private static final String FILE_TRANSFER_CONTENT_TYPE = "application/gzip"; + private static final String FILE_TRANSFER_ZIP_MIME = "application/zip"; + private static final String FILE_TRANSFER_PAX_MIME = "application/pax"; + private static final String FILE_TRANSFER_JSON_MIME = "application/json"; + private static final int FILE_TRANSFER_DEFAULT_BUFFER_SIZE = 8 * 1024; + private static final String RANDOM_FILE_ACCESS_READ_MODE = "r"; + private static final String RANDOM_FILE_ACCESS_READ_WRITE_MODE = "rw"; + + private final RESTMBeanServerConnection restConnection; + + public FileTransferClient(RESTMBeanServerConnection restConnection) throws IOException { + this.restConnection = restConnection; + + if (logger.isLoggable(Level.FINE)) { + logger.logp(Level.FINE, logger.getName(), "constructor", + FileTransferClientMessagesUtil.getMessage(FileTransferClientMessagesUtil.CLIENT_INIT, restConnection.connector.getConnectionId())); + } + } + + /** + * Handle MBean invocation requests + */ + public Object handleOperation(String operation, Object[] params) throws IOException { + if (OPERATION_DOWNLOAD.equals(operation)) { + if (params.length == 2) { + downloadFile((String) params[0], (String) params[1]); + } else { + //partial download + return downloadFile((String) params[0], (String) params[1], (Long) params[2], (Long) params[3]); + } + } else if (OPERATION_UPLOAD.equals(operation)) { + uploadFile((String) params[0], (String) params[1], (Boolean) params[2]); + } else if (OPERATION_DELETE.equals(operation)) { + deleteFile((String) params[0]); + } else if (OPERATION_DELETE_ALL.equals(operation)) { + deleteAll((List) params[0]); + } else { + throw logUnsupportedOperationError("handleOperation", operation); + } + + //currently all operations are void, so return null. + return null; + } + + HttpsURLConnection getFileTransferConnection(URL url, HttpMethod method) throws IOException { + return getFileTransferConnection(url, method, true); + } + + HttpsURLConnection getFileTransferConnection(URL url, HttpMethod method, boolean setEncoding) throws IOException { + HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); + connection.setDoInput(true); + if (method == HttpMethod.POST) { + if (restConnection.serverVersion == 2) { + //In V2 we were setting the Content-Type to application/gzip. In V3+ we corrected that + //by not specifying a Content-Type and instead specifying that the Content-Encoding is gzip. + connection.setRequestProperty("Content-Type", FILE_TRANSFER_CONTENT_TYPE); + } + connection.setDoOutput(true); + } else { + connection.setDoOutput(false); + } + connection.setUseCaches(false); + connection.setRequestMethod(method.toString()); + connection.setReadTimeout(restConnection.connector.getReadTimeout()); + + // fix 'Invalid CRLF found in header name' error + if (restConnection.connector.getBasicAuthHeader() != null) { + connection.setRequestProperty("Authorization", restConnection.connector.getBasicAuthHeader()); + } + if (restConnection.connector.isHostnameVerificationDisabled()) { + connection.setHostnameVerifier(restConnection.hostnameVerificationDisabler); + } + + connection.setRequestProperty("User-Agent", RESTMBeanServerConnection.CLIENT_VERSION); + + //Set routing headers if applicable + if (restConnection.isHostLevelRouting()) { + connection.addRequestProperty(ClientProvider.ROUTING_KEY_HOST_NAME, (String) restConnection.mapRouting.get(ClientProvider.ROUTING_KEY_HOST_NAME)); + } else if (restConnection.isServerLevelRouting()) { + connection.addRequestProperty(ClientProvider.ROUTING_KEY_HOST_NAME, (String) restConnection.mapRouting.get(ClientProvider.ROUTING_KEY_HOST_NAME)); + connection.addRequestProperty(ClientProvider.ROUTING_KEY_SERVER_USER_DIR, (String) restConnection.mapRouting.get(ClientProvider.ROUTING_KEY_SERVER_USER_DIR)); + connection.addRequestProperty(ClientProvider.ROUTING_KEY_SERVER_NAME, (String) restConnection.mapRouting.get(ClientProvider.ROUTING_KEY_SERVER_NAME)); + } + + if (restConnection.getConnector().getCustomSSLSocketFactory() != null) { + connection.setSSLSocketFactory(restConnection.getConnector().getCustomSSLSocketFactory()); + } + + if (restConnection.serverVersion > 2 && setEncoding) { + if (method == HttpMethod.POST) { + connection.addRequestProperty("Content-Encoding", "gzip"); + } else { + connection.addRequestProperty("Accept-Encoding", "gzip"); + } + } + + return connection; + } + + private String getEncodedFilePath(String path) throws IOException { + return "/" + URLEncoder.encode(path, "UTF-8"); + } + + private String getFileTransferURL() throws IOException { + if (restConnection.serverVersion == 2) { + return restConnection.getRootURL() + FILE_TRANSFER_URL_V2; + } else { + return restConnection.getFileTransferURL().toString(); + } + } + + private String getFileTransferRoutingURL() throws IOException { + if (restConnection.serverVersion == 2) { + return restConnection.getRootURL() + FILE_TRANSFER_ROUTER_URL_V2; + } else { + return restConnection.getFileTransferURL().toString(); + } + } + + private URL getURL(Map queryParameters, String additionalURL) throws IOException { + + String coreURLStr; + + if (restConnection.isServerLevelRouting() || restConnection.isHostLevelRouting()) { + coreURLStr = getFileTransferRoutingURL() + additionalURL; + } else { + coreURLStr = getFileTransferURL() + additionalURL; + } + + if (logger.isLoggable(Level.FINEST)) { + logger.logp(Level.FINEST, logger.getName(), "getURL", "coreURLStr: " + coreURLStr); + } + + try { + if (queryParameters != null && !queryParameters.isEmpty()) { + //Iterate through the query parameters and build a query string + StringBuilder sb = new StringBuilder(); + Set> params = queryParameters.entrySet(); + + for (Entry param : params) { + //Add preceding characters + if (sb.length() == 0) { + //first entry + sb.append('?'); + } else { + //not the first entry + sb.append('&'); + } + + //Add parameter + sb.append(param.getKey()); + sb.append('='); + sb.append(URLEncoder.encode(param.getValue(), "UTF-8")); + } + + if (logger.isLoggable(Level.FINEST)) { + logger.logp(Level.FINEST, logger.getName(), "getURL", "queryURL: " + sb.toString()); + } + + return new URL(coreURLStr + sb.toString()); + } + + return new URL(coreURLStr); + + } catch (Exception e) { + throw logClientException("getURL", e); + } + + } + + public void downloadFile(String remoteSourceFile, String localTargetFile) throws IOException { + downloadFile(remoteSourceFile, localTargetFile, 0, -1); //regular download (non-partial download) + } + + public long downloadFile(String remoteSourceFile, String localTargetFile, long startOffset, long endOffset) throws IOException { + final String methodName = "downloadFile(String remoteSourceFile, String localTargetFile, long startOffset, long endOffset)"; + + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), methodName, "Entering downloadFile with remoteSourceFile: " + remoteSourceFile + " ; localTargetFile: " + localTargetFile + + " ; startOffset: " + startOffset + " and endOffset: " + endOffset); + } + + Map queryParams = new HashMap(); + + if (startOffset > 0) { + queryParams.put(QUERY_PARAM_START_OFFSET, String.valueOf(startOffset)); + } + + if (endOffset > -1) { + queryParams.put(QUERY_PARAM_END_OFFSET, String.valueOf(endOffset)); + } + + URL url = getURL(queryParams, getEncodedFilePath(remoteSourceFile)); + HttpsURLConnection connection = getFileTransferConnection(url, HttpMethod.GET); + + // Check response code from server + final int responseCode = connection.getResponseCode(); + InputStream is = null; + switch (responseCode) { + case HttpURLConnection.HTTP_OK: + + //Get the resulting stream + is = connection.getInputStream(); + + if (logger.isLoggable(Level.FINEST)) { + logger.logp(Level.FINEST, logger.getName(), methodName, "Received stream: " + FileTransferClientMessagesUtil.getObjID(is)); + } + //Data is always compressed with this java client, so use GZIP stream reader + is = new GZIPInputStream(is, FILE_TRANSFER_DEFAULT_BUFFER_SIZE); + break; + + case HttpURLConnection.HTTP_BAD_REQUEST: + case HttpURLConnection.HTTP_INTERNAL_ERROR: + throw logServerException(methodName, connection); + case HttpURLConnection.HTTP_UNAUTHORIZED: + case HttpURLConnection.HTTP_FORBIDDEN: + throw logCredentialsException(methodName, responseCode, connection); + case HttpURLConnection.HTTP_GONE: + case HttpURLConnection.HTTP_NOT_FOUND: + IOException ioe = logResponseCodeException(methodName, responseCode, connection); + restConnection.recoverConnection(ioe); + throw ioe; + default: + throw logResponseCodeException(methodName, responseCode, connection); + } + + //Create our target output stream + RandomAccessFile destFile = new RandomAccessFile(localTargetFile, RANDOM_FILE_ACCESS_READ_WRITE_MODE); + long totalBytesRead = 0; + + try { + //Transfer bytes to output file + byte[] buf = new byte[FILE_TRANSFER_DEFAULT_BUFFER_SIZE]; + int bytesRead; + + while ((bytesRead = is.read(buf)) > 0) { + destFile.write(buf, 0, bytesRead); + totalBytesRead += bytesRead; + } + destFile.setLength(totalBytesRead); + } finally { + tryToClose(is); + tryToClose(destFile); + } + + if (logger.isLoggable(Level.FINE)) { + logger.logp(Level.FINE, logger.getName(), methodName, + FileTransferClientMessagesUtil.getMessage(FileTransferClientMessagesUtil.DOWNLOAD_TO_FILE, remoteSourceFile, localTargetFile, + restConnection.connector.getConnectionId())); + } + + if (startOffset < 0) { + startOffset = 0; + } + + long nextStartOffset = startOffset + totalBytesRead; + + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), methodName, "Exiting downloadFile with nextStartOffset=" + nextStartOffset); + } + + return nextStartOffset; + } + + public void uploadFile(String localSourceFile, String remoteTargetFile, boolean expandOnCompletion) throws IOException { + final String methodName = "uploadFile(String localSourceFile, String remoteTargetFile, boolean expandOnCompletion)"; + + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), methodName, "Entering uploadFile with localSourceFile: " + localSourceFile + " and remoteTargetFile: " + remoteTargetFile); + } + + Map queryParams = new HashMap(); + queryParams.put(QUERY_PARAM_UPLOAD_EXPAND, String.valueOf(expandOnCompletion)); + URL url = getURL(queryParams, getEncodedFilePath(remoteTargetFile)); + HttpsURLConnection connection = getFileTransferConnection(url, HttpMethod.POST); + + if (expandOnCompletion && restConnection.serverVersion >= 5) { + //Starting with server V5 users aren't required to put an extension on the target file, + //so for archives that will be expanded we place a proper Content-Type + if (localSourceFile.endsWith(".pax")) { + connection.setRequestProperty("Content-Type", FILE_TRANSFER_PAX_MIME); + } else { + //default is zip, since it's handled the same was WAR/EAR/JAR + connection.setRequestProperty("Content-Type", FILE_TRANSFER_ZIP_MIME); + } + } + + //Grab file to be uploaded + RandomAccessFile uploadFile = new RandomAccessFile(localSourceFile, RANDOM_FILE_ACCESS_READ_MODE); + + //Grab the outgoing stream + OutputStream outStream = null; + try { + outStream = connection.getOutputStream(); + } catch (ConnectException ce) { + restConnection.recoverConnection(ce); + tryToClose(outStream); + tryToClose(uploadFile); + throw ce; + } + + //We're always compressing the transfers from this java client, so use GZIP + outStream = new GZIPOutputStream(outStream, FILE_TRANSFER_DEFAULT_BUFFER_SIZE); + + try { + //Transfer bytes to output file + byte[] buf = new byte[FILE_TRANSFER_DEFAULT_BUFFER_SIZE]; + int bytesRead; + while ((bytesRead = uploadFile.read(buf)) > 0) { + outStream.write(buf, 0, bytesRead); + } + outStream.flush(); + + } finally { + tryToClose(outStream); + tryToClose(uploadFile); + } + + // Check response code from server + final int responseCode = connection.getResponseCode(); + switch (responseCode) { + case HttpURLConnection.HTTP_NO_CONTENT: + + if (logger.isLoggable(Level.FINE)) { + logger.logp(Level.FINE, logger.getName(), methodName, + FileTransferClientMessagesUtil.getMessage(FileTransferClientMessagesUtil.UPLOAD_FROM_FILE, localSourceFile, remoteTargetFile, + restConnection.connector.getConnectionId())); + } + + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), methodName, "Exiting uploadFile"); + } + + return; + + case HttpURLConnection.HTTP_BAD_REQUEST: + case HttpURLConnection.HTTP_INTERNAL_ERROR: + throw logServerException(methodName, connection); + + case HttpURLConnection.HTTP_UNAUTHORIZED: + case HttpURLConnection.HTTP_FORBIDDEN: + throw logCredentialsException(methodName, responseCode, connection); + + case HttpURLConnection.HTTP_GONE: + case HttpURLConnection.HTTP_NOT_FOUND: + IOException ioe = logResponseCodeException(methodName, responseCode, connection); + restConnection.recoverConnection(ioe); + throw ioe; + + default: + throw logResponseCodeException(methodName, responseCode, connection); + } + + } + + public void deleteFile(String remoteSourceFile) throws IOException { + final String methodName = "deleteFile(String remoteSourceFile)"; + + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), methodName, "Entering deleteFile with remoteSourceFile: " + remoteSourceFile); + } + + URL url = getURL(null, getEncodedFilePath(remoteSourceFile)); + HttpsURLConnection connection = getFileTransferConnection(url, HttpMethod.DELETE); + + // Check response code from server + final int responseCode = connection.getResponseCode(); + switch (responseCode) { + case HttpURLConnection.HTTP_NO_CONTENT: + + if (logger.isLoggable(Level.FINE)) { + logger.logp(Level.FINE, logger.getName(), methodName, + FileTransferClientMessagesUtil.getMessage(FileTransferClientMessagesUtil.DELETE_FILE, remoteSourceFile, + restConnection.connector.getConnectionId())); + } + + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), methodName, "Exiting deleteFile"); + } + + return; + + case HttpURLConnection.HTTP_BAD_REQUEST: + case HttpURLConnection.HTTP_INTERNAL_ERROR: + throw logServerException(methodName, connection); + + case HttpURLConnection.HTTP_UNAUTHORIZED: + case HttpURLConnection.HTTP_FORBIDDEN: + throw logCredentialsException(methodName, responseCode, connection); + + case HttpURLConnection.HTTP_GONE: + case HttpURLConnection.HTTP_NOT_FOUND: + IOException ioe = logResponseCodeException(methodName, responseCode, connection); + restConnection.recoverConnection(ioe); + throw ioe; + + default: + throw logResponseCodeException(methodName, responseCode, connection); + } + } + + public void deleteAll(List remoteArtifacts) throws IOException { + final String methodName = "deleteAll(List remoteArtifacts)"; + + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), methodName, "Entering deleteAll with remoteArtifacts: " + remoteArtifacts); + } + + URL url = getURL(null, COLLECTION_URL); + HttpsURLConnection connection = getFileTransferConnection(url, HttpMethod.POST, false); + connection.setRequestProperty("Content-Type", FILE_TRANSFER_JSON_MIME); + + //Grab the outgoing stream + OutputStream outStream = null; + try { + outStream = connection.getOutputStream(); + } catch (ConnectException ce) { + restConnection.recoverConnection(ce); + tryToClose(outStream); + throw ce; + } + + try { + // Generate JSON with following structure: { "delete": ["C:/temp/output.log", "C:/wlp", "C:/workarea"] } + JSONArray artifactsArray = new JSONArray(); + for (String artifact : remoteArtifacts) { + artifactsArray.add(artifact); + } + + JSONObject contentObject = new JSONObject(); + contentObject.put(COLLECTION_OPERATION_DELETE, artifactsArray); + + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), methodName, "Generated JSON: " + contentObject.toString()); + } + outStream.write(contentObject.toString().getBytes("UTF-8")); + outStream.flush(); + } finally { + tryToClose(outStream); + } + + // Check response code from server + final int responseCode = connection.getResponseCode(); + + switch (responseCode) { + case HttpURLConnection.HTTP_NO_CONTENT: + + if (logger.isLoggable(Level.FINE)) { + logger.logp(Level.FINE, logger.getName(), methodName, + FileTransferClientMessagesUtil.getMessage(FileTransferClientMessagesUtil.DELETE_ALL, remoteArtifacts, + restConnection.connector.getConnectionId())); + } + + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), methodName, "Exiting deleteAll"); + } + + return; + + case HttpURLConnection.HTTP_BAD_REQUEST: + case HttpURLConnection.HTTP_INTERNAL_ERROR: + throw logServerException(methodName, connection); + + case HttpURLConnection.HTTP_UNAUTHORIZED: + case HttpURLConnection.HTTP_FORBIDDEN: + throw logCredentialsException(methodName, responseCode, connection); + + case HttpURLConnection.HTTP_GONE: + case HttpURLConnection.HTTP_NOT_FOUND: + IOException ioe = logResponseCodeException(methodName, responseCode, connection); + restConnection.recoverConnection(ioe); + throw ioe; + + default: + throw logResponseCodeException(methodName, responseCode, connection); + } + } + + public static boolean tryToClose(Closeable closeable) { + if (closeable != null) { + try { + closeable.close(); + return true; + } catch (IOException e) { + // ignore + } + } + return false; + } + + private IOException logClientException(String methodName, Exception e) { + String errorMsg = FileTransferClientMessagesUtil.getMessage(FileTransferClientMessagesUtil.CLIENT_ERROR, e.getLocalizedMessage(), + restConnection.connector.getConnectionId()); + logger.logp(Level.SEVERE, logger.getName(), methodName, errorMsg, e); + return new IOException(errorMsg, e); + } + + private IOException logServerException(String methodName, HttpURLConnection connection) { + Throwable t = null; + JSONConverter converter = JSONConverter.getConverter(); + try { + t = converter.readThrowable(connection.getErrorStream()); + logger.logp(Level.SEVERE, logger.getName(), methodName, t.getMessage()); + + } catch (Exception e) { + //Fallback into standard server message + String responseMessage = "error"; + try { + responseMessage = connection.getResponseMessage(); + } catch (IOException io) { + // Use "error" for message..but shouldn't really happen + } + String errorMsg = FileTransferClientMessagesUtil.getMessage(FileTransferClientMessagesUtil.SERVER_ERROR, responseMessage, + restConnection.connector.getConnectionId()); + t = new IOException(errorMsg); + logger.logp(Level.SEVERE, logger.getName(), methodName, errorMsg); + } finally { + JSONConverter.returnConverter(converter); + } + + return (t instanceof IOException) ? (IOException) t : new IOException(t); + } + + private IOException logCredentialsException(String methodName, int responseCode, HttpURLConnection connection) { + String responseMessage = null; + try { + responseMessage = connection.getResponseMessage(); + } catch (IOException io) { + // Use null for message + } + String errorMsg = FileTransferClientMessagesUtil.getMessage(FileTransferClientMessagesUtil.BAD_CREDENTIALS, responseCode, responseMessage, + restConnection.connector.getConnectionId()); + logger.logp(Level.SEVERE, logger.getName(), methodName, errorMsg); + return new IOException(errorMsg); + } + + private IOException logResponseCodeException(String methodName, int responseCode, HttpURLConnection connection) { + String responseMessage = null; + try { + responseMessage = connection.getResponseMessage(); + } catch (IOException io) { + // Use null for message + } + String errorMsg = FileTransferClientMessagesUtil.getMessage(FileTransferClientMessagesUtil.RESPONSE_CODE_ERROR, responseCode, responseMessage, + restConnection.connector.getConnectionId()); + logger.logp(Level.SEVERE, logger.getName(), methodName, errorMsg); + return new IOException(errorMsg); + } + + private IOException logUnsupportedOperationError(String methodName, String operation) { + String errorMsg = FileTransferClientMessagesUtil.getMessage(FileTransferClientMessagesUtil.UNSUPPORTED_OPERATION, operation, restConnection.connector.getConnectionId()); + logger.logp(Level.SEVERE, logger.getName(), methodName, errorMsg); + return new IOException(errorMsg); + } + +} diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/internal/NotificationListenerEntry.java b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/internal/NotificationListenerEntry.java new file mode 100755 index 00000000000..49738d7371c --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/internal/NotificationListenerEntry.java @@ -0,0 +1,71 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012, 2014 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jmx.connector.client.rest.internal; + +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.management.Notification; +import javax.management.NotificationFilter; +import javax.management.NotificationListener; + +import com.ibm.ws.jmx.connector.client.rest.internal.resources.RESTClientMessagesUtil; + +class NotificationListenerEntry { + public final NotificationListener listener; + public final NotificationFilter filter; + public final Object handback; + + private static final Logger logger = Logger.getLogger(NotificationListenerEntry.class.getName()); + + /** + * @param listener + * @param filter + * @param handback + */ + NotificationListenerEntry(NotificationListener listener, NotificationFilter filter, Object handback) { + this.listener = listener; + this.filter = filter; + this.handback = handback; + + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), "NotificationListenerEntry", "[" + RESTClientMessagesUtil.getObjID(this) + "] | listener: " + listener + " | filter: " + + filter + " | handback: " + handback); + } + } + + void handleNotification(Notification notification) { + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), "handleNotification", "[" + RESTClientMessagesUtil.getObjID(this) + "] | Notification: " + notification); + } + + if (filter == null || filter.isNotificationEnabled(notification)) { + listener.handleNotification(notification, handback); + } + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof NotificationListenerEntry)) + return false; + NotificationListenerEntry other = (NotificationListenerEntry) o; + return listener.equals(other.listener) && filter == other.filter && handback == other.handback; + } + + @Override + public int hashCode() { + return listener.hashCode() + + (filter != null ? filter.hashCode() : 0) + + (handback != null ? handback.hashCode() : 0); + } + +} diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/internal/NotificationRegistry.java b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/internal/NotificationRegistry.java new file mode 100755 index 00000000000..15a730bcad1 --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/internal/NotificationRegistry.java @@ -0,0 +1,907 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012, 2014 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jmx.connector.client.rest.internal; + +import java.io.IOException; +import java.io.OutputStream; +import java.net.ConnectException; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.management.InstanceNotFoundException; +import javax.management.ListenerNotFoundException; +import javax.management.Notification; +import javax.management.NotificationFilter; +import javax.management.NotificationListener; +import javax.management.ObjectName; +import javax.management.OperationsException; +import javax.management.RuntimeOperationsException; +import javax.net.ssl.HttpsURLConnection; + +import com.ibm.ws.jmx.connector.client.rest.internal.ClientConstants.HttpMethod; +import com.ibm.ws.jmx.connector.client.rest.internal.RESTMBeanServerConnection.PollingMode; +import com.ibm.ws.jmx.connector.client.rest.internal.resources.RESTClientMessagesUtil; +import com.ibm.ws.jmx.connector.converter.JSONConverter; +import com.ibm.ws.jmx.connector.converter.NotificationTargetInformation; +import com.ibm.ws.jmx.connector.datatypes.NotificationArea; +import com.ibm.ws.jmx.connector.datatypes.NotificationRegistration; +import com.ibm.ws.jmx.connector.datatypes.NotificationSettings; +import com.ibm.ws.jmx.connector.datatypes.ServerNotificationRegistration; +import com.ibm.ws.jmx.connector.datatypes.ServerNotificationRegistration.Operation; + +class NotificationRegistry { + + private static final Logger logger = Logger.getLogger(NotificationRegistry.class.getName()); + + private final RESTMBeanServerConnection serverConnection; + private DynamicURL inboxURL, registrationsURL, serverRegistrationsURL, notificationClientURL; + private final Map registrationMap = Collections.synchronizedMap(new HashMap()); + private final List serverRegistrationList = Collections.synchronizedList(new ArrayList()); + private ObjectIdentityCache identityCache; + private final JSONConverter converter = JSONConverter.getConverter(); + + NotificationRegistry(RESTMBeanServerConnection serverConnection) throws IOException { + this.serverConnection = serverConnection; + + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), "init", "Initializing registry " + RESTClientMessagesUtil.getObjID(this) + " within connection: " + + serverConnection.getConnector().getConnectionId()); + } + + try { + setupNotificationArea(); + } catch (IOException io) { + //ignore IOException at this point, because we will do a connection recovery later on inside the notification thread's run method. + } catch (Throwable t) { + throw new IOException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.UNEXPECTED_SERVER_THROWABLE), t); + } + } + + //NOTE: we don't call recoverConnection from this method, because this method is already called from recoverConnection so + //we want to avoid cycles. + protected void setupNotificationArea() throws Throwable { + final String sourceMethod = "setupNotificationArea"; + + URL notificationsURL = null; + HttpsURLConnection connection = null; + try { + // Get URL for creating a notification area + notificationsURL = serverConnection.getNotificationsURL(); + + if (logger.isLoggable(Level.FINEST)) { + logger.logp(Level.FINEST, logger.getName(), sourceMethod, "[" + RESTClientMessagesUtil.getObjID(this) + "] About to call notificationURL: " + notificationsURL); + } + + // Get connection to server + connection = serverConnection.getConnection(notificationsURL, HttpMethod.POST, true); + + // Create NotificationSettings object + NotificationSettings ns = new NotificationSettings(); + ns.deliveryInterval = serverConnection.getConnector().getNotificationDeliveryInterval(); + ns.inboxExpiry = serverConnection.getConnector().getNotificationInboxExpiry(); + + // Write CreateMBean JSON to connection output stream + OutputStream output = connection.getOutputStream(); + converter.writeNotificationSettings(output, ns); + output.flush(); + } catch (ConnectException ce) { + // Server is down; not a client bug + throw ce; + } catch (IOException io) { + throw serverConnection.getRequestErrorException(sourceMethod, io, notificationsURL); + } + + // Check response code from server + final int responseCode = connection.getResponseCode(); + + if (logger.isLoggable(Level.FINEST)) { + logger.logp(Level.FINEST, logger.getName(), sourceMethod, "Received responseCode: " + responseCode); + } + + switch (responseCode) { + case HttpURLConnection.HTTP_OK: + JSONConverter converter = JSONConverter.getConverter(); + try { + // Process and return server response, which should be a NotificationArea + NotificationArea area = converter.readNotificationArea(connection.getInputStream()); + + inboxURL = new DynamicURL(serverConnection.connector, area.inboxURL); + registrationsURL = new DynamicURL(serverConnection.connector, area.registrationsURL); + serverRegistrationsURL = new DynamicURL(serverConnection.connector, area.serverRegistrationsURL); + notificationClientURL = new DynamicURL(serverConnection.connector, area.clientURL); + + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), "setupNotificationArea", "Successfully setup inboxURL: " + inboxURL.getURL()); + } + break; + } catch (Exception e) { + throw serverConnection.getResponseErrorException(sourceMethod, e, notificationsURL); + } finally { + JSONConverter.returnConverter(converter); + } + case HttpURLConnection.HTTP_NOT_FOUND: + throw new IOException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.URL_NOT_FOUND)); + case HttpURLConnection.HTTP_UNAVAILABLE: + case HttpURLConnection.HTTP_BAD_REQUEST: + case HttpURLConnection.HTTP_INTERNAL_ERROR: + // Server response should be a serialized Throwable + throw serverConnection.getServerThrowable(sourceMethod, connection); + case HttpURLConnection.HTTP_UNAUTHORIZED: + case HttpURLConnection.HTTP_FORBIDDEN: + throw serverConnection.getBadCredentialsException(responseCode, connection); + default: + throw serverConnection.getResponseCodeErrorException(sourceMethod, responseCode, connection); + } + } + + synchronized void addNotificationListener(ObjectName name, NotificationListener listener, NotificationFilter filter, Object handback) throws InstanceNotFoundException, IOException { + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), "addNotificationListener", "[" + RESTClientMessagesUtil.getObjID(this) + "] objectName: " + name + " | listener: " + + listener + " | filter: " + filter + " | handback: " + + handback); + } + // Check if the MBean is registered and throw InstanceNotFoundException if not + // (it is possible the registration will not need updating, so we do this check first) + if (!serverConnection.isRegistered(name)) { + throw new InstanceNotFoundException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.INSTANCE_NOT_FOUND, name)); + } + + // Build identifier for accessing the registration map. + // If a routing context has been set up, include the routing info (host name, server name, server user dir) as part of the key. + final NotificationTargetInformation nti; + if (serverConnection.isServerLevelRouting()) { + nti = new NotificationTargetInformation(name, serverConnection.mapRouting); + } else { + nti = new NotificationTargetInformation(name); + } + + NotificationListenerEntry set = new NotificationListenerEntry(listener, filter, handback); + ClientNotificationRegistration localRegistration = registrationMap.get(nti); + if (localRegistration == null) { + localRegistration = new ClientNotificationRegistration(nti); + registrationMap.put(nti, localRegistration); + } + + localRegistration.addNotificationListenerEntry(set); + + //ensure we're polling for notifications (will be no-op if we're already polling for notifications) + serverConnection.setPollingMode(PollingMode.NOTIFICATION); + } + + synchronized void addNotificationListener(ObjectName name, ObjectName listener, NotificationFilter filter, Object handback) throws InstanceNotFoundException, IOException { + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), "addNotificationListener", "[" + RESTClientMessagesUtil.getObjID(this) + "] objectName: " + name + " | listener: " + + listener + " | filter: " + filter + " | handback: " + handback); + } + + // Build identifier for accessing the server registration list. + // If a routing context has been set up, include the routing info (host name, server name, server user dir) as part of the key. + final NotificationTargetInformation nti; + if (serverConnection.isServerLevelRouting()) { + nti = new NotificationTargetInformation(name, serverConnection.mapRouting); + } else { + nti = new NotificationTargetInformation(name); + } + + try { + updateServerNotificationRegistration(nti, listener, filter, handback, Operation.Add); + serverRegistrationList.add(new ServerNotificationListenerEntry(nti, listener, filter, handback)); + } catch (ListenerNotFoundException lnf) { + throw new IOException(lnf); // Should never happen + } + + //ensure we're polling for notifications (will be no-op if we're already polling for notifications) + serverConnection.setPollingMode(PollingMode.NOTIFICATION); + } + + synchronized void removeNotificationListener(ObjectName name, ObjectName listener) throws InstanceNotFoundException, ListenerNotFoundException, IOException { + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), "removeNotificationListener", "[" + RESTClientMessagesUtil.getObjID(this) + "] objectName: " + name + " | listener: " + + listener); + } + + // Build identifier for accessing the server registration list. + // If a routing context has been set up, include the routing info (host name, server name, server user dir) as part of the key. + final NotificationTargetInformation nti; + if (serverConnection.isServerLevelRouting()) { + nti = new NotificationTargetInformation(name, serverConnection.mapRouting); + } else { + nti = new NotificationTargetInformation(name); + } + + updateServerNotificationRegistration(nti, listener, null, null, Operation.RemoveAll); + Iterator iterator = serverRegistrationList.iterator(); + while (iterator.hasNext()) { + ServerNotificationListenerEntry entry = iterator.next(); + // Remove all registrations for the listener on the given MBean (ObjectName + routing info). + if (entry.nti.equals(nti) && entry.listener.equals(listener)) { + iterator.remove(); + } + } + + cleanupIfEmpty(); + } + + synchronized void removeNotificationListener(ObjectName name, ObjectName listener, NotificationFilter filter, Object handback) throws InstanceNotFoundException, ListenerNotFoundException, IOException { + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), "removeNotificationListener", "[" + RESTClientMessagesUtil.getObjID(this) + "] objectName: " + name + " | listener: " + + listener + " | filter: " + filter + " | handback: " + + handback); + } + + // Build identifier for accessing the server registration list. + // If a routing context has been set up, include the routing info (host name, server name, server user dir) as part of the key. + final NotificationTargetInformation nti; + if (serverConnection.isServerLevelRouting()) { + nti = new NotificationTargetInformation(name, serverConnection.mapRouting); + } else { + nti = new NotificationTargetInformation(name); + } + + updateServerNotificationRegistration(nti, listener, filter, handback, Operation.RemoveSpecific); + serverRegistrationList.remove(new ServerNotificationListenerEntry(nti, listener, filter, handback)); + + cleanupIfEmpty(); + } + + synchronized void removeNotificationListener(ObjectName name, NotificationListener listener) throws InstanceNotFoundException, ListenerNotFoundException, IOException { + removeNotificationListener(name, listener, null, null, true); + } + + synchronized void removeNotificationListener(ObjectName name, NotificationListener listener, NotificationFilter filter, Object handback) throws InstanceNotFoundException, ListenerNotFoundException, IOException { + removeNotificationListener(name, listener, filter, handback, false); + } + + void close() { + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), "close", "Closing registry " + RESTClientMessagesUtil.getObjID(this)); + } + + if (serverConnection.isConnected()) { + sendClosingSignal(); + } + + JSONConverter.returnConverter(converter); + } + + //This method sends a signal to the server-side indicating that the inbox can be deleted, because this client is being closed. + //We don't throw any errors because the connector is about to be closed. + private void sendClosingSignal() { + URL clientURL = null; + HttpsURLConnection connection = null; + try { + // Get the appropriate URL to delete notification client + if (serverConnection.serverVersion >= 4) { + //V4+ clients use /{clientID} to delete the notification client + clientURL = getNotificationClientURL(); + } else { + //Pre-V4 clients use /{clientID}/inbox to delete the notification client + clientURL = getInboxURL(); + } + + if (logger.isLoggable(Level.FINEST)) { + logger.logp(Level.FINEST, + logger.getName(), + "sendClosingSignal", + "Making a call to delete inbox [" + clientURL + "] from [" + + RESTClientMessagesUtil.getObjID(this) + "]"); + } + // Get connection to server + connection = serverConnection.getConnection(clientURL, HttpMethod.DELETE, true); + connection.setReadTimeout(serverConnection.getConnector().getReadTimeout()); + + // Check response code from server + int responseCode = 0; + try { + responseCode = connection.getResponseCode(); + } catch (ConnectException ce) { + logger.logp(Level.FINE, logger.getName(), "sendClosingSignal", ce.getMessage(), ce); + } + + if (logger.isLoggable(Level.FINEST)) { + logger.logp(Level.FINEST, logger.getName(), "sendClosingSignal", "Response code: " + responseCode); + } + + } catch (IOException io) { + logger.logp(Level.FINE, logger.getName(), "sendClosingSignal", io.getMessage(), io); + } + } + + synchronized void connectionFailed(Throwable t) { + serverConnection.connectionFailed(t); + } + + private void updateServerNotificationRegistration(NotificationTargetInformation nti, ObjectName listener, NotificationFilter filter, Object handback, Operation operation) throws InstanceNotFoundException, ListenerNotFoundException, IOException { + final String sourceMethod = "updateServerNotificationRegistration"; + + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), sourceMethod, "[" + RESTClientMessagesUtil.getObjID(this) + "] objectName: " + nti.getName() + " | listener: " + + listener + " | filter: " + filter + " | handback: " + + handback + " | operation: " + operation); + } + + URL serverRegistrationsURL = null; + HttpsURLConnection connection = null; + try { + // Get URL for creating/updating ServerNotificationRegistrations + serverRegistrationsURL = getServerRegistrationsURL(); + + // Get connection to server + connection = serverConnection.getConnection(serverRegistrationsURL, HttpMethod.POST, true, nti.getRoutingInformation()); + + // Create ServerNotificationRegistration object + ServerNotificationRegistration snr = new ServerNotificationRegistration(); + snr.objectName = nti.getName(); + snr.listener = listener; + if (operation == Operation.Add) { + snr.filter = filter; + snr.handback = handback; + } + if (operation != Operation.RemoveAll) { + if (identityCache == null) + identityCache = new ObjectIdentityCache(); + snr.filterID = identityCache.getObjectIdentity(filter); + snr.handbackID = identityCache.getObjectIdentity(handback); + } + snr.operation = operation; + + // Write NotificationRegsitration JSON to connection output stream + OutputStream output = connection.getOutputStream(); + converter.writeServerNotificationRegistration(output, snr); + output.flush(); + output.close(); + } catch (ConnectException ce) { + // Server is down; not a client bug + throw ce; + } catch (IOException io) { + throw serverConnection.getRequestErrorException(sourceMethod, io, serverRegistrationsURL); + } + + // Check response code from server + int responseCode = 0; + try { + responseCode = connection.getResponseCode(); + } catch (ConnectException ce) { + serverConnection.recoverConnection(ce); + // Server is down; not a client bug + throw ce; + } + + switch (responseCode) { + case HttpURLConnection.HTTP_NO_CONTENT: + // Nothing to do; no response expected + break; + case HttpURLConnection.HTTP_GONE: + case HttpURLConnection.HTTP_NOT_FOUND: + try { + // Server response should be a serialized Throwable, and if the notification area is gone, + // this connection is no longer valid + throw serverConnection.getServerThrowable(sourceMethod, connection); + } catch (IOException io) { + serverConnection.recoverConnection(io); + throw io; + } catch (Throwable t) { + throw new IOException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.UNEXPECTED_SERVER_THROWABLE), t); + } + case HttpURLConnection.HTTP_BAD_REQUEST: + case HttpURLConnection.HTTP_INTERNAL_ERROR: + try { + // Server response should be a serialized Throwable + throw converter.readThrowable(connection.getErrorStream()); + } catch (RuntimeOperationsException roe) { + throw roe; + } catch (ListenerNotFoundException lnf) { + throw lnf; + } catch (InstanceNotFoundException inf) { + throw inf; + } catch (IOException io) { + throw io; + } catch (ClassNotFoundException cnf) { + throw new IOException(cnf); + } catch (Throwable t) { + throw new IOException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.UNEXPECTED_SERVER_THROWABLE), t); + } + case HttpURLConnection.HTTP_UNAUTHORIZED: + case HttpURLConnection.HTTP_FORBIDDEN: + throw serverConnection.getBadCredentialsException(responseCode, connection); + default: + throw serverConnection.getResponseCodeErrorException(sourceMethod, responseCode, connection); + } + } + + private void removeNotificationListener(ObjectName name, NotificationListener listener, NotificationFilter filter, Object handback, boolean matchListenerOnly) throws InstanceNotFoundException, ListenerNotFoundException, IOException { + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), "removeNotificationListener", "[" + RESTClientMessagesUtil.getObjID(this) + "] objectName: " + name + " | listener: " + + listener + " | filter: " + filter + " | handback: " + + handback + " | matchListenerOnly: " + matchListenerOnly); + } + + // Check if the MBean is registered and throw InstanceNotFoundException if not + // (it is possible the registration will not need updating, so we do this check first) + if (!serverConnection.isRegistered(name)) { + throw new InstanceNotFoundException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.INSTANCE_NOT_FOUND, name)); + } + + // Build identifier for accessing the registration map. + // If a routing context has been set up, include the routing info (host name, server name, server user dir) as part of the key. + final NotificationTargetInformation nti; + if (serverConnection.isServerLevelRouting()) { + nti = new NotificationTargetInformation(name, serverConnection.mapRouting); + } else { + nti = new NotificationTargetInformation(name); + } + + ClientNotificationRegistration localRegistration = registrationMap.get(nti); + if (localRegistration == null) + throw new ListenerNotFoundException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.LISTENER_NOT_FOUND, name)); + + localRegistration.removeNotificationListenerEntries(name, listener, filter, handback, matchListenerOnly); + if (localRegistration.isEmpty()) { + registrationMap.remove(nti); + } + + cleanupIfEmpty(); + } + + /** + * If there are no more registered listeners then we cleanup this registry and stop notification polling + */ + private void cleanupIfEmpty() { + if (registrationMap.isEmpty() && serverRegistrationList.isEmpty()) { + serverConnection.discardNotificationRegistry(); + } + } + + protected synchronized boolean restoreNotificationRegistrations(boolean sendRestoreNotification) { + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), "restoreNotificationRegistrations", "[" + RESTClientMessagesUtil.getObjID(this) + "]"); + } + + List clientRemovalList = new ArrayList(); + List serverRemovalList = new ArrayList(); + List exceptions = null; + Iterator> cnrIterator = registrationMap.entrySet().iterator(); + // Try to restore the registration for the notification listeners we've accumulated in the registration map. + while (cnrIterator.hasNext()) { + Map.Entry entry = cnrIterator.next(); + try { + entry.getValue().createNotificationRegistration(); + } catch (IOException io) { + // Unsuccessful + return false; + } catch (InstanceNotFoundException inf) { + // Can continue, but need to note that some could not be restored + if (exceptions == null) + exceptions = new ArrayList(); + + clientRemovalList.add(entry.getKey()); + exceptions.add(inf); + } + } + + for (ServerNotificationListenerEntry snl : serverRegistrationList) { + try { + updateServerNotificationRegistration(snl.nti, snl.listener, snl.filter, snl.handback, Operation.Add); + } catch (IOException io) { + // Unsuccessful + return false; + } catch (OperationsException oe) { + // Can continue, but need to note that some could not be restored + if (exceptions == null) + exceptions = new ArrayList(); + + serverRemovalList.add(snl); + exceptions.add(oe); + } + } + + if (exceptions != null) { + for (NotificationTargetInformation clientEntry : clientRemovalList) + registrationMap.remove(clientEntry); + for (ServerNotificationListenerEntry snl : serverRemovalList) + serverRegistrationList.remove(snl); + } + + if (sendRestoreNotification) { + serverConnection.getConnector().connectionRestored(exceptions != null ? exceptions.toArray(new Exception[exceptions.size()]) : null); + } + + return true; + } + + protected URL getInboxURL() throws IOException { + return inboxURL.getURL(); + } + + protected URL getNotificationClientURL() throws IOException { + return notificationClientURL.getURL(); + } + + protected DynamicURL getRegistrationsURL() throws IOException { + return registrationsURL; + } + + protected URL getServerRegistrationsURL() throws IOException { + return serverRegistrationsURL.getURL(); + } + + class ClientNotificationRegistration { + private final NotificationTargetInformation listenerKey; + private DynamicURL registrationURL; + private final List entries; + private List serverFilters; + + ClientNotificationRegistration(NotificationTargetInformation listenerKey) { + this.listenerKey = listenerKey; + entries = new ArrayList(); + + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), "ClientNotificationRegistrion init", "[" + RESTClientMessagesUtil.getObjID(NotificationRegistry.this) + + "] | [" + RESTClientMessagesUtil.getObjID(this) + + "] | objectName: " + listenerKey.getName()); + } + } + + synchronized void addNotificationListenerEntry(NotificationListenerEntry entry) throws InstanceNotFoundException, IOException { + final boolean serverFiltersUpdated; + + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), "addNotificationListenerEntry", "[" + RESTClientMessagesUtil.getObjID(this) + "]"); + } + + // Receive all notifications if there is no filter, or if it cannot be transmitted + // to the server for server-side filtering + final boolean receiveAllNotifications = entry.filter == null || !converter.isSupportedNotificationFilter(entry.filter); + + if (receiveAllNotifications) { + if (serverFilters != null) { + serverFilters = null; + serverFiltersUpdated = true; + } else { + serverFiltersUpdated = false; + } + } else if (serverFilters != null || entries.size() == 0) { + // if there are already server-side filters, or there are no other notification sets, + // the current filter can be added to the list + if (serverFilters == null) + serverFilters = new ArrayList(); + serverFilters.add(entry.filter); + serverFiltersUpdated = true; + } else { + // there is already at least one notification set that cannot rely on + // server side filtering + serverFiltersUpdated = false; + } + + entries.add(entry); + + if (registrationURL == null) { + createNotificationRegistration(); + } else if (serverFiltersUpdated) { + updateNotificationRegistration(); + } + } + + synchronized void removeNotificationListenerEntries(ObjectName name, NotificationListener listener, NotificationFilter filter, Object handback, boolean matchListenerOnly) throws InstanceNotFoundException, ListenerNotFoundException, IOException { + boolean listenerFound = false; + + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), "removeNotificationListenerEntries", "[" + RESTClientMessagesUtil.getObjID(this) + "] | objectName: " + + name + " | listener: " + listener + " | filter: " + filter + " | handback: " + + handback + " | matchListenerOnly: " + matchListenerOnly); + } + + Iterator entryIterator = entries.iterator(); + while (entryIterator.hasNext()) { + NotificationListenerEntry entry = entryIterator.next(); + if (entry.listener == listener && (matchListenerOnly || (entry.filter == filter && entry.handback == handback))) { + listenerFound = true; + entryIterator.remove(); + if (!matchListenerOnly) + break; + } + } + + if (!listenerFound) + throw new ListenerNotFoundException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.LISTENER_NOT_FOUND, name)); + + List newServerFilters = null; + for (NotificationListenerEntry entry : entries) { + if (entry.filter == null || !converter.isSupportedNotificationFilter(entry.filter)) { + newServerFilters = null; + break; + } else { + if (newServerFilters == null) + newServerFilters = new ArrayList(); + newServerFilters.add(entry.filter); + } + } + + final boolean serverFiltersUpdated; + if ((serverFilters != null && !serverFilters.equals(newServerFilters)) || + (serverFilters == null && newServerFilters != null)) { + serverFiltersUpdated = true; + serverFilters = newServerFilters; + } else { + serverFiltersUpdated = false; + } + + if (isEmpty()) { + deleteNotificationRegistration(); + } else if (serverFiltersUpdated) { + updateNotificationRegistration(); + } + } + + private NotificationFilter[] getServerFilters() { + if (serverFilters == null) + return null; + NotificationFilter[] serverFilterArray = new NotificationFilter[serverFilters.size()]; + return serverFilters.toArray(serverFilterArray); + } + + private URL getRegistrationURL() throws IOException { + return registrationURL.getURL(); + } + + boolean isEmpty() { + return entries.isEmpty(); + } + + synchronized void handleNotification(Notification notification) { + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), "handleNotification", "[" + RESTClientMessagesUtil.getObjID(this) + + " | Notification: " + notification); + } + + for (NotificationListenerEntry entry : entries) + entry.handleNotification(notification); + } + + synchronized void createNotificationRegistration() throws InstanceNotFoundException, IOException { + final String sourceMethod = "createNotificationRegistration"; + + URL registrationsURL = null; + HttpsURLConnection connection = null; + try { + // Get URL for creating/updating NotificationRegistrations + registrationsURL = getRegistrationsURL().getURL(); + + // Get connection to server + connection = serverConnection.getConnection(registrationsURL, HttpMethod.POST, true, listenerKey.getRoutingInformation()); + + // Create NotificationRegistration object + NotificationRegistration nr = new NotificationRegistration(); + nr.objectName = listenerKey.getName(); + nr.filters = getServerFilters(); + + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), sourceMethod, RESTClientMessagesUtil.getObjID(this)); + } + + // Write NotificationRegsitration JSON to connection output stream + OutputStream output = connection.getOutputStream(); + converter.writeNotificationRegistration(output, nr); + output.flush(); + output.close(); + } catch (ConnectException ce) { + serverConnection.recoverConnection(ce); + // Server is down; not a client bug + throw ce; + } catch (IOException io) { + throw serverConnection.getRequestErrorException(sourceMethod, io, registrationsURL); + } + + // Check response code from server + int responseCode = 0; + try { + responseCode = connection.getResponseCode(); + } catch (ConnectException ce) { + serverConnection.recoverConnection(ce); + // Server is down; not a client bug + throw ce; + } + + switch (responseCode) { + case HttpURLConnection.HTTP_OK: + try { + // Process and return server response, which should be a URL + String url = converter.readString(connection.getInputStream()); + registrationURL = new DynamicURL(serverConnection.connector, url); + break; + } catch (Exception e) { + throw serverConnection.getResponseErrorException(sourceMethod, e, registrationsURL); + } + case HttpURLConnection.HTTP_GONE: + case HttpURLConnection.HTTP_NOT_FOUND: + IOException ioe = serverConnection.getResponseCodeErrorException(sourceMethod, responseCode, connection); + serverConnection.recoverConnection(ioe); + throw ioe; + case HttpURLConnection.HTTP_BAD_REQUEST: + case HttpURLConnection.HTTP_INTERNAL_ERROR: + try { + // Server response should be a serialized Throwable + throw serverConnection.getServerThrowable(sourceMethod, connection); + } catch (RuntimeOperationsException roe) { + throw roe; + } catch (InstanceNotFoundException inf) { + throw inf; + } catch (IOException io) { + throw io; + } catch (ClassNotFoundException cnf) { + throw new IOException(cnf); + } catch (Throwable t) { + throw new IOException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.UNEXPECTED_SERVER_THROWABLE), t); + } + case HttpURLConnection.HTTP_UNAUTHORIZED: + case HttpURLConnection.HTTP_FORBIDDEN: + throw serverConnection.getBadCredentialsException(responseCode, connection); + default: + throw serverConnection.getResponseCodeErrorException(sourceMethod, responseCode, connection); + } + + } + + private void updateNotificationRegistration() throws InstanceNotFoundException, IOException { + final String sourceMethod = "updateNotificationRegistration"; + + URL registrationURL = null; + HttpsURLConnection connection = null; + try { + // Get URL for this NotificationRegistration + registrationURL = getRegistrationURL(); + + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), sourceMethod, RESTClientMessagesUtil.getObjID(this)); + } + + // Get connection to server + connection = serverConnection.getConnection(registrationURL, HttpMethod.PUT, true, listenerKey.getRoutingInformation()); + + // Write array of NotificationFilters to JSON to connection output stream + OutputStream output = connection.getOutputStream(); + converter.writeNotificationFilters(output, getServerFilters()); + output.flush(); + output.close(); + } catch (ConnectException ce) { + serverConnection.recoverConnection(ce); + // Server is down; not a client bug + throw ce; + } catch (IOException io) { + throw serverConnection.getRequestErrorException(sourceMethod, io, registrationURL); + } + + // Check response code from server + int responseCode = 0; + try { + responseCode = connection.getResponseCode(); + } catch (ConnectException ce) { + serverConnection.recoverConnection(ce); + // Server is down; not a client bug + throw ce; + } + + if (logger.isLoggable(Level.FINEST)) { + logger.logp(Level.FINEST, logger.getName(), sourceMethod, "response code: " + responseCode); + } + switch (responseCode) { + case HttpURLConnection.HTTP_NO_CONTENT: + // Nothing to do; no response expected + break; + case HttpURLConnection.HTTP_GONE: + case HttpURLConnection.HTTP_NOT_FOUND: + IOException ioe = serverConnection.getResponseCodeErrorException(sourceMethod, responseCode, connection); + serverConnection.recoverConnection(ioe); + throw ioe; + case HttpURLConnection.HTTP_BAD_REQUEST: + case HttpURLConnection.HTTP_INTERNAL_ERROR: + try { + // Server response should be a serialized Throwable + throw converter.readThrowable(connection.getErrorStream()); + } catch (InstanceNotFoundException inf) { + throw inf; + } catch (IOException io) { + throw io; + } catch (ClassNotFoundException cnf) { + throw new IOException(cnf); + } catch (Throwable t) { + throw new IOException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.UNEXPECTED_SERVER_THROWABLE), t); + } + case HttpURLConnection.HTTP_UNAUTHORIZED: + case HttpURLConnection.HTTP_FORBIDDEN: + throw serverConnection.getBadCredentialsException(responseCode, connection); + default: + throw serverConnection.getResponseCodeErrorException(sourceMethod, responseCode, connection); + } + } + + private void deleteNotificationRegistration() throws InstanceNotFoundException, ListenerNotFoundException, IOException { + final String sourceMethod = "deleteNotificationRegistration"; + + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), sourceMethod, RESTClientMessagesUtil.getObjID(this)); + } + + URL registrationURL = null; + HttpsURLConnection connection = null; + try { + // Get URL for NotificationRegistration + registrationURL = getRegistrationURL(); + + // Get connection to server + connection = serverConnection.getConnection(registrationURL, HttpMethod.DELETE, true, listenerKey.getRoutingInformation()); + } catch (IOException io) { + throw serverConnection.getRequestErrorException(sourceMethod, io, registrationURL); + } + + // Check response code from server + int responseCode = 0; + try { + responseCode = connection.getResponseCode(); + } catch (ConnectException ce) { + serverConnection.recoverConnection(ce); + // Server is down; not a client bug + throw ce; + } + + if (logger.isLoggable(Level.FINEST)) { + logger.logp(Level.FINEST, logger.getName(), sourceMethod, "Response code: " + responseCode); + } + + switch (responseCode) { + case HttpURLConnection.HTTP_NO_CONTENT: + // Nothing to do; no response expected + break; + case HttpURLConnection.HTTP_GONE: + case HttpURLConnection.HTTP_NOT_FOUND: + IOException ioe = serverConnection.getResponseCodeErrorException(sourceMethod, responseCode, connection); + serverConnection.recoverConnection(ioe); + throw ioe; + case HttpURLConnection.HTTP_BAD_REQUEST: + case HttpURLConnection.HTTP_INTERNAL_ERROR: + try { + // Server response should be a serialized Throwable + throw converter.readThrowable(connection.getInputStream()); + } catch (InstanceNotFoundException inf) { + throw inf; + } catch (ListenerNotFoundException lnf) { + throw lnf; + } catch (IOException io) { + throw io; + } catch (Throwable t) { + throw new IOException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.UNEXPECTED_SERVER_THROWABLE), t); + } + case HttpURLConnection.HTTP_UNAUTHORIZED: + case HttpURLConnection.HTTP_FORBIDDEN: + throw serverConnection.getBadCredentialsException(responseCode, connection); + default: + throw serverConnection.getResponseCodeErrorException(sourceMethod, responseCode, connection); + } + } + + } + + /** + * @return the registrationMap + */ + public Map getRegistrationMap() { + return registrationMap; + } +} \ No newline at end of file diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/internal/ObjectIdentityCache.java b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/internal/ObjectIdentityCache.java new file mode 100755 index 00000000000..1c0404c6c9f --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/internal/ObjectIdentityCache.java @@ -0,0 +1,78 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jmx.connector.client.rest.internal; + +import java.lang.ref.ReferenceQueue; +import java.lang.ref.WeakReference; +import java.util.HashMap; +import java.util.Map; + +/** + * + */ +public class ObjectIdentityCache { + + private final Map identityMap = new HashMap(); + private final ReferenceQueue referenceQueue = new ReferenceQueue(); + private int nextIdentity = Integer.MIN_VALUE + 1; + + int getObjectIdentity(Object o) { + // Clean up cleared references + ObjectReference clearedRef = (ObjectReference) referenceQueue.poll(); + while (clearedRef != null) { + identityMap.remove(clearedRef); + clearedRef = (ObjectReference) referenceQueue.poll(); + } + + if (o == null) + return Integer.MIN_VALUE; + + ObjectReference ref = new ObjectReference(o, referenceQueue); + if (identityMap.containsKey(ref)) { + return identityMap.get(ref); + } else { + if (nextIdentity == Integer.MAX_VALUE) + throw new IllegalStateException(); + final int identity = nextIdentity++; + identityMap.put(ref, identity); + return identity; + } + } + + private static class ObjectReference extends WeakReference { + private final int hashCode; + + ObjectReference(Object referent, ReferenceQueue queue) { + super(referent, queue); + hashCode = referent.hashCode(); + } + + /** {@inheritDoc} */ + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } else if (o instanceof ObjectReference) { + ObjectReference other = (ObjectReference) o; + return other.get() == get(); + } else { + return false; + } + } + + /** {@inheritDoc} */ + @Override + public int hashCode() { + return hashCode; + } + } +} diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/internal/RESTMBeanServerConnection.java b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/internal/RESTMBeanServerConnection.java new file mode 100755 index 00000000000..a27e79f483a --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/internal/RESTMBeanServerConnection.java @@ -0,0 +1,2465 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012, 2017 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jmx.connector.client.rest.internal; + +import java.io.IOException; +import java.io.OutputStream; +import java.net.ConnectException; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLEncoder; +import java.nio.channels.ClosedByInterruptException; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.management.Attribute; +import javax.management.AttributeList; +import javax.management.AttributeNotFoundException; +import javax.management.InstanceAlreadyExistsException; +import javax.management.InstanceNotFoundException; +import javax.management.IntrospectionException; +import javax.management.InvalidAttributeValueException; +import javax.management.ListenerNotFoundException; +import javax.management.MBeanException; +import javax.management.MBeanInfo; +import javax.management.MBeanRegistrationException; +import javax.management.MBeanServerConnection; +import javax.management.NotCompliantMBeanException; +import javax.management.Notification; +import javax.management.NotificationFilter; +import javax.management.NotificationListener; +import javax.management.ObjectInstance; +import javax.management.ObjectName; +import javax.management.QueryExp; +import javax.management.ReflectionException; +import javax.management.RuntimeMBeanException; +import javax.management.RuntimeOperationsException; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLSession; + +import com.ibm.ws.jmx.connector.client.rest.ClientProvider; +import com.ibm.ws.jmx.connector.client.rest.internal.ClientConstants.HttpMethod; +import com.ibm.ws.jmx.connector.client.rest.internal.NotificationRegistry.ClientNotificationRegistration; +import com.ibm.ws.jmx.connector.client.rest.internal.resources.RESTClientMessagesUtil; +import com.ibm.ws.jmx.connector.converter.JSONConverter; +import com.ibm.ws.jmx.connector.converter.NotificationRecord; +import com.ibm.ws.jmx.connector.datatypes.CreateMBean; +import com.ibm.ws.jmx.connector.datatypes.Invocation; +import com.ibm.ws.jmx.connector.datatypes.JMXServerInfo; +import com.ibm.ws.jmx.connector.datatypes.MBeanInfoWrapper; +import com.ibm.ws.jmx.connector.datatypes.MBeanQuery; +import com.ibm.ws.jmx.connector.datatypes.ObjectInstanceWrapper; + +/** + * This class is implemented such that it should be thread-safe. + */ +class RESTMBeanServerConnection implements MBeanServerConnection { + + private static final Logger logger = Logger.getLogger(RESTMBeanServerConnection.class.getName()); + + protected static final String CLIENT_VERSION = "IBM_JMX_REST_client_v5"; + + public enum PollingMode { + FAILOVER, NOTIFICATION + }; + + private static final long NANOS_IN_A_MILLISECOND = 1000000L; + + private final AtomicBoolean isRecoveringConnection = new AtomicBoolean(); + + private ServerPollingThread serverPollingThread; + + protected final Connector connector; + private volatile boolean disconnected = false; + protected int serverVersion; + private final DynamicURL rootURL; + private DynamicURL mbeansURL, createMBeanURL, instanceOfURL, mbeanCountURL, defaultDomainURL, domainsURL, notificationsURL, fileTransferURL; + private final ConcurrentMap mbeanInfoURLMap; + private final ConcurrentMap mbeanAttributesURLMap; + private final ConcurrentMap> mbeanAttributeURLsMap; + private final ConcurrentMap> mbeanOperationURLsMap; + private final FileTransferClient fileTransferClient; + + private NotificationRegistry notificationRegistry; + + protected final HostnameVerifier hostnameVerificationDisabler; + + protected Map mapRouting = null; + + static { + AccessController.doPrivileged(new PrivilegedAction() { + @Override + public Void run() { + String oldValue = System.getProperty("sun.net.http.retryPost"); + + if (oldValue != null) { + if (logger.isLoggable(Level.INFO)) { + logger.logp(Level.INFO, logger.getName(), "StaticBlock[1]", "Value of retry post was already set: " + oldValue); + } + } else { + //Set the value on the client-side to prevent the JDK from retrying invocations. + System.setProperty("sun.net.http.retryPost", "false"); + } + + return null; + } + }); + } + + RESTMBeanServerConnection(Connector connector) throws IOException { + this.connector = connector; + + rootURL = new DynamicURL(connector, connector.getServiceURL().getURLPath()); + + // Set up HostnameVerifier to allow all host names if hostname verification is disabled + if (connector.isHostnameVerificationDisabled()) { + hostnameVerificationDisabler = new HostnameVerifier() { + + @Override + public boolean verify(String hostname, SSLSession session) { + return true; + } + }; + } else { + hostnameVerificationDisabler = null; + } + + //First we need set our initial endpoint + findInitialEndpoint(); + + // Load JMX server info to verify server is reachable + try { + loadJMXServerInfo(); + } catch (IOException e) { + //If we got an IOException for the server being down, we will have tried a recovery + //and then either we have a valid endpoint or the connector will have been automatically + //disconnected. So, if the connector is still connected, we can try 1 more time to connect + if (isConnected()) { + loadJMXServerInfo(); + } else { + throw e; + } + } + + mbeanInfoURLMap = new ConcurrentHashMap(); + mbeanAttributesURLMap = new ConcurrentHashMap(); + mbeanAttributeURLsMap = new ConcurrentHashMap>(); + mbeanOperationURLsMap = new ConcurrentHashMap>(); + fileTransferClient = new FileTransferClient(this); + + //Unless the user asked for fail interval polling to be off (by specifying a negative value), we start the thread. + if (connector.getServerFailoverInterval() >= 0) { + setPollingMode(PollingMode.FAILOVER); + } + + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), "constructor", "Initiated connector " + RESTClientMessagesUtil.getObjID(this) + " within connection: " + + connector.getConnectionId()); + } + if (connector.logFailovers()) { + String connectMsg = RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.MEMBER_CONNECT, connector.getCurrentEndpoint()); + logger.logp(Level.INFO, logger.getName(), "constructor", connectMsg); + } + } + + //Lazy initialization of NotificationRegistry + private NotificationRegistry getNotificationRegistry() throws IOException { + if (notificationRegistry == null) { + notificationRegistry = new NotificationRegistry(this); + } + return notificationRegistry; + } + + protected void setPollingMode(PollingMode mode) { + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), "setPollingMode", "Entering setPollingMode with new mode " + mode.toString()); + } + + if (serverPollingThread != null) { + serverPollingThread.changeMode(mode); + } else { + serverPollingThread = new ServerPollingThread(mode); + serverPollingThread.start(); + } + } + + protected void discardNotificationRegistry() { + if (connector.getServerFailoverInterval() >= 0) { + setPollingMode(PollingMode.FAILOVER); + } else { + //if the user doesn't want to go into FAILOVER mode, then we're done + //with this thread for now + closePollingThread(); + } + notificationRegistry.close(); + notificationRegistry = null; + } + + private void loadJMXServerInfo() throws IOException { + final String sourceMethod = "loadJMXServerInfo"; + checkConnection(); + + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), sourceMethod, "Loading server info for endpoint: " + connector.getCurrentEndpoint()); + } + URL rootURL = null; + HttpsURLConnection connection = null; + try { + // Get JMX server info URL + rootURL = getRootURL(); + + // Get connection to server + connection = getConnection(rootURL, HttpMethod.GET); + } catch (IOException io) { + throw getRequestErrorException(sourceMethod, io, rootURL); + } + + JMXServerInfo jmx = null; + // Check response code from server + int responseCode = 0; + try { + responseCode = connection.getResponseCode(); + } catch (ConnectException ce) { + recoverConnection(ce, true); + // Server is down; not a client bug + throw ce; + } + + switch (responseCode) { + case HttpURLConnection.HTTP_OK: + JSONConverter converter = JSONConverter.getConverter(); + try { + // Process and return server response, which should be a JMXServerInfo + jmx = converter.readJMX(connection.getInputStream()); + break; + } catch (Exception e) { + throw getResponseErrorException(sourceMethod, e, rootURL); + } finally { + JSONConverter.returnConverter(converter); + } + case HttpURLConnection.HTTP_BAD_REQUEST: + case HttpURLConnection.HTTP_INTERNAL_ERROR: + // Server response should be a serialized Throwable + Throwable t = getServerThrowable(sourceMethod, connection); + IOException ioe = t instanceof IOException ? (IOException) t : new IOException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.UNEXPECTED_SERVER_THROWABLE), t); + throw ioe; + case HttpURLConnection.HTTP_UNAUTHORIZED: + case HttpURLConnection.HTTP_FORBIDDEN: + throw getBadCredentialsException(responseCode, connection); + case HttpURLConnection.HTTP_GONE: + case HttpURLConnection.HTTP_NOT_FOUND: + IOException io = getResponseCodeErrorException(sourceMethod, responseCode, connection); + recoverConnection(io, true); + throw io; + default: + throw getResponseCodeErrorException(sourceMethod, responseCode, connection); + } + + serverVersion = jmx.version; + mbeansURL = new DynamicURL(connector, jmx.mbeansURL); + createMBeanURL = new DynamicURL(connector, jmx.createMBeanURL); + instanceOfURL = new DynamicURL(connector, jmx.instanceOfURL); + mbeanCountURL = new DynamicURL(connector, jmx.mbeanCountURL); + defaultDomainURL = new DynamicURL(connector, jmx.defaultDomainURL); + domainsURL = new DynamicURL(connector, jmx.domainsURL); + notificationsURL = new DynamicURL(connector, jmx.notificationsURL); + fileTransferURL = new DynamicURL(connector, jmx.fileTransferURL); + } + + /** {@inheritDoc} */ + @Override + public ObjectInstance createMBean(String className, + ObjectName name) throws ReflectionException, InstanceAlreadyExistsException, MBeanRegistrationException, MBeanException, NotCompliantMBeanException, IOException { + try { + return createMBean(className, name, null, null, null, false, false); + } catch (InstanceNotFoundException inf) { + throw new IOException(inf); // Should never happen + } + } + + /** {@inheritDoc} */ + @Override + public ObjectInstance createMBean(String className, ObjectName name, + ObjectName loaderName) throws ReflectionException, InstanceAlreadyExistsException, MBeanRegistrationException, MBeanException, NotCompliantMBeanException, InstanceNotFoundException, IOException { + return createMBean(className, name, loaderName, null, null, true, false); + } + + /** {@inheritDoc} */ + @Override + public ObjectInstance createMBean(String className, ObjectName name, Object[] params, + String[] signature) throws ReflectionException, InstanceAlreadyExistsException, MBeanRegistrationException, MBeanException, NotCompliantMBeanException, IOException { + try { + return createMBean(className, name, null, params, signature, false, true); + } catch (InstanceNotFoundException inf) { + throw new IOException(inf); // Should never happen + } + } + + /** {@inheritDoc} */ + @Override + public ObjectInstance createMBean(String className, ObjectName name, ObjectName loaderName, Object[] params, + String[] signature) throws ReflectionException, InstanceAlreadyExistsException, MBeanRegistrationException, MBeanException, NotCompliantMBeanException, InstanceNotFoundException, IOException { + return createMBean(className, name, loaderName, params, signature, true, true); + } + + private ObjectInstance createMBean(String className, ObjectName name, ObjectName loaderName, Object[] params, String[] signature, boolean useLoader, + boolean useSignature) throws ReflectionException, InstanceAlreadyExistsException, MBeanRegistrationException, MBeanException, NotCompliantMBeanException, InstanceNotFoundException, IOException { + final String sourceMethod = "createMBean"; + checkConnection(); + if (className == null) + throw new RuntimeOperationsException(new IllegalArgumentException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.CLASS_NAME_NULL))); + else if (name == null) + throw new RuntimeOperationsException(new IllegalArgumentException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.OBJECT_NAME_NULL))); + else if (name.isPattern()) + throw new RuntimeOperationsException(new IllegalArgumentException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.OBJECT_NAME_PATTERN, name))); + + URL createURL = null; + HttpsURLConnection connection = null; + JSONConverter converter = JSONConverter.getConverter(); + try { + // Get URL for creating MBeans + createURL = getCreateMBeanURL(); + + // Get connection to server + connection = getConnection(createURL, HttpMethod.POST); + + // Create CreateMBean object + CreateMBean createMBean = new CreateMBean(); + createMBean.className = className; + createMBean.objectName = name; + createMBean.loaderName = loaderName; + createMBean.params = params; + createMBean.signature = signature; + createMBean.useLoader = useLoader; + createMBean.useSignature = useSignature; + + // Write CreateMBean JSON to connection output stream + OutputStream output = connection.getOutputStream(); + converter.writeCreateMBean(output, createMBean); + output.flush(); + output.close(); + } catch (ConnectException ce) { + recoverConnection(ce); + // Server is down; not a client bug + throw ce; + } catch (IOException io) { + throw getRequestErrorException(sourceMethod, io, createURL); + } finally { + JSONConverter.returnConverter(converter); + } + + // Check response code from server + int responseCode = 0; + try { + responseCode = connection.getResponseCode(); + } catch (ConnectException ce) { + recoverConnection(ce); + // Server is down; not a client bug + throw ce; + } + switch (responseCode) { + case HttpURLConnection.HTTP_OK: + converter = JSONConverter.getConverter(); + try { + // Process and return server response, which should be an ObjectInstanceWrapper + ObjectInstanceWrapper wrapper = converter.readObjectInstance(connection.getInputStream()); + mbeanInfoURLMap.put(wrapper.objectInstance.getObjectName(), new DynamicURL(connector, wrapper.mbeanInfoURL)); + return wrapper.objectInstance; + } catch (Exception e) { + throw getResponseErrorException(sourceMethod, e, createURL); + } finally { + JSONConverter.returnConverter(converter); + } + case HttpURLConnection.HTTP_BAD_REQUEST: + case HttpURLConnection.HTTP_INTERNAL_ERROR: + try { + // Server response should be a serialized Throwable + throw getServerThrowable(sourceMethod, connection); + } catch (RuntimeOperationsException roe) { + throw roe; + } catch (ReflectionException re) { + throw re; + } catch (InstanceAlreadyExistsException iae) { + throw iae; + } catch (MBeanRegistrationException mbr) { + throw mbr; + } catch (MBeanException me) { + throw me; + } catch (RuntimeMBeanException rme) { + throw rme; + } catch (NotCompliantMBeanException ncm) { + throw ncm; + } catch (InstanceNotFoundException inf) { + throw inf; + } catch (IOException io) { + throw io; + } catch (Throwable t) { + throw new IOException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.UNEXPECTED_SERVER_THROWABLE), t); + } + case HttpURLConnection.HTTP_UNAUTHORIZED: + case HttpURLConnection.HTTP_FORBIDDEN: + throw getBadCredentialsException(responseCode, connection); + case HttpURLConnection.HTTP_GONE: + case HttpURLConnection.HTTP_NOT_FOUND: + IOException ioe = getResponseCodeErrorException(sourceMethod, responseCode, connection); + recoverConnection(ioe); + throw ioe; + default: + throw getResponseCodeErrorException(sourceMethod, responseCode, connection); + } + } + + /** {@inheritDoc} */ + @Override + public void unregisterMBean(ObjectName name) throws InstanceNotFoundException, MBeanRegistrationException, IOException { + final String sourceMethod = "unregisterMBean"; + checkConnection(); + if (name == null) + throw new RuntimeOperationsException(new IllegalArgumentException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.OBJECT_NAME_NULL))); + else if (name.isPattern()) + throw new InstanceNotFoundException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.OBJECT_NAME_PATTERN, name)); + + URL mbeanURL = null; + HttpsURLConnection connection = null; + try { + // Get URL for MBean + mbeanURL = getMBeanURL(name); + + // Get connection to server + connection = getConnection(mbeanURL, HttpMethod.DELETE); + } catch (IOException io) { + throw getRequestErrorException(sourceMethod, io, mbeanURL); + } + + // Check response code from server + int responseCode = 0; + try { + responseCode = connection.getResponseCode(); + } catch (ConnectException ce) { + recoverConnection(ce); + // Server is down; not a client bug + throw ce; + } + + switch (responseCode) { + case HttpURLConnection.HTTP_NO_CONTENT: + // Clean up cached URLs + purgeMBeanURLs(name); + return; + case HttpURLConnection.HTTP_BAD_REQUEST: + case HttpURLConnection.HTTP_INTERNAL_ERROR: + try { + // Server response should be a serialized Throwable + throw getServerThrowable(sourceMethod, connection); + } catch (MBeanRegistrationException mbr) { + throw mbr; + } catch (InstanceNotFoundException inf) { + throw inf; + } catch (IOException io) { + throw io; + } catch (Throwable t) { + throw new IOException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.UNEXPECTED_SERVER_THROWABLE), t); + } + case HttpURLConnection.HTTP_UNAUTHORIZED: + case HttpURLConnection.HTTP_FORBIDDEN: + throw getBadCredentialsException(responseCode, connection); + case HttpURLConnection.HTTP_GONE: + case HttpURLConnection.HTTP_NOT_FOUND: + IOException ioe = getResponseCodeErrorException(sourceMethod, responseCode, connection); + recoverConnection(ioe); + throw ioe; + default: + throw getResponseCodeErrorException(sourceMethod, responseCode, connection); + } + } + + /** {@inheritDoc} */ + @Override + public ObjectInstance getObjectInstance(ObjectName name) throws InstanceNotFoundException, IOException { + checkConnection(); + if (name.isPattern()) + throw new InstanceNotFoundException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.OBJECT_NAME_PATTERN, name)); + + @SuppressWarnings("unchecked") + Set results = queryMBeans(name, null, null, true); + + if (results.size() == 1) + return results.toArray(new ObjectInstance[1])[0]; + else + throw new InstanceNotFoundException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.INSTANCE_NOT_FOUND, name)); + } + + @SuppressWarnings("unchecked") + private Set queryMBeans(ObjectName name, QueryExp query, String className, boolean objectInstance) throws IOException { + final String sourceMethod = "queryMBeans"; + final boolean usePOST = query != null; + + URL baseMBeansURL = null; + URL mbeansURL = null; + HttpsURLConnection connection = null; + JSONConverter converter = JSONConverter.getConverter(); + try { + // Get URL for MBeans + baseMBeansURL = getMBeansURL(); + mbeansURL = usePOST ? baseMBeansURL : getMBeansURL(name, className); + + // Get connection to server + connection = getConnection(mbeansURL, usePOST ? HttpMethod.POST : HttpMethod.GET); + + if (usePOST) { + // Create MBeanQuery object + MBeanQuery mbeanQuery = new MBeanQuery(); + mbeanQuery.objectName = name; + mbeanQuery.queryExp = query; + mbeanQuery.className = className; + + // Write MBeanQuery JSON to connection output stream + OutputStream output = connection.getOutputStream(); + converter.writeMBeanQuery(output, mbeanQuery); + output.flush(); + output.close(); + } + } catch (ConnectException ce) { + recoverConnection(ce); + // Server is down; not a client bug + throw ce; + } catch (IOException io) { + throw getRequestErrorException(sourceMethod, io, mbeansURL); + } finally { + JSONConverter.returnConverter(converter); + } + + // Check response code from server + int responseCode = 0; + try { + responseCode = connection.getResponseCode(); + } catch (ConnectException ce) { + recoverConnection(ce); + // Server is down; not a client bug + throw ce; + } + + switch (responseCode) { + case HttpURLConnection.HTTP_OK: + converter = JSONConverter.getConverter(); + try { + // Process and return server response, which should be a Set of ObjectInstanceWrapper + ObjectInstanceWrapper[] wrappers = converter.readObjectInstances(connection.getInputStream()); + Set mbeans = new HashSet(wrappers.length); + Map tempMBeanInfoURLMap = new HashMap(wrappers.length); + for (ObjectInstanceWrapper wrapper : wrappers) { + tempMBeanInfoURLMap.put(wrapper.objectInstance.getObjectName(), wrapper.mbeanInfoURL); + if (objectInstance) + mbeans.add(wrapper.objectInstance); + else + mbeans.add(wrapper.objectInstance.getObjectName()); + } + + processMBeanInfoURLs(tempMBeanInfoURLMap, getMBeansURL().getPath(), name == null && query == null && className == null); + + return mbeans; + } catch (Exception e) { + throw getResponseErrorException(sourceMethod, e, mbeansURL); + } finally { + JSONConverter.returnConverter(converter); + } + case HttpURLConnection.HTTP_BAD_REQUEST: + case HttpURLConnection.HTTP_INTERNAL_ERROR: + Throwable t = getServerThrowable(sourceMethod, connection); + IOException ioe = t instanceof IOException ? (IOException) t : new IOException(RESTClientMessagesUtil.UNEXPECTED_SERVER_THROWABLE, t); + throw ioe; + case HttpURLConnection.HTTP_UNAUTHORIZED: + case HttpURLConnection.HTTP_FORBIDDEN: + throw getBadCredentialsException(responseCode, connection); + case HttpURLConnection.HTTP_GONE: + case HttpURLConnection.HTTP_NOT_FOUND: + IOException io = getResponseCodeErrorException(sourceMethod, responseCode, connection); + recoverConnection(io); + throw io; + default: + throw getResponseCodeErrorException(sourceMethod, responseCode, connection); + } + } + + /** {@inheritDoc} */ + @SuppressWarnings("unchecked") + @Override + public Set queryMBeans(ObjectName name, QueryExp query) throws IOException { + checkConnection(); + return queryMBeans(name, query, null, true); + } + + /** {@inheritDoc} */ + @SuppressWarnings("unchecked") + @Override + public Set queryNames(ObjectName name, QueryExp query) throws IOException { + checkConnection(); + return queryMBeans(name, query, null, false); + } + + /** {@inheritDoc} */ + @Override + public boolean isRegistered(ObjectName name) throws IOException { + checkConnection(); + if (name == null) + throw new RuntimeOperationsException(new IllegalArgumentException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.OBJECT_NAME_NULL))); + else if (name.isPattern()) + return false; + + @SuppressWarnings("unchecked") + Set results = queryMBeans(name, null, null, true); + return results.size() == 1; + } + + /** {@inheritDoc} */ + @Override + public Integer getMBeanCount() throws IOException { + final String sourceMethod = "getMBeanCount"; + checkConnection(); + + URL mbeanCountURL = null; + HttpsURLConnection connection = null; + try { + // Get URL for MBean count + mbeanCountURL = getMBeanCountURL(); + + // Get connection to server + connection = getConnection(mbeanCountURL, HttpMethod.GET); + } catch (IOException io) { + throw getRequestErrorException(sourceMethod, io, mbeanCountURL); + } + + // Check response code from server + int responseCode = 0; + try { + responseCode = connection.getResponseCode(); + } catch (ConnectException ce) { + recoverConnection(ce); + // Server is down; not a client bug + throw ce; + } + + switch (responseCode) { + case HttpURLConnection.HTTP_OK: + JSONConverter converter = JSONConverter.getConverter(); + try { + // Process and return server response + return converter.readInt(connection.getInputStream()); + } catch (Exception e) { + throw getResponseErrorException(sourceMethod, e, mbeanCountURL); + } finally { + JSONConverter.returnConverter(converter); + } + case HttpURLConnection.HTTP_BAD_REQUEST: + case HttpURLConnection.HTTP_INTERNAL_ERROR: + // Server response should be a serialized Throwable + Throwable t = getServerThrowable(sourceMethod, connection); + IOException ioe = t instanceof IOException ? (IOException) t : new IOException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.UNEXPECTED_SERVER_THROWABLE), t); + throw ioe; + case HttpURLConnection.HTTP_UNAUTHORIZED: + case HttpURLConnection.HTTP_FORBIDDEN: + throw getBadCredentialsException(responseCode, connection); + case HttpURLConnection.HTTP_GONE: + case HttpURLConnection.HTTP_NOT_FOUND: + IOException io = getResponseCodeErrorException(sourceMethod, responseCode, connection); + recoverConnection(io); + throw io; + default: + throw getResponseCodeErrorException(sourceMethod, responseCode, connection); + + } + } + + /** {@inheritDoc} */ + @Override + public Object getAttribute(ObjectName name, String attribute) throws MBeanException, AttributeNotFoundException, InstanceNotFoundException, ReflectionException, IOException { + final String sourceMethod = "getAttribute"; + checkConnection(); + if (name == null) + throw new RuntimeOperationsException(new IllegalArgumentException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.OBJECT_NAME_NULL))); + else if (name.isPattern()) + throw new InstanceNotFoundException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.OBJECT_NAME_PATTERN, name)); + else if (attribute == null) + throw new RuntimeOperationsException(new IllegalArgumentException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.ATTRIBUTE_NAME_NULL))); + + URL attributeURL; + + try { + // Get URL for attribute + attributeURL = getAttributeURL(name, attribute); + + } catch (IntrospectionException intro) { + throw getRequestErrorException(sourceMethod, intro); + } catch (IOException io) { + throw getRequestErrorException(sourceMethod, io); + } + + HttpsURLConnection connection; + try { + connection = getConnection(attributeURL, HttpMethod.GET); // Get connection to server + } catch (IOException io) { + throw getRequestErrorException(sourceMethod, io, attributeURL); + } + + // Check response code from server + int responseCode = 0; + try { + responseCode = connection.getResponseCode(); + } catch (ConnectException ce) { + recoverConnection(ce); + // Server is down; not a client bug + throw ce; + } + + switch (responseCode) { + case HttpURLConnection.HTTP_OK: + JSONConverter converter = JSONConverter.getConverter(); + try { + // Process and return server response, which should be a POJO + return converter.readPOJO(connection.getInputStream()); + } catch (ClassNotFoundException cnf) { + // Not a REST connector bug per se; not need to log this case + throw new IOException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.SERVER_RESULT_EXCEPTION), cnf); + } catch (Exception e) { + throw getResponseErrorException(sourceMethod, e, attributeURL); + } finally { + JSONConverter.returnConverter(converter); + } + case HttpURLConnection.HTTP_BAD_REQUEST: + case HttpURLConnection.HTTP_INTERNAL_ERROR: + try { + // Server response should be a serialized Throwable + throw getServerThrowable(sourceMethod, connection); + } catch (MBeanException me) { + throw me; + } catch (AttributeNotFoundException anf) { + throw anf; + } catch (InstanceNotFoundException inf) { + throw inf; + } catch (ReflectionException re) { + throw re; + } catch (IOException io) { + throw io; + } catch (Throwable t) { + throw new IOException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.UNEXPECTED_SERVER_THROWABLE), t); + } + case HttpURLConnection.HTTP_UNAUTHORIZED: + case HttpURLConnection.HTTP_FORBIDDEN: + throw getBadCredentialsException(responseCode, connection); + case HttpURLConnection.HTTP_GONE: + case HttpURLConnection.HTTP_NOT_FOUND: + IOException ioe = getResponseCodeErrorException(sourceMethod, responseCode, connection); + recoverConnection(ioe); + throw ioe; + default: + throw getResponseCodeErrorException(sourceMethod, responseCode, connection); + } + } + + /** {@inheritDoc} */ + @Override + public AttributeList getAttributes(ObjectName name, String[] attributes) throws InstanceNotFoundException, ReflectionException, IOException { + final String sourceMethod = "getAttributes"; + checkConnection(); + if (name == null) + throw new RuntimeOperationsException(new IllegalArgumentException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.OBJECT_NAME_NULL))); + else if (name.isPattern()) + throw new InstanceNotFoundException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.OBJECT_NAME_PATTERN, name)); + else if (attributes == null) + throw new RuntimeOperationsException(new IllegalArgumentException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.ATTRIBUTE_NAMES_NULL))); + + URL attributesURL; + try { + // Get URL for attributes + attributesURL = getAttributesURL(name, attributes); + } catch (IntrospectionException intro) { + throw getRequestErrorException(sourceMethod, intro); + } catch (IOException io) { + throw getRequestErrorException(sourceMethod, io); + } + + HttpsURLConnection connection; + + try { + // Get connection to server + connection = getConnection(attributesURL, HttpMethod.GET); + } catch (IOException io) { + throw getRequestErrorException(sourceMethod, io, attributesURL); + } + + // Check response code from server + int responseCode = 0; + try { + responseCode = connection.getResponseCode(); + } catch (ConnectException ce) { + recoverConnection(ce); + // Server is down; not a client bug + throw ce; + } + + switch (responseCode) { + case HttpURLConnection.HTTP_OK: + JSONConverter converter = JSONConverter.getConverter(); + try { + // Process and return server response, which should be an AttributeList + return converter.readAttributeList(connection.getInputStream()); + } catch (ClassNotFoundException cnf) { + // Not a REST connector bug per se; not need to log this case + throw new IOException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.SERVER_RESULT_EXCEPTION), cnf); + } catch (Exception e) { + throw getResponseErrorException(sourceMethod, e, attributesURL); + } finally { + JSONConverter.returnConverter(converter); + } + case HttpURLConnection.HTTP_BAD_REQUEST: + case HttpURLConnection.HTTP_INTERNAL_ERROR: + try { + // Server response should be a serialized Throwable + throw getServerThrowable(sourceMethod, connection); + } catch (InstanceNotFoundException inf) { + throw inf; + } catch (ReflectionException re) { + throw re; + } catch (IOException io) { + throw io; + } catch (Throwable t) { + throw new IOException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.UNEXPECTED_SERVER_THROWABLE), t); + } + case HttpURLConnection.HTTP_UNAUTHORIZED: + case HttpURLConnection.HTTP_FORBIDDEN: + throw getBadCredentialsException(responseCode, connection); + case HttpURLConnection.HTTP_GONE: + case HttpURLConnection.HTTP_NOT_FOUND: + IOException ioe = getResponseCodeErrorException(sourceMethod, responseCode, connection); + recoverConnection(ioe); + throw ioe; + default: + throw getResponseCodeErrorException(sourceMethod, responseCode, connection); + } + } + + /** {@inheritDoc} */ + @Override + public void setAttribute(ObjectName name, + Attribute attribute) throws InstanceNotFoundException, AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException, IOException { + final String sourceMethod = "setAttribute"; + checkConnection(); + if (name == null) + throw new RuntimeOperationsException(new IllegalArgumentException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.OBJECT_NAME_NULL))); + else if (name.isPattern()) + throw new InstanceNotFoundException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.OBJECT_NAME_PATTERN, name)); + else if (attribute == null) + throw new RuntimeOperationsException(new IllegalArgumentException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.ATTRIBUTE_NULL))); + + URL attributeURL; + HttpsURLConnection connection; + JSONConverter converter = JSONConverter.getConverter(); + try { + // Get URL for attribute + attributeURL = getAttributeURL(name, attribute.getName()); + } catch (ConnectException ce) { + // Server is down; not a client bug + throw ce; + } catch (IntrospectionException intro) { + getRequestErrorException(sourceMethod, intro); + throw new IOException(intro); + } catch (IOException io) { + throw getRequestErrorException(sourceMethod, io); + } finally { + JSONConverter.returnConverter(converter); + } + + try { + + // Get connection to server + connection = getConnection(attributeURL, HttpMethod.PUT); + } catch (IOException io) { + throw getRequestErrorException(sourceMethod, io, attributeURL); + } finally { + JSONConverter.returnConverter(converter); + } + + try { + // Write Invocation JSON to connection output stream + OutputStream output = connection.getOutputStream(); + converter.writePOJO(output, attribute.getValue()); + output.flush(); + output.close(); + } catch (ConnectException ce) { + recoverConnection(ce); + // Server is down; not a client bug + throw ce; + } catch (IOException io) { + throw getRequestErrorException(sourceMethod, io, attributeURL); + } finally { + JSONConverter.returnConverter(converter); + } + + // Check response code from server + int responseCode = 0; + try { + responseCode = connection.getResponseCode(); + } catch (ConnectException ce) { + recoverConnection(ce); + // Server is down; not a client bug + throw ce; + } + switch (responseCode) { + case HttpURLConnection.HTTP_NO_CONTENT: + // No content expected + return; + case HttpURLConnection.HTTP_BAD_REQUEST: + case HttpURLConnection.HTTP_INTERNAL_ERROR: + try { + // Server response should be a serialized Throwable + throw getServerThrowable(sourceMethod, connection); + } catch (MBeanException me) { + throw me; + } catch (RuntimeMBeanException rme) { + throw rme; + } catch (AttributeNotFoundException anf) { + throw anf; + } catch (InstanceNotFoundException inf) { + throw inf; + } catch (InvalidAttributeValueException iav) { + throw iav; + } catch (ReflectionException re) { + throw re; + } catch (IOException io) { + throw io; + } catch (Throwable t) { + throw new IOException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.UNEXPECTED_SERVER_THROWABLE), t); + } + case HttpURLConnection.HTTP_UNAUTHORIZED: + case HttpURLConnection.HTTP_FORBIDDEN: + throw getBadCredentialsException(responseCode, connection); + case HttpURLConnection.HTTP_GONE: + case HttpURLConnection.HTTP_NOT_FOUND: + IOException ioe = getResponseCodeErrorException(sourceMethod, responseCode, connection); + recoverConnection(ioe); + throw ioe; + default: + throw getResponseCodeErrorException(sourceMethod, responseCode, connection); + } + + } + + /** {@inheritDoc} */ + @Override + public AttributeList setAttributes(ObjectName name, AttributeList attributes) throws InstanceNotFoundException, ReflectionException, IOException { + final String sourceMethod = "setAttributes"; + checkConnection(); + if (name == null) + throw new RuntimeOperationsException(new IllegalArgumentException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.OBJECT_NAME_NULL))); + else if (name.isPattern()) + throw new InstanceNotFoundException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.OBJECT_NAME_PATTERN, name)); + else if (attributes == null) + throw new RuntimeOperationsException(new IllegalArgumentException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.ATTRIBUTE_LIST_NULL))); + + URL attributesURL; + HttpsURLConnection connection; + JSONConverter converter = JSONConverter.getConverter(); + try { + // Get URL for attributes + attributesURL = getAttributesURL(name); + } catch (ConnectException ce) { + // Server is down; not a client bug + throw ce; + } catch (IntrospectionException intro) { + throw getRequestErrorException(sourceMethod, intro); + } catch (IOException io) { + throw getRequestErrorException(sourceMethod, io); + } finally { + JSONConverter.returnConverter(converter); + } + + try { + + // Get connection to server + connection = getConnection(attributesURL, HttpMethod.POST); + } catch (IOException io) { + throw getRequestErrorException(sourceMethod, io, attributesURL); + } finally { + JSONConverter.returnConverter(converter); + } + try { + // Write Invocation JSON to connection output stream + OutputStream output = connection.getOutputStream(); + converter.writeAttributeList(output, attributes); + output.flush(); + output.close(); + } catch (ConnectException ce) { + recoverConnection(ce); + // Server is down; not a client bug + throw ce; + } catch (IOException io) { + throw getRequestErrorException(sourceMethod, io, attributesURL); + } finally { + JSONConverter.returnConverter(converter); + } + + // Check response code from server + int responseCode = 0; + try { + responseCode = connection.getResponseCode(); + } catch (ConnectException ce) { + recoverConnection(ce); + // Server is down; not a client bug + throw ce; + } + + switch (responseCode) { + case HttpURLConnection.HTTP_OK: + converter = JSONConverter.getConverter(); + try { + // Process and return server response, which should be an AttributeList + return converter.readAttributeList(connection.getInputStream()); + } catch (ClassNotFoundException cnf) { + // Not a REST connector bug per se; not need to log this case + throw new IOException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.SERVER_RESULT_EXCEPTION), cnf); + } catch (Exception e) { + throw getResponseErrorException(sourceMethod, e, attributesURL); + } finally { + JSONConverter.returnConverter(converter); + } + case HttpURLConnection.HTTP_BAD_REQUEST: + case HttpURLConnection.HTTP_INTERNAL_ERROR: + try { + // Server response should be a serialized Throwable + throw getServerThrowable(sourceMethod, connection); + } catch (InstanceNotFoundException inf) { + throw inf; + } catch (ReflectionException re) { + throw re; + } catch (IOException io) { + throw io; + } catch (Throwable t) { + throw new IOException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.UNEXPECTED_SERVER_THROWABLE), t); + } + case HttpURLConnection.HTTP_UNAUTHORIZED: + case HttpURLConnection.HTTP_FORBIDDEN: + throw getBadCredentialsException(responseCode, connection); + case HttpURLConnection.HTTP_GONE: + case HttpURLConnection.HTTP_NOT_FOUND: + IOException ioe = getResponseCodeErrorException(sourceMethod, responseCode, connection); + recoverConnection(ioe); + throw ioe; + default: + throw getResponseCodeErrorException(sourceMethod, responseCode, connection); + } + } + + /** {@inheritDoc} */ + @Override + public Object invoke(ObjectName name, String operationName, Object[] params, + String[] signature) throws InstanceNotFoundException, MBeanException, ReflectionException, IOException { + final String sourceMethod = "invoke"; + + try { + //Look for routing MBean + if (ClientProvider.CONNECTION_ROUTING_NAME.equals(name.getKeyProperty("name")) && + ClientProvider.CONNECTION_ROUTING_DOMAIN.equals(name.getDomain())) { + + //Handle server-level routing + if (ClientProvider.CONNECTION_ROUTING_OPERATION_ASSIGN_SERVER.equals(operationName)) { + if (params.length == 3) { + //routing at server level + this.mapRouting = new HashMap(); + this.mapRouting.put(ClientProvider.ROUTING_KEY_HOST_NAME, params[0]); + this.mapRouting.put(ClientProvider.ROUTING_KEY_SERVER_USER_DIR, params[1]); + this.mapRouting.put(ClientProvider.ROUTING_KEY_SERVER_NAME, params[2]); + return Boolean.TRUE; + } + + //Handle host-level routing + } else if (ClientProvider.CONNECTION_ROUTING_OPERATION_ASSIGN_HOST.equals(operationName)) { + if (params.length == 1) { + //routing at host level + this.mapRouting = new HashMap(); + this.mapRouting.put(ClientProvider.ROUTING_KEY_HOST_NAME, params[0]); + return Boolean.TRUE; + } + } + } + + } catch (Exception e) { + throw new MBeanException(e); + } + + checkConnection(); + + //Special handling for file transfer MBean invocations + if (ClientProvider.FILE_TRANSFER_NAME.equals(name.getKeyProperty("name")) && + ClientProvider.FILE_TRANSFER_DOMAIN.equals(name.getDomain())) { + return fileTransferClient.handleOperation(operationName, params); + } + + URL invokeURL = null; + HttpsURLConnection connection = null; + JSONConverter converter = JSONConverter.getConverter(); + try { + // Get URL for invoke operation + invokeURL = getOperationURL(name, operationName); + + // Get connection to server + connection = getConnection(invokeURL, HttpMethod.POST); + + // Create Invocation object + Invocation invocation = new Invocation(); + invocation.params = params; + invocation.signature = signature; + + // Write Invocation JSON to connection output stream + OutputStream output = connection.getOutputStream(); + converter.writeInvocation(output, invocation); + output.flush(); + output.close(); + } catch (ConnectException ce) { + recoverConnection(ce); + // Server is down; not a client bug + throw ce; + } catch (IntrospectionException intro) { + throw getRequestErrorException(sourceMethod, intro, invokeURL); + } catch (IOException io) { + throw getRequestErrorException(sourceMethod, io, invokeURL); + } finally { + JSONConverter.returnConverter(converter); + } + + // Check response code from server + int responseCode = 0; + try { + responseCode = connection.getResponseCode(); + } catch (ConnectException ce) { + recoverConnection(ce); + // Server is down; not a client bug + throw ce; + } + + switch (responseCode) { + case HttpURLConnection.HTTP_OK: + converter = JSONConverter.getConverter(); + try { + // Process and return server response, which should be a POJO + return converter.readPOJO(connection.getInputStream()); + } catch (ClassNotFoundException cnf) { + // Not a REST connector bug per se; not need to log this case + throw new IOException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.SERVER_RESULT_EXCEPTION), cnf); + } catch (Exception e) { + throw getResponseErrorException(sourceMethod, e, invokeURL); + } finally { + JSONConverter.returnConverter(converter); + } + case HttpURLConnection.HTTP_BAD_REQUEST: + case HttpURLConnection.HTTP_INTERNAL_ERROR: + try { + // Server response should be a serialized Throwable + throw getServerThrowable(sourceMethod, connection); + } catch (InstanceNotFoundException inf) { + throw inf; + } catch (RuntimeMBeanException rme) { + throw rme; + } catch (MBeanException me) { + throw me; + } catch (ReflectionException re) { + throw re; + } catch (IOException io) { + throw io; + } catch (Throwable t) { + throw new IOException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.UNEXPECTED_SERVER_THROWABLE), t); + } + case HttpURLConnection.HTTP_UNAUTHORIZED: + case HttpURLConnection.HTTP_FORBIDDEN: + throw getBadCredentialsException(responseCode, connection); + case HttpURLConnection.HTTP_GONE: + case HttpURLConnection.HTTP_NOT_FOUND: + IOException ioe = getResponseCodeErrorException(sourceMethod, responseCode, connection); + recoverConnection(ioe); + throw ioe; + default: + IOException e = getResponseCodeErrorException(sourceMethod, responseCode, connection); + throw e; + } + } + + /** {@inheritDoc} */ + @Override + public String getDefaultDomain() throws IOException { + final String sourceMethod = "getDefaultDomain"; + checkConnection(); + + URL defaultDomainURL = null; + HttpsURLConnection connection = null; + try { + // Get URL for default domain + defaultDomainURL = getDefaultDomainURL(); + + // Get connection to server + connection = getConnection(defaultDomainURL, HttpMethod.GET); + } catch (IOException io) { + throw getRequestErrorException(sourceMethod, io, defaultDomainURL); + } + + // Check response code from server + int responseCode = 0; + try { + responseCode = connection.getResponseCode(); + } catch (ConnectException ce) { + recoverConnection(ce); + // Server is down; not a client bug + throw ce; + } + + switch (responseCode) { + case HttpURLConnection.HTTP_OK: + JSONConverter converter = JSONConverter.getConverter(); + try { + // Process and return server response + return converter.readString(connection.getInputStream()); + } catch (Exception e) { + throw getResponseErrorException(sourceMethod, e, defaultDomainURL); + } finally { + JSONConverter.returnConverter(converter); + } + case HttpURLConnection.HTTP_BAD_REQUEST: + case HttpURLConnection.HTTP_INTERNAL_ERROR: + // Server response should be a serialized Throwable + Throwable t = getServerThrowable(sourceMethod, connection); + IOException ioe = t instanceof IOException ? (IOException) t : new IOException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.UNEXPECTED_SERVER_THROWABLE), t); + throw ioe; + case HttpURLConnection.HTTP_UNAUTHORIZED: + case HttpURLConnection.HTTP_FORBIDDEN: + throw getBadCredentialsException(responseCode, connection); + case HttpURLConnection.HTTP_GONE: + case HttpURLConnection.HTTP_NOT_FOUND: + IOException io = getResponseCodeErrorException(sourceMethod, responseCode, connection); + recoverConnection(io); + throw io; + default: + throw getResponseCodeErrorException(sourceMethod, responseCode, connection); + } + } + + /** {@inheritDoc} */ + @Override + public String[] getDomains() throws IOException { + final String sourceMethod = "getDomains"; + checkConnection(); + + URL domainsURL = null; + HttpsURLConnection connection = null; + try { + // Get URL for domains + domainsURL = getDomainsURL(); + + // Get connection to server + connection = getConnection(domainsURL, HttpMethod.GET); + } catch (IOException io) { + throw getRequestErrorException(sourceMethod, io, domainsURL); + } + + // Check response code from server + int responseCode = 0; + try { + responseCode = connection.getResponseCode(); + } catch (ConnectException ce) { + recoverConnection(ce); + // Server is down; not a client bug + throw ce; + } + + switch (responseCode) { + case HttpURLConnection.HTTP_OK: + JSONConverter converter = JSONConverter.getConverter(); + try { + // Process and return server response + return converter.readStringArray(connection.getInputStream()); + } catch (Exception e) { + throw getResponseErrorException(sourceMethod, e, domainsURL); + } finally { + JSONConverter.returnConverter(converter); + } + case HttpURLConnection.HTTP_BAD_REQUEST: + case HttpURLConnection.HTTP_INTERNAL_ERROR: + // Server response should be a serialized Throwable + Throwable t = getServerThrowable(sourceMethod, connection); + IOException ioe = t instanceof IOException ? (IOException) t : new IOException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.UNEXPECTED_SERVER_THROWABLE), t); + throw ioe; + case HttpURLConnection.HTTP_UNAUTHORIZED: + case HttpURLConnection.HTTP_FORBIDDEN: + throw getBadCredentialsException(responseCode, connection); + case HttpURLConnection.HTTP_GONE: + case HttpURLConnection.HTTP_NOT_FOUND: + IOException io = getResponseCodeErrorException(sourceMethod, responseCode, connection); + recoverConnection(io); + throw io; + default: + throw getResponseCodeErrorException(sourceMethod, responseCode, connection); + } + + } + + /** {@inheritDoc} */ + @Override + public void addNotificationListener(ObjectName name, NotificationListener listener, NotificationFilter filter, Object handback) throws InstanceNotFoundException, IOException { + checkConnection(); + getNotificationRegistry().addNotificationListener(name, listener, filter, handback); + } + + /** {@inheritDoc} */ + @Override + public void addNotificationListener(ObjectName name, ObjectName listener, NotificationFilter filter, Object handback) throws InstanceNotFoundException, IOException { + checkConnection(); + getNotificationRegistry().addNotificationListener(name, listener, filter, handback); + } + + /** {@inheritDoc} */ + @Override + public void removeNotificationListener(ObjectName name, ObjectName listener) throws InstanceNotFoundException, ListenerNotFoundException, IOException { + checkConnection(); + getNotificationRegistry().removeNotificationListener(name, listener); + } + + /** {@inheritDoc} */ + @Override + public void removeNotificationListener(ObjectName name, ObjectName listener, NotificationFilter filter, + Object handback) throws InstanceNotFoundException, ListenerNotFoundException, IOException { + checkConnection(); + getNotificationRegistry().removeNotificationListener(name, listener, filter, handback); + } + + /** {@inheritDoc} */ + @Override + public void removeNotificationListener(ObjectName name, NotificationListener listener) throws InstanceNotFoundException, ListenerNotFoundException, IOException { + checkConnection(); + getNotificationRegistry().removeNotificationListener(name, listener); + } + + /** {@inheritDoc} */ + @Override + public void removeNotificationListener(ObjectName name, NotificationListener listener, NotificationFilter filter, + Object handback) throws InstanceNotFoundException, ListenerNotFoundException, IOException { + checkConnection(); + getNotificationRegistry().removeNotificationListener(name, listener, filter, handback); + } + + /** {@inheritDoc} */ + @Override + public MBeanInfo getMBeanInfo(ObjectName name) throws InstanceNotFoundException, IntrospectionException, ReflectionException, IOException { + final String sourceMethod = "getMBeanInfo"; + checkConnection(); + + URL mbeanURL = null; + HttpsURLConnection connection = null; + try { + // Get URL for MBean + mbeanURL = getMBeanURL(name); + + // Get connection to server + connection = getConnection(mbeanURL, HttpMethod.GET); + } catch (IOException io) { + throw getRequestErrorException(sourceMethod, io, mbeanURL); + } + + // Check response code from server + int responseCode = 0; + try { + responseCode = connection.getResponseCode(); + } catch (ConnectException ce) { + recoverConnection(ce); + // Server is down; not a client bug + throw ce; + } + + switch (responseCode) { + case HttpURLConnection.HTTP_OK: + JSONConverter converter = JSONConverter.getConverter(); + try { + // Process and return server response, which should be an MBeanInfoWrapper + MBeanInfoWrapper wrapper = converter.readMBeanInfo(connection.getInputStream()); + mbeanAttributesURLMap.put(name, new DynamicURL(connector, wrapper.attributesURL)); + + //Attributes + Map attributeURLsMap = mbeanAttributeURLsMap.get(name); + final boolean updateAttributes = attributeURLsMap != null; + if (!updateAttributes) { + // Create a new Map - this map is used for future requests and must be thread safe + attributeURLsMap = new ConcurrentHashMap(); + } + processAttributeOrOperationURLs(attributeURLsMap, wrapper.attributeURLs, updateAttributes); + + if (!updateAttributes) { + //Another thread might have created/set this Map already and is about to use it, which is why + //we wait until *after* we have a valid Map and are ready to push that in. + mbeanAttributeURLsMap.putIfAbsent(name, attributeURLsMap); + } + + //Operations + Map operationURLsMap = mbeanOperationURLsMap.get(name); + final boolean updateOperations = operationURLsMap != null; + if (!updateOperations) { + // Create a new Map - this map is used for future requests and must be thread safe + operationURLsMap = new ConcurrentHashMap(); + } + processAttributeOrOperationURLs(operationURLsMap, wrapper.operationURLs, updateOperations); + + if (!updateOperations) { + //Another thread might have created/set this Map already and is about to use it, which is why + //we wait until *after* we have a valid Map and are ready to push that in. + mbeanOperationURLsMap.putIfAbsent(name, operationURLsMap); + } + + return wrapper.mbeanInfo; + + } catch (ClassNotFoundException cnf) { + // Not a REST connector bug per se; not need to log this case + throw new IOException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.SERVER_RESULT_EXCEPTION), cnf); + } catch (Exception e) { + throw getResponseErrorException(sourceMethod, e, mbeanURL); + } finally { + JSONConverter.returnConverter(converter); + } + case HttpURLConnection.HTTP_BAD_REQUEST: + case HttpURLConnection.HTTP_INTERNAL_ERROR: + try { + // Server response should be a serialized Throwable + throw getServerThrowable(sourceMethod, connection); + } catch (IntrospectionException ie) { + throw ie; + } catch (InstanceNotFoundException inf) { + throw inf; + } catch (ReflectionException re) { + throw re; + } catch (IOException io) { + throw io; + } catch (Throwable t) { + throw new IOException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.UNEXPECTED_SERVER_THROWABLE), t); + } + case HttpURLConnection.HTTP_UNAUTHORIZED: + case HttpURLConnection.HTTP_FORBIDDEN: + throw getBadCredentialsException(responseCode, connection); + case HttpURLConnection.HTTP_GONE: + case HttpURLConnection.HTTP_NOT_FOUND: + IOException ioe = getResponseCodeErrorException(sourceMethod, responseCode, connection); + recoverConnection(ioe); + throw ioe; + default: + throw getResponseCodeErrorException(sourceMethod, responseCode, connection); + } + } + + /** {@inheritDoc} */ + @Override + public boolean isInstanceOf(ObjectName name, String className) throws InstanceNotFoundException, IOException { + final String sourceMethod = "isInstanceOf"; + checkConnection(); + if (name.isPattern()) + throw new InstanceNotFoundException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.OBJECT_NAME_PATTERN, name)); + + URL instanceOfURL = null; + HttpsURLConnection connection = null; + try { + // Get URL for instanceOf + instanceOfURL = getInstanceOfURL(name, className); + + // Get connection to server + connection = getConnection(instanceOfURL, HttpMethod.GET); + } catch (IOException io) { + throw getRequestErrorException(sourceMethod, io, instanceOfURL); + } + + // Check response code from server + int responseCode = 0; + try { + responseCode = connection.getResponseCode(); + } catch (ConnectException ce) { + recoverConnection(ce); + // Server is down; not a client bug + throw ce; + } + + switch (responseCode) { + case HttpURLConnection.HTTP_OK: + JSONConverter converter = JSONConverter.getConverter(); + try { + // Process and return server response, which should be a boolean + return converter.readBoolean(connection.getInputStream()); + } catch (Exception e) { + throw getResponseErrorException(sourceMethod, e, instanceOfURL); + } finally { + JSONConverter.returnConverter(converter); + } + case HttpURLConnection.HTTP_BAD_REQUEST: + case HttpURLConnection.HTTP_INTERNAL_ERROR: + try { + // Server response should be a serialized Throwable + throw getServerThrowable(sourceMethod, connection); + } catch (ClassNotFoundException cnf) { + throw new IOException(cnf); + } catch (InstanceNotFoundException inf) { + throw inf; + } catch (Throwable t) { + throw new IOException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.UNEXPECTED_SERVER_THROWABLE), t); + } + case HttpURLConnection.HTTP_UNAUTHORIZED: + case HttpURLConnection.HTTP_FORBIDDEN: + throw getBadCredentialsException(responseCode, connection); + case HttpURLConnection.HTTP_GONE: + case HttpURLConnection.HTTP_NOT_FOUND: + IOException ioe = getResponseCodeErrorException(sourceMethod, responseCode, connection); + recoverConnection(ioe); + throw ioe; + default: + throw getResponseCodeErrorException(sourceMethod, responseCode, connection); + } + + } + + // + // URL Methods + // + + protected URL getRootURL() throws IOException { + return rootURL.getURL(); + } + + private URL getDefaultDomainURL() throws IOException { + return defaultDomainURL.getURL(); + } + + private URL getDomainsURL() throws IOException { + return domainsURL.getURL(); + } + + URL getNotificationsURL() throws IOException { + return notificationsURL.getURL(); + } + + URL getFileTransferURL() throws IOException { + return fileTransferURL.getURL(); + } + + private URL getMBeanCountURL() throws IOException { + return mbeanCountURL.getURL(); + } + + private URL getAttributeURL(ObjectName name, + String attributeName) throws IOException, AttributeNotFoundException, InstanceNotFoundException, IntrospectionException, ReflectionException { + if (!mbeanAttributeURLsMap.containsKey(name)) + getMBeanInfo(name); + if (!mbeanAttributeURLsMap.containsKey(name)) + throw new InstanceNotFoundException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.INSTANCE_NOT_FOUND, name)); + else if (!mbeanAttributeURLsMap.get(name).containsKey(attributeName)) + throw new AttributeNotFoundException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.ATTRIBUTE_NOT_FOUND, name, attributeName)); + + return mbeanAttributeURLsMap.get(name).get(attributeName).getURL(); + } + + private URL getAttributesURL(ObjectName name) throws IOException, InstanceNotFoundException, IntrospectionException, ReflectionException { + if (!mbeanAttributesURLMap.containsKey(name)) + getMBeanInfo(name); + if (!mbeanAttributesURLMap.containsKey(name)) + throw new InstanceNotFoundException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.INSTANCE_NOT_FOUND, name)); + + return mbeanAttributesURLMap.get(name).getURL(); + } + + private URL getAttributesURL(ObjectName name, String[] attributes) throws IOException, InstanceNotFoundException, IntrospectionException, ReflectionException { + if (attributes != null && attributes.length > 0) { + StringBuilder sb = new StringBuilder(); + final int length = attributes.length; + for (int i = 0; i < length - 1; i++) { + sb.append("attribute="); + sb.append(URLEncoder.encode(attributes[i], "UTF-8")); + sb.append("&"); + } + sb.append("attribute="); + sb.append(URLEncoder.encode(attributes[length - 1], "UTF-8")); + String attributeList = sb.toString(); + return new URL(getAttributesURL(name).toString() + "?" + + attributeList); + } else { + return getAttributesURL(name); + } + } + + private URL getOperationURL(ObjectName name, String operationName) throws InstanceNotFoundException, IntrospectionException, ReflectionException, IOException { + if (!mbeanOperationURLsMap.containsKey(name)) + getMBeanInfo(name); + if (!mbeanOperationURLsMap.containsKey(name) || !mbeanOperationURLsMap.get(name).containsKey(operationName)) + throw new ReflectionException(new IllegalArgumentException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.OPERATION_NOT_FOUND, name, operationName))); + + return mbeanOperationURLsMap.get(name).get(operationName).getURL(); + } + + private URL getCreateMBeanURL() throws IOException { + return createMBeanURL.getURL(); + } + + private URL getInstanceOfURL() throws IOException { + return instanceOfURL.getURL(); + } + + private URL getInstanceOfURL(ObjectName name, String className) throws IOException { + return new URL(getInstanceOfURL().toString() + "?" + + (name != null ? "objectName=" + URLEncoder.encode(name.getCanonicalName(), "UTF-8") + "&" : "") + + (className != null ? "className=" + URLEncoder.encode(className, "UTF-8") : "")); + } + + private URL getMBeansURL() throws IOException { + return mbeansURL.getURL(); + } + + private URL getMBeansURL(ObjectName name, String instanceOf) throws IOException { + return new URL(getMBeansURL().toString() + "?" + + (name != null ? "objectName=" + URLEncoder.encode(name.getCanonicalName(), "UTF-8") + "&" : "") + + (instanceOf != null ? "className=" + URLEncoder.encode(instanceOf, "UTF-8") : "")); + } + + private URL getMBeanURL(ObjectName name) throws IOException, InstanceNotFoundException { + if (!mbeanInfoURLMap.containsKey(name)) + queryMBeans(name, null, null, true); + if (!mbeanInfoURLMap.containsKey(name)) + throw new InstanceNotFoundException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.INSTANCE_NOT_FOUND, name)); + return mbeanInfoURLMap.get(name).getURL(); + } + + private void purgeMBeanURLs(ObjectName name) { + mbeanInfoURLMap.remove(name); + mbeanAttributesURLMap.remove(name); + mbeanAttributeURLsMap.remove(name); + mbeanOperationURLsMap.remove(name); + } + + private void processAttributeOrOperationURLs(Map destination, Map source, boolean update) { + if (update) { + // Remove any elements that are not present in the new map + Set missingKeys = new HashSet(destination.keySet()); + missingKeys.removeAll(source.keySet()); + for (String missingKey : missingKeys) { + destination.remove(missingKey); + } + } + + for (Map.Entry e : source.entrySet()) { + if (!update || !destination.containsKey(e.getKey()) || + !destination.get(e.getKey()).getName().equals(e.getValue())) { + destination.put(e.getKey(), new DynamicURL(connector, e.getValue())); + } + } + } + + private void processMBeanInfoURLs(Map source, String parentPath, boolean complete) { + if (complete) { + // This is the complete set of MBeanInfo URLs, so remove any elements that are not present in the new map + Set missingKeys = new HashSet(mbeanInfoURLMap.keySet()); + missingKeys.removeAll(source.keySet()); + for (ObjectName missingKey : missingKeys) { + purgeMBeanURLs(missingKey); + } + } + + for (Map.Entry e : source.entrySet()) { + if (!mbeanInfoURLMap.containsKey(e.getKey()) || + !mbeanInfoURLMap.get(e.getKey()).getName().equals(e.getValue())) { + // if updating the MBeanInfo URL (because new URL did not match), other maps are now invalid, + // so purge before re-adding + if (mbeanInfoURLMap.containsKey(e.getKey())) + purgeMBeanURLs(e.getKey()); + mbeanInfoURLMap.put(e.getKey(), new DynamicURL(connector, e.getValue())); + } + } + } + + // + // Exception Message and Logging Methods + // + + synchronized void logSevereException(String sourceMethod, String errorMsg, Exception e) { + logger.logp(Level.SEVERE, logger.getName(), sourceMethod, errorMsg, e); + } + + synchronized IOException getRequestErrorException(String sourceMethod, Exception e, URL url) { + String urlString = (url != null) ? url.toString() : "null"; + String connectionId = connector.getConnectionId(); + String errorMsg = RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.REQUEST_ERROR, + urlString, connectionId); + logger.logp(Level.SEVERE, logger.getName(), sourceMethod, errorMsg, e); + return new IOException(errorMsg, e); + } + + synchronized IOException getRequestErrorException(String sourceMethod, Exception e) { + String connectionId = connector.getConnectionId(); + String errorMsg = RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.REQUEST_ERROR, + null, connectionId); + logger.logp(Level.SEVERE, logger.getName(), sourceMethod, errorMsg, e); + return new IOException(errorMsg, e); + } + + synchronized IOException getResponseErrorException(String sourceMethod, Exception e, URL url) { + String urlString = (url != null) ? url.toString() : "null"; + String connectionId = connector.getConnectionId(); + String errorMsg = RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.RESPONSE_ERROR, + urlString, connectionId); + logger.logp(Level.SEVERE, logger.getName(), sourceMethod, errorMsg, e); + return new IOException(errorMsg, e); + } + + synchronized IOException getResponseCodeErrorException(String methodName, int responseCode, HttpsURLConnection connection) { + // Did not understand response code; create an IOException with response message and log error + String responseMessage = null; + try { + responseMessage = connection.getResponseMessage(); + } catch (IOException io) { + // Use null for message + } + String errorMsg = RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.RESPONSE_CODE_ERROR, + responseCode, responseMessage, + connection.getURL().toString(), + connector.getConnectionId()); + logger.logp(Level.SEVERE, logger.getName(), methodName, errorMsg); + return new IOException(errorMsg); + } + + synchronized Throwable getServerThrowable(String methodName, HttpsURLConnection connection) { + Throwable t; + JSONConverter converter = JSONConverter.getConverter(); + try { + t = converter.readThrowable(connection.getErrorStream()); + } catch (ClassNotFoundException cnf) { + // Not a REST connector bug per se; no need to log this case + t = new IOException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.SERVER_THROWABLE_EXCEPTION), cnf); + } catch (Exception e) { + t = getResponseErrorException(methodName, e, connection.getURL()); + } finally { + JSONConverter.returnConverter(converter); + } + + return t; + } + + IOException getBadCredentialsException(int responseCode, HttpsURLConnection connection) { + // Received response code 401 or 403; problem with credentials + String responseMessage = null; + try { + responseMessage = connection.getResponseMessage(); + } catch (IOException io) { + // Use null for message + } + return new IOException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.BAD_USER_CREDENTIALS, responseCode, responseMessage)); + } + + // -- Connection methods + + // When the connection normally closes, we disconnect after we have finished closing everything, to give everyone a chance to + //do the proper cleaning procedures. + void close() { + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), "close", "Close called for " + RESTClientMessagesUtil.getObjID(this) + " within connection: " + + connector.getConnectionId()); + } + + closePollingThread(); + + if (notificationRegistry != null) { + notificationRegistry.close(); + } + + if (connector.logFailovers()) { + String disconnectMsg = RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.MEMBER_DISCONNECT, connector.getCurrentEndpoint()); + logger.logp(Level.INFO, logger.getName(), "close", disconnectMsg); + } + + disconnect(); + } + + private void closePollingThread() { + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), "closePollingThread", "Closing thread: " + serverPollingThread.getCustomId()); + } + if (serverPollingThread != null) { + serverPollingThread.interrupt(); + + try { + serverPollingThread.join(2000); + } catch (InterruptedException e) { + //ignore..but we really shouldn't be interrupted by anybody else + } finally { + serverPollingThread = null; + } + } + } + + //When the connection fails we disconnect right away to keep anything else from happening (ie: bad connection) + synchronized void connectionFailed(Throwable t) { + if (!isConnected()) { + //another thread already disconnected this connector, so return + return; + } + + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), "connectionFailed", "Connection failed: " + RESTClientMessagesUtil.getObjID(this)); + } + + disconnect(); + + if (notificationRegistry != null) { + notificationRegistry.close(); + } + + //Emit the notification + connector.connectionFailed(t); + } + + private void disconnect() { + if (logger.isLoggable(Level.FINEST)) { + logger.logp(Level.FINEST, logger.getName(), "disconnect", "Disconnect called for " + RESTClientMessagesUtil.getObjID(this)); + } + this.disconnected = true; + } + + boolean isConnected() { + return !disconnected; + } + + private void checkConnection() throws IOException { + if (!isConnected()) + throw new IOException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.NOT_CONNECTED)); + } + + HttpsURLConnection getBasicConnection(URL url, HttpMethod method) throws IOException { + HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); + connection.setDoInput(true); + connection.setDoOutput(method == HttpMethod.POST || method == HttpMethod.PUT); + connection.setUseCaches(false); + connection.setRequestMethod(method.toString()); + connection.setRequestProperty("Content-Type", ClientConstants.JSON_MIME_TYPE); + connection.setReadTimeout(connector.getReadTimeout()); + // Only add the Authorization header if we have one to add. It may + // not be present in certain flows, such as the certificate-based + // authentication. + if (connector.getBasicAuthHeader() != null) { + connection.setRequestProperty("Authorization", connector.getBasicAuthHeader()); + } + if (connector.isHostnameVerificationDisabled()) + connection.setHostnameVerifier(hostnameVerificationDisabler); + if (this.connector.getCustomSSLSocketFactory() != null) { + connection.setSSLSocketFactory(this.connector.getCustomSSLSocketFactory()); + } + + connection.setRequestProperty("User-Agent", CLIENT_VERSION); + + return connection; + } + + Connector getConnector() { + return connector; + } + + protected boolean isServerLevelRouting() { + + if ((mapRouting != null && mapRouting.size() == 3 && + isValueSet((String) mapRouting.get(ClientProvider.ROUTING_KEY_HOST_NAME)) && isValueSet((String) mapRouting.get(ClientProvider.ROUTING_KEY_SERVER_NAME)) + && isValueSet((String) mapRouting.get(ClientProvider.ROUTING_KEY_SERVER_USER_DIR)))) { + return true; + } else { + return false; + } + } + + protected boolean isHostLevelRouting() { + if ((mapRouting != null && mapRouting.size() == 1 && isValueSet((String) mapRouting.get(ClientProvider.ROUTING_KEY_HOST_NAME)))) { + return true; + } else { + return false; + } + } + + /** + * Checks if a value is null or empty. + * + * @param s The variable need to be checked. + * @return if the variable is not null and not empty. Otherwise return false. + */ + public boolean isValueSet(String s) { + return (s != null && s.trim().isEmpty() == false) ? true : false; + } + + HttpsURLConnection getConnection(URL originalUrl, HttpMethod method) throws IOException { + return getConnection(originalUrl, method, false); + } + + HttpsURLConnection getConnection(URL originalUrl, HttpMethod method, boolean ignoreProxy) throws IOException { + return getConnection(originalUrl, method, ignoreProxy, null); + } + + HttpsURLConnection getConnection(URL originalUrl, HttpMethod method, boolean ignoreProxy, Map routingInfo) throws IOException { + URL url = originalUrl; + String sURL = originalUrl.toString(); + + //For MBean routing we only care about server level routing, so that's our proxy mode. Other users/extenders of this class, + //such as file transfer, might also check for host level routing. + final boolean inProxyMode = !ignoreProxy && isServerLevelRouting(); + if (inProxyMode && sURL.indexOf(ClientConstants.ROUTER_URI) < 0) { + //If we're talking to a server that has a version at or greater than 4, then we don't need the /router URL. + final String asURL = serverVersion >= 4 ? sURL : sURL.replaceFirst(ClientConstants.CONNECTOR_URI, ClientConstants.ROUTER_URI); + try { + url = AccessController.doPrivileged( + new PrivilegedExceptionAction() { + @Override + public URL run() throws MalformedURLException { + return new URL(asURL); + } + }); + } catch (PrivilegedActionException e) { + throw new IOException(e.getMessage()); + } + + } + HttpsURLConnection connection = getBasicConnection(url, method); + // If routing info is explicitly provided to this method always set the request properties with the routing information. + if (inProxyMode || routingInfo != null) { + // Use the MBeanServerConnection's current routing context if routing info wasn't explicitly provided to this method. + if (routingInfo == null) { + routingInfo = mapRouting; + } + connection.addRequestProperty(ClientProvider.ROUTING_KEY_HOST_NAME, (String) routingInfo.get(ClientProvider.ROUTING_KEY_HOST_NAME)); + connection.addRequestProperty(ClientProvider.ROUTING_KEY_SERVER_USER_DIR, (String) routingInfo.get(ClientProvider.ROUTING_KEY_SERVER_USER_DIR)); + connection.addRequestProperty(ClientProvider.ROUTING_KEY_SERVER_NAME, (String) routingInfo.get(ClientProvider.ROUTING_KEY_SERVER_NAME)); + if (inProxyMode) { + connection.addRequestProperty(ClientProvider.READ_TIMEOUT, String.valueOf(connector.getReadTimeout())); + } + } + return connection; + } + + /** + * Attemps to recover the connection, either to the current endpoint or to other endpoints, depending + * on the configuration of this connector and availability of endpoints. + * + * If we cannot connect to any of the available endpoints, this method will disconnect the connector and any subsequent call + * attempts will throw exceptions. If we can connect to a new endpoint, or recover the connection to our old endpoint, then + * the notification area and all URLs will be setup to use the connected endpoint. + * + * Appropriate JMXConnector-level notifications are sent for all events. + * + * @param t represents the exception that led us in here, or null. + */ + protected void recoverConnection(Throwable t) { + recoverConnection(t, false); + } + + protected void recoverConnection(Throwable t, boolean skipCurrentEndpoint) { + final String methodName = "recoverConnection"; + + //We don't want to synchronize this method because we don't want a pile of threads + //to queue up waiting to come in, each doing the same connection recovery. Instead, we + //use an atomic boolean to guard entry so that only 1 thread does the actual recovery. + if (!isRecoveringConnection.compareAndSet(false, true)) { + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), methodName, "Exiting. Another thread is doing the recovery"); + } + + //another thread is currently trying to recover the connection, so we can exit. + return; + } + + //We wrap the entire code below in a try{} so that we're sure to reset the isRecoveringConnection value. + try { + + if (!isConnected()) { + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), methodName, "Connection has been closed."); + } + //the connection has been closed + return; + } + + //The first thing we do is emit the notification that we have temporarily lost connection + connector.connectionTemporarilyLost(t); + + //Get the current endpoint + final String originalEndpoint = connector.getCurrentEndpoint(); + + //Try to re-connect to the current endpoint first. This is to keep the same behaviour for non-WLM scenarios, where there is + //only 1 endpoint and the user may have configured an amount of time that they want to wait for that server to be up. For WLM + //scenarios, users can set this time to 0 so that we don't retry the current endpoint and instead move onto the other endpoints + //right away. Alternatively, WLM users can set this time to be > 0 so that they retry the current endpoint first, if they wish. + + final int maxServerRestartTime = connector.getMaxServerWaitTime(); + + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), methodName, "[" + RESTClientMessagesUtil.getObjID(this) + "] Waiting for current endpoint [" + originalEndpoint + + "] to come up. Max time: " + + maxServerRestartTime); + } + + if (!skipCurrentEndpoint && maxServerRestartTime > 0) { + final int serverStatusPollingInterval = connector.getServerStatusPollingInterval(); + final long endTime = System.nanoTime() + maxServerRestartTime * NANOS_IN_A_MILLISECOND; + + while (System.nanoTime() < endTime) { + // Try to set up new NotificationArea, re-register notifications if successful + try { + if (testConnection(originalEndpoint)) { + //Our notification registry will be null if we came into recovery mode during the connector's init + if (notificationRegistry == null) { + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), methodName, "Returning sucessfully. No notification to recover."); + } + //We still need to send the connection restored + connector.connectionRestored(null); + return; + } + notificationRegistry.setupNotificationArea(); + if (notificationRegistry.restoreNotificationRegistrations(true)) { + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), methodName, "Returning sucessfully, notification restored for current endpoint."); + } + return; + } + } + } catch (Throwable throwable) { + // ignore and try again + } + long currentTime = System.nanoTime(); + if (currentTime < endTime) { + try { + long millisToWait = (endTime - currentTime + (NANOS_IN_A_MILLISECOND - 1)) / NANOS_IN_A_MILLISECOND; // round up - to avoid 0 + Thread.sleep(Math.min(millisToWait, serverStatusPollingInterval)); + } catch (InterruptedException ie) { + // Connection being closed; return false so thread exits + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), methodName, "Returning false, interrupted:" + ie); + } + //disconnect (this will also emit a FAILED notification) + connectionFailed(t); + return; + } + } + } + } + + //Get the full list of endpoints. + List endpoints = connector.getEndpointList(); + + for (String endpoint : endpoints) { + //we already tried the original endpoint, so skip that one. + if (endpoint.equals(originalEndpoint)) { + continue; + } + + if (testConnection(endpoint)) { + //Set our tentative new endpoint so we can attempt to setup notifications. + //If this fails we don't need to worry about re-instating the old endpoint because we + //will either override that value with another endpoint further down the list, or if none are + //available we will fail the entire connection. + connector.setCurrentEndpoint(endpoint); + + try { + + if (notificationRegistry == null) { + //haven't setup the notification thread yet + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), methodName, "Returning sucessfully."); + } + //NOTE: we don't emit an OPEN notification because we're in the connector' initialization process, + //which will already emit an OPEN notification. + return; + } + + //Setup notification area on the new endpoint + notificationRegistry.setupNotificationArea(); + + //restore notifications (don't send restored notification, since we're actually using a new endpoint) + if (notificationRegistry.restoreNotificationRegistrations(false)) { + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), methodName, "Returning sucessfully, notification restored."); + } + + //everything is ready to go, so emit OPENED notification + connector.connectionOpened(); + + //Re-load the server info because it could have changed (ie: server version, URLs) + loadJMXServerInfo(); + + if (connector.logFailovers()) { + String connectMsg = RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.MEMBER_CONNECT, endpoint); + logger.logp(Level.INFO, logger.getName(), methodName, connectMsg); + } + + return; + } + //could not restore notifications, so try next endpoint + continue; + } catch (Throwable e) { + //ignore and try next endpoint + continue; + } + } + } + + //disconnect (this will also emit a FAILED notification) + connectionFailed(t); + + return; + } finally { + //we're done with the recovery (either by return or by runtime exceptions), so restore atomic state + isRecoveringConnection.set(false); + } + } + + private void findInitialEndpoint() throws IOException { + //Get the full list of endpoints. + List endpoints = connector.getEndpointList(); + String connectMsg; + + if (endpoints != null) { + if (endpoints.size() == 1) { + connector.setCurrentEndpoint(endpoints.get(0)); + return; + } + + for (String endpoint : endpoints) { + if (testConnection(endpoint)) { + connector.setCurrentEndpoint(endpoint); + return; + } + } + } + + throw new IOException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.NO_AVAILABLE_ENDPOINTS)); + } + + private URL getSimpleURL(String endpoint) throws MalformedURLException { + String[] endpointSegments = splitEndpoint(endpoint); + return new URL("https", endpointSegments[0], Integer.valueOf(endpointSegments[1]), "/IBMJMXConnectorREST/mbeanServer"); + } + + private boolean testConnection(String endpoint) { + if (logger.isLoggable(Level.FINE)) { + logger.logp(Level.FINE, logger.getName(), "testConnection", "Testing connection for endpoint " + endpoint); + } + + //Build our test URL + URL testURL = null; + try { + //Make the most simple URL available on the server side + testURL = getSimpleURL(endpoint); + } catch (Exception e) { + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), "testConnection", "Failed while making URL:" + e.getMessage()); + } + //Very unlikely to fail here, but return false if it happens + return false; + } + + //Try to connect to the simple URL + try { + HttpsURLConnection connection = getBasicConnection(testURL, HttpMethod.GET); + final int responseCode = connection.getResponseCode(); + if (responseCode == HttpURLConnection.HTTP_OK) { + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), "testConnection", "Successful!"); + } + return true; + } + + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), "testConnection", "Failed connection attempt with response code:" + responseCode); + } + return false; + + } catch (IOException e) { + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), "testConnection", "Failed connection attempt with exception:" + e.getMessage()); + } + return false; + } + + } + + public class ServerPollingThread extends Thread { + + /** + * The current polling mode we're in. Failover vs Notification. + */ + private PollingMode mode = null; + + /** + * The amount of time this thread waits betweeen server polls. Needs + * to be volatile because other threads will trigger a change to this value. + * The actual wait interval will be directly related to the polling mode we're in. + */ + private volatile long waitInterval = 0; + + /** + * Flag used to synchronize stand-by operations + */ + private final Object waitFlag = new PollingWaitFlag(); + + /** + * Inner class to use for the standby-lock (as suggested by findbugs) + */ + private class PollingWaitFlag {} + + //Constructor + private ServerPollingThread(PollingMode mode) { + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), "ServerPollingThread", "Created thread: " + getCustomId()); + } + // polling thread should be run as a daemon by default + setDaemon(true); + setName("JMX-REST-Client-Polling"); + changeMode(mode); + } + + public String getCustomId() { + return "ThreadID[" + this.getId() + "], from [" + connector.getConnectionId() + "]"; + } + + //This method gets called by the RESTMBeanServerConnection when certain events occur + protected void changeMode(PollingMode newMode) { + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), "changeMode", "Changing mode from " + mode + " to " + newMode + " in thread: " + getCustomId()); + } + + //Only take action if we're changing polling mode + if (mode != newMode) { + synchronized (waitFlag) { + //Update mode + mode = newMode; + + if (mode == PollingMode.NOTIFICATION) { + waitInterval = connector.getNotificationFetchInterval(); + } else { + waitInterval = connector.getServerFailoverInterval(); + } + + if (logger.isLoggable(Level.FINEST)) { + logger.logp(Level.FINEST, logger.getName(), "changeMode", "waitInterval is now: " + waitInterval); + } + + //Notify thread to wake up. Only 1 thread (serverPollingThread) will be + //potentially waiting on this flag, so we can use notify() instead of notifyAll(). + waitFlag.notify(); + } + } + } + + /** {@inheritDoc} */ + @Override + public void run() { + final String sourceMethod = "run"; + + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), sourceMethod, "Running thread: " + getCustomId()); + } + + JSONConverter converter = JSONConverter.getConverter(); + + mainLoop: while (!interrupted() && isConnected()) { + URL targetURL = null; + HttpsURLConnection connection = null; + + //We cache the value of "mode" during every iteration of the while loop in case + //another thread changes our polling mode during a HTTP request. We want each + //HTTP request/response to have equal modes, and only change in the next iteration. + final PollingMode currentMode = mode; + + try { + if (currentMode == PollingMode.NOTIFICATION) { + //Connect to inboxURL + targetURL = notificationRegistry.getInboxURL(); + connection = getConnection(targetURL, HttpMethod.GET, true); + connection.setReadTimeout(getConnector().getNotificationReadTimeout()); + } else { + //Connect to a simple URL to ping server + targetURL = getSimpleURL(connector.getCurrentEndpoint()); + connection = getConnection(targetURL, HttpMethod.GET, true); + } + + if (logger.isLoggable(Level.FINEST)) { + logger.logp(Level.FINEST, logger.getName(), sourceMethod, "Making a call to URL [" + targetURL + "] inside thread: " + getCustomId()); + } + + } catch (IOException io) { + //If we got here we have problems other than server connection, so we must fail right away + logger.logp(Level.FINE, logger.getName(), sourceMethod, io.getMessage(), io); + connectionFailed(getRequestErrorException(sourceMethod, io, targetURL)); + break mainLoop; + } + + try { + // Check response code from server + int responseCode = 0; + try { + responseCode = connection.getResponseCode(); + + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), sourceMethod, "Response code: " + responseCode); + } + + } catch (ConnectException ce) { + logger.logp(Level.FINE, logger.getName(), sourceMethod, ce.getMessage(), ce); + recoverConnection(ce); + continue mainLoop; + } catch (IOException io) { + logger.logp(Level.FINE, logger.getName(), sourceMethod, io.getMessage(), io); + continue mainLoop; + } + + switch (responseCode) { + case HttpURLConnection.HTTP_OK: + try { + + if (currentMode == PollingMode.NOTIFICATION) { + // Process and return server response, which should be an array of Notifications + NotificationRecord[] notificationRecords = converter.readNotificationRecords(connection.getInputStream()); + + if (notificationRecords != null && isConnected()) { + + if (logger.isLoggable(Level.FINEST)) { + logger.logp(Level.FINEST, logger.getName(), sourceMethod, "Received " + notificationRecords.length + " notifications"); + } + + for (NotificationRecord nr : notificationRecords) { + Notification n = nr.getNotification(); + Object source = n.getSource(); + if (!(source instanceof ObjectName)) { + logger.logp(Level.FINE, logger.getName(), sourceMethod, "Notification source was not ObjectName: " + source); + getConnector().notificationLost(n); + continue; + } + + // Deliver the notification + ClientNotificationRegistration localRegistration = notificationRegistry.getRegistrationMap().get(nr.getNotificationTargetInformation()); + if (localRegistration != null) { + try { + localRegistration.handleNotification(n); + } catch (Exception e) { + logSevereException(sourceMethod, RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.NOTIFICATION_LOST), e); + getConnector().notificationLost(n); + } + } else { + getConnector().notificationLost(n); + } + } + + if (notificationRecords.length > 0) { + //try to fetch right away, in case this is a burst of notifications + continue mainLoop; + } + } + } else { + //no-op for failover polling, just break into the sleep segment + } + break; + } catch (ClassNotFoundException cnf) { + // Not a REST connector bug per se; not need to log this case + throw new IOException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.SERVER_RESULT_EXCEPTION), cnf); + } catch (Exception e) { + logger.logp(Level.FINE, logger.getName(), sourceMethod, e.getMessage(), e); + throw getResponseErrorException(sourceMethod, e, targetURL); + } + case HttpURLConnection.HTTP_NOT_FOUND: + Throwable ex = new IOException(RESTClientMessagesUtil.getMessage(RESTClientMessagesUtil.URL_NOT_FOUND)); + logger.logp(Level.FINE, logger.getName(), sourceMethod, ex.getMessage()); + recoverConnection(ex); + continue mainLoop; + + case HttpURLConnection.HTTP_GONE: + // Notification area went away; try to re-establish + Throwable t = getServerThrowable(sourceMethod, connection); + logger.logp(Level.FINE, logger.getName(), sourceMethod, t.getMessage()); + recoverConnection(t); + continue mainLoop; + + case HttpURLConnection.HTTP_BAD_REQUEST: + case HttpURLConnection.HTTP_INTERNAL_ERROR: + // Server response should be a serialized Throwable + Throwable ie = getServerThrowable(sourceMethod, connection); + logger.logp(Level.FINE, sourceMethod, logger.getName(), ie.getMessage()); + throw ie; + case HttpURLConnection.HTTP_UNAUTHORIZED: + case HttpURLConnection.HTTP_FORBIDDEN: + throw getBadCredentialsException(responseCode, connection); + default: + throw getResponseCodeErrorException(sourceMethod, responseCode, connection); + } + } catch (ClosedByInterruptException ie) { + logger.logp(Level.FINE, logger.getName(), sourceMethod, ie.getMessage()); + break mainLoop; + } catch (Throwable t) { + logger.logp(Level.FINE, logger.getName(), sourceMethod, t.getMessage()); + //If we get an unknown exception in this polling thread we must try to reconnect, which + //will disconnect the connector if the server is not returning proper requests. + recoverConnection(t); + continue mainLoop; + } + + //We need to wait a certain amount of time before making the next request + if (waitInterval > 0) { + if (logger.isLoggable(Level.FINEST)) { + logger.logp(Level.FINEST, logger.getName(), sourceMethod, "Calling sleep for " + waitInterval + " milliseconds on thread: " + getCustomId()); + } + try { + synchronized (waitFlag) { + waitFlag.wait(waitInterval); + } + } catch (InterruptedException e) { + if (logger.isLoggable(Level.FINE)) { + logger.logp(Level.FINE, logger.getName(), sourceMethod, "Interrupted sleep in thread: " + getCustomId()); + } + } + } + } + + JSONConverter.returnConverter(converter); + } + } + + /** + * Properly split a given endpoint into host/port. + * + * @param endpoint in the form host:port, where host could be a named host, an IPv4 or IPv6 address. + * @return a String array where [0] is the host and [1] is the port. + */ + public static String[] splitEndpoint(String endpoint) { + //The way our endpoints are constructed ensures that we will always have a ":" present..so don't need to check for -1 + final int lastColon = endpoint.lastIndexOf(":"); + String[] splitString = new String[2]; + splitString[0] = endpoint.substring(0, lastColon); + splitString[1] = endpoint.substring(lastColon + 1, endpoint.length()); + + if (logger.isLoggable(Level.FINEST)) { + logger.logp(Level.FINEST, logger.getName(), "splitEndpoint", "Split " + endpoint + " into " + splitString[0] + " and " + splitString[1]); + } + + return splitString; + } + +} diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/internal/ServerNotificationListenerEntry.java b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/internal/ServerNotificationListenerEntry.java new file mode 100755 index 00000000000..fb6b90c6217 --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/internal/ServerNotificationListenerEntry.java @@ -0,0 +1,62 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jmx.connector.client.rest.internal; + +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.management.NotificationFilter; +import javax.management.ObjectName; + +import com.ibm.ws.jmx.connector.converter.NotificationTargetInformation; + +class ServerNotificationListenerEntry { + public final NotificationTargetInformation nti; + public final ObjectName listener; + public final NotificationFilter filter; + public final Object handback; + + private static final Logger logger = Logger.getLogger(ServerNotificationListenerEntry.class.getName()); + + /** + * @param listener + * @param filter + * @param handback + */ + ServerNotificationListenerEntry(NotificationTargetInformation nti, ObjectName listener, NotificationFilter filter, Object handback) { + this.nti = nti; + this.listener = listener; + this.filter = filter; + this.handback = handback; + + if (logger.isLoggable(Level.FINER)) { + logger.logp(Level.FINER, logger.getName(), "init", "targetInfo: " + nti + " | listener: " + listener + " | filter: " + filter + " | handback: " + handback); + } + + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof ServerNotificationListenerEntry)) + return false; + ServerNotificationListenerEntry other = (ServerNotificationListenerEntry) o; + return nti.equals(other.nti) && listener.equals(other.listener) && filter == other.filter && handback == other.handback; + } + + @Override + public int hashCode() { + return nti.hashCode() + listener.hashCode() + + (filter != null ? filter.hashCode() : 0) + + (handback != null ? handback.hashCode() : 0); + } + +} diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/internal/package-info.java b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/internal/package-info.java new file mode 100755 index 00000000000..59084992b27 --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/internal/package-info.java @@ -0,0 +1,17 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +/** + * @version 1.0 + */ +@org.osgi.annotation.versioning.Version("1.0") +package com.ibm.ws.jmx.connector.client.rest.internal; + diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessagesUtil.java b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessagesUtil.java new file mode 100755 index 00000000000..39798e60228 --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/internal/resources/FileTransferClientMessagesUtil.java @@ -0,0 +1,48 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012, 2014 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jmx.connector.client.rest.internal.resources; + +import java.text.MessageFormat; +import java.util.ResourceBundle; + +/** + * + */ +public class FileTransferClientMessagesUtil { + + private static final ResourceBundle logMessages = ResourceBundle.getBundle("com.ibm.ws.jmx.connector.client.rest.internal.resources.FileTransferClientMessages"); + + // Error messages + public static final String CLIENT_ERROR = "filetransfer.client.error"; + public static final String SERVER_ERROR = "filetransfer.server.error"; + public static final String BAD_CREDENTIALS = "filetransfer.client.bad.credentials"; + public static final String RESPONSE_CODE_ERROR = "filetransfer.response.code.error"; + public static final String UNSUPPORTED_OPERATION = "filetransfer.unsupported.operation"; + + // Info messages + public static final String CLIENT_INIT = "filetransfer.client.init"; + public static final String DOWNLOAD_TO_FILE = "filetransfer.download.file"; + public static final String UPLOAD_FROM_FILE = "filetransfer.upload.file"; + public static final String DELETE_FILE = "filetransfer.delete.file"; + public static final String DELETE_ALL = "filetransfer.delete.all"; + + public static String getMessage(String messageName, Object... arguments) { + if (arguments.length > 0) + return MessageFormat.format(logMessages.getString(messageName), arguments); + else + return logMessages.getString(messageName); + } + + public static String getObjID(Object obj) { + return obj.getClass().getSimpleName() + "@" + System.identityHashCode(obj); + } +} diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessagesUtil.java b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessagesUtil.java new file mode 100755 index 00000000000..af3d56b5ea3 --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/internal/resources/RESTClientMessagesUtil.java @@ -0,0 +1,75 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jmx.connector.client.rest.internal.resources; + +import java.text.MessageFormat; +import java.util.ResourceBundle; + +/** + * + */ +public class RESTClientMessagesUtil { + + private static final ResourceBundle logMessages = ResourceBundle.getBundle("com.ibm.ws.jmx.connector.client.rest.internal.resources.RESTClientMessages"); + + // Severe log messages + public static final String REQUEST_ERROR = "jmx.rest.client.request.error"; + public static final String RESPONSE_ERROR = "jmx.rest.client.response.error"; + public static final String RESPONSE_CODE_ERROR = "jmx.rest.client.response.code.error"; + + // Exception messages + public static final String SERVER_THROWABLE_EXCEPTION = "jmx.rest.client.server.throwable.exception"; + public static final String SERVER_RESULT_EXCEPTION = "jmx.rest.client.server.result.exception"; + public static final String NOT_CONNECTED = "jmx.rest.client.not.connected"; + public static final String URL_NOT_FOUND = "jmx.rest.client.url.not.found"; + public static final String CLASS_NAME_NULL = "jmx.rest.client.class.name.null"; + public static final String ATTRIBUTE_NAME_NULL = "jmx.rest.client.attribute.name.null"; + public static final String ATTRIBUTE_NAMES_NULL = "jmx.rest.client.attribute.names.null"; + public static final String ATTRIBUTE_NULL = "jmx.rest.client.attribute.null"; + public static final String ATTRIBUTE_LIST_NULL = "jmx.rest.client.attribute.list.null"; + public static final String OBJECT_NAME_NULL = "jmx.rest.client.object.name.null"; + public static final String UNEXPECTED_SERVER_THROWABLE = "jmx.rest.client.unexpected.server.throwable"; + + // Exception messages with parameters + public static final String BAD_CREDENTIALS = "jmx.rest.client.bad.credentials"; + public static final String BAD_USER_CREDENTIALS = "jmx.rest.client.bad.user.credentials"; + public static final String OBJECT_NAME_PATTERN = "jmx.rest.client.object.name.pattern"; + public static final String INSTANCE_NOT_FOUND = "jmx.rest.client.instance.not.found"; + public static final String ATTRIBUTE_NOT_FOUND = "jmx.rest.client.attribute.not.found"; + public static final String OPERATION_NOT_FOUND = "jmx.rest.client.operation.not.found"; + public static final String LISTENER_NOT_FOUND = "jmx.rest.client.listener.not.found"; + + // Connection listener messages + public static final String NOTIFICATION_LOST = "jmx.rest.client.notification.lost"; + public static final String CONNECTION_FAILED = "jmx.rest.client.connection.failed"; + public static final String CONNECTION_TEMPORARILY_LOST = "jmx.rest.client.connection.temporarily.lost"; + public static final String CONNECTION_RESTORED_WITH_EXCEPTIONS = "jmx.rest.client.connection.restored.with.exceptions"; + public static final String CONNECTION_RESTORED = "jmx.rest.client.connection.restored"; + public static final String MEMBER_CONNECT = "jmx.rest.client.connection.connect"; + public static final String MEMBER_DISCONNECT = "jmx.rest.client.connection.disconnect"; + + // Endpoint related messages + public static final String NULL_SERVICE_URL = "jmx.rest.client.connection.illegal.argument"; + public static final String INVALID_ENDPOINT = "jmx.rest.client.connection.invalid.endpoint"; + public static final String NO_AVAILABLE_ENDPOINTS = "jmx.rest.client.connection.no.endpoints"; + + public static String getMessage(String messageName, Object... arguments) { + if (arguments.length > 0) + return MessageFormat.format(logMessages.getString(messageName), arguments); + else + return logMessages.getString(messageName); + } + + public static String getObjID(Object obj) { + return obj.getClass().getSimpleName() + "@" + System.identityHashCode(obj); + } +} diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/package-info.java b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/package-info.java new file mode 100755 index 00000000000..32487a53f4b --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/client/rest/package-info.java @@ -0,0 +1,16 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +/** + * @version 1.4.0 + */ +@org.osgi.annotation.versioning.Version("1.4.0") +package com.ibm.ws.jmx.connector.client.rest; diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/converter/JSONConverter.java b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/converter/JSONConverter.java new file mode 100755 index 00000000000..caa62fa9de2 --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/converter/JSONConverter.java @@ -0,0 +1,4418 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012,2015 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jmx.connector.converter; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.lang.reflect.Array; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.Stack; +import java.util.TreeMap; +import java.util.Vector; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.management.Attribute; +import javax.management.AttributeChangeNotification; +import javax.management.AttributeChangeNotificationFilter; +import javax.management.AttributeList; +import javax.management.Descriptor; +import javax.management.ImmutableDescriptor; +import javax.management.MBeanAttributeInfo; +import javax.management.MBeanConstructorInfo; +import javax.management.MBeanInfo; +import javax.management.MBeanNotificationInfo; +import javax.management.MBeanOperationInfo; +import javax.management.MBeanParameterInfo; +import javax.management.MBeanServerNotification; +import javax.management.MalformedObjectNameException; +import javax.management.Notification; +import javax.management.NotificationFilter; +import javax.management.NotificationFilterSupport; +import javax.management.ObjectInstance; +import javax.management.ObjectName; +import javax.management.QueryExp; +import javax.management.openmbean.ArrayType; +import javax.management.openmbean.CompositeData; +import javax.management.openmbean.CompositeDataSupport; +import javax.management.openmbean.CompositeType; +import javax.management.openmbean.OpenDataException; +import javax.management.openmbean.OpenType; +import javax.management.openmbean.SimpleType; +import javax.management.openmbean.TabularData; +import javax.management.openmbean.TabularDataSupport; +import javax.management.openmbean.TabularType; +import javax.management.relation.MBeanServerNotificationFilter; +import javax.management.relation.RelationNotification; +import javax.management.remote.JMXConnectionNotification; +import javax.management.timer.TimerNotification; + +import com.ibm.json.java.JSON; +import com.ibm.json.java.JSONArray; +import com.ibm.json.java.JSONArtifact; +import com.ibm.json.java.JSONObject; +import com.ibm.ws.jmx.connector.client.rest.ClientProvider; +import com.ibm.ws.jmx.connector.datatypes.ConversionException; +import com.ibm.ws.jmx.connector.datatypes.CreateMBean; +import com.ibm.ws.jmx.connector.datatypes.Invocation; +import com.ibm.ws.jmx.connector.datatypes.JMXServerInfo; +import com.ibm.ws.jmx.connector.datatypes.MBeanInfoWrapper; +import com.ibm.ws.jmx.connector.datatypes.MBeanQuery; +import com.ibm.ws.jmx.connector.datatypes.NotificationArea; +import com.ibm.ws.jmx.connector.datatypes.NotificationRegistration; +import com.ibm.ws.jmx.connector.datatypes.NotificationSettings; +import com.ibm.ws.jmx.connector.datatypes.ObjectInstanceWrapper; +import com.ibm.ws.jmx.connector.datatypes.ServerNotificationRegistration; +import com.ibm.ws.jmx.connector.datatypes.ServerNotificationRegistration.Operation; + +/** + * Class used to convert JSON data for use as input and output to the JMX/REST + * connector. + *

+ * Note that the internals of this class are NOT thread safe, but the contract + * to obtain an instance is. Do not use the same instance of this class in + * multiple threads. Obtain a new instance each time an action is required + * using the following pattern: + *

{@code JSONConverter converter = JSONConverter.getConverter();}
{@code ...}
{@code JSONConverter.returnConverter(converter); } + */ +public class JSONConverter { + private static final Logger logger = Logger.getLogger(JSONConverter.class.getName()); + private static final boolean USE_BASE64_FOR_POJO = false; + private static final boolean USE_BASE64_FOR_MBEANINFO = false; + + private static DefaultSerializationHelper defaultHelper = new DefaultSerializationHelper(); + private static SerializationHelper helper = defaultHelper; + + // All supported interfaces/classes. + private static enum TYPE { + _Byte, _Short, _Integer, _Long, _Float, _Double, _Character, _Boolean, + Byte, Short, Integer, Long, Float, Double, Character, Boolean, + String, BigInteger, BigDecimal, Date, ObjectName, + + Object, + Collection, Map, + CompositeData, TabularData, + + List, Set, + ArrayList, LinkedList, Vector, + HashMap, Hashtable, TreeMap, + HashSet, + CompositeDataSupport, TabularDataSupport + } + + // Map from supported classes to Type enumeration, so that we can + // switch on the returned value. Implementations classes corresponding + // to the second half of the constants map to the base concepts: + // Collection / Map / CompositeData / TabularData. + // This map is used for writing and reading. + private static final Map, TYPE> SupportedClasses = new HashMap, TYPE>(); + static { + SupportedClasses.put(Byte.TYPE, TYPE._Byte); + SupportedClasses.put(Short.TYPE, TYPE._Short); + SupportedClasses.put(Integer.TYPE, TYPE._Integer); + SupportedClasses.put(Long.TYPE, TYPE._Long); + SupportedClasses.put(Float.TYPE, TYPE._Float); + SupportedClasses.put(Double.TYPE, TYPE._Double); + SupportedClasses.put(Character.TYPE, TYPE._Character); + SupportedClasses.put(Boolean.TYPE, TYPE._Boolean); + SupportedClasses.put(Byte.class, TYPE.Byte); + SupportedClasses.put(Short.class, TYPE.Short); + SupportedClasses.put(Integer.class, TYPE.Integer); + SupportedClasses.put(Long.class, TYPE.Long); + SupportedClasses.put(Float.class, TYPE.Float); + SupportedClasses.put(Double.class, TYPE.Double); + SupportedClasses.put(Character.class, TYPE.Character); + SupportedClasses.put(Boolean.class, TYPE.Boolean); + SupportedClasses.put(String.class, TYPE.String); + SupportedClasses.put(BigInteger.class, TYPE.BigInteger); + SupportedClasses.put(BigDecimal.class, TYPE.BigDecimal); + SupportedClasses.put(Date.class, TYPE.Date); + SupportedClasses.put(ObjectName.class, TYPE.ObjectName); + + SupportedClasses.put(Object.class, TYPE.Object); + SupportedClasses.put(Collection.class, TYPE.Collection); + SupportedClasses.put(Map.class, TYPE.Map); + SupportedClasses.put(CompositeData.class, TYPE.CompositeData); + SupportedClasses.put(TabularData.class, TYPE.TabularData); + + SupportedClasses.put(List.class, TYPE.Collection); + SupportedClasses.put(Set.class, TYPE.Collection); + SupportedClasses.put(ArrayList.class, TYPE.Collection); + SupportedClasses.put(LinkedList.class, TYPE.Collection); + SupportedClasses.put(Vector.class, TYPE.Collection); + SupportedClasses.put(HashMap.class, TYPE.Map); + SupportedClasses.put(Hashtable.class, TYPE.Map); + SupportedClasses.put(TreeMap.class, TYPE.Map); + SupportedClasses.put(HashSet.class, TYPE.Collection); + SupportedClasses.put(CompositeDataSupport.class, TYPE.CompositeData); + SupportedClasses.put(TabularDataSupport.class, TYPE.TabularData); + } + + // Set of 13 simple value classes corresponding to values that can be + // represented as Strings, hence used as keys in simple maps. + // Unlike SimpleValues, this one doesn't include java.lang.Object. + // This map is used only during writing. + private static final Set> SimpleKeys = new HashSet>(); + static { + SimpleKeys.add(Byte.class); + SimpleKeys.add(Short.class); + SimpleKeys.add(Integer.class); + SimpleKeys.add(Long.class); + SimpleKeys.add(Float.class); + SimpleKeys.add(Double.class); + SimpleKeys.add(Character.class); + SimpleKeys.add(Boolean.class); + SimpleKeys.add(String.class); + SimpleKeys.add(BigInteger.class); + SimpleKeys.add(BigDecimal.class); + SimpleKeys.add(Date.class); + SimpleKeys.add(ObjectName.class); + } + + // Set of 8 primitive, 8 corresponding built-in, and String classes. + // Array of these types can't contain instance of other classes. + private static final Set> SimpleArrays = new HashSet>(); + static { + SimpleArrays.add(Byte.TYPE); + SimpleArrays.add(Short.TYPE); + SimpleArrays.add(Integer.TYPE); + SimpleArrays.add(Long.TYPE); + SimpleArrays.add(Float.TYPE); + SimpleArrays.add(Double.TYPE); + SimpleArrays.add(Character.TYPE); + SimpleArrays.add(Boolean.TYPE); + SimpleArrays.add(Byte.class); + SimpleArrays.add(Short.class); + SimpleArrays.add(Integer.class); + SimpleArrays.add(Long.class); + SimpleArrays.add(Float.class); + SimpleArrays.add(Double.class); + SimpleArrays.add(Character.class); + SimpleArrays.add(Boolean.class); + SimpleArrays.add(String.class); + } + + // Set of 14 simple value classes corresponding to values that can be + // represented as Strings. + // This map is used only during reading. + private static final Map SimpleValues = new HashMap(); + static { + SimpleValues.put(Byte.class.getName(), TYPE.Byte); + SimpleValues.put(Short.class.getName(), TYPE.Short); + SimpleValues.put(Integer.class.getName(), TYPE.Integer); + SimpleValues.put(Long.class.getName(), TYPE.Long); + SimpleValues.put(Float.class.getName(), TYPE.Float); + SimpleValues.put(Double.class.getName(), TYPE.Double); + SimpleValues.put(Character.class.getName(), TYPE.Character); + SimpleValues.put(Boolean.class.getName(), TYPE.Boolean); + SimpleValues.put(String.class.getName(), TYPE.String); + SimpleValues.put(BigInteger.class.getName(), TYPE.BigInteger); + SimpleValues.put(BigDecimal.class.getName(), TYPE.BigDecimal); + SimpleValues.put(Date.class.getName(), TYPE.Date); + SimpleValues.put(Object.class.getName(), TYPE.Object); + SimpleValues.put(ObjectName.class.getName(), TYPE.ObjectName); + } + + // The map from class names to the simple open types. + // This map is only used during reading. + private static final Map> Name2SimpleTypes = new HashMap>(); + static { + // Don't need to worry about VOID + Name2SimpleTypes.put(Byte.class.getName(), SimpleType.BYTE); + Name2SimpleTypes.put(Short.class.getName(), SimpleType.SHORT); + Name2SimpleTypes.put(Integer.class.getName(), SimpleType.INTEGER); + Name2SimpleTypes.put(Long.class.getName(), SimpleType.LONG); + Name2SimpleTypes.put(Float.class.getName(), SimpleType.FLOAT); + Name2SimpleTypes.put(Double.class.getName(), SimpleType.DOUBLE); + Name2SimpleTypes.put(Character.class.getName(), SimpleType.CHARACTER); + Name2SimpleTypes.put(Boolean.class.getName(), SimpleType.BOOLEAN); + Name2SimpleTypes.put(String.class.getName(), SimpleType.STRING); + Name2SimpleTypes.put(BigInteger.class.getName(), SimpleType.BIGINTEGER); + Name2SimpleTypes.put(BigDecimal.class.getName(), SimpleType.BIGDECIMAL); + Name2SimpleTypes.put(Date.class.getName(), SimpleType.DATE); + Name2SimpleTypes.put(ObjectName.class.getName(), SimpleType.OBJECTNAME); + } + + // The simple open types to the type enumerations. + // This map is only used during reading. + private static final Map, TYPE> SimpleOpenTypes = new HashMap, TYPE>(); + static { + // Don't need to worry about VOID + SimpleOpenTypes.put(SimpleType.BYTE, TYPE.Byte); + SimpleOpenTypes.put(SimpleType.SHORT, TYPE.Short); + SimpleOpenTypes.put(SimpleType.INTEGER, TYPE.Integer); + SimpleOpenTypes.put(SimpleType.LONG, TYPE.Long); + SimpleOpenTypes.put(SimpleType.FLOAT, TYPE.Float); + SimpleOpenTypes.put(SimpleType.DOUBLE, TYPE.Double); + SimpleOpenTypes.put(SimpleType.CHARACTER, TYPE.Character); + SimpleOpenTypes.put(SimpleType.BOOLEAN, TYPE.Boolean); + SimpleOpenTypes.put(SimpleType.STRING, TYPE.String); + SimpleOpenTypes.put(SimpleType.BIGINTEGER, TYPE.BigInteger); + SimpleOpenTypes.put(SimpleType.BIGDECIMAL, TYPE.BigDecimal); + SimpleOpenTypes.put(SimpleType.DATE, TYPE.Date); + SimpleOpenTypes.put(SimpleType.OBJECTNAME, TYPE.ObjectName); + } + + // Map from names of complex structure classes to the type enumerations. + // This map is only used during reading. + private static final Map StructuredClasses = new HashMap(); + static { + StructuredClasses.put(ArrayList.class.getName(), TYPE.ArrayList); + StructuredClasses.put(LinkedList.class.getName(), TYPE.LinkedList); + StructuredClasses.put(Vector.class.getName(), TYPE.Vector); + StructuredClasses.put(HashMap.class.getName(), TYPE.HashMap); + StructuredClasses.put(Hashtable.class.getName(), TYPE.Hashtable); + StructuredClasses.put(TreeMap.class.getName(), TYPE.TreeMap); + StructuredClasses.put(HashSet.class.getName(), TYPE.HashSet); + StructuredClasses.put(CompositeDataSupport.class.getName(), TYPE.CompositeDataSupport); + StructuredClasses.put(TabularDataSupport.class.getName(), TYPE.TabularDataSupport); + } + + // Names of JSON object members. + private static final String N_API = "api"; + private static final byte[] OM_API = { '"', 'a', 'p', 'i', '"', ':' }; + private static final String N_ATTRIBUTENAME = "attributeName"; + private static final byte[] OM_ATTRIBUTENAME = { '"', 'a', 't', 't', 'r', 'i', 'b', 'u', 't', 'e', 'N', 'a', 'm', 'e', '"', ':' }; + private static final String N_ATTRIBUTES = "attributes"; + private static final byte[] OM_ATTRIBUTES = { '"', 'a', 't', 't', 'r', 'i', 'b', 'u', 't', 'e', 's', '"', ':' }; + private static final String N_ATTRIBUTES_URL = "attributes_URL"; + private static final byte[] OM_ATTRIBUTES_URL = { '"', 'a', 't', 't', 'r', 'i', 'b', 'u', 't', 'e', 's', '_', 'U', 'R', 'L', '"', ':' }; + private static final String N_ATTRIBUTETYPE = "attributeType"; + private static final byte[] OM_ATTRIBUTETYPE = { '"', 'a', 't', 't', 'r', 'i', 'b', 'u', 't', 'e', 'T', 'y', 'p', 'e', '"', ':' }; + private static final String N_CLASSNAME = "className"; + private static final byte[] OM_CLASSNAME = { '"', 'c', 'l', 'a', 's', 's', 'N', 'a', 'm', 'e', '"', ':' }; + private static final String N_CLIENT = "client"; + private static final byte[] OM_CLIENT = { '"', 'c', 'l', 'i', 'e', 'n', 't', '"', ':' }; + private static final String N_CONNECTIONID = "connectionId"; + private static final byte[] OM_CONNECTIONID = { '"', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', 'I', 'd', '"', ':' }; + private static final String N_CONSTRUCTORS = "constructors"; + private static final byte[] OM_CONSTRUCTORS = { '"', 'c', 'o', 'n', 's', 't', 'r', 'u', 'c', 't', 'o', 'r', 's', '"', ':' }; + private static final String N_CREATEMBEAN = "createMBean"; + private static final byte[] OM_CREATEMBEAN = { '"', 'c', 'r', 'e', 'a', 't', 'e', 'M', 'B', 'e', 'a', 'n', '"', ':' }; + private static final String N_DEFAULTDOMAIN = "defaultDomain"; + private static final byte[] OM_DEFAULTDOMAIN = { '"', 'd', 'e', 'f', 'a', 'u', 'l', 't', 'D', 'o', 'm', 'a', 'i', 'n', '"', ':' }; + private static final String N_DELIVERYINTERVAL = "deliveryInterval"; + private static final byte[] OM_DELIVERYINTERVAL = { '"', 'd', 'e', 'l', 'i', 'v', 'e', 'r', 'y', 'I', 'n', 't', 'e', 'r', 'v', 'a', 'l', '"', ':' }; + private static final String N_DESCRIPTION = "description"; + private static final byte[] OM_DESCRIPTION = { '"', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', '"', ':' }; + private static final String N_DESCRIPTOR = "descriptor"; + private static final byte[] OM_DESCRIPTOR = { '"', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', '"', ':' }; + private static final String N_DIMENSION = "dimension"; + private static final byte[] OM_DIMENSION = { '"', 'd', 'i', 'm', 'e', 'n', 's', 'i', 'o', 'n', '"', ':' }; + private static final String N_DISABLED = "disabled"; + private static final byte[] OM_DISABLED = { '"', 'd', 'i', 's', 'a', 'b', 'l', 'e', 'd', '"', ':' }; + private static final String N_DOMAINS = "domains"; + private static final byte[] OM_DOMAINS = { '"', 'd', 'o', 'm', 'a', 'i', 'n', 's', '"', ':' }; + private static final String N_ELEMENTTYPE = "elementType"; + private static final byte[] OM_ELEMENTTYPE = { '"', 'e', 'l', 'e', 'm', 'e', 'n', 't', 'T', 'y', 'p', 'e', '"', ':' }; + private static final String N_ENABLED = "enabled"; + private static final byte[] OM_ENABLED = { '"', 'e', 'n', 'a', 'b', 'l', 'e', 'd', '"', ':' }; + private static final String N_ENTRIES = "entries"; + private static final byte[] OM_ENTRIES = { '"', 'e', 'n', 't', 'r', 'i', 'e', 's', '"', ':' }; + private static final String N_FILE_TRANSFER = "fileTransfer"; + private static final byte[] OM_FILE_TRANSFER = { '"', 'f', 'i', 'l', 'e', 'T', 'r', 'a', 'n', 's', 'f', 'e', 'r', '"', ':' }; + private static final String N_FILTER = "filter"; + private static final byte[] OM_FILTER = { '"', 'f', 'i', 'l', 't', 'e', 'r', '"', ':' }; + private static final String N_FILTERID = "filterID"; + private static final byte[] OM_FILTERID = { '"', 'f', 'i', 'l', 't', 'e', 'r', 'I', 'D', '"', ':' }; + private static final String N_FILTERS = "filters"; + private static final byte[] OM_FILTERS = { '"', 'f', 'i', 'l', 't', 'e', 'r', 's', '"', ':' }; + private static final String N_GRAPH = "graph"; + private static final byte[] OM_GRAPH = { '"', 'g', 'r', 'a', 'p', 'h', '"', ':' }; + private static final String N_HANDBACK = "handback"; + private static final byte[] OM_HANDBACK = { '"', 'h', 'a', 'n', 'd', 'b', 'a', 'c', 'k', '"', ':' }; + private static final String N_HANDBACKID = "handbackID"; + private static final byte[] OM_HANDBACKID = { '"', 'h', 'a', 'n', 'd', 'b', 'a', 'c', 'k', 'I', 'D', '"', ':' }; + private static final String N_HOSTNAME = "hostName"; + private static final byte[] OM_HOSTNAME = { '"', 'h', 'o', 's', 't', 'N', 'a', 'm', 'e', '"', ':' }; + private static final String N_IMPACT = "impact"; + private static final byte[] OM_IMPACT = { '"', 'i', 'm', 'p', 'a', 'c', 't', '"', ':' }; + private static final String N_INBOX = "inbox"; + private static final byte[] OM_INBOX = { '"', 'i', 'n', 'b', 'o', 'x', '"', ':' }; + private static final String N_INBOXEXPIRY = "inboxExpiry"; + private static final byte[] OM_INBOXEXPIRTY = { '"', 'i', 'n', 'b', 'o', 'x', 'E', 'x', 'p', 'i', 'r', 'y', '"', ':' }; + private static final String N_INDEXNAMES = "indexNames"; + private static final byte[] OM_INDEXNAMES = { '"', 'i', 'n', 'd', 'e', 'x', 'N', 'a', 'm', 'e', 's', '"', ':' }; + private static final String N_INSTANCEOF = "instanceOf"; + private static final byte[] OM_INSTANCEOF = { '"', 'i', 'n', 's', 't', 'a', 'n', 'c', 'e', 'O', 'f', '"', ':' }; + private static final String N_ISIS = "isIs"; + private static final byte[] OM_ISIS = { '"', 'i', 's', 'I', 's', '"', ':' }; + private static final String N_ISREADABLE = "isReadable"; + private static final byte[] OM_ISREADABLE = { '"', 'i', 's', 'R', 'e', 'a', 'd', 'a', 'b', 'l', 'e', '"', ':' }; + private static final String N_ISWRITABLE = "isWritable"; + private static final byte[] OM_ISWRITABLE = { '"', 'i', 's', 'W', 'r', 'i', 't', 'a', 'b', 'l', 'e', '"', ':' }; + private static final String N_ITEMS = "items"; + private static final byte[] OM_ITEMS = { '"', 'i', 't', 'e', 'm', 's', '"', ':' }; + private static final String N_LISTENER = "listener"; + private static final byte[] OM_LISTENER = { '"', 'l', 'i', 's', 't', 'e', 'n', 'e', 'r', '"', ':' }; + private static final String N_LOADERNAME = "loaderName"; + private static final byte[] OM_LOADERNAME = { '"', 'l', 'o', 'a', 'd', 'e', 'r', 'N', 'a', 'm', 'e', '"', ':' }; + private static final String N_KEY = "key"; + private static final byte[] OM_KEY = { '"', 'k', 'e', 'y', '"', ':' }; + private static final String N_KEYTYPE = "keyType"; + private static final byte[] OM_KEYTYPE = { '"', 'k', 'e', 'y', 'T', 'y', 'p', 'e', '"', ':' }; + private static final String N_MBEANCOUNT = "mbeanCount"; + private static final byte[] OM_MBEANCOUNT = { '"', 'm', 'b', 'e', 'a', 'n', 'C', 'o', 'u', 'n', 't', '"', ':' }; + private static final String N_MBEANNAME = "mbeanName"; + private static final byte[] OM_MBEANNAME = { '"', 'm', 'b', 'e', 'a', 'n', 'N', 'a', 'm', 'e', '"', ':' }; + private static final String N_MBEANS = "mbeans"; + private static final byte[] OM_MBEANS = { '"', 'm', 'b', 'e', 'a', 'n', 's', '"', ':' }; + private static final String N_MBEANSTOUNREGISTER = "mbeansToUnregister"; + private static final byte[] OM_MBEANSTOUNREGISTER = { '"', 'm', 'b', 'e', 'a', 'n', 's', 'T', 'o', 'U', 'n', 'r', 'e', 'g', 'i', 's', 't', 'e', 'r', '"', ':' }; + private static final String N_MESSAGE = "message"; + private static final byte[] OM_MESSAGE = { '"', 'm', 'e', 's', 's', 'a', 'g', 'e', '"', ':' }; + private static final String N_NAME = "name"; + private static final byte[] OM_NAME = { '"', 'n', 'a', 'm', 'e', '"', ':' }; + private static final String N_NAMES = "names"; + private static final byte[] OM_NAMES = { '"', 'n', 'a', 'm', 'e', 's', '"', ':' }; + private static final String N_NEWROLEVALUE = "newRoleValue"; + private static final byte[] OM_NEWROLEVALUE = { '"', 'n', 'e', 'w', 'R', 'o', 'l', 'e', 'V', 'a', 'l', 'u', 'e', '"', ':' }; + private static final String N_NEWVALUE = "newValue"; + private static final byte[] OM_NEWVALUE = { '"', 'n', 'e', 'w', 'V', 'a', 'l', 'u', 'e', '"', ':' }; + private static final String N_NOTIFICATIONID = "notificationID"; + private static final byte[] OM_NOTIFICATIONID = { '"', 'n', 'o', 't', 'i', 'f', 'i', 'c', 'a', 't', 'i', 'o', 'n', 'I', 'D', '"', ':' }; + private static final String N_NOTIFICATIONS = "notifications"; + private static final byte[] OM_NOTIFICATIONS = { '"', 'n', 'o', 't', 'i', 'f', 'i', 'c', 'a', 't', 'i', 'o', 'n', 's', '"', ':' }; + private static final String N_NOTIFTYPES = "notifTypes"; + private static final byte[] OM_NOTIFTYPES = { '"', 'n', 'o', 't', 'i', 'f', 'T', 'y', 'p', 'e', 's', '"', ':' }; + private static final String N_OBJECTNAME = "objectName"; + private static final byte[] OM_OBJECTNAME = { '"', 'o', 'b', 'j', 'e', 'c', 't', 'N', 'a', 'm', 'e', '"', ':' }; + private static final String N_OLDROLEVALUE = "oldRoleValue"; + private static final byte[] OM_OLDROLEVALUE = { '"', 'o', 'l', 'd', 'R', 'o', 'l', 'e', 'V', 'a', 'l', 'u', 'e', '"', ':' }; + private static final String N_OLDVALUE = "oldValue"; + private static final byte[] OM_OLDVALUE = { '"', 'o', 'l', 'd', 'V', 'a', 'l', 'u', 'e', '"', ':' }; + private static final String N_OPENTYPE = "openType"; + private static final byte[] OM_OPENTYPE = { '"', 'o', 'p', 'e', 'n', 'T', 'y', 'p', 'e', '"', ':' }; + private static final String N_OPENTYPECLASS = "openTypeClass"; + private static final byte[] OM_OPENTYPECLASS = { '"', 'o', 'p', 'e', 'n', 'T', 'y', 'p', 'e', 'C', 'l', 'a', 's', 's', '"', ':' }; + private static final String N_OPENTYPES = "openTypes"; + private static final byte[] OM_OPENTYPES = { '"', 'o', 'p', 'e', 'n', 'T', 'y', 'p', 'e', 's', '"', ':' }; + private static final String N_OPERATION = "operation"; + private static final byte[] OM_OPERATION = { '"', 'o', 'p', 'e', 'r', 'a', 't', 'i', 'o', 'n', '"', ':' }; + private static final String N_OPERATIONS = "operations"; + private static final byte[] OM_OPERATIONS = { '"', 'o', 'p', 'e', 'r', 'a', 't', 'i', 'o', 'n', 's', '"', ':' }; + private static final String N_PARAMS = "params"; + private static final byte[] OM_PARAMS = { '"', 'p', 'a', 'r', 'a', 'm', 's', '"', ':' }; + private static final String N_QUERYEXP = "queryExp"; + private static final byte[] OM_QUERYEXP = { '"', 'q', 'u', 'e', 'r', 'y', 'E', 'x', 'p', '"', ':' }; + private static final String N_REGISTRATIONS = "registrations"; + private static final byte[] OM_REGISTRATIONS = { '"', 'r', 'e', 'g', 'i', 's', 't', 'r', 'a', 't', 'i', 'o', 'n', 's', '"', ':' }; + private static final String N_RELATIONID = "relationId"; + private static final byte[] OM_RELATIONID = { '"', 'r', 'e', 'l', 'a', 't', 'i', 'o', 'n', 'I', 'd', '"', ':' }; + private static final String N_RELATIONTYPENAME = "relationTypeName"; + private static final byte[] OM_RELATIONTYPENAME = { '"', 'r', 'e', 'l', 'a', 't', 'i', 'o', 'n', 'T', 'y', 'p', 'e', 'N', 'a', 'm', 'e', '"', ':' }; + private static final String N_RETURNTYPE = "returnType"; + private static final byte[] OM_RETURNTYPE = { '"', 'r', 'e', 't', 'u', 'r', 'n', 'T', 'y', 'p', 'e', '"', ':' }; + private static final String N_ROLENAME = "roleName"; + private static final byte[] OM_ROLENAME = { '"', 'r', 'o', 'l', 'e', 'N', 'a', 'm', 'e', '"', ':' }; + private static final String N_ROWTYPE = "rowType"; + private static final byte[] OM_ROWTYPE = { '"', 'r', 'o', 'w', 'T', 'y', 'p', 'e', '"', ':' }; + private static final String N_SEQUENCENUMBER = "sequenceNumber"; + private static final byte[] OM_SEQUENCENUMBER = { '"', 's', 'e', 'q', 'u', 'e', 'n', 'c', 'e', 'N', 'u', 'm', 'b', 'e', 'r', '"', ':' }; + private static final String N_SERIALIZED = "serialized"; + private static final byte[] OM_SERIALIZED = { '"', 's', 'e', 'r', 'i', 'a', 'l', 'i', 'z', 'e', 'd', '"', ':' }; + private static final String N_SERVERNAME = "serverName"; + private static final byte[] OM_SERVERNAME = { '"', 's', 'e', 'r', 'v', 'e', 'r', 'N', 'a', 'm', 'e', '"', ':' }; + private static final String N_SERVERREGISTRATIONS = "serverRegistrations"; + private static final byte[] OM_SERVERREGISTRATIONS = { '"', 's', 'e', 'r', 'v', 'e', 'r', 'R', 'e', 'g', 'i', 's', 't', 'r', 'a', 't', 'i', 'o', 'n', 's', '"', ':' }; + private static final String N_SERVERUSERDIR = "serverUserDir"; + private static final byte[] OM_SERVERUSERDIR = { '"', 's', 'e', 'r', 'v', 'e', 'r', 'U', 's', 'e', 'r', 'D', 'i', 'r', '"', ':' }; + private static final String N_SIGNATURE = "signature"; + private static final byte[] OM_SIGNATURE = { '"', 's', 'i', 'g', 'n', 'a', 't', 'u', 'r', 'e', '"', ':' }; + private static final String N_SIMPLEKEY = "simpleKey"; + private static final byte[] OM_SIMPLEKEY = { '"', 's', 'i', 'm', 'p', 'l', 'e', 'K', 'e', 'y', '"', ':' }; + private static final String N_SOURCE = "source"; + private static final byte[] OM_SOURCE = { '"', 's', 'o', 'u', 'r', 'c', 'e', '"', ':' }; + // "stacktrace" is not read by the Java client. + // private static final String N_STACKTRACE = "stackTrace"; + private static final byte[] OM_STACKTRACE = { '"', 's', 't', 'a', 'c', 'k', 'T', 'r', 'a', 'c', 'e', '"', ':' }; + private static final String N_THROWABLE = "throwable"; + private static final byte[] OM_THROWABLE = { '"', 't', 'h', 'r', 'o', 'w', 'a', 'b', 'l', 'e', '"', ':' }; + private static final String N_TIMESTAMP = "timeStamp"; + private static final byte[] OM_TIMESTAMP = { '"', 't', 'i', 'm', 'e', 'S', 't', 'a', 'm', 'p', '"', ':' }; + private static final String N_TYPE = "type"; + private static final byte[] OM_TYPE = { '"', 't', 'y', 'p', 'e', '"', ':' }; + private static final String N_TYPENAME = "typeName"; + private static final byte[] OM_TYPENAME = { '"', 't', 'y', 'p', 'e', 'N', 'a', 'm', 'e', '"', ':' }; + private static final String N_TYPES = "types"; + private static final byte[] OM_TYPES = { '"', 't', 'y', 'p', 'e', 's', '"', ':' }; + private static final String N_URL = "URL"; + private static final byte[] OM_URL = { '"', 'U', 'R', 'L', '"', ':' }; + private static final String N_USELOADER = "useLoader"; + private static final byte[] OM_USELOADER = { '"', 'u', 's', 'e', 'L', 'o', 'a', 'd', 'e', 'r', '"', ':' }; + private static final String N_USERDATA = "userData"; + private static final byte[] OM_USERDATA = { '"', 'u', 's', 'e', 'r', 'D', 'a', 't', 'a', '"', ':' }; + private static final String N_USESIGNATURE = "useSignature"; + private static final byte[] OM_USESIGNATURE = { '"', 'u', 's', 'e', 'S', 'i', 'g', 'n', 'a', 't', 'u', 'r', 'e', '"', ':' }; + private static final String N_VALUE = "value"; + private static final byte[] OM_VALUE = { '"', 'v', 'a', 'l', 'u', 'e', '"', ':' }; + private static final String N_VALUES = "values"; + private static final byte[] OM_VALUES = { '"', 'v', 'a', 'l', 'u', 'e', 's', '"', ':' }; + private static final String N_VERSION = "version"; + private static final byte[] OM_VERSION = { '"', 'v', 'e', 'r', 's', 'i', 'o', 'n', '"', ':' }; + + private static final byte[] LONG_MIN = { '-', '9', '2', '2', '3', '3', '7', + '2', '0', '3', '6', '8', '5', '4', + '7', '7', '5', '8', '0', '8' }; + private static final byte[] INT_MIN = { '-', '2', '1', '4', '7', '4', '8', + '3', '6', '4', '8' }; + private static final byte[] TRUE = { 't', 'r', 'u', 'e' }; + private static final byte[] FALSE = { 'f', 'a', 'l', 's', 'e' }; + private static final byte[] NULL = { 'n', 'u', 'l', 'l' }; + private static final Object OBJECT = new Object(); + + // Maps used by base64 encoding/decoding + private static final byte[] BASE64 = new byte[64]; + private static final byte[] BASE64_D = new byte[128]; + static { + for (int i = 0; i < 128; i++) { + BASE64_D[i] = -1; + } + for (byte i = 0; i < 26; i++) { + BASE64[i] = (byte) (i + 'A'); + BASE64_D[i + 'A'] = i; + } + for (int i = 0; i < 26; i++) { + BASE64[i + 26] = (byte) (i + 'a'); + BASE64_D[i + 'a'] = (byte) (i + 26); + } + for (int i = 0; i < 10; i++) { + BASE64[i + 52] = (byte) (i + '0'); + BASE64_D[i + '0'] = (byte) (i + 52); + } + BASE64[62] = '+'; + BASE64[63] = '/'; + BASE64_D['+'] = 62; + BASE64_D['/'] = 63; + BASE64_D['='] = 0; + } + + // Pool of converters, used by the server. + private static final Stack POOL = new Stack(); + + // Byte buffer for writing integers and encoding base64 values. + // Make sure the buffer is long enough to hold LONG_MIN, and is divisible + // by 3, for base64 encoding. + private final byte[] BYTE_BUFFER = new byte[LONG_MIN.length / 3 * 3 + 3]; + + // Whether the next array/object item is the first. If not, need to write ','. + private boolean firstItem; + + // ByteArrayOutputStream used for encoding String to base64 + private final ByteArrayOutputStream byteArrayOS = new ByteArrayOutputStream(); + + // Base64OutputStream used to base64 encoding its content + private final Base64OutputStream base64Stream = new Base64OutputStream(); + + // Class for providing base64 encoding capability to an OutputStream + private class Base64OutputStream extends OutputStream { + private OutputStream out; + private int count; + + private void start(OutputStream out) { + this.out = out; + this.count = 0; + } + + @Override + public void write(int b) throws IOException { + // If the buffer is already full, base64-encode it. + // The size is divisible by 3, so no padding is done. + if (count == BYTE_BUFFER.length) { + encodeBase64(); + count = 0; + } + BYTE_BUFFER[count++] = (byte) b; + } + + @Override + public void write(byte b[], int off, int len) throws IOException { + int left = BYTE_BUFFER.length - count; + // If we have more than what the buffer can hold + while (len > left) { + // Fill the buffer and base64 encode it + // The size is divisible by 3, so no padding is done. + System.arraycopy(b, off, BYTE_BUFFER, count, left); + count = BYTE_BUFFER.length; + encodeBase64(); + len -= left; + off += left; + left = BYTE_BUFFER.length; + } + // Copy the rest into the buffer + System.arraycopy(b, off, BYTE_BUFFER, count, len); + count += len; + } + + @Override + public void flush() throws IOException { + // Encode and write out any pending bytes + if (count > 0) { + encodeBase64(); + } + } + + private void end() throws IOException { + flush(); + out = null; + } + + private void encodeBase64() throws IOException { + final int left = count % 3; + int pos = 0, b1, b2, b3; + // For every 3-byte sequence + for (; pos < count - left;) { + b1 = BYTE_BUFFER[pos++]; + b2 = BYTE_BUFFER[pos++]; + b3 = BYTE_BUFFER[pos++]; + // Write out 4 bytes + out.write(BASE64[(b1 >> 2) & 0x3f]); + out.write(BASE64[((b1 & 0x3) << 4) | ((b2 >> 4) & 0xf)]); + out.write(BASE64[((b2 & 0xf) << 2) | ((b3 >> 6) & 0x3)]); + out.write(BASE64[b3 & 0x3f]); + } + // 1 byte is left. Need 2 padding chars '==' + if (left == 1) { + b1 = BYTE_BUFFER[pos]; + out.write(BASE64[(b1 >> 2) & 0x3f]); + out.write(BASE64[(b1 & 0x3) << 4]); + out.write('='); + out.write('='); + } + // 2 bytes are left. Need 1 padding char '=' + else if (left == 2) { + b1 = BYTE_BUFFER[pos++]; + b2 = BYTE_BUFFER[pos++]; + out.write(BASE64[(b1 >> 2) & 0x3f]); + out.write(BASE64[((b1 & 0x3) << 4) | ((b2 >> 4) & 0xf)]); + out.write(BASE64[(b2 & 0xf) << 2]); + out.write('='); + } + count = 0; + } + } + + /** + * Retrieve an instance of the JSON converter. When the converter is no + * longer needed, it can be returned to a global pool for reuse, by + * calling {@link #returnConverter(JSONConverter)}. + * + * @return an instance of the JSONConverter. {@code null} is not returned. + */ + public static JSONConverter getConverter() { + synchronized (POOL) { + if (!POOL.empty()) { + return POOL.pop(); + } + } + return new JSONConverter(); + } + + /** + * Returns the JSONConverter instance to the global pool for reuse later. + * + * @param converter the JSONConverter to return. {@code null} is not supported. + */ + public static void returnConverter(JSONConverter converter) { + if (!POOL.contains(converter)) + POOL.push(converter); + } + + // Use getConverter() + private JSONConverter() {} + + /** + * Encode an integer value as JSON. An array is used to wrap the value: + * [ Integer ] + * + * @param out The stream to write JSON to + * @param value The integer value to encode + * @throws IOException If an I/O error occurs + * @see #readInt(InputStream) + */ + public void writeInt(OutputStream out, int value) throws IOException { + writeStartArray(out); + writeIntInternal(out, value); + writeEndArray(out); + } + + /** + * Decode a JSON document to retrieve an integer value. + * + * @param in The stream to read JSON from + * @return The decoded integer value + * @throws ConversionException If JSON uses unexpected structure/format + * @throws IOException If an I/O error occurs or if JSON is ill-formed. + * @see #writeInt(OutputStream, int) + */ + public int readInt(InputStream in) throws ConversionException, IOException { + JSONArray json = parseArray(in); + if (json.size() != 1) { + throwConversionException("readInt() expects one item in the array: [ Integer ].", json); + } + return readIntInternal(json.get(0)); + } + + /** + * Encode a boolean value as JSON. An array is used to wrap the value: + * [ true | false ] + * + * @param out The stream to write JSON to + * @param value The boolean value to encode + * @throws IOException If an I/O error occurs + * @see #readBoolean(InputStream) + */ + public void writeBoolean(OutputStream out, boolean value) throws IOException { + writeStartArray(out); + writeBooleanInternal(out, value); + writeEndArray(out); + } + + /** + * Decode a JSON document to retrieve an boolean value. + * + * @param in The stream to read JSON from + * @return The decoded boolean value + * @throws ConversionException If JSON uses unexpected structure/format + * @throws IOException If an I/O error occurs or if JSON is ill-formed. + * @see #writeInt(OutputStream, int) + */ + public boolean readBoolean(InputStream in) throws ConversionException, IOException { + JSONArray json = parseArray(in); + if (json.size() != 1) { + throwConversionException("readBoolean() expects one item in the array: [ true | false ].", json); + } + return readBooleanInternal(json.get(0)); + } + + /** + * Encode a String value as JSON. An array is used to wrap the value: + * [ String ] + * + * @param out The stream to write JSON to + * @param value The String value to encode. + * @throws IOException If an I/O error occurs + * @see #readString(InputStream) + */ + public void writeString(OutputStream out, String value) throws IOException { + writeStartArray(out); + writeStringInternal(out, value); + writeEndArray(out); + } + + /** + * Decode a JSON document to retrieve a String value. + * + * @param in The stream to read JSON from + * @return The decoded String value + * @throws ConversionException If JSON uses unexpected structure/format + * @throws IOException If an I/O error occurs or if JSON is ill-formed. + * @see #writeString(OutputStream, String) + */ + public String readString(InputStream in) throws ConversionException, IOException { + JSONArray json = parseArray(in); + if (json.size() != 1) { + throwConversionException("readString() expects one item in the array: [ String ].", json); + } + return readStringInternal(json.get(0)); + } + + /** + * Encode a String array as JSON: + * [ String* ] + * + * @param out The stream to write JSON to + * @param value The String array to encode. Can't be null. + * @throws IOException If an I/O error occurs + */ + public void writeStringArray(OutputStream out, String[] value) throws IOException { + writeStringArrayInternal(out, value); + } + + /** + * Decode a JSON document to retrieve a String array. + * + * @param in The stream to read JSON from + * @return The decoded String array + * @throws ConversionException If JSON uses unexpected structure/format + * @throws IOException If an I/O error occurs or if JSON is ill-formed. + * @see #writeStringArray(OutputStream, String[]) + */ + public String[] readStringArray(InputStream in) throws ConversionException, IOException { + return readStringArrayInternal(parse(in)); + } + + /** + * Encode an Object as JSON. + * + * Format: + * + * { + * serialized: Base64, ? // If object has cyclic references. Otherwise use the following fields instead. + * value: Value, ? + * type: Type, ? + * openTypes: [ OpenType * ], ? // Only if open types are used + * } + * + * *** Value *** + * + * 1. For "null" value, or a value that's not expressible in JSON + * + * null + * + * 2. For a simple value (primitive, String, BigInteger/Decimal, Date, + * ObjectName), or Object. For Object, "" is used. + * + * String + * + * 3. For array or collection + * + * [ Value* ] + * + * 4. For map where all keys are simple values + * + * { + * String: Value * + * } + * + * 5. For map with complex keys + * + * [ {key: Value, value: Value}* ] + * + * 6. For CompositeData + * + * { + * String: Value * + * } + * + * 7. and TabularData + * + * [ CompositeData* ] + * + * *** Type *** + * + * 1. For "null" value + * + * null + * + * 2. For a simple value, arrays of primitives or final simple values, + * or Object. For Object, "" is used. + * + * String // The class name + * + * 3. Otherwise + * + * { + * class: String, // Class name of the object + * serialized: Base64 ? // Optional: If the class is not supported. The java serialization of the value. + * } + * + * The following additional fields apply depending on the kind of value. + * + * 3.1 For complex array or collection classes: + * + * { + * items: [ Type* ] + * } + * + * 3.4 For maps + * + * { + * simpleKey: boolean, // Whether all keys are simple. Then each entry has a "key" field. + * entries: [ + * { + * key: String, ? // For simple key + * keyType: Type, + * value: Type + * } * + * ] + * + * 3.5 For CompositeData and TabularData + * + * { + * openType: Integer // Reference to the OpenType array in root Type + * } + * + * *** OpenType *** + * + * 1. For SimpleType instances: + * + * String // The name of the simple type. + * + * 2. For all other OpenTypes: + * + * { + * openTypeClass: String, // The OpenType class. + * serialized: Base64 // Optional: If the class is not supported. The java serialization of the OpenType object. + * + * className: String, + * typeName: String, + * description: String, + * } + * + * 2.1 ArrayType + * + * { + * dimension: Integer, + * elementType: Integer, + * } + * + * 2.2 CompositeType + * + * { + * items: { String: { description: String, type: Integer } *} + * } + * + * 2.3 TabularType + * + * { + * rowType: Integer, + * indexNames: [String*] + * } + * + * @param out The stream to write JSON to + * @param value The Object to encode. Can be null. + * @throws IOException If an I/O error occurs + * @see #readPOJO(InputStream) + */ + public void writePOJO(OutputStream out, Object value) throws IOException { + writePOJOInternal(out, value); + } + + /** + * Decode a JSON document to retrieve an Object. + * + * @param in The stream to read JSON from + * @return The decoded Object + * @throws ConversionException If JSON uses unexpected structure/format + * @throws IOException If an I/O error occurs or if JSON is ill-formed. + * @throws ClassNotFoundException If needed class can't be found. + * @see #writePOJO(OutputStream, Object) + */ + public Object readPOJO(InputStream in) throws ConversionException, IOException, ClassNotFoundException { + return readPOJOInternal(parse(in)); + } + + /** + * Encode a JMX instance as JSON: + * { + * "version" : Integer, + * "mbeans" : URL, + * "createMBean" : URL, + * "mbeanCount" : URL, + * "defaultDomain" : URL, + * "domains" : URL, + * "notifications" : URL, + * "instanceOf" : URL + * } + * + * @param out The stream to write JSON to + * @param value The JMX instance to encode. Can't be null. + * @throws IOException If an I/O error occurs + * @see #readJMX(InputStream) + */ + public void writeJMX(OutputStream out, JMXServerInfo value) throws IOException { + assert value != null; + writeStartObject(out); + writeIntField(out, OM_VERSION, value.version); + writeStringField(out, OM_MBEANS, value.mbeansURL); + writeStringField(out, OM_CREATEMBEAN, value.createMBeanURL); + writeStringField(out, OM_MBEANCOUNT, value.mbeanCountURL); + writeStringField(out, OM_DEFAULTDOMAIN, value.defaultDomainURL); + writeStringField(out, OM_DOMAINS, value.domainsURL); + writeStringField(out, OM_NOTIFICATIONS, value.notificationsURL); + writeStringField(out, OM_INSTANCEOF, value.instanceOfURL); + writeStringField(out, OM_FILE_TRANSFER, value.fileTransferURL); + writeStringField(out, OM_API, value.apiURL); + writeStringField(out, OM_GRAPH, value.graphURL); + writeEndObject(out); + } + + /** + * Decode a JSON document to retrieve a JMX instance. + * + * @param in The stream to read JSON from + * @return The decoded JMX instance + * @throws ConversionException If JSON uses unexpected structure/format + * @throws IOException If an I/O error occurs or if JSON is ill-formed. + * @see #writeJMX(OutputStream, JMXServerInfo) + */ + public JMXServerInfo readJMX(InputStream in) throws ConversionException, IOException { + JSONObject json = parseObject(in); + JMXServerInfo ret = new JMXServerInfo(); + ret.version = readIntInternal(json.get(N_VERSION)); + ret.mbeansURL = readStringInternal(json.get(N_MBEANS)); + ret.createMBeanURL = readStringInternal(json.get(N_CREATEMBEAN)); + ret.mbeanCountURL = readStringInternal(json.get(N_MBEANCOUNT)); + ret.defaultDomainURL = readStringInternal(json.get(N_DEFAULTDOMAIN)); + ret.domainsURL = readStringInternal(json.get(N_DOMAINS)); + ret.notificationsURL = readStringInternal(json.get(N_NOTIFICATIONS)); + ret.instanceOfURL = readStringInternal(json.get(N_INSTANCEOF)); + ret.fileTransferURL = readStringInternal(json.get(N_FILE_TRANSFER)); + ret.apiURL = readStringInternal(json.get(N_API)); + ret.graphURL = readStringInternal(json.get(N_GRAPH)); + return ret; + } + + /** + * Encode an ObjectInstanceWrapper instance as JSON: + * { + * "objectName" : ObjectName, + * "className" : String, + * "URL" : URL, + * } + * + * @param out The stream to write JSON to + * @param value The ObjectInstanceWrapper instance to encode. + * The value and value.objectInstance can't be null. + * @throws IOException If an I/O error occurs + * @see #readObjectInstance(InputStream) + */ + public void writeObjectInstance(OutputStream out, ObjectInstanceWrapper value) throws IOException { + // ObjectInstance has no known sub-class. + assert value != null && value.objectInstance != null; + writeStartObject(out); + writeObjectNameField(out, OM_OBJECTNAME, value.objectInstance.getObjectName()); + writeStringField(out, OM_CLASSNAME, value.objectInstance.getClassName()); + writeStringField(out, OM_URL, value.mbeanInfoURL); + writeEndObject(out); + } + + /** + * Decode a JSON document to retrieve an ObjectInstanceWrapper instance. + * + * @param in The stream to read JSON from + * @return The decoded ObjectInstanceWrapper instance + * @throws ConversionException If JSON uses unexpected structure/format + * @throws IOException If an I/O error occurs or if JSON is ill-formed. + * @see #writeObjectInstance(OutputStream, ObjectInstanceWrapper) + */ + public ObjectInstanceWrapper readObjectInstance(InputStream in) throws ConversionException, IOException { + return readObjectInstanceInternal(parse(in)); + } + + /** + * Encode an ObjectInstanceWrapper array as JSON: + * [ ObjectInstanceWrapper* ] + * + * @param out The stream to write JSON to + * @param value The ObjectInstanceWrapper array to encode. Can't be null. + * And none of its entries can be null. + * @throws IOException If an I/O error occurs + * @see #readObjectInstances(InputStream) + * @see #writeObjectInstance(OutputStream, ObjectInstanceWrapper) + */ + public void writeObjectInstanceArray(OutputStream out, ObjectInstanceWrapper[] value) throws IOException { + assert value != null; + writeStartArray(out); + for (ObjectInstanceWrapper item : value) { + writeArrayItem(out); + writeObjectInstance(out, item); + } + writeEndArray(out); + } + + /** + * Decode a JSON document to retrieve an ObjectInstanceWrapper array. + * + * @param in The stream to read JSON from + * @return The decoded ObjectInstanceWrapper array + * @throws ConversionException If JSON uses unexpected structure/format + * @throws IOException If an I/O error occurs or if JSON is ill-formed. + * @see #writeObjectInstanceArray(OutputStream, ObjectInstanceWrapper[]) + * @see #readObjectInstance(InputStream) + */ + public ObjectInstanceWrapper[] readObjectInstances(InputStream in) throws ConversionException, IOException { + JSONArray json = parseArray(in); + ObjectInstanceWrapper[] ret = new ObjectInstanceWrapper[json.size()]; + int pos = 0; + for (Object item : json) { + ret[pos++] = readObjectInstanceInternal(item); + } + return ret; + } + + /** + * Encode an MBeanQuery instance as JSON: + * { + * "objectName" : ObjectName, + * "queryExp" : Base64, + * "className" : String, + * } + * + * @param out The stream to write JSON to + * @param value The MBeanQuery instance to encode. Can't be null. + * @throws IOException If an I/O error occurs + * @see #readMBeanQuery(InputStream) + */ + public void writeMBeanQuery(OutputStream out, MBeanQuery value) throws IOException { + assert value != null; + writeStartObject(out); + writeObjectNameField(out, OM_OBJECTNAME, value.objectName); + // TODO: Produce proper JSON for QueryExp? + writeSerializedField(out, OM_QUERYEXP, value.queryExp); + writeStringField(out, OM_CLASSNAME, value.className); + writeEndObject(out); + } + + /** + * Decode a JSON document to retrieve an MBeanQuery instance. + * + * @param in The stream to read JSON from + * @return The decoded MBeanQuery instance + * @throws ConversionException If JSON uses unexpected structure/format + * @throws IOException If an I/O error occurs or if JSON is ill-formed. + * @throws ClassNotFoundException If needed class can't be found. + * @see #writeMBeanQuery(OutputStream, MBeanQuery) + */ + public MBeanQuery readMBeanQuery(InputStream in) throws ConversionException, IOException, ClassNotFoundException { + JSONObject json = parseObject(in); + MBeanQuery ret = new MBeanQuery(); + ret.objectName = readObjectName(json.get(N_OBJECTNAME)); + Object queryExp = readSerialized(json.get(N_QUERYEXP)); + if (queryExp != null && !(queryExp instanceof QueryExp)) { + throwConversionException("readMBeanQuery() receives an instance that's not a QueryExp.", json.get(N_QUERYEXP)); + } + ret.queryExp = (QueryExp) queryExp; + ret.className = readStringInternal(json.get(N_CLASSNAME)); + return ret; + } + + /** + * Encode a CreateMBean instance as JSON: + * { + * "className" : String, + * "objectName" : ObjectName, + * "loaderName" : ObjectName, + * "params" : [ POJO* ], + * "signature" : [ String* ], + * "useLoader" : Boolean, + * "useSignatue" : Boolean + * } + * + * @param out The stream to write JSON to + * @param value The CreateMBean instance to encode. Can't be null. + * @throws IOException If an I/O error occurs + * @see #readCreateMBean(InputStream) + */ + public void writeCreateMBean(OutputStream out, CreateMBean value) throws IOException { + assert value != null; + writeStartObject(out); + writeStringField(out, OM_CLASSNAME, value.className); + writeObjectNameField(out, OM_OBJECTNAME, value.objectName); + writeObjectNameField(out, OM_LOADERNAME, value.loaderName); + writePOJOArrayField(out, OM_PARAMS, value.params); + writeStringArrayField(out, OM_SIGNATURE, value.signature); + writeBooleanField(out, OM_USELOADER, value.useLoader); + writeBooleanField(out, OM_USESIGNATURE, value.useSignature); + writeEndObject(out); + } + + /** + * Decode a JSON document to retrieve a CreateMBean instance. + * + * @param in The stream to read JSON from + * @return The decoded CreateMBean instance + * @throws ConversionException If JSON uses unexpected structure/format + * @throws IOException If an I/O error occurs or if JSON is ill-formed. + * @throws ClassNotFoundException If needed class can't be found. + * @see #writeCreateMBean(OutputStream, CreateMBean) + */ + public CreateMBean readCreateMBean(InputStream in) throws ConversionException, IOException, ClassNotFoundException { + JSONObject json = parseObject(in); + CreateMBean ret = new CreateMBean(); + ret.objectName = readObjectName(json.get(N_OBJECTNAME)); + ret.className = readStringInternal(json.get(N_CLASSNAME)); + ret.loaderName = readObjectName(json.get(N_LOADERNAME)); + ret.params = readPOJOArray(json.get(N_PARAMS)); + ret.signature = readStringArrayInternal(json.get(N_SIGNATURE)); + ret.useLoader = readBooleanInternal(json.get(N_USELOADER)); + ret.useSignature = readBooleanInternal(json.get(N_USESIGNATURE)); + return ret; + } + + /** + * Encode an MBeanInfoWrapper instance as JSON: + * { + * "className" : String, + * "description" : String, + * "descriptor" : Descriptor, + * "attributes" : [ MBeanAttributeInfo* ], + * "attributes_URL" : URL, + * "constructors" : [ MBeanConstructorInfo* ], + * "notifications" : [ MBeanNotificationInfo* ], + * "operations" : [ MBeanOperationInfo* ] + * } + * + * Descriptor: + * { + * "names" : [ String* ],{ + * "values" : [ POJO* ] + * } + * + * MBeanAttributeInfo: + * { + * "name" : String, + * "type" : String, + * "description" : String, + * "descriptor" : Descriptor, + * "isIs" : Boolean, + * "isReadable" : Boolean, + * "isWritable" : Boolean, + * "URL" : URL + * } + * + * MBeanConstructorInfo: + * { + * "name" : String, + * "description" : String, + * "descriptor" : Descriptor, + * "signature" : [ MBeanParameterInfo* ] + * } + * + * MBeanParameterInfo: + * { + * "name" : String, + * "type" : String, + * "description" : String, + * "descriptor" : Descriptor + * } + * + * MBeanNotificationInfo: + * { + * "name" : String, + * "description" : String, + * "descriptor" : Descriptor, + * "notifTypes" [ String* ] + * } + * + * MBeanOperationInfo: + * { + * "name" : String, + * "description" : String, + * "descriptor" : Descriptor, + * "impact" : Integer, + * "returnType" : String, + * "signature" : [ MBeanParameterInfo* ], + * "URI" : URI + * } + * + * @param out The stream to write JSON to + * @param value The MBeanInfoWrapper instance to encode. + * The value and its members can't be null. + * @throws IOException If an I/O error occurs + * @see #readMBeanInfo(InputStream) + */ + public void writeMBeanInfo(OutputStream out, MBeanInfoWrapper value) throws IOException { + // TODO: MBeanInfo has 2 sub-classes, Model*Support and Open*Support. + // How to handle them? "Open" has references to OpenTMBean*Info. + // Model has more convenience methods for retrieving individual + // items, and methods to set the descriptors. + // Same for subclasses of the various items. + assert value != null && value.mbeanInfo != null && value.attributeURLs != null && value.operationURLs != null; + writeStartObject(out); + if (USE_BASE64_FOR_MBEANINFO) { + writeSerializedField(out, OM_SERIALIZED, value.mbeanInfo); + writeStringField(out, OM_ATTRIBUTES_URL, value.attributesURL); + writeSerializedField(out, OM_ATTRIBUTES, value.attributeURLs); + writeSerializedField(out, OM_OPERATIONS, value.operationURLs); + return; + } + if (value.mbeanInfo.getClass() != MBeanInfo.class) { + writeSerializedField(out, OM_SERIALIZED, value.mbeanInfo); + } + writeStringField(out, OM_CLASSNAME, value.mbeanInfo.getClassName()); + writeStringField(out, OM_DESCRIPTION, value.mbeanInfo.getDescription()); + writeDescriptor(out, OM_DESCRIPTOR, value.mbeanInfo.getDescriptor()); + writeAttributes(out, OM_ATTRIBUTES, value.mbeanInfo.getAttributes(), value.attributeURLs); + writeStringField(out, OM_ATTRIBUTES_URL, value.attributesURL); + writeConstructors(out, OM_CONSTRUCTORS, value.mbeanInfo.getConstructors()); + writeNotifications(out, OM_NOTIFICATIONS, value.mbeanInfo.getNotifications()); + writeOperations(out, OM_OPERATIONS, value.mbeanInfo.getOperations(), value.operationURLs); + writeEndObject(out); + } + + /** + * Decode a JSON document to retrieve an MBeanInfoWrapper instance. + * + * Note that all descriptors are of class ImmutableDescriptor. + * + * @param in The stream to read JSON from + * @return The decoded MBeanInfoWrapper instance + * @throws ConversionException If JSON uses unexpected structure/format + * @throws IOException If an I/O error occurs or if JSON is ill-formed. + * @throws ClassNotFoundException If needed class can't be found. + * @see #writeMBeanInfo(OutputStream, MBeanInfoWrapper) + */ + @SuppressWarnings("unchecked") + public MBeanInfoWrapper readMBeanInfo(InputStream in) throws ConversionException, IOException, ClassNotFoundException { + JSONObject json = parseObject(in); + MBeanInfoWrapper ret = new MBeanInfoWrapper(); + if (USE_BASE64_FOR_MBEANINFO) { + Object o = readSerialized(json.get(N_SERIALIZED)); + if (!(o instanceof MBeanInfo)) { + throwConversionException("readMBeanInfo() receives an instance that's not a MBeanInfo.", json.get(N_SERIALIZED)); + } + ret.mbeanInfo = (MBeanInfo) o; + ret.attributesURL = readStringInternal(json.get(N_ATTRIBUTES_URL)); + o = readSerialized(json.get(OM_ATTRIBUTES)); + if (!(o instanceof HashMap)) { + throwConversionException("readMBeanInfo() receives an instance that's not a HashMap.", json.get(OM_ATTRIBUTES)); + } + ret.attributeURLs = (Map) o; + o = readSerialized(json.get(OM_OPERATIONS)); + if (!(o instanceof HashMap)) { + throwConversionException("readMBeanInfo() receives an instance that's not a HashMap.", json.get(OM_OPERATIONS)); + } + ret.operationURLs = (Map) o; + return ret; + } + ret.attributeURLs = new HashMap(); + ret.operationURLs = new HashMap(); + String className = readStringInternal(json.get(N_CLASSNAME)); + String description = readStringInternal(json.get(N_DESCRIPTION)); + Descriptor descriptor = readDescriptor(json.get(N_DESCRIPTOR)); + MBeanAttributeInfo[] attributes = readAttributes(json.get(N_ATTRIBUTES), ret.attributeURLs); + String attributeURL = readStringInternal(json.get(N_ATTRIBUTES_URL)); + MBeanConstructorInfo[] constructors = readConstructors(json.get(N_CONSTRUCTORS)); + MBeanNotificationInfo[] notifications = readNotifications(json.get(N_NOTIFICATIONS)); + MBeanOperationInfo[] operations = readOperations(json.get(N_OPERATIONS), ret.operationURLs); + ret.attributesURL = attributeURL; + Object o = json.get(N_SERIALIZED); + if (o != null) { + o = readSerialized(o); + if (!(o instanceof MBeanInfo)) { + throwConversionException("readMBeanInfo() receives an instance that's not a MBeanInfo.", json.get(N_SERIALIZED)); + } + ret.mbeanInfo = (MBeanInfo) o; + } else { + ret.mbeanInfo = new MBeanInfo(className, description, attributes, + constructors, operations, notifications, + descriptor); + } + return ret; + } + + /** + * Encode an AttributeList instance as JSON: + * [ { + * "name" : String, + * "value" : POJO + * }* ] + * + * @param out The stream to write JSON to + * @param value The AttributeList instance to encode. Can be null, + * but its Attribute items can't be null. + * @throws IOException If an I/O error occurs + * @see #readAttributeList(InputStream) + */ + public void writeAttributeList(OutputStream out, AttributeList value) throws IOException { + // AttributeList has no known sub-class. + writeStartArray(out); + if (value != null) { + for (Attribute item : value.asList()) { + assert item != null; + writeArrayItem(out); + writeStartObject(out); + writeStringField(out, OM_NAME, item.getName()); + writePOJOField(out, OM_VALUE, item.getValue()); + writeEndObject(out); + } + } + writeEndArray(out); + } + + /** + * Decode a JSON document to retrieve an AttributeList instance. + * + * @param in The stream to read JSON from + * @return The decoded AttributeList instance + * @throws ConversionException If JSON uses unexpected structure/format + * @throws IOException If an I/O error occurs or if JSON is ill-formed. + * @throws ClassNotFoundException If needed class can't be found. + * @see #writeAttributeList(OutputStream, AttributeList) + */ + public AttributeList readAttributeList(InputStream in) throws ConversionException, IOException, ClassNotFoundException { + JSONArray json = parseArray(in); + AttributeList ret = new AttributeList(); + for (Object item : json) { + if (!(item instanceof JSONObject)) { + throwConversionException("readAttributeList() receives an items that's not a JSONObject.", item); + } + JSONObject jo = (JSONObject) item; + String name = readStringInternal(jo.get(N_NAME)); + Object value = readPOJOInternal(jo.get(N_VALUE)); + ret.add(new Attribute(name, value)); + } + return ret; + } + + /** + * Encode an Invocation instance as JSON: + * { + * "params" : [ POJO* ], + * "signature" : [ String* ] + * } + * + * @param out The stream to write JSON to + * @param value The Invocation instance to encode. Can't be null. + * @throws IOException If an I/O error occurs + * @see #readInvocation(InputStream) + */ + public void writeInvocation(OutputStream out, Invocation value) throws IOException { + assert value != null; + writeStartObject(out); + writePOJOArrayField(out, OM_PARAMS, value.params); + writeStringArrayField(out, OM_SIGNATURE, value.signature); + writeEndObject(out); + } + + /** + * Decode a JSON document to retrieve an Invocation instance. + * + * @param in The stream to read JSON from + * @return The decoded Invocation instance + * @throws ConversionException If JSON uses unexpected structure/format + * @throws IOException If an I/O error occurs or if JSON is ill-formed. + * @throws ClassNotFoundException If needed class can't be found. + * @see #writeInvocation(OutputStream, Invocation) + */ + public Invocation readInvocation(InputStream in) throws ConversionException, IOException, ClassNotFoundException { + JSONObject json = parseObject(in); + Invocation ret = new Invocation(); + ret.params = readPOJOArray(json.get(N_PARAMS)); + ret.signature = readStringArrayInternal(json.get(N_SIGNATURE)); + return ret; + } + + /** + * Encode a NotificationArea instance as JSON: + * { + * "registrations" : URL, + * "serverRegistrations" : URL, + * "inbox" : URL + * } + * + * @param out The stream to write JSON to + * @param value The NotificationArea instance to encode. Can't be null. + * @throws IOException If an I/O error occurs + * @see #readNotificationArea(InputStream) + */ + public void writeNotificationArea(OutputStream out, NotificationArea value) throws IOException { + assert value != null; + writeStartObject(out); + writeStringField(out, OM_REGISTRATIONS, value.registrationsURL); + writeStringField(out, OM_SERVERREGISTRATIONS, value.serverRegistrationsURL); + writeStringField(out, OM_INBOX, value.inboxURL); + writeStringField(out, OM_CLIENT, value.clientURL); + writeEndObject(out); + } + + /** + * Decode a JSON document to retrieve a NotificationArea instance. + * + * @param in The stream to read JSON from + * @return The decoded NotificationArea instance + * @throws ConversionException If JSON uses unexpected structure/format + * @throws IOException If an I/O error occurs or if JSON is ill-formed. + * @see #writeNotificationArea(OutputStream, NotificationArea) + */ + public NotificationArea readNotificationArea(InputStream in) throws ConversionException, IOException { + JSONObject json = parseObject(in); + NotificationArea ret = new NotificationArea(); + ret.registrationsURL = readStringInternal(json.get(N_REGISTRATIONS)); + ret.serverRegistrationsURL = readStringInternal(json.get(N_SERVERREGISTRATIONS)); + ret.inboxURL = readStringInternal(json.get(N_INBOX)); + ret.clientURL = readStringInternal(json.get(N_CLIENT)); + return ret; + } + + /** + * Encode a NotificationRegistration instance as JSON: + * { + * "objectName" : ObjectName, + * "filters" : [ NotificationFilter* ] + * } + * + * @param out The stream to write JSON to + * @param value The NotificationRegistration instance to encode. + * Can't be null. See writeNotificationFilters() for + * requirements on the filters. + * @throws IOException If an I/O error occurs + * @see #readNotificationRegistration(InputStream) + * @see #writeNotificationFilters(OutputStream, NotificationFilter[]) + */ + public void writeNotificationRegistration(OutputStream out, NotificationRegistration value) throws IOException { + assert value != null; + writeStartObject(out); + writeObjectNameField(out, OM_OBJECTNAME, value.objectName); + writeNotificationFiltersField(out, OM_FILTERS, value.filters); + writeEndObject(out); + } + + /** + * Decode a JSON document to retrieve a NotificationRegistration instance. + * + * @param in The stream to read JSON from + * @return The decoded NotificationRegistration instance + * @throws ConversionException If JSON uses unexpected structure/format + * @throws IOException If an I/O error occurs or if JSON is ill-formed. + * @throws ClassNotFoundException If needed class can't be found. + * @see #writeNotificationRegistration(OutputStream, NotificationRegistration) + */ + public NotificationRegistration readNotificationRegistration(InputStream in) throws ConversionException, IOException, ClassNotFoundException { + JSONObject json = parseObject(in); + NotificationRegistration ret = new NotificationRegistration(); + ret.objectName = readObjectName(json.get(N_OBJECTNAME)); + ret.filters = readNotificationFiltersInternal(json.get(N_FILTERS)); + return ret; + } + + /** + * Encode a ServerNotificationRegistration instance as JSON: + * { + * "operation" : ("Add" | "RemoveAll" | "RemoveSpecific") + * "objectName" : ObjectName, + * "listener" : ObjectName, + * "filter" : NotificationFilter, + * "handback" : POJO, + * "filterID" : Integer, + * "handbackID" : Integer + * } + * + * @param out The stream to write JSON to + * @param value The ServerNotificationRegistration instance to encode. + * Can't be null. + * @throws IOException If an I/O error occurs + * @see #readServerNotificationRegistration(InputStream) + */ + public void writeServerNotificationRegistration(OutputStream out, ServerNotificationRegistration value) throws IOException { + assert value != null; + writeStartObject(out); + boolean hasOperation = value.operation != null; + if (hasOperation) { + writeSimpleStringField(out, OM_OPERATION, value.operation.name()); + } + writeObjectNameField(out, OM_OBJECTNAME, value.objectName); + writeObjectNameField(out, OM_LISTENER, value.listener); + writeNotificationFilterField(out, OM_FILTER, value.filter); + writePOJOField(out, OM_HANDBACK, value.handback); + if (hasOperation) { + writeIntField(out, OM_FILTERID, value.filterID); + writeIntField(out, OM_HANDBACKID, value.handbackID); + } + writeEndObject(out); + } + + /** + * Decode a JSON document to retrieve a ServerNotificationRegistration instance. + * + * @param in The stream to read JSON from + * @return The decoded ServerNotificationRegistration instance + * @throws ConversionException If JSON uses unexpected structure/format + * @throws IOException If an I/O error occurs or if JSON is ill-formed. + * @throws ClassNotFoundException If needed class can't be found. + * @see #writeServerNotificationRegistration(OutputStream, ServerNotificationRegistration) + */ + public ServerNotificationRegistration readServerNotificationRegistration(InputStream in) throws ConversionException, IOException, ClassNotFoundException { + JSONObject json = parseObject(in); + ServerNotificationRegistration ret = new ServerNotificationRegistration(); + String name = readStringInternal(json.get(N_OPERATION)); + ret.operation = name != null ? Operation.valueOf(name) : null; + ret.objectName = readObjectName(json.get(N_OBJECTNAME)); + ret.listener = readObjectName(json.get(N_LISTENER)); + ret.filter = readNotificationFilterInternal(json.get(N_FILTER), true); + ret.handback = readPOJOInternal(json.get(N_HANDBACK)); + ret.filterID = readIntInternal(json.get(N_FILTERID)); + ret.handbackID = readIntInternal(json.get(N_HANDBACKID)); + return ret; + } + + /** + * Check if a NotificationFilter is a standard filter that can be + * send to a JMX server. + * + * @param filter The filter to check. Can't be null. + * @return Whether the filter is a standard one + */ + public boolean isSupportedNotificationFilter(NotificationFilter filter) { + Class clazz = filter.getClass(); + return clazz == AttributeChangeNotificationFilter.class || + clazz == MBeanServerNotificationFilter.class || + clazz == NotificationFilterSupport.class; + } + + /** + * Encode a NotificationFilter array as JSON: + * [ NotificationFilter* ] + * + * Format of NotificationFilter: + * { + * className: "AttributeChangeNotificationFilter" | "MBeanServerNotificationFilter" | "NotificationFilterSupport", + * enabled: [ String* ], // For AttributeChangeNotificationFilter and MBeanServerNotificationFilter + * disabled: [ String* ], // For MBeanServerNotificationFilter + * types: [ String* ], // For MBeanServerNotificationFilter and NotificationFilterSupport + * } + * + * @param out The stream to write JSON to + * @param value The NotificationFilter array to encode. Can be null. + * The individual filters can't be null either. They must be of + * one of the 3 known filter classes. + * @throws IOException If an I/O error occurs + * @see #readNotificationFilters(InputStream) + */ + public void writeNotificationFilters(OutputStream out, NotificationFilter[] value) throws IOException { + writeNotificationFiltersInternal(out, value); + } + + /** + * Decode a JSON document to retrieve a NotificationFilter array. + * + * @param in The stream to read JSON from + * @return The decoded NotificationFilter array + * @throws ConversionException If JSON uses unexpected structure/format + * @throws IOException If an I/O error occurs or if JSON is ill-formed. + * @throws ClassNotFoundException If needed class can't be found. + * @see #writeNotificationFilters(OutputStream, NotificationFilter[]) + */ + public NotificationFilter[] readNotificationFilters(InputStream in) throws ConversionException, IOException, ClassNotFoundException { + return readNotificationFiltersInternal(parseArray(in)); + } + + /** + * Encode an array of Notification instance as JSON: + * + * @param out The stream to write JSON to + * @param value The Notification array to encode. Value can be null, + * but its items can't be null. + * The "source" of the items must be an instance of ObjectName. + * @throws IOException If an I/O error occurs + * @see #readNotifications(InputStream) + */ + public void writeNotifications(OutputStream out, Notification[] value) throws IOException { + final NotificationRecord[] records; + if (value != null) { + records = new NotificationRecord[value.length]; + for (int i = 0; i < value.length; ++i) { + Notification n = value[i]; + if (n != null) { + Object source = n.getSource(); + NotificationRecord nr; + if (source instanceof ObjectName) { + nr = new NotificationRecord(n, (ObjectName) source); + } else { + nr = new NotificationRecord(n, (source != null) ? source.toString() : null); + } + records[i] = nr; + } + } + } else { + records = null; + } + writeNotificationRecords(out, records); + } + + /** + * Encode an array of NotificationRecord instance as JSON: + * [ { + * "className" : "String", // The class name of the Notification object + * "serialized" : "Base64", // If the object is not of one of the known + * // classes, then base64 serialize it. + * "type" : String, + * "source" : POJO, + * "sequenceNumber" : Long, + * "timeStamp" : Long, + * "message" : String, + * "userData" : POJO, + * + * "hostName" : String, // For routed Notifications only + * "serverName" : String, + * "serverUserDir" : String, + * + * "attributeName" : String, // For AttributeChangeNotification only + * "attributeType" : String, + * "oldValue", POJO, + * "newValue", POJO, + * + * "connectionId" : String, // For JMXConnectionNotification + * + * "mbeanName" : String, // For MBeanServerNotification + * + * "relationId" : String, // For RelationNotification + * "relationTypeName" : String, + * "objectName" : String, + * "mbeansToUnregister" : [ String* ], + * "roleName" : String, + * "oldRoleValue" : [String*], + * "newRoleValue" : [String*], + * + * "notificationID" : Integer, // For TimerNotification + * } * ] + * + * @param out The stream to write JSON to + * @param value The NotificationRecord array to encode. Value can be null, + * but its items can't be null. + * The "source" of the items must be an instance of ObjectName. + * @throws IOException If an I/O error occurs + * @see #readNotificationRecords(InputStream) + */ + public void writeNotificationRecords(OutputStream out, NotificationRecord[] value) throws IOException { + writeStartArray(out); + if (value == null) { + writeEndArray(out); + return; + } + + for (NotificationRecord nr : value) { + assert nr != null; + Notification item = nr.getNotification(); + assert item != null; + writeArrayItem(out); + writeStartObject(out); + + // Fields common to all notification classes + Class clazz = item.getClass(); + writeSimpleStringField(out, OM_CLASSNAME, clazz.getName()); + writeStringField(out, OM_TYPE, item.getType()); + ObjectName on = null; + if (item.getSource() instanceof String) { + try { + on = new ObjectName((String) item.getSource()); + } catch (Exception e) { + } + } else { + on = (ObjectName) item.getSource(); + } + + writeObjectNameField(out, OM_SOURCE, on); + writeLongField(out, OM_SEQUENCENUMBER, item.getSequenceNumber()); + writeLongField(out, OM_TIMESTAMP, item.getTimeStamp()); + writeStringField(out, OM_MESSAGE, item.getMessage()); + writePOJOField(out, OM_USERDATA, item.getUserData()); + + // Write routing information (host name, server name, server user dir) if this is a routed notification. + final Map routingInfo = nr.getNotificationTargetInformation().getRoutingInformation(); + if (routingInfo != null) { + String hostName = (String) routingInfo.get(ClientProvider.ROUTING_KEY_HOST_NAME); + String serverName = (String) routingInfo.get(ClientProvider.ROUTING_KEY_SERVER_NAME); + String serverUserDir = (String) routingInfo.get(ClientProvider.ROUTING_KEY_SERVER_USER_DIR); + + assert hostName != null; + assert serverName != null; + assert serverUserDir != null; + + writeStringField(out, OM_HOSTNAME, hostName); + writeStringField(out, OM_SERVERNAME, serverName); + writeStringField(out, OM_SERVERUSERDIR, serverUserDir); + } + + if (clazz == Notification.class) { + } else if (clazz == AttributeChangeNotification.class) { + AttributeChangeNotification v = (AttributeChangeNotification) item; + writeStringField(out, OM_ATTRIBUTENAME, v.getAttributeName()); + writeStringField(out, OM_ATTRIBUTETYPE, v.getAttributeType()); + writePOJOField(out, OM_OLDVALUE, v.getOldValue()); + writePOJOField(out, OM_NEWVALUE, v.getNewValue()); + } else if (clazz == JMXConnectionNotification.class) { + JMXConnectionNotification v = (JMXConnectionNotification) item; + writeStringField(out, OM_CONNECTIONID, v.getConnectionId()); + } else if (clazz == MBeanServerNotification.class) { + MBeanServerNotification v = (MBeanServerNotification) item; + writeObjectNameField(out, OM_MBEANNAME, v.getMBeanName()); + } else if (clazz == RelationNotification.class) { + RelationNotification v = (RelationNotification) item; + writeStringField(out, OM_RELATIONID, v.getRelationId()); + writeStringField(out, OM_RELATIONTYPENAME, v.getRelationTypeName()); + writeObjectNameField(out, OM_OBJECTNAME, v.getObjectName()); + String roleName = v.getRoleName(); + if (roleName == null) { + writeObjectNameListField(out, OM_MBEANSTOUNREGISTER, v.getMBeansToUnregister()); + } else { + writeStringField(out, OM_ROLENAME, v.getRoleName()); + writeObjectNameListField(out, OM_OLDROLEVALUE, v.getOldRoleValue()); + writeObjectNameListField(out, OM_NEWROLEVALUE, v.getNewRoleValue()); + } + } else if (clazz == TimerNotification.class) { + TimerNotification v = (TimerNotification) item; + writeIntField(out, OM_NOTIFICATIONID, v.getNotificationID()); + } else { + // MonitorNotification and TimerAlarmClockNotification are + // known, but either the class or the constructor is not + // visible, and we have to use base64. + // SnmpTableEntryNotification is a sun specific implementation. + writeSerializedField(out, OM_SERIALIZED, item); + } + + writeEndObject(out); + } + writeEndArray(out); + } + + /** + * Decode a JSON document to retrieve an array of Notification instances. + * + * @param in The stream to read JSON from + * @return The decoded Notification array + * @throws ConversionException If JSON uses unexpected structure/format + * @throws IOException If an I/O error occurs or if JSON is ill-formed. + * @throws ClassNotFoundException If needed class can't be found. + * @see #writeNotifications(OutputStream, Notification[]) + */ + public Notification[] readNotifications(InputStream in) throws ConversionException, IOException, ClassNotFoundException { + final NotificationRecord[] records = readNotificationRecords(in); + final Notification[] ret = new Notification[records.length]; + for (int i = 0; i < records.length; ++i) { + ret[i] = records[i].getNotification(); + } + return ret; + } + + /** + * Decode a JSON document to retrieve an array of NotificationRecord instances. + * + * @param in The stream to read JSON from + * @return The non-null decoded NotificationRecord array + * @throws ConversionException If JSON uses unexpected structure/format + * @throws IOException If an I/O error occurs or if JSON is ill-formed. + * @throws ClassNotFoundException If needed class can't be found. + * @see #writeNotificationRecords(OutputStream, NotificationRecord[]) + */ + public NotificationRecord[] readNotificationRecords(InputStream in) throws ConversionException, IOException, ClassNotFoundException { + JSONArray json = parseArray(in); + int size = json.size(); + NotificationRecord[] ret = new NotificationRecord[size]; + for (int i = 0; i < size; i++) { + Object o = json.get(i); + if (!(o instanceof JSONObject)) { + throwConversionException("readNotifications() expects a JSONObject.", o); + } + JSONObject obj = (JSONObject) o; + + // Fields common to all Notification classes. + String className = readStringInternal(obj.get(N_CLASSNAME)); + String type = readStringInternal(obj.get(N_TYPE)); + ObjectName source = readObjectName(obj.get(N_SOURCE)); + long sequenceNumber = readLongInternal(obj.get(N_SEQUENCENUMBER)); + long timeStamp = readLongInternal(obj.get(N_TIMESTAMP)); + String message = readStringInternal(obj.get(N_MESSAGE)); + Object userData = readPOJOInternal(obj.get(N_USERDATA)); + + // Read routing information (host name, server name, server user dir) if this is a routed notification. + String hostName = readStringInternal(obj.get(N_HOSTNAME)); + String serverName; + String serverUserDir; + if (hostName != null) { + serverName = readStringInternal(obj.get(N_SERVERNAME)); + serverUserDir = readStringInternal(obj.get(N_SERVERUSERDIR)); + } else { + serverName = null; + serverUserDir = null; + } + + Notification n; + if ("javax.management.Notification".equals(className)) { + n = new Notification(type, source, sequenceNumber, timeStamp, message); + } else if ("javax.management.AttributeChangeNotification".equals(className)) { + if (!AttributeChangeNotification.ATTRIBUTE_CHANGE.equals(type)) { + throwConversionException("Type for AttributeChangeNotification should be ATTRIBUTE_CHANGE", o); + } + String attributeName = readStringInternal(obj.get(N_ATTRIBUTENAME)); + String attributeType = readStringInternal(obj.get(N_ATTRIBUTETYPE)); + Object oldValue = readPOJOInternal(obj.get(N_OLDVALUE)); + Object newValue = readPOJOInternal(obj.get(N_NEWVALUE)); + n = new AttributeChangeNotification(source, sequenceNumber, timeStamp, message, + attributeName, attributeType, oldValue, newValue); + } else if ("javax.management.remote.JMXConnectionNotification".equals(className)) { + String connectionId = readStringInternal(obj.get(N_CONNECTIONID)); + n = new JMXConnectionNotification(type, source, connectionId, sequenceNumber, message, userData); + // Replace the value set by the constructor + n.setTimeStamp(timeStamp); + } else if ("javax.management.MBeanServerNotification".equals(className)) { + ObjectName objectName = readObjectName(obj.get(N_MBEANNAME)); + n = new MBeanServerNotification(type, source, sequenceNumber, objectName); + // Replace the value set by the constructor + n.setTimeStamp(timeStamp); + } else if ("javax.management.relation.RelationNotification".equals(className)) { + String relationId = readStringInternal(obj.get(N_RELATIONID)); + String typeName = readStringInternal(obj.get(N_RELATIONTYPENAME)); + ObjectName objectName = readObjectName(obj.get(N_OBJECTNAME)); + String roleName = readStringInternal(obj.get(N_ROLENAME)); + if (roleName == null) { + List mbeansToUnregister = readObjectNameList(obj.get(N_MBEANSTOUNREGISTER)); + n = new RelationNotification(type, source, sequenceNumber, timeStamp, message, + relationId, typeName, objectName, mbeansToUnregister); + } else { + List oldValue = readObjectNameList(obj.get(N_OLDROLEVALUE)); + List newValue = readObjectNameList(obj.get(N_NEWROLEVALUE)); + n = new RelationNotification(type, source, sequenceNumber, timeStamp, message, + relationId, typeName, objectName, + roleName, oldValue, newValue); + } + } else if ("javax.management.timer.TimerNotification".equals(className)) { + Integer notificationID = readIntInternal(obj.get(N_NOTIFICATIONID)); + n = new TimerNotification(type, source, sequenceNumber, timeStamp, message, notificationID); + } else { + Object serialized = readSerialized(obj.get(N_SERIALIZED)); + if (!(serialized instanceof Notification)) { + throwConversionException("readNotifications() expects a Notification.", o); + } + n = (Notification) serialized; + } + + n.setUserData(userData); + + final NotificationRecord nr; + if (hostName != null) { + nr = new NotificationRecord(n, source, hostName, serverName, serverUserDir); + } else { + nr = new NotificationRecord(n, source); + } + ret[i] = nr; + } + return ret; + } + + /** + * Encode a NotificationSettings instance as JSON: + * { + * "deliveryInterval" : Integer + * } + * + * @param out The stream to write JSON to + * @param value The NotificationSettings instance to encode. Can't be null. + * @throws IOException If an I/O error occurs + * @see #readNotificationSettings(InputStream) + */ + public void writeNotificationSettings(OutputStream out, NotificationSettings value) throws IOException { + assert value != null; + writeStartObject(out); + writeIntField(out, OM_DELIVERYINTERVAL, value.deliveryInterval); + writeIntField(out, OM_INBOXEXPIRTY, value.inboxExpiry); + writeEndObject(out); + } + + /** + * Decode a JSON document to retrieve a NotificationSettings instance. + * + * @param in The stream to read JSON from + * @return The decoded NotificationSettings instance + * @throws ConversionException If JSON uses unexpected structure/format + * @throws IOException If an I/O error occurs or if JSON is ill-formed. + * @see #writeNotificationSettings(OutputStream, NotificationSettings) + */ + public NotificationSettings readNotificationSettings(InputStream in) throws ConversionException, IOException { + JSONObject json = parseObject(in); + NotificationSettings ret = new NotificationSettings(); + ret.deliveryInterval = readIntInternal(json.get(N_DELIVERYINTERVAL)); + ret.inboxExpiry = readIntInternal(json.get(N_INBOXEXPIRY)); + return ret; + } + + /** + * Encode a Throwable instance as JSON: + * { + * "throwable" : Base64, + * "stackTrace" : String + * } + * + * @param out The stream to write JSON to + * @param value The Throwable instance to encode. Can't be null. + * @throws IOException If an I/O error occurs + * @see #readThrowable(InputStream) + */ + public void writeThrowable(OutputStream out, Throwable value) throws IOException { + assert value != null; + writeStartObject(out); + writeSerializedField(out, OM_THROWABLE, value); + StringWriter sw = new StringWriter(); + value.printStackTrace(new PrintWriter(sw)); + writeStringField(out, OM_STACKTRACE, sw.toString()); + writeEndObject(out); + } + + /** + * Decode a JSON document to retrieve a Throwable instance. + * + * @param in The stream to read JSON from + * @return The decoded Throwable instance + * @throws ConversionException If JSON uses unexpected structure/format + * @throws IOException If an I/O error occurs or if JSON is ill-formed. + * @throws ClassNotFoundException If needed class can't be found. + * @see #writeThrowable(OutputStream, Throwable) + */ + public Throwable readThrowable(InputStream in) throws ConversionException, IOException, ClassNotFoundException { + byte[] byteInputStream = convertInputStreamToBytes(in); + ByteArrayInputStream bais = new ByteArrayInputStream(byteInputStream); + JSONObject json = null; + try { + json = parseObject(bais); + } catch (IOException ex) { + bais.reset(); + throw new RuntimeException(convertStreamToString(bais)); + } + Object t = readSerialized(json.get(N_THROWABLE)); + if (!(t instanceof Throwable)) { + throwConversionException("readThrowable() receives an instance that's not a Throwable.", json.get(N_THROWABLE)); + } + return (Throwable) t; + } + + /** + * Converts inputstream to bytearray + * + * @param in + * @return + * @throws IOException + */ + private byte[] convertInputStreamToBytes(InputStream in) throws IOException { + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + + int len; + byte[] data = new byte[16384]; + + while ((len = in.read(data, 0, data.length)) != -1) { + buffer.write(data, 0, len); + } + + buffer.flush(); + return buffer.toByteArray(); + } + + /** + * Converts inputstream to String + * + * @param in + * @return + * @throws IOException + */ + + private String convertStreamToString(InputStream input) throws IOException { + BufferedReader reader = new BufferedReader(new InputStreamReader(input)); + StringBuilder sb = new StringBuilder(); + String line = null; + + while ((line = reader.readLine()) != null) { + sb.append(line); + } + + input.close(); + return sb.toString(); + } + + /** + * Encode a String in base64. The content of the string is first encoded + * as UTF-8 bytes, the bytes are then base64 encoded. The resulting base64 + * value is returned as a String. + * + * @param value The String to encode + * @return The encoded base64 String + * @throws ConversionException If the String content can not be UTF-8 encoded. + */ + public String encodeStringAsBase64(String value) throws ConversionException { + try { + return encodeStringAsBase64Internal(value); + } catch (IOException e) { + // Will never happen + return null; + } + } + + @SuppressWarnings("deprecation") + private String encodeStringAsBase64Internal(String value) throws ConversionException, IOException { + final Base64OutputStream out = base64Stream; + byteArrayOS.reset(); + out.start(byteArrayOS); + for (int i = 0; i < value.length(); i++) { + char ch = value.charAt(i); + if (ch < 0x80) { + // 1-byte + out.write(ch); + } else if (ch < 0x800) { + // 2-byte + out.write(0xC0 | (ch >> 6)); + out.write(0x80 | (0x3F & ch)); + } else if (ch < 0xD800 || ch >= 0xE000) { + // 3-byte + out.write(0xE0 | (ch >> 12)); + out.write(0x80 | (0x3F & (ch >> 6))); + out.write(0x80 | (0x3F & ch)); + } else if (ch < 0xDC00) { + // 4-byte. Surrogate pair. + if (i == value.length() - 1) { + // Error if second half is missing + utf8EncodeError(value); + } else { + char ch2 = value.charAt(i + 1); + if (ch2 >= 0xDC00 && ch2 < 0xE000) { + int c = 0x00010000 + ((ch - 0xD800) << 10) + (ch2 - 0xDC00); + out.write(0xF0 | (c >> 18)); /* no mask needed */ + out.write(0x80 | (0x3F & (c >> 12))); + out.write(0x80 | (0x3F & (c >> 6))); + out.write(0x80 | (0x3F & c)); + i++; + } else { + // Error if second half is out of range + utf8EncodeError(value); + } + } + } else { + // Error if first half is out of range + utf8EncodeError(value); + } + } + out.end(); + // Base64 encoded String only has ASCII characters. + return byteArrayOS.toString(0); + } + + private void writeStartObject(OutputStream out) throws IOException { + out.write('{'); + firstItem = true; + } + + private void writeFieldName(OutputStream out, byte[] name) throws IOException { + if (firstItem) { + firstItem = false; + } else { + out.write(','); + } + out.write(name); + } + + private void writeSimpleFieldName(OutputStream out, String name) throws IOException { + if (firstItem) { + firstItem = false; + } else { + out.write(','); + } + writeSimpleString(out, name); + out.write(':'); + } + + private void escapeFieldName(OutputStream out, String name) throws IOException { + if (firstItem) { + firstItem = false; + } else { + out.write(','); + } + writeStringInternal(out, name); + out.write(':'); + } + + private void writeEndObject(OutputStream out) throws IOException { + out.write('}'); + firstItem = false; + } + + private void writeStartArray(OutputStream out) throws IOException { + out.write('['); + firstItem = true; + } + + private void writeArrayItem(OutputStream out) throws IOException { + if (firstItem) { + firstItem = false; + } else { + out.write(','); + } + } + + private void writeEndArray(OutputStream out) throws IOException { + out.write(']'); + firstItem = false; + } + + /** + * Debug (dump) the contents of an input stream. This effectively copies + * the input stream into a byte array, dumps one and then returns another. + * If logging is not enabled, nothing happens. + * + * @param in + * @throws IOException + */ + private InputStream debugInputStream(InputStream in) throws IOException { + if (logger.isLoggable(Level.FINEST)) { + final byte[] buffer = new byte[1024]; + final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + int len; + String line; + + logger.finest("[START] Dumping the InputStream that will be passed to JSON.parse()"); + while ((len = in.read(buffer)) > -1) { + baos.write(buffer, 0, len); + } + baos.flush(); + + ByteArrayInputStream dumpIn = new ByteArrayInputStream(baos.toByteArray()); + BufferedReader br = new BufferedReader(new InputStreamReader(dumpIn)); + while ((line = br.readLine()) != null) { + logger.finest(line); + } + logger.finest("[END] Dumping the InputStream that will be passed to JSON.parse()"); + + return new ByteArrayInputStream(baos.toByteArray()); + } else { + return in; + + } + } + + /** + * Parse (and possible debug) the InputStream as a JSONArtifact. + * + * @param in + * @return + * @throws IOException + */ + private JSONArtifact debugAndParse(InputStream in) throws IOException { + return JSON.parse(debugInputStream(in)); + } + + private Object parse(InputStream in) throws IOException { + return debugAndParse(in); + } + + private JSONObject parseObject(InputStream in) throws ConversionException, IOException { + JSONArtifact json = debugAndParse(in); + if (!(json instanceof JSONObject)) { + throwConversionException("parseObject() receives an instance that's not a JSONObject.", json); + } + return (JSONObject) json; + } + + private JSONArray parseArray(InputStream in) throws ConversionException, IOException { + JSONArtifact json = debugAndParse(in); + if (!(json instanceof JSONArray)) { + throwConversionException("parseArray() receives an instance that's not a JSONArray.", json); + } + return (JSONArray) json; + } + + private byte readByteInternal(Object in) throws ConversionException { + int value = readIntInternal(in); + if (value > Byte.MAX_VALUE || value < Byte.MIN_VALUE) { + throwConversionException("readByteInternal() receives an out-of-range value.", in); + } + return (byte) value; + } + + private short readShortInternal(Object in) throws ConversionException { + int value = readIntInternal(in); + if (value > Short.MAX_VALUE || value < Short.MIN_VALUE) { + throwConversionException("readShortInternal() receives an out-of-range value.", in); + } + return (short) value; + } + + private void writeIntField(OutputStream out, byte[] name, int value) throws IOException { + writeFieldName(out, name); + writeIntInternal(out, value); + } + + private void writeIntInternal(OutputStream out, int value) throws IOException { + out.write('"'); + encodeInt(out, value); + out.write('"'); + } + + private void encodeInt(OutputStream out, int value) throws IOException { + if (value < 0) { + // -Integer.MIN_VALUE is out of "int" range. Special-casing it. + if (value == Integer.MIN_VALUE) { + out.write(INT_MIN); + return; + } + + // Turn value to positive so that % and / work as expected. + out.write('-'); + value = -value; + } + + // Write from right to left + final byte[] bytes = BYTE_BUFFER; + int pos = BYTE_BUFFER.length; + do { + int q = value / 10; + int r = value - (q << 3) - (q << 1); // same as (value - q * 10) + value = q; + bytes[--pos] = (byte) (r + '0'); + } while (value != 0); + + out.write(bytes, pos, BYTE_BUFFER.length - pos); + } + + private int readIntInternal(Object in) throws ConversionException { + if (in == null) { + return 0; + } + + if (!(in instanceof String)) { + throwConversionException("readIntInternal() expects a String.", in); + } + try { + return Integer.parseInt((String) in); + } catch (NumberFormatException e) { + throwConversionException(e, in); + return 0; + } + } + + private void writeLongField(OutputStream out, byte[] name, long value) throws IOException { + writeFieldName(out, name); + writeLongInternal(out, value); + } + + private void writeLongInternal(OutputStream out, long value) throws IOException { + out.write('"'); + encodeLong(out, value); + out.write('"'); + } + + private void encodeLong(OutputStream out, long value) throws IOException { + if (value < 0) { + // -Long.MIN_VALUE is out of "long" range. Special-casing it. + if (value == Long.MIN_VALUE) { + out.write(LONG_MIN); + return; + } + + // Turn value to positive so that % and / work as expected. + out.write('-'); + value = -value; + } + + // Write from right to left + final byte[] bytes = BYTE_BUFFER; + int pos = BYTE_BUFFER.length; + do { + long q = value / 10; + long r = value - (q << 3) - (q << 1); // same as (value - q * 10) + value = q; + bytes[--pos] = (byte) (r + '0'); + } while (value != 0); + + out.write(bytes, pos, BYTE_BUFFER.length - pos); + } + + private long readLongInternal(Object in) throws ConversionException { + if (!(in instanceof String)) { + throwConversionException("readLongInternal() expects a String.", in); + } + try { + return Long.parseLong((String) in); + } catch (NumberFormatException e) { + throwConversionException(e, in); + return 0; + } + } + + private float readFloatInternal(Object in) throws ConversionException { + if (!(in instanceof String)) { + throwConversionException("readFloatInternal() expects a String.", in); + } + try { + return Float.parseFloat((String) in); + } catch (NumberFormatException e) { + throwConversionException(e, in); + return 0; + } + } + + private double readDoubleInternal(Object in) throws ConversionException { + if (!(in instanceof String)) { + throwConversionException("readDoubleInternal() expects a String.", in); + } + try { + return Double.parseDouble((String) in); + } catch (NumberFormatException e) { + throwConversionException(e, in); + return 0; + } + } + + private char readCharInternal(Object in) throws ConversionException { + if (!(in instanceof String)) { + throwConversionException("readCharInternal() expects a String.", in); + } + String str = (String) in; + if (str.length() != 1) { + throwConversionException("readCharInternal() expects a String of length 1.", in); + } + return str.charAt(0); + } + + private void writeBooleanField(OutputStream out, byte[] name, boolean value) throws IOException { + writeFieldName(out, name); + writeBooleanInternal(out, value); + } + + private void writeBooleanInternal(OutputStream out, boolean value) throws IOException { + out.write(value ? TRUE : FALSE); + } + + private boolean readBooleanInternal(Object in) throws ConversionException { + if (!(in instanceof Boolean)) { + throwConversionException("readBooleanInternal() expects a Boolean.", in); + } + return ((Boolean) in).booleanValue(); + } + + private void writeSimpleStringField(OutputStream out, byte[] name, CharSequence value) throws IOException { + writeFieldName(out, name); + writeSimpleString(out, value); + } + + // Called for ASCII Strings that don't contain any need-to-escape characters. + // The value can't be null. + private void writeSimpleString(OutputStream out, CharSequence value) throws IOException { + out.write('"'); + for (int i = 0; i < value.length(); i++) { + out.write(value.charAt(i)); + } + out.write('"'); + } + + private void writeStringField(OutputStream out, byte[] name, String value) throws IOException { + if (value == null) { + return; + } + writeFieldName(out, name); + writeStringInternal(out, value); + } + + private void writeStringInternal(OutputStream out, String value) throws IOException { + if (value == null) { + out.write(NULL); + return; + } + + out.write('"'); + escapeString(out, value); + out.write('"'); + } + + private void escapeString(OutputStream out, String value) throws IOException { + for (int i = 0; i < value.length(); i++) { + char ch = value.charAt(i); + // Escape '"' and '\' + if (ch == '"') { + out.write('\\'); + out.write('"'); + } else if (ch == '\\') { + out.write('\\'); + out.write('\\'); + } else if (ch >= 0x80) { + // Multi-byte chars + if (ch < 0x800) { + // 2-byte + out.write(0xC0 | (ch >> 6)); + out.write(0x80 | (0x3F & ch)); + } else if (ch < 0xD800 || ch >= 0xE000) { + // 3-byte + out.write(0xE0 | (ch >> 12)); + out.write(0x80 | (0x3F & (ch >> 6))); + out.write(0x80 | (0x3F & ch)); + } else if (ch < 0xDC00) { + // 4-byte. Surrogate pair. + if (i == value.length() - 1) { + // Error if second half is missing + writeInvalidChar(out, ch); + } else { + char ch2 = value.charAt(i + 1); + if (ch2 >= 0xDC00 && ch2 < 0xE000) { + int c = 0x00010000 + ((ch - 0xD800) << 10) + (ch2 - 0xDC00); + out.write(0xF0 | (c >> 18)); /* no mask needed */ + out.write(0x80 | (0x3F & (c >> 12))); + out.write(0x80 | (0x3F & (c >> 6))); + out.write(0x80 | (0x3F & c)); + i++; + } else { + // Error if second half is out of range + writeInvalidChar(out, ch); + } + } + } else { + // Error if first half is out of range + writeInvalidChar(out, ch); + } + } else if (ch >= 0x20) { + // Common case: ASCII and not special + out.write(ch); + } else { + // Escape control characters. + out.write('\\'); + switch (ch) { + case 8: + out.write('b'); + break; + case 9: + out.write('t'); + break; + case 0xA: + out.write('n'); + break; + case 0xC: + out.write('f'); + break; + case 0xD: + out.write('r'); + break; + default: + out.write('u'); + out.write('0'); + out.write('0'); + out.write(hex(ch >> 4)); + out.write(hex(ch & 0xf)); + } + } + } + } + + private void writeInvalidChar(OutputStream out, char value) throws IOException { + out.write('\\'); + out.write('u'); + out.write(hex(value >> 12)); + out.write(hex((value >> 8) & 0xf)); + out.write(hex((value >> 4) & 0xf)); + out.write(hex(value & 0xf)); + } + + private byte hex(int value) { + return (byte) (value < 10 ? value + '0' : value + 'A' - 10); + } + + private String readStringInternal(Object in) throws ConversionException { + if (in == null) { + return null; + } + if (!(in instanceof String)) { + throwConversionException("readStringInternal() expects a String.", in); + } + // The JSON parser already decoded the string. + return (String) in; + } + + private void writeStringArrayField(OutputStream out, byte[] name, String[] value) throws IOException { + if (value == null) { + return; + } + writeFieldName(out, name); + writeStringArrayInternal(out, value); + } + + private void writeStringArrayInternal(OutputStream out, String[] value) throws IOException { + writeStartArray(out); + if (value != null) { + for (String s : value) { + writeArrayItem(out); + writeStringInternal(out, s); + } + } + writeEndArray(out); + } + + private String[] readStringArrayInternal(Object in) throws ConversionException { + if (in == null) { + return null; + } + if (!(in instanceof JSONArray)) { + throwConversionException("readStringArrayInternal() expects a JSONArray.", in); + } + JSONArray json = (JSONArray) in; + int size = json.size(); + String[] ret = new String[size]; + for (int i = 0; i < size; i++) { + ret[i] = readStringInternal(json.get(i)); + } + return ret; + } + + private void writeSerializedField(OutputStream out, byte[] name, Object value) throws IOException { + if (value == null) { + return; + } + writeFieldName(out, name); + writeSerialized(out, value); + } + + private void writeSerialized(OutputStream out, Object value) throws IOException { + if (value == null) { + out.write(NULL); + return; + } + out.write('"'); + base64Stream.start(out); + ObjectOutputStream objectOut = new ObjectOutputStream(base64Stream); + objectOut.writeObject(value); + base64Stream.end(); + out.write('"'); + } + + private Object readSerialized(Object in) throws ConversionException, ClassNotFoundException { + if (in == null) { + return null; + } + if (!(in instanceof String)) { + throwConversionException("readSerialized() expects a String.", in); + } + String value = (String) in; + int slen = value.length(); + if (slen == 0 || slen / 4 * 4 != slen) { + base64DecodeError(in); + } + int blen = slen / 4 * 3; + byte[] binary = new byte[blen]; + int c1 = 0, c2 = 0, c3 = 0, c4 = 0, pos = 0; + for (int i = 0; i < slen;) { + c1 = value.charAt(i++); + c2 = value.charAt(i++); + c3 = value.charAt(i++); + c4 = value.charAt(i++); + if (c1 >= BASE64_D.length || BASE64_D[c1] == -1 || + c2 >= BASE64_D.length || BASE64_D[c2] == -1 || + c2 >= BASE64_D.length || BASE64_D[c3] == -1 || + c2 >= BASE64_D.length || BASE64_D[c4] == -1) { + base64DecodeError(in); + } + c1 = BASE64_D[c1]; + c2 = BASE64_D[c2]; + c3 = BASE64_D[c3]; + c4 = BASE64_D[c4]; + binary[pos++] = (byte) ((c1 << 2) | (c2 >> 4)); + binary[pos++] = (byte) ((c2 << 4) | (c3 >> 2)); + binary[pos++] = (byte) ((c3 << 6) | c4); + } + + if (value.charAt(slen - 1) == '=') { + if (binary[--blen] != 0) { + base64DecodeError(in); + } + if (value.charAt(slen - 2) == '=') { + if (binary[--blen] != 0) { + base64DecodeError(in); + } + } + } + + return helper.readObject(in, blen, binary); + } + + public static void setSerializationHelper(SerializationHelper sh) { + if (null == sh) { + helper = defaultHelper; + } else { + helper = sh; + } + } + + private void writePOJOField(OutputStream out, byte[] name, Object value) throws IOException { + if (value == null) { + return; + } + writeFieldName(out, name); + writePOJOInternal(out, value); + } + + private void writePOJOInternal(OutputStream out, Object value) throws IOException { + if (USE_BASE64_FOR_POJO) { + writeStartObject(out); + if (value != null) { + writeSimpleStringField(out, OM_CLASSNAME, value.getClass().getName()); + writeSerializedField(out, OM_SERIALIZED, value); + } + writeEndObject(out); + return; + } + + writeStartObject(out); + // Merge this with the "writeType" method? + // Then need to write "type" content into the byateArrayOS. + if (hasCycle(value, new Stack())) { + // If the value object contains cycle, then java-serialize it. + writeSerializedField(out, OM_SERIALIZED, value); + } else { + writeFieldName(out, OM_VALUE); + writePOJOValue(out, value); + writeFieldName(out, OM_TYPE); + List> openTypes = new ArrayList>(); + writePOJOType(out, value, openTypes); + writeOpenTypes(out, openTypes); + } + writeEndObject(out); + } + + private boolean hasCycle(Object value, Stack seen) { + if (value == null) { + return false; + } + + for (Object o : seen) { + if (o == value) { + return true; + } + } + + Class clazz = value.getClass(); + + if (clazz.isArray()) { + Class componentType = clazz.getComponentType(); + if (componentType.isPrimitive()) { + return false; + } + + Class leaf = componentType; + while (leaf.isArray()) { + leaf = leaf.getComponentType(); + } + if (SupportedClasses.get(leaf) == null) { + return false; + } + + if (SimpleArrays.contains(leaf)) { + return false; + } + + seen.push(value); + for (Object o : (Object[]) value) { + if (hasCycle(o, seen)) { + return true; + } + } + seen.pop(); + return false; + } + + TYPE type = SupportedClasses.get(clazz); + if (type == null) { + return false; + } + + switch (type) { + case Byte: + case Short: + case Integer: + case Long: + case Float: + case Double: + case Character: + case Boolean: + case String: + case BigInteger: + case BigDecimal: + case Date: + case Object: + return false; + case Collection: + seen.push(value); + for (Object o : (Collection) value) { + if (hasCycle(o, seen)) { + return true; + } + } + seen.pop(); + return false; + case Map: + Map map = (Map) value; + seen.push(value); + for (Entry entry : map.entrySet()) { + if (hasCycle(entry.getKey(), seen)) { + return true; + } + if (hasCycle(entry.getValue(), seen)) { + return true; + } + } + seen.pop(); + return false; + case CompositeData: + CompositeData composite = (CompositeData) value; + seen.push(value); + for (String key : composite.getCompositeType().keySet()) { + if (hasCycle(composite.get(key), seen)) { + return true; + } + } + seen.pop(); + return false; + case TabularData: + TabularData tabular = (TabularData) value; + seen.push(value); + for (Object o : tabular.values()) { + if (hasCycle(o, seen)) { + return true; + } + } + seen.pop(); + return false; + } + return false; + } + + private void writePOJOValue(OutputStream out, Object value) throws IOException { + if (value == null) { + // - For "null" value: + // value: null + out.write(NULL); + return; + } + + Class clazz = value.getClass(); + + if (clazz.isArray()) { + // - For array + // value: [ Value* ] + Class componentType = clazz.getComponentType(); + if (componentType.isPrimitive()) { + writePrimitiveArray(out, value, componentType); + return; + } + + writeStartArray(out); + for (Object o : (Object[]) value) { + writeArrayItem(out); + writePOJOValue(out, o); + } + writeEndArray(out); + return; + } + + TYPE type = SupportedClasses.get(clazz); + if (type == null) { + if (value instanceof TabularData) { + type = TYPE.TabularData; + } else if (value instanceof CompositeData) { + type = TYPE.CompositeData; + } else if (value instanceof Map) { + type = TYPE.Map; + } else if (value instanceof Collection) { + type = TYPE.Collection; + } else if (value instanceof BigInteger) { + type = TYPE.BigInteger; + } else if (value instanceof BigDecimal) { + type = TYPE.BigDecimal; + } else if (value instanceof Date) { + type = TYPE.Date; + } else if (value instanceof ObjectName) { + type = TYPE.ObjectName; + } else { + // - For a value that's not expressible in JSON: + // null + out.write(NULL); + return; + } + } + + switch (type) { + case Byte: + case Short: + case Integer: + case Long: + case Float: + case Double: + case Boolean: + case BigInteger: + case BigDecimal: + // These value are ASCII without \ or " character, so no + // escaping is needed. + // - For a simple value + // value: String representation + writeSimpleString(out, value.toString()); + return; + case String: + writeStringInternal(out, (String) value); + return; + case ObjectName: + writeObjectName(out, (ObjectName) value); + return; + case Date: + writeLongInternal(out, ((Date) value).getTime()); + return; + case Object: + // - For an Object: + // value: "". "null" isn't very accurate. + writeSimpleString(out, ""); + return; + case Character: + // Could be special; may need to escape. + writeStringInternal(out, value.toString()); + return; + case Collection: + // - For Collection + // value: [ Value* ] + writeStartArray(out); + for (Object o : (Collection) value) { + writeArrayItem(out); + writePOJOValue(out, o); + } + writeEndArray(out); + return; + case Map: + Map map = (Map) value; + if (map.isEmpty()) { + writeStartObject(out); + writeEndObject(out); + return; + } + boolean simpleKey = true; + for (Object key : map.keySet()) { + // If a key is "null", then treat as complex key + if (key == null || !SimpleKeys.contains(key.getClass())) { + simpleKey = false; + break; + } + } + if (simpleKey) { + // - For map with simple key: + // value: { + // String: Value * + // } + writeStartObject(out); + for (Entry entry : map.entrySet()) { + Object key = entry.getKey(); + Object v = entry.getValue(); + if (key instanceof String) { + escapeFieldName(out, (String) key); + } else { + writeSimpleFieldName(out, key.toString()); + } + writePOJOValue(out, v); + } + writeEndObject(out); + } else { + // -For map with complex keys + // value: [ {key: Value, value: Value}* ] + writeStartArray(out); + for (Entry entry : map.entrySet()) { + Object key = entry.getKey(); + writeArrayItem(out); + writeStartObject(out); + writeFieldName(out, OM_KEY); + writePOJOValue(out, key); + writeFieldName(out, OM_VALUE); + writePOJOValue(out, entry.getValue()); + writeEndObject(out); + } + writeEndArray(out); + } + return; + case CompositeData: + // - For CompositeData + // value: { + // String: Value * // Key can't be null + // } + CompositeData composite = (CompositeData) value; + writeStartObject(out); + for (String key : composite.getCompositeType().keySet()) { + escapeFieldName(out, key); + writePOJOValue(out, composite.get(key)); + } + writeEndObject(out); + return; + case TabularData: + // - TabularData + // value: [ CompositeData * ] + TabularData tabular = (TabularData) value; + writeStartArray(out); + for (Object item : tabular.values()) { + writeArrayItem(out); + writePOJOValue(out, item); + } + writeEndArray(out); + return; + } + } + + private void writePrimitiveArray(OutputStream out, Object value, Class component) throws IOException { + switch (SupportedClasses.get(component)) { + case _Byte: + case Byte: + writeStartArray(out); + for (byte v : (byte[]) value) { + writeArrayItem(out); + writeIntInternal(out, v); + } + writeEndArray(out); + break; + case _Short: + case Short: + writeStartArray(out); + for (short v : (short[]) value) { + writeArrayItem(out); + writeIntInternal(out, v); + } + writeEndArray(out); + break; + case _Integer: + case Integer: + writeStartArray(out); + for (int v : (int[]) value) { + writeArrayItem(out); + writeIntInternal(out, v); + } + writeEndArray(out); + break; + case _Long: + case Long: + writeStartArray(out); + for (long v : (long[]) value) { + writeArrayItem(out); + writeLongInternal(out, v); + } + writeEndArray(out); + break; + case _Float: + case Float: + writeStartArray(out); + for (Float v : (Float[]) value) { + writeArrayItem(out); + writeSimpleString(out, Float.toString(v)); + } + writeEndArray(out); + break; + case _Double: + case Double: + writeStartArray(out); + for (Double v : (Double[]) value) { + writeArrayItem(out); + writeSimpleString(out, Double.toString(v)); + } + writeEndArray(out); + break; + case _Character: + case Character: + writeStartArray(out); + for (char v : (char[]) value) { + writeArrayItem(out); + writeIntInternal(out, v); + } + writeEndArray(out); + break; + case _Boolean: + case Boolean: + writeStartArray(out); + for (boolean v : (boolean[]) value) { + writeArrayItem(out); + out.write(v ? TRUE : FALSE); + } + writeEndArray(out); + break; + default: + break; + } + } + + private void writePOJOType(OutputStream out, Object value, List> openTypes) throws IOException { + if (value == null) { + // - For "null" value: + // type: null + out.write(NULL); + return; + } + + Class clazz = value.getClass(); + + if (clazz.isArray()) { + // - For simple array + // type: String + // - For complex array + // type: { + // className: String, ? + // value: Base64, ? + // items: [ Type* ] ? + // } + Class componentType = clazz.getComponentType(); + if (componentType.isPrimitive()) { + writeSimpleString(out, clazz.getName()); + return; + } + + Class leaf = componentType; + while (leaf.isArray()) { + leaf = leaf.getComponentType(); + } + if (SupportedClasses.get(leaf) == null) { + // Unknown array type. Java serialize it + writeStartObject(out); + writeSimpleStringField(out, OM_CLASSNAME, clazz.getName()); + writeSerializedField(out, OM_VALUE, value); + writeEndObject(out); + // And do not produce type information for the subtree. + return; + } + + if (SimpleArrays.contains(leaf)) { + writeSimpleString(out, clazz.getName()); + // Don't need further type information for simple arrays + return; + } + + writeStartObject(out); + writeSimpleStringField(out, OM_CLASSNAME, clazz.getName()); + writeFieldName(out, OM_ITEMS); + writeStartArray(out); + + for (Object o : (Object[]) value) { + writeArrayItem(out); + writePOJOType(out, o, openTypes); + } + writeEndArray(out); + writeEndObject(out); + return; + } + + TYPE type = SupportedClasses.get(clazz); + if (type == null) { + // Unknown array type. Java serialize it + // type: { + // className: String, ? + // value: Base64, ? + // } + writeStartObject(out); + writeSimpleStringField(out, OM_CLASSNAME, clazz.getName()); + writeSerializedField(out, OM_VALUE, value); + writeEndObject(out); + // And do not produce type information for the subtree. + return; + } + + switch (type) { + case Byte: + case Short: + case Integer: + case Long: + case Float: + case Double: + case Character: + case Boolean: + case String: + case BigInteger: + case BigDecimal: + case Date: + case ObjectName: + case Object: + // - For a simple value + // type: String (class name) + // These value are ASCII without \ or " character, so no + // escaping is needed. + writeSimpleString(out, clazz.getName()); + return; + case Collection: + // - For Collection + // type: { + // className: String, + // items: [ Type* ] + // } + writeStartObject(out); + writeSimpleStringField(out, OM_CLASSNAME, clazz.getName()); + writeFieldName(out, OM_ITEMS); + writeStartArray(out); + for (Object o : (Collection) value) { + writeArrayItem(out); + writePOJOType(out, o, openTypes); + } + writeEndArray(out); + writeEndObject(out); + return; + case Map: + Map map = (Map) value; + // - For maps + // type: { + // className: String, + // simpleKey: boolean, + // entries: [ + // { + // key:String, ? // For simple key + // keyType:Type, + // value:Type + // } * + // ] + // } + writeStartObject(out); + writeSimpleStringField(out, OM_CLASSNAME, clazz.getName()); + if (map.isEmpty()) { + writeEndObject(out); + return; + } + + boolean simpleKey = true; + for (Object key : map.keySet()) { + // If a key is "null", then treat as complex key + if (key == null || !SimpleKeys.contains(key.getClass())) { + simpleKey = false; + break; + } + } + + writeBooleanField(out, OM_SIMPLEKEY, simpleKey); + writeFieldName(out, OM_ENTRIES); + writeStartArray(out); + for (Entry entry : map.entrySet()) { + Object key = entry.getKey(); + writeArrayItem(out); + writeStartObject(out); + if (simpleKey) { + if (key instanceof String) { + writeStringField(out, OM_KEY, (String) key); + } else { + writeSimpleStringField(out, OM_KEY, key.toString()); + } + } + writeFieldName(out, OM_KEYTYPE); + writePOJOType(out, key, openTypes); + writeFieldName(out, OM_VALUE); + writePOJOType(out, entry.getValue(), openTypes); + writeEndObject(out); + } + writeEndArray(out); + writeEndObject(out); + return; + case CompositeData: + // - For CompositeData + // type: { + // className: String, + // openType: Integer // Reference to the OpenType array in root Type + // } + CompositeData composite = (CompositeData) value; + writeStartObject(out); + writeSimpleStringField(out, OM_CLASSNAME, clazz.getName()); + CompositeType ct = composite.getCompositeType(); + writeOpenTypeField(out, OM_OPENTYPE, ct, openTypes); + writeEndObject(out); + return; + case TabularData: + // - TabularData + // type: { + // className: String, + // openType: Integer // Reference to the OpenType array in root Type + // } + TabularData tabular = (TabularData) value; + writeStartObject(out); + writeSimpleStringField(out, OM_CLASSNAME, clazz.getName()); + TabularType tt = tabular.getTabularType(); + writeOpenTypeField(out, OM_OPENTYPE, tt, openTypes); + writeEndObject(out); + break; + default: + break; + } + } + + private void writeOpenTypeField(OutputStream out, byte[] name, OpenType openType, List> openTypes) throws IOException { + int idx = openTypes.indexOf(openType); + if (idx < 0) { + writeIntField(out, name, openTypes.size()); + openTypes.add(openType); + } else { + writeIntField(out, name, idx); + } + } + + private void writeOpenTypes(OutputStream out, List> openTypes) throws IOException { + if (openTypes.isEmpty()) { + return; + } + + writeFieldName(out, OM_OPENTYPES); + writeStartArray(out); + for (int i = 0; i < openTypes.size(); i++) { + writeArrayItem(out); + OpenType ot = openTypes.get(i); + Class clazz = ot.getClass(); + if (clazz == SimpleType.class) { + // - For SimpleType instances: + // String // The name of the simple type. + writeSimpleString(out, ((SimpleType) ot).getTypeName()); + } else { + // - For all other OpenTypes: + // { + // openTypeClass: String, + // className: String, + // typeName: String, + // description: String, + // } + writeStartObject(out); + writeSimpleStringField(out, OM_OPENTYPECLASS, clazz.getName()); + writeSimpleStringField(out, OM_CLASSNAME, ot.getClassName()); + writeStringField(out, OM_TYPENAME, ot.getTypeName()); + writeStringField(out, OM_DESCRIPTION, ot.getDescription()); + if (clazz == ArrayType.class) { + // - ArrayType + // { + // dimension: Integer, + // elementType: Integer, + // } + ArrayType at = (ArrayType) ot; + writeIntField(out, OM_DIMENSION, at.getDimension()); + OpenType elemntType = at.getElementOpenType(); + writeOpenTypeField(out, OM_ELEMENTTYPE, elemntType, openTypes); + } else if (clazz == CompositeType.class) { + // - CompositeType + // { + // items: [ { key: String, description: String, type: Integer } *] + // } + CompositeType ct = (CompositeType) ot; + writeFieldName(out, OM_ITEMS); + writeStartArray(out); + for (String key : ct.keySet()) { + writeArrayItem(out); + writeStartObject(out); + writeStringField(out, OM_KEY, key); + writeStringField(out, OM_DESCRIPTION, ct.getDescription(key)); + writeOpenTypeField(out, OM_TYPE, ct.getType(key), openTypes); + writeEndObject(out); + } + writeEndArray(out); + } else if (clazz == TabularType.class) { + // - TabularType + // { + // rowType: Integer, + // indexNames: [String*] + // } + TabularType tt = (TabularType) ot; + writeOpenTypeField(out, OM_ROWTYPE, tt.getRowType(), openTypes); + writeFieldName(out, OM_INDEXNAMES); + writeStartArray(out); + for (String name : tt.getIndexNames()) { + writeArrayItem(out); + writeStringInternal(out, name); + } + writeEndArray(out); + } else { + // - For unknown OpenTypes + // { + // serialized: Base64 + // } + writeSerializedField(out, OM_SERIALIZED, ot); + } + writeEndObject(out); + } + } + writeEndArray(out); + } + + private Object readPOJOInternal(Object in) throws ConversionException, ClassNotFoundException { + if (in == null) { + return null; + } + if (!(in instanceof JSONObject)) { + throwConversionException("readPOJOInternal() expects a JSONObject.", in); + } + JSONObject json = (JSONObject) in; + Object o = json.get(N_SERIALIZED); + if (o != null) { + // If the original object contains cycle, then java-deserialize it. + return readSerialized(o); + } + if (USE_BASE64_FOR_POJO) { + return null; + } + OpenType[] openTypes = readOpenTypes(json.get(N_OPENTYPES)); + return readPOJOValue(json.get(N_VALUE), json.get(N_TYPE), openTypes); + } + + private OpenType[] readOpenTypes(Object in) throws ConversionException, ClassNotFoundException { + if (in == null) { + return null; + } + if (!(in instanceof JSONArray)) { + throwConversionException("readOpenTypes() expects a JSONArray.", in); + } + + JSONArray json = (JSONArray) in; + int size = json.size(); + OpenType[] openTypes = new OpenType[size]; + try { + for (int i = 0; i < size; i++) { + readOpenType(json, i, openTypes); + } + } catch (OpenDataException e) { + throwConversionException(e, in); + } + return openTypes; + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + private OpenType readOpenType(JSONArray json, int i, OpenType[] openTypes) throws ConversionException, ClassNotFoundException, OpenDataException { + if (openTypes[i] != null) { + return openTypes[i]; + } + Object o = json.get(i); + if (o instanceof String) { + openTypes[i] = Name2SimpleTypes.get(o); + if (openTypes[i] == null) { + throwConversionException("readOpenType() received an unknown simple type name.", o); + } + return openTypes[i]; + } + + if (!(o instanceof JSONObject)) { + throwConversionException("readOpenType() expects a JSONObject.", o); + } + + JSONObject type = (JSONObject) o; + Object serialized = type.get(N_SERIALIZED); + if (serialized != null) { + Object ret = readSerialized(serialized); + if (!(ret instanceof OpenType)) { + throwConversionException("readOpenType() expects an OpenType.", serialized); + } + return openTypes[i] = (OpenType) ret; + } + + String openTypeClass = readStringInternal(type.get(N_OPENTYPECLASS)); + if ("javax.management.openmbean.ArrayType".equals(openTypeClass)) { + int dimension = readIntInternal(type.get(N_DIMENSION)); + int elementType = readIntInternal(type.get(N_ELEMENTTYPE)); + if (elementType < 0 || elementType >= openTypes.length) { + throwConversionException("readOpenType() receives an out-of-range open type index.", type.get(N_ELEMENTTYPE)); + } + OpenType etype = readOpenType(json, elementType, openTypes); + if (etype instanceof SimpleType) { + return openTypes[i] = new ArrayType((SimpleType) etype, true); + } else { + return openTypes[i] = new ArrayType(dimension, etype); + } + } + + if ("javax.management.openmbean.CompositeType".equals(openTypeClass)) { + String typeName = readStringInternal(type.get(N_TYPENAME)); + String description = readStringInternal(type.get(N_DESCRIPTION)); + + o = type.get(N_ITEMS); + if (!(o instanceof JSONArray)) { + throwConversionException("readOpenType() expects a JSONArray.", o); + } + + JSONArray items = (JSONArray) o; + int size = items.size(); + String[] itemNames = new String[size]; + String[] itemDescriptions = new String[size]; + OpenType[] itemTypes = new OpenType[size]; + for (int p = 0; p < size; p++) { + o = items.get(p); + if (!(o instanceof JSONObject)) { + throwConversionException("readOpenType() expects a JSONObject.", o); + } + + JSONObject item = (JSONObject) o; + itemNames[p] = readStringInternal(item.get(N_KEY)); + itemDescriptions[p] = readStringInternal(item.get(N_DESCRIPTION)); + int itemType = readIntInternal(item.get(N_TYPE)); + if (itemType < 0 || itemType >= openTypes.length) { + throwConversionException("readOpenType() receives an out-of-range open type index.", item.get(N_TYPE)); + } + itemTypes[p] = readOpenType(json, itemType, openTypes); + } + return openTypes[i] = new CompositeType(typeName, description, itemNames, itemDescriptions, itemTypes); + } + + if ("javax.management.openmbean.TabularType".equals(openTypeClass)) { + String typeName = readStringInternal(type.get(N_TYPENAME)); + String description = readStringInternal(type.get(N_DESCRIPTION)); + int rowType = readIntInternal(type.get(N_ROWTYPE)); + if (rowType < 0 || rowType >= openTypes.length) { + throwConversionException("readOpenType() receives an out-of-range open type index.", type.get(N_ROWTYPE)); + } + + OpenType rtype = readOpenType(json, rowType, openTypes); + if (!(rtype instanceof CompositeType)) { + throwConversionException("readOpenType() expects a CompositeType.", rtype); + } + + o = type.get(N_INDEXNAMES); + if (!(o instanceof JSONArray)) { + throwConversionException("readOpenType() expects a JSONArray.", o); + } + + JSONArray names = (JSONArray) o; + int size = names.size(); + String[] indexNames = new String[size]; + for (int p = 0; p < size; p++) { + // Service change 119678: + // Original code: indexNames[i] = readStringInternal(names.get(p)); + indexNames[p] = readStringInternal(names.get(p)); + } + return openTypes[i] = new TabularType(typeName, description, (CompositeType) rtype, indexNames); + } + + throwConversionException("readOpenType() received an unknown open type class.", openTypeClass); + return null; + } + + private Object readPOJOValue(Object value, Object type, OpenType[] openTypes) throws ConversionException, ClassNotFoundException { + if (type == null) { + return null; + } + + if (type instanceof String) { + String tstr = (String) type; + TYPE t = SimpleValues.get(tstr); + if (t == null) { + if (tstr.length() > 0 && tstr.charAt(0) == '[') { + return readSimpleArray(value, Class.forName(tstr)); + } + throwConversionException("readPOJOValue() received an unknown class name.", type); + } + return readSimpleValue(value, t); + } + + if (!(type instanceof JSONObject)) { + throwConversionException("readPOJOValue() expects a JSONObject.", type); + } + + JSONObject tjson = (JSONObject) type; + Object o = tjson.get(N_VALUE); + if (o != null) { + return readSerialized(o); + } + + o = tjson.get(N_CLASSNAME); + if (o == null || !(o instanceof String)) { + throwConversionException("readPOJOValue() expects a String.", o); + } + + String className = (String) o; + TYPE t = StructuredClasses.get(className); + if (t == null) { + if (className.length() > 0 && className.charAt(0) == '[') { + return readComplexArray(value, Class.forName(className), tjson.get(N_ITEMS), openTypes); + } + throwConversionException("readPOJOValue() received an unknown class name.", o); + } + switch (t) { + case ArrayList: + return readCollectionValue(value, tjson, new ArrayList(), openTypes); + case LinkedList: + return readCollectionValue(value, tjson, new LinkedList(), openTypes); + case Vector: + return readCollectionValue(value, tjson, new Vector(), openTypes); + case HashSet: + return readCollectionValue(value, tjson, new HashSet(), openTypes); + case HashMap: + return readMapValue(value, tjson, new HashMap(), openTypes); + case Hashtable: + return readMapValue(value, tjson, new Hashtable(), openTypes); + case TreeMap: + return readMapValue(value, tjson, new TreeMap(), openTypes); + case CompositeDataSupport: + case TabularDataSupport: + int ot = readIntInternal(tjson.get(N_OPENTYPE)); + return readOpenData(value, openTypes[ot]); + } + + return null; + } + + private Object readSimpleValue(Object value, TYPE t) throws ConversionException { + if (value == null) { + return null; + } + if (!(value instanceof String)) { + throwConversionException("readSimpleValue() expects a String.", value); + } + String vstr = (String) value; + switch (t) { + case Byte: + return Byte.valueOf(vstr); + case Short: + return Short.valueOf(vstr); + case Integer: + return Integer.valueOf(vstr); + case Long: + return Long.valueOf(vstr); + case Float: + return Float.valueOf(vstr); + case Double: + return Double.valueOf(vstr); + case Character: + if (vstr.length() != 1) { + throwConversionException("readSimpleValue() expects a String of length 1 for Characgter.", value); + } + return Character.valueOf(vstr.charAt(0)); + case Boolean: + return Boolean.valueOf(vstr); + case String: + return vstr; + case BigInteger: + return new BigInteger(vstr); + case BigDecimal: + return new BigDecimal(vstr); + case Date: + return new Date(readLongInternal(vstr)); + case ObjectName: + return readObjectName(vstr); + case Object: + if (vstr.length() != 0) { + throwConversionException("readSimpleValue() expects an empty String for Object.", value); + } + return OBJECT; + } + return null; + } + + private Object readSimpleArray(Object value, Class array) throws ConversionException { + if (value == null) { + return null; + } + if (!(value instanceof JSONArray)) { + throwConversionException("readSimpleArray() expects a JSONArray.", value); + } + JSONArray json = (JSONArray) value; + int size = json.size(); + Class component = array.getComponentType(); + if (component.isArray()) { + Object[] ret = (Object[]) Array.newInstance(component, size); + for (int i = 0; i < size; i++) { + ret[i] = readSimpleArray(json.get(i), component); + } + return ret; + } + if (component.isPrimitive()) { + return readPrimitiveArray(json, SupportedClasses.get(component)); + } + + Object[] ret = (Object[]) Array.newInstance(component, size); + for (int i = 0; i < size; i++) { + ret[i] = readSimpleValue(json.get(i), SupportedClasses.get(component)); + } + return ret; + } + + private Object readPrimitiveArray(JSONArray value, TYPE type) throws ConversionException { + int size = value.size(); + switch (type) { + case _Byte: + case Byte: + byte[] bytes = new byte[size]; + for (int i = 0; i < size; i++) { + bytes[i] = readByteInternal(value.get(i)); + } + return bytes; + case _Short: + case Short: + short[] shorts = new short[size]; + for (int i = 0; i < size; i++) { + shorts[i] = readShortInternal(value.get(i)); + } + return shorts; + case _Integer: + case Integer: + int[] ints = new int[size]; + for (int i = 0; i < size; i++) { + ints[i] = readIntInternal(value.get(i)); + } + return ints; + case _Long: + case Long: + long[] longs = new long[size]; + for (int i = 0; i < size; i++) { + longs[i] = readLongInternal(value.get(i)); + } + return longs; + case _Float: + case Float: + float[] floats = new float[size]; + for (int i = 0; i < size; i++) { + floats[i] = readFloatInternal(value.get(i)); + } + return floats; + case _Double: + case Double: + double[] doubles = new double[size]; + for (int i = 0; i < size; i++) { + doubles[i] = readDoubleInternal(value.get(i)); + } + return doubles; + case _Character: + case Character: + char[] chars = new char[size]; + for (int i = 0; i < size; i++) { + chars[i] = readCharInternal(value.get(i)); + } + return chars; + case _Boolean: + case Boolean: + boolean[] bools = new boolean[size]; + for (int i = 0; i < size; i++) { + bools[i] = readBooleanInternal(value.get(i)); + } + return bools; + } + return null; + } + + private Object readComplexArray(Object value, Class array, Object type, OpenType[] openTypes) throws ConversionException, ClassNotFoundException { + if (!(value instanceof JSONArray)) { + throwConversionException("readComplexArray() expects a JSONArray.", value); + } + if (!(type instanceof JSONArray)) { + throwConversionException("readComplexArray() expects a JSONArray.", type); + } + JSONArray vjson = (JSONArray) value; + JSONArray tjson = (JSONArray) type; + int size = tjson.size(); + if (size != vjson.size()) { + throwConversionException("readComplexArray() expects same size from value and type arrays.", null); + } + + Object[] ret = (Object[]) Array.newInstance(array.getComponentType(), size); + for (int i = 0; i < size; i++) { + ret[i] = readPOJOValue(vjson.get(i), tjson.get(i), openTypes); + } + return ret; + } + + private Object readCollectionValue(Object value, JSONObject t, Collection ret, OpenType[] openTypes) throws ConversionException, ClassNotFoundException { + Object type = t.get(N_ITEMS); + if (!(value instanceof JSONArray)) { + throwConversionException("readCollectionValue() expects a JSONArray.", value); + } + if (!(type instanceof JSONArray)) { + throwConversionException("readCollectionValue() expects a JSONArray.", type); + } + + JSONArray vjson = (JSONArray) value; + JSONArray tjson = (JSONArray) type; + if (vjson.size() != tjson.size()) { + throwConversionException("readCollectionValue() expects same size from value and type arrays.", null); + } + for (int i = 0; i < tjson.size(); i++) { + ret.add(readPOJOValue(vjson.get(i), tjson.get(i), openTypes)); + } + return ret; + } + + private Object readMapValue(Object value, JSONObject t, Map ret, OpenType[] openTypes) throws ConversionException, ClassNotFoundException { + if (value == null) { + return ret; + } + + Object simple = t.get(N_SIMPLEKEY); + + if (simple == null) { + return ret; + } + + if (!(simple instanceof Boolean)) { + throwConversionException("readMapValue() expects a Boolean.", simple); + } + boolean simpleKey = ((Boolean) simple).booleanValue(); + + Object type = t.get(N_ENTRIES); + if (!(type instanceof JSONArray)) { + throwConversionException("readMapValue() expects a JSONArray.", type); + } + JSONArray tjson = (JSONArray) type; + + if (simpleKey) { + if (!(value instanceof JSONObject)) { + throwConversionException("readMapValue() expects a JSONObject.", value); + } + JSONObject vjson = (JSONObject) value; + if (tjson.size() != vjson.size()) { + throwConversionException("readMapValue() expects same size from value and type arrays.", null); + } + for (Object e : tjson) { + if (!(e instanceof JSONObject)) { + throwConversionException("readMapValue() expects a JSONObject.", e); + } + JSONObject entry = (JSONObject) e; + Object k = entry.get(N_KEY); + if (!(k instanceof String)) { + throwConversionException("readMapValue() expects a String.", k); + } + String key = (String) k; + ret.put(readPOJOValue(key, entry.get(N_KEYTYPE), openTypes), + readPOJOValue(vjson.get(key), entry.get(N_VALUE), openTypes)); + } + } else { + if (!(value instanceof JSONArray)) { + throwConversionException("readMapValue() expects a JSONArray.", value); + } + JSONArray vjson = (JSONArray) value; + if (tjson.size() != vjson.size()) { + throwConversionException("readMapValue() expects same size from value and type arrays.", null); + } + for (int i = 0; i < tjson.size(); i++) { + Object te = tjson.get(i); + if (!(te instanceof JSONObject)) { + throwConversionException("readMapValue() expects a JSONObject.", te); + } + JSONObject tentry = (JSONObject) te; + Object ve = vjson.get(i); + if (!(ve instanceof JSONObject)) { + throwConversionException("readMapValue() expects a JSONObject.", ve); + } + JSONObject ventry = (JSONObject) ve; + ret.put(readPOJOValue(ventry.get(N_KEY), tentry.get(N_KEYTYPE), openTypes), + readPOJOValue(ventry.get(N_VALUE), tentry.get(N_VALUE), openTypes)); + } + } + return ret; + } + + private Object readOpenData(Object value, OpenType openType) throws ConversionException { + if (value == null) { + return null; + } + if (openType instanceof SimpleType) { + return readSimpleValue(value, SimpleOpenTypes.get(openType)); + } + if (openType instanceof ArrayType) { + ArrayType at = (ArrayType) openType; + OpenType elementOT = at.getElementOpenType(); + Class elementType = null; + try { + elementType = Class.forName(elementOT.getClassName()); + } catch (ClassNotFoundException e) { + // Should never happen. All open type names are known. + } + + if (!(value instanceof JSONArray)) { + throwConversionException("readOpenData() expects a JSONArray.", value); + } + JSONArray json = (JSONArray) value; + + if (at.isPrimitiveArray()) { + return readPrimitiveArray(json, SupportedClasses.get(elementType)); + } + + int size = json.size(); + Object[] ret = (Object[]) Array.newInstance(elementType, size); + for (int i = 0; i < size; i++) { + ret[i] = readOpenData(json.get(i), elementOT); + } + return ret; + } else if (openType instanceof CompositeType) { + return readCompositeData(value, (CompositeType) openType); + } else if (openType instanceof TabularType) { + TabularType tt = (TabularType) openType; + CompositeType row = tt.getRowType(); + if (!(value instanceof JSONArray)) { + throwConversionException("readOpenData() expects a JSONArray.", value); + } + JSONArray json = (JSONArray) value; + + TabularDataSupport ret = new TabularDataSupport(tt); + for (Object o : json) { + ret.put(readCompositeData(o, row)); + } + return ret; + } + return null; + } + + private CompositeData readCompositeData(Object value, CompositeType ct) throws ConversionException { + Set keys = ct.keySet(); + if (!(value instanceof JSONObject)) { + throwConversionException("readCompositeData() expects a JSONObject.", value); + } + JSONObject json = (JSONObject) value; + + int size = keys.size(); + if (size != json.size()) { + throwConversionException("readCompositeData() expects the same number of entries as in the type.", json); + } + + String[] names = new String[size]; + Object[] values = new Object[size]; + int i = 0; + for (String key : keys) { + names[i] = key; + values[i++] = readOpenData(json.get(key), ct.getType(key)); + } + try { + return new CompositeDataSupport(ct, names, values); + } catch (OpenDataException e) { + // Should never happen. All names/values are constructed based + // on the open type. + } + return null; + } + + private void writePOJOArrayField(OutputStream out, byte[] name, Object[] value) throws IOException { + if (value == null) { + return; + } + writeFieldName(out, name); + writePOJOArray(out, value); + } + + private void writePOJOArray(OutputStream out, Object[] value) throws IOException { + writeStartArray(out); + for (Object o : value) { + writeArrayItem(out); + writePOJOInternal(out, o); + } + writeEndArray(out); + } + + private Object[] readPOJOArray(Object in) throws ConversionException, ClassNotFoundException { + if (in == null) { + return null; + } + if (!(in instanceof JSONArray)) { + throwConversionException("readPOJOArray() expects a JSONArray.", in); + } + JSONArray json = (JSONArray) in; + int size = json.size(); + Object[] ret = new Object[size]; + for (int i = 0; i < size; i++) { + ret[i] = readPOJOInternal(json.get(i)); + } + return ret; + } + + private void writeObjectNameListField(OutputStream out, byte[] name, List value) throws IOException { + if (value == null) { + return; + } + writeFieldName(out, name); + writeStartArray(out); + for (ObjectName item : value) { + writeArrayItem(out); + writeObjectName(out, item); + } + writeEndArray(out); + } + + private List readObjectNameList(Object in) throws ConversionException { + if (in == null) { + return null; + } + if (!(in instanceof JSONArray)) { + throwConversionException("readObjectNameList() expects a JSONArray.", in); + } + JSONArray json = (JSONArray) in; + int size = json.size(); + List ret = new ArrayList(size); + for (Object o : json) { + ret.add(readObjectName(o)); + } + return ret; + } + + private void writeObjectNameField(OutputStream out, byte[] name, ObjectName value) throws IOException { + if (value == null) { + return; + } + writeFieldName(out, name); + writeObjectName(out, value); + } + + private void writeObjectName(OutputStream out, ObjectName value) throws IOException { + // ObjectName has no known sub-class. + writeStringInternal(out, value.toString()); + } + + private ObjectName readObjectName(Object in) throws ConversionException { + if (in == null) { + return null; + } + try { + return new ObjectName(readStringInternal(in)); + } catch (MalformedObjectNameException e) { + throwConversionException(e, in); + return null; + } + } + + private ObjectInstanceWrapper readObjectInstanceInternal(Object in) throws ConversionException { + if (!(in instanceof JSONObject)) { + throwConversionException("readObjectInstanceInternal() expects a JSONObject.", in); + } + JSONObject json = (JSONObject) in; + ObjectName objectName = readObjectName(json.get(N_OBJECTNAME)); + String className = readStringInternal(json.get(N_CLASSNAME)); + ObjectInstanceWrapper ret = new ObjectInstanceWrapper(); + ret.objectInstance = new ObjectInstance(objectName, className); + ret.mbeanInfoURL = readStringInternal(json.get(N_URL)); + return ret; + } + + private void writeDescriptor(OutputStream out, byte[] name, Descriptor value) throws IOException { + if (value == null) { + return; + } + writeFieldName(out, name); + writeStartObject(out); + String[] names = value.getFieldNames(); + writeStringArrayField(out, OM_NAMES, names); + writePOJOArrayField(out, OM_VALUES, value.getFieldValues(names)); + writeEndObject(out); + } + + private Descriptor readDescriptor(Object in) throws ConversionException, ClassNotFoundException { + if (in == null) { + return null; + } + if (!(in instanceof JSONObject)) { + throwConversionException("readDescriptor() expects a JSONObject.", in); + } + JSONObject json = (JSONObject) in; + String[] names = readStringArrayInternal(json.get(N_NAMES)); + Object[] values = readPOJOArray(json.get(N_VALUES)); + // All descriptors (on the client side) are immutable + return new ImmutableDescriptor(names, values); + } + + private void writeAttributes(OutputStream out, byte[] name, MBeanAttributeInfo[] value, Map urls) throws IOException { + if (value == null) { + return; + } + writeFieldName(out, name); + writeStartArray(out); + for (MBeanAttributeInfo item : value) { + writeArrayItem(out); + writeStartObject(out); + writeStringField(out, OM_NAME, item.getName()); + writeStringField(out, OM_TYPE, item.getType()); + writeStringField(out, OM_DESCRIPTION, item.getDescription()); + writeDescriptor(out, OM_DESCRIPTOR, item.getDescriptor()); + writeBooleanField(out, OM_ISIS, item.isIs()); + writeBooleanField(out, OM_ISREADABLE, item.isReadable()); + writeBooleanField(out, OM_ISWRITABLE, item.isWritable()); + assert urls.containsKey(item.getName()); + writeStringField(out, OM_URL, urls.get(item.getName())); + writeEndObject(out); + } + writeEndArray(out); + } + + private MBeanAttributeInfo[] readAttributes(Object in, Map urls) throws ConversionException, ClassNotFoundException { + if (in == null) { + return null; + } + if (!(in instanceof JSONArray)) { + throwConversionException("readAttributes() expects a JSONArray.", in); + } + JSONArray json = (JSONArray) in; + MBeanAttributeInfo[] ret = new MBeanAttributeInfo[json.size()]; + int pos = 0; + for (Object item : json) { + if (!(item instanceof JSONObject)) { + throwConversionException("readAttributes() expects a JSONObject.", item); + } + JSONObject value = (JSONObject) item; + String name = readStringInternal(value.get(N_NAME)); + String type = readStringInternal(value.get(N_TYPE)); + String description = readStringInternal(value.get(N_DESCRIPTION)); + boolean isReadable = readBooleanInternal(value.get(N_ISREADABLE)); + boolean isWritable = readBooleanInternal(value.get(N_ISWRITABLE)); + boolean isIs = readBooleanInternal(value.get(N_ISIS)); + Descriptor descriptor = readDescriptor(value.get(N_DESCRIPTOR)); + ret[pos++] = new MBeanAttributeInfo(name, type, description, + isReadable, isWritable, isIs, + descriptor); + urls.put(name, readStringInternal(value.get(N_URL))); + } + return ret; + } + + private void writeConstructors(OutputStream out, byte[] name, MBeanConstructorInfo[] value) throws IOException { + if (value == null) { + return; + } + writeFieldName(out, name); + writeStartArray(out); + for (MBeanConstructorInfo item : value) { + writeArrayItem(out); + writeStartObject(out); + writeStringField(out, OM_NAME, item.getName()); + writeStringField(out, OM_DESCRIPTION, item.getDescription()); + writeDescriptor(out, OM_DESCRIPTOR, item.getDescriptor()); + writeParameters(out, OM_SIGNATURE, item.getSignature()); + writeEndObject(out); + } + writeEndArray(out); + } + + private MBeanConstructorInfo[] readConstructors(Object in) throws ConversionException, ClassNotFoundException { + if (in == null) { + return null; + } + if (!(in instanceof JSONArray)) { + throwConversionException("readConstructors() expects a JSONArray.", in); + } + JSONArray json = (JSONArray) in; + MBeanConstructorInfo[] ret = new MBeanConstructorInfo[json.size()]; + int pos = 0; + for (Object item : json) { + if (!(item instanceof JSONObject)) { + throwConversionException("readConstructors() expects a JSONObject.", item); + } + JSONObject value = (JSONObject) item; + String name = readStringInternal(value.get(N_NAME)); + String description = readStringInternal(value.get(N_DESCRIPTION)); + MBeanParameterInfo[] signature = readParameters(value.get(N_SIGNATURE)); + Descriptor descriptor = readDescriptor(value.get(N_DESCRIPTOR)); + ret[pos++] = new MBeanConstructorInfo(name, description, + signature, descriptor); + } + return ret; + } + + private void writeParameters(OutputStream out, byte[] name, MBeanParameterInfo[] value) throws IOException { + if (value == null) { + return; + } + writeFieldName(out, name); + writeStartArray(out); + for (MBeanParameterInfo item : value) { + writeArrayItem(out); + writeStartObject(out); + writeStringField(out, OM_NAME, item.getName()); + writeStringField(out, OM_TYPE, item.getType()); + writeStringField(out, OM_DESCRIPTION, item.getDescription()); + writeDescriptor(out, OM_DESCRIPTOR, item.getDescriptor()); + writeEndObject(out); + } + writeEndArray(out); + } + + private MBeanParameterInfo[] readParameters(Object in) throws ConversionException, ClassNotFoundException { + if (in == null) { + return null; + } + if (!(in instanceof JSONArray)) { + throwConversionException("readParameters() expects a JSONArray.", in); + } + JSONArray json = (JSONArray) in; + MBeanParameterInfo[] ret = new MBeanParameterInfo[json.size()]; + int pos = 0; + for (Object item : json) { + if (!(item instanceof JSONObject)) { + throwConversionException("readParameters() expects a JSONObject.", item); + } + JSONObject value = (JSONObject) item; + String name = readStringInternal(value.get(N_NAME)); + String type = readStringInternal(value.get(N_TYPE)); + String description = readStringInternal(value.get(N_DESCRIPTION)); + Descriptor descriptor = readDescriptor(value.get(N_DESCRIPTOR)); + ret[pos++] = new MBeanParameterInfo(name, type, description, + descriptor); + } + return ret; + } + + private void writeNotifications(OutputStream out, byte[] name, MBeanNotificationInfo[] value) throws IOException { + if (value == null) { + return; + } + writeFieldName(out, name); + writeStartArray(out); + for (MBeanNotificationInfo item : value) { + writeArrayItem(out); + writeStartObject(out); + writeStringField(out, OM_NAME, item.getName()); + writeStringField(out, OM_DESCRIPTION, item.getDescription()); + writeDescriptor(out, OM_DESCRIPTOR, item.getDescriptor()); + writeStringArrayField(out, OM_NOTIFTYPES, item.getNotifTypes()); + writeEndObject(out); + } + writeEndArray(out); + } + + private MBeanNotificationInfo[] readNotifications(Object in) throws ConversionException, ClassNotFoundException { + if (in == null) { + return null; + } + if (!(in instanceof JSONArray)) { + throwConversionException("readNotifications() expects a JSONArray.", in); + } + JSONArray json = (JSONArray) in; + MBeanNotificationInfo[] ret = new MBeanNotificationInfo[json.size()]; + int pos = 0; + for (Object item : json) { + if (!(item instanceof JSONObject)) { + throwConversionException("readNotifications() expects a JSONObject.", item); + } + JSONObject value = (JSONObject) item; + String name = readStringInternal(value.get(N_NAME)); + String description = readStringInternal(value.get(N_DESCRIPTION)); + String[] notifTypes = readStringArrayInternal(value.get(N_NOTIFTYPES)); + Descriptor descriptor = readDescriptor(value.get(N_DESCRIPTOR)); + ret[pos++] = new MBeanNotificationInfo(notifTypes, name, description, + descriptor); + } + return ret; + } + + private void writeOperations(OutputStream out, byte[] name, MBeanOperationInfo[] value, Map urls) throws IOException { + if (value == null) { + return; + } + writeFieldName(out, name); + writeStartArray(out); + for (MBeanOperationInfo item : value) { + writeArrayItem(out); + writeStartObject(out); + writeStringField(out, OM_NAME, item.getName()); + writeStringField(out, OM_DESCRIPTION, item.getDescription()); + writeDescriptor(out, OM_DESCRIPTOR, item.getDescriptor()); + writeIntField(out, OM_IMPACT, item.getImpact()); + writeStringField(out, OM_RETURNTYPE, item.getReturnType()); + writeParameters(out, OM_SIGNATURE, item.getSignature()); + assert urls.containsKey(item.getName()); + writeStringField(out, OM_URL, urls.get(item.getName())); + writeEndObject(out); + } + writeEndArray(out); + } + + private MBeanOperationInfo[] readOperations(Object in, Map urls) throws ConversionException, ClassNotFoundException { + if (in == null) { + return null; + } + if (!(in instanceof JSONArray)) { + throwConversionException("readOperations() expects a JSONArray.", in); + } + JSONArray json = (JSONArray) in; + MBeanOperationInfo[] ret = new MBeanOperationInfo[json.size()]; + int pos = 0; + for (Object item : json) { + if (!(item instanceof JSONObject)) { + throwConversionException("readOperations() expects a JSONObject.", item); + } + JSONObject value = (JSONObject) item; + String description = readStringInternal(value.get(N_DESCRIPTION)); + String name = readStringInternal(value.get(N_NAME)); + int impact = readIntInternal(value.get(N_IMPACT)); + String returnType = readStringInternal(value.get(N_RETURNTYPE)); + MBeanParameterInfo[] signature = readParameters(value.get(N_SIGNATURE)); + Descriptor descriptor = readDescriptor(value.get(N_DESCRIPTOR)); + ret[pos++] = new MBeanOperationInfo(name, description, signature, + returnType, impact, descriptor); + urls.put(name, readStringInternal(value.get(N_URL))); + } + return ret; + } + + private void writeNotificationFiltersField(OutputStream out, byte[] name, NotificationFilter[] value) throws IOException { + if (value == null) { + return; + } + writeFieldName(out, name); + writeNotificationFiltersInternal(out, value); + } + + private void writeNotificationFiltersInternal(OutputStream out, NotificationFilter[] value) throws IOException { + writeStartArray(out); + if (value != null) { + for (NotificationFilter item : value) { + writeArrayItem(out); + writeNotificationFilterInternal(out, item, false); + } + } + writeEndArray(out); + } + + private void writeNotificationFilterInternal(OutputStream out, NotificationFilter value, boolean allowOther) throws IOException { + assert value != null; + writeStartObject(out); + Class clazz = value.getClass(); + writeSimpleStringField(out, OM_CLASSNAME, clazz.getName()); + if (clazz == AttributeChangeNotificationFilter.class) { + writeFieldName(out, OM_ENABLED); + writeStartArray(out); + for (String e : ((AttributeChangeNotificationFilter) value).getEnabledAttributes()) { + writeArrayItem(out); + writeStringInternal(out, e); + } + writeEndArray(out); + } else if (clazz == MBeanServerNotificationFilter.class) { + MBeanServerNotificationFilter filter = (MBeanServerNotificationFilter) value; + byte[] fieldName = OM_ENABLED; + Vector list = filter.getEnabledObjectNames(); + if (list == null) { + fieldName = OM_DISABLED; + list = filter.getDisabledObjectNames(); + } + writeFieldName(out, fieldName); + writeStartArray(out); + for (ObjectName e : list) { + writeArrayItem(out); + writeStringInternal(out, e.toString()); + } + writeEndArray(out); + writeFieldName(out, OM_TYPES); + writeStartArray(out); + for (String e : ((MBeanServerNotificationFilter) value).getEnabledTypes()) { + writeArrayItem(out); + writeStringInternal(out, e); + } + writeEndArray(out); + } else if (clazz == NotificationFilterSupport.class) { + writeFieldName(out, OM_TYPES); + writeStartArray(out); + for (String e : ((NotificationFilterSupport) value).getEnabledTypes()) { + writeArrayItem(out); + writeStringInternal(out, e); + } + writeEndArray(out); + } else if (allowOther) { + writeSerializedField(out, OM_SERIALIZED, value); + } else { + // The caller guarantees that only the known classes are used. + assert false; + } + writeEndObject(out); + } + + private void writeNotificationFilterField(OutputStream out, byte[] name, NotificationFilter value) throws IOException { + if (value == null) { + return; + } + writeFieldName(out, name); + writeNotificationFilterInternal(out, value, true); + } + + private NotificationFilter[] readNotificationFiltersInternal(Object in) throws ConversionException, ClassNotFoundException { + if (in == null) { + return null; + } + if (!(in instanceof JSONArray)) { + throwConversionException("readNotificationFiltersInternal() expects a JSONArray.", in); + } + JSONArray json = (JSONArray) in; + NotificationFilter[] ret = new NotificationFilter[json.size()]; + int pos = 0; + for (Object item : json) { + if ((ret[pos++] = readNotificationFilterInternal(item, false)) == null) { + throwConversionException("readNotificationFilterInternal() received a null NotificationListener.", in); + } + } + return ret; + } + + private NotificationFilter readNotificationFilterInternal(Object in, boolean allowOther) throws ConversionException, ClassNotFoundException { + if (in == null) { + return null; + } + if (!(in instanceof JSONObject)) { + throwConversionException("readNotificationFilterInternal() expects a JSONObject.", in); + } + JSONObject json = (JSONObject) in; + String className = readStringInternal(json.get(N_CLASSNAME)); + if ("javax.management.AttributeChangeNotificationFilter".equals(className)) { + AttributeChangeNotificationFilter filter = new AttributeChangeNotificationFilter(); + String[] enabled = readStringArrayInternal(json.get(N_ENABLED)); + for (String item : enabled) { + filter.enableAttribute(item); + } + return filter; + } else if ("javax.management.relation.MBeanServerNotificationFilter".equals(className)) { + MBeanServerNotificationFilter filter = new MBeanServerNotificationFilter(); + String[] enabled = readStringArrayInternal(json.get(N_ENABLED)); + if (enabled != null) { + for (String item : enabled) { + filter.enableObjectName(readObjectName(item)); + } + } else { + String[] disabled = readStringArrayInternal(json.get(N_DISABLED)); + + if (disabled != null) { + if (disabled.length == 0) { + filter.enableAllObjectNames(); + } else { + for (String item : disabled) { + filter.disableObjectName(readObjectName(item)); + } + } + } + } + String[] types = readStringArrayInternal(json.get(N_TYPES)); + for (String item : types) { + filter.enableType(item); + } + return filter; + } else if ("javax.management.NotificationFilterSupport".equals(className)) { + NotificationFilterSupport filter = new NotificationFilterSupport(); + String[] types = readStringArrayInternal(json.get(N_TYPES)); + for (String item : types) { + filter.enableType(item); + } + return filter; + } else if (allowOther) { + Object o = readSerialized(json.get(N_SERIALIZED)); + if (!(o instanceof NotificationFilter)) { + throwConversionException("readNotificationFilterInternal() expects a NotificationFilter.", in); + } + return (NotificationFilter) o; + } + throwConversionException("readNotificationFilterInternal() received an unknown filter class.", className); + return null; + } + + private void utf8EncodeError(Object json) throws ConversionException { + throwConversionException("encodeStringAsBase64Internal() can't encode the value in UTF-8.", json); + } + + private void base64DecodeError(Object json) throws ConversionException { + throwConversionException("readSerialized() received invalid base64 string.", json); + } + + private static String combineErrorMessage(String message, Object json) throws ConversionException { + try { + if (json instanceof JSONArtifact) { + message = message + "\n\t" + ((JSONArtifact) json).serialize(true); + } else if (json != null) { + message = message + "\n\t" + json.toString(); + } + } catch (IOException e) { + // Should never happen + } + return message; + } + + private static void throwConversionException(String message, Object json) throws ConversionException { + throw new ConversionException(combineErrorMessage(message, json)); + } + + public static void throwConversionException(Throwable t, Object json) throws ConversionException { + throw new ConversionException(combineErrorMessage(t.getMessage(), json), t); + } + + static class DefaultSerializationHelper implements SerializationHelper { + + @Override + public Object readObject(Object in, int blen, byte[] binary) throws ClassNotFoundException, ConversionException { + try { + return new ObjectInputStream(new ByteArrayInputStream(binary, 0, blen)).readObject(); + } catch (IOException e) { + throwConversionException(e, in); + return null; + } + } + } +} diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/converter/NotificationRecord.java b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/converter/NotificationRecord.java new file mode 100755 index 00000000000..e3fb940bbaa --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/converter/NotificationRecord.java @@ -0,0 +1,52 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jmx.connector.converter; + +import javax.management.Notification; +import javax.management.ObjectName; + +/** + * Data structure containing a JMX Notification and information about which target it came from. + */ +public final class NotificationRecord { + + private final Notification n; + private final NotificationTargetInformation nti; + + public NotificationRecord(Notification n, ObjectName name) { + this.n = n; + this.nti = new NotificationTargetInformation(name); + } + + public NotificationRecord(Notification n, String name) { + this.n = n; + this.nti = new NotificationTargetInformation(name); + } + + public NotificationRecord(Notification n, ObjectName name, String hostName, String serverName, String serverUserDir) { + this.n = n; + this.nti = new NotificationTargetInformation(name, hostName, serverName, serverUserDir); + } + + public NotificationRecord(Notification n, String name, String hostName, String serverName, String serverUserDir) { + this.n = n; + this.nti = new NotificationTargetInformation(name, hostName, serverName, serverUserDir); + } + + public Notification getNotification() { + return n; + } + + public NotificationTargetInformation getNotificationTargetInformation() { + return nti; + } +} diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/converter/NotificationTargetInformation.java b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/converter/NotificationTargetInformation.java new file mode 100755 index 00000000000..0ff818359b5 --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/converter/NotificationTargetInformation.java @@ -0,0 +1,120 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jmx.connector.converter; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import javax.management.ObjectName; + +import com.ibm.ws.jmx.connector.client.rest.ClientProvider; + +/** + * Routing information for a JMX Notification which helps the connector + * to correlate a Notification with the appropriate NotificationListener. + * Combined with the ObjectName, the routing information provides a unique + * identifier for an MBean in a cluster of servers. + */ +public final class NotificationTargetInformation { + + private ObjectName name; + private final String nameAsString; + private final Map routingInfo; + + public NotificationTargetInformation(ObjectName name) { + this(name.getCanonicalName()); + this.name = name; + } + + public NotificationTargetInformation(String name) { + this.nameAsString = name; + this.routingInfo = null; + } + + public NotificationTargetInformation(ObjectName name, String hostName, String serverName, String serverUserDir) { + this(name.getCanonicalName(), hostName, serverName, serverUserDir); + this.name = name; + } + + public NotificationTargetInformation(String name, String hostName, String serverName, String serverUserDir) { + Map routingInfo = new HashMap(); + routingInfo.put(ClientProvider.ROUTING_KEY_HOST_NAME, hostName); + routingInfo.put(ClientProvider.ROUTING_KEY_SERVER_NAME, serverName); + routingInfo.put(ClientProvider.ROUTING_KEY_SERVER_USER_DIR, serverUserDir); + this.nameAsString = name; + this.routingInfo = Collections.unmodifiableMap(routingInfo); + } + + public NotificationTargetInformation(ObjectName name, Map routingInfo) { + this(name.getCanonicalName(), routingInfo); + this.name = name; + } + + public NotificationTargetInformation(String name, Map routingInfo) { + this.nameAsString = name; + this.routingInfo = (routingInfo != null) ? Collections.unmodifiableMap(new HashMap(routingInfo)) : null; + } + + // Returns null if this object was not constructed with an ObjectName. + public ObjectName getName() { + return name; + } + + public String getNameAsString() { + return nameAsString; + } + + public Map getRoutingInformation() { + return routingInfo; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof NotificationTargetInformation)) { + return false; + } + NotificationTargetInformation other = (NotificationTargetInformation) obj; + return (nameAsString == other.nameAsString || (nameAsString != null && nameAsString.equals(other.nameAsString))) && + (routingInfo == other.routingInfo || (routingInfo != null && routingInfo.equals(other.routingInfo))); + } + + @Override + public int hashCode() { + if (routingInfo != null) { + int hash = routingInfo.hashCode() * 37; + if (nameAsString != null) { + hash += nameAsString.hashCode(); + } + return hash; + } else if (nameAsString != null) { + return nameAsString.hashCode(); + } + return 0; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("[ObjectName: "); + sb.append(nameAsString); + if (routingInfo != null) { + sb.append(", RoutingInfo: "); + sb.append(routingInfo); + } + sb.append(']'); + return sb.toString(); + } +} \ No newline at end of file diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/converter/SerializationHelper.java b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/converter/SerializationHelper.java new file mode 100755 index 00000000000..4e96f87549e --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/converter/SerializationHelper.java @@ -0,0 +1,20 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jmx.connector.converter; + +import com.ibm.ws.jmx.connector.datatypes.ConversionException; + +public interface SerializationHelper { + + public Object readObject(Object in, int blen, byte[] binary) throws ClassNotFoundException, ConversionException; + +} diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/converter/package-info.java b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/converter/package-info.java new file mode 100755 index 00000000000..5517c821851 --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/converter/package-info.java @@ -0,0 +1,17 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +/** + * @version 1.0 + */ +@org.osgi.annotation.versioning.Version("1.0") +package com.ibm.ws.jmx.connector.converter; + diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/datatypes/ConversionException.java b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/datatypes/ConversionException.java new file mode 100755 index 00000000000..d0524432ad5 --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/datatypes/ConversionException.java @@ -0,0 +1,24 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jmx.connector.datatypes; + +public final class ConversionException extends Exception { + private static final long serialVersionUID = -2548273252032545919L; + + public ConversionException(String message) { + super(message); + } + + public ConversionException(String message, Throwable t) { + super(message, t); + } +} diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/datatypes/CreateMBean.java b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/datatypes/CreateMBean.java new file mode 100755 index 00000000000..dcc068e985e --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/datatypes/CreateMBean.java @@ -0,0 +1,21 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jmx.connector.datatypes; + +import javax.management.ObjectName; + +public final class CreateMBean { + public ObjectName objectName, loaderName; + public String className, signature[]; + public Object params[]; + public boolean useLoader, useSignature; +} diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/datatypes/Invocation.java b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/datatypes/Invocation.java new file mode 100755 index 00000000000..d886c59a24e --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/datatypes/Invocation.java @@ -0,0 +1,20 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jmx.connector.datatypes; + +/** + * + */ +public final class Invocation { + public String signature[]; + public Object params[]; +} diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/datatypes/JMXServerInfo.java b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/datatypes/JMXServerInfo.java new file mode 100755 index 00000000000..f522876b1e4 --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/datatypes/JMXServerInfo.java @@ -0,0 +1,20 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012-2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jmx.connector.datatypes; + +/** + * + */ +public final class JMXServerInfo { + public int version; + public String mbeansURL, createMBeanURL, mbeanCountURL, defaultDomainURL, domainsURL, notificationsURL, instanceOfURL, fileTransferURL, apiURL, graphURL; +} diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/datatypes/MBeanInfoWrapper.java b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/datatypes/MBeanInfoWrapper.java new file mode 100755 index 00000000000..e2780629057 --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/datatypes/MBeanInfoWrapper.java @@ -0,0 +1,25 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jmx.connector.datatypes; + +import java.util.Map; + +import javax.management.MBeanInfo; + +/** + * + */ +public final class MBeanInfoWrapper { + public MBeanInfo mbeanInfo; + public String attributesURL; + public Map attributeURLs, operationURLs; +} diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/datatypes/MBeanQuery.java b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/datatypes/MBeanQuery.java new file mode 100755 index 00000000000..b329fa0e82c --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/datatypes/MBeanQuery.java @@ -0,0 +1,24 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jmx.connector.datatypes; + +import javax.management.ObjectName; +import javax.management.QueryExp; + +/** + * + */ +public final class MBeanQuery { + public ObjectName objectName; + public QueryExp queryExp; + public String className; +} diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/datatypes/NotificationArea.java b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/datatypes/NotificationArea.java new file mode 100755 index 00000000000..7d1a199fb53 --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/datatypes/NotificationArea.java @@ -0,0 +1,19 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jmx.connector.datatypes; + +/** + * + */ +public final class NotificationArea { + public String registrationsURL, serverRegistrationsURL, inboxURL, clientURL; +} diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/datatypes/NotificationRegistration.java b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/datatypes/NotificationRegistration.java new file mode 100755 index 00000000000..87adcd57d0c --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/datatypes/NotificationRegistration.java @@ -0,0 +1,23 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jmx.connector.datatypes; + +import javax.management.NotificationFilter; +import javax.management.ObjectName; + +/** + * + */ +public final class NotificationRegistration { + public ObjectName objectName; + public NotificationFilter filters[]; +} diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/datatypes/NotificationSettings.java b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/datatypes/NotificationSettings.java new file mode 100755 index 00000000000..e82f19b3637 --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/datatypes/NotificationSettings.java @@ -0,0 +1,17 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jmx.connector.datatypes; + +public final class NotificationSettings { + public int deliveryInterval; + public int inboxExpiry; +} diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/datatypes/ObjectInstanceWrapper.java b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/datatypes/ObjectInstanceWrapper.java new file mode 100755 index 00000000000..c7521a71bc8 --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/datatypes/ObjectInstanceWrapper.java @@ -0,0 +1,22 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jmx.connector.datatypes; + +import javax.management.ObjectInstance; + +/** + * + */ +public final class ObjectInstanceWrapper { + public ObjectInstance objectInstance; + public String mbeanInfoURL; +} diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/datatypes/ServerNotificationRegistration.java b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/datatypes/ServerNotificationRegistration.java new file mode 100755 index 00000000000..d45ca1e3597 --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/datatypes/ServerNotificationRegistration.java @@ -0,0 +1,27 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jmx.connector.datatypes; + +import javax.management.NotificationFilter; +import javax.management.ObjectName; + +public final class ServerNotificationRegistration { + public enum Operation { + Add, RemoveAll, RemoveSpecific + } + + public Operation operation; + public ObjectName objectName, listener; + public NotificationFilter filter; + public Object handback; + public int filterID, handbackID; +} diff --git a/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/datatypes/package-info.java b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/datatypes/package-info.java new file mode 100755 index 00000000000..735402c8433 --- /dev/null +++ b/dev/com.ibm.ws.jmx.connector.client.rest/src/com/ibm/ws/jmx/connector/datatypes/package-info.java @@ -0,0 +1,17 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +/** + * @version 1.0 + */ +@org.osgi.annotation.versioning.Version("1.0") +package com.ibm.ws.jmx.connector.datatypes; + diff --git a/dev/com.ibm.ws.jmx_fat/.classpath b/dev/com.ibm.ws.jmx_fat/.classpath new file mode 100644 index 00000000000..c422489df40 --- /dev/null +++ b/dev/com.ibm.ws.jmx_fat/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/dev/com.ibm.ws.jmx_fat/.classpath.gradle b/dev/com.ibm.ws.jmx_fat/.classpath.gradle new file mode 100644 index 00000000000..c422489df40 --- /dev/null +++ b/dev/com.ibm.ws.jmx_fat/.classpath.gradle @@ -0,0 +1,7 @@ + + + + + + + diff --git a/dev/com.ibm.ws.jmx_fat/.gitignore b/dev/com.ibm.ws.jmx_fat/.gitignore new file mode 100644 index 00000000000..27e131e35a6 --- /dev/null +++ b/dev/com.ibm.ws.jmx_fat/.gitignore @@ -0,0 +1 @@ +/bootstrapping.properties diff --git a/dev/com.ibm.ws.jmx_fat/.project b/dev/com.ibm.ws.jmx_fat/.project new file mode 100755 index 00000000000..7aea1fcf31c --- /dev/null +++ b/dev/com.ibm.ws.jmx_fat/.project @@ -0,0 +1,23 @@ + + + com.ibm.ws.jmx_fat + + + + + + org.eclipse.jdt.core.javabuilder + + + + + bndtools.core.bndbuilder + + + + + + org.eclipse.jdt.core.javanature + bndtools.core.bndnature + + diff --git a/dev/com.ibm.ws.jmx_fat/.settings/org.eclipse.core.resources.prefs b/dev/com.ibm.ws.jmx_fat/.settings/org.eclipse.core.resources.prefs new file mode 100755 index 00000000000..2d37f3472a8 --- /dev/null +++ b/dev/com.ibm.ws.jmx_fat/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,4 @@ +#Ant properties +#Automatically generated by the ant prepare.settings.files task +encoding/=UTF-8 +eclipse.preferences.version=1 diff --git a/dev/com.ibm.ws.jmx_fat/.settings/org.eclipse.jdt.core.prefs b/dev/com.ibm.ws.jmx_fat/.settings/org.eclipse.jdt.core.prefs new file mode 100755 index 00000000000..462d94d2e7b --- /dev/null +++ b/dev/com.ibm.ws.jmx_fat/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,280 @@ +#Ant properties +#Automatically generated by the ant prepare.settings.files task +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0 +org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line +org.eclipse.jdt.core.formatter.join_lines_in_comments=false +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false +org.eclipse.jdt.core.formatter.comment.indent_root_tags=true +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=0 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert +org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=4 +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert +org.eclipse.jdt.core.formatter.blank_lines_before_method=1 +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true +org.eclipse.jdt.core.formatter.use_on_off_tags=false +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.comment.format_html=false +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=0 +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert +org.eclipse.jdt.core.formatter.alignment_for_enum_constants=16 +org.eclipse.jdt.core.formatter.tabulation.size=4 +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=do not insert +org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=true +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert +org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false +org.eclipse.jdt.core.formatter.tabulation.char=space +org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=18 +org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=0 +org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off +org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 +org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert +org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert +org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert +org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert +org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 +org.eclipse.jdt.core.formatter.join_wrapped_lines=false +org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 +org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert +org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=true +org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert +org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.blank_lines_before_field=0 +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=do not insert +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert +org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false +org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert +org.eclipse.jdt.core.formatter.comment.format_block_comments=true +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false +org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=false +org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line +org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false +org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=false +org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 +org.eclipse.jdt.core.formatter.lineSplit=180 +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=0 +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=2 +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=2 +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.blank_lines_before_package=0 +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert +org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert +org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=do not insert +org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false +org.eclipse.jdt.core.formatter.align_type_members_on_columns=false +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 +org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert +org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.comment.format_header=false +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert +org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=0 +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=do not insert +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=20 +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=0 +org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert +org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=18 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=18 +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert +org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=2 +org.eclipse.jdt.core.formatter.indentation.size=8 +org.eclipse.jdt.core.formatter.alignment_for_assignment=0 +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert +org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.indent_empty_lines=false +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.comment.format_line_comments=false +org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=18 +org.eclipse.jdt.core.formatter.alignment_for_binary_expression=18 +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=do not insert +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=4 +org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert +org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true +org.eclipse.jdt.core.formatter.compact_else_if=true +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.compiler.source=1.6 +org.eclipse.jdt.core.formatter.comment.format_source_code=true +org.eclipse.jdt.core.formatter.comment.line_length=180 +org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert +org.eclipse.jdt.core.formatter.continuation_indentation=4 +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert diff --git a/dev/com.ibm.ws.jmx_fat/.settings/org.eclipse.jdt.ui.prefs b/dev/com.ibm.ws.jmx_fat/.settings/org.eclipse.jdt.ui.prefs new file mode 100755 index 00000000000..bf3c1827a5d --- /dev/null +++ b/dev/com.ibm.ws.jmx_fat/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,62 @@ +#Ant properties +#Automatically generated by the ant prepare.settings.files task +sp_cleanup.add_missing_override_annotations=true +org.eclipse.jdt.ui.text.custom_code_templates= +sp_cleanup.convert_to_enhanced_for_loop=false +sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true +sp_cleanup.remove_unnecessary_nls_tags=true +editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true +sp_cleanup.make_variable_declarations_final=true +sp_cleanup.add_generated_serial_version_id=false +sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true +sp_cleanup.remove_trailing_whitespaces_ignore_empty=false +sp_cleanup.always_use_this_for_non_static_method_access=false +sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true +sp_cleanup.remove_unused_private_methods=true +sp_cleanup.sort_members=false +sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true +sp_cleanup.remove_trailing_whitespaces=true +sp_cleanup.remove_unused_private_members=false +org.eclipse.jdt.ui.staticondemandthreshold=99 +sp_cleanup.make_parameters_final=false +sp_cleanup.make_private_fields_final=true +sp_cleanup.remove_unused_imports=true +sp_cleanup.remove_unnecessary_casts=true +sp_cleanup.always_use_parentheses_in_expressions=false +sp_cleanup.make_local_variable_final=false +sp_cleanup.use_this_for_non_static_method_access=false +sp_cleanup.remove_private_constructors=true +sp_cleanup.qualify_static_method_accesses_with_declaring_class=false +sp_cleanup.remove_trailing_whitespaces_all=true +sp_cleanup.add_missing_deprecated_annotations=true +sp_cleanup.add_missing_annotations=true +sp_cleanup.never_use_parentheses_in_expressions=true +sp_cleanup.organize_imports=true +sp_cleanup.format_source_code_changes_only=false +sp_cleanup.always_use_blocks=true +org.eclipse.jdt.ui.importorder=java;javax;org;com; +sp_cleanup.use_this_for_non_static_field_access=false +sp_cleanup.use_blocks=false +sp_cleanup.use_blocks_only_for_return_and_throw=false +sp_cleanup.never_use_blocks=false +sp_cleanup.remove_unused_private_types=true +sp_cleanup.sort_members_all=false +sp_cleanup.add_missing_nls_tags=false +sp_cleanup.always_use_this_for_non_static_field_access=false +eclipse.preferences.version=1 +org.eclipse.jdt.ui.ondemandthreshold=99 +sp_cleanup.add_missing_methods=false +sp_cleanup.make_type_abstract_if_missing_method=false +sp_cleanup.format_source_code=true +sp_cleanup.add_missing_override_annotations_interface_methods=true +sp_cleanup.use_parentheses_in_expressions=false +sp_cleanup.remove_unused_local_variables=false +sp_cleanup.add_default_serial_version_id=true +sp_cleanup.on_save_use_additional_actions=true +sp_cleanup.qualify_static_field_accesses_with_declaring_class=false +sp_cleanup.correct_indentation=false +sp_cleanup.remove_unused_private_fields=true +sp_cleanup.qualify_static_member_accesses_with_declaring_class=false +org.eclipse.jdt.ui.javadoc=true +org.eclipse.jdt.ui.ignorelowercasenames=true +sp_cleanup.add_serial_version_id=false diff --git a/dev/com.ibm.ws.jmx_fat/bnd.bnd b/dev/com.ibm.ws.jmx_fat/bnd.bnd new file mode 100644 index 00000000000..20b28a82bd2 --- /dev/null +++ b/dev/com.ibm.ws.jmx_fat/bnd.bnd @@ -0,0 +1,28 @@ +-include= ~../cnf/resources/bnd/bundle.props +bVersion=1.0 + +src: \ + fat/src + +-buildpath: \ + ${javac.bootclasspath.java6}, \ + ../build.sharedResources/lib/junit/old/junit.jar;version=file, \ + ../build.sharedResources/lib/ws-junit/ws-junit.jar;version=file, \ + ../build.sharedResources/lib/hamcrest-all.jar;version=file, \ + ../build.sharedResources/lib/jmock/old/jmock-junit4.jar;version=file, \ + ../build.sharedResources/lib/jmock/old/jmock.jar;version=file, \ + fattest.simplicity;version=latest, \ + ../fattest.simplicity/lib/public.api.jar;version=file, \ + ../com.ibm.ws.kernel.boot.archive/lib/org.apache.commons.compress-1.10.jar;version=file, \ + com.ibm.websphere.org.osgi.core.6.0.0;version=latest, \ + com.ibm.websphere.org.osgi.service.cm.1.5.0;version=latest,\ + com.ibm.websphere.org.osgi.service.component.1.3.0;version=latest,\ + com.ibm.wsspi.thirdparty.equinox;version=latest, \ + com.ibm.ws.kernel.boot.core;version=latest,\ + com.ibm.ws.kernel.service;version=latest,\ + com.ibm.ws.kernel.service.location;version=latest,\ + com.ibm.ws.logging.core;version=latest,\ + com.ibm.ws.org.eclipse.equinox.region.1.3.2;version=latest, \ + com.ibm.ws.runtime.update;version=latest, \ + com.ibm.ws.kernel.feature.core;version=latest, \ + com.ibm.ws.kernel.feature;version=latest diff --git a/dev/com.ibm.ws.jmx_fat/bnd.bnd.gradle b/dev/com.ibm.ws.jmx_fat/bnd.bnd.gradle new file mode 100644 index 00000000000..20b28a82bd2 --- /dev/null +++ b/dev/com.ibm.ws.jmx_fat/bnd.bnd.gradle @@ -0,0 +1,28 @@ +-include= ~../cnf/resources/bnd/bundle.props +bVersion=1.0 + +src: \ + fat/src + +-buildpath: \ + ${javac.bootclasspath.java6}, \ + ../build.sharedResources/lib/junit/old/junit.jar;version=file, \ + ../build.sharedResources/lib/ws-junit/ws-junit.jar;version=file, \ + ../build.sharedResources/lib/hamcrest-all.jar;version=file, \ + ../build.sharedResources/lib/jmock/old/jmock-junit4.jar;version=file, \ + ../build.sharedResources/lib/jmock/old/jmock.jar;version=file, \ + fattest.simplicity;version=latest, \ + ../fattest.simplicity/lib/public.api.jar;version=file, \ + ../com.ibm.ws.kernel.boot.archive/lib/org.apache.commons.compress-1.10.jar;version=file, \ + com.ibm.websphere.org.osgi.core.6.0.0;version=latest, \ + com.ibm.websphere.org.osgi.service.cm.1.5.0;version=latest,\ + com.ibm.websphere.org.osgi.service.component.1.3.0;version=latest,\ + com.ibm.wsspi.thirdparty.equinox;version=latest, \ + com.ibm.ws.kernel.boot.core;version=latest,\ + com.ibm.ws.kernel.service;version=latest,\ + com.ibm.ws.kernel.service.location;version=latest,\ + com.ibm.ws.logging.core;version=latest,\ + com.ibm.ws.org.eclipse.equinox.region.1.3.2;version=latest, \ + com.ibm.ws.runtime.update;version=latest, \ + com.ibm.ws.kernel.feature.core;version=latest, \ + com.ibm.ws.kernel.feature;version=latest diff --git a/dev/com.ibm.ws.jmx_fat/build-test.xml b/dev/com.ibm.ws.jmx_fat/build-test.xml new file mode 100755 index 00000000000..64159bf99af --- /dev/null +++ b/dev/com.ibm.ws.jmx_fat/build-test.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.jmx_fat/build.gradle b/dev/com.ibm.ws.jmx_fat/build.gradle new file mode 100644 index 00000000000..e69de29bb2d diff --git a/dev/com.ibm.ws.jmx_fat/delivery.sets b/dev/com.ibm.ws.jmx_fat/delivery.sets new file mode 100755 index 00000000000..674398425a0 --- /dev/null +++ b/dev/com.ibm.ws.jmx_fat/delivery.sets @@ -0,0 +1 @@ +SLE diff --git a/dev/com.ibm.ws.jmx_fat/fat/src/com/ibm/ws/jmx/fat/AttachSupport.java b/dev/com.ibm.ws.jmx_fat/fat/src/com/ibm/ws/jmx/fat/AttachSupport.java new file mode 100755 index 00000000000..8b73d8a9d3b --- /dev/null +++ b/dev/com.ibm.ws.jmx_fat/fat/src/com/ibm/ws/jmx/fat/AttachSupport.java @@ -0,0 +1,128 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jmx.fat; + +import java.io.File; +import java.lang.reflect.UndeclaredThrowableException; +import java.util.List; +import java.util.Properties; + +import javax.management.MBeanServerConnection; +import javax.management.remote.JMXConnector; +import javax.management.remote.JMXConnectorFactory; +import javax.management.remote.JMXServiceURL; + +import com.ibm.ws.jmx.fat.attach.VirtualMachineDescriptorProxy; +import com.ibm.ws.jmx.fat.attach.VirtualMachineProxy; +import com.ibm.ws.jmx.fat.attach.VirtualMachineProxyHelper; + +/** + * + */ +public class AttachSupport { + + private static String LOCAL_CONNECTOR_ADDRESS = "com.sun.management.jmxremote.localConnectorAddress"; + + MBeanServerConnection mbsc = null; + + public AttachSupport() throws Exception { + System.setProperty("com.ibm.tools.attach.timeout", "5000"); + List vms = VirtualMachineProxyHelper.list(); + System.out.println("Found the following vms: " + vms); + + for (VirtualMachineDescriptorProxy vmd : vms) { + VirtualMachineProxy vm = null; + try { + vm = VirtualMachineProxyHelper.attach(vmd); + } catch (Exception e) { + continue; + } + + System.out.println("Working with vm " + vm); + + try { + Properties props = vm.getSystemProperties(); + Object bvtServer = props.getProperty("com.ibm.ws.jmx.test.fat"); + System.out.println("Found system property " + bvtServer); + + if (bvtServer != null) { + // Search for the value of "localConnectorAddress" within the VM's system properties and agent properties. + // Oracle's examples check the agent properties but have been finding in practice that the value is found + // from a system property. Trying both in case agent properties are used on some platforms to expose + // the value of "localConnectorAddress". + String connectorAddr = vm.getSystemProperties().getProperty(LOCAL_CONNECTOR_ADDRESS); + System.out.println("Local connector address (system property): " + connectorAddr); + + if (connectorAddr == null) { + connectorAddr = vm.getAgentProperties().getProperty(LOCAL_CONNECTOR_ADDRESS); + System.out.println("Local connector address (agent property): " + connectorAddr); + + // It looks like the 'management' agent hasn't been loaded. Try to load it and read the system property again. + if (connectorAddr == null) { + long start = System.currentTimeMillis(); + System.out.println("Starting the management agent ..." + start); + + final String javaHome = vm.getSystemProperties().getProperty("java.home"); + // Try to load the agent jar from "java.home"/lib. Assumes that "java.home" points to JDK_BASE_DIR/jre. + String agent = javaHome + File.separator + "lib" + File.separator + "management-agent.jar"; + try { + vm.loadAgent(agent); + } catch (UndeclaredThrowableException e) { + Throwable t = e.getCause(); + if (t != null && "AgentLoadException".equals(t.getClass().getSimpleName())) { + // The agent wasn't found. Perhaps "java.home" is pointing to the JDK_BASE_DIR. Try again with "java.home"/jre/lib. + agent = javaHome + File.separator + "jre" + File.separator + "lib" + File.separator + "management-agent.jar"; + vm.loadAgent(agent); + } else { + throw e; + } + } + long end = System.currentTimeMillis(); + System.out.println("Management agent started... " + end + ", took ~" + ((end - start) / 1000) + " seconds"); + + connectorAddr = vm.getSystemProperties().getProperty(LOCAL_CONNECTOR_ADDRESS); + System.out.println("Local connector address (system property): " + connectorAddr); + + if (connectorAddr == null) { + connectorAddr = vm.getAgentProperties().getProperty(LOCAL_CONNECTOR_ADDRESS); + System.out.println("Local connector address (agent property): " + connectorAddr); + } + } + } + + if (connectorAddr != null) { + JMXServiceURL url = new JMXServiceURL(connectorAddr); + System.out.println("JMXServiceURL: " + url); + + JMXConnector connector = JMXConnectorFactory.connect(url); + System.out.println("JMXConnector: " + connector); + + mbsc = connector.getMBeanServerConnection(); + System.out.println("MBeanServerConnection: " + mbsc); + } + return; + } + } finally { + try { + vm.detach(); + } catch (Exception e) { + // Detach failed. Ignore and move on to the next VM. + } + } + } + throw new RuntimeException("Could not find the server VM"); + } + + public MBeanServerConnection getMBeanServer() { + return mbsc; + } +} diff --git a/dev/com.ibm.ws.jmx_fat/fat/src/com/ibm/ws/jmx/fat/ClientConnector.java b/dev/com.ibm.ws.jmx_fat/fat/src/com/ibm/ws/jmx/fat/ClientConnector.java new file mode 100755 index 00000000000..c3bfc43ca17 --- /dev/null +++ b/dev/com.ibm.ws.jmx_fat/fat/src/com/ibm/ws/jmx/fat/ClientConnector.java @@ -0,0 +1,60 @@ +package com.ibm.ws.jmx.fat; + +import java.io.IOException; +import java.net.MalformedURLException; + +import javax.management.MBeanServerConnection; +import javax.management.remote.JMXConnector; +import javax.management.remote.JMXConnectorFactory; +import javax.management.remote.JMXServiceURL; + +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ + +/** + * + */ +public class ClientConnector { + + MBeanServerConnection mbsc = null; + + public ClientConnector() { + int port = Integer.valueOf(System.getProperty("JMXTest", "8999")); + String URL = "service:jmx:rmi:///jndi/rmi://localhost:" + port + "/server"; + System.out.println("JMX ClientConnector URL " + URL); + + JMXServiceURL url; + try { + url = new JMXServiceURL(URL); + } catch (MalformedURLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } + JMXConnector jmxc; + try { + jmxc = JMXConnectorFactory.connect(url, null); + } catch (IOException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } + try { + mbsc = jmxc.getMBeanServerConnection(); + } catch (IOException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } + } + + public MBeanServerConnection getMBeanServer() { + return mbsc; + } +} diff --git a/dev/com.ibm.ws.jmx_fat/fat/src/com/ibm/ws/jmx/fat/FATSuite.java b/dev/com.ibm.ws.jmx_fat/fat/src/com/ibm/ws/jmx/fat/FATSuite.java new file mode 100755 index 00000000000..baaab80aa51 --- /dev/null +++ b/dev/com.ibm.ws.jmx_fat/fat/src/com/ibm/ws/jmx/fat/FATSuite.java @@ -0,0 +1,22 @@ +package com.ibm.ws.jmx.fat; + +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011 + * + * The source code for this program is not published or other- + * wise divested of its trade secrets, irrespective of what has + * been deposited with the U.S. Copyright Office. + */ + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +@RunWith(Suite.class) +@SuiteClasses({ + JMXTest.class }) +public class FATSuite {} diff --git a/dev/com.ibm.ws.jmx_fat/fat/src/com/ibm/ws/jmx/fat/JMXTest.java b/dev/com.ibm.ws.jmx_fat/fat/src/com/ibm/ws/jmx/fat/JMXTest.java new file mode 100755 index 00000000000..c4fb6b32ed3 --- /dev/null +++ b/dev/com.ibm.ws.jmx_fat/fat/src/com/ibm/ws/jmx/fat/JMXTest.java @@ -0,0 +1,239 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jmx.fat; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +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.util.Set; + +import javax.management.InstanceNotFoundException; +import javax.management.JMX; +import javax.management.MBeanInfo; +import javax.management.MBeanOperationInfo; +import javax.management.MBeanServerConnection; +import javax.management.MBeanServerDelegate; +import javax.management.MBeanServerDelegateMBean; +import javax.management.ObjectName; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Ignore; +import org.junit.Test; + +import componenttest.topology.impl.LibertyServer; +import componenttest.topology.impl.LibertyServerFactory; + +/** + * + */ +public class JMXTest { + + protected static LibertyServer server; + + @BeforeClass + public static void setUp() throws Exception { + server = LibertyServerFactory.getLibertyServer("com.ibm.ws.jmx.fat"); + server.installSystemFeature("jmxtest-1.0"); + server.copyFileToLibertyInstallRoot("lib", "bundles/com.ibm.ws.jmx.fat_1.0.0.jar"); + + server.startServer("JMXTest.log"); + server.waitForStringInLog("CWWKE0002I"); + assertNotNull("FeatureManager should report update is complete", + server.waitForStringInLog("CWWKF0008I")); + assertNotNull("Server should report it has started", + server.waitForStringInLog("CWWKF0011I")); + assertNotNull("JMXConnectorServer started not found", server.waitForStringInTrace("SERVER_READY|JMXConnectorServer is ready")); + } + + @AfterClass + public static void tearDown() throws Exception { + + if (server != null && server.isStarted()) { + server.stopServer(); + } + server.uninstallSystemFeature("jmxtest-1.0"); + } + + public JMXTest() { + super(); + } + + @Test + public void testMBeanConnector() throws Exception { + ClientConnector cc = new ClientConnector(); + checkMBeanServerConnection(cc.getMBeanServer()); + } + + @Test + public void testMBeanLocalConnector() throws Exception { + String serverRoot = server.getServerRoot(); + LocalConnector lc = new LocalConnector(serverRoot); + checkMBeanServerConnection(lc.getMBeanServer()); + + compareFileContent(lc.getStateFile(), lc.getWorkAreaFile()); + } + + /** + * @param stateFile + * @param workAreaFile + * @throws IOException + */ + private void compareFileContent(File stateFile, File workAreaFile) throws IOException { + BufferedReader reader = new BufferedReader(new FileReader(stateFile)); + String stateLine = reader.readLine(); + reader.close(); + reader = new BufferedReader(new FileReader(workAreaFile)); + String workAreaLine = reader.readLine(); + reader.close(); + + assertEquals("The content of the local address file in the logs/state and workarea files should be the same", stateLine, workAreaLine); + } + + @Test + @Ignore + // Disabling this test. The Attach API has been very unstable + // and is not being used by the tools for connecting to JMX. + public void testMBeanAttachAPI() throws Exception { + AttachSupport as = new AttachSupport(); + checkMBeanServerConnection(as.getMBeanServer()); + } + + @Test + public void testMBeanNotLoaded() throws Exception { + ClientConnector cc = new ClientConnector(); + MBeanServerConnection server = cc.getMBeanServer(); + ObjectName beanCounterName = new ObjectName("WebSphere", "name", "com.ibm.ws.jmx.test.fat.beanCounter"); + + int before = (Integer) server.getAttribute(beanCounterName, "beanCount"); + + ObjectName on = new ObjectName("WebSphere", "name", "com.ibm.ws.jmx.test.fat.testBean3"); + @SuppressWarnings("unused") + MBeanInfo info = server.getMBeanInfo(on); + + int after = (Integer) server.getAttribute(beanCounterName, "beanCount"); + + assertTrue(after == before + 1); + } + + // Simple method that demands the pattern provided matches exactly one mbean + private MBeanInfo getMBeanInfo(MBeanServerConnection connection, ObjectName pattern) throws Exception { + Set mbeans = connection.queryNames(pattern, null); + assertTrue("Expected one mbean matching pattern " + pattern + ", found: " + mbeans.size(), mbeans.size() == 1); + ObjectName name = mbeans.iterator().next(); + MBeanInfo result = connection.getMBeanInfo(name); + assertTrue("No mbean info for " + name, result != null); + return result; + } + + @Test + public void testOSGiMBeans() throws Exception { + ClientConnector cc = new ClientConnector(); + final MBeanServerConnection server = cc.getMBeanServer(); + + //this ObjectName is also ObjectNameConstants.OSGI_CONFIGURATION_ADMIN_MBEAN_NAME + MBeanInfo info = getMBeanInfo(server, new ObjectName("osgi.compendium:service=cm,version=1.3,*")); + MBeanOperationInfo[] ops = info.getOperations(); + + // Check that only read-only operations are available from ConfigurationAdmin. + assertTrue(containsOperation(ops, "getProperties")); + assertTrue(!containsOperation(ops, "deleteForLocation")); + final String mbeanClassName = info.getClassName(); + assertTrue("com.ibm.ws.jmx.internal.ReadOnlyConfigurationAdmin".equals(mbeanClassName)); + + // Sanity check with a few other OSGi JMX MBeans. + // Ensures the delayed registration is working correctly. + //this ObjectName is also ObjectNameConstants.OSGI_FRAMEWORK_MBEAN_NAME + info = getMBeanInfo(server, new ObjectName("osgi.core:type=framework,version=1.7,*")); + assertTrue(info != null); + assertTrue(containsOperation(info.getOperations(), "restartFramework")); + assertTrue(containsOperation(info.getOperations(), "shutdownFramework")); + + //this ObjectName is also ObjectNameConstants.OSGI_BUNDLE_STATE_MBEAN_NAME + info = getMBeanInfo(server, new ObjectName("osgi.core:type=bundleState,version=1.7,*")); + assertTrue(info != null); + assertTrue(containsOperation(info.getOperations(), "listBundles")); + + } + + @Test + public void testDelayedOSGiMBeans() throws Exception { + ClientConnector cc = new ClientConnector(); + final MBeanServerConnection server = cc.getMBeanServer(); + + ObjectName tester = new ObjectName("WebSphere", "name", "com.ibm.ws.jmx.test.fat.delayedMbeanTester"); + ObjectName bean1 = new ObjectName("WebSphere", "name", "com.ibm.ws.jmx.test.fat.delayedMbeanTester.Bean1"); + ObjectName bean2 = new ObjectName("WebSphere", "name", "com.ibm.ws.jmx.test.fat.delayedMbeanTester.Bean2"); + server.invoke(tester, "register", null, null); + + try { + server.getMBeanInfo(bean1); + fail("Expected InstanceNotFoundException"); + } catch (InstanceNotFoundException e) { + //expected + } + server.invoke(tester, "allow1Service", null, null); + //this should work if delayed mbeans are implemented correctly + assertNotNull("Expected successful delayed mbean instantiation", server.getMBeanInfo(bean1)); + + try { + server.getMBeanInfo(bean2); + fail("Expected InstanceNotFoundException"); + } catch (InstanceNotFoundException e) { + //expected + } + + server.invoke(tester, "unregister", null, null); + } + + private boolean containsOperation(MBeanOperationInfo[] ops, String name) { + for (MBeanOperationInfo op : ops) { + if (name.equals(op.getName())) { + return true; + } + } + return false; + } + + private void checkMBeanServerConnection(MBeanServerConnection server) throws Exception { + assertNotNull("Server must not be null", server); + + int numBeans = server.getMBeanCount(); + assertTrue("Number of beans shoud be greater than or equal to 2, numBeans=" + numBeans, numBeans >= 2); + + Set set = server.queryNames(null, null); + + ObjectName on1 = new ObjectName("WebSphere", "name", "com.ibm.ws.jmx.test.fat.testBean1"); + ObjectName on2 = new ObjectName("WebSphere", "name", "com.ibm.ws.jmx.test.fat.testBean2"); + + assertTrue("Set must contain object name '" + on1 + "': found " + set, set.contains(on1)); + assertTrue("Set must contain object name '" + on1 + "': found " + set, set.contains(on2)); + + MBeanInfo info = server.getMBeanInfo(on1); + assertNotNull("MBeanInfo for object name 1 must not be null", info); + + info = server.getMBeanInfo(on2); + assertNotNull("MBeanInfo for object name 2 must not be null", info); + + MBeanServerDelegateMBean serverDelegate = JMX.newMBeanProxy(server, MBeanServerDelegate.DELEGATE_NAME, MBeanServerDelegateMBean.class); + System.out.println("Server delegate: " + serverDelegate); + System.out.println("Mbean server id: " + serverDelegate.getMBeanServerId()); + assertTrue("Expected that server ID starts with WebSphere", + serverDelegate.getMBeanServerId().startsWith("WebSphere")); + } +} diff --git a/dev/com.ibm.ws.jmx_fat/fat/src/com/ibm/ws/jmx/fat/LocalConnector.java b/dev/com.ibm.ws.jmx_fat/fat/src/com/ibm/ws/jmx/fat/LocalConnector.java new file mode 100755 index 00000000000..44ab6b6fb5d --- /dev/null +++ b/dev/com.ibm.ws.jmx_fat/fat/src/com/ibm/ws/jmx/fat/LocalConnector.java @@ -0,0 +1,105 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jmx.fat; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; + +import javax.management.MBeanServerConnection; +import javax.management.remote.JMXConnector; +import javax.management.remote.JMXConnectorFactory; +import javax.management.remote.JMXServiceURL; + +/** + * + */ +public class LocalConnector { + + private static final String CONNECTOR_ADDRESS_FILE_NAME = "com.ibm.ws.jmx.local.address"; + + MBeanServerConnection mbsc = null; + + private File stateFile; + private File workAreaFile; + + public LocalConnector(String serverRoot) throws IOException { + if (serverRoot == null || serverRoot.length() == 0) { + throw new RuntimeException("server.root property is not set"); + } + serverRoot = serverRoot.replaceAll("\\\\", "/"); + String connectorFile = serverRoot + "/logs/state/" + CONNECTOR_ADDRESS_FILE_NAME; + System.out.println(connectorFile); + + stateFile = new File(connectorFile); + workAreaFile = new File(serverRoot, "workarea/" + CONNECTOR_ADDRESS_FILE_NAME); + + if (stateFile.exists()) { + String connectorAddr = null; + BufferedReader br = null; + try { + br = new BufferedReader(new InputStreamReader(new FileInputStream(stateFile), "UTF-8")); + connectorAddr = br.readLine(); + } catch (IOException e) { + throw new RuntimeException(e); + } finally { + try { + if (br != null) { + br.close(); + } + } catch (IOException e) { + // ignore + } + } + if (connectorAddr != null) { + System.out.println("JMX connector address: " + connectorAddr); + JMXConnector connector = null; + try { + JMXServiceURL url = new JMXServiceURL(connectorAddr); + connector = JMXConnectorFactory.connect(url); + System.out.println("JMX Connector: " + connector); + mbsc = connector.getMBeanServerConnection(); + if (mbsc != null) { + return; //Successful, return. + } + } catch (IOException ioe) { + if (connector != null) { + try { + connector.close(); + } catch (IOException e) { + // ignore + } + } + throw (ioe); + } + } else { + System.out.println("JMXConnection: JMX connector address is null. The connector address file is " + stateFile.getAbsolutePath()); + } + } else { + System.out.println("JMXConnection: JMX address file doesn't exist. The connector address file is " + stateFile.getAbsolutePath()); + } + } + + public MBeanServerConnection getMBeanServer() { + return mbsc; + } + + public File getStateFile() { + return stateFile; + } + + public File getWorkAreaFile() { + return workAreaFile; + } +} diff --git a/dev/com.ibm.ws.jmx_fat/fat/src/com/ibm/ws/jmx/fat/attach/ForwardingInvocationHandler.java b/dev/com.ibm.ws.jmx_fat/fat/src/com/ibm/ws/jmx/fat/attach/ForwardingInvocationHandler.java new file mode 100755 index 00000000000..7a8fdab1512 --- /dev/null +++ b/dev/com.ibm.ws.jmx_fat/fat/src/com/ibm/ws/jmx/fat/attach/ForwardingInvocationHandler.java @@ -0,0 +1,45 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jmx.fat.attach; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +/** + * + */ +class ForwardingInvocationHandler implements InvocationHandler { + + private final Object target; + + public ForwardingInvocationHandler(Object target) { + this.target = target; + } + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + final String name = method.getName(); + if ("getBackingObject".equals(name) && + method.getDeclaringClass() == ObjectProxy.class) { + return target; + } + final Class[] types = method.getParameterTypes(); + try { + Method m = target.getClass().getMethod(name, types); + m.setAccessible(true); + return m.invoke(target, args); + } catch (InvocationTargetException e) { + throw e.getCause(); + } + } +} diff --git a/dev/com.ibm.ws.jmx_fat/fat/src/com/ibm/ws/jmx/fat/attach/ObjectProxy.java b/dev/com.ibm.ws.jmx_fat/fat/src/com/ibm/ws/jmx/fat/attach/ObjectProxy.java new file mode 100755 index 00000000000..a26938936ba --- /dev/null +++ b/dev/com.ibm.ws.jmx_fat/fat/src/com/ibm/ws/jmx/fat/attach/ObjectProxy.java @@ -0,0 +1,21 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jmx.fat.attach; + +/** + * + */ +interface ObjectProxy { + + public Object getBackingObject(); + +} diff --git a/dev/com.ibm.ws.jmx_fat/fat/src/com/ibm/ws/jmx/fat/attach/VirtualMachineDescriptorProxy.java b/dev/com.ibm.ws.jmx_fat/fat/src/com/ibm/ws/jmx/fat/attach/VirtualMachineDescriptorProxy.java new file mode 100755 index 00000000000..dd2470d6127 --- /dev/null +++ b/dev/com.ibm.ws.jmx_fat/fat/src/com/ibm/ws/jmx/fat/attach/VirtualMachineDescriptorProxy.java @@ -0,0 +1,25 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jmx.fat.attach; + +/** + * + */ +public interface VirtualMachineDescriptorProxy { + + public String displayName(); + + public String id(); + + public String toString(); + +} diff --git a/dev/com.ibm.ws.jmx_fat/fat/src/com/ibm/ws/jmx/fat/attach/VirtualMachineProxy.java b/dev/com.ibm.ws.jmx_fat/fat/src/com/ibm/ws/jmx/fat/attach/VirtualMachineProxy.java new file mode 100755 index 00000000000..292f5ba9c71 --- /dev/null +++ b/dev/com.ibm.ws.jmx_fat/fat/src/com/ibm/ws/jmx/fat/attach/VirtualMachineProxy.java @@ -0,0 +1,44 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jmx.fat.attach; + +import java.io.IOException; +import java.util.Properties; + +/** + * + */ +public interface VirtualMachineProxy { + + public void detach() throws IOException; + + public String id(); + + public Properties getAgentProperties() throws IOException; + + public Properties getSystemProperties() throws IOException; + + public void loadAgent(String agent) throws IOException; + + public void loadAgent(String agent, String options) throws IOException; + + public void loadAgentLibrary(String agentLibrary) throws IOException; + + public void loadAgentLibrary(String agentLibrary, String options) throws IOException; + + public void loadAgentPath(String agentPath) throws IOException; + + public void loadAgentPath(String agentPath, String options) throws IOException; + + public String toString(); + +} diff --git a/dev/com.ibm.ws.jmx_fat/fat/src/com/ibm/ws/jmx/fat/attach/VirtualMachineProxyHelper.java b/dev/com.ibm.ws.jmx_fat/fat/src/com/ibm/ws/jmx/fat/attach/VirtualMachineProxyHelper.java new file mode 100755 index 00000000000..20b4ad85a93 --- /dev/null +++ b/dev/com.ibm.ws.jmx_fat/fat/src/com/ibm/ws/jmx/fat/attach/VirtualMachineProxyHelper.java @@ -0,0 +1,153 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jmx.fat.attach; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.List; + +/** + * + */ +public final class VirtualMachineProxyHelper { + + private static final String IBM_VIRTUAL_MACHINE = "com.ibm.tools.attach.VirtualMachine"; + private static final String SUN_VIRTUAL_MACHINE = "com.sun.tools.attach.VirtualMachine"; + + private static final String IBM_VIRTUAL_MACHINE_DESCRIPTOR = "com.ibm.tools.attach.VirtualMachineDescriptor"; + private static final String SUN_VIRTUAL_MACHINE_DESCRIPTOR = "com.sun.tools.attach.VirtualMachineDescriptor"; + + private static final Class VIRTUAL_MACHINE_CLASS; + private static final Class VIRTUAL_MACHINE_DESCRIPTOR_CLASS; + static { + Class c1 = null; + Class c2 = null; + try { + // Attempt to load the IBM flavor of the Attach API. + c1 = Class.forName(IBM_VIRTUAL_MACHINE); + c2 = Class.forName(IBM_VIRTUAL_MACHINE_DESCRIPTOR); + } catch (ClassNotFoundException e) { + try { + // Not an IBM JDK. Attempt to load the Oracle/Sun flavor of the Attach API. + // This requires tools.jar. We cannot assume it's on the system classpath + // so we add it to the search path of the ClassLoader. + String javaHome = System.getProperty("java.home"); + // Assumes "java.home" points to JDK_BASE_DIR/jre or JDK_BASE_DIR + File toolsJarLocation1 = new File(javaHome + File.separator + ".." + File.separator + "lib" + File.separator + "tools.jar"); + File toolsJarLocation2 = new File(javaHome + File.separator + "lib" + File.separator + "tools.jar"); + ClassLoader cl = URLClassLoader.newInstance(new URL[] { toolsJarLocation1.toURI().toURL(), + toolsJarLocation2.toURI().toURL() }); + c1 = Class.forName(SUN_VIRTUAL_MACHINE, true, cl); + c2 = Class.forName(SUN_VIRTUAL_MACHINE_DESCRIPTOR, true, cl); + } catch (MalformedURLException e2) { + throw new IllegalStateException(e2); + } catch (ClassNotFoundException e2) { + throw new IllegalStateException("An implementation of the Attach API was not found.", e2); + } + } + VIRTUAL_MACHINE_CLASS = c1; + VIRTUAL_MACHINE_DESCRIPTOR_CLASS = c2; + } + + public static VirtualMachineProxy attach(String id) throws IOException { + try { + Method attachMethod = VIRTUAL_MACHINE_CLASS.getMethod("attach", String.class); + attachMethod.setAccessible(true); + Object vm = attachMethod.invoke(null, id); + if (vm != null) { + return (VirtualMachineProxy) Proxy.newProxyInstance(VirtualMachineProxy.class.getClassLoader(), + new Class[] { VirtualMachineProxy.class }, + new ForwardingInvocationHandler(vm)); + } + return null; + } catch (NoSuchMethodException e) { + throw new IllegalStateException(e); + } catch (IllegalArgumentException e) { + throw new IllegalStateException(e); + } catch (IllegalAccessException e) { + throw new IllegalStateException(e); + } catch (InvocationTargetException e) { + throw new IllegalStateException(e); + } + } + + public static VirtualMachineProxy attach(VirtualMachineDescriptorProxy vmd) throws IOException { + Object _vmd = null; + if (vmd instanceof ObjectProxy) { + _vmd = ((ObjectProxy) vmd).getBackingObject(); + } else if (vmd != null) { + throw new IllegalArgumentException("Unsupported proxy instance."); + } + try { + Method attachMethod = VIRTUAL_MACHINE_CLASS.getMethod("attach", VIRTUAL_MACHINE_DESCRIPTOR_CLASS); + attachMethod.setAccessible(true); + Object vm = attachMethod.invoke(null, _vmd); + if (vm != null) { + return (VirtualMachineProxy) Proxy.newProxyInstance(VirtualMachineProxy.class.getClassLoader(), + new Class[] { VirtualMachineProxy.class }, + new ForwardingInvocationHandler(vm)); + } + return null; + } catch (NoSuchMethodException e) { + throw new IllegalStateException(e); + } catch (IllegalArgumentException e) { + throw new IllegalStateException(e); + } catch (IllegalAccessException e) { + throw new IllegalStateException(e); + } catch (InvocationTargetException e) { + throw new IllegalStateException(e); + } + } + + public static List list() { + try { + Method attachMethod = VIRTUAL_MACHINE_CLASS.getMethod("list"); + attachMethod.setAccessible(true); + @SuppressWarnings("rawtypes") + List list = (List) attachMethod.invoke(null); + if (list == null) { + return null; + } + final int size = list.size(); + List _list = new ArrayList(size); + for (int i = 0; i < size; ++i) { + Object vmd = list.get(i); + if (vmd != null) { + _list.add((VirtualMachineDescriptorProxy) Proxy.newProxyInstance(VirtualMachineDescriptorProxy.class.getClassLoader(), + new Class[] { VirtualMachineDescriptorProxy.class, ObjectProxy.class }, + new ForwardingInvocationHandler(vmd))); + } else { + _list.add(null); + } + } + return _list; + } catch (NoSuchMethodException e) { + throw new IllegalStateException(e); + } catch (IllegalArgumentException e) { + throw new IllegalStateException(e); + } catch (IllegalAccessException e) { + throw new IllegalStateException(e); + } catch (InvocationTargetException e) { + throw new IllegalStateException(e); + } + } + + private VirtualMachineProxyHelper() {} + +} diff --git a/dev/com.ibm.ws.jmx_fat/publish/.gitignore b/dev/com.ibm.ws.jmx_fat/publish/.gitignore new file mode 100644 index 00000000000..7ad6e8cac5f --- /dev/null +++ b/dev/com.ibm.ws.jmx_fat/publish/.gitignore @@ -0,0 +1,2 @@ +/bundles +/files diff --git a/dev/com.ibm.ws.jmx_fat/publish/features/jmxtest-1.0.mf b/dev/com.ibm.ws.jmx_fat/publish/features/jmxtest-1.0.mf new file mode 100755 index 00000000000..5b5e26ae2ea --- /dev/null +++ b/dev/com.ibm.ws.jmx_fat/publish/features/jmxtest-1.0.mf @@ -0,0 +1,8 @@ + +Subsystem-ManifestVersion: 1 +IBM-ShortName: jmxtest-1.0 +Subsystem-SymbolicName: com.ibm.websphere.jmx.jmxtest-1.0;visibility:=public +Subsystem-Version: 1.0.0 +Subsystem-Content: com.ibm.ws.jmx.fat;version=0 +Subsystem-Type: osgi.subsystem.feature +IBM-Feature-Version: 2 \ No newline at end of file diff --git a/dev/com.ibm.ws.jmx_fat/publish/servers/com.ibm.ws.jmx.fat/bootstrap.properties b/dev/com.ibm.ws.jmx_fat/publish/servers/com.ibm.ws.jmx.fat/bootstrap.properties new file mode 100755 index 00000000000..703551895b3 --- /dev/null +++ b/dev/com.ibm.ws.jmx_fat/publish/servers/com.ibm.ws.jmx.fat/bootstrap.properties @@ -0,0 +1,5 @@ +bootstrap.include=../testports.properties +com.ibm.ws.logging.trace.specification=*=info=enabled:\ +logservice=all=enabled:\ +com.ibm.ws.jmx.internal=all:\ +com.ibm.ws.kernel.boot.jmx.internal=all:\ diff --git a/dev/com.ibm.ws.jmx_fat/publish/servers/com.ibm.ws.jmx.fat/server.xml b/dev/com.ibm.ws.jmx_fat/publish/servers/com.ibm.ws.jmx.fat/server.xml new file mode 100755 index 00000000000..90b60256d51 --- /dev/null +++ b/dev/com.ibm.ws.jmx_fat/publish/servers/com.ibm.ws.jmx.fat/server.xml @@ -0,0 +1,8 @@ + + + + localConnector-1.0 + timedexit-1.0 + jmxtest-1.0 + + diff --git a/dev/com.ibm.ws.jmx_fat/test-bundles/test-mbeans/bnd.bnd b/dev/com.ibm.ws.jmx_fat/test-bundles/test-mbeans/bnd.bnd new file mode 100755 index 00000000000..2af06f6876c --- /dev/null +++ b/dev/com.ibm.ws.jmx_fat/test-bundles/test-mbeans/bnd.bnd @@ -0,0 +1,51 @@ +-include= ~../../../cnf/resources/bnd/bundle.props +bVersion=1.0.0 + +# For more information, see http://was.pok.ibm.com/xwiki/bin/view/Liberty/UsingBnd + +Bundle-Name: JMX Test bundle +Bundle-SymbolicName: com.ibm.ws.jmx.fat +Bundle-Description: Test bundle for the jmx project + +# optional... +WS-TraceGroup: projectExample + +Private-Package: com.ibm.ws.jmx.test.fat + +Import-Package: !*.internal.*, org.osgi.framework;version="1.3", * + +#Include-Resource: OSGI-INF=bvt-bundle/resources/OSGI-INF + +-dsannotations=com.ibm.ws.jmx.test.fat.DelayedMbeanTester + +Service-Component: \ + com.ibm.ws.jmx.test.fat.testBean1;\ + implementation:=com.ibm.ws.jmx.test.fat.TestBean1;\ + provide:='javax.management.DynamicMBean';\ + immediate:=true;\ + configuration-policy:=ignore;\ + properties:="service.vendor=IBM,jmx.objectname=WebSphere:name=com.ibm.ws.jmx.test.fat.testBean1",\ + com.ibm.ws.jmx.test.fat.testBean2;\ + implementation:=com.ibm.ws.jmx.test.fat.TestBean2;\ + provide:='javax.management.DynamicMBean';\ + immediate:=true;\ + configuration-policy:=ignore;\ + properties:="service.vendor=IBM,jmx.objectname=WebSphere:name=com.ibm.ws.jmx.test.fat.testBean2",\ + com.ibm.ws.jmx.test.fat.testBean3;\ + implementation:=com.ibm.ws.jmx.test.fat.TestBean3;\ + provide:='javax.management.DynamicMBean';\ + immediate:=false;\ + configuration-policy:=ignore;\ + properties:="service.vendor=IBM,jmx.objectname=WebSphere:name=com.ibm.ws.jmx.test.fat.testBean3",\ + com.ibm.ws.jmx.test.fat.beanCounter;\ + implementation:=com.ibm.ws.jmx.test.fat.BeanCounter;\ + jmxServer=com.ibm.ws.jmx.PlatformMBeanService;\ + provide:='javax.management.DynamicMBean';\ + immediate:=true;\ + configuration-policy:=ignore;\ + properties:="service.vendor=IBM,jmx.objectname=WebSphere:name=com.ibm.ws.jmx.test.fat.beanCounter",\ + ServerTestConnector;\ + implementation:=com.ibm.ws.jmx.test.fat.ServerConnector;\ + jmxServer=com.ibm.ws.jmx.PlatformMBeanService;\ + immediate:=true;\ + properties:="service.vendor=IBM" diff --git a/dev/com.ibm.ws.jmx_fat/test-bundles/test-mbeans/src/com/ibm/ws/jmx/test/fat/BeanCounter.java b/dev/com.ibm.ws.jmx_fat/test-bundles/test-mbeans/src/com/ibm/ws/jmx/test/fat/BeanCounter.java new file mode 100755 index 00000000000..47afc8a0410 --- /dev/null +++ b/dev/com.ibm.ws.jmx_fat/test-bundles/test-mbeans/src/com/ibm/ws/jmx/test/fat/BeanCounter.java @@ -0,0 +1,94 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jmx.test.fat; + +import java.lang.reflect.Field; + +import javax.management.AttributeNotFoundException; +import javax.management.MBeanException; +import javax.management.MBeanServer; +import javax.management.ReflectionException; + +import org.osgi.framework.ServiceReference; +import org.osgi.service.component.ComponentContext; + +import com.ibm.ws.jmx.PlatformMBeanService; + +/** + * + */ +public class BeanCounter extends TestBean { + + ServiceReference mbeanServerRef; + MBeanServer mBeanServer; + PlatformMBeanService mbeanService; + + /** + * @param name + */ + public BeanCounter() { + super(BeanCounter.class.getName()); + + } + + public void activate(ComponentContext compContext) { + mbeanService = null; + try { + mbeanService = compContext.locateService("jmxServer", mbeanServerRef); + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException(e); + } + } + + public void deactivate(ComponentContext compContext) {} + + public void setJmxServer(ServiceReference mbeanServerRef) { + this.mbeanServerRef = mbeanServerRef; + } + + public void unsetJmxServer(ServiceReference mbeanServer) {} + + public int getNonDelayedBeanCount() { + MBeanServer server = mbeanService.getMBeanServer(); + try { + Class clazz = server.getClass(); + Field f = clazz.getDeclaredField("last"); + f.setAccessible(true); + server = (MBeanServer) f.get(server); + } catch (Exception e) { + e.printStackTrace(); + } + mBeanServer = server; + return mBeanServer.getMBeanCount(); + } + + @Override + public Object getAttribute(String s) throws AttributeNotFoundException, MBeanException, ReflectionException { + return "beanCount".equals(s) ? getNonDelayedBeanCount() : super.getAttribute(s); + } + + // @Override + // public MBeanInfo getMBeanInfo() { + // try { + // Class clazz = this.getClass(); + // Method getter = clazz.getDeclaredMethod("getNonDelayedBeanCount", null); + // MBeanAttributeInfo aInfo = new MBeanAttributeInfo("beanCount", "beanCounter.beanCount", getter, null); + // MBeanAttributeInfo[] attrs = new MBeanAttributeInfo[] { aInfo }; + // MBeanInfo info = new MBeanInfo(toString(), "bean counter", attrs, null, null, null); + // return info; + // } catch (Exception e) { + // e.printStackTrace(); + // throw new RuntimeException(e); + // } + // } +} diff --git a/dev/com.ibm.ws.jmx_fat/test-bundles/test-mbeans/src/com/ibm/ws/jmx/test/fat/DelayedMbeanTester.java b/dev/com.ibm.ws.jmx_fat/test-bundles/test-mbeans/src/com/ibm/ws/jmx/test/fat/DelayedMbeanTester.java new file mode 100755 index 00000000000..58896d35bd0 --- /dev/null +++ b/dev/com.ibm.ws.jmx_fat/test-bundles/test-mbeans/src/com/ibm/ws/jmx/test/fat/DelayedMbeanTester.java @@ -0,0 +1,102 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2014 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jmx.test.fat; + +import java.util.Hashtable; + +import javax.management.DynamicMBean; + +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceFactory; +import org.osgi.framework.ServiceRegistration; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.ConfigurationPolicy; + +/** + * Registers and unregisters some "delayed" mbeans that don't like to return the service references + */ +@Component(configurationPolicy = ConfigurationPolicy.IGNORE, + property = { "jmx.objectname=WebSphere:name=com.ibm.ws.jmx.test.fat.delayedMbeanTester" }) +public class DelayedMbeanTester implements DelayedMbeanTesterMBean { + + private BundleContext bundleContext; + private ServiceRegistration reg1; + private boolean allow1; + private ServiceRegistration reg2; + + protected void activate(BundleContext bundleContext) { + this.bundleContext = bundleContext; + } + + protected void deactivate() { + this.bundleContext = null; + } + + /* + * (non-Javadoc) + * + * @see com.ibm.ws.jmx.test.fat.DelayedMbeanTesterMBean#register() + */ + @Override + public void register() { + Hashtable properties1 = new Hashtable(); + properties1.put("jmx.objectname", "WebSphere:name=com.ibm.ws.jmx.test.fat.delayedMbeanTester.Bean1"); + reg1 = bundleContext.registerService(DynamicMBean.class.getName(), + new ServiceFactory() { + + @Override + public TestBean getService(Bundle bundle, ServiceRegistration registration) { + return allow1 ? new TestBean("delayed1") : null; + } + + @Override + public void ungetService(Bundle bundle, ServiceRegistration registration, TestBean service) {} + }, + properties1); + Hashtable properties2 = new Hashtable(); + properties2.put("jmx.objectname", "WebSphere:name=com.ibm.ws.jmx.test.fat.delayedMbeanTester.Bean2"); + reg2 = bundleContext.registerService(DynamicMBean.class.getName(), + new ServiceFactory() { + + @Override + public TestBean getService(Bundle bundle, ServiceRegistration registration) { + return null; + } + + @Override + public void ungetService(Bundle bundle, ServiceRegistration registration, TestBean service) {} + }, + properties2); + } + + /* + * (non-Javadoc) + * + * @see com.ibm.ws.jmx.test.fat.DelayedMbeanTesterMBean#allow1Service() + */ + @Override + public void allow1Service() { + allow1 = true; + } + + /* + * (non-Javadoc) + * + * @see com.ibm.ws.jmx.test.fat.DelayedMbeanTesterMBean#unregister() + */ + @Override + public void unregister() { + reg1.unregister(); + reg2.unregister(); + } +} diff --git a/dev/com.ibm.ws.jmx_fat/test-bundles/test-mbeans/src/com/ibm/ws/jmx/test/fat/DelayedMbeanTesterMBean.java b/dev/com.ibm.ws.jmx_fat/test-bundles/test-mbeans/src/com/ibm/ws/jmx/test/fat/DelayedMbeanTesterMBean.java new file mode 100755 index 00000000000..2ee1918a7fa --- /dev/null +++ b/dev/com.ibm.ws.jmx_fat/test-bundles/test-mbeans/src/com/ibm/ws/jmx/test/fat/DelayedMbeanTesterMBean.java @@ -0,0 +1,25 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2014 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jmx.test.fat; + +/** + * + */ +public interface DelayedMbeanTesterMBean { + + void register(); + + void allow1Service(); + + void unregister(); + +} \ No newline at end of file diff --git a/dev/com.ibm.ws.jmx_fat/test-bundles/test-mbeans/src/com/ibm/ws/jmx/test/fat/Messages.properties b/dev/com.ibm.ws.jmx_fat/test-bundles/test-mbeans/src/com/ibm/ws/jmx/test/fat/Messages.properties new file mode 100755 index 00000000000..c19eb03f649 --- /dev/null +++ b/dev/com.ibm.ws.jmx_fat/test-bundles/test-mbeans/src/com/ibm/ws/jmx/test/fat/Messages.properties @@ -0,0 +1,4 @@ +STARTED=Registry started with URL {0}. +SERVER=MBeanServer obtained with domains {0}. +SERVER_READY=JMXConnectorServer is ready with open connections {0}. +SERVER_STOPPED=JMXConnectorServer is stopped. diff --git a/dev/com.ibm.ws.jmx_fat/test-bundles/test-mbeans/src/com/ibm/ws/jmx/test/fat/ServerConnector.java b/dev/com.ibm.ws.jmx_fat/test-bundles/test-mbeans/src/com/ibm/ws/jmx/test/fat/ServerConnector.java new file mode 100755 index 00000000000..46d1aa5ae43 --- /dev/null +++ b/dev/com.ibm.ws.jmx_fat/test-bundles/test-mbeans/src/com/ibm/ws/jmx/test/fat/ServerConnector.java @@ -0,0 +1,161 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jmx.test.fat; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.rmi.NoSuchObjectException; +import java.rmi.RemoteException; +import java.rmi.registry.LocateRegistry; +import java.rmi.registry.Registry; +import java.rmi.server.UnicastRemoteObject; + +import javax.management.remote.JMXConnectorServer; +import javax.management.remote.JMXConnectorServerFactory; +import javax.management.remote.JMXServiceURL; + +import org.osgi.framework.ServiceReference; +import org.osgi.service.component.ComponentContext; + +import com.ibm.websphere.ras.Tr; +import com.ibm.websphere.ras.TraceComponent; +import com.ibm.ws.jmx.PlatformMBeanService; +import com.ibm.wsspi.kernel.service.utils.OsgiPropertyUtils; + +/** + * + */ +public class ServerConnector { + private static final TraceComponent tc = Tr.register(ServerConnector.class); + + String URL; + JMXConnectorServer cs; + ComponentContext context; + ServiceReference mbeanServerRef; + Registry registry; + + public ServerConnector() { + super(); + cs = null; + context = null; + mbeanServerRef = null; + registry = null; + } + + public void activate(ComponentContext compContext) { + context = compContext; + + int port = Integer.valueOf(OsgiPropertyUtils.getProperty("bvt.prop.JMXTest", "8999")); + final String URL = "service:jmx:rmi:///jndi/rmi://localhost:" + port + "/server"; + + registry = null; + try { + registry = LocateRegistry.createRegistry(port); + } catch (RemoteException e1) { + // TODO Auto-generated catch block + // Do you need FFDC here? Remember FFDC instrumentation and @FFDCIgnore + // https://websphere.pok.ibm.com/~alpine/secure/docs/dev/API/com.ibm.ws.ras/com/ibm/ws/ffdc/annotation/FFDCIgnore.html + e1.printStackTrace(); + throw new RuntimeException(e1); + } + Tr.info(tc, "STARTED", URL); + + Runnable r = new Runnable() { + + @Override + public void run() { + PlatformMBeanService mbeanServer = null; + try { + mbeanServer = context.locateService("jmxServer", mbeanServerRef); + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException(e); + } + Tr.info(tc, "SERVER", strings(mbeanServer.getMBeanServer().getDomains())); + + JMXServiceURL url = null; + try { + url = new JMXServiceURL(URL); + } catch (MalformedURLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } + + try { + cs = JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbeanServer.getMBeanServer()); + } catch (IOException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } + + try { + cs.start(); + } catch (IOException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } + Tr.info(tc, "SERVER_READY", strings(cs.getConnectionIds())); + } + }; + Thread thr = new Thread(r); + thr.start(); + + } + + public void deactivate(ComponentContext compContext) { + try { + cs.stop(); + } catch (IOException e) { + // TODO Auto-generated catch block + // Do you need FFDC here? Remember FFDC instrumentation and @FFDCIgnore + // https://websphere.pok.ibm.com/~alpine/secure/docs/dev/API/com.ibm.ws.ras/com/ibm/ws/ffdc/annotation/FFDCIgnore.html + e.printStackTrace(); + throw new RuntimeException(e); + } + context = null; + try { + UnicastRemoteObject.unexportObject(registry, true); + } catch (NoSuchObjectException e) { + // TODO Auto-generated catch block + // Do you need FFDC here? Remember FFDC instrumentation and @FFDCIgnore + // https://websphere.pok.ibm.com/~alpine/secure/docs/dev/API/com.ibm.ws.ras/com/ibm/ws/ffdc/annotation/FFDCIgnore.html + e.printStackTrace(); + } + registry = null; + Tr.info(tc, "SERVER_STOPPED"); + } + + public void setJmxServer(ServiceReference mbeanServerRef) { + this.mbeanServerRef = mbeanServerRef; + } + + public void unsetJmxServer(ServiceReference mbeanServer) { + cs = null; + } + + private static String strings(String[] strs) { + StringBuilder str = new StringBuilder("["); + if (strs != null) { + boolean first = true; + for (String s : strs) { + if (first) { + first = false; + } else { + str.append(','); + } + str.append(s); + } + } + str.append(']'); + return str.toString(); + } +} diff --git a/dev/com.ibm.ws.jmx_fat/test-bundles/test-mbeans/src/com/ibm/ws/jmx/test/fat/TestBean.java b/dev/com.ibm.ws.jmx_fat/test-bundles/test-mbeans/src/com/ibm/ws/jmx/test/fat/TestBean.java new file mode 100755 index 00000000000..1cd79c13a6d --- /dev/null +++ b/dev/com.ibm.ws.jmx_fat/test-bundles/test-mbeans/src/com/ibm/ws/jmx/test/fat/TestBean.java @@ -0,0 +1,97 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jmx.test.fat; + +import java.util.Map; + +import javax.management.Attribute; +import javax.management.AttributeList; +import javax.management.AttributeNotFoundException; +import javax.management.DynamicMBean; +import javax.management.InvalidAttributeValueException; +import javax.management.MBeanException; +import javax.management.MBeanInfo; +import javax.management.ReflectionException; + +/** + * + */ +public class TestBean implements DynamicMBean { + + private final String name; + + protected TestBean(String name) { + System.setProperty("com.ibm.ws.jmx.test.fat", "true"); + this.name = name; + } + + /** + * DS method to activate this component. + * Best practice: this should be a protected method, not public or private + * + * @param properties : Map containing service properties + */ + protected void activate(Map properties) {} + + /** + * DS method to deactivate this component. + * Best practice: this should be a protected method, not public or private + * + * @param reason int representation of reason the component is stopping + */ + protected void deactivate(int reason) {} + + @Override + public String toString() { + return name; + } + + /** {@inheritDoc} */ + @Override + public Object getAttribute(String arg0) throws AttributeNotFoundException, MBeanException, ReflectionException { + return toString(); + } + + /** {@inheritDoc} */ + @Override + public AttributeList getAttributes(String[] arg0) { + // TODO Auto-generated method stub + return null; + } + + /** {@inheritDoc} */ + @Override + public MBeanInfo getMBeanInfo() { + return new MBeanInfo(name, "test bean", null, null, null, null); + } + + /** {@inheritDoc} */ + @Override + public Object invoke(String arg0, Object[] arg1, String[] arg2) throws MBeanException, ReflectionException { + // TODO Auto-generated method stub + return null; + } + + /** {@inheritDoc} */ + @Override + public void setAttribute(Attribute arg0) throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException { + // TODO Auto-generated method stub + + } + + /** {@inheritDoc} */ + @Override + public AttributeList setAttributes(AttributeList arg0) { + // TODO Auto-generated method stub + return null; + } +} diff --git a/dev/com.ibm.ws.jmx_fat/test-bundles/test-mbeans/src/com/ibm/ws/jmx/test/fat/TestBean1.java b/dev/com.ibm.ws.jmx_fat/test-bundles/test-mbeans/src/com/ibm/ws/jmx/test/fat/TestBean1.java new file mode 100755 index 00000000000..065c567bfca --- /dev/null +++ b/dev/com.ibm.ws.jmx_fat/test-bundles/test-mbeans/src/com/ibm/ws/jmx/test/fat/TestBean1.java @@ -0,0 +1,21 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jmx.test.fat; + +/** + * + */ +public class TestBean1 extends TestBean { + public TestBean1() { + super(TestBean1.class.getName()); + } +} diff --git a/dev/com.ibm.ws.jmx_fat/test-bundles/test-mbeans/src/com/ibm/ws/jmx/test/fat/TestBean2.java b/dev/com.ibm.ws.jmx_fat/test-bundles/test-mbeans/src/com/ibm/ws/jmx/test/fat/TestBean2.java new file mode 100755 index 00000000000..dcce080f80e --- /dev/null +++ b/dev/com.ibm.ws.jmx_fat/test-bundles/test-mbeans/src/com/ibm/ws/jmx/test/fat/TestBean2.java @@ -0,0 +1,25 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jmx.test.fat; + +/** + * + */ +public class TestBean2 extends TestBean { + + public TestBean2() { + super(TestBean2.class.getName()); + + // System.out.println("$$$$$$$$$$$$$$$$$$$$$$$ in TestBean2"); + } + +} diff --git a/dev/com.ibm.ws.jmx_fat/test-bundles/test-mbeans/src/com/ibm/ws/jmx/test/fat/TestBean3.java b/dev/com.ibm.ws.jmx_fat/test-bundles/test-mbeans/src/com/ibm/ws/jmx/test/fat/TestBean3.java new file mode 100755 index 00000000000..a41516778bb --- /dev/null +++ b/dev/com.ibm.ws.jmx_fat/test-bundles/test-mbeans/src/com/ibm/ws/jmx/test/fat/TestBean3.java @@ -0,0 +1,25 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jmx.test.fat; + +/** + * + */ +public class TestBean3 extends TestBean { + + public TestBean3() { + super(TestBean3.class.getName()); + + // System.out.println("###################### in TestBean3.ctor"); + } + +} diff --git a/dev/com.ibm.ws.jmx_fat/test-bundles/test-mbeans/src/com/ibm/ws/jmx/test/fat/package-info.java b/dev/com.ibm.ws.jmx_fat/test-bundles/test-mbeans/src/com/ibm/ws/jmx/test/fat/package-info.java new file mode 100755 index 00000000000..f6a5d5d0910 --- /dev/null +++ b/dev/com.ibm.ws.jmx_fat/test-bundles/test-mbeans/src/com/ibm/ws/jmx/test/fat/package-info.java @@ -0,0 +1,19 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +/** + * @version 1.0 + */ +@TraceOptions(traceGroup = "projectExample", messageBundle = "com.ibm.ws.jmx.test.fat.Messages") +package com.ibm.ws.jmx.test.fat; + +import com.ibm.websphere.ras.annotation.TraceOptions; + diff --git a/dev/com.ibm.ws.kernel.boot_fat/.classpath b/dev/com.ibm.ws.kernel.boot_fat/.classpath new file mode 100644 index 00000000000..c422489df40 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/dev/com.ibm.ws.kernel.boot_fat/.classpath.gradle b/dev/com.ibm.ws.kernel.boot_fat/.classpath.gradle new file mode 100644 index 00000000000..c422489df40 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/.classpath.gradle @@ -0,0 +1,7 @@ + + + + + + + diff --git a/dev/com.ibm.ws.kernel.boot_fat/.gitignore b/dev/com.ibm.ws.kernel.boot_fat/.gitignore new file mode 100644 index 00000000000..9fb7b834a97 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/.gitignore @@ -0,0 +1,5 @@ +*.log* +/TestBundleDeactivate.txt +/coverage.ec +/lib +/reports diff --git a/dev/com.ibm.ws.kernel.boot_fat/.project b/dev/com.ibm.ws.kernel.boot_fat/.project new file mode 100755 index 00000000000..86c8544a2b1 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/.project @@ -0,0 +1,23 @@ + + + com.ibm.ws.kernel.boot_fat + + + + + + org.eclipse.jdt.core.javabuilder + + + + + bndtools.core.bndbuilder + + + + + + org.eclipse.jdt.core.javanature + bndtools.core.bndnature + + diff --git a/dev/com.ibm.ws.kernel.boot_fat/.settings/org.eclipse.core.resources.prefs b/dev/com.ibm.ws.kernel.boot_fat/.settings/org.eclipse.core.resources.prefs new file mode 100755 index 00000000000..25d9425fe34 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,4 @@ +#Ant properties +#Automatically generated by the ant prepare.settings.files task +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/dev/com.ibm.ws.kernel.boot_fat/.settings/org.eclipse.jdt.core.prefs b/dev/com.ibm.ws.kernel.boot_fat/.settings/org.eclipse.jdt.core.prefs new file mode 100755 index 00000000000..845c3083c7d --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,286 @@ +#Ant properties +#Automatically generated by the ant prepare.settings.files task +org.eclipse.jdt.core.codeComplete.argumentPrefixes= +org.eclipse.jdt.core.codeComplete.argumentSuffixes= +org.eclipse.jdt.core.codeComplete.fieldPrefixes= +org.eclipse.jdt.core.codeComplete.fieldSuffixes= +org.eclipse.jdt.core.codeComplete.localPrefixes= +org.eclipse.jdt.core.codeComplete.localSuffixes= +org.eclipse.jdt.core.codeComplete.staticFieldPrefixes= +org.eclipse.jdt.core.codeComplete.staticFieldSuffixes= +org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes= +org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes= +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.6 +org.eclipse.jdt.core.formatter.align_type_members_on_columns=false +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=0 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=18 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=2 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=2 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=18 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=2 +org.eclipse.jdt.core.formatter.alignment_for_assignment=0 +org.eclipse.jdt.core.formatter.alignment_for_binary_expression=18 +org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=0 +org.eclipse.jdt.core.formatter.alignment_for_enum_constants=16 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=18 +org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=18 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=18 +org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=0 +org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=20 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=4 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +org.eclipse.jdt.core.formatter.blank_lines_before_field=0 +org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 +org.eclipse.jdt.core.formatter.blank_lines_before_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 +org.eclipse.jdt.core.formatter.blank_lines_before_package=0 +org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 +org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 +org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false +org.eclipse.jdt.core.formatter.comment.format_block_comments=true +org.eclipse.jdt.core.formatter.comment.format_header=false +org.eclipse.jdt.core.formatter.comment.format_html=false +org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true +org.eclipse.jdt.core.formatter.comment.format_line_comments=false +org.eclipse.jdt.core.formatter.comment.format_source_code=true +org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true +org.eclipse.jdt.core.formatter.comment.indent_root_tags=true +org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert +org.eclipse.jdt.core.formatter.comment.line_length=180 +org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true +org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true +org.eclipse.jdt.core.formatter.compact_else_if=true +org.eclipse.jdt.core.formatter.continuation_indentation=4 +org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=4 +org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off +org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on +org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false +org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=false +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true +org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_empty_lines=false +org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true +org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true +org.eclipse.jdt.core.formatter.indentation.size=8 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert +org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.join_lines_in_comments=false +org.eclipse.jdt.core.formatter.join_wrapped_lines=false +org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false +org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false +org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false +org.eclipse.jdt.core.formatter.lineSplit=180 +org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=true +org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=true +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 +org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=false +org.eclipse.jdt.core.formatter.tabulation.char=space +org.eclipse.jdt.core.formatter.tabulation.size=4 +org.eclipse.jdt.core.formatter.use_on_off_tags=true +org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false +org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true +org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true diff --git a/dev/com.ibm.ws.kernel.boot_fat/.settings/org.eclipse.jdt.ui.prefs b/dev/com.ibm.ws.kernel.boot_fat/.settings/org.eclipse.jdt.ui.prefs new file mode 100755 index 00000000000..fadbc117581 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,117 @@ +#Ant properties +#Automatically generated by the ant prepare.settings.files task +cleanup.add_default_serial_version_id=false +cleanup.add_generated_serial_version_id=true +cleanup.add_missing_annotations=true +cleanup.add_missing_deprecated_annotations=true +cleanup.add_missing_methods=false +cleanup.add_missing_nls_tags=false +cleanup.add_missing_override_annotations=true +cleanup.add_missing_override_annotations_interface_methods=true +cleanup.add_serial_version_id=false +cleanup.always_use_blocks=true +cleanup.always_use_parentheses_in_expressions=false +cleanup.always_use_this_for_non_static_field_access=false +cleanup.always_use_this_for_non_static_method_access=false +cleanup.convert_to_enhanced_for_loop=false +cleanup.correct_indentation=true +cleanup.format_source_code=false +cleanup.format_source_code_changes_only=false +cleanup.make_local_variable_final=false +cleanup.make_parameters_final=true +cleanup.make_private_fields_final=false +cleanup.make_type_abstract_if_missing_method=false +cleanup.make_variable_declarations_final=false +cleanup.never_use_blocks=false +cleanup.never_use_parentheses_in_expressions=true +cleanup.organize_imports=true +cleanup.qualify_static_field_accesses_with_declaring_class=false +cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true +cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true +cleanup.qualify_static_member_accesses_with_declaring_class=true +cleanup.qualify_static_method_accesses_with_declaring_class=false +cleanup.remove_private_constructors=true +cleanup.remove_trailing_whitespaces=true +cleanup.remove_trailing_whitespaces_all=true +cleanup.remove_trailing_whitespaces_ignore_empty=false +cleanup.remove_unnecessary_casts=true +cleanup.remove_unnecessary_nls_tags=true +cleanup.remove_unused_imports=true +cleanup.remove_unused_local_variables=false +cleanup.remove_unused_private_fields=true +cleanup.remove_unused_private_members=false +cleanup.remove_unused_private_methods=true +cleanup.remove_unused_private_types=true +cleanup.sort_members=false +cleanup.sort_members_all=false +cleanup.use_blocks=true +cleanup.use_blocks_only_for_return_and_throw=false +cleanup.use_parentheses_in_expressions=true +cleanup.use_this_for_non_static_field_access=false +cleanup.use_this_for_non_static_field_access_only_if_necessary=true +cleanup.use_this_for_non_static_method_access=false +cleanup.use_this_for_non_static_method_access_only_if_necessary=true +eclipse.preferences.version=1 +editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true +org.eclipse.jdt.ui.exception.name=e +org.eclipse.jdt.ui.gettersetter.use.is=true +org.eclipse.jdt.ui.ignorelowercasenames=true +org.eclipse.jdt.ui.importorder=java;javax;org;com; +org.eclipse.jdt.ui.javadoc=true +org.eclipse.jdt.ui.keywordthis=false +org.eclipse.jdt.ui.ondemandthreshold=99 +org.eclipse.jdt.ui.overrideannotation=true +org.eclipse.jdt.ui.staticondemandthreshold=99 +org.eclipse.jdt.ui.text.custom_code_templates= +sp_cleanup.add_default_serial_version_id=true +sp_cleanup.add_generated_serial_version_id=false +sp_cleanup.add_missing_annotations=true +sp_cleanup.add_missing_deprecated_annotations=true +sp_cleanup.add_missing_methods=false +sp_cleanup.add_missing_nls_tags=false +sp_cleanup.add_missing_override_annotations=true +sp_cleanup.add_missing_override_annotations_interface_methods=true +sp_cleanup.add_serial_version_id=false +sp_cleanup.always_use_blocks=true +sp_cleanup.always_use_parentheses_in_expressions=false +sp_cleanup.always_use_this_for_non_static_field_access=false +sp_cleanup.always_use_this_for_non_static_method_access=false +sp_cleanup.convert_to_enhanced_for_loop=false +sp_cleanup.correct_indentation=false +sp_cleanup.format_source_code=true +sp_cleanup.format_source_code_changes_only=false +sp_cleanup.make_local_variable_final=false +sp_cleanup.make_parameters_final=false +sp_cleanup.make_private_fields_final=true +sp_cleanup.make_type_abstract_if_missing_method=false +sp_cleanup.make_variable_declarations_final=true +sp_cleanup.never_use_blocks=false +sp_cleanup.never_use_parentheses_in_expressions=true +sp_cleanup.on_save_use_additional_actions=true +sp_cleanup.organize_imports=true +sp_cleanup.qualify_static_field_accesses_with_declaring_class=false +sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_with_declaring_class=false +sp_cleanup.qualify_static_method_accesses_with_declaring_class=false +sp_cleanup.remove_private_constructors=true +sp_cleanup.remove_trailing_whitespaces=true +sp_cleanup.remove_trailing_whitespaces_all=true +sp_cleanup.remove_trailing_whitespaces_ignore_empty=false +sp_cleanup.remove_unnecessary_casts=true +sp_cleanup.remove_unnecessary_nls_tags=true +sp_cleanup.remove_unused_imports=true +sp_cleanup.remove_unused_local_variables=false +sp_cleanup.remove_unused_private_fields=true +sp_cleanup.remove_unused_private_members=false +sp_cleanup.remove_unused_private_methods=true +sp_cleanup.remove_unused_private_types=true +sp_cleanup.sort_members=false +sp_cleanup.sort_members_all=false +sp_cleanup.use_blocks=false +sp_cleanup.use_blocks_only_for_return_and_throw=false +sp_cleanup.use_parentheses_in_expressions=false +sp_cleanup.use_this_for_non_static_field_access=false +sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true +sp_cleanup.use_this_for_non_static_method_access=false +sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true diff --git a/dev/com.ibm.ws.kernel.boot_fat/bnd.bnd b/dev/com.ibm.ws.kernel.boot_fat/bnd.bnd new file mode 100644 index 00000000000..20b28a82bd2 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/bnd.bnd @@ -0,0 +1,28 @@ +-include= ~../cnf/resources/bnd/bundle.props +bVersion=1.0 + +src: \ + fat/src + +-buildpath: \ + ${javac.bootclasspath.java6}, \ + ../build.sharedResources/lib/junit/old/junit.jar;version=file, \ + ../build.sharedResources/lib/ws-junit/ws-junit.jar;version=file, \ + ../build.sharedResources/lib/hamcrest-all.jar;version=file, \ + ../build.sharedResources/lib/jmock/old/jmock-junit4.jar;version=file, \ + ../build.sharedResources/lib/jmock/old/jmock.jar;version=file, \ + fattest.simplicity;version=latest, \ + ../fattest.simplicity/lib/public.api.jar;version=file, \ + ../com.ibm.ws.kernel.boot.archive/lib/org.apache.commons.compress-1.10.jar;version=file, \ + com.ibm.websphere.org.osgi.core.6.0.0;version=latest, \ + com.ibm.websphere.org.osgi.service.cm.1.5.0;version=latest,\ + com.ibm.websphere.org.osgi.service.component.1.3.0;version=latest,\ + com.ibm.wsspi.thirdparty.equinox;version=latest, \ + com.ibm.ws.kernel.boot.core;version=latest,\ + com.ibm.ws.kernel.service;version=latest,\ + com.ibm.ws.kernel.service.location;version=latest,\ + com.ibm.ws.logging.core;version=latest,\ + com.ibm.ws.org.eclipse.equinox.region.1.3.2;version=latest, \ + com.ibm.ws.runtime.update;version=latest, \ + com.ibm.ws.kernel.feature.core;version=latest, \ + com.ibm.ws.kernel.feature;version=latest diff --git a/dev/com.ibm.ws.kernel.boot_fat/bnd.bnd.gradle b/dev/com.ibm.ws.kernel.boot_fat/bnd.bnd.gradle new file mode 100644 index 00000000000..20b28a82bd2 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/bnd.bnd.gradle @@ -0,0 +1,28 @@ +-include= ~../cnf/resources/bnd/bundle.props +bVersion=1.0 + +src: \ + fat/src + +-buildpath: \ + ${javac.bootclasspath.java6}, \ + ../build.sharedResources/lib/junit/old/junit.jar;version=file, \ + ../build.sharedResources/lib/ws-junit/ws-junit.jar;version=file, \ + ../build.sharedResources/lib/hamcrest-all.jar;version=file, \ + ../build.sharedResources/lib/jmock/old/jmock-junit4.jar;version=file, \ + ../build.sharedResources/lib/jmock/old/jmock.jar;version=file, \ + fattest.simplicity;version=latest, \ + ../fattest.simplicity/lib/public.api.jar;version=file, \ + ../com.ibm.ws.kernel.boot.archive/lib/org.apache.commons.compress-1.10.jar;version=file, \ + com.ibm.websphere.org.osgi.core.6.0.0;version=latest, \ + com.ibm.websphere.org.osgi.service.cm.1.5.0;version=latest,\ + com.ibm.websphere.org.osgi.service.component.1.3.0;version=latest,\ + com.ibm.wsspi.thirdparty.equinox;version=latest, \ + com.ibm.ws.kernel.boot.core;version=latest,\ + com.ibm.ws.kernel.service;version=latest,\ + com.ibm.ws.kernel.service.location;version=latest,\ + com.ibm.ws.logging.core;version=latest,\ + com.ibm.ws.org.eclipse.equinox.region.1.3.2;version=latest, \ + com.ibm.ws.runtime.update;version=latest, \ + com.ibm.ws.kernel.feature.core;version=latest, \ + com.ibm.ws.kernel.feature;version=latest diff --git a/dev/com.ibm.ws.kernel.boot_fat/build-test.xml b/dev/com.ibm.ws.kernel.boot_fat/build-test.xml new file mode 100755 index 00000000000..305d7ade58b --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/build-test.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/dev/com.ibm.ws.kernel.boot_fat/build.gradle b/dev/com.ibm.ws.kernel.boot_fat/build.gradle new file mode 100644 index 00000000000..e69de29bb2d diff --git a/dev/com.ibm.ws.kernel.boot_fat/delivery.sets b/dev/com.ibm.ws.kernel.boot_fat/delivery.sets new file mode 100755 index 00000000000..674398425a0 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/delivery.sets @@ -0,0 +1 @@ +SLE diff --git a/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/FATSuite.java b/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/FATSuite.java new file mode 100755 index 00000000000..1bbe7536a7b --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/FATSuite.java @@ -0,0 +1,59 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.kernel.boot; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +import com.ibm.ws.kernel.boot.commandline.CreateCommandTest; +import com.ibm.ws.kernel.boot.commandline.DumpCommandTest; +import com.ibm.ws.kernel.boot.commandline.PauseResumeCommandTest; +import com.ibm.ws.kernel.boot.commandline.StartCommandTest; +import com.ibm.ws.kernel.boot.commandport.ServerCommandPortTest; +import com.ibm.ws.kernel.boot.internal.commands.LogLevelPropertyTest; +import com.ibm.ws.kernel.boot.internal.commands.PackageCommandTest; +import com.ibm.ws.kernel.provisioning.KernelChangeTest; +import com.ibm.ws.kernel.provisioning.ProvisioningTest; +import com.ibm.wsspi.kernel.embeddable.EmbeddedServerAddProductExtensionMultipleTest; +import com.ibm.wsspi.kernel.embeddable.EmbeddedServerAddProductExtensionTest; +import com.ibm.wsspi.kernel.embeddable.EmbeddedServerTest; + +/** + * Collection of a few fast example tests + */ +@RunWith(Suite.class) +/* + * The classes specified in the @SuiteClasses annotation + * below should only be mainline test cases that complete + * in a combined total of 5 minutes or less. + */ +@SuiteClasses({ + EmbeddedServerTest.class, + EmbeddedServerAddProductExtensionTest.class, + EmbeddedServerAddProductExtensionMultipleTest.class, + ProvisioningTest.class, + KernelChangeTest.class, + ServerStartTest.class, + ServerStartAsServiceTest.class, + ShutdownTest.class, + ServerCommandPortTest.class, + DumpCommandTest.class, + PackageCommandTest.class, + LogLevelPropertyTest.class, + CreateCommandTest.class, + StartCommandTest.class, + ServerClasspathTest.class, + ServerStartJVMOptionsTest.class, + PauseResumeCommandTest.class +}) +public class FATSuite {} diff --git a/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/OnlyRunOnWinRule.java b/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/OnlyRunOnWinRule.java new file mode 100644 index 00000000000..e8c45e8428d --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/OnlyRunOnWinRule.java @@ -0,0 +1,41 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2016 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.kernel.boot; + +import org.junit.rules.TestRule; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; + +import com.ibm.websphere.simplicity.log.Log; + +/** + * Rule to run on Windows. + */ +public class OnlyRunOnWinRule implements TestRule { + + /** This constant is exposed to any test code to use. It is true iff the FAT is running on z/OS. */ + public static final boolean IS_RUNNING_ON_WINDOWS = System.getProperty("os.name").toLowerCase().contains("windows"); + + @Override + public Statement apply(final Statement statement, final Description description) { + return new Statement() { + @Override + public void evaluate() throws Throwable { + if (IS_RUNNING_ON_WINDOWS) { + statement.evaluate(); + } else { + Log.info(description.getTestClass(), description.getMethodName(), "Test class or method is skipped due to run on Windows rule"); + } + } + }; + } +} diff --git a/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/ServerClasspathTest.java b/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/ServerClasspathTest.java new file mode 100644 index 00000000000..b4381d98d19 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/ServerClasspathTest.java @@ -0,0 +1,84 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2016 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.kernel.boot; + +import static org.junit.Assert.assertEquals; + +import java.util.Iterator; +import java.util.List; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.rules.TestRule; + +import componenttest.custom.junit.runner.OnlyRunInJava7Rule; +import componenttest.topology.impl.LibertyServer; +import componenttest.topology.impl.LibertyServerFactory; + +/** + * Tests what can and cannot be loaded by the server's JVM classpath. + */ +public class ServerClasspathTest { + + private static final String SERVER_NAME = "com.ibm.ws.kernel.boot.classpath.fat"; + + private static final LibertyServer server = LibertyServerFactory.getLibertyServer(SERVER_NAME); + + private static final String[] EXPECTED_PACKAGES = { "com.ibm.ws.kernel", "java.", "javax.", "sun.", + "org.osgi.framework", "com.ibm.crypto", "com.ibm.security", + "com.ibm.misc", "com.ibm.xml", "com.ibm.nio", "com.ibm.jvm", + "org.apache.xerces", "com.ibm.Compiler", "com.ibm.oti", + "org.omg.CORBA", "com.sun", "org.xml.sax", "com.ibm.jit", + "com.ibm.jsse2", "com.ibm.lang.management", "com.ibm.tools.attach", + "com.ibm.virtualization.management", "com.ibm.wsspi.kernel", + "jdk.xml.internal", // Windows, Sun + "jdk.net" // Java 8, Sun 1.7 + }; + + @ClassRule + public static final TestRule java7Rule = new OnlyRunInJava7Rule(); + + @BeforeClass + public static void before() throws Exception { + server.startServer(); + } + + @AfterClass + public static void after() throws Exception { + server.stopServer(); + } + + @Test + public void testJvmAppClasspath() throws Exception { + //TODO: check logs for any packages that are not in the expected packages list + StringBuilder unexpectedPackages = new StringBuilder(); + List pkgsOnCP = server.findStringsInLogs("AppLoader can load: .*", server.getConsoleLogFile()); + Iterator iter = pkgsOnCP.iterator(); + boolean allowed; + while (iter.hasNext()) { + allowed = false; + String pkg = iter.next().substring("AppLoader can load: ".length()); + for (String allowedPkg : EXPECTED_PACKAGES) { + if (pkg.startsWith(allowedPkg)) { + allowed = true; + break; + } + } + if (!allowed) { + unexpectedPackages.append(" " + pkg); + } + } + assertEquals("Found unexpected packages in the server JVM's application classpath", "", unexpectedPackages.toString()); + } +} diff --git a/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/ServerStartAsServiceTest.java b/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/ServerStartAsServiceTest.java new file mode 100644 index 00000000000..bd65dd6d56b --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/ServerStartAsServiceTest.java @@ -0,0 +1,140 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.kernel.boot; + +import static org.junit.Assert.assertTrue; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.ProtocolException; +import java.net.URL; + +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.rules.TestRule; + +import com.ibm.websphere.simplicity.log.Log; +import componenttest.topology.impl.LibertyServer; +import componenttest.topology.impl.LibertyServerFactory; + +/** + * This test bucket tests the server startup process. + */ +public class ServerStartAsServiceTest { + private static final Class c = ServerStartAsServiceTest.class; + + private static final String SERVER_NAME = "ServerStartAsServiceTest"; + + private static LibertyServer server; + + @ClassRule + public static final TestRule onWinRule = new OnlyRunOnWinRule(); + + @Test + /** + * test Liberty Server to Register, Start, Stop and Unregister as a Windows Service + * + * @throws Exception + */ + public void testWinServiceLifeCycle() throws Exception { + final String METHOD_NAME = "testWinServiceLifeCycle"; + Log.entering(c, METHOD_NAME); + + Log.info(c, METHOD_NAME, "calling LibertyServerFactory.getLibertyServer(SERVER_NAME, ON): " + SERVER_NAME); + server = LibertyServerFactory.getLibertyServer(SERVER_NAME, LibertyServerFactory.WinServiceOption.ON); + + Log.info(c, METHOD_NAME, "calling server.startServer()"); + server.startServer(); + + Log.info(c, METHOD_NAME, "calling server.waitForStringInLog('CWWKF0011I')"); + server.waitForStringInLog("CWWKF0011I"); + + assertTrue("the server should have been started", server.isStarted()); + + Log.info(c, METHOD_NAME, "calling server.stopServer(): " + SERVER_NAME); + server.stopServer(); + + Log.exiting(c, METHOD_NAME); + } + + @Test + /** + * test Liberty Server to Register, Start, Stop and Unregister as a Windows Service + * test snoop can be installed and accessed. + * + * @throws Exception + */ + public void testWinServiceAppAccess() throws Exception { + final String METHOD_NAME = "testWinServiceAppAccess"; + + Log.entering(c, METHOD_NAME); + + Log.info(c, METHOD_NAME, "calling LibertyServerFactory.getLibertyServer(SERVER_NAME, ON): " + SERVER_NAME); + server = LibertyServerFactory.getLibertyServer(SERVER_NAME, LibertyServerFactory.WinServiceOption.ON); + + Log.info(c, METHOD_NAME, "calling server.startServer()"); + server.startServer(); + + Log.info(c, METHOD_NAME, "calling server.waitForStringInLog('CWWKF0011I')"); + server.waitForStringInLog("CWWKF0011I"); + + assertTrue("the server should have been started", server.isStarted()); + + URL url = new URL("http://" + server.getHostname() + ":" + server.getHttpDefaultPort() + "/snoop"); + Log.info(c, METHOD_NAME, "Calling Snoop Application with URL=" + url.toString()); + HttpURLConnection con = getHttpConnection(url); + BufferedReader br = getConnectionStream(con); + String line = br.readLine(); + assertTrue("The response did not contain the \'Snoop Servlet\'", + line.contains("Snoop Servlet")); + + Log.info(c, METHOD_NAME, "return line: " + line); + + Log.info(c, METHOD_NAME, "calling server.stopServer(): " + SERVER_NAME); + server.stopServer(); + + Log.exiting(c, METHOD_NAME); + } + + /** + * This method is used to get a connection stream from an HTTP connection. It + * gives the output from the webpage that it gets from the connection + * + * @param con The connection to the HTTP address + * @return The Output from the webpage + */ + private static BufferedReader getConnectionStream(HttpURLConnection con) throws IOException { + InputStream is = con.getInputStream(); + InputStreamReader isr = new InputStreamReader(is); + BufferedReader br = new BufferedReader(isr); + return br; + } + + /** + * This method creates a connection to a webpage and then reutrns the connection + * + * @param url The Http Address to connect to + * @return The connection to the http address + */ + private static HttpURLConnection getHttpConnection(URL url) throws IOException, ProtocolException { + HttpURLConnection con = (HttpURLConnection) url.openConnection(); + con.setDoInput(true); + con.setDoOutput(true); + con.setUseCaches(false); + con.setRequestMethod("GET"); + return con; + } + +} diff --git a/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/ServerStartJVMOptionsTest.java b/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/ServerStartJVMOptionsTest.java new file mode 100644 index 00000000000..2207aa68e5d --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/ServerStartJVMOptionsTest.java @@ -0,0 +1,457 @@ +/* +* IBM Confidential +* +* OCO Source Materials +* +* WLP Copyright IBM Corp. 2016 +* +* The source code for this program is not published or otherwise divested +* of its trade secrets, irrespective of what has been deposited with the +* U.S. Copyright Office. +*/ +package com.ibm.ws.kernel.boot; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.util.Enumeration; +import java.util.Properties; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.ibm.websphere.simplicity.ProgramOutput; +import com.ibm.websphere.simplicity.log.Log; + +import componenttest.custom.junit.runner.Mode; +import componenttest.custom.junit.runner.Mode.TestMode; +import componenttest.topology.impl.LibertyServer; +import componenttest.topology.impl.LibertyServerFactory; + +/** + * + */ +public class ServerStartJVMOptionsTest { + private static final Class c = ServerStartJVMOptionsTest.class; + + private static final String SERVER_NAME = "com.ibm.ws.kernel.boot.serverstart.fat"; + static String executionDir; + + private static LibertyServer server; + static File dirs; + static File dirs2; + static File jvmoptionsconfigdefaults; + static File jvmoptionsserverroot; + static File jvmoptionsconfigoverrides; + static File etcjvmoptions; + static File sharedjvmoptions; + static File bootstrapPropFile; + + @BeforeClass + public static void before() { + server = LibertyServerFactory.getLibertyServer(SERVER_NAME); + executionDir = server.getInstallRoot(); + dirs = new File(executionDir + File.separator + "usr" + File.separator + "servers" + File.separator + SERVER_NAME + + File.separator + "configDropins" + File.separator + "defaults"); + dirs2 = new File(executionDir + File.separator + "usr" + File.separator + "servers" + File.separator + SERVER_NAME + + File.separator + "configDropins" + File.separator + "overrides"); + jvmoptionsconfigdefaults = new File(executionDir + File.separator + "usr" + File.separator + "servers" + File.separator + SERVER_NAME + + File.separator + "configDropins" + File.separator + "defaults" + File.separator + "jvm.options"); + jvmoptionsserverroot = new File(executionDir + File.separator + "usr" + File.separator + "servers" + File.separator + SERVER_NAME + + File.separator + "jvm.options"); + jvmoptionsconfigoverrides = new File(executionDir + File.separator + "usr" + File.separator + "servers" + File.separator + SERVER_NAME + + File.separator + "configDropins" + File.separator + "overrides" + File.separator + "jvm.options"); + etcjvmoptions = new File(executionDir + File.separator + "etc" + File.separator + "jvm.options"); + sharedjvmoptions = new File(executionDir + File.separator + "usr" + File.separator + "shared" + File.separator + "jvm.options"); + bootstrapPropFile = new File(executionDir + File.separator + "usr" + File.separator + "servers" + File.separator + SERVER_NAME + + File.separator + "bootstrap.properties"); + } + + @AfterClass + public static void after() throws Exception { + if (server.isStarted()) { + server.stopServer(); + } + } + + /** + * This test ensures the server can be started with no jvm.options files or merged.jvm.options file + * + * @throws Exception + */ + @Test + public void testServerStartNoJVMOptions() throws Exception { + final String METHOD_NAME = "testServerStartNoJVMOptions"; + Log.entering(c, METHOD_NAME); + + String command = "bin" + File.separator + "server"; + String[] parms = new String[2]; + parms[0] = "start"; + parms[1] = SERVER_NAME; + + Properties envVars = new Properties(); + envVars.put("CDPATH", "."); + + initialize(); + + ProgramOutput po = server.getMachine().execute(command, parms, executionDir, envVars); + Log.info(c, METHOD_NAME, "server start stdout = " + po.getStdout()); + Log.info(c, METHOD_NAME, "server start stderr = " + po.getStderr()); + + server.waitForStringInLog("CWWKF0011I"); + server.resetStarted(); + + assertTrue("the server should have been started", server.isStarted()); + + server.stopServer(); + } + + /** + * This test ensures the server fails over to etc/jvm.options if none are found + * + * @throws Exception + */ + @Test + public void testServerStartNoJVMOptionsETCFailover() throws Exception { + final String METHOD_NAME = "testServerStartNoJVMOptionsETCFailover"; + Log.entering(c, METHOD_NAME); + + String command = "bin" + File.separator + "server"; + String[] parms = new String[2]; + parms[0] = "start"; + parms[1] = SERVER_NAME; + + Properties envVars = new Properties(); + envVars.put("CDPATH", "."); + + initialize(); + + Writer isw = new OutputStreamWriter(new FileOutputStream(etcjvmoptions), "UTF-8"); + BufferedWriter bw = new BufferedWriter(isw); + bw.write("-DTest1=Test1"); + bw.close(); + + ProgramOutput po = server.getMachine().execute(command, parms, executionDir, envVars); + Log.info(c, METHOD_NAME, "server start stdout = " + po.getStdout()); + Log.info(c, METHOD_NAME, "server start stderr = " + po.getStderr()); + + server.waitForStringInLog("CWWKF0011I"); + server.resetStarted(); + + server.serverDump(); + File[] filesAfterDump = new File(executionDir + File.separator + "usr" + File.separator + "servers" + File.separator + SERVER_NAME).listFiles(); + + File dumpFile = new File(""); + for (File f : filesAfterDump) { + String fileName = f.getName(); + Log.info(c, METHOD_NAME, "Found file: " + fileName); + if (fileName.startsWith(SERVER_NAME + ".dump") && fileName.endsWith(".zip")) { + dumpFile = f; + break; + } + } + + if (dumpFile.getPath().compareTo("") == 0) { + fail("The Dump File was not found"); + } + + ZipFile zipFile = new ZipFile(dumpFile); + + boolean foundTest1 = false; + for (Enumeration en = zipFile.entries(); en.hasMoreElements();) { + ZipEntry entry = en.nextElement(); + String entryName = entry.getName(); + if (entryName.endsWith("JavaRuntimeInformation.txt")) { + InputStream inputstream = zipFile.getInputStream(entry); + BufferedReader reader = new BufferedReader(new InputStreamReader(inputstream)); + String line; + int i = 0; + while ((line = reader.readLine()) != null) { + Log.info(c, METHOD_NAME, "Run" + i + ": " + line); + if (line.contains("-DTest1=Test1")) { + foundTest1 = true; + break; + } + i++; + } + + reader.close(); + inputstream.close(); + } + } + + zipFile.close(); + dumpFile.delete(); + assertTrue("The jvm option was not found", foundTest1); + + server.stopServer(); + } + + /** + * This test ensures the server can be started with one jvm.options file + * + * @throws Exception + */ + @Test + public void testServerStartOneJVMOption() throws Exception { + final String METHOD_NAME = "testServerStartOneJVMOption"; + Log.entering(c, METHOD_NAME); + + String command = "bin" + File.separator + "server"; + String[] parms = new String[2]; + parms[0] = "start"; + parms[1] = SERVER_NAME; + + Properties envVars = new Properties(); + envVars.put("CDPATH", "."); + + initialize(); + + Writer isw = new OutputStreamWriter(new FileOutputStream(jvmoptionsconfigdefaults), "UTF-8"); + BufferedWriter bw = new BufferedWriter(isw); + bw.write("-DTest1=Test1"); + bw.close(); + + ProgramOutput po = server.getMachine().execute(command, parms, executionDir, envVars); + Log.info(c, METHOD_NAME, "server start stdout = " + po.getStdout()); + Log.info(c, METHOD_NAME, "server start stderr = " + po.getStderr()); + server.waitForStringInLog("CWWKF0011I"); + server.resetStarted(); + + server.serverDump(); + File[] filesAfterDump = new File(executionDir + File.separator + "usr" + File.separator + "servers" + File.separator + SERVER_NAME).listFiles(); + + File dumpFile = new File(""); + for (File f : filesAfterDump) { + String fileName = f.getName(); + Log.info(c, METHOD_NAME, "Found file: " + fileName); + if (fileName.startsWith(SERVER_NAME + ".dump") && fileName.endsWith(".zip")) { + dumpFile = f; + break; + } + } + + if (dumpFile.getPath().compareTo("") == 0) { + fail("The Dump File was not found"); + } + + ZipFile zipFile = new ZipFile(dumpFile); + + boolean foundTest1 = false; + for (Enumeration en = zipFile.entries(); en.hasMoreElements();) { + ZipEntry entry = en.nextElement(); + String entryName = entry.getName(); + if (entryName.endsWith("JavaRuntimeInformation.txt")) { + InputStream inputstream = zipFile.getInputStream(entry); + BufferedReader reader = new BufferedReader(new InputStreamReader(inputstream)); + String line; + int i = 0; + while ((line = reader.readLine()) != null) { + Log.info(c, METHOD_NAME, "Run" + i + ": " + line); + if (line.contains("-DTest1=Test1")) { + foundTest1 = true; + break; + } + i++; + } + + reader.close(); + inputstream.close(); + } + } + + zipFile.close(); + dumpFile.delete(); + assertTrue("The jvm option was not found", foundTest1); + + server.stopServer(); + } + + /** + * This test ensures the server can be started with all jvm.options files and + * the right options are used at the end + * + * @throws Exception + */ + @Test + @Mode(TestMode.LITE) + public void testServerStartAllJVMOptions() throws Exception { + final String METHOD_NAME = "testServerStartAllJVMOptions"; + Log.entering(c, METHOD_NAME); + + String command = "bin" + File.separator + "server"; + String[] parms = new String[2]; + parms[0] = "start"; + parms[1] = SERVER_NAME; + + Properties envVars = new Properties(); + envVars.put("CDPATH", "."); + + initialize(); + + Writer isw = new OutputStreamWriter(new FileOutputStream(jvmoptionsconfigdefaults), "UTF-8"); + BufferedWriter bw = new BufferedWriter(isw); + bw.write("-DTest=Bad Value\n"); + bw.write("-DTest2=Bad Value\n"); + bw.write("-DTest3=Good Value\n"); + bw.write("-Xmx512m\n"); + bw.close(); + Writer isw2 = new OutputStreamWriter(new FileOutputStream(jvmoptionsserverroot), "UTF-8"); + BufferedWriter bw2 = new BufferedWriter(isw2); + bw2.write("-DTest=Good Value\n"); + bw2.write("-DTest4=Bad Value\n"); + bw2.write("-DTest5=Good Value\n"); + bw2.write("-Xmx1024m\n"); + bw2.close(); + Writer isw3 = new OutputStreamWriter(new FileOutputStream(jvmoptionsconfigoverrides), "UTF-8"); + BufferedWriter bw3 = new BufferedWriter(isw3); + bw3.write("-DTest2=Good Value\n"); + bw3.write("-DTest4=Good Value\n"); + bw3.write("-DTest6=Good Value\n"); + bw3.write("-XX:MaxPermSize=512m"); + bw3.close(); + Writer isw4 = new OutputStreamWriter(new FileOutputStream(sharedjvmoptions), "UTF-8"); + BufferedWriter bw4 = new BufferedWriter(isw4); + bw4.write("-DTest2=Bad Value\n"); + bw4.write("-DTest7=Good Value\n"); + bw4.close(); + Writer isw5 = new OutputStreamWriter(new FileOutputStream(etcjvmoptions), "UTF-8"); + BufferedWriter bw5 = new BufferedWriter(isw5); + bw5.write("-DTest8=Bad Value\n"); + bw5.close(); + + ProgramOutput po = server.getMachine().execute(command, parms, executionDir, envVars); + Log.info(c, METHOD_NAME, "server start stdout = " + po.getStdout()); + Log.info(c, METHOD_NAME, "server start stderr = " + po.getStderr()); + server.waitForStringInLog("CWWKF0011I"); + server.resetStarted(); + + server.serverDump(); + File[] filesAfterDump = new File(executionDir + File.separator + "usr" + File.separator + "servers" + File.separator + SERVER_NAME).listFiles(); + + File dumpFile = new File(""); + for (File f : filesAfterDump) { + String fileName = f.getName(); + Log.info(c, METHOD_NAME, "Found file: " + fileName); + if (fileName.startsWith(SERVER_NAME + ".dump") && fileName.endsWith(".zip")) { + dumpFile = f; + break; + } + } + + if (dumpFile.getPath().compareTo("") == 0) { + fail("The Dump File was not found"); + } + + ZipFile zipFile = new ZipFile(dumpFile); + + boolean[] foundTest = new boolean[8]; + for (int i = 0; i < 8; i++) { + foundTest[i] = false; + } + for (Enumeration en = zipFile.entries(); en.hasMoreElements();) { + ZipEntry entry = en.nextElement(); + String entryName = entry.getName(); + if (entryName.endsWith("JavaHeapInfo.txt")) { + InputStream inputstream = zipFile.getInputStream(entry); + BufferedReader reader = new BufferedReader(new InputStreamReader(inputstream)); + String line; + int i = 0; + while ((line = reader.readLine()) != null) { + if (line.contains("MaxHeapSizeLimit")) { + String num[] = line.split(":"); + int heapsize = Integer.parseInt(num[1].substring(1)); + assertTrue("JVM Option " + i + " wasn't found", (heapsize == 1073741824)); + } + } + } + if (entryName.endsWith("JavaRuntimeInformation.txt")) { + boolean afterSysProps = false; + InputStream inputstream = zipFile.getInputStream(entry); + BufferedReader reader = new BufferedReader(new InputStreamReader(inputstream)); + String line; + int i = 0; + while ((line = reader.readLine()) != null) { + Log.info(c, "testJVMOptionsMergingAllOptions", "Run" + i + ": " + line); + if (line.contains("Java System Properties")) { + afterSysProps = true; + } + if (line.contains("-XX:MaxPermSize=512m")) { + foundTest[0] = true; + } + if (afterSysProps) { + if (line.contains("Test3=Good")) { + foundTest[1] = true; + } else if (line.contains("Test=Good Value")) { + foundTest[2] = true; + } else if (line.contains("Test5=Good Value")) { + foundTest[3] = true; + } else if (line.contains("Test2=Good Value")) { + foundTest[4] = true; + } else if (line.contains("Test4=Good Value")) { + foundTest[5] = true; + } else if (line.contains("Test6=Good Value")) { + foundTest[6] = true; + } else if (line.contains("Test7=Good Value")) { + foundTest[7] = true; + } else if (line.contains("Test=Bad Value")) { + fail("Contains Option 'Test=Bad Value' that it shouldn't"); + } else if (line.contains("Test2=Bad Value")) { + fail("Contains Option 'Test2=Bad Value' that it shouldn't"); + } else if (line.contains("Test4=Bad Value")) { + fail("Contains Option 'Test4=Bad Value' that it shouldn't"); + } else if (line.contains("Test2=Bad Value")) { + fail("Contains Option 'Test2=Bad Value' that it shouldn't"); + } else if (line.contains("Test8=Bad Value")) { + fail("Contains Option 'Test8=Bad Value' that it shouldn't"); + } + } + i++; + } + reader.close(); + inputstream.close(); + } + } + + zipFile.close(); + for (int i = 0; i < 8; i++) { + assertTrue("JVM Option " + i + " wasn't found", foundTest[i]); + } + + server.stopServer(); + } + + public void initialize() { + dirs.mkdirs(); + dirs2.mkdirs(); + if (jvmoptionsconfigdefaults.exists()) { + jvmoptionsconfigdefaults.delete(); + } + if (jvmoptionsserverroot.exists()) { + jvmoptionsserverroot.delete(); + } + if (jvmoptionsconfigoverrides.exists()) { + jvmoptionsconfigoverrides.delete(); + } + if (sharedjvmoptions.exists()) { + sharedjvmoptions.delete(); + } + if (etcjvmoptions.exists()) { + etcjvmoptions.delete(); + } + if (bootstrapPropFile.exists()) { + bootstrapPropFile.delete(); + } + } +} \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/ServerStartTest.java b/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/ServerStartTest.java new file mode 100755 index 00000000000..7f1e4ea87a9 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/ServerStartTest.java @@ -0,0 +1,153 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.kernel.boot; + +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.util.Properties; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestName; + +import com.ibm.websphere.simplicity.ProgramOutput; +import com.ibm.websphere.simplicity.log.Log; +import componenttest.topology.impl.LibertyServer; +import componenttest.topology.impl.LibertyServerFactory; + +/** + * This test bucket tests the server startup process. + */ +public class ServerStartTest { + private static final Class c = ServerStartTest.class; + + private static final String SERVER_NAME = "com.ibm.ws.kernel.boot.serverstart.fat"; + private static final String SYMLINK_NAME = "com.ibm.ws.kernel.boot.serverstart.fat.symlink"; + + private static LibertyServer server; + + @Rule + public TestName testName = new TestName(); + + @Before + public void before() { + server = LibertyServerFactory.getLibertyServer(SERVER_NAME); + } + + @After + public void after() throws Exception { + server.stopServer(); + } + + @Test + /** + * This test validates that the server start script functions correctly when the CDPATH environment variable + * is present. + * + * @throws Exception + */ + public void testServerStartWithCDPATH() throws Exception { + final String METHOD_NAME = "testServerStartWithCDPATH"; + Log.entering(c, METHOD_NAME); + + // issuing the command from the Liberty install root while supplying the bin directory as + // part of the command itself causes the server script to cd to the bin directory, which + // is where we noticed problems when CDPATH is set + String executionDir = server.getInstallRoot(); + String command = "bin" + File.separator + "server"; + + String[] parms = new String[2]; + parms[0] = "start"; + parms[1] = SERVER_NAME; + + Properties envVars = new Properties(); + envVars.put("CDPATH", "."); + + ProgramOutput po = server.getMachine().execute(command, parms, executionDir, envVars); + Log.info(c, METHOD_NAME, "server start stdout = " + po.getStdout()); + Log.info(c, METHOD_NAME, "server start stderr = " + po.getStderr()); + + server.waitForStringInLog("CWWKF0011I"); + + // because we didn't start the server using the LibertyServer APIs, we need to have it detect + // its started state so it will stop and save logs properly + server.resetStarted(); + + assertTrue("the server should have been started", server.isStarted()); + + Log.exiting(c, METHOD_NAME); + } + + @Test + /** + * This test validates that the server start functions correctly when the server is referenced + * via a symbolic link (on those systems which support same) + * + * @throws Exception + */ + public void testServerStartViaSymbolicLink() throws Exception + { + String linkCommand = "/bin/ln"; + + // only try this test if the unix ln command exists and can be executed + File ln = new File(linkCommand); + if (ln.exists() && ln.canExecute()) { + // Copy the server directory elsewhere + String originalPath = server.getServerRoot(); + String relocatedPath = server.getServerRoot() + "/../../" + server.getServerName(); + String copyCommand = "cp"; + String[] copyParms = new String[] { "-r", originalPath, relocatedPath }; // Make sure -r works on all these platforms... + ProgramOutput po = server.getMachine().execute(copyCommand, copyParms); + + // Set up the symlink + String symPath = server.getServerRoot() + "/../" + SYMLINK_NAME; + String unlinkCommand = "rm"; + String[] unlinkParms = new String[] { symPath }; + po = server.getMachine().execute(unlinkCommand, unlinkParms); + + String[] linkParms = new String[] { "-s", relocatedPath, symPath }; // Symbolic link relocated copy as + po = server.getMachine().execute(linkCommand, linkParms); + + // Get a handle to the alias.Note that this must use a new entry point to get a handle to an already configured server. + LibertyServer symlink_server = LibertyServerFactory.getExistingLibertyServer(SYMLINK_NAME); + + // Confirm it can start and stop + server.stopServer(); // Pause the original + symlink_server.startServer(); // Start the alias (and confirm) + symlink_server.stopServer(); // stop the alias (and confirm) + server.startServer(); // Resume original (in case following test needs it). + } + + } + + @Test + /** + * This test ensures that the servers starts without error when using the -Xfuture command line + * argument. This argument enforces strict class file verification. One customer ran into + * BundleExceptions due to empty package-info.class files (defect 177872). + */ + public void testServerStartWithDashXFutureCmdArg() throws Exception { + server.copyFileToTempDir("server.xml", "origServer.xml"); + try { + server.setServerConfigurationFile("Xfuture/server.xml"); + server.copyFileToLibertyServerRoot("Xfuture/jvm.options"); + + server.startServer(); + } finally { + server.deleteDirectoryFromLibertyServerRoot("jvm.options"); + server.setServerConfigurationFile("tmp/origServer.xml"); + } + } +} diff --git a/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/ShutdownTest.java b/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/ShutdownTest.java new file mode 100755 index 00000000000..3d8e6c97941 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/ShutdownTest.java @@ -0,0 +1,101 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2013, 2014 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.kernel.boot; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.net.HttpURLConnection; +import java.net.URL; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestName; + +import com.ibm.websphere.simplicity.log.Log; +import componenttest.topology.impl.LibertyServer; +import componenttest.topology.impl.LibertyServerFactory; + +public class ShutdownTest { + private static final Class c = ShutdownTest.class; + + @Rule + public final TestName testName = new TestName(); + + LibertyServer server; + + @Before + public void before() { + server = LibertyServerFactory.getLibertyServer("com.ibm.ws.kernel.shutdown.fat"); + } + + @After + public void after() throws Exception { + // We stop the server by other means, so wait for that stop to finish, + // and then call stopServer to save logs, reset log offsets, etc. + server.waitForStringInLog("CWWKE0036I"); + server.stopServer(); + } + + private void runTest(String exitMethodName) throws Exception { + final String m = testName.getMethodName(); + Log.entering(c, m); + try { + server.startServer(m + ".log"); + + URL url = new URL("http://" + server.getHostname() + ":" + server.getHttpDefaultPort() + "/shutdownfat?exit=" + exitMethodName); + try { + HttpURLConnection con = (HttpURLConnection) url.openConnection(); + Log.info(c, m, "HTTP response: " + con.getResponseCode()); + + InputStream in = con.getInputStream(); + try { + BufferedReader reader = new BufferedReader(new InputStreamReader(in)); + + for (String line; (line = reader.readLine()) != null;) { + Log.info(c, m, "Output: " + line); + } + } finally { + try { + in.close(); + } catch (IOException e) { + Log.error(c, m, e); + } + } + } catch (Throwable t) { + // The server might die before the response can be written. + StringWriter sw = new StringWriter(); + t.printStackTrace(new PrintWriter(sw)); + Log.info(ShutdownTest.class, "testSystemExit", "Ignoring " + sw.toString()); + } + + server.waitForStringInLog("CWWKE0084I:.*" + exitMethodName); + } finally { + Log.exiting(c, m); + } + } + + @Test + public void testSystemExit() throws Exception { + runTest("System.exit"); + } + + @Test + public void testRuntimeExit() throws Exception { + runTest("Runtime.exit"); + } +} diff --git a/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/commandline/CreateCommandTest.java b/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/commandline/CreateCommandTest.java new file mode 100755 index 00000000000..b9b3b1c02cb --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/commandline/CreateCommandTest.java @@ -0,0 +1,78 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2015 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.kernel.boot.commandline; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.ibm.websphere.simplicity.Machine; +import com.ibm.websphere.simplicity.ProgramOutput; +import componenttest.common.apiservices.Bootstrap; +import componenttest.topology.impl.LibertyFileManager; +import componenttest.topology.utils.LibertyServerUtils; + +/** + * + */ +public class CreateCommandTest { + + private final static double javaLevel = Double.parseDouble(System.getProperty("java.specification.version")); + + private final static String serverName = "com.ibm.ws.kernel.boot.commandline.CreateCommandTest"; + private static Bootstrap bootstrap; + private static Machine machine; + private static String installPath;; + private static String defaultServerPath;; + + @BeforeClass + public static void setup() throws Exception { + bootstrap = Bootstrap.getInstance(); + machine = LibertyServerUtils.createMachine(bootstrap); + installPath = LibertyFileManager.getInstallPath(bootstrap); + defaultServerPath = installPath + "/usr/servers/" + serverName; + } + + @Before + public void cleanupBeforeRun() throws Exception { + // since we are not using the normal LibertyServer class for this server, + // we need to make sure to explicitly clean up. We do this before running + // the test in order to preserve the contents on disk. + if (LibertyFileManager.libertyFileExists(machine, defaultServerPath)) { + LibertyFileManager.deleteLibertyDirectoryAndContents(machine, defaultServerPath); + } + } + + @Test + public void testIsServerEnvCreated() throws Exception { + + ProgramOutput po = LibertyServerUtils.executeLibertyCmd(bootstrap, "server", "create", serverName); + assertEquals("Unexpected return code from server create command", 0, po.getReturnCode()); + + // check that server directory was created + assertTrue("Expected server directory to exist at " + defaultServerPath + ", but does not", LibertyFileManager.libertyFileExists(machine, defaultServerPath)); + + // check that server.xml exists + String serverXmlPath = defaultServerPath + "/server.xml"; + assertTrue("Expected server.xml file to exist at " + serverXmlPath + ", but does not", LibertyFileManager.libertyFileExists(machine, serverXmlPath)); + + // if we are running in a JVM that is version 1.8 or higher, we also need to check for the server.env file + if (javaLevel >= 1.8) { + String serverEnvPath = defaultServerPath + "/server.env"; + assertTrue("Expected server.env file to exist at " + serverEnvPath + ", but does not", LibertyFileManager.libertyFileExists(machine, serverEnvPath)); + } + + } +} diff --git a/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/commandline/DumpCommandTest.java b/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/commandline/DumpCommandTest.java new file mode 100755 index 00000000000..c4c15ea5c1f --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/commandline/DumpCommandTest.java @@ -0,0 +1,154 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.kernel.boot.commandline; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assume.assumeTrue; + +import java.io.File; +import java.util.Properties; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestName; + +import com.ibm.websphere.simplicity.OperatingSystem; +import com.ibm.websphere.simplicity.ProgramOutput; +import com.ibm.websphere.simplicity.log.Log; +import componenttest.topology.impl.LibertyServer; +import componenttest.topology.impl.LibertyServerFactory; + +/** + * + */ +public class DumpCommandTest { + private static final Class c = DumpCommandTest.class; + + @Rule + public final TestName testName = new TestName(); + + private static LibertyServer server; + private static File serverRoot; + private static boolean isIBM_JVM = false; + + @BeforeClass + public static void before() throws Exception { + server = LibertyServerFactory.getLibertyServer("com.ibm.ws.kernel.shutdown.fat"); + Log.info(c, "before", "starting server"); + server.startServer("DumpCommandTest.log"); + serverRoot = new File(server.getServerRoot()); + + String javaHome = server.getMachineJavaJDK(); + Properties env = new Properties(); + env.setProperty("JAVA_HOME", javaHome); + String javaBinDir = javaHome + "/bin"; + ProgramOutput javaVersionOutput = server.getMachine().execute(javaBinDir + "/java", new String[] { "-version" }, javaBinDir, env); + String stdout = javaVersionOutput.getStdout(); + String stderr = javaVersionOutput.getStderr(); + Log.info(c, "before", "java -version stdout: " + stdout); + Log.info(c, "before", "java -version stderr: " + stderr); + assertEquals("Unexpected return code from java -version", 0, javaVersionOutput.getReturnCode()); + + if ((stdout != null && stdout.contains("IBM")) || (stderr != null && stderr.contains("IBM"))) { + isIBM_JVM = true; + } + } + + @AfterClass + public static void after() throws Exception { + // We stop the server by other means, but call stopServer in order to + // save logs, reset log offsets, etc. + server.stopServer(); + } + + /** + * Tests the command line tool: server javadump <serverName> + * Test will pass if the command executes successfully and (if using an + * IBM JVM) creates a file, "javacore*.txt", in the server root dir. + * Non-IBM JDKs do not produce javacores - and the javadump command + * does not usually return successfully on these platforms, so this test + * only runs on IBM JDKs. + */ + @Test + public void testJavadump() throws Exception { + assumeTrue(isIBM_JVM); + File[] filesBeforeDump = serverRoot.listFiles(); + Log.info(c, "testJavadump", "javadump"); + ProgramOutput output = server.javadumpThreads(); + assertEquals("Unexpected output code running javadump", 0, output.getReturnCode()); + + assertNotNull("Did not see expected CWWKE0068I in logs", server.waitForStringInLog("CWWKE0068I.*javacore")); + + File[] filesAfterDump = serverRoot.listFiles(); + assertTrue("Did not find expected additional files in serverRoot: " + serverRoot.getAbsolutePath(), + filesBeforeDump.length < filesAfterDump.length); + boolean foundJavacoreFile = false; + for (File f : filesAfterDump) { + String fileName = f.getName(); + Log.info(c, "testJavadump", "Found file: " + fileName); + if (fileName.startsWith("javacore") && fileName.endsWith(".txt")) { + foundJavacoreFile = true; + break; + } + } + assertTrue("Expected javacore*.txt file not found in serverRoot: " + serverRoot.getAbsolutePath(), foundJavacoreFile); + + Log.info(c, "testJavadump", "exit success"); + } + + /** + * Tests the command line tool: server dump <serverName> --include=heap,system,thread + * Test will pass if the command executes successfully and creates a file, + * "dump.<serverName>.dump*.zip", in the server root dir. Non-IBM JDKs do not produce + * artifacts like javacores, heap dumps, system cores in the same way as IBM JDKs - and the + * dump command does not usually return successfully on these platforms, so this test + * only runs on IBM JDKs. + */ + @Test + public void testDump() throws Exception { + assumeTrue(isIBM_JVM); + File[] filesBeforeDump = serverRoot.listFiles(); + Log.info(c, "testDump", "dump"); + ProgramOutput output = server.serverDump("heap,system,thread"); + + assertEquals("Unexpected output code running dump", 0, output.getReturnCode()); + + assertNotNull("Did not find expected CWWKE0068I message for heap dump in logs", server.waitForStringInLog("CWWKE0068I.*phd")); //heap dump + if (server.getMachine().getOperatingSystem() == OperatingSystem.ZOS) { + assertNotNull("Did not find expected CWWKE0092I message for java system dump on zos in logs", server.waitForStringInLog("CWWKE0092I")); + } else { + assertNotNull("Did not find expected CWWKE0068I message for system core in logs", server.waitForStringInLog("CWWKE0068I.*dmp")); //system core + } + assertNotNull("Did not find expected CWWKE0068I message for javacore in logs", server.waitForStringInLog("CWWKE0068I.*javacore")); //javacore + + File[] filesAfterDump = serverRoot.listFiles(); + assertTrue("Did not find expected additional files in serverRoot: " + serverRoot.getAbsolutePath(), + filesBeforeDump.length < filesAfterDump.length); + String serverName = server.getServerName(); + boolean foundDumpZip = false; + for (File f : filesAfterDump) { + String fileName = f.getName(); + Log.info(c, "testDump", "Found file: " + fileName); + if (fileName.startsWith(serverName + ".dump") && fileName.endsWith(".zip")) { + foundDumpZip = true; + break; + } + } + assertTrue("Expected .dump*.zip file not found in serverRoot: " + serverRoot.getAbsolutePath(), foundDumpZip); + + Log.info(c, "testDump", "exit success"); + } +} diff --git a/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/commandline/PauseResumeCommandTest.java b/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/commandline/PauseResumeCommandTest.java new file mode 100644 index 00000000000..91b4572bc10 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/commandline/PauseResumeCommandTest.java @@ -0,0 +1,158 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2015 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.kernel.boot.commandline; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.ibm.websphere.simplicity.log.Log; + +import componenttest.topology.impl.LibertyServer; +import componenttest.topology.impl.LibertyServerFactory; + +/** + * + */ +public class PauseResumeCommandTest { + + private static final Class c = PauseResumeCommandTest.class; + + private static final String PAUSE_RESUME_SERVER_NAME = "com.ibm.ws.kernel.boot.pause.resume.fat"; + + private static final LibertyServer pauseResumeServer = LibertyServerFactory.getLibertyServer(PAUSE_RESUME_SERVER_NAME); + + @Before + public void setup() throws Exception { + pauseResumeServer.startServer(); + } + + @After + public void teardown() throws Exception { + pauseResumeServer.stopServer("CWWKE093*"); + } + + /** + * Tests the case where the "server pause" command is issued and no + * pauseable components exist + * + * @throws Exception + */ + @Test + public void testPauseNoPauseableComponents() throws Exception { + final String METHOD_NAME = "testPauseNoPauseableComponents"; + Log.entering(c, METHOD_NAME); + + String output = pauseResumeServer.executeServerScript("pause", null).getStdout(); + + assertTrue(output.contains("failed")); + assertNotNull(pauseResumeServer.waitForStringInLog("CWWKE0933W", 10000)); + + Log.exiting(c, METHOD_NAME); + } + + /** + * Tests the case where the "server resume" command is issued and no + * pauseable components exist + * + * @throws Exception + */ + @Test + public void testResumeNoPauseableComponents() throws Exception { + final String METHOD_NAME = "testResumeNoPauseableComponents"; + Log.entering(c, METHOD_NAME); + + String output = pauseResumeServer.executeServerScript("resume", null).getStdout(); + + assertTrue(output.contains("failed")); + assertNotNull(pauseResumeServer.waitForStringInLog("CWWKE0934W", 10000)); + + Log.exiting(c, METHOD_NAME); + } + + /** + * Tests the case where the "server pause" command is issued with an empty target list. + * + * @throws Exception + */ + @Test + public void testPauseEmptyTargetList() throws Exception { + final String METHOD_NAME = "testPauseEmptyTargetList"; + Log.entering(c, METHOD_NAME); + + String output = pauseResumeServer.executeServerScript("pause", new String[] { "--target=" }).getStdout(); + + assertTrue(output.contains("failed")); + assertNotNull(pauseResumeServer.waitForStringInLog("CWWKE0931W", 10000)); + + Log.exiting(c, METHOD_NAME); + } + + /** + * Tests the case where the "server resume" command is issued with an empty target list. + * + * @throws Exception + */ + @Test + public void testResumeEmptyTargetList() throws Exception { + final String METHOD_NAME = "testResumeEmptyTargetList"; + Log.entering(c, METHOD_NAME); + + String output = pauseResumeServer.executeServerScript("resume", new String[] { "--target=" }).getStdout(); + + assertTrue(output.contains("failed")); + assertNotNull(pauseResumeServer.waitForStringInLog("CWWKE0932W", 10000)); + + Log.exiting(c, METHOD_NAME); + } + + /** + * Tests the case where the "server resume" command is issued with an invalid target. + * + * @throws Exception + */ + @Test + public void testPauseInvalidTarget() throws Exception { + final String METHOD_NAME = "testPauseInvalidTarget"; + Log.entering(c, METHOD_NAME); + + String output = pauseResumeServer.executeServerScript("pause", new String[] { "--target=InvalidTarget" }).getStdout(); + + assertTrue(output.contains("failed")); + assertNotNull(pauseResumeServer.waitForStringInLog("CWWKE0935W", + 10000)); + + Log.exiting(c, METHOD_NAME); + } + + /** + * Tests the case where the "server resume" command is issued with an empty target list. + * + * @throws Exception + */ + @Test + public void testResumeInvalidTarget() throws Exception { + final String METHOD_NAME = "testResumeInvalidTarget"; + Log.entering(c, METHOD_NAME); + + String output = pauseResumeServer.executeServerScript("resume", new String[] { "--target=InvalidTarget" }).getStdout(); + + assertTrue(output.contains("failed")); + assertNotNull(pauseResumeServer.waitForStringInLog("CWWKE0936W", + 10000)); + + Log.exiting(c, METHOD_NAME); + } +} diff --git a/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/commandline/StartCommandTest.java b/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/commandline/StartCommandTest.java new file mode 100755 index 00000000000..5875ce63537 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/commandline/StartCommandTest.java @@ -0,0 +1,90 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2015 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.kernel.boot.commandline; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.ibm.websphere.simplicity.Machine; +import com.ibm.websphere.simplicity.ProgramOutput; +import componenttest.common.apiservices.Bootstrap; +import componenttest.topology.impl.LibertyFileManager; +import componenttest.topology.utils.LibertyServerUtils; + +/** + * + */ +public class StartCommandTest { + + private final static double javaLevel = Double.parseDouble(System.getProperty("java.specification.version")); + + private final static String defaultServerName = "defaultServer"; + private static Bootstrap bootstrap; + private static Machine machine; + private static String installPath; + private static String defaultServerPath; + + @BeforeClass + public static void setup() throws Exception { + bootstrap = Bootstrap.getInstance(); + machine = LibertyServerUtils.createMachine(bootstrap); + installPath = LibertyFileManager.getInstallPath(bootstrap); + defaultServerPath = installPath + "/usr/servers/" + defaultServerName; + } + + @Before + public void cleanupBeforeRun() throws Exception { + // since we are not using the normal LibertyServer class for this server, + // we need to make sure to explicitly clean up. We do this before running + // the test in order to preserve the contents on disk. + + if (LibertyFileManager.libertyFileExists(machine, defaultServerPath)) { + LibertyFileManager.deleteLibertyDirectoryAndContents(machine, defaultServerPath); + } + } + + /** + * Tests the case where the "server run" command is issued and defaultServer + * does not exist. In this case, defaultServer is created on the fly. + * + * @throws Exception + */ + @Test + public void testIsServerEnvCreatedForImplicitServerCreate() throws Exception { + + ProgramOutput po = LibertyServerUtils.executeLibertyCmd(bootstrap, "server", "start"); + assertEquals("Unexpected return code from server start command", 0, po.getReturnCode()); + + try { + // check that server directory was created + assertTrue("Expected server directory to exist at " + defaultServerPath + ", but does not", LibertyFileManager.libertyFileExists(machine, defaultServerPath)); + + // check that server.xml exists + String serverXmlPath = defaultServerPath + "/server.xml"; + assertTrue("Expected server.xml file to exist at " + serverXmlPath + ", but does not", LibertyFileManager.libertyFileExists(machine, serverXmlPath)); + + // if we are running in a JVM that is version 1.8 or higher, we also need to check for the server.env file + if (javaLevel >= 1.8) { + String serverEnvPath = defaultServerPath + "/server.env"; + assertTrue("Expected server.env file to exist at " + serverEnvPath + ", but does not", LibertyFileManager.libertyFileExists(machine, serverEnvPath)); + } + } finally { + po = LibertyServerUtils.executeLibertyCmd(bootstrap, "server", "stop"); + assertEquals("Unexpected return code from server stop command", 0, po.getReturnCode()); + } + + } +} diff --git a/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/commandport/ServerCommandPortTest.java b/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/commandport/ServerCommandPortTest.java new file mode 100755 index 00000000000..45d791dcc4d --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/commandport/ServerCommandPortTest.java @@ -0,0 +1,243 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.kernel.boot.commandport; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.BufferedReader; +import java.io.InputStreamReader; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestName; + +import com.ibm.websphere.simplicity.RemoteFile; +import com.ibm.websphere.simplicity.log.Log; + +import componenttest.topology.impl.LibertyServer; +import componenttest.topology.impl.LibertyServerFactory; +import componenttest.topology.utils.HttpUtils; + +/** + * This test bucket validates the functionality of the server command port, the port that is used by the server script + * to communicate with a running server, if required. + */ +public class ServerCommandPortTest { + private static final String COMMAND_PORT_DISABLED_SERVER_NAME = "com.ibm.ws.kernel.boot.commandport.disabled.fat"; + private static final String COMMAND_PORT_ENABLED_SERVER_NAME = "com.ibm.ws.kernel.boot.commandport.enabled.fat"; + + private static final LibertyServer commandPortDisabledServer = LibertyServerFactory.getLibertyServer(COMMAND_PORT_DISABLED_SERVER_NAME); + private static final LibertyServer commandPortEnabledServer = LibertyServerFactory.getLibertyServer(COMMAND_PORT_ENABLED_SERVER_NAME); + + private static final boolean isMac = System.getProperty("os.name", "unknown").toLowerCase().indexOf("mac os") >= 0; + + @Rule + public TestName testName = new TestName(); + + @Test + /** + * This test validates the functionality of a server with the command port disabled. The server script has + * only limited ability to administer a server with the command port disabled. + * + * @throws Exception + */ + public void testServerCommandPortDisabled() throws Exception { + LibertyServer server = commandPortDisabledServer; + + // server should start, but with a warning message that we can't actually tell if it completed starting + // because the command port is disabled + // + // NOTE: don't use "server.startServer()" because this causes the LibertyServer to remember that it is + // started and it will try to stop it during test cleanup, failing due to command port disablement + String output = server.executeServerScript("start", null).getStdout(); + + try { + // there are two messages for starting a server, one that contains a process ID and one that does not; + // either message indicates success of the start command for this purpose + assertTrue(output.contains("CWWKE0088W") || output.contains("CWWKE0087W")); + server.waitForStringInLog("CWWKF0011I"); + + // save the PID to validate the server status command - note that on Windows, the PID is not returned + // as part of the start message, so we can't always perform this verification + int serverPid = getServerPid(output); + + // server status should work as usual, since the command port is not needed for it + output = server.executeServerScript("status", null).getStdout(); + assertTrue(output.contains("Server " + server.getServerName() + " is running")); + + if (serverPid > 0) { + assertTrue(output.contains("with process ID " + serverPid)); + } + + // ensure that the command port in the .sCommand file is -1 + assertEquals(-1, getCommandPort(server)); + + // generating a java dump should produce an error saying that the dump can't be taken due to command + // port disablement + output = server.executeServerScript("javadump", null).getStdout(); + assertTrue(output.contains("CWWKE0091E")); + + // generating a server dump should produce a warning saying that the dump was taken, but that some + // information is missing + output = server.executeServerScript("dump", null).getStdout(); + assertTrue(output.contains("CWWKE0090W")); + validateDumpFile(output, server, COMMAND_PORT_DISABLED_SERVER_NAME); + + // stopping the server should produce an error + output = server.executeServerScript("stop", null).getStdout(); + assertTrue(output.contains("CWWKE0089E")); + } finally { + Log.info(ServerCommandPortTest.class, "testServerCommandPortDisabled", + "Stop the server via a servlet since the command port is disabled."); + try { + // make sure the shutdown app is available before using it to shutdown the server + server.validateAppLoaded("shutdownfat"); + + HttpUtils.findStringInUrl(server, "/shutdownfat", "exit="); + } catch (Throwable t) { + Log.error(ServerCommandPortTest.class, "testServerCommandPortDisabled", t); + } + server.waitForStringInLog("CWWKE0036I"); + + // make sure logs are collected (not stopping the normal way...no command port) + server.postStopServerArchive(); + } + } + + @Test + /** + * This test validates the functionality of a server with the command port enabled. + * + * @throws Exception + */ + public void testServerCommandPortEnabled() throws Exception { + LibertyServer server = commandPortEnabledServer; + + String output = server.startServer().getStdout(); + assertTrue(output.contains("Server " + server.getServerName() + " started")); + + // save the PID to validate the server status command - note that on Windows, the PID is not returned + // as part of the start message, so we can't always perform this verification + int serverPid = getServerPid(output); + + // validate server status command + output = server.executeServerScript("status", null).getStdout(); + assertTrue(output.contains("Server " + server.getServerName() + " is running")); + + if (serverPid > 0) { + assertTrue(output.contains("with process ID " + serverPid)); + } + + // ensure that the command port in the .sCommand file is greater than 0 + assertTrue(getCommandPort(server) > 0); + + // validate server javadump command on all platforms except mac, because javadump + // is unreliable on hotspot jvms + if (!isMac) { + output = server.executeServerScript("javadump", null).getStdout(); + assertTrue(output.contains("Server " + server.getServerName() + " dump complete in")); + validateDumpFile(output, server, COMMAND_PORT_ENABLED_SERVER_NAME); + } + + // validate server dump command + output = server.executeServerScript("dump", null).getStdout(); + assertTrue(output.contains("Server " + server.getServerName() + " dump complete in")); + validateDumpFile(output, server, COMMAND_PORT_ENABLED_SERVER_NAME); + + // validate server stop command + output = server.stopServer().getStdout(); + assertTrue(output.contains("Server " + server.getServerName() + " stopped.")); + + // make sure server really stopped + output = server.executeServerScript("status", null).getStdout(); + assertTrue(output.contains("Server " + server.getServerName() + " is not running.")); + } + + /** + * Validates the existence of a dump file. The dump file name is parsed from the input parameter, + * which is the output of the server script command that requested the dump. + * + * @param outputMessage the output of the server script command that requested the dump + */ + private void validateDumpFile(String outputMessage, LibertyServer server, final String serverName) throws Exception { + String dumpFileName = null; + + // The format of the dump complete message is: + // Server dump complete in . + // The filename comes after "in" and has a period attached. + boolean foundServerName = false; + String[] words = outputMessage.split("\\s+"); + for (int i = 0; i < words.length; i++) { + // we are checking for the message header here to avoid a Mac JDK bug + // that prints a message that includes the word "in" but then causes a + // StringIndexOutOfBoundsException below. This check could be removed + // when the Mac bug is fixed, but it doesn't hurt to leave it in. + // See defects 124026 and 123011 for more details. + if (i > 0 && words[i - 1].equals("Server") && words[i].equals(serverName)) { + foundServerName = true; + } else if (words[i].equals("in") && foundServerName && i < (words.length - 1)) { + dumpFileName = words[i + 1]; + + int serverRootLength = server.getServerRoot().length(); + int periodIndex = dumpFileName.length() - 1; + + // strip the server root off the front and the period off the end + dumpFileName = dumpFileName.substring(serverRootLength, periodIndex); + break; + } + } + + // verify that the server dump file exists and that *something* is inside it + RemoteFile dumpFile = server.getFileFromLibertyServerRoot(dumpFileName); + assertTrue(dumpFile.exists()); + assertTrue(dumpFile.length() > 0); + } + + /** + * Parses and returns the server PID from the output of the server start command. + * + * @param outputMessage the output of the server start command + * @return the server's PID, or -1 if the PID cannot be parsed from the command output + */ + private int getServerPid(String outputMessage) throws Exception { + // The format of the server started message is: + // Server started with process ID . + // The PID comes after "ID" and has a period or comma attached. + String[] words = outputMessage.split("\\s+"); + for (int i = 0; i < words.length; i++) { + if (words[i].equals("ID")) { + String pidString = words[i + 1]; + pidString = pidString.substring(0, pidString.length() - 2); // strip trailing period + return Integer.parseInt(pidString); + } + } + return -1; + } + + /** + * Gets the current command port for the specified server. Note that this is + * NOT something that is visible to the customer. This is a test of our own + * internals added as a secondary verification that command port enablement + * and disablement works. + * + * @param server the server to get the command port for + * @return the server's command port + */ + private int getCommandPort(LibertyServer server) throws Exception { + RemoteFile commandFile = server.getFileFromLibertyServerRoot("workarea/.sCommand"); + BufferedReader reader = new BufferedReader(new InputStreamReader(commandFile.openForReading())); + String line = reader.readLine(); + reader.close(); + return Integer.parseInt(line.split(":")[1]); + } +} diff --git a/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/internal/commands/LogLevelPropertyTest.java b/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/internal/commands/LogLevelPropertyTest.java new file mode 100755 index 00000000000..71982771499 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/internal/commands/LogLevelPropertyTest.java @@ -0,0 +1,122 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2014 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.kernel.boot.internal.commands; + +import static org.junit.Assert.assertEquals; + +import java.io.File; +import java.util.Locale; +import java.util.Map; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.ibm.websphere.simplicity.Machine; +import com.ibm.websphere.simplicity.ProgramOutput; +import com.ibm.websphere.simplicity.log.Log; +import componenttest.topology.impl.LibertyServer; +import componenttest.topology.impl.LibertyServerFactory; + +public class LogLevelPropertyTest { + + private static LibertyServer server; + private static boolean isMac; + private static boolean isZos; + + @BeforeClass + public static void before() throws Exception { + server = LibertyServerFactory.getLibertyServer("com.ibm.ws.kernel.bootstrap.output.fat"); + + String osName = System.getProperty("os.name", "unknown").toLowerCase(Locale.ROOT); + + Map options = server.getJvmOptionsAsMap(); + String maxPermSize = "-XX:MaxPermSize"; + if (options.containsKey(maxPermSize)) { + options.remove(maxPermSize); + } + + // Temporary debug for 130858. + isZos = osName.contains("z/os"); + if (isZos) { + String option = "-Xtrace:output=shared_classes.trc,maximal={j9shr}"; + Log.info(LogLevelPropertyTest.class, "before", "Adding " + option + " for z/OS"); + options.put(option, null); + + } + + server.setJvmOptions(options); + + server.startServer(); + + isMac = osName.indexOf("mac os") >= 0; + } + + @Test + public void testLogLevelPropertyDisabled() throws Exception { + try { + if (isMac) { + // There might (with Java7 on some versions of the OS) be garbage in console.log that is + // printed by the JVM (we have no control over it). It looks something like this: + // objc[25086]: Class JavaLaunchHelper is implemented in both /.../jre/bin/java and /.../jre/lib/libinstrument.dylib. One of the two will be used. Which one is undefined. + // only test for the empty console log if that message isn't present + if (server.waitForStringInLog("objc.*", 0, server.getConsoleLogFile()) == null) { + assertEquals("Console log file was not empty.", 0, server.getConsoleLogFile().length()); + } + } else if (server.isJavaVersion8() && server.isOracleJVM()) { + // On Oracle JDK 8, the JVM will complain about the MaxPermSize option + if (server.waitForStringInLog(".*support was removed in 8.0", 0, server.getConsoleLogFile()) == null) { + assertEquals("Console log file was not empty.", 0, server.getConsoleLogFile().length()); + } + } else { + assertEquals("Console log file was not empty.", 0, server.getConsoleLogFile().length()); + } + } finally { + // Temporary debug for 130858. + if (isZos) { + final Class c = LogLevelPropertyTest.class; + final String m = "testLogLevelPropertyDisabled"; + + Machine machine = server.getMachine(); + ProgramOutput output = machine.execute("ls", + new String[] { + "-l", + new File(server.getUserDir(), "servers/.classCache").getAbsolutePath(), + new File(server.getUserDir(), "servers/.classCache/javasharedresources").getAbsolutePath() }); + Log.info(c, m, "ls -l diagnostic return code: " + output.getReturnCode()); + Log.info(c, m, "ls -l diagnostic stdout: " + output.getStdout()); + Log.info(c, m, "ls -l diagnostic stderr: " + output.getStderr()); + + output = machine.execute("ipcs"); + Log.info(c, m, "icps diagnostic return code: " + output.getReturnCode()); + Log.info(c, m, "icps diagnostic stdout: " + output.getStdout()); + Log.info(c, m, "icps diagnostic stderr: " + output.getStderr()); + + output = machine.execute(new File(server.getMachineJavaJDK(), "../bin/jar").getAbsolutePath(), + new String[] { + "cfM", + // Weird extension to avoid filtering. + new File(server.getServerRoot(), "scControlFiles.zip.diag").getAbsolutePath(), + new File(server.getUserDir(), "servers/.classCache").getAbsolutePath() + }); + Log.info(c, m, "jar cf diagnostic return code: " + output.getReturnCode()); + Log.info(c, m, "jar cf diagnostic stdout: " + output.getStdout()); + Log.info(c, m, "jar cf diagnostic stderr: " + output.getStderr()); + } + } + } + + @AfterClass + public static void after() throws Exception { + server.stopServer(); + } +} \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/internal/commands/PackageCommandTest.java b/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/internal/commands/PackageCommandTest.java new file mode 100755 index 00000000000..077146d6e79 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/boot/internal/commands/PackageCommandTest.java @@ -0,0 +1,171 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2014 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.kernel.boot.internal.commands; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assume.assumeTrue; + +import java.io.FileNotFoundException; +import java.util.Enumeration; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.jar.Manifest; + +import org.junit.Test; + +import componenttest.topology.impl.LibertyServer; +import componenttest.topology.impl.LibertyServerFactory; + +/** + * + */ +public class PackageCommandTest { + + /** + * The package command requires that the lib/extract directory exists, as this directory + * contains a required manifest, self extractable classes, etc. If this directory does + * not exist, then the command should print this message: + *
+ * CWWKE0922E: The package command cannot complete because the installation is missing the lib/extract directory. + *
+ * This test verifies that this error message is printed. + *
+ * Note: This test assumes that the lib/extract directory is already missing. As of today, the + * FAT environment's installation of WLP does not include this directory. If we end up creating that + * directory in the FAT environment, then we'll need to find another way to run this test - as we + * probably don't want to delete a directory in the FAT environment's installation. + * + * @throws Exception + */ + @Test + public void testCorrectErrorMessageWhenLibExtractDirIsMissing() throws Exception { + // Pick any server, doesn't matter. + LibertyServer server = LibertyServerFactory.getLibertyServer("com.ibm.ws.kernel.bootstrap.fat"); + // Only run the test if the lib/extract directory does not exist + try { + server.getFileFromLibertyInstallRoot("lib/extract"); + assumeTrue(false); // the directory exists, so we skip this test. + } catch (FileNotFoundException ex) { + //expected - the directory does not exist - so proceed. + } + + String stdout = server.executeServerScript("package", new String[] { "--include=minify" }).getStdout(); + + assertTrue("Did not find expected failure message, CWWKE0922E", stdout.contains("CWWKE0922E")); + } + + /** + * Packages --include=minify,runnable jar and verifies correct content. + * This test is not run if: + * 1) platform is z/OS (jar archive not supported) + * 2) wlp/lib/extract directory does not exist + * + * @throws Exception + */ + @Test + public void testCreateRunnableJar() throws Exception { + // Pick any server, doesn't matter. + String serverName = "com.ibm.ws.kernel.bootstrap.fat"; + String jarFileName = serverName + ".jar"; + String mainClass = "wlp.lib.extract.SelfExtractRun"; + + // Doesn't work on z/OS (because you can't package into a jar on z/OS) + assumeTrue(!System.getProperty("os.name").equals("z/OS")); + + LibertyServer server = LibertyServerFactory.getLibertyServer(serverName); + + // Only run the test if the lib/extract directory exists + try { + server.getFileFromLibertyInstallRoot("lib/extract"); + + String stdout = server.executeServerScript("package", new String[] { "--archive=" + jarFileName, "--include=runnable" }).getStdout(); + + assertTrue("Could not package server " + serverName, stdout.contains("Server " + serverName + " package complete")); + + JarFile jarFile = new JarFile(server.getFileFromLibertyServerRoot(jarFileName).getAbsolutePath()); + + // Check the manifest for headers that should be in there. + Manifest mf = jarFile.getManifest(); + assertNotNull("There should be a manifest in the jar file", mf); + + // make sure it'a a runnable jar + assertEquals(mainClass, mf.getMainAttributes().getValue("Main-Class")); + + // Check that the self-extract and the server's entries are in the jar + Enumeration entries = jarFile.entries(); + assertTrue(entries.hasMoreElements()); + + boolean foundSelfExtractRun = false; + while (entries.hasMoreElements()) { + JarEntry entry = entries.nextElement(); + foundSelfExtractRun |= entry.getName().startsWith("wlp/lib/extract/SelfExtractRun.class"); + } + + assertTrue(foundSelfExtractRun); + + } catch (FileNotFoundException ex) { + assumeTrue(false); // the directory does not exist, so we skip this test. + } + } + + /** + * Make sure that when packaging a jar archive using --include=usr, + * the resulting jar files does NOT contain the self-extract files. + */ + @Test + public void testPackageJarArchiveWithIncludeEqualsUsr() throws Exception { + + // NOTE: This test won't work cuz the necessary MANIFEST files and + // self-extract files (wlp/lib/extract/*) aren't present in our test environment. + assumeTrue(false); + + // Doesn't work on z/OS (cuz you can't package into a jar on z/OS) + assumeTrue(!System.getProperty("os.name").equals("z/OS")); + + // Pick any server, doesn't matter. + LibertyServer server = LibertyServerFactory.getLibertyServer("com.ibm.ws.kernel.bootstrap.fat"); + + String jarFileName = "package.usr.jar"; + + String stdout = server.executeServerScript("package", + new String[] { "--archive=" + jarFileName, + "--include=usr" }).getStdout(); + + JarFile jarFile = new JarFile(server.getFileFromLibertyServerRoot(jarFileName).getAbsolutePath()); + + // Check the manifest for headers that should be in there. + Manifest mf = jarFile.getManifest(); + assertNotNull("There should be a manifest in the jar file", mf); + + assertTrue(mf.getMainAttributes().containsKey("Applies-To")); + assertEquals("com.ibm.websphere.appserver", mf.getMainAttributes().getValue("Applies-To")); + assertEquals("false", mf.getMainAttributes().getValue("Extract-Installer")); + + // Check that the self-extract and the server's entries are in the jar + Enumeration entries = jarFile.entries(); + assertTrue(entries.hasMoreElements()); + + boolean foundServerEntry = false; + boolean foundSelfExtractEntry = false; + while (entries.hasMoreElements()) { + JarEntry entry = entries.nextElement(); + foundServerEntry |= entry.getName().startsWith("wlp/usr/servers/com.ibm.ws.kernel.bootstrap.fat"); + foundSelfExtractEntry |= entry.getName().startsWith("wlp/lib/extract"); + } + + assertTrue(foundServerEntry); + assertTrue(foundSelfExtractEntry); + } + +} diff --git a/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/provisioning/KernelChangeTest.java b/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/provisioning/KernelChangeTest.java new file mode 100755 index 00000000000..3d5e1681e01 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/provisioning/KernelChangeTest.java @@ -0,0 +1,80 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.kernel.provisioning; + +import static org.junit.Assert.assertTrue; + +import java.util.List; + +import org.junit.After; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestName; + +import componenttest.topology.impl.LibertyServer; +import componenttest.topology.impl.LibertyServerFactory; + +/** + * + */ +public class KernelChangeTest { + private static LibertyServer server = LibertyServerFactory.getLibertyServer("com.ibm.ws.kernel.bootstrap.fat"); + + @Rule + public TestName testName = new TestName(); + + @After + public void tearDown() throws Exception { + server.stopServer(); + } + + @Test + public void testKernelChangeRestart() throws Exception { + // Start the server (wait for server started message) + server.startServer("part1.console.log"); + + // Make sure no error messages in console.log + List output = server.findStringsInLogs("ERROR.*", server.getConsoleLogFile()); + assertTrue("We should not see error messages in the log. output=" + output, output.isEmpty()); + + // Stop the server (WARM) + server.stopServer(false); + + // Save logs, switch bootstrap.properties files to enable hpel + server.renameLibertyServerRootFile("logs/messages.log", "logs/part1.messages.log"); + server.renameLibertyServerRootFile("logs/trace.log", "logs/part1.trace.log"); + server.renameLibertyServerRootFile("bootstrap.properties", "bootstrap.properties.orig"); + server.renameLibertyServerRootFile("bootstrap.properties.hpel", "bootstrap.properties"); + + // Start the server with HPEL (WARM) + server.startServer("part2.console.log", false, false); + + // Make sure no error messages in console.log + output = server.findStringsInLogs("ERROR.*", server.getConsoleLogFile()); + assertTrue("We should not see error messages in the log. output=" + output, output.isEmpty()); + + // Stop the server (WARM) + server.stopServer(false); + + // Save logs, switch back to disable hpel again + server.renameLibertyServerRootFile("bootstrap.properties", "bootstrap.properties.hpel"); + server.renameLibertyServerRootFile("bootstrap.properties.orig", "bootstrap.properties"); + + // Start the server WITHOUT HPEL again + server.startServer("part3.console.log", false, false); + + // Make sure no error messages in console.log + output = server.findStringsInLogs("ERROR.*", server.getConsoleLogFile()); + assertTrue("We should not see error messages in the log. output=" + output, output.isEmpty()); + } + +} diff --git a/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/provisioning/ProvisioningTest.java b/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/provisioning/ProvisioningTest.java new file mode 100755 index 00000000000..75d8307fbc9 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/ws/kernel/provisioning/ProvisioningTest.java @@ -0,0 +1,700 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012, 2014 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.kernel.provisioning; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.List; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestName; + +import com.ibm.websphere.simplicity.log.Log; +import componenttest.topology.impl.LibertyFileManager; +import componenttest.topology.impl.LibertyServer; +import componenttest.topology.impl.LibertyServerFactory; + +public class ProvisioningTest { + + private static final Class c = ProvisioningTest.class; + private static LibertyServer server = LibertyServerFactory.getLibertyServer("com.ibm.ws.kernel.provisioning.fat"); + + private static final String BUNDLE_NAME = "ProvisioningTestBundle"; + private static final String INTERIM_FIX_BUNDLE_NAME = "ProvisioningInterimFixesTestBundle"; + private static final String FEATURE_MF = "provisioningTest-1.0.mf"; + private static final String FIX_DATA = "workarea/platform/fix.data"; + private static final String V100 = "1.0.0"; + private static final String V101 = "1.0.1"; + private static final String V102 = "1.0.2"; + private static final String V1099 = "1.0.99"; + private static final String V10100 = "1.0.100"; + private static final String V101APAR1 = "1.0.1.201202020001-APAR0001"; + private static final String V101APAR2 = "1.0.1.201203030001-APAR0002"; + private static final String V101TEST = "1.0.1.201204040001-TestAPAR0001"; + private static final String V102APAR1 = "1.0.2.201201010001-APAR0001"; + + private static final String INTERIM_FIX_FEATURE = "provisioningInterimFixTest-1.0.mf"; + private static final String INTERIM_FIXES_FEATURE = "provisioningInterimFixesTest-1.0.mf"; + + private static String getBundleAndVersionName(String bundleVersion) { + return BUNDLE_NAME + "_" + bundleVersion; + } + + private static String getJarName(String bundleVersion) { + return BUNDLE_NAME + "_" + bundleVersion + ".jar"; + } + + private static String getRegularExpression(String bundleVersion) { + // see com.ibm.ws.kernel.provisioning.Activator.start method. + return "com.ibm.ws.kernel.provisioning.Activator.start bundle name = \\[" + BUNDLE_NAME + "\\], bundle version = \\[" + bundleVersion + "\\]"; + } + + private static void deleteTestBundleJars() throws Exception { + final String METHOD_NAME = "deleteTestBundleJars"; + + List filenames; + filenames = server.listLibertyInstallRoot("lib", BUNDLE_NAME); + Log.info(c, METHOD_NAME, "found " + filenames.size() + " bundle jars to delete."); + for (String filename : filenames) { + server.deleteFileFromLibertyInstallRoot("lib/" + filename); + } + filenames = server.listLibertyInstallRoot("lib", BUNDLE_NAME); + Log.info(c, METHOD_NAME, "found " + filenames.size() + " bundle jars after delete."); + + filenames = server.listLibertyInstallRoot("lib", INTERIM_FIX_BUNDLE_NAME); + Log.info(c, METHOD_NAME, "found " + filenames.size() + " bundle jars to delete."); + for (String filename : filenames) { + server.deleteFileFromLibertyInstallRoot("lib/" + filename); + } + filenames = server.listLibertyInstallRoot("lib", INTERIM_FIX_BUNDLE_NAME); + Log.info(c, METHOD_NAME, "found " + filenames.size() + " bundle jars after delete."); + } + + /* + * Delete any test bundle jars from the server's lib directory. There should be none + * present as they are removed after each test, but just in case there was abnormal + * termination of a test run we check before running the first test. We also add the + * feature that we're testing to the servers feature dir. + */ + @BeforeClass + public static void classSetUp() throws Exception { + final String METHOD_NAME = "classSetUp"; + + Log.entering(c, METHOD_NAME); + + if (server.isStarted()) { + server.stopServer(); + } + deleteTestBundleJars(); + server.copyFileToLibertyInstallRoot("lib/features", FEATURE_MF); + server.copyFileToLibertyInstallRoot("lib/features", INTERIM_FIX_FEATURE); + server.copyFileToLibertyInstallRoot("lib/features", INTERIM_FIXES_FEATURE); + server.saveServerConfiguration(); + + Log.exiting(c, METHOD_NAME); + } + + /* + * The test feature manifest file is copied into the server's lib/features directory by + * the test framework. After each test method we remove the corresponding bundle jar + * files, so the next test can install the bundle jars it needs without those from + * previous test methods interfering. This method deletes the feature manifest file after + * the last test so the final state of the server is that both the test feature manifest + * and the test bundle jars are removed (i.e. no artifacts from this test class remain in + * the server). + */ + @AfterClass + public static void classTearDown() throws Exception { + final String METHOD_NAME = "classTearDown"; + + Log.entering(c, METHOD_NAME); + + if (server.isStarted()) { + server.stopServer(); + } + if (server.fileExistsInLibertyInstallRoot("lib/features/" + FEATURE_MF)) { + Log.info(c, METHOD_NAME, "lib/features/" + FEATURE_MF + " will be deleted."); + server.deleteFileFromLibertyInstallRoot("lib/features/" + FEATURE_MF); + } + + if (server.fileExistsInLibertyInstallRoot("lib/features/" + INTERIM_FIX_FEATURE)) { + Log.info(c, METHOD_NAME, "lib/features/" + INTERIM_FIX_FEATURE + " will be deleted."); + server.deleteFileFromLibertyInstallRoot("lib/features/" + INTERIM_FIX_FEATURE); + } + + if (server.fileExistsInLibertyInstallRoot("lib/features/" + INTERIM_FIXES_FEATURE)) { + Log.info(c, METHOD_NAME, "lib/features/" + INTERIM_FIXES_FEATURE + " will be deleted."); + server.deleteFileFromLibertyInstallRoot("lib/features/" + INTERIM_FIXES_FEATURE); + } + + Log.exiting(c, METHOD_NAME); + } + + @After + public void tearDown() throws Exception { + final String METHOD_NAME = "tearDown"; + + Log.entering(c, METHOD_NAME); + + if (server.isStarted()) { + server.stopServer(); + } + + server.restoreServerConfiguration(); + + deleteTestBundleJars(); + + Log.exiting(c, METHOD_NAME); + } + + /** + * TestDescription: + * This test ensures that when a number of interim fixes are installed, and displayed in the logs, that the output + * doesn't contain duplicate APAR entries. + */ + @Test + public void testSingleInterimFixOutput() throws Exception { + final String METHOD_NAME = "testSingleInterimFixOutput"; + + Log.entering(c, METHOD_NAME); + + server.copyFileToLibertyInstallRoot("lib", "ProvisioningInterimFixesTestBundle4_1.0.0.jar"); + server.copyFileToLibertyInstallRoot("lib", "ProvisioningInterimFixesTestBundle4_1.0.0.20130101.jar"); + server.setServerConfigurationFile("singleInterimFixServer.xml"); + server.startServer(); + + String msgId = "CWWKF0015I"; + String interimFixesMsg = server.waitForStringInLog(msgId); + assertNotNull("There should be CWWKF0015I messages in the log", interimFixesMsg); + + assertTrue("APAR0007 is not listed as in the InterimFixes list: " + interimFixesMsg, interimFixesMsg.contains("APAR0007")); + int APAR0007Pos = interimFixesMsg.indexOf("APAR0007"); + assertTrue("There are duplicated APAR0007 entries in the InterimFixes list: " + interimFixesMsg, interimFixesMsg.indexOf("APAR0007", APAR0007Pos + 1) == -1); + + Log.exiting(c, METHOD_NAME); + } + + /** + * TestDescription: + * This test ensures that when a number of interim fixes are installed, and displayed in the logs, that the output + * doesn't contain duplicate APAR entries. + */ + @Test + public void testInterimFixesOutput() throws Exception { + final String METHOD_NAME = "testInterimFixesOutput"; + + Log.entering(c, METHOD_NAME); + + server.copyFileToLibertyInstallRoot("lib", "ProvisioningInterimFixesTestBundle1_1.0.0.jar"); + server.copyFileToLibertyInstallRoot("lib", "ProvisioningInterimFixesTestBundle1_1.0.0.20130101.jar"); + server.copyFileToLibertyInstallRoot("lib", "ProvisioningInterimFixesTestBundle2_1.0.0.jar"); + server.copyFileToLibertyInstallRoot("lib", "ProvisioningInterimFixesTestBundle2_1.0.0.20130101.jar"); + server.copyFileToLibertyInstallRoot("lib", "ProvisioningInterimFixesTestBundle3_1.0.0.jar"); + server.copyFileToLibertyInstallRoot("lib", "ProvisioningInterimFixesTestBundle3_1.0.0.20130101.jar"); + server.copyFileToLibertyInstallRoot("lib", "ProvisioningInterimFixesTestBundle4_1.0.0.jar"); + server.copyFileToLibertyInstallRoot("lib", "ProvisioningInterimFixesTestBundle4_1.0.0.20130101.jar"); + server.setServerConfigurationFile("interimFixesServer.xml"); + server.startServer(); + + String msgId = "CWWKF0015I"; + String interimFixesMsg = server.waitForStringInLog(msgId); + assertNotNull("There should be CWWKF0015I messages in the log", interimFixesMsg); + + assertTrue("APAR0005 is not listed as in the InterimFixes list: " + interimFixesMsg, interimFixesMsg.contains("APAR0005")); + int APAR0005Pos = interimFixesMsg.indexOf("APAR0005"); + assertTrue("There are duplicated APAR0005 entries in the InterimFixes list: " + interimFixesMsg, interimFixesMsg.indexOf("APAR0005", APAR0005Pos + 1) == -1); + + assertTrue("APAR0006 is not listed as in the InterimFixes list: " + interimFixesMsg, interimFixesMsg.contains("APAR0006")); + int APAR0006Pos = interimFixesMsg.indexOf("APAR0006"); + assertTrue("There are duplicated APAR0006 entries in the InterimFixes list: " + interimFixesMsg, interimFixesMsg.indexOf("APAR0006", APAR0006Pos + 1) == -1); + + assertTrue("APAR0007 is not listed as in the InterimFixes list: " + interimFixesMsg, interimFixesMsg.contains("APAR0007")); + int APAR0007Pos = interimFixesMsg.indexOf("APAR0007"); + assertTrue("There are duplicated APAR0007 entries in the InterimFixes list: " + interimFixesMsg, interimFixesMsg.indexOf("APAR0007", APAR0007Pos + 1) == -1); + + assertTrue("APAR0008 is not listed as in the InterimFixes list: " + interimFixesMsg, interimFixesMsg.contains("APAR0008")); + int APAR0008Pos = interimFixesMsg.indexOf("APAR0008"); + assertTrue("There are duplicated APAR0008 entries in the InterimFixes list: " + interimFixesMsg, interimFixesMsg.indexOf("APAR0008", APAR0008Pos + 1) == -1); + + // Now ensure that one of the APAR numbers that are prefixed with a space in the manifest header isn't also in the list. + assertFalse("APAR0008 is not listed as in the InterimFixes list: " + interimFixesMsg, interimFixesMsg.contains(" APAR0008")); + + Log.exiting(c, METHOD_NAME); + } + + /** + * TestDescription: + * This test ensures that the runtime can load a feature bundle. + */ + @Test + public void testBundleIsInstalled() throws Exception { + final String METHOD_NAME = "testBundleIsInstalled"; + + Log.entering(c, METHOD_NAME); + + String regex; + boolean found; + + server.copyFileToLibertyInstallRoot("lib", getJarName(V100)); + server.startServer(); + + regex = getRegularExpression(V100); + found = !server.findStringsInLogsAndTrace(regex).isEmpty(); + assertTrue(getBundleAndVersionName(V100) + " should have been started.", found); + + Log.exiting(c, METHOD_NAME); + } + + /** + * TestDescription: + * This test ensures that the runtime always loads the latest version of the bundle. In the test we have 2 bundles + * a different versions, and check that the newer one is loaded. We then stop the server, add another bundle, and + * ensure that this newest one is installed correctly. + */ + @Test + public void testLatestBundleVersionIsInstalled() throws Exception { + final String METHOD_NAME = "testLatestBundleVersionIsInstalled"; + + Log.entering(c, METHOD_NAME); + + String regex; + boolean found; + + server.copyFileToLibertyInstallRoot("lib", getJarName(V100)); + server.copyFileToLibertyInstallRoot("lib", getJarName(V101)); + server.startServer(); + + regex = getRegularExpression(V100); + found = !server.findStringsInLogsAndTrace(regex).isEmpty(); + assertTrue(getBundleAndVersionName(V100) + " should not have been started.", !found); + + regex = getRegularExpression(V101); + found = !server.findStringsInLogsAndTrace(regex).isEmpty(); + assertTrue(getBundleAndVersionName(V101) + " should have been started.", found); + + server.stopServer(); + server.copyFileToLibertyInstallRoot("lib", getJarName(V102)); + server.startServer(); + + regex = getRegularExpression(V102); + found = !server.findStringsInLogsAndTrace(regex).isEmpty(); + assertTrue(getBundleAndVersionName(V102) + " should have been started.", found); + + server.stopServer(); + + Log.exiting(c, METHOD_NAME); + } + + /** + * TestDescription: + * This test ensures that when an ifix that doesn't match any existing fixpack bundles is added to + * the server runtime dir, the ifix bundle will be ignored. + */ + @Test + public void testInvalidIFixIsIgnored1() throws Exception { + final String METHOD_NAME = "testInvalidIFixIsIgnored1"; + + Log.entering(c, METHOD_NAME); + + String regex; + boolean found; + + server.copyFileToLibertyInstallRoot("lib", getJarName(V100)); + server.copyFileToLibertyInstallRoot("lib", getJarName(V101APAR1)); + server.startServer(); + + regex = getRegularExpression(V101APAR1); + found = !server.findStringsInLogsAndTrace(regex).isEmpty(); + assertTrue(getBundleAndVersionName(V101APAR1) + " should not have been started.", !found); + + regex = getRegularExpression(V100); + found = !server.findStringsInLogsAndTrace(regex).isEmpty(); + assertTrue(getBundleAndVersionName(V100) + " should have been started.", found); + + server.stopServer(); + + Log.exiting(c, METHOD_NAME); + } + + /** + * TestDescription: + * This test ensures that when an ifix that doesn't match any existing fixpack bundles is added to + * the server runtime dir, the ifix bundle will be ignored, but if another valid ifix bundle is + * present, that that bundle is installed. + */ + @Test + public void testInvalidIFixIsIgnored2() throws Exception { + final String METHOD_NAME = "testInvalidIFixIsIgnored2"; + + Log.entering(c, METHOD_NAME); + + String regex; + boolean found; + + server.copyFileToLibertyInstallRoot("lib", getJarName(V101)); + server.copyFileToLibertyInstallRoot("lib", getJarName(V101APAR1)); + server.copyFileToLibertyInstallRoot("lib", getJarName(V102APAR1)); + server.startServer(); + + regex = getRegularExpression(V101); + found = !server.findStringsInLogsAndTrace(regex).isEmpty(); + assertTrue(getBundleAndVersionName(V101) + " should not have been started.", !found); + + regex = getRegularExpression(V102APAR1); + found = !server.findStringsInLogsAndTrace(regex).isEmpty(); + assertTrue(getBundleAndVersionName(V102APAR1) + " should not have been started.", !found); + + regex = getRegularExpression(V101APAR1); + found = !server.findStringsInLogsAndTrace(regex).isEmpty(); + assertTrue(getBundleAndVersionName(V101APAR1) + " should have been started.", found); + + server.stopServer(); + + Log.exiting(c, METHOD_NAME); + } + + /** + * TestDescription: + * This test ensures that when an ifix that matches an existing fixpack bundle is added to + * the server runtime dir, the ifix bundle will be installed. + */ + @Test + public void testValidIFixIsInstalled1() throws Exception { + final String METHOD_NAME = "testValidIFixIsInstalled1"; + + Log.entering(c, METHOD_NAME); + + String regex; + boolean found; + + server.copyFileToLibertyInstallRoot("lib", getJarName(V101)); + server.copyFileToLibertyInstallRoot("lib", getJarName(V101APAR1)); + server.startServer(); + + regex = getRegularExpression(V101); + found = !server.findStringsInLogsAndTrace(regex).isEmpty(); + assertTrue(getBundleAndVersionName(V101) + " should not have been started.", !found); + + regex = getRegularExpression(V101APAR1); + found = !server.findStringsInLogsAndTrace(regex).isEmpty(); + assertTrue(getBundleAndVersionName(V101APAR1) + " should have been started.", found); + + server.stopServer(); + + Log.exiting(c, METHOD_NAME); + } + + /** + * TestDescription: + * This test ensures that when an ifix that matches an existing fixpack bundle is added to + * the server runtime dir, the ifix bundle will be installed. + */ + @Test + public void testValidIFixIsInstalled2() throws Exception { + final String METHOD_NAME = "testValidIFixIsInstalled2"; + + Log.entering(c, METHOD_NAME); + + String regex; + boolean found; + + server.copyFileToLibertyInstallRoot("lib", getJarName(V101)); + server.startServer(); + + regex = getRegularExpression(V101); + found = !server.findStringsInLogsAndTrace(regex).isEmpty(); + assertTrue(getBundleAndVersionName(V101) + " should have been started.", found); + + server.stopServer(); + server.copyFileToLibertyInstallRoot("lib", getJarName(V101APAR1)); + server.startServer(); + + regex = getRegularExpression(V101); + found = !server.findStringsInLogsAndTrace(regex).isEmpty(); + assertTrue(getBundleAndVersionName(V101) + " should not have been started.", !found); + + regex = getRegularExpression(V101APAR1); + found = !server.findStringsInLogsAndTrace(regex).isEmpty(); + assertTrue(getBundleAndVersionName(V101APAR1) + " should have been started.", found); + + server.stopServer(); + + Log.exiting(c, METHOD_NAME); + } + + /** + * TestDescription: + * This test is testing that when an ifix is installed and the server is warm started, the ifix + * will be installed. + */ + @Test + public void testValidIFixIsInstalledWarmStart() throws Exception { + final String METHOD_NAME = "testValidIFixIsInstalledWarmStart"; + + Log.entering(c, METHOD_NAME); + + String regex; + boolean found; + + server.copyFileToLibertyInstallRoot("lib", getJarName(V101)); + server.startServer(); + + regex = getRegularExpression(V101); + found = !server.findStringsInLogsAndTrace(regex).isEmpty(); + assertTrue(getBundleAndVersionName(V101) + " should have been started.", found); + + server.stopServer(); + server.copyFileToLibertyInstallRoot("lib", getJarName(V101APAR1)); + server.startServer(false); + + // for V8.5, warm-start does not result in an update. + regex = getRegularExpression(V101); + found = !server.findStringsInLogsAndTrace(regex).isEmpty(); + assertTrue(getBundleAndVersionName(V101) + " should have been started.", found); + + server.stopServer(); + + Log.exiting(c, METHOD_NAME); + } + + /** + * TestDescription: + * This test ensures that a bundle for a newer release isn't installed into the runtime. + * New releases have a micro version which are incremental factors of 100. + */ + @Test + public void testNextReleaseBundleIsIgnored() throws Exception { + final String METHOD_NAME = "testNextReleaseBundleIsIgnored"; + + Log.entering(c, METHOD_NAME); + + String regex; + boolean found; + + server.copyFileToLibertyInstallRoot("lib", getJarName(V1099)); + server.copyFileToLibertyInstallRoot("lib", getJarName(V10100)); + server.startServer(); + + regex = getRegularExpression(V10100); + found = !server.findStringsInLogsAndTrace(regex).isEmpty(); + assertTrue(getBundleAndVersionName(V10100) + " should not have been started.", !found); + + regex = getRegularExpression(V1099); + found = !server.findStringsInLogsAndTrace(regex).isEmpty(); + assertTrue(getBundleAndVersionName(V1099) + " should have been started.", found); + + server.stopServer(); + + Log.exiting(c, METHOD_NAME); + } + + /** + * TestDescription: + * This test ensures that when a bundle has manifest headers of IBM-Test-Fixes and IBM-Interim-Fixes + * the contents are output to the server logs. + */ + @Test + public void testAPARManifestHeadersAreLogged() throws Exception { + final String METHOD_NAME = "testAPARManifestHeadersAreLogged"; + + Log.entering(c, METHOD_NAME); + + final String V101APAR1_IFIX_HEADER = ": APAR0001"; + final String V101TEST_TFIX_HEADER = ": TestAPAR0001"; + + String regex; + boolean found; + + server.copyFileToLibertyInstallRoot("lib", getJarName(V101)); + server.copyFileToLibertyInstallRoot("lib", getJarName(V101APAR1)); + server.startServer(); + + assertTrue(FIX_DATA + " file missing.", server.fileExistsInLibertyServerRoot(FIX_DATA)); + + found = !server.findStringsInFileInLibertyServerRoot(".*" + V101APAR1_IFIX_HEADER + ".*", FIX_DATA).isEmpty(); + assertTrue(V101APAR1 + " should have corresponding text \"" + V101APAR1_IFIX_HEADER + "\" in " + FIX_DATA, found); + + server.stopServer(); + server.copyFileToLibertyInstallRoot("lib", getJarName(V101TEST)); + server.startServer(); + + assertTrue(FIX_DATA + " file missing.", server.fileExistsInLibertyServerRoot(FIX_DATA)); + + regex = ".*" + V101APAR1_IFIX_HEADER + ".*"; + found = !server.findStringsInFileInLibertyServerRoot(regex, FIX_DATA).isEmpty(); + assertTrue(V101APAR1 + " should not have corresponding text \"" + V101APAR1_IFIX_HEADER + "\" in " + FIX_DATA, !found); + + regex = ".*" + V101TEST_TFIX_HEADER + ".*"; + found = !server.findStringsInFileInLibertyServerRoot(regex, FIX_DATA).isEmpty(); + assertTrue(V101TEST + " should have corresponding text \"" + V101TEST_TFIX_HEADER + "\" in " + FIX_DATA, found); + + server.stopServer(); + + Log.exiting(c, METHOD_NAME); + } + + /** + * TestDescription: + * This test ensures that when a new ifix is installed, it is installed rather than any older versions. + */ + @Test + public void testSupercedingIFixIsInstalled() throws Exception { + final String METHOD_NAME = "testSupercedingIFixIsInstalled"; + + Log.entering(c, METHOD_NAME); + + String regex; + boolean found; + + server.copyFileToLibertyInstallRoot("lib", getJarName(V101)); + server.copyFileToLibertyInstallRoot("lib", getJarName(V101APAR1)); + server.copyFileToLibertyInstallRoot("lib", getJarName(V101APAR2)); + server.startServer(); + + regex = getRegularExpression(V101); + found = !server.findStringsInLogsAndTrace(regex).isEmpty(); + assertTrue(getBundleAndVersionName(V101) + " should not have been started.", !found); + + regex = getRegularExpression(V101APAR1); + found = !server.findStringsInLogsAndTrace(regex).isEmpty(); + assertTrue(getBundleAndVersionName(V101APAR1) + " should not have been started.", !found); + + regex = getRegularExpression(V101APAR2); + found = !server.findStringsInLogsAndTrace(regex).isEmpty(); + assertTrue(getBundleAndVersionName(V101APAR2) + " should have been started.", found); + + server.stopServer(); + + Log.exiting(c, METHOD_NAME); + } + + private static final LibertyServer fpServer = LibertyServerFactory.getLibertyServer("com.ibm.ws.kernel.provisioning.fat.fingerprint"); + private final String fingerprintFileName = "service.fingerprint"; + private final String fingerprintLocation = "lib/versions"; + private final String fingerprintFileRelativePath = fingerprintLocation + "/" + fingerprintFileName; + private final String fingerprintFileAbsPath = fpServer.getInstallRoot() + fingerprintFileRelativePath; + private final String fingerprintFileAbsPathOld = fingerprintFileAbsPath + ".old"; + + private void mockApplyFix() throws Exception { + //backup the existing service fingerprint + LibertyFileManager.renameLibertyFile(fpServer.getMachine(), fingerprintFileAbsPath, fingerprintFileAbsPathOld); + //copy a mock fingerprint file + fpServer.copyFileToLibertyInstallRoot(fingerprintLocation, "service.fingerprint"); + } + + private void mockRemoveFix() throws Exception { + //remove the mock fingerprint file + fpServer.deleteFileFromLibertyInstallRoot(fingerprintFileRelativePath); + //restore the original service fingerprint + LibertyFileManager.renameLibertyFile(fpServer.getMachine(), fingerprintFileAbsPathOld, fingerprintFileAbsPath); + } + + @Rule + public TestName name = new TestName(); + + private void validateCleanStartWithFixAfterNStarts(int n) throws Exception { + try { + for (int i = 1; i <= n; i++) { + //perform a clean start the first time + fpServer.startServer(name.getMethodName() + "_prestart" + i + "_console.log", (i == 1) ? true : false); + //stop the server and apply the mock service + fpServer.stopServer(); + } + try { + mockApplyFix(); + //copy a marker file into the work area so we can see if it gets cleaned + fpServer.copyFileToLibertyServerRoot("workarea", "marker"); + //specify that we don't want a clean start from the test framework + //because we want it to happen automatically + fpServer.startServer(name.getMethodName() + "_console.log", false); + boolean markerExists = fpServer.fileExistsInLibertyServerRoot("workarea/marker"); + assertFalse("The workarea marker file existed when it should not have, the server did not automatically clean start when the server fingerprint changed after the server had been started " + + n + " times", + markerExists); + } finally { + mockRemoveFix(); + } + } finally { + //now stop and collect the logs + fpServer.stopServer(); + } + } + + /** + * APAR 117401: prove that the server gets clean started when service is applied + * For one previous server start + * + * @throws Exception + */ + @Test + public void testFixCausesCleanOnePreviousStart() throws Exception { + validateCleanStartWithFixAfterNStarts(1); + } + + /** + * APAR 117401: prove that the server gets clean started when service is applied + * For multiple previous server starts + * + * @throws Exception + */ + @Test + public void testFixCausesCleanMultiplePreviousStarts() throws Exception { + validateCleanStartWithFixAfterNStarts(3); + } + + /** + * APAR 117401: validate that the start is warm (not clean) when no service has been applied + * + * @throws Exception + */ + @Test + public void testServerDoesNotCleanStartIfNoFix() throws Exception { + try { + //initially clean start + fpServer.startServer(name.getMethodName() + "_clean_console.log", true); + //stop and collect logs + fpServer.stopServer(false); + //copy a marker file into the work area so we can see if it gets cleaned + fpServer.copyFileToLibertyServerRoot("workarea", "marker"); + //warm start the server + fpServer.startServer(name.getMethodName() + "_warm_console.log", false); + //assert the marker file is still there + boolean markerExists = fpServer.fileExistsInLibertyServerRoot("workarea/marker"); + assertTrue("The workarea marker file did not exist when it should have, the server clean started even though there was no fingerprint change", markerExists); + } finally { + //now stop and collect the logs + fpServer.stopServer(); + } + } + + /** + * Make sure that a server restart causes the server state directory to clear. + * + * @throws Exception + */ + @Test + public void testCleanStateDir() throws Exception { + try { + fpServer.copyFileToLibertyServerRoot("logs/state/", "marker"); + fpServer.startServer(); + assertFalse("The server marker should have been deleted from the state dir on server startup", fpServer.fileExistsInLibertyServerRoot("logs/state/marker")); + } finally { + fpServer.stopServer(); + } + } +} diff --git a/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/wsspi/kernel/embeddable/EmbeddedServerAddProductExtensionMultipleTest.java b/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/wsspi/kernel/embeddable/EmbeddedServerAddProductExtensionMultipleTest.java new file mode 100755 index 00000000000..f595552f237 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/wsspi/kernel/embeddable/EmbeddedServerAddProductExtensionMultipleTest.java @@ -0,0 +1,203 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2016 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.wsspi.kernel.embeddable; + +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.List; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; + +import com.ibm.websphere.simplicity.log.Log; + +import componenttest.topology.impl.LibertyServer; +import componenttest.topology.impl.LibertyServerFactory; +import junit.framework.AssertionFailedError; + +public class EmbeddedServerAddProductExtensionMultipleTest { + + static final Class c = EmbeddedServerAddProductExtensionMultipleTest.class; + + static LibertyServer ls = null; + static Object driver = null; + + static File wsServerBundle = null; + static File testServerClasses = null; + + static Class driverClazz = null; + + public String testName; + + static String serverName = "com.ibm.wsspi.kernel.embeddable.add.product.extension.multiple.fat"; + public static File outputAutoFVTDirectory; + + @Rule + public TestRule testInvoker = new TestRule() { + @Override + public Statement apply(final Statement stmt, final Description desc) { + return new Statement() { + @Override + public void evaluate() throws Throwable { + try { + testName = desc.getMethodName(); + embeddedServerTestHelper(testName); + stmt.evaluate(); + } finally { + testName = null; + } + } + }; + } + }; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + final String METHOD_NAME = "setUpBeforeClass"; + + // Save this off for the tearDown method to manually copy logs from /NonDefaultUser + // folder to /autoFVT/output/servers/ folder. + outputAutoFVTDirectory = new File("output/servers", serverName); + Log.info(c, METHOD_NAME, "outputAutoFVTDirectory: " + outputAutoFVTDirectory.getAbsolutePath()); + + // Find the necessary bundles in our install image + ls = LibertyServerFactory.getLibertyServer("com.ibm.wsspi.kernel.embeddable.add.product.extension.multiple.fat"); + testServerClasses = new File("build/classes"); + + wsServerBundle = new File(ls.getInstallRoot() + "/bin/tools/ws-server.jar"); + + String userDir = ls.getUserDir(); + String outputDir = userDir + "/servers"; + + Log.info(c, METHOD_NAME, "wsServerBundle: " + wsServerBundle.getAbsolutePath()); + Log.info(c, METHOD_NAME, "testServerClasses: " + testServerClasses.getAbsolutePath()); + + URLClassLoader classloader = new URLClassLoader(new URL[] { wsServerBundle.toURI().toURL(), + testServerClasses.toURI().toURL() }) { + // Borrowed from the bvt tests + @Override + protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException { + Class result = null; + + if (name == null || name.length() == 0) + return null; + + result = findLoadedClass(name); + + if (result == null && name != null) { + try { + // Try to load the class from the child classpath first... + result = findClass(name); + } catch (ClassNotFoundException cnfe) { + result = super.loadClass(name, resolve); + } + } + + return result; + } + }; + + driverClazz = classloader.loadClass("com.ibm.wsspi.kernel.embeddable.EmbeddedServerDriver"); + Constructor dCTOR = driverClazz.getConstructor(String.class, String.class, String.class); + driver = dCTOR.newInstance(serverName, userDir, outputDir); + } + + @AfterClass + public static void tearDown() throws Throwable { + final String METHOD_NAME = "tearDown"; + + // Manually copying server logs since they are in a non-default location + // and build script copy does not pick them up. + outputAutoFVTDirectory.mkdirs(); + Log.info(c, METHOD_NAME, "Copying directory from " + + ls.getUserDir() + "/servers/" + serverName + " to " + + outputAutoFVTDirectory.getAbsolutePath()); + + File srcDir = new File(ls.getUserDir() + "/servers/" + serverName); + copyDirectory(srcDir, outputAutoFVTDirectory.getAbsoluteFile()); + } + + @Test + public void testAddProductExtensionMultiple() throws Throwable {} + + private static void embeddedServerTestHelper(final String REMOTE_METHOD_NAME) throws Throwable { + final String METHOD_NAME = "embeddedServerTestHelper"; + Log.info(c, METHOD_NAME, "Preparing to run: " + REMOTE_METHOD_NAME); + + Method testMethod = driverClazz.getDeclaredMethod(REMOTE_METHOD_NAME); + + Method initMethod = driverClazz.getDeclaredMethod("init", new Class[] { String.class }); + + Method tearDownMethod = driverClazz.getDeclaredMethod("tearDown"); + + Method getFailuresMethod = driverClazz.getDeclaredMethod("getFailures"); + + try { + + initMethod.invoke(driver, new Object[] { REMOTE_METHOD_NAME }); + testMethod.invoke(driver); + tearDownMethod.invoke(driver); + + List failures = (List) getFailuresMethod.invoke(driver); + for (AssertionFailedError fail : failures) + Log.info(driverClazz, REMOTE_METHOD_NAME, fail.getMessage()); + + if (!failures.isEmpty()) + //add string buffer here to show failures in detail + assertTrue("Failures found " + failures, false); + } catch (InvocationTargetException t) { + throw t.getCause(); + } + } + + public static void copyDirectory(File source, File target) throws IOException { + if (source.isDirectory()) { + if (!target.exists()) { + target.mkdir(); + } + + String[] children = source.list(); + for (int i = 0; i < children.length; i++) { + copyDirectory(new File(source, children[i]), + new File(target, children[i])); + } + } else { + InputStream in = new FileInputStream(source); + OutputStream out = new FileOutputStream(target); + + byte[] buf = new byte[1024]; + int len; + while ((len = in.read(buf)) > 0) { + out.write(buf, 0, len); + } + in.close(); + out.close(); + } + } + +} diff --git a/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/wsspi/kernel/embeddable/EmbeddedServerAddProductExtensionTest.java b/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/wsspi/kernel/embeddable/EmbeddedServerAddProductExtensionTest.java new file mode 100755 index 00000000000..3566074f5fb --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/wsspi/kernel/embeddable/EmbeddedServerAddProductExtensionTest.java @@ -0,0 +1,203 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2016 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.wsspi.kernel.embeddable; + +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.List; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; + +import com.ibm.websphere.simplicity.log.Log; + +import componenttest.topology.impl.LibertyServer; +import componenttest.topology.impl.LibertyServerFactory; +import junit.framework.AssertionFailedError; + +public class EmbeddedServerAddProductExtensionTest { + + static final Class c = EmbeddedServerAddProductExtensionTest.class; + + static LibertyServer ls = null; + static Object driver = null; + + static File wsServerBundle = null; + static File testServerClasses = null; + + static Class driverClazz = null; + + public String testName; + + static String serverName = "com.ibm.wsspi.kernel.embeddable.add.product.extension.fat"; + public static File outputAutoFVTDirectory; + + @Rule + public TestRule testInvoker = new TestRule() { + @Override + public Statement apply(final Statement stmt, final Description desc) { + return new Statement() { + @Override + public void evaluate() throws Throwable { + try { + testName = desc.getMethodName(); + embeddedServerTestHelper(testName); + stmt.evaluate(); + } finally { + testName = null; + } + } + }; + } + }; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + final String METHOD_NAME = "setUpBeforeClass"; + + // Save this off for the tearDown method to manually copy logs from /NonDefaultUser + // folder to /autoFVT/output/servers/ folder. + outputAutoFVTDirectory = new File("output/servers", serverName); + Log.info(c, METHOD_NAME, "outputAutoFVTDirectory: " + outputAutoFVTDirectory.getAbsolutePath()); + + // Find the necessary bundles in our install image + ls = LibertyServerFactory.getLibertyServer("com.ibm.wsspi.kernel.embeddable.add.product.extension.fat"); + testServerClasses = new File("build/classes"); + + wsServerBundle = new File(ls.getInstallRoot() + "/bin/tools/ws-server.jar"); + + String userDir = ls.getUserDir(); + String outputDir = userDir + "/servers"; + + Log.info(c, METHOD_NAME, "wsServerBundle: " + wsServerBundle.getAbsolutePath()); + Log.info(c, METHOD_NAME, "testServerClasses: " + testServerClasses.getAbsolutePath()); + + URLClassLoader classloader = new URLClassLoader(new URL[] { wsServerBundle.toURI().toURL(), + testServerClasses.toURI().toURL() }) { + // Borrowed from the bvt tests + @Override + protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException { + Class result = null; + + if (name == null || name.length() == 0) + return null; + + result = findLoadedClass(name); + + if (result == null && name != null) { + try { + // Try to load the class from the child classpath first... + result = findClass(name); + } catch (ClassNotFoundException cnfe) { + result = super.loadClass(name, resolve); + } + } + + return result; + } + }; + + driverClazz = classloader.loadClass("com.ibm.wsspi.kernel.embeddable.EmbeddedServerDriver"); + Constructor dCTOR = driverClazz.getConstructor(String.class, String.class, String.class); + driver = dCTOR.newInstance(serverName, userDir, outputDir); + } + + @AfterClass + public static void tearDown() throws Throwable { + final String METHOD_NAME = "tearDown"; + + // Manually copying server logs since they are in a non-default location + // and build script copy does not pick them up. + outputAutoFVTDirectory.mkdirs(); + Log.info(c, METHOD_NAME, "Copying directory from " + + ls.getUserDir() + "/servers/" + serverName + " to " + + outputAutoFVTDirectory.getAbsolutePath()); + + File srcDir = new File(ls.getUserDir() + "/servers/" + serverName); + copyDirectory(srcDir, outputAutoFVTDirectory.getAbsoluteFile()); + } + + @Test + public void testAddProductExtension() throws Throwable {} + + private static void embeddedServerTestHelper(final String REMOTE_METHOD_NAME) throws Throwable { + final String METHOD_NAME = "embeddedServerTestHelper"; + Log.info(c, METHOD_NAME, "Preparing to run: " + REMOTE_METHOD_NAME); + + Method testMethod = driverClazz.getDeclaredMethod(REMOTE_METHOD_NAME); + + Method initMethod = driverClazz.getDeclaredMethod("init", new Class[] { String.class }); + + Method tearDownMethod = driverClazz.getDeclaredMethod("tearDown"); + + Method getFailuresMethod = driverClazz.getDeclaredMethod("getFailures"); + + try { + + initMethod.invoke(driver, new Object[] { REMOTE_METHOD_NAME }); + testMethod.invoke(driver); + tearDownMethod.invoke(driver); + + List failures = (List) getFailuresMethod.invoke(driver); + for (AssertionFailedError fail : failures) + Log.info(driverClazz, REMOTE_METHOD_NAME, fail.getMessage()); + + if (!failures.isEmpty()) + //add string buffer here to show failures in detail + assertTrue("Failures found " + failures, false); + } catch (InvocationTargetException t) { + throw t.getCause(); + } + } + + public static void copyDirectory(File source, File target) throws IOException { + if (source.isDirectory()) { + if (!target.exists()) { + target.mkdir(); + } + + String[] children = source.list(); + for (int i = 0; i < children.length; i++) { + copyDirectory(new File(source, children[i]), + new File(target, children[i])); + } + } else { + InputStream in = new FileInputStream(source); + OutputStream out = new FileOutputStream(target); + + byte[] buf = new byte[1024]; + int len; + while ((len = in.read(buf)) > 0) { + out.write(buf, 0, len); + } + in.close(); + out.close(); + } + } + +} diff --git a/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/wsspi/kernel/embeddable/EmbeddedServerDriver.java b/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/wsspi/kernel/embeddable/EmbeddedServerDriver.java new file mode 100755 index 00000000000..c5eff7df837 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/wsspi/kernel/embeddable/EmbeddedServerDriver.java @@ -0,0 +1,609 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2013, 2016 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.wsspi.kernel.embeddable; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.PrintStream; +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; +import java.util.Scanner; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; + +import com.ibm.websphere.simplicity.log.Log; +import com.ibm.ws.kernel.boot.ReturnCode; +import com.ibm.ws.kernel.boot.cmdline.Utils; +import com.ibm.wsspi.kernel.embeddable.Server.Result; + +import junit.framework.Assert; +import junit.framework.AssertionFailedError; + +public class EmbeddedServerDriver implements ServerEventListener { + + private final Class c = EmbeddedServerDriver.class; + private String CURRENT_METHOD_NAME = null; + + private CountDownLatch startingEventOccurred; + private CountDownLatch startedEventOccurred; + private CountDownLatch stoppedEventOccurred; + private CountDownLatch failedEventOccurred; + + private String serverName = null; + private String userDir = null; + private String outputDir = null; + + private ServerBuilder sb = null; + private Server server = null; + private Result result = null; + private Properties props = null; + private Properties props2 = null; + private Properties props3 = null; + + private List failures = null; + + public EmbeddedServerDriver(String serverName, String userDir, String outputDir) throws UnsupportedEncodingException { + this.serverName = serverName; + this.userDir = userDir; + this.outputDir = outputDir; + this.props = new Properties(); + this.props.setProperty("com.ibm.websphere.productId", "com.ibm.cicsts"); + this.props.setProperty("com.ibm.websphere.productInstall", "wlp/usr/servers/com.ibm.wsspi.kernel.embeddable.add.product.extension.fat/producttest"); + this.props2 = new Properties(); + this.props2.setProperty("com.ibm.websphere.productId", "com.ibm.cicstsb"); + this.props2.setProperty("com.ibm.websphere.productInstall", "wlp/usr/servers/com.ibm.wsspi.kernel.embeddable.add.product.extension.multiple.fat/producttestb"); + this.props3 = new Properties(); + this.props3.setProperty("com.ibm.websphere.productId", "com.ibm.cicsts"); + this.props3.setProperty("com.ibm.websphere.productInstall", "wlp/usr/servers/com.ibm.wsspi.kernel.embeddable.add.product.extension.multiple.fat/producttest"); + init("EmbeddedServerDriver"); + } + + public void init(String CURRENT_METHOD_NAME) throws UnsupportedEncodingException { + this.CURRENT_METHOD_NAME = CURRENT_METHOD_NAME; + + Log.info(c, "init", "Setting up for " + this.CURRENT_METHOD_NAME); + + startingEventOccurred = new CountDownLatch(1); + startedEventOccurred = new CountDownLatch(1); + stoppedEventOccurred = new CountDownLatch(1); + failedEventOccurred = new CountDownLatch(1); + + failures = new ArrayList(); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + System.setOut(new PrintStream(baos, true, "UTF-8")); + + sb = new ServerBuilder(); + if (CURRENT_METHOD_NAME.equals("testAddProductExtension")) { + Log.info(c, "init", "current method name is testAddProductExtension "); + server = sb.setName(serverName).setOutputDir(new File(outputDir)).setUserDir(new File(userDir)).addProductExtension("productA", + props).setServerEventListener(this).build(); + } else if (CURRENT_METHOD_NAME.equals("testAddProductExtensionMultiple")) { + Log.info(c, "init", "current method name is testAddProductExtensionMultiple "); + server = sb.setName(serverName).setOutputDir(new File(outputDir)).setUserDir(new File(userDir)).addProductExtension("productA", + props3).addProductExtension("productB", + props2).setServerEventListener(this).build(); + + } else { + server = sb.setName(serverName).setOutputDir(new File(outputDir)).setUserDir(new File(userDir)).setServerEventListener(this).build(); + } + + String serverConsoleOutput = new String(baos.toByteArray(), "UTF-8"); + Log.info(c, "init", "consoleOutput = " + serverConsoleOutput); + + result = null; + checkServerRunning(false); // server should be stopped + } + + public void tearDown() { + Log.info(c, "init", "Cleaning up after " + this.CURRENT_METHOD_NAME); + + if (server != null) { + Future stopFuture = server.stop(); + stopFuture.cancel(true); + } + + startingEventOccurred = null; + startedEventOccurred = null; + stoppedEventOccurred = null; + failedEventOccurred = null; + } + + public void testStoppingAStoppedServer() { + + // Stop a stopped server + Future stopFuture = server.stop(); + try { + result = stopFuture.get(); + dumpResult("Stopping a stopped server", result); + Assert.assertFalse("Stopping a stopped server should not be successful", result.successful()); + Assert.assertEquals("Should have a redundant operation returned", ReturnCode.REDUNDANT_ACTION_STATUS.getValue(), result.getReturnCode()); + } catch (AssertionFailedError e) { + failures.add(e); + Log.error(c, CURRENT_METHOD_NAME, e); + } catch (InterruptedException e) { + failures.add(new AssertionFailedError("Stop operation did not complete normally: " + e)); + Log.error(c, CURRENT_METHOD_NAME, e); + } catch (ExecutionException e) { + failures.add(new AssertionFailedError("Stop operation could not be queued: " + e)); + Log.error(c, CURRENT_METHOD_NAME, e); + } + + checkServerRunning(false); // server should be stopped + } + + public void testStartingAStoppedServer() { + PrintStream originalSysOut = System.out; + try { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + System.setOut(new PrintStream(baos, true, "UTF-8")); + coldStartServer(); + verifyServerEvent("\"STARTING\" ServerEvent should have fired", startingEventOccurred); + verifyServerEvent("\"STARTED\" ServerEvent should have fired", startedEventOccurred); + + String serverConsoleOutput = new String(baos.toByteArray(), "UTF-8"); + Log.info(c, "testStartingAStoppedServer", "consoleOutput = " + serverConsoleOutput); + try { + Assert.assertTrue("No indication that application started", serverConsoleOutput.contains("CWWKZ0001I: Application simpleApp started")); + } catch (Throwable t) { + failures.add(new AssertionFailedError("Exception occurred while searching for app started message in logs - " + t)); + Log.error(c, CURRENT_METHOD_NAME, t); + } + + // PI20344: Verify that Utils.java is using the correct user dir + String utilsUserDirAbsolutePath = Utils.getUserDir().getAbsolutePath().replace('\\', '/'); + String userDirAbsolutePath = userDir.replace('\\', '/'); + Log.info(c, "testStartingAStoppedServer", "UserDirAbsolutePath=[" + userDirAbsolutePath + "] utilsUserDirAbsolutePath=[" + utilsUserDirAbsolutePath + "]"); + Assert.assertTrue("Utils.userDir() should be using the java property with any luck at all.", userDirAbsolutePath.equals(utilsUserDirAbsolutePath)); + + stopRunningServer(); + } catch (UnsupportedEncodingException ex) { + } finally { + System.setOut(originalSysOut); + } + } + + public void testAddProductExtension() { + PrintStream originalSysOut = System.out; + try { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + System.setOut(new PrintStream(baos, true, "UTF-8")); + coldStartServer(); + verifyServerEvent("\"STARTING\" ServerEvent should have fired", startingEventOccurred); + verifyServerEvent("\"STARTED\" ServerEvent should have fired", startedEventOccurred); + + String serverConsoleOutput = new String(baos.toByteArray(), "UTF-8"); + Log.info(c, "testAddProductExtension", "consoleOutput = " + serverConsoleOutput); + try { + Assert.assertTrue("No indication that application started", serverConsoleOutput.contains("CWWKZ0001I: Application simpleApp started")); + } catch (Throwable t) { + failures.add(new AssertionFailedError("Exception occurred while searching for app started message in logs - " + t)); + Log.error(c, CURRENT_METHOD_NAME, t); + } + try { + //[AUDIT ] CWWKF0012I: The server installed the following features: [jsp-2.2, productA:prodtest-1.0, timedexit-1.0, servlet-3.0]. + Assert.assertTrue("No indication that the product extension feature productA:prodtest-1.0 was installed", + isProductExtensionInstalled(serverConsoleOutput, "productA:prodtest-1.0")); + } catch (Throwable t) { + failures.add(new AssertionFailedError("Exception occurred while searching for the product extension feature was installed message in logs - " + t)); + Log.error(c, CURRENT_METHOD_NAME, t); + } + + try { + // Check that the server logs contain the CWWKE0108I message + String messageToFind = "CWWKE0108I"; + boolean messageFound = false; + Log.info(c, CURRENT_METHOD_NAME, "SCANNING: " + outputDir + "/" + serverName + "/logs/message.log"); + File logFile = new File(outputDir + "/" + serverName + "/logs/messages.log"); + Scanner logScanner = new Scanner(logFile); + while (logScanner.hasNextLine() && messageFound == false) { + String line = logScanner.nextLine(); + Log.info(c, CURRENT_METHOD_NAME, line); + if (line.contains(messageToFind)) { + messageFound = true; + } + } + logScanner.close(); + Assert.assertTrue(messageFound); + } catch (Throwable t) { + failures.add(new AssertionFailedError("Exception occurred while searching for product extension was added message in logs - " + t)); + Log.error(c, CURRENT_METHOD_NAME, t); + } + + stopRunningServer(); + } catch (UnsupportedEncodingException ex) { + } finally { + System.setOut(originalSysOut); + } + } + + /** + * Determine if the input product extension exists in the input string. + * + * @param inputString string to search. + * @param productExtension product extension to search for. + * @return true if input product extension is found in the input string. + */ + private boolean isProductExtensionInstalled(String inputString, String productExtension) { + if ((productExtension == null) || (inputString == null)) { + return false; + } + int msgIndex = inputString.indexOf("CWWKF0012I: The server installed the following features:"); + if (msgIndex == -1) { + return false; + } + + String msgString = inputString.substring(msgIndex); + int leftBracketIndex = msgString.indexOf("["); + int rightBracketIndex = msgString.indexOf("]"); + if ((leftBracketIndex == -1) || + (rightBracketIndex == -1) || + (rightBracketIndex < leftBracketIndex)) { + return false; + } + + String features = msgString.substring(leftBracketIndex, rightBracketIndex); + Log.info(c, "isProductExtensionInstalled", features); + if (features.indexOf(productExtension) == -1) { + return false; + } + return true; + } + + public void testAddProductExtensionMultiple() { + PrintStream originalSysOut = System.out; + try { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + System.setOut(new PrintStream(baos, true, "UTF-8")); + coldStartServer(); + verifyServerEvent("\"STARTING\" ServerEvent should have fired", startingEventOccurred); + verifyServerEvent("\"STARTED\" ServerEvent should have fired", startedEventOccurred); + + String serverConsoleOutput = new String(baos.toByteArray(), "UTF-8"); + Log.info(c, "testAddProductExtensionMultiple", "consoleOutput = " + serverConsoleOutput); + try { + Assert.assertTrue("No indication that application started", serverConsoleOutput.contains("CWWKZ0001I: Application simpleApp started")); + } catch (Throwable t) { + failures.add(new AssertionFailedError("Exception occurred while searching for app started message in logs - " + t)); + Log.error(c, CURRENT_METHOD_NAME, t); + } + // [AUDIT ] CWWKF0012I: The server installed the following features: [jsp-2.2, productA:prodtest-1.0, productB:prodtestb-1.0, timedexit-1.0, servlet-3.0]. + try { + Assert.assertTrue("No indication that the product extension feature productA:prodtest-1.0 was installed", + isProductExtensionInstalled(serverConsoleOutput, "productA:prodtest-1.0")); + } catch (Throwable t) { + failures.add(new AssertionFailedError("Exception occurred while searching for the product extension feature was installed message in logs - " + t)); + Log.error(c, CURRENT_METHOD_NAME, t); + } + + try { + Assert.assertTrue("No indication that the product extension feature productB:prodtestb-1.0 was installed", + isProductExtensionInstalled(serverConsoleOutput, "productB:prodtestb-1.0")); + } catch (Throwable t) { + failures.add(new AssertionFailedError("Exception occurred while searching for the product extension feature was installed message in logs - " + t)); + Log.error(c, CURRENT_METHOD_NAME, t); + } + + try { + // Check that the server logs contain the CWWKE0108I message + String messageToFind = "CWWKE0108I"; + boolean messageFound = false; + Log.info(c, CURRENT_METHOD_NAME, "SCANNING: " + outputDir + "/" + serverName + "/logs/message.log"); + File logFile = new File(outputDir + "/" + serverName + "/logs/messages.log"); + Scanner logScanner = new Scanner(logFile); + while (logScanner.hasNextLine() && messageFound == false) { + String line = logScanner.nextLine(); + Log.info(c, CURRENT_METHOD_NAME, line); + if (line.contains(messageToFind)) { + messageFound = true; + } + } + logScanner.close(); + Assert.assertTrue(messageFound); + } catch (Throwable t) { + failures.add(new AssertionFailedError("Exception occurred while searching for product extension was added message in logs - " + t)); + Log.error(c, CURRENT_METHOD_NAME, t); + } + + stopRunningServer(); + } catch (UnsupportedEncodingException ex) { + } finally { + System.setOut(originalSysOut); + } + } + + public void testStartingAStartedServer() { + warmStartServer(); + + verifyServerEvent("\"STARTING\" ServerEvent should have fired", startingEventOccurred); + verifyServerEvent("\"STARTED\" ServerEvent should have fired", startedEventOccurred); + + // Start the started server + Future startFuture2 = server.start(); + try { + result = startFuture2.get(); + dumpResult("Starting a started server", result); + Assert.assertFalse("Starting a started server should not be successful", result.successful()); + Assert.assertEquals("Should have a redundant operation returned", ReturnCode.REDUNDANT_ACTION_STATUS.getValue(), result.getReturnCode()); + } catch (AssertionFailedError e) { + failures.add(e); + Log.error(c, CURRENT_METHOD_NAME, e); + } catch (InterruptedException e) { + failures.add(new AssertionFailedError("Start operation did not complete normally: " + e)); + Log.error(c, CURRENT_METHOD_NAME, e); + } catch (ExecutionException e) { + failures.add(new AssertionFailedError("Start operation could not be queued: " + e)); + Log.error(c, CURRENT_METHOD_NAME, e); + } + + checkServerRunning(true); // server should be started + stopRunningServer(); + } + + public void testStoppingAStartedServer() { + warmStartServer(); + verifyServerEvent("\"STARTING\" ServerEvent should have fired", startingEventOccurred); + verifyServerEvent("\"STARTED\" ServerEvent should have fired", startedEventOccurred); + stopRunningServer(); + } + + public void testBadArgument() { + Future startFuture = server.start(new String[] { "--nOnSeNsE" }); + + try { + // check for failed event: should fire w/o requiring interaction w/ future.get + verifyServerEvent("\"FAILED\" ServerEvent should have fired", failedEventOccurred); + + result = startFuture.get(); + dumpResult("Starting a server", result); + Assert.assertFalse("Result of start attempt with bad args should fail", result.successful()); + Assert.assertEquals("Should have an BAD_ARGUMENT return code", ReturnCode.BAD_ARGUMENT.getValue(), result.getReturnCode()); + } catch (AssertionFailedError e) { + failures.add(e); + Log.error(c, CURRENT_METHOD_NAME, e); + } catch (InterruptedException e) { + failures.add(new AssertionFailedError("Start operation did not complete normally: " + e)); + Log.error(c, CURRENT_METHOD_NAME, e); + startFuture.cancel(true); + } catch (ExecutionException e) { + failures.add(new AssertionFailedError("Start operation could not be queued: " + e)); + Log.error(c, CURRENT_METHOD_NAME, e); + } + + checkServerRunning(false); // server should not be started + } + + public void testLaunchException() { + Future startFuture = server.start("--create"); // server already created in init(), double create should fail + + try { + result = startFuture.get(); + dumpResult("Starting an embedded server with \"--create\", which is a bad thing to do", result); + Assert.assertFalse("Result of LaunchException should be failure", result.successful()); + Assert.assertEquals("Should have a BAD_ARGUMENT return code", ReturnCode.BAD_ARGUMENT.getValue(), result.getReturnCode()); + } catch (AssertionFailedError e) { + failures.add(e); + Log.error(c, CURRENT_METHOD_NAME, e); + } catch (InterruptedException e) { + failures.add(new AssertionFailedError("Start operation did not complete normally: " + e)); + Log.error(c, CURRENT_METHOD_NAME, e); + startFuture.cancel(true); + } catch (ExecutionException e) { + failures.add(new AssertionFailedError("Start operation could not be queued: " + e)); + Log.error(c, CURRENT_METHOD_NAME, e); + } + + checkServerRunning(false); // server should not be started + } + + public void testLocationException() { + + String bogusName = "bOgUsSeRvErNaMe"; + server = sb.setName(bogusName).setOutputDir(new File(outputDir)).setUserDir(new File(userDir)).setServerEventListener(this).build(); + + (new File(outputDir + "/" + bogusName, "server.xml")).delete(); // delete the server from the hfs, so start() throws a LocationException + + Future startFuture = server.start(); + + try { + // check for failed event: should fire w/o requiring interaction w/ future.get + verifyServerEvent("\"FAILED\" ServerEvent should have fired", failedEventOccurred); + + result = startFuture.get(); + dumpResult("Starting a server with a bogus name", result); + Assert.assertFalse("Result of LocationException should be failure", result.successful()); + Assert.assertEquals("Should have a LOCATION_EXCEPTION return code", ReturnCode.LOCATION_EXCEPTION.getValue(), result.getReturnCode()); + } catch (AssertionFailedError e) { + failures.add(e); + Log.error(c, CURRENT_METHOD_NAME, e); + } catch (InterruptedException e) { + failures.add(new AssertionFailedError("Start operation did not complete normally: " + e)); + Log.error(c, CURRENT_METHOD_NAME, e); + startFuture.cancel(true); + } catch (ExecutionException e) { + failures.add(new AssertionFailedError("Start operation could not be queued: " + e)); + Log.error(c, CURRENT_METHOD_NAME, e); + } + + checkServerRunning(false); // server should not be started + } + + public void testServerUnknownStatus() { + //TODO: This is not called by the test framework + // because I don't know how to guarantee an InterruptedException + // without jMock, which seems pointless in a FAT scenario like this + + Future startFuture = server.start(new String[] { "--clean" }); + + try { + result = startFuture.get(); + dumpResult("Force an InterruptException while starting a server", result); + Assert.assertFalse("Result of InterruptedException should be failure", result.successful()); + Assert.assertEquals("Should have a SERVER_UNKNOWN_STATUS return code", ReturnCode.SERVER_UNKNOWN_STATUS.getValue(), result.getReturnCode()); + } catch (AssertionFailedError e) { + failures.add(e); + Log.error(c, CURRENT_METHOD_NAME, e); + } catch (InterruptedException e) { + failures.add(new AssertionFailedError("Start operation did not complete normally: " + e)); + Log.error(c, CURRENT_METHOD_NAME, e); + startFuture.cancel(true); + } catch (ExecutionException e) { + failures.add(new AssertionFailedError("Start operation could not be queued: " + e)); + Log.error(c, CURRENT_METHOD_NAME, e); + } + + checkServerRunning(true); // server should be started + + } + + public void testErrorServerStart() { + //TODO: This is not called by the test framework + // because I don't know how to force waitForStarted() to return false + // without jMock, which seems pointless in a FAT scenario like this + + } + + public List getFailures() { + return failures; + } + + private void verifyServerEvent(String msg, CountDownLatch event) { + boolean pass = false; + + try { + event.await(5, TimeUnit.SECONDS); + pass = true; + } catch (InterruptedException e) { + pass = false; + } + + try { + Assert.assertTrue(msg, pass); + } catch (AssertionFailedError e) { + failures.add(new AssertionFailedError(e.toString())); + Log.error(c, CURRENT_METHOD_NAME, e); + } + + } + + private void warmStartServer() { + Future startFuture = server.start(); + + try { + result = startFuture.get(); + dumpResult("Starting a server", result); + Assert.assertTrue("Result of start attempt should be successful", result.successful()); + Assert.assertEquals("Should have an OK return code", ReturnCode.OK.getValue(), result.getReturnCode()); + } catch (AssertionFailedError e) { + failures.add(e); + Log.error(c, CURRENT_METHOD_NAME, e); + } catch (InterruptedException e) { + failures.add(new AssertionFailedError("Start operation did not complete normally: " + e)); + Log.error(c, CURRENT_METHOD_NAME, e); + startFuture.cancel(true); + } catch (ExecutionException e) { + failures.add(new AssertionFailedError("Start operation could not be queued: " + e)); + Log.error(c, CURRENT_METHOD_NAME, e); + } + + checkServerRunning(true); // server should be started + } + + private void coldStartServer() { + Future startFuture = server.start(new String[] { "--clean" }); + + try { + result = startFuture.get(); + dumpResult("Starting a server", result); + Assert.assertTrue("Result of first start attempt should be successful", result.successful()); + Assert.assertEquals("Should have an OK return code", ReturnCode.OK.getValue(), result.getReturnCode()); + } catch (AssertionFailedError e) { + failures.add(e); + Log.error(c, CURRENT_METHOD_NAME, e); + } catch (InterruptedException e) { + failures.add(new AssertionFailedError("Start operation did not complete normally: " + e)); + Log.error(c, CURRENT_METHOD_NAME, e); + startFuture.cancel(true); + } catch (ExecutionException e) { + failures.add(new AssertionFailedError("Start operation could not be queued: " + e)); + Log.error(c, CURRENT_METHOD_NAME, e); + } + + checkServerRunning(true); // server should be started + } + + private void stopRunningServer() { + Future stopFuture = server.stop(); + try { + result = stopFuture.get(); + dumpResult("Stopping a started server", result); + Assert.assertTrue("Stopping a running server should be successful", result.successful()); + Assert.assertEquals("Should have an OK return code", ReturnCode.OK.getValue(), result.getReturnCode()); + } catch (AssertionFailedError e) { + failures.add(e); + Log.error(c, CURRENT_METHOD_NAME, e); + } catch (InterruptedException e) { + failures.add(new AssertionFailedError("Stop operation did not complete normally: " + e)); + Log.error(c, CURRENT_METHOD_NAME, e); + } catch (ExecutionException e) { + failures.add(new AssertionFailedError("Stop operation could not be queued: " + e)); + Log.error(c, CURRENT_METHOD_NAME, e); + } + + checkServerRunning(false); // server should be stopped + + verifyServerEvent("\"STOPPED\" ServerEvent should have fired", stoppedEventOccurred); + } + + private void checkServerRunning(boolean expectRunning) { + try { + if (expectRunning) { + Assert.assertTrue("Server should be running", server.isRunning()); + } else { + Assert.assertFalse("Server should not be running", server.isRunning()); + } + } catch (AssertionFailedError e) { + failures.add(e); + } + } + + private void dumpResult(String msg, Result result) { + Log.info(c, "dumpResult", msg + " -- Result: success=" + result.successful() + ", rc=" + result.getReturnCode() + ", ex=" + result.getException()); + } + + @Override + public void serverEvent(ServerEvent serverEvent) { + String event = serverEvent.toString(); + Log.info(c, "serverEvent", "NEW SERVER EVENT FIRED: " + event); + + switch (serverEvent.getType()) { + case STARTING: + startingEventOccurred.countDown(); + break; + case STARTED: + startedEventOccurred.countDown(); + break; + case STOPPED: + stoppedEventOccurred.countDown(); + break; + case FAILED: + failedEventOccurred.countDown(); + break; + default: + break; + } + } +} diff --git a/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/wsspi/kernel/embeddable/EmbeddedServerTest.java b/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/wsspi/kernel/embeddable/EmbeddedServerTest.java new file mode 100755 index 00000000000..2f5089bda93 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/fat/src/com/ibm/wsspi/kernel/embeddable/EmbeddedServerTest.java @@ -0,0 +1,265 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.wsspi.kernel.embeddable; + +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.channels.FileChannel; +import java.util.List; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; + +import com.ibm.websphere.simplicity.log.Log; + +import componenttest.topology.impl.LibertyServer; +import componenttest.topology.impl.LibertyServerFactory; +import junit.framework.AssertionFailedError; + +public class EmbeddedServerTest { + + static final Class c = EmbeddedServerTest.class; + + static LibertyServer ls = null; + static Object driver = null; + + static File wsServerBundle = null; + static File testServerClasses = null; + + static Class driverClazz = null; + + public String testName; + + static String serverName = "com.ibm.wsspi.kernel.embeddable.fat"; + public static File outputAutoFVTDirectory; + + @Rule + public TestRule testInvoker = new TestRule() { + @Override + public Statement apply(final Statement stmt, final Description desc) { + return new Statement() { + @Override + public void evaluate() throws Throwable { + try { + testName = desc.getMethodName(); + embeddedServerTestHelper(testName); + stmt.evaluate(); + } finally { + testName = null; + } + } + }; + } + }; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + final String METHOD_NAME = "setUpBeforeClass"; + + // Save this off for the tearDown method to manually copy logs from /NonDefaultUser + // folder to /autoFVT/output/servers/ folder. + outputAutoFVTDirectory = new File("output/servers", serverName); + Log.info(c, METHOD_NAME, "outputAutoFVTDirectory: " + outputAutoFVTDirectory.getAbsolutePath()); + + // Find the necessary bundles in our install image + ls = LibertyServerFactory.getLibertyServer("com.ibm.wsspi.kernel.embeddable.fat"); + + testServerClasses = new File("build/classes"); + + wsServerBundle = new File(ls.getInstallRoot() + "/bin/tools/ws-server.jar"); + + // PI20344: Use non default directories. + String userDir = ls.getUserDir() + "/../NonDefaultUser"; // originally ls.getUserDir() + String outputDir = userDir + "/servers"; // originally ls.getServerRoot(); + + // PI20344: Additional setup needed when using non default directories. + // Copy the server directory to my output directory + // Also need the test.properties file + File destDir = new File(outputDir, serverName); + File srcDir = new File(ls.getServerRoot()); + destDir.mkdirs(); + copyDirectory(srcDir, destDir); + + File dest_TestPorts = new File(destDir, "/../testports.properties"); + File src_TestPorts = new File(srcDir, "/../testports.properties"); + copyFile(src_TestPorts, dest_TestPorts); + // END PI20344 + + Log.info(c, METHOD_NAME, "wsServerBundle: " + wsServerBundle.getAbsolutePath()); + Log.info(c, METHOD_NAME, "testServerClasses: " + testServerClasses.getAbsolutePath()); + + URLClassLoader classloader = new URLClassLoader(new URL[] { wsServerBundle.toURI().toURL(), + testServerClasses.toURI().toURL() }) { + // Borrowed from the bvt tests + @Override + protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException { + Class result = null; + + if (name == null || name.length() == 0) + return null; + + result = findLoadedClass(name); + + if (result == null && name != null) { + try { + // Try to load the class from the child classpath first... + result = findClass(name); + } catch (ClassNotFoundException cnfe) { + result = super.loadClass(name, resolve); + } + } + + return result; + } + }; + + driverClazz = classloader.loadClass("com.ibm.wsspi.kernel.embeddable.EmbeddedServerDriver"); + Constructor dCTOR = driverClazz.getConstructor(String.class, String.class, String.class); + driver = dCTOR.newInstance(serverName, userDir, outputDir); + } + + @AfterClass + public static void tearDown() throws Throwable { + final String METHOD_NAME = "tearDown"; + + // Manually copying server logs since they are in a non-default location + // and build script copy does not pick them up. + outputAutoFVTDirectory.mkdirs(); + Log.info(c, METHOD_NAME, "Copying directory from " + + ls.getUserDir() + "/../NonDefaultUser" + " to " + + outputAutoFVTDirectory.getAbsolutePath()); + + File srcDir = new File(ls.getUserDir() + "/../NonDefaultUser"); + copyDirectory(srcDir, outputAutoFVTDirectory.getAbsoluteFile()); + } + + @Test + public void testStoppingAStoppedServer() throws Throwable {} + + @Test + public void testStartingAStoppedServer() throws Throwable {} + + @Test + public void testStartingAStartedServer() throws Throwable {} + + @Test + public void testStoppingAStartedServer() throws Throwable {} + + @Test + public void testBadArgument() throws Throwable {} + + @Test + public void testLaunchException() throws Throwable {} + + //@Test + //public void testLocationException() throws Throwable {} + + private static void embeddedServerTestHelper(final String REMOTE_METHOD_NAME) throws Throwable { + final String METHOD_NAME = "testEmbeddedServer"; + Log.info(c, METHOD_NAME, "Preparing to run: " + REMOTE_METHOD_NAME); + + Method testMethod = driverClazz.getDeclaredMethod(REMOTE_METHOD_NAME); + + Method initMethod = driverClazz.getDeclaredMethod("init", new Class[] { String.class }); + + Method tearDownMethod = driverClazz.getDeclaredMethod("tearDown"); + + Method getFailuresMethod = driverClazz.getDeclaredMethod("getFailures"); + + try { + + initMethod.invoke(driver, new Object[] { REMOTE_METHOD_NAME }); + testMethod.invoke(driver); + tearDownMethod.invoke(driver); + + List failures = (List) getFailuresMethod.invoke(driver); + for (AssertionFailedError fail : failures) + Log.info(driverClazz, REMOTE_METHOD_NAME, fail.getMessage()); + + if (!failures.isEmpty()) + //add string buffer here to show failures in detail + assertTrue("Failures found " + failures, false); + } catch (InvocationTargetException t) { + throw t.getCause(); + } + } + + private static void copyFile(File fromFile, File toFile) throws IOException { + // Open the source file + FileInputStream fis = new FileInputStream(fromFile); + try { + // Open the destination file + File destDir = toFile.getParentFile(); + if (!destDir.exists() && !destDir.mkdirs()) { + throw new IOException("Failed to create path: " + destDir.getAbsolutePath()); + } + + System.out.println("Copying file from: " + fromFile.getAbsolutePath()); + System.out.println("Copying file to: " + toFile.getAbsolutePath()); + + FileOutputStream fos = new FileOutputStream(toFile); + + // Perform the transfer using nio channels; this is simpler, and usually + // faster, than copying the file a chunk at a time + try { + FileChannel inChan = fis.getChannel(); + FileChannel outChan = fos.getChannel(); + inChan.transferTo(0, inChan.size(), outChan); + } finally { + fos.close(); + } + } finally { + fis.close(); + } + } + + public static void copyDirectory(File source, File target) throws IOException { + if (source.isDirectory()) { + if (!target.exists()) { + target.mkdir(); + } + + String[] children = source.list(); + for (int i = 0; i < children.length; i++) { + copyDirectory(new File(source, children[i]), + new File(target, children[i])); + } + } else { + InputStream in = new FileInputStream(source); + OutputStream out = new FileOutputStream(target); + + byte[] buf = new byte[1024]; + int len; + while ((len = in.read(buf)) > 0) { + out.write(buf, 0, len); + } + in.close(); + out.close(); + } + } +} diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/applications/SharedLooseEAR.ear.xml b/dev/com.ibm.ws.kernel.boot_fat/publish/applications/SharedLooseEAR.ear.xml new file mode 100755 index 00000000000..cc417f09a57 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/applications/SharedLooseEAR.ear.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/files/ProvisioningInterimFixesTestBundle1_1.0.0.20130101.jar b/dev/com.ibm.ws.kernel.boot_fat/publish/files/ProvisioningInterimFixesTestBundle1_1.0.0.20130101.jar new file mode 100755 index 0000000000000000000000000000000000000000..ea1069f0f196920bacfa0002f8482b76dfae97c2 GIT binary patch literal 797 zcmWIWW@Zs#0D+Bp7EWLWl;8x?zOEsTx}JV+`Tf=zqd`9}(m^w&On=<=!ZMYZGV()&B4ry6|}H#qu! z?@+tAX@ls~EOp*Bt62oJcq2D*>6~QP?c5P4pVIXFWaF)ni{d-oeCO+R|B_!=xhlh8 z$?CqlIp2@}e|Jo(_2`t|zH^li3NwTZd#3755%a5C{mv-tXyEC$=fch|oVn%BhuR$< zGw(3&nQ-<_$n26|E@=&xcUfPZ+M&F!b@}!8HXG9IGUi_}c`@(e<%EF6{Vh##{bwtW zAKexE?b`F}Hd|G9?D(cPZ;?*3R;t6|LTit`gc{jN>8Kq=wz?SDW|4Lt;~$wXLm@YPoXNtVa^)^U1OECJFhBj{NR1- zZv5A;oAkuD+FdX4{KpXB&B$aAP72u4kqR_L2|#Iha^Yf701GiPNH7HLon~b9>ntOT zR_iUE^ZVjiMugGW(jLrckU8o=3^y7nB_i9h*2Jm98fZ&VmZi-@Rs K1k!FyARYiF#x?^0 literal 0 HcmV?d00001 diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/files/ProvisioningInterimFixesTestBundle1_1.0.0.jar b/dev/com.ibm.ws.kernel.boot_fat/publish/files/ProvisioningInterimFixesTestBundle1_1.0.0.jar new file mode 100755 index 0000000000000000000000000000000000000000..ed70dc5c5770c44771fcb53b836ef4b34abb7daa GIT binary patch literal 769 zcmWIWW@Zs#0D+Bp7EWLWl;8x?zOEsTx}JV+`TSJZR@a+BT!V0?WUQeFf`1rZ{{JEI4Ew0H&%dfPBh&es@dG;7rz1WgKpAY-ycIjhjF2Id|9R_wkueT^4Vd(NXxaB%RGgpc|%s6?ap`fJr%G5aa8g9S$8$T<= z{WuOI%X8omp)Brjyl`P%tC z-Y#FzM^sNAt3~bXUjDEofPN$2sUpP2$v@3%-c@IjQ+g)in8ZVOMSN zArq;CFETj;_Z(m1F>z;F*y$UG^f&$9|K@dS?7z*wbbcQD&k*3v$Yc+WZft2q1)6FE zpfo&5a4{%=g%}wm7=rdrGqU=1mJvp)^%l?heeo hu3s{6E6Id7#1=MJ0m75Da-8_(;UW440#cc0hfGtM7u@8#%xO!wrv86lG7D>*Zn zBPjo*^PepX&n%F-x7BXTxrGlmTXg*J-d$=ju}1D!+=aaRrqYWiZJOd6e13<*h@89T@Xpp*i@n^XTnW$+J$AUzIIMw&ZmP?*~v?61-acFUdYOZ;meBK{Z zX$JjkY3o+UTGc9DJ}~DUQ)ucP!TX0Uzb==%VJv@V{sog4^DbUa2w2=N#=2K-_UFFt z(%o;?o?l;?9k}cG$+39WBgsS(iDti-^-cI|pcW-RP*7eyDw>D~f^_1?m z`DieGXZseNHxt7Sv#wlM5p>B@t#suDv$dzMyU#cx=+e*KFKT4Z_ zuih7T?P>5@{o8WC#Y7>zCI!Hfo(qYlJyqmdFKvMryL7dBf1Z7IsKw0X#ipaZ;F*+5QV0>Xnp J+LZ~!0{~)cEB62Z literal 0 HcmV?d00001 diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/files/ProvisioningInterimFixesTestBundle2_1.0.0.jar b/dev/com.ibm.ws.kernel.boot_fat/publish/files/ProvisioningInterimFixesTestBundle2_1.0.0.jar new file mode 100755 index 0000000000000000000000000000000000000000..8decf44057c43b240df57bee4ffa45b42b270445 GIT binary patch literal 768 zcmWIWW@Zs#0D&EO7EWLWl;8x?zOEsTx}JV+`TSJZR@a+BT!V0?WUQeFf`1rZ{{JEI4Ew0H&%dfPBh&es@dG;7rz1WgKpA6N+RRW|$m>=$;LKHa9Z_IpY~uxP{LLk6m=4;abZuytzr5nVt?wjD;XcYc(y`&FW(QbIroyEJMQ_> z{5#m>b@};=pA!PyHYR_r$nWGh)@nm7??`18S zCQTPF3oWYX_nfFye0I&Wjji!1-|KH)KfUWu`q#)$OaCzjcr!BDgJT<8Qc-~>8UZK` zPZ3-U3Sc2d1_=f^&4X4}zs@qkXtmzrIlnKSMKT&&@`4!+GDjVV;YK4RHe_1@o=-Y! e4YZ{w%hKi{D}oO2W@Q68g$W1`0%=Vq5Dx(7>m(5X literal 0 HcmV?d00001 diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/files/ProvisioningInterimFixesTestBundle3_1.0.0.20130101.jar b/dev/com.ibm.ws.kernel.boot_fat/publish/files/ProvisioningInterimFixesTestBundle3_1.0.0.20130101.jar new file mode 100755 index 0000000000000000000000000000000000000000..b1cc8684eff1222a70a67449d3a7858128a52e36 GIT binary patch literal 796 zcmWIWW@Zs#0D(Pu7EWLWl;8x?zOEsTx}JV+`T!Xd~gxN;FeX>KoT@DT0D>y^-65o+mD~rr; z|M`0FYQ#c=85=HMw0u`7BQ;IpSkTiTPWAnfrIM%rtjO4HoLZc5#Mit;KCkALX+wIp z@#Uv%bL}Q(CHR&1tulGnk^k`Jx7**}bn-_n&$#t^&f?<-7j)U(UUB{HCd>TYG0P9f z{r)p+`6d?e>-UZZ&sY{P%|zo$9((8ah4ZF!s9nm_ynS1kTmM@*ueWuX>&A_F)79mk zY3X`&-H|(6v_s*lsK1ky-%>r1TgyaiYFj)-oPKO*(72Zvv?OC|np@|M1M)_@|G!$D z8mpI4I`8e%AM63%j7;|6lz=T6sX!By0F;KO7A^(_un;4I1cT(d?eP@N>A{Q!nWGNGaHEkDBC;*~TQpj&fwmN7S=u~gMbH7>tZX2sFahB~AnnQo G;sF3GZXrDY literal 0 HcmV?d00001 diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/files/ProvisioningInterimFixesTestBundle3_1.0.0.jar b/dev/com.ibm.ws.kernel.boot_fat/publish/files/ProvisioningInterimFixesTestBundle3_1.0.0.jar new file mode 100755 index 0000000000000000000000000000000000000000..ec2429663d3d6e9912d3ecce9791ffe6eda8b3e6 GIT binary patch literal 769 zcmWIWW@Zs#0D(Pu7EWLWl;8x?zOEsTx}JV+`T;+xA~%WMHUaW?%qm zhAZ=R^z(Fc4Gz)sb?Xg2*mui;XRq={{%dkt6Ur8`h)r9zNN9uZ>8ynv8}25Xs<7#_ z`dAq+JbVATu!3&8*OMnVK7Ot~e=a6%i)-@H@+)m2Vonc!o;}7@FSaDmCq>VE$|POq zfHZfxN6U4WihcdC?(4!*Ki>E!fo}1));{KZ^4Z|SueaY~Hyi3{_#V+Yc;?cyfOY|0 zx6?0v-j3Rn%v8Kmv7%vt_%BC^FNs$1&d2$!)){&Si3C>OSTW^Mt4#uj_u9TEYysP5 zr}{MU#lJM4Wy)<~TB1KUyvk<3pZ&s4)2G|C)_zY(2o`Nve8@m`^#LQ98@5g@zdQ`* z$uewRyJ`Iv$Fu8WQuqGnIU{tGDgANf+}$(3^&6k=bjvgpe0)jpeYM>d34S%N=U(2& zcf~gQhs0&wdYfx1994L`Qv5)#|7OMyr(PKa>mIr|X(i*s7tdB`@8$a;Hs@aQbH_bD zntunIye>a~@pD3eyS(MA?^Q_;%VXBv7Jc9U&(u$sQ*YJY?qz|qoI;HjT(o#C{CL*WuZkC{hkw*iqEc@wy`xn<$L|j>!)}9N&g!8srNr)fHxzPJvh3tr4epFD7_HV@Jm>etvq(l`OJ6XfLFT9fG2CdR)P`)!YsYnm ft%0@_Wm(!hWJS;c-mGjOr!WEGK_IQg1mXbzPvawT literal 0 HcmV?d00001 diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/files/ProvisioningInterimFixesTestBundle4_1.0.0.20130101.jar b/dev/com.ibm.ws.kernel.boot_fat/publish/files/ProvisioningInterimFixesTestBundle4_1.0.0.20130101.jar new file mode 100755 index 0000000000000000000000000000000000000000..21e8d5ec4ed7597826f2b46aa0c90004bb105c47 GIT binary patch literal 792 zcmWIWW@Zs#0D-l67EWLWl;8x?zOEsTx}JV+`TKvn?nd#U+S&#!#&lyUj8_NK)gk9~Z#>#yhByPCbY=~9cY@EM+5j!=e+ zHZd;!_F->Cg=cWG*0KM|JMj0w`-3Uln#8_G^UYAz-1K5c{OKu=cHT&4;8x{-A{DT0 zZdw@2+x?g0uV`mKV0jTUA-wKQcI53l&+GP@$)3F-dB&@R;h|DY(YfEEKNw5bXqc-W z%yO5ymdcnDlA(Ra!(f}{3|Xg^R}O~rp0gAMr_ImoJyo|$YnAz?O)j?#BSb^rr4{eL zS1qY6!X|8HWi{Wn-}$i6;fPf+S`VL?uhvVRDKDB^zAT5YcgIV&w}*TE_p*J+$xYjJ zXZB_FAl@@C&jn6BCi_v>=5F2U!}EST_$T69{kHgvg+$23bm_0VV$GiGPS4(cGkbpg z=a6X+9^Kkq!F5^W)FignTW=LU+Fki9bkOCNZfbS4-@~K-)+J^hU#DSq?d_){hhv_~ zO;XynRoktWkpWU zj+~oRt@@8Kz?+fD9-IoWB_S1PViJJT@RY*Epa2$PWRPIkW>>0b_3JDnj8^L{p7ZuIrUGrHPDu#EK8e*tOz>5o0SdZ6eb`%2&5gEKs*2+ CJt-pq literal 0 HcmV?d00001 diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/files/ProvisioningInterimFixesTestBundle4_1.0.0.jar b/dev/com.ibm.ws.kernel.boot_fat/publish/files/ProvisioningInterimFixesTestBundle4_1.0.0.jar new file mode 100755 index 0000000000000000000000000000000000000000..189cbd8f06c5c4d3781ac79841021bc54dd95a81 GIT binary patch literal 769 zcmWIWW@Zs#0D-l67EWLWl;8x?zOEsTx}JV+`T((3Wn}5qeV6XB=c{j@tg;d?y>jT0=m@Ww|au8HIyD{nwqnlA& zdAaZD{qNT>n#(9Xyj*eY^RvC?k7u6AXg=08e+BPKot6WiUvE|Yr{}R);&jY9P1R~1 z$Czfa}Hl1Dm_1207CW4n)jJ>6uWSvap z^%gCc*Z$bXd1gu50%k|^FUX^v>(pmWm%=SLXIg|VyKusJ^|!Br zY8M6C`nfwE$*Q?_oiW`UbxiEvgu8#!<8@zunje~e()=HPfHxzPJvh3tr4>0b_3JDnj8^L{p7Z*wPowXplMTKnyn;DYYTn^0%h= fgf-BXqAW|BhpY%Xz?+o~~wi*5olYGZC|g|&3R zBWl!^Xyqv%nw@@O5S zuIK7FZD;9H$rFUF>R3|2RQ(8w-EK@Z4)u{P%Qi|l3oH`q-WHy#%15PnAPplwa3Vyi zP_t)s^Q()Vp3R>lz}u$gJGSEVNaB|{K(@0S-st!6MxXmsi{Dxup$RTjmA-^reV42O z6MZSXFh>j3%|u*J1D{IblpwY4(0p-uhy@JDZ;^|zjvmxam-Ww0pN!yXlr>eSq+_f} zb=xrIP;+y2N$j*e6-J&`iff=e8=!4<7~X3w&*NsBXy2C0l2Bmh|M1gHUU~|as2AGa z5xUuQ97EP-?k6&KbeY%rLuIm*3;GgD%CDpCKB$zJCVMRF`RI zJ%isQ#+Vv2AF8xWofJFQ(5iLe;?1(7UH6#3O!HJ0hAX@Luc7kYS?*uj1pu1k!qK0b zY9)#CN3Y;O9U>u6=ldw}b*R%}{|5;D8t8vKH0XH1I{ck)mRH#j9}*gTiWo)=4k8Af zSR;!9q}XsY^rppWGQZ6eMF0T#-(+*IaN;S?@ZeCSSAb_&SQeffDsu$3crG{m*W-aF zi%6`tE3yZxE0T{`nU6Th+BocnS(Y~p6||Gs1>L;u%~A8JsRp3%b`eeyY>Adv_8^LV zsAnkb#tl5;?4(ASBxVtR+jlGN2)##kR+&FD?Q9)8CT+Jc#C8om!HlVv7Hp;vdt(m%s(%dL?O>F}5 z0BS3@{qzVsKIDFEqN0md)Gy_Ac@fg1VJ{dsOzF#cL(R7jZ_)QOWZb={7i$2<7SS%v zqjb~{WnF+*5fIb1*VV+{kmeX_h)&hby%Q74_b)sZ*eNk1Q`yP^BMFp@6RhyUkb;sL zowPtZPHJLTLQRa0e8V3C`?|3ey?GJOqpBcvaklUr=I#?&y?*L=o(yuD{m4YeFJ~KN z^f~wN$eTgSoOt%3cL{?KnBS8+<*A&OB!u9gs0Qf?D7W&e!k|QS+8Nut2Yx9Y`MQmR z{l{EPCkT>-weRZXD-MiWaf9Z@a06tMw6eDU{oa=+=8L(P&PUdZg{N>!UsY&gAV zoYZo@KT6v)3XQpmjV~3i>+vz`QMx37F-pzPFmyHhDI(P5MOUwDU#h$!Q7gxaj~wQPz8@!3A&7&qgNB5Zs&c`vW1Y&_}J)K*{cxjS~O zJsrX1ehFrl1~*>jwL!_BP{&>QV{u8~o(al%_t}cX19@%%TL{he+o<&qvwJUg@2?5q zHrE>(Q_Xgr#~!(1;rRGHo{;!g%#YOWlLoaVpL*w((#}TBx3TAPk}^Xmj^SruH*TR=2;aIzAF17396x(j61V+h&&YYC_|UjB>mFv1lLUtm78?;uP)j-P!VJ zg;ptAntl?2QQ$md(CZ~_-F>ZQ8p`l~D+O`#nFPbU#*G*R>xAl)Nxclu1m~DM-j+bd6 zqSS-B3QHiIHAnygeBbW)-}bs#bF@|S0}05k7~MwpxAikkm7jO;&o$~gGlT%kvj6}B zV1Si(^6_b5HV8*}IW)RH^EbG<%Eqd>QUH+RCuf268v1?KvWl+8GAni+YeiGPPh3{j z)mSE8{hGL@vH$WnQrUm`LmTqH(cCY^Hdfu$VygVKnXkoP{Dc1%pEvVWv2QdOXDtj~ Q=8N!;kNlsOS1Wh_0QDSu#sB~S literal 0 HcmV?d00001 diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/files/ProvisioningTestBundle_1.0.1.201202020001-APAR0001.jar b/dev/com.ibm.ws.kernel.boot_fat/publish/files/ProvisioningTestBundle_1.0.1.201202020001-APAR0001.jar new file mode 100755 index 0000000000000000000000000000000000000000..b6281ee58425e8d57ce006cb59c3279a45f94811 GIT binary patch literal 2331 zcmai02{@E%8~(;J##oYR8Ea%Ke}=LzStE`;imV|rV#p}VjFTTjj4k2F45d*-hu>1R zj4j(_3}rdl&G{u7yAG*~V`%Yr=|9hRz0dPr*LUB~cU|B2-p~D6nXRM<9=*m; z&AQ&8KW@x_@}Hs()o-!~@bK`oLD=n7{7ObE?iu|B+YfH4bj)Rh+?HXL_x=NqVq7QM z#|WN^h9zewd3@qM@}&O=mukO)G5j~T<_zoRa#j8O<2jUtxVm26{_vi&u$6P6r4He? z7o9FjXHLo)^r>Bba8$fkt&TNqw*1rU~y?I0GMTO2f*;a}yhC*?t$N zLtpb-9Fz_oqDBS0iii<*JcjvqK?ULZ{!#P{*-Ag}{hG4ON^ec2dR0n$_sIxFuu*P# z+M25TQM2@9!D4q=hQ)uxIhS!uWO3OJu|qUEUG!D*pDZVM=3!5o$H549V#*at(7k{h zQmK4`pXGRb%**J~aCw2MLKdw~qaqsN`ZT5(S`ld>nAxOsC7tGT)OHSrU{L?il=sP$ zB92Z^o*P;oFwBgintg~KfWm!7Dn#F9Hpa@b4nQPuBcQA&kA((!unD0Sgx5ZCm$DUV z2l|{HPt)Cb@0ERcDo}KG)MOI1G-lP0*GzcSa`S!X-YNMz;u8J-%?Jkit9(|Sg>=b1u?O(13YRlIucI%vpkq?_u`_YpMLFy&1IIoo7mY zCmWtBtL1CUB^jN6W?(n`m#urudbm!0=QYJL(r4PzW zB-CHp=)ilZwUD|L6`BStmu_7)oDrDO^UFD?rul(Czw%O4hZpqZD=v65hLa03%(~fC zQ>I0;tZxl%qI6z$I%*pt%ZIwW(byS|o|DqfoTW=F!$ez8Ib*#L3wDPqH{O-sZC@zB z3N`bUC!C6PC+9fKE7Cmnn|A(Q%HStoUg3kfDJG=wAGU{u`rU~pa8(vxdZ{Ga5r>M=z!;i zSpa~G4FH%k?Hklw&%(sW(8d;FZj@-#h#J)8tCLvVM-rAzDf<_JEw$zssn`lmYvcXW z)KUiq$f&e#Zcd*v7Tg~p#GB~u+NxOYKZf~JpeXf_clKIbYbrtl;@OQdUtG=Nj?XRZ zB?bl#K`NY6&wMVsKb%{wF^!#J*x0T5kW&3ey1Y1+KFFp;p;q%oYFun`;;dsHlGtiRp)#wof3!M^G9B<=7 zoq?qOj5tl6B+dv&aY=8LH2SDaH(ukDE?VjHbdmRHzzIdFiUMAGHK)pT-Wv(fdwY!3 zlL<5Wub!urTp-^+e)6|IA*VM%W%~>tCcS^XVN-PNDy*0&=73>_tOv{z6O)XJUtssNL{92BI zbJ?Ztb%85O_1GN#sy-pnvyB+Qav0@Ckx)s~xS%;Q0dZBw`8qG|b0xe~RB!5Ne^mYK zY7`cU#*%SEk}+#uEG9KgzS$CJxoqplQFehvHyH#sk$&<;0hj7}D^n25f$fvCw;S%9 zLcTAD@w+$voW*pP#<~v);{ifO-frD6dwm->U5|{kK6x*ug-PB!z uhXTyI0008uK*Y(nC{qX(6zHR_HNpP9TA8wgnHY|(>mvvNxVL^G0N`&0JcX+O literal 0 HcmV?d00001 diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/files/ProvisioningTestBundle_1.0.1.201203030001-APAR0002.jar b/dev/com.ibm.ws.kernel.boot_fat/publish/files/ProvisioningTestBundle_1.0.1.201203030001-APAR0002.jar new file mode 100755 index 0000000000000000000000000000000000000000..06f522ad2cf32c8d365b29e0af186a166b0583ef GIT binary patch literal 2337 zcmai02{@E%8~%hbh>JnSl8mj6lNn`fhwMwTXBQAzUSt3lOEYp#Fmq>?WXz_RHKks+F&+}f_ci+!M)!RCJ z4&cp<4#XgQ-7yH8AEJ17pw5N0lop= zU&&wqe-Wz(sWUuBU{{R`wg2%3XAmDBUmKXyK@C$jP?cx0EF=hOtZ^bwMO-<^j_`Rw2$%{ZImU}0 zjT1`ENkOmiAGp_dfLFaw`8f2NTT_;8Q>D5=;ZM08bC)0W@b^V`nF=kPj4VGDjrz^` zHwEH|l3}lg$1NFH&Ctg)LoGF6c6_@y%L7Nt|PuU1M(3lZ*FljHT;UPx}jLGvH zVkM$*uAdqk)O|5t(&-TH(%q`;Fu{S)iFzA@g2@%tgG)URYBX!po<2KrQ3Yf|uFP0b zN61)Yriz!kD^6M6hjB0B7wTb(?b7?`Or}(K>f1es`DTUgH4TB_?xZyD4s2dfZhko; z8Dl+^6yF(F9*q#I{bP?d#iW>?9X5_D<*ACX5+^nyy))^4GN>6L_!RYp7Q&AxPZ}5> zIoZF+Feb)QE#Aj5c%Xi7s-(tvP8&#QP}EmmwgU^Wu4Flf_9&`Q43a^YrIHpeMDkdFEso(B!j8sA^KSDh+eLmS3F zN$JJ?bPT6wP-hZbz*|N0(xL6o;4@H5%1Kjo);SRtqBYS;ckW6Olk`0l>VVN4)NRj? zc_{vC%`uVQQQN~eK=n-@UcaiKl4O1V()Jx3No$sb4kHP_%#iO4CrppY`GC$hTX$%- z1rmDs8Z%`_Vuj{a^4~!mlyU}R53INmh-jK8RRgROjFbx#)k3dN}0f25&W zRijWxDaFM8PeX^-%P9BwkI}k?lwg&L{7>|SjpW~PD=pLoV#3uRl0&6-vCBXKJo&Nf zdOHEF(UMP7QEp^dFC=;xPl!$EV{%0_wBADsYg}X7y?Bmv^Fo_&+`PEg>>IQP720&` z$E}f#9h9@qGN=eefdG&7CzR;W8F?MzG*fm_NUHVd=_oJwoP%i1`dH=lr*n6sB$@;& zlaD62*XN#^RiUE=%_$}2Q;>R(B>^5suTc;bJ*-ymZXQ<_oItO4i#rva?GycUuw(VI zsH1J;nT9C5B0*)gl2kMfmnx`u;Mgx#PpFNXH|p~7%P;e}RhVeA;X;}rlN_#B27wEY zD@$y!v4#!LrhoyU+AT+m^n0~~;*F-l*_%*q6@-T?q#<`Nj_!iVcY4Q5Pa_5gqg z2LP~U+E=KhzLlAYu^kF-Y4RVGZQv_qf%B$JUDC4hC6p7l@GH-Wf{Xwq`*8vC{gaciW>IQS`K@`bkiRSh-(iQM`zb)G^5Naqse9jG7BrFe<(KmZ2Sc^51VAv?R^>P z{l+(^ljN8T`4N6OC85Z-8g$!4!iuCztnGrsCsv= z-9ax(a39T(IyAN@!9h+eoKI#qk#ezWuJzzVB_3E3#c(9JM}#Dw0Xvf|`Rq$ubIRHq zZ@~dmiB1R!)P`y(5riO}PRtKM$2@Z$<#UR!FWDo@USwVOG9+53uZLMy|YY-k}uCVNA5arvg-feuRr6 zvbtPqMOGuWa-gV|k7m8x74bsXNPTqFatWV5>?%DIn@fMc#+*MKL3n;VCf_fzM|f1T zN1hi{k{7J7(K!mcboS9muyB;@(4~GQNW4oaFG&2h%W$Iv=a+wA0l!#9ks9 z;pjAVOco+MD5qJ##S&)5AYwv1N^h$uhRs<7{M}eD);G`f%vnmuVq>$X*!Bo-_0R5} zxZR5apIh>qL;je>^2qJQVkvCyFRU%c{4tT`ncIs+wBFo1h+iG_8-F(s{l>qrEB`x3 z{ZedqPu(siy_x>|@5R1zSk`;x0e&p(?b@uEzNz1@+TE5p+aBGmPqLfPJHiS0Ia(Jzy?48DbW32&B0W*)OjQQx18UyjX5WXh2h$~R@ndmviTzc0RI5k;e-wV literal 0 HcmV?d00001 diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/files/ProvisioningTestBundle_1.0.1.201204040001-TestAPAR0001.jar b/dev/com.ibm.ws.kernel.boot_fat/publish/files/ProvisioningTestBundle_1.0.1.201204040001-TestAPAR0001.jar new file mode 100755 index 0000000000000000000000000000000000000000..4d11853da9255e9fcb63642c07cdce9733fd176a GIT binary patch literal 2331 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 literal 0 HcmV?d00001 diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/files/ProvisioningTestBundle_1.0.2.jar b/dev/com.ibm.ws.kernel.boot_fat/publish/files/ProvisioningTestBundle_1.0.2.jar new file mode 100755 index 0000000000000000000000000000000000000000..c532b85b7843a32437fde6428368dd894060fd21 GIT binary patch literal 2299 zcmWIWW@h1H0D-NE1rA^al;C7wVeoYgan$wnbJPEKih&^js8j?f$-%(gT02vd;YA_qaW zvm2vsGxu!R`|jPXj{Wa%GzjypJ(M|PX6@&Ddp^c2+v1o!H+}{0$`Xco1+#la|DE() zY&>x$kA_;cOoLIhP{(~Uk?1RjXJ4Cs&C;}HTI-kkEzw6gpZvZcytnN4vYQgmMcmKn z9J+F;Er9<(e9yFhm(Oqg+$MNtDcgIwJ?{>DWsBoq_Sv)~W__@o&teJL|1(&$mK7)p z%Nz(=-E@j^O5Sy!Usp;p_f1l`XDD~EWtLI&)N9s80wJsqG|bN&(%R6&R@VMtv7W|} z%^3l+wSGG>X8k)II_*bdf|TYp6Y2A>@BE+fZ=aeOm#*lgX&ei^SXetPBsRLwP14!K z&++Ke$;IiO%eItGGrDtH*FUIATT9w(mb(0ud*;%@y_b@n^z=W~t2)#w7TnT#=}*|S z?u_dyYFgG=x8CKbGDjuuE;-Qb|8Ev=gLqs-mX`HT1CL{DbBdTHUuCtben>Ca#Xq+jMpQy0f=f30)JZ|3gZ#rNdyWY38biV5lNUKS|h9BQ=S;*>nM zNAqjqYG~p|I4n=`l<~gHSv%jH6!mja>zR7e^wWi3 zl?5#;?VBz>7Wz}r9w?_=?7Mc_!dB*+cddWlT66k(RJ@h^<#Sre9>f=_$jijo)7>`0BRE628MR}+YutZ!6p)}D|XzRcdYg7yfg3A4pje8=rU$3ImZ5Ap~U~qvzJ}2 zKI?PtX7SH|?|+fxu@AgetknPa+=!I`8CaN>*XWZz{ zds8|mqD{)EMYw-%U-EB0`8C(%xy`Q`ct}i7JUlJ%@Md$T<(l(OedyeKh3{JJMR(yZ zL6sY$YC|GpBGqO*)pfpVk+Mihar=W`aSx7e=U{F9x~wYl&+HE)w?+O{r1u z;+b<`H_KYZM_iYM{6y8tZ=Y>0xYW=l6RlC*xMIufQo(!0ul5BvEqVRJRQ=19UE3{p zOgM4Du)&zkZQ%BR9!&*OUhU%PqFP{e8{(RkaM)O&puPxWPB(m;qk$W-YV7nIcbq?j$ zyNt8etdzdaThmkNH~Vr{XTn^A-PfsHCt?)N;O=6$*!aIM?AXW7yE z1s7+tL$N zbJU6L}H8pYwcmiO&XE^gW_6}H`0^y>3Komp)A4u8LMYtz{| z%9&4WGVec~a70Gpp-H#ZyM@ahw!eL$lEGGY#Q&7#@%-+qyoaVLKW!HNXuSBDP`K{g z`%Ud^=N`@Ji~q2?&3$%Uj(F06K-J}2uS`2X@r=vHoTmr2np!Nk)9rH$-R2yA=UYfp z+pk*t(dmBa;ZYp2JrAsX(Z z5mc%|07&BsRE_X57NH+oDT~m51FL?tG8bkT_EHyOm;#Uz1(wCI`UB_-sAEtJLo0&= Tyjj^m`q_c-C$P=(2FwEhqUv&` literal 0 HcmV?d00001 diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/files/ProvisioningTestBundle_1.0.99.jar b/dev/com.ibm.ws.kernel.boot_fat/publish/files/ProvisioningTestBundle_1.0.99.jar new file mode 100755 index 0000000000000000000000000000000000000000..0895ca97ce1b8c1c149ada802e5933fcc226ecc3 GIT binary patch literal 2302 zcmai#3pkW%8^>SK#Ay03$~fehLoQ<+lN>@!tn(TXwj3fOhsl_%#vAlpe5C3w@-0*t#Gtw7&Hk9C%!}}UMhc$A zkzHdYv|^wsxye3j2V@@h%LwZAYgoc=do|v2Y^3U$6&pN1}fA5q~( zK%MnCtCTefKh<~q!hLx;+SrG4W6d;vUShk1oYT*Lnzb6h`Zdg9BaDnl<%Ip@`X_vk zfkhjT9ktp+4owfT_PT&o3i7uzwE_;YQF(KWP@}E6wkOk< n(H#zkpGwd#g zl3#&H46+|fi0z1}ARxqRe%WK#i7aL3;HL3q;Hn#T5?KtLi<#^IdDJ{qeU|mi01=R- zNFJG<{C@DwfJIg`%Vs5J01OKlu9AM0)exu3JHW3%9OlV>SRy$9iA;>J%jpe>_srFJ zGSK&fyU~RAfxDF})#9b6N314;mqs1>Nd}1znt!_2ox|tm1TxlJB!Yd^Z%rRA+poux zpmmKC8P>-KjW^$84$B$3Aw4d9>(9{LJej**dE;p;!L;_-lDu?KM+n9bzau4%>RqMw2^ofzuL@N%8L6LLw2DWmYyFe zP*1G$TyH1&9B;V;V#`c-&w`q=@Dj-R=k0>=A@D;spfpL%bVZ zk1Gw?_H`{03})vg4|&v&szSjR)*Ctr*m*_cthot=H&E#otsf%&)E8aEXzQ=2ciI+< zBPAP!sEJx}-gJuFf;QVn*t+vk#jFVZ!m<$9)o%&}^BF%z_qL8HzZ}P=d&RgBa{LKx zqs;g5Vy=#ibM=u#Rg(4sm0U8dE?rRh*mY2xPO6D{ZQku4kYDb9zv!mJ#(DC59@*s% z6~kX-sUf++!)-R;%>o91YA=k**5>0P0Pq2}7ARA=l^qhX&IEu@eTg3s#o< zDzVV$>b=f0p-ttI;_jTroc`PW`nr*ah>LYJ_hx~YgHI=azq0n=Ic!QR`I#Dn!%Q-t zi>iac|1Ofb^fp$wlL&ezJybSTLm7;oj)WX;oy!pGRYCqClWx+i<#ChG$Th&Ztuo4n zc1fOaB1}J0G3s9++`6!Bv9Dk0i>t~IK4%^kCZzjUuv$aZu-s~~p!mdD-D2BJLK;uN zheB0!F>pDvOpN%EzdTo^aS5925!1yEs~IC}twOka z0tWFL=eucmdEztw0D{BS(Lfs=FiBWarUSiP!wa9_hZatksVH}sS=peja6+F@GY|L^ z=X!X>jNj`@0tlT74l1@Mz*1P!bCO?+)3@Jxj6D`6bK>3X^XXB_{j&@6QbsFlIGuaN z19O$c-lN#?@Y%VB+LjW<1`FLfe~D&Ilp?Q$E&5{9M#ofNT#0I1a?Byvx#^mygS92T z{#J7{F^x + + + + + webProfile-6.0 + + + + + diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/files/interimFixesServer.xml b/dev/com.ibm.ws.kernel.boot_fat/publish/files/interimFixesServer.xml new file mode 100755 index 00000000000..12fde62f6aa --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/files/interimFixesServer.xml @@ -0,0 +1,12 @@ + + + + + + jsp-2.2 + provisioningInterimFixesTest-1.0 + + + + + diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/files/marker b/dev/com.ibm.ws.kernel.boot_fat/publish/files/marker new file mode 100755 index 00000000000..74fd67bb1d0 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/files/marker @@ -0,0 +1 @@ +A marker file to put in the workarea in the fingerprint clean tests. \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/files/provisioningInterimFixTest-1.0.mf b/dev/com.ibm.ws.kernel.boot_fat/publish/files/provisioningInterimFixTest-1.0.mf new file mode 100755 index 00000000000..ebf1245cd20 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/files/provisioningInterimFixTest-1.0.mf @@ -0,0 +1,6 @@ +Subsystem-ManifestVersion: 1.0 +Subsystem-SymbolicName: provisioningInterimFixTest-1.0;visibility:=public +Subsystem-Version: 1.0.0 +Subsystem-Content: ProvisioningInterimFixesTestBundle4; version="[1,1.0.100)" +Subsystem-Type: osgi.subsystem.feature +IBM-Feature-Version: 2 diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/files/provisioningInterimFixesTest-1.0.mf b/dev/com.ibm.ws.kernel.boot_fat/publish/files/provisioningInterimFixesTest-1.0.mf new file mode 100755 index 00000000000..ecf49f7ebd6 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/files/provisioningInterimFixesTest-1.0.mf @@ -0,0 +1,9 @@ +Subsystem-ManifestVersion: 1.0 +Subsystem-SymbolicName: provisioningInterimFixesTest-1.0;visibility:=public +Subsystem-Version: 1.0.0 +Subsystem-Content: ProvisioningInterimFixesTestBundle1; version="[1,1.0.100)", + ProvisioningInterimFixesTestBundle2; version="[1,1.0.100)", + ProvisioningInterimFixesTestBundle3; version="[1,1.0.100)", + ProvisioningInterimFixesTestBundle4; version="[1,1.0.100)" +Subsystem-Type: osgi.subsystem.feature +IBM-Feature-Version: 2 diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/files/provisioningTest-1.0.mf b/dev/com.ibm.ws.kernel.boot_fat/publish/files/provisioningTest-1.0.mf new file mode 100755 index 00000000000..9f6781da6bc --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/files/provisioningTest-1.0.mf @@ -0,0 +1,6 @@ +Subsystem-ManifestVersion: 1 +Subsystem-SymbolicName: provisioningTest-1.0; visibility:=public +Subsystem-Version: 1.0.0 +Subsystem-Content: ProvisioningTestBundle; version="[1,1.0.100)" +Subsystem-Type: osgi.subsystem.feature +IBM-Feature-Version: 2 \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/files/service.fingerprint b/dev/com.ibm.ws.kernel.boot_fat/publish/files/service.fingerprint new file mode 100755 index 00000000000..1fc7a99648a --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/files/service.fingerprint @@ -0,0 +1 @@ +A test fingerprint file for mocking the service.fingerprint - in response to APAR 117401 \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/files/singleInterimFixServer.xml b/dev/com.ibm.ws.kernel.boot_fat/publish/files/singleInterimFixServer.xml new file mode 100755 index 00000000000..3139c91691e --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/files/singleInterimFixServer.xml @@ -0,0 +1,12 @@ + + + + + + jsp-2.2 + provisioningInterimFixTest-1.0 + + + + + diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/files/test_template_option/extensions/templateTestAbsolute.properties b/dev/com.ibm.ws.kernel.boot_fat/publish/files/test_template_option/extensions/templateTestAbsolute.properties new file mode 100755 index 00000000000..bc4bf180ed4 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/files/test_template_option/extensions/templateTestAbsolute.properties @@ -0,0 +1 @@ +com.ibm.websphere.productInstall= \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/files/test_template_option/extensions/templateTestRelative.properties b/dev/com.ibm.ws.kernel.boot_fat/publish/files/test_template_option/extensions/templateTestRelative.properties new file mode 100755 index 00000000000..2f12f144323 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/files/test_template_option/extensions/templateTestRelative.properties @@ -0,0 +1 @@ +com.ibm.websphere.productInstall=wlpExt (&+) diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/files/test_template_option/templates/clients/template2/client.xml b/dev/com.ibm.ws.kernel.boot_fat/publish/files/test_template_option/templates/clients/template2/client.xml new file mode 100755 index 00000000000..a07161e7dde --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/files/test_template_option/templates/clients/template2/client.xml @@ -0,0 +1,7 @@ + + + + javaeeClient-7.0 + + + diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/files/test_template_option/templates/servers/templateTest/server.xml b/dev/com.ibm.ws.kernel.boot_fat/publish/files/test_template_option/templates/servers/templateTest/server.xml new file mode 100755 index 00000000000..4f3c32e2ec9 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/files/test_template_option/templates/servers/templateTest/server.xml @@ -0,0 +1,14 @@ + + + + + jsp-2.2 + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/resources/looseConfig/earContent/META-INF/application.xml b/dev/com.ibm.ws.kernel.boot_fat/publish/resources/looseConfig/earContent/META-INF/application.xml new file mode 100755 index 00000000000..3c8c2abda26 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/resources/looseConfig/earContent/META-INF/application.xml @@ -0,0 +1,16 @@ + + + TestMyEAR + + + TestWeb1.war + TestMyWeb1 + + + + + TestWeb0.war + TestMyWeb0 + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/resources/looseConfig/testUtil/classes/META-INF/MANIFEST.MF b/dev/com.ibm.ws.kernel.boot_fat/publish/resources/looseConfig/testUtil/classes/META-INF/MANIFEST.MF new file mode 100755 index 00000000000..254272e1c07 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/resources/looseConfig/testUtil/classes/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Class-Path: + diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/resources/looseConfig/testWeb0/WebContent/META-INF/MANIFEST.MF b/dev/com.ibm.ws.kernel.boot_fat/publish/resources/looseConfig/testWeb0/WebContent/META-INF/MANIFEST.MF new file mode 100755 index 00000000000..59499bce4a2 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/resources/looseConfig/testWeb0/WebContent/META-INF/MANIFEST.MF @@ -0,0 +1,2 @@ +Manifest-Version: 1.0 + diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/resources/looseConfig/testWeb0/WebContent/index.jsp b/dev/com.ibm.ws.kernel.boot_fat/publish/resources/looseConfig/testWeb0/WebContent/index.jsp new file mode 100755 index 00000000000..7c276b94a38 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/resources/looseConfig/testWeb0/WebContent/index.jsp @@ -0,0 +1,12 @@ +<%@ page language="java" contentType="text/html; charset=ISO-8859-1" + pageEncoding="ISO-8859-1"%> + + + + +Welcome + + + Hi, this is web0. + + \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/resources/looseConfig/testWeb1/WebContent/META-INF/MANIFEST.MF b/dev/com.ibm.ws.kernel.boot_fat/publish/resources/looseConfig/testWeb1/WebContent/META-INF/MANIFEST.MF new file mode 100755 index 00000000000..59499bce4a2 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/resources/looseConfig/testWeb1/WebContent/META-INF/MANIFEST.MF @@ -0,0 +1,2 @@ +Manifest-Version: 1.0 + diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/resources/looseConfig/testWeb1/WebContent/index.jsp b/dev/com.ibm.ws.kernel.boot_fat/publish/resources/looseConfig/testWeb1/WebContent/index.jsp new file mode 100755 index 00000000000..7c276b94a38 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/resources/looseConfig/testWeb1/WebContent/index.jsp @@ -0,0 +1,12 @@ +<%@ page language="java" contentType="text/html; charset=ISO-8859-1" + pageEncoding="ISO-8859-1"%> + + + + +Welcome + + + Hi, this is web0. + + \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/resources/looseConfig/utils/classes/META-INF/MANIFEST.MF b/dev/com.ibm.ws.kernel.boot_fat/publish/resources/looseConfig/utils/classes/META-INF/MANIFEST.MF new file mode 100755 index 00000000000..254272e1c07 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/resources/looseConfig/utils/classes/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Class-Path: + diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/servers/ServerStartAsServiceTest/bootstrap.properties b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/ServerStartAsServiceTest/bootstrap.properties new file mode 100644 index 00000000000..4f1ae5a2e10 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/ServerStartAsServiceTest/bootstrap.properties @@ -0,0 +1 @@ +bootstrap.include=../testports.properties diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/servers/ServerStartAsServiceTest/dropins/snoop.war b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/ServerStartAsServiceTest/dropins/snoop.war new file mode 100644 index 0000000000000000000000000000000000000000..eff33454efa15a3564a3f9e4c3a321d2c9e1f912 GIT binary patch literal 7238 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 literal 0 HcmV?d00001 diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/servers/ServerStartAsServiceTest/server.xml b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/ServerStartAsServiceTest/server.xml new file mode 100644 index 00000000000..1d8a79716f1 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/ServerStartAsServiceTest/server.xml @@ -0,0 +1,12 @@ + + + + jsp-2.2 + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.bvt/apps/Apps Loose Web.war.xml b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.bvt/apps/Apps Loose Web.war.xml new file mode 100755 index 00000000000..5c1bcb1587e --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.bvt/apps/Apps Loose Web.war.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.bvt/apps/AppsLooseWeb-InvalidRelPaths.war.xml b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.bvt/apps/AppsLooseWeb-InvalidRelPaths.war.xml new file mode 100755 index 00000000000..41d0c37d096 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.bvt/apps/AppsLooseWeb-InvalidRelPaths.war.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.bvt/apps/AppsLooseWeb-RelPaths.war.xml b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.bvt/apps/AppsLooseWeb-RelPaths.war.xml new file mode 100755 index 00000000000..dee07e12b8f --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.bvt/apps/AppsLooseWeb-RelPaths.war.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.bvt/apps/AppsLooseWeb-Signed.war.xml b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.bvt/apps/AppsLooseWeb-Signed.war.xml new file mode 100755 index 00000000000..bcbd83212b8 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.bvt/apps/AppsLooseWeb-Signed.war.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + arbitrary text between tags should not cause package command to fail + \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.bvt/apps/AppsLooseWeb.war.xml b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.bvt/apps/AppsLooseWeb.war.xml new file mode 100755 index 00000000000..5c1bcb1587e --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.bvt/apps/AppsLooseWeb.war.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.bvt/bootstrap.properties b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.bvt/bootstrap.properties new file mode 100755 index 00000000000..8de793643ea --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.bvt/bootstrap.properties @@ -0,0 +1,5 @@ +com.ibm.ws.logging.trace.specification=*=info=enabled:bootstrap=all=enabled +com.ibm.ws.logging.trace.max.files=30 + +# com.ibm.ws.kernel.boot.env.bvt needs testports.properties for HTTP +#bootstrap.include=../testports.properties \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.bvt/dropins/DropinsLooseWeb.ear.xml b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.bvt/dropins/DropinsLooseWeb.ear.xml new file mode 100755 index 00000000000..4522aedfe5a --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.bvt/dropins/DropinsLooseWeb.ear.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.bvt/server.xml b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.bvt/server.xml new file mode 100755 index 00000000000..8b22ca755eb --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.bvt/server.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.classpath.fat/.gitignore b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.classpath.fat/.gitignore new file mode 100644 index 00000000000..2b09f7ba1e1 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.classpath.fat/.gitignore @@ -0,0 +1 @@ +/apps diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.classpath.fat/bootstrap.properties b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.classpath.fat/bootstrap.properties new file mode 100644 index 00000000000..6fe952051a3 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.classpath.fat/bootstrap.properties @@ -0,0 +1,5 @@ +com.ibm.ws.logging.trace.specification=*=info=enabled:bootstrap=all=enabled +com.ibm.ws.logging.trace.max.files=1 +com.ibm.ws.logging.console.log.level=INFO + +bootstrap.include=../testports.properties \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.classpath.fat/server.xml b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.classpath.fat/server.xml new file mode 100644 index 00000000000..98604eaa3fe --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.classpath.fat/server.xml @@ -0,0 +1,9 @@ + + + + + ejbLite-3.2 + + + + diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.commandport.disabled.fat/.gitignore b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.commandport.disabled.fat/.gitignore new file mode 100644 index 00000000000..f3f483d82c0 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.commandport.disabled.fat/.gitignore @@ -0,0 +1 @@ +/dropins diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.commandport.disabled.fat/bootstrap.properties b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.commandport.disabled.fat/bootstrap.properties new file mode 100755 index 00000000000..831b15d60ef --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.commandport.disabled.fat/bootstrap.properties @@ -0,0 +1,2 @@ +command.port=-1 +bootstrap.include=../testports.properties diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.commandport.disabled.fat/server.xml b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.commandport.disabled.fat/server.xml new file mode 100755 index 00000000000..94fb81cd155 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.commandport.disabled.fat/server.xml @@ -0,0 +1,6 @@ + + + servlet-3.0 + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.commandport.enabled.fat/server.xml b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.commandport.enabled.fat/server.xml new file mode 100755 index 00000000000..dd543055eaf --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.commandport.enabled.fat/server.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.env.bvt/bootstrap.properties b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.env.bvt/bootstrap.properties new file mode 100755 index 00000000000..fe859a24711 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.env.bvt/bootstrap.properties @@ -0,0 +1,2 @@ +com.ibm.ws.logging.trace.specification=*=info=enabled +bootstrap.include=../testports.properties \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.env.bvt/server.xml b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.env.bvt/server.xml new file mode 100755 index 00000000000..a0f06d9e4b9 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.env.bvt/server.xml @@ -0,0 +1,11 @@ + + + + + + + httpservice-2.2 + fileinstall-1.0 + + + diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.pause.resume.fat/server.xml b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.pause.resume.fat/server.xml new file mode 100755 index 00000000000..dd543055eaf --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.pause.resume.fat/server.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.serverstart.fat/server.xml b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.serverstart.fat/server.xml new file mode 100755 index 00000000000..dd543055eaf --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.boot.serverstart.fat/server.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.bootstrap.fat/bootstrap.properties b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.bootstrap.fat/bootstrap.properties new file mode 100755 index 00000000000..14294e57943 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.bootstrap.fat/bootstrap.properties @@ -0,0 +1,5 @@ +com.ibm.ws.logging.trace.specification=*=info=enabled:bootstrap=all=enabled +com.ibm.ws.logging.trace.max.files=30 +com.ibm.ws.logging.console.log.level=INFO + +bootstrap.include=../testports.properties \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.bootstrap.fat/bootstrap.properties.hpel b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.bootstrap.fat/bootstrap.properties.hpel new file mode 100755 index 00000000000..c5ee4367a12 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.bootstrap.fat/bootstrap.properties.hpel @@ -0,0 +1,7 @@ +com.ibm.ws.logging.trace.specification=*=info=enabled:bootstrap=all=enabled +com.ibm.ws.logging.trace.max.files=30 +com.ibm.ws.logging.console.log.level=INFO + +websphere.log.provider=binaryLogging-1.0 + +bootstrap.include=../testports.properties \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.bootstrap.fat/server.xml b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.bootstrap.fat/server.xml new file mode 100755 index 00000000000..8c7a1920c7f --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.bootstrap.fat/server.xml @@ -0,0 +1,4 @@ + + + + diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.bootstrap.output.fat/bootstrap.properties b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.bootstrap.output.fat/bootstrap.properties new file mode 100755 index 00000000000..308b99268d4 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.bootstrap.output.fat/bootstrap.properties @@ -0,0 +1,2 @@ +com.ibm.ws.logging.console.log.level=OFF +bootstrap.include=../testports.properties \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.bootstrap.output.fat/server.xml b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.bootstrap.output.fat/server.xml new file mode 100755 index 00000000000..4163d65d362 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.bootstrap.output.fat/server.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.provisioning.fat.fingerprint/bootstrap.properties b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.provisioning.fat.fingerprint/bootstrap.properties new file mode 100755 index 00000000000..31f32c6fd52 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.provisioning.fat.fingerprint/bootstrap.properties @@ -0,0 +1 @@ +bootstrap.include=../testports.properties \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.provisioning.fat.fingerprint/server.xml b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.provisioning.fat.fingerprint/server.xml new file mode 100755 index 00000000000..7b298238aa6 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.provisioning.fat.fingerprint/server.xml @@ -0,0 +1,9 @@ + + + + + + jsp-2.2 + + + diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.provisioning.fat/bootstrap.properties b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.provisioning.fat/bootstrap.properties new file mode 100755 index 00000000000..31f32c6fd52 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.provisioning.fat/bootstrap.properties @@ -0,0 +1 @@ +bootstrap.include=../testports.properties \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.provisioning.fat/server.xml b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.provisioning.fat/server.xml new file mode 100755 index 00000000000..13f01736f3d --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.provisioning.fat/server.xml @@ -0,0 +1,12 @@ + + + + + + jsp-2.2 + provisioningTest-1.0 + + + + + diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.shutdown.fat/.gitignore b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.shutdown.fat/.gitignore new file mode 100644 index 00000000000..f3f483d82c0 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.shutdown.fat/.gitignore @@ -0,0 +1 @@ +/dropins diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.shutdown.fat/bootstrap.properties b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.shutdown.fat/bootstrap.properties new file mode 100755 index 00000000000..7ff78ec74f8 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.shutdown.fat/bootstrap.properties @@ -0,0 +1,2 @@ +com.ibm.ws.logging.trace.specification=*=info=enabled:bootstrap=all=enabled +bootstrap.include=../testports.properties diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.shutdown.fat/server.xml b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.shutdown.fat/server.xml new file mode 100755 index 00000000000..0d3471bf0d8 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.ws.kernel.shutdown.fat/server.xml @@ -0,0 +1,7 @@ + + + servlet-3.0 + + + + diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.wsspi.kernel.embeddable.add.product.extension.fat/bootstrap.properties b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.wsspi.kernel.embeddable.add.product.extension.fat/bootstrap.properties new file mode 100755 index 00000000000..2e3faa500d3 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.wsspi.kernel.embeddable.add.product.extension.fat/bootstrap.properties @@ -0,0 +1,2 @@ +com.ibm.ws.logging.trace.specification=*=info=enabled +bootstrap.include=../testports.properties diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.wsspi.kernel.embeddable.add.product.extension.fat/dropins/simpleApp.war/index.jsp b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.wsspi.kernel.embeddable.add.product.extension.fat/dropins/simpleApp.war/index.jsp new file mode 100755 index 00000000000..bdb6c10537e --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.wsspi.kernel.embeddable.add.product.extension.fat/dropins/simpleApp.war/index.jsp @@ -0,0 +1,3 @@ + +
Hi, my name is <%=request.getParameter("name")%>
+ \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.wsspi.kernel.embeddable.add.product.extension.fat/producttest/lib/com.ibm.ws.prodtest.internal_1.0.jar b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.wsspi.kernel.embeddable.add.product.extension.fat/producttest/lib/com.ibm.ws.prodtest.internal_1.0.jar new file mode 100755 index 0000000000000000000000000000000000000000..85a6fa4f6adfbc8f99da9ede95bba524b8923460 GIT binary patch literal 1719 zcmWIWW@Zs#U|`^25c7z2w0L)CeK->X!(nCy29T()Ylx$+r=Od?ucM!*n`>~0p0As4 z@WH%C1_FECPucfatVwWPq%vU(%SNFKdETK>S1!Cu^j9-`uvU2aHs|U4?-w$a98Hxt zzh~z6XQ`fE`%-UJBQ(nh-#4c7@^)f5U%zek{Wd?gA9jCpQRJthDI(zZF zt_P8JJ8zm_mNuH+e8*s}cHGQk%u^?AITrQpx&pWLxd#n~GEtL#qWZV=o}S#S$M(zW zldxt)R^(+;smL8e^aV$uU2$Uk1|@z1YpM^}h-{43e-+h4eT z)4clo$C(|Ur2~HjuD@*m{`d2Mp1?BAtQ5AgiJfbrp6@uv{d>hur`eOca&|mmyPh#Y zQhIU!#8|7BCHqVLcb;UnobYDbb=%(Gja=$`9KeM5urSIInD*d+6Ug!pcJ~A)L}rEnZ*~rl959)J0d9?aKzX>v97BUV zeNuD_A?wafElDh?EJ!8E1QwtP$@#e?=>d5Sq$e|pG=1Di`pSz*vQiXPYe{BqYD#KF zW(i4#$l)?1Gp{7IC@(Pwt7(i(BH(fcd+7r-l7W#y0Ym`-wz4R|8)5=-vVo-wP_jXQ zPM|P6E#T7zN;C*?2w59A3E|TVN-{_QSct-{geM?;`auZ>0i1yPK}i9h4scF@Ybk^3 z03{xLx + + + + + jsp-2.2 + productA:prodtest-1.0 + + + + + diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.wsspi.kernel.embeddable.add.product.extension.multiple.fat/bootstrap.properties b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.wsspi.kernel.embeddable.add.product.extension.multiple.fat/bootstrap.properties new file mode 100755 index 00000000000..2e3faa500d3 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.wsspi.kernel.embeddable.add.product.extension.multiple.fat/bootstrap.properties @@ -0,0 +1,2 @@ +com.ibm.ws.logging.trace.specification=*=info=enabled +bootstrap.include=../testports.properties diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.wsspi.kernel.embeddable.add.product.extension.multiple.fat/dropins/simpleApp.war/index.jsp b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.wsspi.kernel.embeddable.add.product.extension.multiple.fat/dropins/simpleApp.war/index.jsp new file mode 100755 index 00000000000..bdb6c10537e --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.wsspi.kernel.embeddable.add.product.extension.multiple.fat/dropins/simpleApp.war/index.jsp @@ -0,0 +1,3 @@ + +
Hi, my name is <%=request.getParameter("name")%>
+ \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.wsspi.kernel.embeddable.add.product.extension.multiple.fat/producttest/lib/com.ibm.ws.prodtest.internal_1.0.jar b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.wsspi.kernel.embeddable.add.product.extension.multiple.fat/producttest/lib/com.ibm.ws.prodtest.internal_1.0.jar new file mode 100755 index 0000000000000000000000000000000000000000..85a6fa4f6adfbc8f99da9ede95bba524b8923460 GIT binary patch literal 1719 zcmWIWW@Zs#U|`^25c7z2w0L)CeK->X!(nCy29T()Ylx$+r=Od?ucM!*n`>~0p0As4 z@WH%C1_FECPucfatVwWPq%vU(%SNFKdETK>S1!Cu^j9-`uvU2aHs|U4?-w$a98Hxt zzh~z6XQ`fE`%-UJBQ(nh-#4c7@^)f5U%zek{Wd?gA9jCpQRJthDI(zZF zt_P8JJ8zm_mNuH+e8*s}cHGQk%u^?AITrQpx&pWLxd#n~GEtL#qWZV=o}S#S$M(zW zldxt)R^(+;smL8e^aV$uU2$Uk1|@z1YpM^}h-{43e-+h4eT z)4clo$C(|Ur2~HjuD@*m{`d2Mp1?BAtQ5AgiJfbrp6@uv{d>hur`eOca&|mmyPh#Y zQhIU!#8|7BCHqVLcb;UnobYDbb=%(Gja=$`9KeM5urSIInD*d+6Ug!pcJ~A)L}rEnZ*~rl959)J0d9?aKzX>v97BUV zeNuD_A?wafElDh?EJ!8E1QwtP$@#e?=>d5Sq$e|pG=1Di`pSz*vQiXPYe{BqYD#KF zW(i4#$l)?1Gp{7IC@(Pwt7(i(BH(fcd+7r-l7W#y0Ym`-wz4R|8)5=-vVo-wP_jXQ zPM|P6E#T7zN;C*?2w59A3E|TVN-{_QSct-{geM?;`auZ>0i1yPK}i9h4scF@Ybk^3 z03{xLxX!(nCy29T()Ylx$+r=Od?ucM!*n`>~0p0As4 z@WH%C1_FECPucfatVwWPq%vU(%SNFKdETK>S1!Cu^j9-`uvU2aHs|U4?-w$a98Hxt zzh~z6XQ`fE`%-UJBQ(nh-#4c7@^)f5U%zek{Wd?gA9jCpQRJthDI(zZF zt_P8JJ8zm_mNuH+e8*s}cHGQk%u^?AITrQpx&pWLxd#n~GEtL#qWZV=o}S#S$M(zW zldxt)R^(+;smL8e^aV$uU2$Uk1|@z1YpM^}h-{43e-+h4eT z)4clo$C(|Ur2~HjuD@*m{`d2Mp1?BAtQ5AgiJfbrp6@uv{d>hur`eOca&|mmyPh#Y zQhIU!#8|7BCHqVLcb;UnobYDbb=%(Gja=$`9KeM5urSIInD*d+6Ug!pcJ~A)L}rEnZ*~rl959)J0d9?aKzX>v97BUV zeNuD_A?wafElDh?EJ!8E1QwtP$@#e?=>d5Sq$e|pG=1Di`pSz*vQiXPYe{BqYD#KF zW(i4#$l)?1Gp{7IC@(Pwt7(i(BH(fcd+7r-l7W#y0Ym`-wz4R|8)5=-vVo-wP_jXQ zPM|P6E#T7zN;C*?2w59A3E|TVN-{_QSct-{geM?;`auZ>0i1yPK}i9h4scF@Ybk^3 z03{xLx + + + + + jsp-2.2 + productA:prodtest-1.0 + productB:prodtestb-1.0 + + + + + diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.wsspi.kernel.embeddable.fat/bootstrap.properties b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.wsspi.kernel.embeddable.fat/bootstrap.properties new file mode 100755 index 00000000000..2e3faa500d3 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.wsspi.kernel.embeddable.fat/bootstrap.properties @@ -0,0 +1,2 @@ +com.ibm.ws.logging.trace.specification=*=info=enabled +bootstrap.include=../testports.properties diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.wsspi.kernel.embeddable.fat/dropins/simpleApp.war/index.jsp b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.wsspi.kernel.embeddable.fat/dropins/simpleApp.war/index.jsp new file mode 100755 index 00000000000..bdb6c10537e --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.wsspi.kernel.embeddable.fat/dropins/simpleApp.war/index.jsp @@ -0,0 +1,3 @@ + +
Hi, my name is <%=request.getParameter("name")%>
+ \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.wsspi.kernel.embeddable.fat/server.xml b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.wsspi.kernel.embeddable.fat/server.xml new file mode 100755 index 00000000000..72b547c216c --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/com.ibm.wsspi.kernel.embeddable.fat/server.xml @@ -0,0 +1,11 @@ + + + + + + jsp-2.2 + + + + + diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/servers/embed_me/bootstrap.properties b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/embed_me/bootstrap.properties new file mode 100755 index 00000000000..fe859a24711 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/embed_me/bootstrap.properties @@ -0,0 +1,2 @@ +com.ibm.ws.logging.trace.specification=*=info=enabled +bootstrap.include=../testports.properties \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_fat/publish/servers/embed_me/server.xml b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/embed_me/server.xml new file mode 100755 index 00000000000..8b22ca755eb --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/publish/servers/embed_me/server.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/dev/com.ibm.ws.kernel.boot_fat/test-applications/checkJvmAppClasspath/src/com/ibm/ws/kernel/boot/app/classpath/CheckJvmAppClasspathPackagesBean.java b/dev/com.ibm.ws.kernel.boot_fat/test-applications/checkJvmAppClasspath/src/com/ibm/ws/kernel/boot/app/classpath/CheckJvmAppClasspathPackagesBean.java new file mode 100644 index 00000000000..8c81c5d791a --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/test-applications/checkJvmAppClasspath/src/com/ibm/ws/kernel/boot/app/classpath/CheckJvmAppClasspathPackagesBean.java @@ -0,0 +1,42 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2016 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.kernel.boot.app.classpath; + +import java.lang.reflect.Method; + +import javax.annotation.PostConstruct; +import javax.ejb.LocalBean; +import javax.ejb.Singleton; +import javax.ejb.Startup; + +@Startup +@Singleton +@LocalBean +public class CheckJvmAppClasspathPackagesBean { + + private static ClassLoader JVM_APP_LOADER = ClassLoader.getSystemClassLoader(); + + @PostConstruct + public void printJvmAppClasspathPackages() { + Method m; + try { + m = ClassLoader.class.getDeclaredMethod("getPackages"); + m.setAccessible(true); + Package[] pkgs = (Package[]) m.invoke(JVM_APP_LOADER); + for (Package p : pkgs) { + System.out.println("AppLoader can load: " + p.getName()); + } + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/dev/com.ibm.ws.kernel.boot_fat/test-applications/shutdownfat/.gitignore b/dev/com.ibm.ws.kernel.boot_fat/test-applications/shutdownfat/.gitignore new file mode 100644 index 00000000000..e47e1b33a74 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/test-applications/shutdownfat/.gitignore @@ -0,0 +1 @@ +/resources diff --git a/dev/com.ibm.ws.kernel.boot_fat/test-applications/shutdownfat/src/com/ibm/ws/kernel/boot/fat/ShutdownTestServlet.java b/dev/com.ibm.ws.kernel.boot_fat/test-applications/shutdownfat/src/com/ibm/ws/kernel/boot/fat/ShutdownTestServlet.java new file mode 100755 index 00000000000..85a52828141 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_fat/test-applications/shutdownfat/src/com/ibm/ws/kernel/boot/fat/ShutdownTestServlet.java @@ -0,0 +1,46 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2013 + * + * The source code for this program is not published or other- + * wise divested of its trade secrets, irrespective of what has + * been deposited with the U.S. Copyright Office. + */ +package com.ibm.ws.kernel.boot.fat; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +@WebServlet("/*") +@SuppressWarnings("serial") +public class ShutdownTestServlet extends HttpServlet { + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + final String exitMethodName = request.getParameter("exit"); + response.getWriter().println("exit=" + exitMethodName); + + // WebContainer "helpfully" blocks app stop until all servlets have + // finished their requests. That only makes the FAT take longer, so use + // a secondary thread. + new Thread() { + @Override + public void run() { + if ("Runtime.exit".equals(exitMethodName)) { + System.out.println(this + ": calling Runtime.exit"); + Runtime.getRuntime().exit(0); + } else { + System.out.println(this + ": calling Shutdown.exit"); + System.exit(0); + } + } + }.start(); + } +} diff --git a/dev/com.ibm.ws.kernel.boot_test/.classpath b/dev/com.ibm.ws.kernel.boot_test/.classpath new file mode 100644 index 00000000000..bd880329225 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/dev/com.ibm.ws.kernel.boot_test/.classpath.gradle b/dev/com.ibm.ws.kernel.boot_test/.classpath.gradle new file mode 100644 index 00000000000..bd880329225 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/.classpath.gradle @@ -0,0 +1,7 @@ + + + + + + + diff --git a/dev/com.ibm.ws.kernel.boot_test/.gitignore b/dev/com.ibm.ws.kernel.boot_test/.gitignore new file mode 100644 index 00000000000..9fb7b834a97 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/.gitignore @@ -0,0 +1,5 @@ +*.log* +/TestBundleDeactivate.txt +/coverage.ec +/lib +/reports diff --git a/dev/com.ibm.ws.kernel.boot_test/.project b/dev/com.ibm.ws.kernel.boot_test/.project new file mode 100755 index 00000000000..fd207f3e333 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/.project @@ -0,0 +1,23 @@ + + + com.ibm.ws.kernel.boot_test + + + + + + org.eclipse.jdt.core.javabuilder + + + + + bndtools.core.bndbuilder + + + + + + org.eclipse.jdt.core.javanature + bndtools.core.bndnature + + diff --git a/dev/com.ibm.ws.kernel.boot_test/.settings/org.eclipse.core.resources.prefs b/dev/com.ibm.ws.kernel.boot_test/.settings/org.eclipse.core.resources.prefs new file mode 100755 index 00000000000..25d9425fe34 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,4 @@ +#Ant properties +#Automatically generated by the ant prepare.settings.files task +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/dev/com.ibm.ws.kernel.boot_test/.settings/org.eclipse.jdt.core.prefs b/dev/com.ibm.ws.kernel.boot_test/.settings/org.eclipse.jdt.core.prefs new file mode 100755 index 00000000000..845c3083c7d --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,286 @@ +#Ant properties +#Automatically generated by the ant prepare.settings.files task +org.eclipse.jdt.core.codeComplete.argumentPrefixes= +org.eclipse.jdt.core.codeComplete.argumentSuffixes= +org.eclipse.jdt.core.codeComplete.fieldPrefixes= +org.eclipse.jdt.core.codeComplete.fieldSuffixes= +org.eclipse.jdt.core.codeComplete.localPrefixes= +org.eclipse.jdt.core.codeComplete.localSuffixes= +org.eclipse.jdt.core.codeComplete.staticFieldPrefixes= +org.eclipse.jdt.core.codeComplete.staticFieldSuffixes= +org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes= +org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes= +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.6 +org.eclipse.jdt.core.formatter.align_type_members_on_columns=false +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=0 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=18 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=2 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=2 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=18 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=2 +org.eclipse.jdt.core.formatter.alignment_for_assignment=0 +org.eclipse.jdt.core.formatter.alignment_for_binary_expression=18 +org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=0 +org.eclipse.jdt.core.formatter.alignment_for_enum_constants=16 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=18 +org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=18 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=18 +org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=0 +org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=20 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=4 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +org.eclipse.jdt.core.formatter.blank_lines_before_field=0 +org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 +org.eclipse.jdt.core.formatter.blank_lines_before_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 +org.eclipse.jdt.core.formatter.blank_lines_before_package=0 +org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 +org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 +org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false +org.eclipse.jdt.core.formatter.comment.format_block_comments=true +org.eclipse.jdt.core.formatter.comment.format_header=false +org.eclipse.jdt.core.formatter.comment.format_html=false +org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true +org.eclipse.jdt.core.formatter.comment.format_line_comments=false +org.eclipse.jdt.core.formatter.comment.format_source_code=true +org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true +org.eclipse.jdt.core.formatter.comment.indent_root_tags=true +org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert +org.eclipse.jdt.core.formatter.comment.line_length=180 +org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true +org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true +org.eclipse.jdt.core.formatter.compact_else_if=true +org.eclipse.jdt.core.formatter.continuation_indentation=4 +org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=4 +org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off +org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on +org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false +org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=false +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true +org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_empty_lines=false +org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true +org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true +org.eclipse.jdt.core.formatter.indentation.size=8 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert +org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.join_lines_in_comments=false +org.eclipse.jdt.core.formatter.join_wrapped_lines=false +org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false +org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false +org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false +org.eclipse.jdt.core.formatter.lineSplit=180 +org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=true +org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=true +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 +org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=false +org.eclipse.jdt.core.formatter.tabulation.char=space +org.eclipse.jdt.core.formatter.tabulation.size=4 +org.eclipse.jdt.core.formatter.use_on_off_tags=true +org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false +org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true +org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true diff --git a/dev/com.ibm.ws.kernel.boot_test/.settings/org.eclipse.jdt.ui.prefs b/dev/com.ibm.ws.kernel.boot_test/.settings/org.eclipse.jdt.ui.prefs new file mode 100755 index 00000000000..fadbc117581 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,117 @@ +#Ant properties +#Automatically generated by the ant prepare.settings.files task +cleanup.add_default_serial_version_id=false +cleanup.add_generated_serial_version_id=true +cleanup.add_missing_annotations=true +cleanup.add_missing_deprecated_annotations=true +cleanup.add_missing_methods=false +cleanup.add_missing_nls_tags=false +cleanup.add_missing_override_annotations=true +cleanup.add_missing_override_annotations_interface_methods=true +cleanup.add_serial_version_id=false +cleanup.always_use_blocks=true +cleanup.always_use_parentheses_in_expressions=false +cleanup.always_use_this_for_non_static_field_access=false +cleanup.always_use_this_for_non_static_method_access=false +cleanup.convert_to_enhanced_for_loop=false +cleanup.correct_indentation=true +cleanup.format_source_code=false +cleanup.format_source_code_changes_only=false +cleanup.make_local_variable_final=false +cleanup.make_parameters_final=true +cleanup.make_private_fields_final=false +cleanup.make_type_abstract_if_missing_method=false +cleanup.make_variable_declarations_final=false +cleanup.never_use_blocks=false +cleanup.never_use_parentheses_in_expressions=true +cleanup.organize_imports=true +cleanup.qualify_static_field_accesses_with_declaring_class=false +cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true +cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true +cleanup.qualify_static_member_accesses_with_declaring_class=true +cleanup.qualify_static_method_accesses_with_declaring_class=false +cleanup.remove_private_constructors=true +cleanup.remove_trailing_whitespaces=true +cleanup.remove_trailing_whitespaces_all=true +cleanup.remove_trailing_whitespaces_ignore_empty=false +cleanup.remove_unnecessary_casts=true +cleanup.remove_unnecessary_nls_tags=true +cleanup.remove_unused_imports=true +cleanup.remove_unused_local_variables=false +cleanup.remove_unused_private_fields=true +cleanup.remove_unused_private_members=false +cleanup.remove_unused_private_methods=true +cleanup.remove_unused_private_types=true +cleanup.sort_members=false +cleanup.sort_members_all=false +cleanup.use_blocks=true +cleanup.use_blocks_only_for_return_and_throw=false +cleanup.use_parentheses_in_expressions=true +cleanup.use_this_for_non_static_field_access=false +cleanup.use_this_for_non_static_field_access_only_if_necessary=true +cleanup.use_this_for_non_static_method_access=false +cleanup.use_this_for_non_static_method_access_only_if_necessary=true +eclipse.preferences.version=1 +editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true +org.eclipse.jdt.ui.exception.name=e +org.eclipse.jdt.ui.gettersetter.use.is=true +org.eclipse.jdt.ui.ignorelowercasenames=true +org.eclipse.jdt.ui.importorder=java;javax;org;com; +org.eclipse.jdt.ui.javadoc=true +org.eclipse.jdt.ui.keywordthis=false +org.eclipse.jdt.ui.ondemandthreshold=99 +org.eclipse.jdt.ui.overrideannotation=true +org.eclipse.jdt.ui.staticondemandthreshold=99 +org.eclipse.jdt.ui.text.custom_code_templates= +sp_cleanup.add_default_serial_version_id=true +sp_cleanup.add_generated_serial_version_id=false +sp_cleanup.add_missing_annotations=true +sp_cleanup.add_missing_deprecated_annotations=true +sp_cleanup.add_missing_methods=false +sp_cleanup.add_missing_nls_tags=false +sp_cleanup.add_missing_override_annotations=true +sp_cleanup.add_missing_override_annotations_interface_methods=true +sp_cleanup.add_serial_version_id=false +sp_cleanup.always_use_blocks=true +sp_cleanup.always_use_parentheses_in_expressions=false +sp_cleanup.always_use_this_for_non_static_field_access=false +sp_cleanup.always_use_this_for_non_static_method_access=false +sp_cleanup.convert_to_enhanced_for_loop=false +sp_cleanup.correct_indentation=false +sp_cleanup.format_source_code=true +sp_cleanup.format_source_code_changes_only=false +sp_cleanup.make_local_variable_final=false +sp_cleanup.make_parameters_final=false +sp_cleanup.make_private_fields_final=true +sp_cleanup.make_type_abstract_if_missing_method=false +sp_cleanup.make_variable_declarations_final=true +sp_cleanup.never_use_blocks=false +sp_cleanup.never_use_parentheses_in_expressions=true +sp_cleanup.on_save_use_additional_actions=true +sp_cleanup.organize_imports=true +sp_cleanup.qualify_static_field_accesses_with_declaring_class=false +sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_with_declaring_class=false +sp_cleanup.qualify_static_method_accesses_with_declaring_class=false +sp_cleanup.remove_private_constructors=true +sp_cleanup.remove_trailing_whitespaces=true +sp_cleanup.remove_trailing_whitespaces_all=true +sp_cleanup.remove_trailing_whitespaces_ignore_empty=false +sp_cleanup.remove_unnecessary_casts=true +sp_cleanup.remove_unnecessary_nls_tags=true +sp_cleanup.remove_unused_imports=true +sp_cleanup.remove_unused_local_variables=false +sp_cleanup.remove_unused_private_fields=true +sp_cleanup.remove_unused_private_members=false +sp_cleanup.remove_unused_private_methods=true +sp_cleanup.remove_unused_private_types=true +sp_cleanup.sort_members=false +sp_cleanup.sort_members_all=false +sp_cleanup.use_blocks=false +sp_cleanup.use_blocks_only_for_return_and_throw=false +sp_cleanup.use_parentheses_in_expressions=false +sp_cleanup.use_this_for_non_static_field_access=false +sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true +sp_cleanup.use_this_for_non_static_method_access=false +sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true diff --git a/dev/com.ibm.ws.kernel.boot_test/bnd.bnd b/dev/com.ibm.ws.kernel.boot_test/bnd.bnd new file mode 100755 index 00000000000..5b9fdb80859 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/bnd.bnd @@ -0,0 +1,21 @@ +-include= ~../cnf/resources/bnd/liberty-release.props +bVersion=1.0 + +-nobundles=true + +src: \ + unittest/src + +-buildpath: \ + ${javac.bootclasspath.java6}, \ + ../build.sharedResources/lib/junit/old/junit.jar;version=file, \ + ../build.sharedResources/lib/ws-junit/ws-junit.jar;version=file, \ + ../build.sharedResources/lib/hamcrest-all.jar;version=file, \ + ../build.sharedResources/lib/jmock/old/jmock-junit4.jar;version=file, \ + ../build.sharedResources/lib/jmock/old/jmock.jar;version=file, \ + ../build.sharedResources/lib/jmock/legacy/jmock-legacy.jar;version=file, \ + ../build.sharedResources/lib/jmock/legacy/objenesis.jar;version=file, \ + ../build.sharedResources/lib/jmock/legacy/cglib-nodep.jar;version=file, \ + com.ibm.websphere.org.osgi.core.6.0.0;version=latest, \ + com.ibm.ws.logging.core;version=latest,\ + com.ibm.ws.kernel.boot;version=latest diff --git a/dev/com.ibm.ws.kernel.boot_test/bnd.bnd.gradle b/dev/com.ibm.ws.kernel.boot_test/bnd.bnd.gradle new file mode 100755 index 00000000000..5b9fdb80859 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/bnd.bnd.gradle @@ -0,0 +1,21 @@ +-include= ~../cnf/resources/bnd/liberty-release.props +bVersion=1.0 + +-nobundles=true + +src: \ + unittest/src + +-buildpath: \ + ${javac.bootclasspath.java6}, \ + ../build.sharedResources/lib/junit/old/junit.jar;version=file, \ + ../build.sharedResources/lib/ws-junit/ws-junit.jar;version=file, \ + ../build.sharedResources/lib/hamcrest-all.jar;version=file, \ + ../build.sharedResources/lib/jmock/old/jmock-junit4.jar;version=file, \ + ../build.sharedResources/lib/jmock/old/jmock.jar;version=file, \ + ../build.sharedResources/lib/jmock/legacy/jmock-legacy.jar;version=file, \ + ../build.sharedResources/lib/jmock/legacy/objenesis.jar;version=file, \ + ../build.sharedResources/lib/jmock/legacy/cglib-nodep.jar;version=file, \ + com.ibm.websphere.org.osgi.core.6.0.0;version=latest, \ + com.ibm.ws.logging.core;version=latest,\ + com.ibm.ws.kernel.boot;version=latest diff --git a/dev/com.ibm.ws.kernel.boot_test/build-unittest.xml b/dev/com.ibm.ws.kernel.boot_test/build-unittest.xml new file mode 100755 index 00000000000..86cb5c63ace --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/build-unittest.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + Project classpath: ${pcp} + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/com.ibm.ws.kernel.boot_test/build.gradle b/dev/com.ibm.ws.kernel.boot_test/build.gradle new file mode 100644 index 00000000000..e69de29bb2d diff --git a/dev/com.ibm.ws.kernel.boot_test/delivery.sets b/dev/com.ibm.ws.kernel.boot_test/delivery.sets new file mode 100755 index 00000000000..674398425a0 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/delivery.sets @@ -0,0 +1 @@ +SLE diff --git a/dev/com.ibm.ws.kernel.boot_test/launch.bnd b/dev/com.ibm.ws.kernel.boot_test/launch.bnd new file mode 100755 index 00000000000..36e984b875c --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/launch.bnd @@ -0,0 +1,9 @@ +-nouses=true +bVersion=1.0 +-output ${bnd.target}/${Bundle-SymbolicName}_${bVersion}.jar + +Bundle-Name: WebSphere kernel bootstrap launcher +Bundle-SymbolicName: launch +Bundle-Version: ${bVersion} +WebSphere-DefaultKernel: test-kernel-1.0 +WebSphere-DefaultLogProvider: test-logging-1.0 \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_test/resources/Factory.empty b/dev/com.ibm.ws.kernel.boot_test/resources/Factory.empty new file mode 100755 index 00000000000..e69de29bb2d diff --git a/dev/com.ibm.ws.kernel.boot_test/resources/packages.list b/dev/com.ibm.ws.kernel.boot_test/resources/packages.list new file mode 100755 index 00000000000..73141766e79 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/resources/packages.list @@ -0,0 +1 @@ +not.right.property.name=value \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_test/resources/serverDefaults/bootstrap.properties b/dev/com.ibm.ws.kernel.boot_test/resources/serverDefaults/bootstrap.properties new file mode 100755 index 00000000000..a9e01451363 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/resources/serverDefaults/bootstrap.properties @@ -0,0 +1,15 @@ +# port for the OSGi console +osgi.console=5678 + +# +# OSGi caching +# Equinox will cache information about a running server to speed up +# class resolution when the server is restarted. Alpine and Equinox +# will take steps to ensure that this data is refreshed if bundles in +# the lib directory are updated, but if you are getting a lot of +# messages about missing bundle constraints, and you know the bundle +# in question is well formed, starting with a clean slate may fix +# things up. Uncomment the following ("osgi.clean=true") to force +# equinox to clear cached information before installing or starting +# any bundles. +# osgi.clean=true diff --git a/dev/com.ibm.ws.kernel.boot_test/resources/serverDefaults/server.cfg b/dev/com.ibm.ws.kernel.boot_test/resources/serverDefaults/server.cfg new file mode 100755 index 00000000000..6ffbd599b68 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/resources/serverDefaults/server.cfg @@ -0,0 +1,21 @@ +############################################## +# Default Alpine Configuration +# +# Format: +# group:key value +# or +# group{ +# #a series of +# key value +# } +# where can be: =, -=, +=, >=, or <= +# value can be: +# - String +# - String Array: values enclosed by [] and delimited by , +# - Map of Strings: set of "key=value" value pairs enclosed by {} and delimited by , +# See "Config Parser and Config File Format" document for more details. +############################################## + +com.ibm.ws.kernel.feature:featuresets+=[webcontainer, http, ssl] + +Applications:scanning.enabled=true diff --git a/dev/com.ibm.ws.kernel.boot_test/resources/system-packages_1.6.0.properties b/dev/com.ibm.ws.kernel.boot_test/resources/system-packages_1.6.0.properties new file mode 100755 index 00000000000..055dbd0f1b8 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/resources/system-packages_1.6.0.properties @@ -0,0 +1,3 @@ +# An empty list for testing + +org.osgi.framework.system.packages=1.6.0 diff --git a/dev/com.ibm.ws.kernel.boot_test/resources/system-packages_1.7.0.properties b/dev/com.ibm.ws.kernel.boot_test/resources/system-packages_1.7.0.properties new file mode 100755 index 00000000000..e0d682403da --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/resources/system-packages_1.7.0.properties @@ -0,0 +1,3 @@ +# An empty list for testing + +org.osgi.framework.system.packages=1.7.0 diff --git a/dev/com.ibm.ws.kernel.boot_test/resources/system-packages_1.8.0.properties b/dev/com.ibm.ws.kernel.boot_test/resources/system-packages_1.8.0.properties new file mode 100755 index 00000000000..73fc4869b66 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/resources/system-packages_1.8.0.properties @@ -0,0 +1,3 @@ +# An empty list for testing + +org.osgi.framework.system.packages=1.8.0 diff --git a/dev/com.ibm.ws.kernel.boot_test/simple.bnd b/dev/com.ibm.ws.kernel.boot_test/simple.bnd new file mode 100755 index 00000000000..7f4d4db1b7d --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/simple.bnd @@ -0,0 +1,13 @@ +-nouses=true +-resourceonly=true +bVersion=1.0 +-output ${bnd.target}/${Bundle-SymbolicName}_${bVersion}.jar + +Bundle-Name: simple bundle +Bundle-SymbolicName: simple +Bundle-Version: ${bVersion} +Bundle-Description: simple, version ${bVersion} + +#include the real property file resources +Include-Resource: \ + @${unittest.kernel.boot.jar.name}!/OSGI-OPT/websphere/*.properties diff --git a/dev/com.ibm.ws.kernel.boot_test/simple2.bnd b/dev/com.ibm.ws.kernel.boot_test/simple2.bnd new file mode 100755 index 00000000000..96bf0d4a1a9 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/simple2.bnd @@ -0,0 +1,21 @@ +-nouses=true +-resourceonly=true +bVersion=2.0 +-output ${bnd.target}/${Bundle-SymbolicName}_${bVersion}.jar + + +Bundle-Name: simple bundle +Bundle-SymbolicName: simple +Bundle-Version: ${bVersion} +Bundle-Description: simple, version ${bVersion} +WebSphere-DefaultKernel: test-kernel-2.0 + +# For each exported package, create (in that package) a package-info.java +# file, and place an @version javadoc tag in package-level javadoc. +# Append ";provide:=true" if this bundle also provides an implementation +# for the exported API. +Export-Package: com.ibm.ws.kernel.launch.service;provide:=true + +#Include dummy resources for system-packages +Include-Resource: \ + OSGI-OPT/websphere=resources diff --git a/dev/com.ibm.ws.kernel.boot_test/simple3.bnd b/dev/com.ibm.ws.kernel.boot_test/simple3.bnd new file mode 100755 index 00000000000..93cf8514f67 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/simple3.bnd @@ -0,0 +1,13 @@ +-nouses=true +-resourceonly=true +bVersion=3.0 +-output ${bnd.target}/${Bundle-SymbolicName}_${bVersion}.jar + +Bundle-Name: simple bundle +Bundle-SymbolicName: simple +Bundle-Version: ${bVersion} +Bundle-Description: simple, version ${bVersion} +WebSphere-DefaultKernel: test-kernel-2.0 + +## It is important that the pacakges.list file does not actually exist in the generated bundle.. +# because this is testing missing system packages so we don't include them here! diff --git a/dev/com.ibm.ws.kernel.boot_test/simple4.bnd b/dev/com.ibm.ws.kernel.boot_test/simple4.bnd new file mode 100755 index 00000000000..d182b3af5e7 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/simple4.bnd @@ -0,0 +1,13 @@ +-nouses=true +-resourceonly=true +bVersion=4.0 +-output ${bnd.target}/${Bundle-SymbolicName}_${bVersion}.jar + +Bundle-Name: simple bundle +Bundle-SymbolicName: simple +Bundle-Version: ${bVersion} +Bundle-Description: simple, version ${bVersion} +WebSphere-DefaultKernel: test-kernel-2.0 + +#mock up a 1.6.0 package list from the package.list with a bad property +Include-Resource: OSGI-OPT/websphere/system-packages_1.6.0.properties=resources/packages.list diff --git a/dev/com.ibm.ws.kernel.boot_test/simple5.bnd b/dev/com.ibm.ws.kernel.boot_test/simple5.bnd new file mode 100755 index 00000000000..90506590396 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/simple5.bnd @@ -0,0 +1,13 @@ +-nouses=true +-resourceonly=true +bVersion=5.0 +-output ${bnd.target}/${Bundle-SymbolicName}_${bVersion}.jar + +Bundle-Name: simple bundle +Bundle-SymbolicName: simple +Bundle-Version: ${bVersion} +Bundle-Description: simple, version ${bVersion} + +#Include dummy resources for system-packages +Include-Resource: \ + OSGI-OPT/websphere=resources \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/BootstrapConfigTest.java b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/BootstrapConfigTest.java new file mode 100755 index 00000000000..50c96f777ee --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/BootstrapConfigTest.java @@ -0,0 +1,782 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2010, 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + * + * Change activity: + * + * Issue Date Name Description + * ----------- ----------- --------- ------------------------------------ + * Initial version + */ +package com.ibm.ws.kernel.boot; + +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.assertSame; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.PrintWriter; +import java.lang.reflect.Field; +import java.security.PrivilegedExceptionAction; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import javax.xml.parsers.DocumentBuilderFactory; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Assume; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestName; +import org.junit.rules.TestRule; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import test.common.SharedOutputManager; +import test.shared.Constants; +import test.shared.TestUtils; + +import com.ibm.ws.kernel.boot.internal.BootstrapConstants; +import com.ibm.ws.kernel.boot.internal.BootstrapConstants.VerifyServer; + +/** + * + */ +public class BootstrapConfigTest { + static SharedOutputManager outputMgr = SharedOutputManager.getInstance(); + static final File defaultServer = new File(Constants.TEST_TMP_ROOT, "defaultServer"); + + @Rule + public TestName testName = new TestName(); + + @Rule + public TestRule outputRule = outputMgr; + + @BeforeClass + public static void setUpBeforeClass() { + TestUtils.cleanTempFiles(); + } + + @AfterClass + public static void tearDownAfterClass() { + TestUtils.cleanTempFiles(); + } + + Map initProps = new HashMap(); + BootstrapConfig bc = new TestBootstrapConfig(initProps); + + @Before + public void setUp() { + Constants.TEST_TMP_ROOT_FILE.mkdirs(); + + // Create server/workarea directories... + defaultServer.mkdirs(); + } + + @After + public void tearDown() throws Exception { + initProps.clear(); + TestUtils.cleanTempFiles(); + } + + /** + * Test method for {@link com.ibm.ws.kernel.boot.BootstrapConfig#mergeProperties(java.util.Map, java.net.URL, java.lang.String)} . + */ + @Test + public void testMergeProperties() { + + try { + File f1 = new File(Constants.TEST_PLATFORM_DIR + "include.properties"); + + // Test system property value override: compare with testProcessIncludes, + // which just looks for original value un-influenced by system properties + System.setProperty("override", "systemProperty"); + bc.mergeProperties(initProps, null, f1.toURI().toString()); + assertEquals("System property value should win", "systemProperty", bc.get("override")); + assertEquals("Peer file should be found", "found", bc.get("peer")); + assertEquals("Relative file should be found", "found", bc.get("relative")); + } finally { + System.clearProperty("override"); + } + } + + @Test + public void testMergePropertiesBadURL() { + Map map = new HashMap(); + + try { + bc.mergeProperties(map, null, "unknown:junk"); + fail("Expected location exception was not thrown"); + } catch (LocationException e) { + System.out.println(BootstrapConstants.messages.getString("error.badLocation")); + System.out.println(e.getTranslatedMessage()); + + // unable to resolve locations + assertTrue(outputMgr.checkForStandardOut("CWWKE0004E")); + // malformed URI for bootstrap properties + assertTrue(outputMgr.checkForStandardOut("CWWKE0008E")); + } + } + + @Test + public void testMergePropertiesBadFile() { + Map map = new HashMap(); + + try { + bc.mergeProperties(map, null, new File(Constants.TEST_PLATFORM_DIR + "notexist").toURI().toString()); + } catch (LocationException ex) { + assertTrue(ex.getTranslatedMessage().contains("CWWKE0014E")); + } + } + + /** + * Test method for {@link com.ibm.ws.kernel.boot.BootstrapConfig#addMissingProperties(java.util.Properties, java.util.Map)} . + */ + @Test + public void testAddMissingProperties() { + final String key1 = "existingKey", value1 = "existingValue", key2 = "newKey", value2 = "newValue", value3 = "replaceValue"; + + initProps.put(key1, value1); + + Properties source = new Properties(); + // add replacement value; should be ignored + source.setProperty(key1, value3); + source.setProperty(key2, value2); + + bc.addMissingProperties(source, initProps); + + assertEquals("Original value should be preserved", value1, initProps.get(key1)); + assertEquals("New key should be set", value2, initProps.get(key2)); + + // Should not blow up w/ null/empty source or target + bc.addMissingProperties(null, initProps); + source.clear(); + bc.addMissingProperties(source, initProps); + bc.addMissingProperties(source, null); + + // Should not blow up w/ zero-length key + source.setProperty("", "blah"); + bc.addMissingProperties(source, initProps); + } + + /** + * Test method for {@link com.ibm.ws.kernel.boot.BootstrapConfig#processIncludes(java.util.Map, java.net.URL, java.lang.String)} . Most valid paths are tested via + * mergeProperties + */ + @Test + public void testProcessIncludes() { + bc.processIncludes(initProps, null, null); + + File f1 = new File(Constants.TEST_PLATFORM_DIR + "include.properties"); + String fname = f1.toURI().toString(); + bc.processIncludes(initProps, null, fname + " "); + // Compare with testMergeProperties + assertEquals("Original value should be present", "original", bc.get("override")); + assertEquals("Peer file should be found", "found", bc.get("peer")); + assertEquals("Relative file should be found", "found", bc.get("relative")); + + bc.processIncludes(initProps, null, fname + " ,\t" + fname); + } + + /** + * Expect an IllegalArgumentException when null is passed to configure Test + * method for {@link com.ibm.ws.kernel.boot.BootstrapConfig#configure(java.util.Map)}. + */ + @Test(expected = IllegalArgumentException.class) + public void testConfigureNull() { + TestBootstrapConfig bc = new TestBootstrapConfig(); + + // configure(map) + bc.configure(null); + } + + /** + * Expect a LocationException when an unresolvable file is used as install dir + * + * Test method for {@link com.ibm.ws.kernel.boot.BootstrapConfig#configure(java.util.Map)}. + * + * @throws IOException + */ + @Test(expected = com.ibm.ws.kernel.boot.LocationException.class) + public void testConfigureBadLocation() throws IOException { + String fName = "InstallDirAsFile"; + File file = new File(Constants.TEST_TMP_ROOT, fName); + file.createNewFile(); + file.deleteOnExit(); + + TestBootstrapConfig bc = new TestBootstrapConfig(); + bc.findLocations(testName.getMethodName(), file.getAbsolutePath(), null, null, null); + } + + /** + * Test method for {@link com.ibm.ws.kernel.boot.BootstrapConfig#configure(java.util.Map)}. + */ + @Test + public void testFindLocations() throws Exception { + File test1 = new File(Constants.TEST_TMP_ROOT, "test1"); + + try { + + bc = new TestBootstrapConfig(); + bc.findLocations(null, null, null, null, null); + + bc.printLocations(false); // print locations: no formatting + assertTrue("Bootstrap lib dir should be a directory (not a jar)", bc.bootstrapLib.isDirectory()); + + checkDirs("A", bc); + assertEquals("A: Default server name", BootstrapConstants.DEFAULT_SERVER_NAME, bc.getProcessName()); + assertEquals("A: installRoot should be parent of bootstrap lib", bc.installRoot, bc.bootstrapLib.getParentFile()); + assertEquals("A: userRoot should be child of installRoot", bc.installRoot, bc.userRoot.getParentFile()); + assertEquals("A: processesRoot should be a child of the userRoot", bc.userRoot, bc.processesRoot.getParentFile()); + assertEquals("A: configDir should be a child of the processesRoot", bc.processesRoot, bc.configDir.getParentFile()); + assertSame("A: outputRoot should be same as processesRoot", bc.processesRoot, bc.outputRoot); + assertSame("A: outputDir should be same as configDir", bc.configDir, bc.outputDir); + + bc = new TestBootstrapConfig(); + bc.findLocations(testName.getMethodName(), test1.getAbsolutePath(), null, null, null); + + checkDirs("B", bc); + assertEquals("B: userRoot should match userDir parameter", test1.getCanonicalFile(), bc.userRoot.getCanonicalFile()); + assertEquals("B: processesRoot should be a child of the userRoot", bc.userRoot, bc.processesRoot.getParentFile()); + assertEquals("B: configDir should be a child of the processesRoot", bc.processesRoot, bc.configDir.getParentFile()); + assertEquals("B: getServerFile(null) should return configDir", bc.configDir, bc.getConfigFile(null)); + + assertSame("B: outputRoot should be same as processesRoot", bc.processesRoot, bc.outputRoot); + assertSame("B: outputDir should be same as configDir", bc.configDir, bc.outputDir); + assertEquals("B: getServerOutputFile(null) should return outputDir", bc.outputDir, bc.getOutputFile(null)); + + // Now test for the output dir split: we now have two trees... (one shorter + // than the other.. ) + bc = new TestBootstrapConfig(); + bc.findLocations(testName.getMethodName(), null, test1.getAbsolutePath(), null, null); + + checkDirs("C", bc); + assertEquals("C: userRoot should be child of installRoot", bc.installRoot, bc.userRoot.getParentFile()); + assertEquals("C: processesRoot should be a child of the userRoot", bc.userRoot, bc.processesRoot.getParentFile()); + assertEquals("C: configDir should be a child of the processesRoot", bc.processesRoot, bc.configDir.getParentFile()); + assertEquals("C: getServerFile(null) should return configDir", bc.configDir, bc.getConfigFile(null)); + + assertEquals("C: outputRoot should match outputDir parameter", test1.getCanonicalFile(), bc.outputRoot.getCanonicalFile()); + assertEquals("C: outputDir should be a child of the outputRoot", bc.outputRoot, bc.outputDir.getParentFile()); + assertEquals("C: getServerOutputFile(null) should return outputDir", bc.outputDir, bc.getOutputFile(null)); + + assertEquals("C: getLogDiretory() should be a child of outputDir", bc.getOutputFile("logs"), bc.getLogDirectory()); + + // Now test for a separate log directory + bc = new TestBootstrapConfig(); + bc.findLocations(testName.getMethodName(), null, null, test1.getAbsolutePath(), null); + + checkDirs("D", bc); + assertEquals("D: userRoot should be child of installRoot", bc.installRoot, bc.userRoot.getParentFile()); + assertEquals("D: processesRoot should be a child of the userRoot", bc.userRoot, bc.processesRoot.getParentFile()); + assertEquals("D: configDir should be a child of the processesRoot", bc.processesRoot, bc.configDir.getParentFile()); + assertEquals("D: getServerFile(null) should return configDir", bc.configDir, bc.getConfigFile(null)); + + assertSame("D: outputRoot should be same as processesRoot", bc.processesRoot, bc.outputRoot); + assertSame("D: outputDir should be same as configDir", bc.configDir, bc.outputDir); + assertEquals("D: getServerOutputFile(null) should return outputDir", bc.outputDir, bc.getOutputFile(null)); + + assertEquals("D: getLogDiretory() should match logDir parameter", test1.getCanonicalFile(), bc.getLogDirectory().getCanonicalFile()); + + initProps.clear(); + + // Make sure system properties are ignored + System.setProperty(BootstrapConstants.LOC_PROPERTY_INSTANCE_DIR, test1.getAbsolutePath()); + bc = new TestBootstrapConfig(); + // configure(map, userDir, outputDir, logDir) + bc.findLocations(testName.getMethodName(), null, null, null, null); + + // This set should be identical to the conditions used in A (i.e. the defaults, + // as null is passed in as a parameters) + checkDirs("E", bc); + assertEquals("E: userRoot should be child of installRoot", bc.installRoot, bc.userRoot.getParentFile()); + assertEquals("E: processesRoot should be a child of the userRoot", bc.userRoot, bc.processesRoot.getParentFile()); + assertEquals("E: configDir should be a child of the processesRoot", bc.processesRoot, bc.configDir.getParentFile()); + assertSame("E: outputRoot should be same as processesRoot", bc.processesRoot, bc.outputRoot); + assertSame("E: outputDir should be same as configDir", bc.configDir, bc.outputDir); + + } finally { + TestUtils.cleanTempFiles(test1); + System.clearProperty(BootstrapConstants.LOC_PROPERTY_INSTANCE_DIR); + System.clearProperty(BootstrapConstants.LOC_PROPERTY_INSTALL_DIR); + } + } + + /** + * Test method for {@link com.ibm.ws.kernel.boot.BootstrapConfig#setSystemProperties()}. + */ + @Test + public void testSetSystemProperty() { + final String key1 = "existingKey", value1 = "existingValue", key2 = "newKey", value2 = "newValue", nonExistentKey = "nonExistentKey"; + + String javaSecurityProp = "websphere.java.security"; + + bc.setSystemProperties(); + assertNull("System property test value did not return null as expected.", System.getProperty(key1)); + assertNull("System property test value did not return null as expected.", System.getProperty(key2)); + assertNull("Non existent system property did not return null as expected.", System.getProperty(nonExistentKey)); + assertNull("Websphere Java security property did not return null as expected.", System.getProperty(javaSecurityProp)); + + initProps.put(key1, value1); + initProps.put(key2, value2); + bc.setSystemProperties(); + assertEquals("System property test value did not equal expected value.", value1, System.getProperty(key1)); + assertEquals("System property test value did not equal expected value.", value2, System.getProperty(key2)); + assertNull("Non existent system property did not return null as expected.", System.getProperty(nonExistentKey)); + assertNull("System property " + javaSecurityProp + " did not return null as expected.", System.getProperty(javaSecurityProp)); + + initProps.put(javaSecurityProp, "true"); + bc.setSystemProperties(); + assertEquals("System property test value did not equal expected value.", value1, System.getProperty(key1)); + assertEquals("System property test value did not equal expected value.", value2, System.getProperty(key2)); + assertNull("Non existent system property did not return null as expected.", System.getProperty(nonExistentKey)); + assertNull("System property " + javaSecurityProp + " did not return null as expected.", System.getProperty(javaSecurityProp)); + } + + /** + * Prepare a server directory and BootstrapConfig for verification. + */ + private BootstrapConfig prepareServer(String serverName) { + File usrDir = new File(Constants.TEST_TMP_ROOT); + File serverDir = new File(usrDir, "servers" + File.separatorChar + serverName); + TestUtils.cleanTempFiles(serverDir); + bc = new BootstrapConfig(); + bc.findLocations(serverName, Constants.TEST_TMP_ROOT, null, null, null); + return bc; + } + + private static final String[] SERVER_NAMES = new String[] { "defaultServer", "newServer" }; + + private BootstrapConfig prepareDefaultServer() { + return prepareServer("defaultServer"); + } + + private BootstrapConfig prepareNewServer() { + return prepareServer("newServer"); + } + + /** + * The type of templates that can be used when creating a server. + */ + private enum ServerTemplateType { + /** Liberty templates (wlp/templates/servers/defaultServer/) */ + LIBERTY, + /** --template=test (files created by {@link #runTemplateTest}) */ + TEST, + /** Kernel template (boot JAR, used when no other templates found) */ + KERNEL, + } + + /** + * Prepare bootstrap statics to allow templates to be found, and then run + * the specified action. + */ + private void withMockTemplatesDirectory(ServerTemplateType templateType, PrivilegedExceptionAction action) throws Exception { + File installDir; + switch (templateType) { + case TEST: + installDir = new File(Constants.TEST_TMP_ROOT_FILE, "install"); + break; + case LIBERTY: + installDir = new File(Constants.BOOTSTRAP_PUBLISH_DIR); + break; + default: + throw new IllegalArgumentException(String.valueOf(templateType)); + } + + TestUtils.setKernelUtilsBootstrapLibDir(new File(installDir, "lib")); + try { + if (templateType == ServerTemplateType.TEST) { + File templateDir = new File(installDir, "templates/servers/test"); + assertTrue("created " + templateDir, templateDir.mkdirs()); + PrintWriter pw = new PrintWriter(new File(templateDir, "server.xml"), "UTF-8"); + pw.println(""); + pw.close(); + } + + action.run(); + } finally { + TestUtils.setKernelUtilsBootstrapLibDir(null); + } + } + + /** + * Analyze server.xml to determine which server template was used. + */ + private ServerTemplateType getServerTemplateType(File serverConfig) throws Exception { + Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new FileInputStream(serverConfig)); + Element element = doc.getDocumentElement(); + assertEquals("server", element.getNodeName()); + + if ("test".equals(element.getAttribute("description"))) { + // A test server.xml create by runTemplateTest above. + return ServerTemplateType.TEST; + } + + if (element.getElementsByTagName("featureManager").getLength() > 0) { + // /com.ibm.ws.kernel.boot/publish/servers/defaultServer/server.xml + // aka wlp/templates/servers/defaultServer/server.xml. + return ServerTemplateType.LIBERTY; + } + + // Otherwise, assume it was the "kernel default" server.xml, which + // (currently?) has no features enabled. + // /com.ibm.ws.kernel.boot/resources/OSGI-OPT/websphere/server/server.xml + // aka wlp/lib/com.ibm.ws.kernel_*.jar!/OSGI-OPT/websphere/server/server.xml + return ServerTemplateType.KERNEL; + } + + /** + * VerifyServer.EXISTS with a missing server = SERVER_NOT_EXIST_STATUS + */ + @Test + public void testVerifyServerExistsError() { + for (String serverName : SERVER_NAMES) { + try { + prepareServer(serverName).verifyProcess(VerifyServer.EXISTS, null); + } catch (LaunchException e) { + assertEquals(ReturnCode.SERVER_NOT_EXIST_STATUS, e.getReturnCode()); + } + } + } + + /** + * VerifyServer.EXISTS after creating should succeed. + */ + @Test + public void testVerifyServerExists() throws Exception { + for (String serverName : SERVER_NAMES) { + prepareServer(serverName).verifyProcess(VerifyServer.CREATE, null); + bc.verifyProcess(VerifyServer.EXISTS, null); + } + } + + /** + * VerifyServer.CREATE should use the default kernel template when creating. + */ + @Test + public void testVerifyServerCreate() throws Exception { + for (String serverName : SERVER_NAMES) { + prepareServer(serverName).verifyProcess(VerifyServer.CREATE, null); + assertEquals(ServerTemplateType.KERNEL, getServerTemplateType(bc.getConfigFile(BootstrapConstants.SERVER_XML))); + } + } + + /** + * VerifyServer.CREATE should use wlp/templates if present when creating. + */ + @Test + public void testVerifyServerCreateKernelTemplate() throws Exception { + withMockTemplatesDirectory(ServerTemplateType.LIBERTY, new PrivilegedExceptionAction() { + @Override + public Void run() throws Exception { + for (String serverName : SERVER_NAMES) { + prepareServer(serverName).verifyProcess(VerifyServer.CREATE, null); + assertEquals(ServerTemplateType.LIBERTY, getServerTemplateType(bc.getConfigFile(BootstrapConstants.SERVER_XML))); + } + return null; + } + }); + } + + /** + * VerifyServer.CREATE with invalid --template = LAUNCH_EXCEPTION + error.fileNotFound. + */ + @Test + public void testVerifyServerCreateWithInvalidTemplate() throws Exception { + try { + String[] args = new String[] { "--template=invalid" }; + List cmdArgs = new ArrayList(Arrays.asList(args)); + prepareDefaultServer().verifyProcess(VerifyServer.CREATE, new LaunchArguments(cmdArgs, null)); + } catch (LaunchException e) { + assertEquals(ReturnCode.LAUNCH_EXCEPTION, e.getReturnCode()); + assertTrue(e.getTranslatedMessage(), e.getTranslatedMessage().startsWith("CWWKE0054E:")); + } + } + + /** + * VerifyServer.CREATE with --template should use that template. + */ + @Test + public void testVerifyServerCreateWithTemplate() throws Exception { + withMockTemplatesDirectory(ServerTemplateType.TEST, new PrivilegedExceptionAction() { + @Override + public Void run() throws Exception { + for (String serverName : SERVER_NAMES) { + String[] args = new String[] { "--template=test" }; + List cmdArgs = new ArrayList(Arrays.asList(args)); + prepareServer(serverName).verifyProcess(VerifyServer.CREATE, new LaunchArguments(cmdArgs, null)); + assertEquals(ServerTemplateType.TEST, getServerTemplateType(bc.getConfigFile(BootstrapConstants.SERVER_XML))); + } + return null; + } + }); + } + + /** + * VerifyServer.CREATE after creating a server = REDUNDANT_ACTION_STATUS. + */ + @Test + public void testVerifyServerCreateAlreadyExists() { + for (String serverName : SERVER_NAMES) { + try { + prepareServer(serverName).verifyProcess(VerifyServer.CREATE, null); + bc.verifyProcess(VerifyServer.CREATE, null); + } catch (LaunchException e) { + assertEquals(ReturnCode.REDUNDANT_ACTION_STATUS, e.getReturnCode()); + } + } + } + + /** + * VerifyServer.CREATE_DEFAULT should use the default kernel template when + * creating defaultServer. + */ + @Test + public void testVerifyServerCreateDefaultKernelTemplate() throws Exception { + prepareDefaultServer().verifyProcess(VerifyServer.CREATE_DEFAULT, null); + assertEquals(ServerTemplateType.KERNEL, getServerTemplateType(bc.getConfigFile(BootstrapConstants.SERVER_XML))); + } + + /** + * VerifyServer.CREATE_DEFAULT should use wlp/templates if present when + * creating defaultServer. + */ + @Test + public void testVerifyServerCreateDefaultLibertyTemplate() throws Exception { + withMockTemplatesDirectory(ServerTemplateType.LIBERTY, new PrivilegedExceptionAction() { + @Override + public Void run() throws Exception { + prepareDefaultServer().verifyProcess(VerifyServer.CREATE_DEFAULT, null); + assertEquals(ServerTemplateType.LIBERTY, getServerTemplateType(bc.getConfigFile(BootstrapConstants.SERVER_XML))); + return null; + } + }); + } + + /** + * VerifyServer.CREATE_DEFAULT should ignore --template when creating + * defaultServer. + */ + @Test + public void testVerifyServerCreateDefaultWithTemplate() throws Exception { + // This will fail if CREATE_DEFAULT erroneously checks --template. + String[] args = new String[] { "--template=invalid" }; + List cmdArgs = new ArrayList(Arrays.asList(args)); + prepareDefaultServer().verifyProcess(VerifyServer.CREATE_DEFAULT, new LaunchArguments(cmdArgs, null)); + assertEquals(ServerTemplateType.KERNEL, getServerTemplateType(bc.getConfigFile(BootstrapConstants.SERVER_XML))); + } + + /** + * VerifyServer.CREATE_DEFAULT should ignore --template when creating + * defaultServer, even if an empty directory already exists. + */ + @Test + public void testVerifyServerCreateDefaultForEmptyDirWithTemplate() throws Exception { + assertTrue("created server directory", prepareDefaultServer().getConfigFile(null).mkdirs()); + // This will fail if CREATE_DEFAULT erroneously checks --template. + String[] args = new String[] { "--template=invalid" }; + List cmdArgs = new ArrayList(Arrays.asList(args)); + bc.verifyProcess(VerifyServer.CREATE_DEFAULT, new LaunchArguments(cmdArgs, null)); + assertEquals(ServerTemplateType.KERNEL, getServerTemplateType(bc.getConfigFile(BootstrapConstants.SERVER_XML))); + } + + /** + * VerifyServer.CREATE_DEFAULT is like EXISTS for non-defaultServer: + * non-existent server = SERVER_NOT_EXIST_STATUS + */ + @Test + public void testVerifyServerCreateDefaultError() { + try { + prepareNewServer().verifyProcess(VerifyServer.CREATE_DEFAULT, null); + } catch (LaunchException e) { + assertEquals(ReturnCode.SERVER_NOT_EXIST_STATUS, e.getReturnCode()); + } + } + + /** + * VerifyServer.CREATE_DEFAULT is a no-op for an existing server. + */ + @Test + public void testVerifyServerCreateDefaultAlreadyExists() { + for (String serverName : SERVER_NAMES) { + prepareServer(serverName).verifyProcess(VerifyServer.CREATE, null); + bc.verifyProcess(VerifyServer.CREATE_DEFAULT, null); + } + } + + /** + * VerifyServer.SKIP (or null) is a no-op regardless of whether or not + * the server exists. + */ + @Test + public void testVerifyServerSkip() throws Exception { + for (String serverName : SERVER_NAMES) { + prepareServer(serverName).verifyProcess(null, null); + bc.verifyProcess(VerifyServer.SKIP, null); + + // Create the server and try again. + bc.verifyProcess(VerifyServer.CREATE, null); + bc.verifyProcess(null, null); + bc.verifyProcess(VerifyServer.SKIP, null); + } + } + + @Test + public void testNewServer() throws Exception { + File commonFile = new File(Constants.TEST_TMP_ROOT); + File newServerDir = new File(commonFile, "servers/newServer"); + + try { + TestUtils.cleanTempFiles(newServerDir); + + // Find the new server (includes mapping to canonical name, etc.) + bc = new BootstrapConfig(); + bc.findLocations("newServer", Constants.TEST_TMP_ROOT, null, null, null); + System.out.println(newServerDir.toURI().toString()); + + // Invoke configure with property indicating that the server should be created + bc.verifyProcess(VerifyServer.CREATE, null); + + assertTrue("I: new server should have been created", newServerDir.exists() && newServerDir.isDirectory()); + assertEquals("I: intended server should be created", newServerDir.getCanonicalFile(), bc.configDir.getCanonicalFile()); + + File sFile = new File(bc.configDir, "server.xml"); + assertTrue("I: new server should have server.xml file created", sFile.exists() && sFile.isFile()); + } finally { + TestUtils.cleanTempFiles(newServerDir.getParentFile()); // servers dir + } + } + + @Test + public void testServerNameCaseSensitivity() { + + File serversDir = new File(Constants.TEST_TMP_ROOT_FILE, "servers"); + File newServerDir = new File(serversDir, "newServer"); + File newserverDir = new File(serversDir, "newserver"); + + try { + TestUtils.cleanTempFiles(newServerDir); + TestUtils.cleanTempFiles(newserverDir); + + // Create a server named "newServer" + + // find locations first + bc = new BootstrapConfig(); + bc.findLocations("newServer", Constants.TEST_TMP_ROOT, null, null, null); + + // configure / create the server + initProps.clear(); + bc.verifyProcess(VerifyServer.CREATE, null); + + // This test cannot proceed unless the file system is case-insensitive. + Assume.assumeTrue(newserverDir.exists()); + + // Configure a server named "newserver". + bc = new BootstrapConfig(); + bc.findLocations("newserver", Constants.TEST_TMP_ROOT, null, null, null); + bc.verifyProcess(VerifyServer.CREATE_DEFAULT, null); + + initProps.clear(); + bc.configure(initProps); + + // Verify that the server is named "newServer". + assertEquals("newServer", bc.getProcessName()); + assertEquals("newServer", bc.getConfigFile(null).getName()); + assertEquals("newServer", bc.getOutputFile(null).getName()); + + // Verify that no framework property contains "newserver" since + // these are all set as system properties. + for (Map.Entry entry : bc.getFrameworkProperties().entrySet()) { + assertFalse("framework property " + entry.getKey() + '=' + entry.getValue(), + entry.getValue().contains("newserver")); + } + } finally { + TestUtils.cleanTempFiles(serversDir); + } + } + + @Test + public void testSetServerName() { + bc.setProcessName("abcdefghijklmnopqrstuvwxyz"); + bc.setProcessName("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); + bc.setProcessName("12345567890"); + bc.setProcessName("_-.+"); + bc.setProcessName("+-._"); + } + + @Test(expected = LocationException.class) + public void testSetServerDirBad1() { + bc.setProcessName("bad!"); + } + + @Test(expected = LocationException.class) + public void testSetServerDirBad2() { + bc.setProcessName("bad "); + } + + @Test(expected = LocationException.class) + public void testSetServerDirBad3() { + bc.setProcessName("bad\b"); + } + + @Test(expected = LocationException.class) + public void testSetServerDirBad4() { + bc.setProcessName(".bad"); + } + + @Test(expected = LocationException.class) + public void testSetServerDirBad5() { + bc.setProcessName("-bad"); + } + + public void checkDirs(String m, BootstrapConfig bc) throws IllegalArgumentException, IllegalAccessException { + // make sure all dirs are set.. use reflection so that we catch if we + // missed + // one.. + Field fields[] = BootstrapConfig.class.getDeclaredFields(); + for (Field f : fields) { + if (f.getType().equals(File.class)) { + f.setAccessible(true); + String name = f.getName(); + File file = (File) f.get(bc); + assertNotNull(m + ": File location should be set for " + name, file); + System.out.printf("%18s %s\n", name, file.getAbsolutePath()); + } + } + + // sanity check the calculated directories + assertEquals(bc.outputDir, bc.workarea.getParentFile()); + } + + protected class TestBootstrapConfig extends BootstrapConfig { + TestBootstrapConfig() {} + + TestBootstrapConfig(Map initProps) { + super.initProps = initProps; + } + + @Override + protected void verifyProcess(VerifyServer verify, LaunchArguments args) throws LaunchException {} + } +} diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/LaunchArgumentsTest.java b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/LaunchArgumentsTest.java new file mode 100755 index 00000000000..6aa4e292713 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/LaunchArgumentsTest.java @@ -0,0 +1,318 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.kernel.boot; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestRule; + +import test.common.SharedOutputManager; +import test.shared.TestUtils; + +import com.ibm.ws.kernel.boot.internal.BootstrapConstants; +import com.ibm.ws.kernel.boot.internal.BootstrapConstants.VerifyServer; + +/** + * + */ +public class LaunchArgumentsTest { + static SharedOutputManager outputMgr = SharedOutputManager.getInstance(); + + @Rule + public TestRule outputRule = outputMgr; + + @BeforeClass + public static void setUpBeforeClass() { + TestUtils.cleanTempFiles(); + } + + @AfterClass + public static void tearDownAfterClass() { + TestUtils.cleanTempFiles(); + } + + @Test + public void testProcessBatchFileArgs() { + Launcher launcher = new Launcher(); + assertEquals(Arrays.asList(), + launcher.processBatchFileArgs(makeList())); + assertEquals(Arrays.asList("defaultServer"), + launcher.processBatchFileArgs(makeList("defaultServer"))); + assertEquals(Arrays.asList("--batch-file"), + launcher.processBatchFileArgs(makeList("--batch-file"))); + assertEquals(Arrays.asList("--batch-file=--stop"), + launcher.processBatchFileArgs(makeList("--batch-file=--stop"))); + + assertEquals(Arrays.asList("defaultServer"), + launcher.processBatchFileArgs(makeList("--batch-file", "run"))); + assertEquals(Arrays.asList("defaultServer"), + launcher.processBatchFileArgs(makeList("--batch-file", "run", "defaultServer"))); + assertEquals(Arrays.asList("myServer"), + launcher.processBatchFileArgs(makeList("--batch-file", "run", "myServer"))); + assertEquals(Arrays.asList("defaultServer", "--option"), + launcher.processBatchFileArgs(makeList("--batch-file", "run", "--option"))); + assertEquals(Arrays.asList("defaultServer", "--option"), + launcher.processBatchFileArgs(makeList("--batch-file", "run", "defaultServer", "--option"))); + assertEquals(Arrays.asList("myServer", "--option"), + launcher.processBatchFileArgs(makeList("--batch-file", "run", "myServer", "--option"))); + + assertEquals(Arrays.asList("--stop"), + launcher.processBatchFileArgs(makeList("--stop"))); + assertEquals(Arrays.asList("--stop", "defaultServer"), + launcher.processBatchFileArgs(makeList("--stop", "defaultServer"))); + assertEquals(Arrays.asList("--stop", "myServer"), + launcher.processBatchFileArgs(makeList("--stop", "myServer"))); + assertEquals(Arrays.asList("--stop", "--option"), + launcher.processBatchFileArgs(makeList("--stop", "--option"))); + assertEquals(Arrays.asList("--stop", "defaultServer", "--option"), + launcher.processBatchFileArgs(makeList("--stop", "defaultServer", "--option"))); + assertEquals(Arrays.asList("--stop", "myServer", "--option"), + launcher.processBatchFileArgs(makeList("--stop", "myServer", "--option"))); + + assertEquals(Arrays.asList("--stop", "defaultServer"), + launcher.processBatchFileArgs(makeList("--batch-file=--stop", "stop"))); + assertEquals(Arrays.asList("--stop", "defaultServer"), + launcher.processBatchFileArgs(makeList("--batch-file=--stop", "stop", "defaultServer"))); + assertEquals(Arrays.asList("--stop", "myServer"), + launcher.processBatchFileArgs(makeList("--batch-file=--stop", "stop", "myServer"))); + assertEquals(Arrays.asList("--stop", "defaultServer", "--option"), + launcher.processBatchFileArgs(makeList("--batch-file=--stop", "stop", "--option"))); + assertEquals(Arrays.asList("--stop", "defaultServer", "--option"), + launcher.processBatchFileArgs(makeList("--batch-file=--stop", "stop", "defaultServer", "--option"))); + assertEquals(Arrays.asList("--stop", "myServer", "--option"), + launcher.processBatchFileArgs(makeList("--batch-file=--stop", "stop", "myServer", "--option"))); + } + + /** + * Make sure the command line --clean will override the system property + * value for clean + */ + @Test + public void testParameterClean() { + String[] args = new String[] { "--clean" }; + List cmdArgs = new ArrayList(Arrays.asList(args)); + + System.setProperty(BootstrapConstants.INITPROP_OSGI_CLEAN, "none"); + + Map initProps = new HashMap(); + LaunchArguments launchArgs = new LaunchArguments(cmdArgs, initProps); + ReturnCode rc = launchArgs.getRc(); + + assertEquals("InitProps should contain the value to enable a clean start", + BootstrapConstants.OSGI_CLEAN_VALUE, initProps.get(BootstrapConstants.INITPROP_OSGI_CLEAN)); + assertNull("The system property value should be removed, as overridden by command line", + System.getProperty(BootstrapConstants.OSGI_CLEAN_VALUE)); + assertEquals("VerifyServer should be CREATE_DEFAULT for default start action", + VerifyServer.CREATE_DEFAULT, rc.getVerifyServer()); + } + + /** + * Make sure the command line --autoAcceptSigner will override the system property + * value for SSL auto-accept-signer-certificate. + */ + @Test + public void testParameterAutoAcceptSigner() { + String[] args = new String[] { "--autoAcceptSigner" }; + List cmdArgs = new ArrayList(Arrays.asList(args)); + + System.setProperty(BootstrapConstants.AUTO_ACCEPT_SIGNER, "false"); + + Map initProps = new HashMap(); + LaunchArguments launchArgs = new LaunchArguments(cmdArgs, initProps, true); + ReturnCode rc = launchArgs.getRc(); + + assertEquals("InitProps should contain the value to enable a clean start", + "true", initProps.get(BootstrapConstants.AUTO_ACCEPT_SIGNER)); + assertEquals("VerifyServer should be CREATE_DEFAULT for default start action", + VerifyServer.CREATE_DEFAULT, rc.getVerifyServer()); + } + + @Test + public void testParameterEmpty() { + String[] args = new String[] {}; + List cmdArgs = new ArrayList(Arrays.asList(args)); + Map initProps = new HashMap(); + LaunchArguments launchArgs = new LaunchArguments(cmdArgs, initProps); + ReturnCode rc = launchArgs.getRc(); + + assertEquals("VerifyServer should be CREATE_DEFAULT for default start action", + VerifyServer.CREATE_DEFAULT, rc.getVerifyServer()); + + assertEquals("We should be ok!", ReturnCode.OK, rc); + } + + /** + */ + @Test + public void testParameterCreate() { + String[] args = new String[] { "--create" }; + List cmdArgs = new ArrayList(Arrays.asList(args)); + Map initProps = new HashMap(); + + LaunchArguments launchArgs = new LaunchArguments(cmdArgs, initProps); + ReturnCode rc = launchArgs.getRc(); + + assertEquals("VerifyServer should be CREATE for create action", + VerifyServer.CREATE, rc.getVerifyServer()); + assertEquals("We should be set for a create operation", ReturnCode.CREATE_ACTION, rc); + } + + /** + */ + @Test + public void testParameterStop() { + String[] args = new String[] { "--stop" }; + List cmdArgs = new ArrayList(Arrays.asList(args)); + Map initProps = new HashMap(); + LaunchArguments launchArgs = new LaunchArguments(cmdArgs, initProps); + ReturnCode rc = launchArgs.getRc(); + + assertEquals("VerifyServer should be EXISTS for stop action", + VerifyServer.EXISTS, rc.getVerifyServer()); + + assertSame("Stop command should return stop action return code", ReturnCode.STOP_ACTION, rc); + } + + /** + */ + @Test + public void testParameterStatus() { + String[] args = new String[] { "--status" }; + List cmdArgs = new ArrayList(Arrays.asList(args)); + Map initProps = new HashMap(); + LaunchArguments launchArgs = new LaunchArguments(cmdArgs, initProps); + ReturnCode rc = launchArgs.getRc(); + + assertEquals("VerifyServer should be EXISTS for status action", + VerifyServer.EXISTS, rc.getVerifyServer()); + + assertSame("status command should return status action return code", ReturnCode.STATUS_ACTION, rc); + } + + /** + */ + @Test + public void testParameterStatusStart() { + String[] args = new String[] { "--status:start" }; + List cmdArgs = new ArrayList(Arrays.asList(args)); + Map initProps = new HashMap(); + LaunchArguments launchArgs = new LaunchArguments(cmdArgs, initProps); + ReturnCode rc = launchArgs.getRc(); + + assertEquals("VerifyServer should be SKIP for status:start action", + VerifyServer.SKIP, rc.getVerifyServer()); + + assertSame("status:start command should return start status action return code", ReturnCode.START_STATUS_ACTION, rc); + } + + /** + */ + @Test + public void testParameterServerName() { + String[] args = new String[] { "name1", "name2" }; + List cmdArgs = new ArrayList(Arrays.asList(args)); + Map initProps = new HashMap(); + LaunchArguments launchArgs = new LaunchArguments(cmdArgs, initProps); + + assertSame("status should be ok after double name", ReturnCode.OK, launchArgs.getRc()); + assertTrue("should see a warning about second name", outputMgr.checkForStandardOut("CWWKE0027W")); + } + + @Test + public void testParameterVersion() { + String[] args = new String[] { "--version" }; + List cmdArgs = new ArrayList(Arrays.asList(args)); + Map initProps = new HashMap(); + LaunchArguments launchArgs = new LaunchArguments(cmdArgs, initProps); + ReturnCode rc = launchArgs.getRc(); + + assertEquals("VerifyServer should be SKIP for version action", + VerifyServer.SKIP, rc.getVerifyServer()); + + assertEquals("ReturnCode should select version action", ReturnCode.VERSION_ACTION, rc); + } + + @Test + public void testParameterHelp() { + String[] args = new String[] { "--help" }; + List cmdArgs = new ArrayList(Arrays.asList(args)); + Map initProps = new HashMap(); + LaunchArguments launchArgs = new LaunchArguments(cmdArgs, initProps); + ReturnCode rc = launchArgs.getRc(); + + assertEquals("VerifyServer should be SKIP for help action", + VerifyServer.SKIP, rc.getVerifyServer()); + + assertEquals("ReturnCode should select help action", ReturnCode.HELP_ACTION, rc); + } + + @Test + public void testParameterHelpArgs() { + String[] args = new String[] { "--script=bin/server", "--help" }; + List cmdArgs = new ArrayList(Arrays.asList(args)); + Map initProps = new HashMap(); + LaunchArguments launchArgs = new LaunchArguments(cmdArgs, initProps); + + assertEquals("ReturnCode should select help action", ReturnCode.HELP_ACTION, launchArgs.getRc()); + assertEquals("original argument should be present as an option", "--help", launchArgs.getOption("arg")); + assertEquals("script should be set as an option", "bin/server", launchArgs.getOption("script")); + + args = new String[] { "--help:usage" }; + cmdArgs = new ArrayList(Arrays.asList(args)); + launchArgs = new LaunchArguments(cmdArgs, initProps); + + assertEquals("ReturnCode should select help action", ReturnCode.HELP_ACTION, launchArgs.getRc()); + assertEquals("original argument should be present as an option", "--help:usage", launchArgs.getOption("arg")); + assertNull("script should not be set as an option", launchArgs.getOption("script")); + } + + /** + */ + @Test + public void testParameterUnknownBad() { + String args[] = new String[] { "--garbage" }; + List cmdArgs = new ArrayList(Arrays.asList(args)); + Map initProps = new HashMap(); + LaunchArguments launchArgs = new LaunchArguments(cmdArgs, initProps); + + assertSame("status should be BAD_ARGUMENT after garbage argument", ReturnCode.BAD_ARGUMENT, launchArgs.getRc()); + assertTrue("should see a error about bad argument", outputMgr.checkForStandardOut("CWWKE0013E")); + } + + @Test + public void testParameterUnknownSingleDash() { + String args[] = new String[] { "-garbage" }; + List cmdArgs = new ArrayList(Arrays.asList(args)); + Map initProps = new HashMap(); + LaunchArguments launchArgs = new LaunchArguments(cmdArgs, initProps); + + assertSame("status should be BAD_ARGUMENT after garbage argument", ReturnCode.BAD_ARGUMENT, launchArgs.getRc()); + assertTrue("should see a error about bad argument", outputMgr.checkForStandardOut("CWWKE0013E")); + } + + private List makeList(String... args) { + return new ArrayList(Arrays.asList(args)); + } +} diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/LauncherTest.java b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/LauncherTest.java new file mode 100755 index 00000000000..20ec2b8c602 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/LauncherTest.java @@ -0,0 +1,205 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2009, 2013 + * + * The source code for this program is not published or other- + * wise divested of its trade secrets, irrespective of what has + * been deposited with the U.S. Copyright Office. + */ +package com.ibm.ws.kernel.boot; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.PrintStream; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestRule; + +import com.ibm.ws.kernel.boot.internal.BootstrapConstants; +import com.ibm.ws.kernel.boot.internal.FileUtils; + +import test.common.SharedOutputManager; +import test.shared.Constants; +import test.shared.TestUtils; + +public class LauncherTest { + static final File defaultServer = new File(Constants.TEST_TMP_ROOT, "usr/servers/defaultServer"); + static SharedOutputManager outputMgr = SharedOutputManager.getInstance(); + + @Rule + public TestRule outputRule = outputMgr; + + @BeforeClass + public static void setUpBeforeClass() { + TestUtils.cleanTempFiles(); + } + + @AfterClass + public static void tearDownAfterClass() { + TestUtils.cleanTempFiles(); + } + + TestLauncher tlauncher = new TestLauncher(); + BootstrapConfig config = new BootstrapConfig(); + + // Grab streams set by SharedOutputManager + PrintStream outputMgrOut; + PrintStream outputMgrErr; + + @Before + public void setUp() { + outputMgr.resetStreams(); + Set keys = System.getProperties().stringPropertyNames(); + for (String key : keys) { + // Restrict the system properties we pick up and pass to the + // framework for launch + if (key.contains("osgi") || key.contains("was") || key.contains("equinox")) + System.clearProperty(key); + } + + outputMgrOut = System.out; + outputMgrErr = System.err; + + // Create server/workarea directories... + defaultServer.mkdir(); + } + + @After + public void tearDown() { + tlauncher.fakeEnv.clear(); + FileUtils.recursiveClean(defaultServer); + } + + @Test + public void testHardCodedMainClass() throws Exception { + File bootJar = TestUtils.findBuiltKernelBundle(); + URLClassLoader loader = new URLClassLoader(new URL[] { bootJar.toURI().toURL() }, null); + // Our main class is not API/SPI, but we do hard code it in several + // places, so we use this test to ensure they're all updated. + // - /com.ibm.ws.kernel.boot/build.xml + // - wlp/bin/tools/ws-server.jar!/META-INF/MANIFEST.MF Main-Class + // - wlp/lib/ws-launch.jar!/META-INF/MANIFEST.MF Main-Class + // - /com.ibm.zos.native/server_launcher.c + // - CMVC NATV/ws/code/os400.native/src/script/qwlpstrsvr.cpp + loader.loadClass("com.ibm.ws.kernel.boot.cmdline.EnvCheck"); + } + + @Test + public void testParameterVersion() throws Exception { + String[] args = new String[] { "--version" }; + + // This needs to crack open a manifest for a jar, so feed it a jar... + TestUtils.setKernelUtilsBootstrapJar(TestUtils.findBuiltKernelBundle()); + TestUtils.setKernelUtilsBootstrapLibDir(Constants.TEST_DIST_DIR_FILE); + TestUtils.setUtilsInstallDir(Constants.TEST_DATA_FILE); + + try { + int rc = tlauncher.createPlatform(args); + assertEquals(ReturnCode.OK.val, rc); + assertTrue(outputMgr.checkForStandardOut("WebSphere Application Server")); // config-root + // message + } finally { + TestUtils.setKernelUtilsBootstrapJar(null); + TestUtils.setKernelUtilsBootstrapLibDir(null); + TestUtils.setUtilsInstallDir(null); + } + } + + @Test + public void testParameterHelp() { + String[] args = new String[] { "--help" }; + + int rc = tlauncher.createPlatform(args); + assertEquals(ReturnCode.OK.val, rc); + assertTrue("ws-server.jar should be displayed for java -jar help", outputMgr.checkForStandardOut("ws-server.jar")); + + // More detailed testing of help is done in LauncherVerificationTest BVT + // because script vs. not-script is determined by an env variable.. + } + + /** + */ + @Test + public void testParameterUnknownBad() { + String args[] = new String[] { "--garbage" }; + + int rc = tlauncher.createPlatform(args); + assertTrue(outputMgr.checkForStandardOut("CWWKE0013E")); + assertEquals(ReturnCode.BAD_ARGUMENT.val, rc); + } + + /** + * When launched with --version, we still read the initial configuration + * and environment variables: use that to verify that we *are* reading + * the environment variables so we don't have to deal with launchPlatform. + */ + @Test + public void testFindLocationsEnv() { + final String m = "testFindLocationsEnv"; + + try { + File log_dir = TestUtils.createTempDirectory("log_dir"); + File x_log_dir = TestUtils.createTempDirectory("x_log_dir"); + BootstrapConfig bootProps = new BootstrapConfig(); + + // add a fake environment variable for the private/calculated temp dir X_LOG_DIR + tlauncher.fakeEnv.put(BootstrapConstants.ENV_X_LOG_DIR, x_log_dir.getCanonicalPath()); + + tlauncher.findLocations(bootProps, "defaultServer"); + assertEquals("The logDirectory value should be value of X_LOG_DIR", + x_log_dir.getCanonicalPath(), + bootProps.getLogDirectory().getCanonicalPath()); + + // add a fake environment variable for the LOG_DIR. This value should be ignored because X_LOG_DIR exists. + tlauncher.fakeEnv.put(BootstrapConstants.ENV_LOG_DIR, log_dir.getCanonicalPath()); + tlauncher.findLocations(bootProps, "defaultServer"); + assertEquals("The logDirectory value should be value of X_LOG_DIR", + x_log_dir.getCanonicalPath(), + bootProps.getLogDirectory().getCanonicalPath()); + + // clear out the value of X_LOG_DIR. Now the logDirectory should use LOG_DIR + tlauncher.fakeEnv.remove(BootstrapConstants.ENV_X_LOG_DIR); + tlauncher.findLocations(bootProps, "defaultServer"); + assertEquals("The logDirectory value should be value of LOG_DIR", + log_dir.getCanonicalPath(), + bootProps.getLogDirectory().getCanonicalPath()); + + } catch (Throwable t) { + outputMgr.failWithThrowable(m, t); + TestUtils.cleanTempFiles(); + } + } + + /** + * Simple extension of the launcher for toggling of the behavior of some + * protected/internal methods in order to control code coverage in the + * parent. + */ + class TestLauncher extends Launcher { + int exceptionType = 0; + boolean superGetDefs = false; + int fakeJar = 0; + + final Map fakeEnv = new HashMap(); + + @Override + protected String getEnv(String key) { + return fakeEnv.get(key); + } + } +} diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/SharedBootstrapConfig.java b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/SharedBootstrapConfig.java new file mode 100755 index 00000000000..1d506cdd7f2 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/SharedBootstrapConfig.java @@ -0,0 +1,72 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2010, 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.kernel.boot; + +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import com.ibm.ws.kernel.boot.internal.FileUtils; + +import test.common.SharedOutputManager; +import test.shared.TestUtils; + +public class SharedBootstrapConfig extends BootstrapConfig { + + public static SharedBootstrapConfig createSharedConfig(SharedOutputManager outputMgr) { + try { + return new SharedBootstrapConfig(); + } catch (IOException e) { + outputMgr.failWithThrowable("createSharedConfig", e); + // unreachable: make compiler happy + throw new RuntimeException(e); + } + } + + public static SharedBootstrapConfig createSharedConfig(SharedOutputManager outputMgr, String serverName) { + try { + return new SharedBootstrapConfig(serverName); + } catch (IOException e) { + outputMgr.failWithThrowable("createSharedConfig", e); + // unreachable: make compiler happy + throw new RuntimeException(e); + } + } + + private SharedBootstrapConfig(String serverName) throws IOException { + this.processName = serverName; + + File root = TestUtils.createTempDirectory(serverName); + if (root == null || !root.exists()) + throw new IllegalArgumentException("root directory does not exist"); + + final String rootDirStr = root.getAbsolutePath(); + + HashMap map = new HashMap(); + + this.findLocations(serverName, rootDirStr, null, null, null); + this.configure(map); + } + + private SharedBootstrapConfig() throws IOException { + this("defaultServer"); + } + + public void setInitProps(Map initProps) { + this.initProps = initProps; + } + + public void cleanServerDir() { + FileUtils.recursiveClean(getConfigFile(null)); + } +} \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/internal/BootstrapManifestTest.java b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/internal/BootstrapManifestTest.java new file mode 100755 index 00000000000..bce5e3c9d85 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/internal/BootstrapManifestTest.java @@ -0,0 +1,291 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.kernel.boot.internal; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.File; +import java.io.FilenameFilter; +import java.util.HashMap; +import java.util.Map; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestName; +import org.junit.rules.TestRule; + +import test.common.SharedOutputManager; +import test.shared.Constants; +import test.shared.TestUtils; + +import com.ibm.ws.kernel.boot.BootstrapConfig; +import com.ibm.ws.kernel.boot.SharedBootstrapConfig; + +/** + * + */ +public class BootstrapManifestTest { + static SharedOutputManager outputMgr = SharedOutputManager.getInstance(); + + @Rule + public TestName testName = new TestName(); + + @Rule + public TestRule outputRule = outputMgr; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + TestUtils.cleanTempFiles(); + TestUtils.setKernelUtilsBootstrapJar(null); // make sure jar is clear + } + + @AfterClass + public static void tearDownAfterClass() { + TestUtils.cleanTempFiles(); + } + + @After + public void tearDown() throws Exception { + // reset the bootstrap jar... + TestUtils.setKernelUtilsBootstrapJar(null); // make sure jar is clear + } + + @Test + public void testGetDefaults() throws Exception { + BootstrapConfig config = new BootstrapConfig(); + + setBootstrapJar(0); // use a real built jar + BootstrapManifest m = new BootstrapManifest(); + assertNotNull("Bundle version should be set for the kernel.boot jar/bundle", m.getBundleVersion()); + assertEquals("Kernel definition should be set to the name of the default", "kernelCore-1.0", m.getKernelDefinition(config)); + assertEquals("Log provider definition should be set to the name of the default", "defaultLogging-1.0", m.getLogProviderDefinition(config)); + } + + @Test + public void testMissingKernelDefinition() throws Exception { + BootstrapConfig config = new BootstrapConfig(); + + setBootstrapJar(1); // use a jar with a missing kernel definition + BootstrapManifest m = new BootstrapManifest(); + assertNull("No value should have been found for kernel version", m.getKernelDefinition(config)); // this will throw + assertNull("No value should have been found for log provider", m.getLogProviderDefinition(config)); + } + + @Test + public void testMissingAttributesWithProperties() throws Exception { + SharedBootstrapConfig config = SharedBootstrapConfig.createSharedConfig(outputMgr); + + setBootstrapJar(1); // use a jar with a missing kernel definition and log provider + + String kernelDef = "kernel_1.x"; + String operatingSystemExtensionsDef = "extension_1.x"; + String logProviderDef = "logging_1.x"; + + Map initProps = new HashMap(); + initProps.put(BootstrapManifest.BOOTPROP_KERNEL, kernelDef); + initProps.put(BootstrapManifest.BOOTPROP_OS_EXTENSIONS, operatingSystemExtensionsDef); + initProps.put(BootstrapManifest.BOOTPROP_LOG_PROVIDER, logProviderDef); + config.setInitProps(initProps); + + BootstrapManifest m = new BootstrapManifest(); + assertEquals("Property was set: Kernel definition should equal provided property value", + kernelDef, m.getKernelDefinition(config)); + assertEquals("Property was set: OS extensions definition should equal provided property value", + operatingSystemExtensionsDef, m.getOSExtensionDefinition(config)); + assertEquals("Property was set: Log provider definition should equal provided property value", + logProviderDef, m.getLogProviderDefinition(config)); + } + + @Test(expected = com.ibm.ws.kernel.boot.LaunchException.class) + public void testMissingSystemPackagesList() throws Exception { + BootstrapConfig config = new BootstrapConfig(); + + // WebSphere-SystemPackages in MANIFEST.MF, points to file not present in bundle/jar + setBootstrapJar(3); + BootstrapManifest m = new BootstrapManifest(); + m.prepSystemPackages(config); + } + + @Test + public void testSystemPackages() throws Exception { + Map initProps = new HashMap(); + + SharedBootstrapConfig config = SharedBootstrapConfig.createSharedConfig(outputMgr); + config.setInitProps(initProps); + + setBootstrapJar(1); // use a jar with system packages + BootstrapManifest m = new BootstrapManifest(); + m.prepSystemPackages(config); + //the system packages are obtained from a java.version file name + assertNull(initProps.get(BootstrapConstants.INITPROP_OSGI_EXTRA_PACKAGE)); + assertNotNull(initProps.get(BootstrapConstants.INITPROP_OSGI_SYSTEM_PACKAGES)); + } + + @Test + public void testSystemPackagesExtraFromExportPackage() throws Exception { + Map initProps = new HashMap(); + + SharedBootstrapConfig config = SharedBootstrapConfig.createSharedConfig(outputMgr); + config.setInitProps(initProps); + + // Export-Package in MANIFEST.MF + setBootstrapJar(2); + BootstrapManifest m = new BootstrapManifest(); + m.prepSystemPackages(config); + assertNotNull(initProps.get(BootstrapConstants.INITPROP_OSGI_EXTRA_PACKAGE)); + //system-packages are not null because we included mocked up properties files + assertNotNull(initProps.get(BootstrapConstants.INITPROP_OSGI_SYSTEM_PACKAGES)); + } + + @Test + public void testSystemPackagesJavaVersion() throws Exception { + Map initProps = new HashMap(); + + SharedBootstrapConfig config = SharedBootstrapConfig.createSharedConfig(outputMgr); + config.setInitProps(initProps); + + setBootstrapJar(5); // use a jar with fake system packages that have version numbers + BootstrapManifest m = new BootstrapManifest(); + m.prepSystemPackages(config); + String sysPkgs = initProps.get(BootstrapConstants.INITPROP_OSGI_SYSTEM_PACKAGES); + + String javaVersion = System.getProperty("java.version"); + // strip off the update modifier + int index = javaVersion.indexOf('_'); + index = (index == -1) ? javaVersion.indexOf('-') : index; + javaVersion = (index == -1) ? javaVersion : javaVersion.substring(0, index); + //validate the system packages obtained match the running java.version file name + assertTrue("The system packages being used do not match the running java.version: " + + javaVersion + + " . This is normal if you are running the test on a version of Java that we support for running the server, but do not fully support. If we are intending to fully support a new Java version then new files are required in /com.ibm.ws.kernel.boot/resources/OSGI-OPT/websphere/system-packages_*.properties for production and /com.ibm.ws.kernel.boot_test/resources/system-packages_*.properties for test.", + sysPkgs.contains(javaVersion)); + + String versionsToCheck = null; + if (javaVersion.equals("1.6.0")) { + versionsToCheck = "1.6.0"; + } else if (javaVersion.equals("1.7.0")) { + versionsToCheck = "1.7.0,1.6.0"; + } else if (javaVersion.equals("1.8.0")) { + versionsToCheck = "1.8.0,1.7.0,1.6.0"; + } else { + fail("The running java version: " + javaVersion + " is newer than we have properties files for, system-packages udpates are required"); + } + + //validate that merging works and we have the older versions too + assertEquals("The system-packages_*.properties files were not merged for multiple java versions.", versionsToCheck, + sysPkgs); + } + + @Test + public void testSystemPackagesFileWrongProperty() throws Exception { + Map initProps = new HashMap(); + + SharedBootstrapConfig config = SharedBootstrapConfig.createSharedConfig(outputMgr); + config.setInitProps(initProps); + + setBootstrapJar(4); + BootstrapManifest m = new BootstrapManifest(); + m.prepSystemPackages(config); + assertNull(initProps.get(BootstrapConstants.INITPROP_OSGI_EXTRA_PACKAGE)); + assertNull(initProps.get(BootstrapConstants.INITPROP_OSGI_SYSTEM_PACKAGES)); + } + + @Test + public void testGetNormalizedOperatingSystemName() throws Exception { + Map names = new HashMap(); + names.put("AIX", "aix"); + names.put("Digital Unix", "digitalunix"); + names.put("FreeBSD", "freebsd"); + names.put("HP UX", "hpux"); + names.put("Irix", "irix"); + names.put("Linux", "linux"); + names.put("Mac OS", "macos"); + names.put("Mac OS X", "macosx"); + names.put("MPE/iX", "mpeix"); + names.put("Netware 4.11", "netware411"); + names.put("OS/2", "os2"); + names.put("OS/390", "os390"); + names.put("Solaris", "solaris"); + names.put("Windows 2000", "windows2000"); + names.put("Windows 7", "windows7"); + names.put("Windows 8", "windows8"); + names.put("Windows 95", "windows95"); + names.put("Windows 98", "windows98"); + names.put("Windows NT", "windowsnt"); + names.put("Windows NT (unknown)", "windowsntunknown"); + names.put("Windows Server 2012", "windowsserver2012"); + names.put("Windows Vista", "windowsvista"); + names.put("Windows XP", "windowsxp"); + names.put("z/OS", "zos"); + + for (String osName : names.keySet()) { + assertEquals(names.get(osName), BootstrapManifest.getNormalizedOperatingSystemName(osName)); + } + } + + protected static void setBootstrapJar(int jarTestCase) throws Exception { + File root = new File(Constants.TEST_DIST_DIR); + final String filterExpr; + + switch (jarTestCase) { + default: + case 0: + filterExpr = "com.ibm.ws.kernel.boot.*\\.jar"; + root = new File(Constants.BOOTSTRAP_LIB_DIR); + break; + case 1: + // Manifest does not contain default kernel definition / log provider + filterExpr = "simple_1\\.0\\.jar"; + break; + case 2: // Fake jar with manifest that does not contain + // framework/kernel + // definitions + filterExpr = "simple_2\\.0\\.jar"; + break; + case 3: + // Manifest references a system package list that doesn't exist + filterExpr = "simple_3\\.0\\.jar"; + break; + case 4: + // the system packages file exists, but contains + // invalid properties + filterExpr = "simple_4\\.0\\.jar"; + break; + case 5: + // the system packages file exists, but contains + // invalid properties + filterExpr = "simple_5\\.0\\.jar"; + break; + } + + File fileList[] = root.listFiles(new FilenameFilter() + { + @Override + public boolean accept(File dir, String name) + { + return name.matches(filterExpr); + } + }); + + if (fileList == null || fileList.length < 1) + throw new RuntimeException("Unable to find " + filterExpr + " in " + root.getName()); + + TestUtils.setKernelUtilsBootstrapJar(fileList[0]); // set for the test case + } +} diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/internal/FileUtilsTest.java b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/internal/FileUtilsTest.java new file mode 100755 index 00000000000..066da6d25bb --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/internal/FileUtilsTest.java @@ -0,0 +1,260 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012, 2014 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.kernel.boot.internal; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; + +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Assume; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestName; +import org.junit.rules.TestRule; + +import test.common.SharedOutputManager; +import test.shared.Constants; +import test.shared.TestUtils; + +public class FileUtilsTest { + static SharedOutputManager outputMgr = SharedOutputManager.getInstance(); + + @Rule + public TestName testName = new TestName(); + + @Rule + public TestRule outputRule = outputMgr; + + @BeforeClass + public static void setUpBeforeClass() { + TestUtils.cleanTempFiles(); + } + + @AfterClass + public static void tearDownAfterClass() { + TestUtils.cleanTempFiles(); + } + + @Test + public void testNormalizePathDrive() { + Assume.assumeTrue(File.separatorChar == '\\'); + Assert.assertEquals("", FileUtils.normalizePathDrive("")); + Assert.assertEquals("c", FileUtils.normalizePathDrive("c")); + Assert.assertEquals("C", FileUtils.normalizePathDrive("C")); + Assert.assertEquals("C:", FileUtils.normalizePathDrive("c:")); + Assert.assertEquals("C:", FileUtils.normalizePathDrive("C:")); + Assert.assertEquals("C:\\", FileUtils.normalizePathDrive("c:\\")); + Assert.assertEquals("C:\\", FileUtils.normalizePathDrive("C:\\")); + } + + @Test + public void testGetFile() throws MalformedURLException { + final String m = "testGetFile"; + + URL url; + File result; + String expected; + + try { + // The following strings were printed out from getBootstrapJar + // during debugging... Need to make sure all end up legible... + // (i.e. these strings construct equivalent URLs to what is returned + // from Utils.class.getProtectionDomain().getCodeSource().getLocation()) + + // UNC path with a space. + // The URL for a UNC path is file:////server/path, but the + // deprecated File.toURL() as used by java -jar/-cp incorrectly + // returns file://server/path/, which has an invalid authority + // component. + url = new URL("file://HOST/with%20space/lib/com.ibm.alpine_1.0.jar"); + expected = "//HOST/with space/lib/com.ibm.alpine_1.0.jar"; + result = FileUtils.getFile(url); + testResult(url, expected, result); + + // UNC path without a space. + // The URL for a UNC path is file:////server/path, but the + // deprecated File.toURL() as used by java -jar/-cp incorrectly + // returns file://server/path/, which has an invalid authority + // component. + url = new URL("file://HOST/nospace/lib/com.ibm.alpine_1.0.jar"); + expected = "//HOST/nospace/lib/com.ibm.alpine_1.0.jar"; + result = FileUtils.getFile(url); + testResult(url, expected, result); + + // Windows path with space + url = new URL("file:/C:/with%20space/lib/com.ibm.alpine_1.0.jar"); + expected = "/C:/with space/lib/com.ibm.alpine_1.0.jar"; + result = FileUtils.getFile(url); + testResult(url, expected, result); + + // Windows path without space + url = new URL("file:/C:/nospace/lib/com.ibm.alpine_1.0.jar"); + expected = "/C:/nospace/lib/com.ibm.alpine_1.0.jar"; + result = FileUtils.getFile(url); + testResult(url, expected, result); + + // Windows path with a literal + + url = new URL("file:/C:/with+plus/lib/com.ibm.alpine_1.0.jar"); + expected = "/C:/with+plus/lib/com.ibm.alpine_1.0.jar"; + result = FileUtils.getFile(url); + testResult(url, expected, result); + + // *nix path with space + url = new URL("file:/with%20space/lib/com.ibm.alpine_1.0.jar"); + expected = "/with space/lib/com.ibm.alpine_1.0.jar"; + result = FileUtils.getFile(url); + testResult(url, expected, result); + + // *nix path without space + url = new URL("file:/nospace/lib/com.ibm.alpine_1.0.jar"); + expected = "/nospace/lib/com.ibm.alpine_1.0.jar"; + result = FileUtils.getFile(url); + testResult(url, expected, result); + + // *nix path with a literal + + url = new URL("file:/with+plus/lib/com.ibm.alpine_1.0.jar"); + expected = "/with+plus/lib/com.ibm.alpine_1.0.jar"; + result = FileUtils.getFile(url); + testResult(url, expected, result); + } catch (Throwable t) { + outputMgr.failWithThrowable(m, t); + } finally { + outputMgr.restoreStreams(); + } + } + + private void testResult(URL url, String expected, File resultFile) { + File expectedFile = new File(expected); + + System.out.println("--- URL: " + url.toString()); + System.out.println(" expected:\t" + expectedFile); + System.out.println(" result:\t" + resultFile); + + assertEquals(url.toString() + " not converted to path as expected ", expectedFile, resultFile); + } + + /** + * Test method for {@link com.ibm.ws.kernel.boot.internal.KernelUtils.Utils#recursiveClean(java.io.File)} . + * + * @throws IOException + */ + @Test + public void testRecursiveClean() throws IOException { + + // These shouldn't blow up + FileUtils.recursiveClean(null); + FileUtils.recursiveClean(new File("notexist")); + + // Test recursive clean + File file1, dir2, file3, dir4, file5; + String prefix = "FileTestTmp"; + + file1 = TestUtils.createTempFile(prefix, ".tmp"); + file1.deleteOnExit(); + + dir2 = new File(file1.getParentFile(), prefix); + dir2.mkdirs(); + dir2.deleteOnExit(); + + file3 = TestUtils.createTempFile(prefix, ".tmp", dir2); + + dir4 = new File(dir2, prefix); + dir4.mkdirs(); + dir4.deleteOnExit(); + + file5 = TestUtils.createTempFile(prefix, ".tmp", dir4); + + assertTrue(file1.exists()); + assertTrue(dir2.exists()); + assertTrue(file3.exists()); + assertTrue(file3.getParent().equals(dir2.getPath())); + assertTrue(dir4.exists()); + assertTrue(file5.exists()); + assertTrue(file5.getParent().equals(dir4.getPath())); + + FileUtils.recursiveClean(file1); + assertFalse("File1 should not exist (deleted)", file1.exists()); + assertTrue("Dir2 should exist (untouched)", dir2.exists()); + assertTrue("File3 should exist (untouched)", file3.exists()); + assertTrue("Dir4 should exist (untouched)", dir4.exists()); + assertTrue("File5 should exist (untouched)", file5.exists()); + + FileUtils.recursiveClean(dir2); + assertFalse("Dir2 should not exist (deleted)", dir2.exists()); + assertFalse("File3 should not exist(deleted recursively)", file3.exists()); + assertFalse("Dir4 should exist (deleted)", dir4.exists()); + assertFalse("File5 should exist (deleted)", file5.exists()); + } + + /** + * Test that recursiveClean doesn't blow up with an NPE when a directory can't be read + * + * @throws IOException + */ + @Test + public void testRecursiveCleanNoReadPerms() throws IOException { + File file1, dir2 = null; + try { + // These shouldn't blow up + FileUtils.recursiveClean(null); + FileUtils.recursiveClean(new File("notexist")); + + // Test recursive clean + + String prefix = "FileTestTmp"; + + dir2 = new File(Constants.TEST_TMP_ROOT_FILE, prefix); + dir2.mkdirs(); + dir2.deleteOnExit(); + if (!dir2.setReadable(false)) { + // Platform doesn't support setting readable to false, just return + return; + } + if ("root".equals(System.getProperty("user.name"))) { + // The super-user can't set a file not readable to itself, so just return + return; + } + + file1 = TestUtils.createTempFile(prefix, ".tmp", dir2); + file1.deleteOnExit(); + + assertTrue(file1.exists()); + assertTrue(dir2.exists()); + + boolean cleaned = FileUtils.recursiveClean(dir2); + assertFalse("recursiveClean should report failure", cleaned); + assertTrue("Dir2 should exist (not deleted)", dir2.exists()); + assertTrue("File1 should exist (not deleted)", file1.exists()); + + assertTrue(dir2.setReadable(true)); + assertTrue(dir2.setWritable(true)); + cleaned = FileUtils.recursiveClean(dir2); + assertTrue("recursiveClean should succeed", cleaned); + assertFalse("Dir2 should not exist (deleted)", dir2.exists()); + assertFalse("File1 should not exist (deleted)", file1.exists()); + } finally { + if (dir2 != null) { + dir2.setReadable(true); + dir2.setWritable(true); + } + } + + } +} diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/internal/FrameworkManagerTest.java b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/internal/FrameworkManagerTest.java new file mode 100755 index 00000000000..5142481538b --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/internal/FrameworkManagerTest.java @@ -0,0 +1,280 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2013, 2014 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.kernel.boot.internal; + +import java.io.File; +import java.lang.reflect.Field; +import java.util.Collections; +import java.util.HashMap; +import java.util.concurrent.CountDownLatch; + +import org.jmock.Expectations; +import org.jmock.Mockery; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.BundleException; +import org.osgi.framework.ServiceReference; +import org.osgi.framework.launch.Framework; + +import com.ibm.ws.kernel.boot.BootstrapConfig; +import com.ibm.ws.kernel.boot.SharedBootstrapConfig; +import com.ibm.ws.kernel.boot.cmdline.Utils; +import com.ibm.ws.kernel.launch.internal.FrameworkManager; +import com.ibm.ws.kernel.launch.service.FrameworkReady; + +import junit.framework.Assert; +import test.common.SharedOutputManager; + +public class FrameworkManagerTest { + @Rule + public final TimeoutRule rule = new TimeoutRule(); + + @Rule + public final SharedOutputManager outputMgr = SharedOutputManager.getInstance(); + + private final Mockery mockery = new Mockery(); + Framework framework = mockery.mock(Framework.class); + BundleContext systemBundleContext = mockery.mock(BundleContext.class); + + boolean frameworkStarted; + boolean frameworkStopped; + private Thread launchFrameworkThread; + private Throwable launchFrameworkThrowable; + private File installDirBefore; + + @Before + public void before() throws Exception { + mockery.checking(new Expectations() { + { + allowing(framework).getBundleContext(); + will(returnValue(systemBundleContext)); + allowing(framework).getState(); + will(returnValue(Bundle.ACTIVE)); + + } + }); + + Field f = Utils.class.getDeclaredField("installDir"); + f.setAccessible(true); + installDirBefore = (File) f.get(null); + f.set(null, new File("unittest", "test data")); + } + + @After + public void after() throws Exception { + Field f = Utils.class.getDeclaredField("installDir"); + f.setAccessible(true); + f.set(null, installDirBefore); + + // Previous these tests were using @RunWith(JMock) to check expectations. I switched to asserting + // expectations here because the TimeoutRule will not be called when using @RunWith(JMock) + mockery.assertIsSatisfied(); + } + + private void setupFrameworkReadyServices() throws Exception { + mockery.checking(new Expectations() { + { + allowing(systemBundleContext).getServiceReferences(FrameworkReady.class, null); + will(returnValue(Collections.emptyList())); + } + }); + } + + private void launchFramework(FrameworkManager fm) { + SharedBootstrapConfig config = SharedBootstrapConfig.createSharedConfig(outputMgr); + config.setInitProps(new HashMap()); + fm.launchFramework(config, null); + } + + private void startLaunchFrameworkThread(final FrameworkManager fm) { + launchFrameworkThread = new Thread() { + @Override + public void run() { + try { + launchFramework(fm); + } catch (Throwable t) { + launchFrameworkThrowable = t; + } + } + }; + launchFrameworkThread.start(); + } + + private void joinLaunchFrameworkThread() throws InterruptedException { + launchFrameworkThread.join(); + if (launchFrameworkThrowable != null) { + throw new RuntimeException(launchFrameworkThrowable); + } + } + + @Test + public void testLaunchAndShutdown() throws Throwable { + setupFrameworkReadyServices(); + TestFrameworkManager fm = new TestFrameworkManager(); + + startLaunchFrameworkThread(fm); + fm.waitForReady(); + Assert.assertTrue(frameworkStarted); + + fm.shutdownFramework(); + fm.waitForShutdown(); + Assert.assertTrue(frameworkStopped); + + joinLaunchFrameworkThread(); + } + + @Test + public void testFrameworkReadyService() throws Exception { + mockery.checking(new Expectations() { + { + ServiceReference reference = mockery.mock(ServiceReference.class); + allowing(systemBundleContext).getServiceReferences(with(FrameworkReady.class), with((String) null)); + will(returnValue(Collections.singletonList(reference))); + + FrameworkReady frameworkReady = mockery.mock(FrameworkReady.class); + allowing(systemBundleContext).getService(reference); + will(returnValue(frameworkReady)); + + one(frameworkReady).waitForFrameworkReady(); + } + }); + + TestFrameworkManager fm = new TestFrameworkManager(); + + startLaunchFrameworkThread(fm); + Assert.assertTrue(fm.waitForReady()); + + fm.shutdownFramework(); + fm.waitForShutdown(); + + joinLaunchFrameworkThread(); + } + + @Test + public void testStartFrameworkException() throws Throwable { + TestFrameworkManager fm = new TestFrameworkManager() { + @Override + protected Framework startFramework(BootstrapConfig config) { + throw new TestException(); + } + }; + + try { + launchFramework(fm); + Assert.fail("expected TestException"); + } catch (TestException e) { + } + + Assert.assertFalse(fm.waitForReady()); + Assert.assertFalse(frameworkStarted); + + fm.waitForShutdown(); + Assert.assertFalse(frameworkStopped); + } + + @Test + public void testInnerLaunchFrameworkException() throws Throwable { + setupFrameworkReadyServices(); + + TestFrameworkManager fm = new TestFrameworkManager() { + @Override + protected void innerLaunchFramework(boolean isClient) { + throw new TestException(); + } + }; + + try { + launchFramework(fm); + Assert.fail("expected TestException"); + } catch (TestException e) { + } + + Assert.assertFalse(fm.waitForReady()); + Assert.assertTrue(frameworkStarted); + + fm.waitForShutdown(); + Assert.assertTrue(frameworkStopped); + } + + // Timing out here rather than in the ant script so that we can generate a core using TimeoutRule when + // this hangs. Five minutes is probably excessive, but it's still less than the ant timeout. + // This is here to debug Java Defect 126649 -- once we get a core from that, we can remove this. + @Test(timeout = 300000) + public void testShutdownHook() throws Throwable { + setupFrameworkReadyServices(); + TestFrameworkManager fm = new TestFrameworkManager(); + + startLaunchFrameworkThread(fm); + Assert.assertTrue(fm.waitForReady()); + Assert.assertTrue(frameworkStarted); + + fm.runShutdownHook(); + + fm.waitForShutdown(); + Assert.assertTrue(frameworkStopped); + + joinLaunchFrameworkThread(); + } + + @SuppressWarnings("serial") + private static class TestException extends RuntimeException {} + + private class TestFrameworkManager extends FrameworkManager { + private final CountDownLatch frameworkStoppedLatch = new CountDownLatch(1); + + void runShutdownHook() { + shutdownHook.run(); + } + + @Override + protected Framework startFramework(BootstrapConfig config) throws BundleException { + frameworkStarted = true; + return FrameworkManagerTest.this.framework; + } + + @Override + protected void stopFramework() { + frameworkStopped = true; + frameworkStoppedLatch.countDown(); + } + + @Override + protected void waitForFrameworkStop() { + try { + frameworkStoppedLatch.await(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + @Override + protected void innerLaunchFramework(boolean isClient) {} + + @Override + protected void startServerCommandListener() {} + + @Override + public boolean waitForReady() throws InterruptedException { + boolean result = super.waitForReady(); + + if (result) { + Assert.assertNotNull(framework); + } + + return result; + } + } +} diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/internal/KernelResolverTest.java b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/internal/KernelResolverTest.java new file mode 100755 index 00000000000..9b39491155b --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/internal/KernelResolverTest.java @@ -0,0 +1,168 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.kernel.boot.internal; + +import java.io.File; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +import junit.framework.Assert; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestName; +import org.junit.rules.TestRule; + +import test.common.SharedOutputManager; +import test.shared.DumpTimerRule; +import test.shared.TestUtils; + +import com.ibm.ws.kernel.boot.LaunchException; +import com.ibm.ws.kernel.boot.SharedBootstrapConfig; + +/** + * + */ +public class KernelResolverTest { + static SharedOutputManager outputMgr = SharedOutputManager.getInstance(); + + @Rule + public TestName testName = new TestName(); + + @Rule + public TestRule outputRule = outputMgr; + + @Rule + public TestRule dumpTimerRule = new DumpTimerRule(30000, new File("build/unittest")); + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + TestUtils.cleanTempFiles(); + TestUtils.setKernelUtilsBootstrapLibDir(new File("unittest/test data/lbr/lib")); + } + + @AfterClass + public static void tearDownAfterClass() throws Exception { + TestUtils.cleanTempFiles(); + TestUtils.setKernelUtilsBootstrapLibDir(null); + } + + // Shared configuration places the instance directory in the build dir + SharedBootstrapConfig config = SharedBootstrapConfig.createSharedConfig(outputMgr, "kernelResolver"); + File installDir = config.getInstallRoot(); + + @Test + public void testKernelResolverNoIncludesNoExtensions() throws Exception { + + // Read kernelCore and defaultLogging-- null os extensions + // This should be happy/healthy, and should not throw + KernelResolver resolver = new KernelResolver(installDir, null, "kernelCore-1.0", "defaultLogging-1.0", null); + + final List urlList = new ArrayList(4); + + // Add OSGi framework, log provider, and/or os extension "boot.jar" elements + resolver.addBootJars(urlList); + System.out.println(urlList); + + Assert.assertEquals("Should have two jars in the jar list by default", 2, urlList.size()); + Assert.assertTrue("Should have resolved x.y; version=\"[1.0.0,1.0.100)\"; type=\"boot.jar\" to x.y_1.0.jar", listContains(urlList, "x.y_1.0.jar")); + Assert.assertTrue("Should have resolved a.b; version=\"[1,1.0.100)\"; type=\"boot.jar\" to a.b_1.0.1.v2.jar", listContains(urlList, "a.b_1.0.1.v2.jar")); + Assert.assertEquals("Should have read the log provider from defaultLogging-1.0.jar", "com.ibm.ws.logging.internal.impl.LogProviderImpl", resolver.getLogProvider()); + + // There should be a warning issued about ignoring iFix jar a.b_1.0.2.v1.jar + Assert.assertTrue("Should have a warning message about skipping an iFix jar", outputMgr.checkForStandardOut("CWWKE0060W.*a.b_1.0.2.v1.jar")); + } + + @Test + public void testKernelResolverIncludesNoExtensions() throws Exception { + + // Read kernelCore and defaultLogging-- null os extensions + // This should be happy/healthy, and should not throw + KernelResolver resolver = new KernelResolver(installDir, null, "kernelCore-1.0", "binaryLogging-1.0", null); + + final List urlList = new ArrayList(4); + + resolver.addBootJars(urlList); + System.out.println(urlList); + + // Conditions are mostly the same: the binaryLogging mf includes defaultLogging mf, but the log provider class is different + Assert.assertEquals("Should have two jars in the jar list by default", 2, urlList.size()); + Assert.assertTrue("Should have resolved x.y; version=\"[1.0.0,1.0.100)\"; type=\"boot.jar\" to x.y_1.0.jar", listContains(urlList, "x.y_1.0.jar")); + Assert.assertTrue("Should have resolved a.b; version=\"[1,1.0.100)\"; type=\"boot.jar\" to a.b_1.0.1.v2.jar", listContains(urlList, "a.b_1.0.1.v2.jar")); + Assert.assertEquals("Should have read the log provider from defaultLogging-1.0.mf", "com.ibm.ws.logging.internal.hpel.HpelLogProviderImpl", resolver.getLogProvider()); + } + + @Test + public void testKernelResolverExtensions() { + + // Read kernelCore and defaultLogging-- null os extensions + // This should be happy/healthy, and should not throw + KernelResolver resolver = new KernelResolver(installDir, null, "kernelCore-1.0", "emptyLogging-1.0", "extension-1.0"); + + final List urlList = new ArrayList(4); + + resolver.addBootJars(urlList); + System.out.println(urlList); + + // Conditions are mostly the same: emptyLogging has no boot.jars, but extension-1.0 does + Assert.assertEquals("Should have two jars in the jar list by default", 2, urlList.size()); + Assert.assertTrue("Should have resolved x.y; version=\"[1.0.0,1.0.100)\"; type=\"boot.jar\" to x.y_1.0.jar", listContains(urlList, "x.y_1.0.jar")); + Assert.assertTrue("Should have resolved a.b; version=\"[1,1.0.100)\"; type=\"boot.jar\" to a.b_1.0.1.v2.jar", listContains(urlList, "a.b_1.0.1.v2.jar")); + Assert.assertEquals("Should have read the log provider from emptyLogging-1.0.mf", "dummy.LogProvider", resolver.getLogProvider()); + } + + @Test(expected = LaunchException.class) + public void testKernelResolverNullKernel() { + + // Throw: null kernel definition + new KernelResolver(installDir, null, null, null, null); + } + + @Test(expected = LaunchException.class) + public void testKernelResolverMissingKernel() { + + // Throw: null missing kernel definition + new KernelResolver(installDir, null, "bogus-1.0", null, null); + } + + @Test(expected = LaunchException.class) + public void testKernelResolverNullLogProvider() { + + // Throw: null log provider definition + new KernelResolver(installDir, null, "kernelCore-1.0", null, null); + } + + @Test(expected = LaunchException.class) + public void testKernelResolverMissingLogProvider() { + + // Throw: missing log provider definition + new KernelResolver(installDir, null, "kernelCore-1.0", "bogus-1.0", null); + } + + @Test(expected = LaunchException.class) + public void testKernelResolverMissingBundle() { + + // Throw: we couldn't find one of the specified jars + new KernelResolver(installDir, null, "kernelCore-1.0", "missingJar-1.0", null); + } + + boolean listContains(List urlList, String filename) { + for (URL url : urlList) { + if (url.toString().contains(filename)) + return true; + } + return false; + } +} diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/internal/ServerLockTest.java b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/internal/ServerLockTest.java new file mode 100755 index 00000000000..1c818db48ac --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/internal/ServerLockTest.java @@ -0,0 +1,263 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011, 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.kernel.boot.internal; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assume.assumeTrue; + +import java.io.File; +import java.io.FileOutputStream; +import java.nio.channels.FileChannel; +import java.nio.channels.FileLock; + +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import test.common.SharedOutputManager; +import test.shared.TestUtils; + +import com.ibm.ws.kernel.boot.LaunchException; +import com.ibm.ws.kernel.boot.SharedBootstrapConfig; +import com.ibm.ws.kernel.boot.cmdline.Utils; + +/** + * + */ +public class ServerLockTest { + static SharedOutputManager outputMgr; + static SharedBootstrapConfig config; + + /** + * @throws java.lang.Exception + */ + @BeforeClass + public static void setUpBeforeClass() throws Exception { + File f = TestUtils.createTempFile("ResourceUtilsTest", "tmp"); + f.delete(); + f.mkdir(); + + // make stdout/stderr "quiet"-- no output will show up for test + // unless one of the copy methods or documentThrowable is called + outputMgr = SharedOutputManager.getInstance(); + + // Bootstrap configuration/locations + config = SharedBootstrapConfig.createSharedConfig(outputMgr); + + outputMgr.captureStreams(); + } + + /** + * @throws java.lang.Exception + */ + @AfterClass + public static void tearDownAfterClass() throws Exception { + outputMgr.restoreStreams(); + TestUtils.cleanTempFiles(); + } + + @Before + public void setUp() { + TestUtils.cleanTempFiles(); + } + + /** + * Test method for {@link com.ibm.ws.kernel.boot.internal.KernelUtils#checkServerLock(java.io.File, java.lang.String)} . + * Additional testing of deleting the lock file at server shutdown + */ + @Test + public void testCheckServerLock() { + final String m = "testCheckServerLock"; + + try { + File sLockFile = config.getWorkareaFile(BootstrapConstants.S_LOCK_FILE); + assertTrue("Parent dirs should exist", sLockFile.getParentFile().exists() || sLockFile.getParentFile().mkdirs()); + + ServerLock serverLock = ServerLock.createServerLock(config); + try { + // get lock for testServer1 + serverLock.obtainServerLock(); + assertTrue("Lock file exists after call to obtain", sLockFile.exists()); + } finally { + serverLock.releaseServerLock(); + sLockFile.delete(); + } + } catch (Throwable t) { + outputMgr.failWithThrowable(m, t); + } finally { + if (config != null) { + // This method skips/preserves .sLock files + FileUtils.recursiveClean(config.getWorkareaFile(null)); + } + } + } + + /** + * Test method for {@link com.ibm.ws.kernel.boot.internal.KernelUtils#checkServerLock(java.io.File, java.lang.String)} . + * Test permissions surrounding get/obtain server lock + */ + @Test + public void testCheckServerLockPermissions() { + final String m = "testCheckServerLockPermissions"; + + try { + File tmpServerDir = config.getConfigFile(null); + File workArea = config.getWorkareaFile(null); + + // Test a write-only server directory + //we use an assume instead of an assert here because the test has no + //meaning and should be ignored if it could not set the directory to + //be unwritable (e.g. on Windows) + assumeTrue(tmpServerDir.setWritable(false, false)); + try { + // only test behavior with read-only directory if we could make the dir read-only: bug 48667 + if (tmpServerDir.canWrite() == false) { + assertFalse("tmpServerDir() should be false after setWritable(false)", tmpServerDir.canWrite()); + ServerLock.createServerLock(config); + throw new Exception("Missed expected launch exception with unwritable server directory"); + } + } catch (LaunchException le) { + // Expected exception + String translatedMsg = le.getTranslatedMessage(); + assertNotNull("Exception should contain translated message", translatedMsg); + assertTrue("Exception should contain console message CWWKE0044E", translatedMsg.contains("CWWKE0044E")); + assertFalse("Server workarea should not have been created", workArea.isDirectory()); + } finally { + tmpServerDir.setWritable(true, false); + } + + assertTrue("couldn't create workarea", workArea.mkdirs()); + + // Make allocated workarea read-only + assertTrue("must be able to make server workarea unwritable", workArea.setWritable(false, false)); + try { + // only test behavior with read-only directory if we could make the dir read-only: bug 48667 + if (workArea.canWrite() == false) { + assertFalse("workArea.canWrite() should be false after setWritable(false)", workArea.canWrite()); + ServerLock.createServerLock(config); + throw new Exception("Missed expected launch exception with read-only workarea"); + } + } catch (LaunchException le) { + // Expected exception + String translatedMsg = le.getTranslatedMessage(); + assertNotNull("Exception should contain translated message", translatedMsg); + assertTrue("Exception should contain console message CWWKE0044E", translatedMsg.contains("CWWKE0044E")); + } finally { + workArea.setWritable(true, false); + } + + // Allocate lock file, make it read-only + File lockFile = new File(workArea, BootstrapConstants.S_LOCK_FILE); + lockFile.createNewFile(); + assertTrue("must be able to make lockfile unwritable", lockFile.setWritable(false, false)); + try { + // only test behavior with read-only directory if we could make the dir read-only: bug 48667 + if (workArea.canWrite() == false) { + assertFalse("lockFile.canWrite() should be false after setWritable(false)", lockFile.canWrite()); + ServerLock.createServerLock(config); + throw new Exception("Missed expected launch exception with unwritable lock file"); + } + } catch (LaunchException le) { + // Expected exception + String translatedMsg = le.getTranslatedMessage(); + assertNotNull("Exception should contain translated message", translatedMsg); + assertTrue("Exception should contain console message CWWKE0044E", translatedMsg.contains("CWWKE0044E")); + } finally { + lockFile.setWritable(true, false); + } + } catch (Throwable t) { + outputMgr.failWithThrowable(m, t); + } finally { + if (config != null) { + FileUtils.recursiveClean(config.getWorkareaFile(null)); + } + } + } + + @Test + public void testCheckServerLockAlreadyLocked() { + final String m = "testCheckServerLockAlreadyLocked"; + + try { + File workArea = config.getWorkareaFile(null); + assertTrue("Parent dirs should exist", workArea.isDirectory() || workArea.mkdirs()); + + ServerLock serverLock = null; + File lockFile = null; + FileOutputStream fos = null; + FileChannel fc = null; + FileLock lock = null; + + try { + serverLock = ServerLock.createServerLock(config); + lockFile = new File(workArea, BootstrapConstants.S_LOCK_FILE); + fos = new FileOutputStream(lockFile); + fc = fos.getChannel(); + lock = fc.lock(); + + // Try to obtain with lock already held. + serverLock.obtainServerLock(); + throw new Exception("Missed expected launch exception: lock already held"); + } catch (LaunchException le) { + // Expected exception + String translatedMsg = le.getTranslatedMessage(); + assertNotNull("Exception should contain translated message", translatedMsg); + assertTrue("Exception should contain console message CWWKE0029E", translatedMsg.contains("CWWKE0029E")); + } finally { + if (lock != null) { + lock.release(); + lockFile.delete(); + } + if (!Utils.tryToClose(fc)) { + Utils.tryToClose(fos); + } + } + } catch (Throwable t) { + outputMgr.failWithThrowable(m, t); + } finally { + if (config != null) + FileUtils.recursiveClean(config.getWorkareaFile(null)); + } + } + + /** + * Test method for {@link com.ibm.ws.kernel.boot.internal.FileUtils#recursiveClean(java.io.File)} . + * Additional testing of not deleting the lock file. + */ + @Test + public void testRecursiveCleanWithLock() { + final String m = "testRecursiveCleanWithLock"; + + try { + ServerLock.createServerLock(config); + File workarea = config.getWorkareaFile(null); + assertTrue("Parent dirs should exist", workarea.isDirectory() || workarea.mkdirs()); + + File sLockFile = config.getWorkareaFile(BootstrapConstants.S_LOCK_FILE); + File nonLockFile = config.getWorkareaFile("notLock.file"); + + assertTrue(".sLock file should exist pre-test", sLockFile.exists() || sLockFile.createNewFile()); + assertTrue("nonLockFile should exist pre-test", nonLockFile.exists() || nonLockFile.createNewFile()); + + FileUtils.recursiveClean(config.getConfigFile(null)); + + assertFalse("non-lock file should not exist (deleted)", nonLockFile.exists()); + assertTrue("lock file should exist (untouched)", sLockFile.exists()); + assertTrue("workarea directory should exist (untouched-- preserve in-use .sLock file)", workarea.exists()); + } catch (Throwable t) { + outputMgr.failWithThrowable(m, t); + } + } +} diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/internal/ServerRunningTest.java b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/internal/ServerRunningTest.java new file mode 100755 index 00000000000..eebe7919a94 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/internal/ServerRunningTest.java @@ -0,0 +1,131 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012, 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.kernel.boot.internal; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.io.File; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import test.common.SharedOutputManager; +import test.shared.TestUtils; + +import com.ibm.ws.kernel.boot.SharedBootstrapConfig; + +/** + * + */ +public class ServerRunningTest { + static SharedOutputManager outputMgr; + static SharedBootstrapConfig config; + + /** + * @throws java.lang.Exception + */ + @BeforeClass + public static void setUpBeforeClass() throws Exception { + File f = TestUtils.createTempFile("ResourceUtilsTest", "tmp"); + f.delete(); + boolean suc = f.mkdir(); + + // make stdout/stderr "quiet"-- no output will show up for test + // unless one of the copy methods or documentThrowable is called + outputMgr = SharedOutputManager.getInstance(); + + // Bootstrap configuration/locations + config = SharedBootstrapConfig.createSharedConfig(outputMgr); + + outputMgr.captureStreams(); + } + + /** + * @throws java.lang.Exception + */ + @AfterClass + public static void tearDownAfterClass() throws Exception { + outputMgr.restoreStreams(); + TestUtils.cleanTempFiles(); + } + + /** + * Test to make sure .sRunning file is created and exists as server is running and that it isn't + * deleted as part of a cleaning of workarea. + */ + @Test + public void testServerRunning() { + + final String m = "testServerRunning"; + File sRunningFile = null; + + try { + // Must create parent workarea - server lock code ensures this exists + File serverWorkArea = config.getWorkareaFile(null); + if (!serverWorkArea.exists()) { + boolean suc = serverWorkArea.mkdirs(); + } + + ServerLock.createServerRunningMarkerFile(config); // Unit test runtime code + sRunningFile = config.getWorkareaFile(BootstrapConstants.SERVER_RUNNING_FILE); + assertTrue("Running marker file exists after call to obtain", sRunningFile.exists()); + + } catch (Throwable t) { + outputMgr.failWithThrowable(m, t); + } finally { + if (config != null) { + // This method skips/preserves .sRunning file + FileUtils.recursiveClean(config.getWorkareaFile(null)); + } + } + assertTrue("Running marke file exists after call to clean workspace", sRunningFile.exists()); + } + + /** + * Test to make sure workspace area is cleaned after a JVM ABEND + */ + @Test + public void testServerRunningAfterABEND() { + + final String m = "testServerRunningAfterABEND"; + File sRunningFile = null; + + try { + // Must create parent workarea - server lock code ensures this exists + File serverWorkArea = config.getWorkareaFile(null); + if (!serverWorkArea.exists()) { + boolean suc = serverWorkArea.mkdirs(); + } + + sRunningFile = config.getWorkareaFile(BootstrapConstants.SERVER_RUNNING_FILE); + sRunningFile.delete(); // Make sure sRunning file isn't there. + + ServerLock.createServerRunningMarkerFile(config); // Unit test runtime code + boolean cleanStart = config.checkCleanStart(); + assertFalse("Clean start should not be requested", cleanStart); + + ServerLock.createServerRunningMarkerFile(config); // 2nd call - file will exist, appears as ABEND + cleanStart = config.checkCleanStart(); + assertTrue("Clean start should be requested", cleanStart); + + } catch (Throwable t) { + outputMgr.failWithThrowable(m, t); + } finally { + if (config != null) { + // This method skips/preserves .sRunning file + FileUtils.recursiveClean(config.getWorkareaFile(null)); + } + } + } +} diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/internal/TimeoutRule.java b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/internal/TimeoutRule.java new file mode 100755 index 00000000000..cfabbac3cb3 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/internal/TimeoutRule.java @@ -0,0 +1,89 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2014 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.kernel.boot.internal; + +import java.lang.management.ManagementFactory; + +import org.junit.rules.TestRule; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; + +/** + * + */ +public class TimeoutRule implements TestRule { + + /* + * (non-Javadoc) + * + * @see org.junit.rules.TestRule#apply(org.junit.runners.model.Statement, org.junit.runner.Description) + */ + @Override + public Statement apply(final Statement base, final Description arg1) { + return new CoreOnTimeoutStatement(base); + } + + public class CoreOnTimeoutStatement extends Statement { + + private final Statement base; + + /** + * @param base + */ + public CoreOnTimeoutStatement(Statement base) { + this.base = base; + } + + /* + * (non-Javadoc) + * + * @see org.junit.runners.model.Statement#evaluate() + */ + @Override + public void evaluate() throws Throwable { + try { + base.evaluate(); + } catch (Throwable ex) { + // Make sure this is a timeout + if (ex.getMessage() != null && ex.getMessage().startsWith("test timed out")) { + // Run gcore to generate a core dump on platforms where it's available + String osName = System.getProperty("os.name"); + if (osName.startsWith("Linux") || osName.startsWith("Solaris") || osName.startsWith("Sun")) { + int pid = getProcessPid(); + + Process p = Runtime.getRuntime().exec("gcore " + pid); + p.waitFor(); + } + } + + throw ex; + } + + } + + /** + * Get the process PID using the RuntimeMXBean. There are no real guarantees about the format, + * so this could easily break some day. + */ + private int getProcessPid() throws Exception { + String pidStr = ManagementFactory.getRuntimeMXBean().getName(); + + if (pidStr.contains("@")) { + return Integer.parseInt(pidStr.split("@")[0]); + } else { + return -1; + } + + } + + } +} diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/internal/commands/DumpProcessorTest.java b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/internal/commands/DumpProcessorTest.java new file mode 100755 index 00000000000..0474de7d9a4 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/internal/commands/DumpProcessorTest.java @@ -0,0 +1,109 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2015 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.kernel.boot.internal.commands; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertTrue; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import org.jmock.Expectations; +import org.jmock.Mockery; +import org.jmock.integration.junit4.JUnit4Mockery; +import org.jmock.lib.legacy.ClassImposteriser; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Ignore; +import org.junit.Test; + +import test.common.SharedOutputManager; +import test.shared.Constants; + +import com.ibm.ws.kernel.boot.BootstrapConfig; +import com.ibm.ws.kernel.boot.ReturnCode; + +/** + * + */ +@Ignore +public class DumpProcessorTest { + + private static SharedOutputManager outputMgr; + + private final Mockery mockery = new JUnit4Mockery() { + { + setImposteriser(ClassImposteriser.INSTANCE); + } + }; + + /** + * @throws java.lang.Exception + */ + @BeforeClass + public static void setUpBeforeClass() throws Exception { + // capture system output + outputMgr = SharedOutputManager.getInstance(); + outputMgr.captureStreams(); + } + + @AfterClass + public static void tearDownAfterClass() throws Exception { + outputMgr.restoreStreams(); + } + + @Test + public void testUnableToFindJavaDumps() throws Exception { + final String serverName = "server-testUnableToFindJavaDumps"; + final File tempServerDir = new File(new File(Constants.TEST_TMP_ROOT_FILE, "servers"), serverName); + final BootstrapConfig mockBootConfig = mockery.mock(BootstrapConfig.class); + + // Methods called on BootstratpConfig from DumpProcessor execute method. + mockery.checking(new Expectations() { + { + allowing(mockBootConfig).getUserRoot(); + will(returnValue(Constants.TEST_TMP_ROOT_FILE)); + + allowing(mockBootConfig).getOutputFile(null); + will(returnValue(tempServerDir)); + } + }); + + File dumpFile = new File(Constants.TEST_TMP_ROOT_FILE, "dump.testUnableToFindJavaDumps.zip").getAbsoluteFile(); + + assertTrue("Precondition Failed - unable to create temp server directory", tempServerDir.mkdirs()); + + dumpFile.createNewFile(); + + // create paths to heap and system dumps that do not exist + List javaDumps = new ArrayList(); + javaDumps.add(new File(Constants.TEST_TMP_ROOT, "NON_EXISTENT_HEAP_DUMP.phd").getAbsolutePath()); + javaDumps.add(new File(Constants.TEST_TMP_ROOT, "NON_EXISTENT_SYSTEM_DUMP.dmp").getAbsolutePath()); + + try { + DumpProcessor dumpProcessor = new DumpProcessor(serverName, dumpFile, mockBootConfig, javaDumps); + assertEquals(ReturnCode.OK, dumpProcessor.execute()); + + // verify that the user is alerted to missing java dump files: + assertTrue("Did not find expected error message for missing heap dump file", outputMgr.checkForStandardOut("CWWKE0009E.*NON_EXISTENT_HEAP_DUMP.phd")); + assertTrue("Did not find expected error message for missing system dump file", outputMgr.checkForStandardOut("CWWKE0009E.*NON_EXISTENT_SYSTEM_DUMP.dmp")); + } finally { + if (dumpFile.exists()) { + dumpFile.delete(); + } + if (tempServerDir.exists()) { + tempServerDir.delete(); + } + } + } +} diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/internal/commands/FolderStructureGeneratorTest.java b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/internal/commands/FolderStructureGeneratorTest.java new file mode 100755 index 00000000000..ee8244b435e --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/internal/commands/FolderStructureGeneratorTest.java @@ -0,0 +1,59 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.kernel.boot.internal.commands; + +import java.io.File; +import java.util.Formatter; +import java.util.regex.Pattern; + +import org.junit.Assert; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestRule; + +import test.common.SharedOutputManager; + +public class FolderStructureGeneratorTest { + static SharedOutputManager outputMgr = SharedOutputManager.getInstance(); + private static final File dataDir = new File("unittest/test data/dump"); + + @Rule + public TestRule outputRule = outputMgr; + + @Test + public void testMD5() { + String md5 = new ServerDumpPackager.FolderStructureGenerator().md5(new File(dataDir, "/md5-1.txt")); + Assert.assertEquals("a62c519aaabfce3f6d02bfc983f26098", md5); + } + + @Test + public void testPrintFileList() throws Exception { + StringBuilder builder = new StringBuilder(); + Formatter formatter = new Formatter(builder); + new ServerDumpPackager.FolderStructureGenerator().printFileList(dataDir, formatter, dataDir.getAbsolutePath().length() + 1); + String[] lines = builder.toString().split("\r?\n"); + String dateTime = "\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}"; + String sep = Pattern.quote(File.separator); + + int i = 0; + Assert.assertTrue(lines[i], lines[i].matches("d " + dateTime + " lib" + sep)); + i++; + Assert.assertTrue(lines[i], lines[i].matches("f 54 " + dateTime + " c327688b13b293d7d42c60d39e59f8a5 lib" + sep + "md5-2.txt")); + i++; + Assert.assertTrue(lines[i], lines[i].matches("f 46 " + dateTime + " a62c519aaabfce3f6d02bfc983f26098 md5-1.txt")); + i++; + Assert.assertTrue(lines[i], lines[i].matches("d " + dateTime + " usr" + sep)); + i++; + // Files beneath usr should not be printed. + Assert.assertEquals(i, lines.length); + } +} diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/internal/commands/PackageProcessorTest.java b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/internal/commands/PackageProcessorTest.java new file mode 100755 index 00000000000..debfb02e46b --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/internal/commands/PackageProcessorTest.java @@ -0,0 +1,133 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2014 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.kernel.boot.internal.commands; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.jar.Attributes; +import java.util.jar.Manifest; + +import org.jmock.Expectations; +import org.jmock.Mockery; +import org.jmock.integration.junit4.JUnit4Mockery; +import org.jmock.lib.legacy.ClassImposteriser; +import org.junit.Before; +import org.junit.Test; + +import test.shared.Constants; +import test.shared.TestUtils; + +import com.ibm.ws.kernel.boot.BootstrapConfig; +import com.ibm.ws.kernel.boot.internal.BootstrapConstants; + +/** + * + */ +public class PackageProcessorTest { + + /** + * Mock environment. + */ + protected static Mockery mockery; + + /** + * Create the mockery environment. Called before each test to setup a new + * mockery environment for each test, which helps isolate Expectation sets + * and makes it easier to read error log output when Expectations fail. + */ + @Before + public void before() { + mockery = new JUnit4Mockery() { + { + setImposteriser(ClassImposteriser.INSTANCE); + } + }; + } + + /** + * @return A manifest file to use for testing. + */ + private File createTestManifestFile() throws IOException { + File maniFile = TestUtils.createTempFile("PackageProcessorTest.MANIFEST", ".mf"); + maniFile.deleteOnExit(); + + Manifest mf = new Manifest(); + Attributes atts = mf.getMainAttributes(); + + atts.putValue("Manifest-Version", "1.0"); + atts.putValue("Archive-Content-Type", "install"); + atts.putValue("Archive-Root", "wlp/"); + atts.putValue("Bnd-LastModified", "1389725452656"); + atts.putValue("Bundle-Copyright", "The Program materials contained in this file are IBM c" + + "opyright materials. WLP Copyright International Business Machines Corp." + + " 1999, 2013 All Rights Reserved * Licensed Materials - Property of IBM " + + "US Government Users Restricted Rights - Use, duplication or disclosure " + + "restricted by GSA ADP Schedule Contract with IBM Corp."); + atts.putValue("Bundle-Vendor", "IBM"); + atts.putValue("Created-By", "1.6.0 (IBM Corporation)"); + atts.putValue("Extract-Installer", "true"); + atts.putValue("Import-Package", "javax.xml.parsers,org.w3c.dom,org.xml.sax"); + atts.putValue("License-Agreement", "wlp/lafiles/LA"); + atts.putValue("License-Information", "wlp/lafiles/LI"); + atts.putValue("Main-Class", "wlp.lib.extract.SelfExtract"); + + mf.write(new FileOutputStream(maniFile)); + + return maniFile; + } + + /** + * + */ + @Test + public void testBuildManifestForIncludeEqualsUsr() throws Exception { + + final BootstrapConfig mockBootConfig = mockery.mock(BootstrapConfig.class); + + // Methods called on BootstratpConfig from PackageProcessor.CTOR. + mockery.checking(new Expectations() { + { + allowing(mockBootConfig).getUserRoot(); + will(returnValue(Constants.TEST_TMP_ROOT_FILE)); + + allowing(mockBootConfig).getConfigFile(null); + will(returnValue(Constants.TEST_TMP_ROOT_FILE)); + + allowing(mockBootConfig).get(BootstrapConstants.LOC_PROPERTY_SRVTMP_DIR); + will(returnValue(Constants.TEST_TMP_ROOT)); + + allowing(mockBootConfig).getProcessType(); + will(returnValue(BootstrapConstants.LOC_PROCESS_TYPE_SERVER)); + } + }); + + // Run the code under test. + File newManiFile = new PackageProcessor(null, null, mockBootConfig, null, null) + .buildManifestForIncludeEqualsUsr(createTestManifestFile()); + newManiFile.deleteOnExit(); + + // Verify content of new manifest file + Manifest mf = new Manifest(); + mf.read(new FileInputStream(newManiFile)); + + Attributes atts = mf.getMainAttributes(); + assertNull(atts.getValue("License-Information")); + assertNull(atts.getValue("License-Agreement")); + assertEquals("com.ibm.websphere.appserver", atts.getValue("Applies-To")); + assertEquals("false", atts.getValue("Extract-Installer")); + } +} diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/internal/framework/BasicLauncherDelegate.java b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/internal/framework/BasicLauncherDelegate.java new file mode 100755 index 00000000000..5dc0ac9b68d --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/internal/framework/BasicLauncherDelegate.java @@ -0,0 +1,22 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2010, 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.kernel.boot.internal.framework; + +import com.ibm.ws.kernel.boot.BootstrapConfig; +import com.ibm.ws.kernel.launch.internal.LauncherDelegateImpl; + +public class BasicLauncherDelegate extends LauncherDelegateImpl { + public BasicLauncherDelegate(BootstrapConfig config) { + super(config); + } + +} diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/internal/framework/BasicLogProvider.java b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/internal/framework/BasicLogProvider.java new file mode 100755 index 00000000000..68698c56905 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/internal/framework/BasicLogProvider.java @@ -0,0 +1,30 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2010 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.kernel.boot.internal.framework; + +import java.io.File; +import java.util.Map; + +import com.ibm.wsspi.logprovider.LogProvider; + +/** + * + */ +public class BasicLogProvider implements LogProvider { + @Override + public void configure(Map config, + File logLocation, + com.ibm.wsspi.logging.TextFileOutputStreamFactory factory) {} + + @Override + public void stop() {} +} diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/jmx/internal/MBeanServerPipelineTest.java b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/jmx/internal/MBeanServerPipelineTest.java new file mode 100755 index 00000000000..35389b732fe --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/jmx/internal/MBeanServerPipelineTest.java @@ -0,0 +1,185 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.kernel.boot.jmx.internal; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.util.ArrayList; +import java.util.List; + +import javax.management.MBeanServerFactory; + +import org.junit.Before; +import org.junit.Test; + +import com.ibm.ws.kernel.boot.jmx.service.MBeanServerForwarderDelegate; +import com.ibm.ws.kernel.boot.jmx.service.MBeanServerPipeline; + +/** + * + */ +public class MBeanServerPipelineTest { + + private static final String MBEAN_SERVER_BUILDER_PROPERTY = "javax.management.builder.initial"; + private static final String MBEAN_SERVER_BUILDER_CLASS = PlatformMBeanServerBuilder.class.getName(); + + public static final class MBeanServerPipelineHolder implements PlatformMBeanServerBuilderListener { + + private MBeanServerPipeline pipeline; + + @Override + public void platformMBeanServerCreated(MBeanServerPipeline pipeline) { + this.pipeline = pipeline; + } + + public MBeanServerPipeline getMBeanServerPipeline() { + return pipeline; + } + } + + public static class BasicFilter extends MBeanServerForwarderDelegate { + + private final int priority; + + public BasicFilter(int priority) { + this.priority = priority; + } + + @Override + public final int getPriority() { + return priority; + } + } + + public static class PriorityRecorder extends BasicFilter { + + private final List priorities; + + public PriorityRecorder(int priority, List priorities) { + super(priority); + this.priorities = priorities; + } + + @Override + public Integer getMBeanCount() { + priorities.add(getPriority()); + return super.getMBeanCount(); + } + } + + protected PlatformMBeanServer mBeanServer; + protected MBeanServerPipeline mBeanServerPipeline; + + @Before + public void setUp() throws Exception { + System.setProperty(MBEAN_SERVER_BUILDER_PROPERTY, MBEAN_SERVER_BUILDER_CLASS); + mBeanServer = (PlatformMBeanServer) MBeanServerFactory.newMBeanServer(); + MBeanServerPipelineHolder pipelineHolder = new MBeanServerPipelineHolder(); + mBeanServer.invokePlatformMBeanServerCreated(pipelineHolder); + mBeanServerPipeline = pipelineHolder.getMBeanServerPipeline(); + } + + @Test + public void testInsert() { + final BasicFilter f1 = new BasicFilter(5); + final BasicFilter f2 = new BasicFilter(-1); + + assertTrue("Excpected insert of BasicFilter(5) succeeded.", mBeanServerPipeline.insert(f1)); + assertFalse("Excpected insert of BasicFilter(5) failed.", mBeanServerPipeline.insert(f1)); + assertFalse("Excpected insert of BasicFilter(-1) failed.", mBeanServerPipeline.insert(f2)); + assertFalse("Excpected insert of null failed.", mBeanServerPipeline.insert(null)); + } + + @Test + public void testRemove() { + final BasicFilter f1 = new BasicFilter(42); + final BasicFilter f2 = new BasicFilter(8); + final BasicFilter f3 = new BasicFilter(13); + + assertFalse("Excpected remove of BasicFilter(42) failed.", mBeanServerPipeline.remove(f1)); + + mBeanServerPipeline.insert(f1); + mBeanServerPipeline.insert(f2); + mBeanServerPipeline.insert(f3); + + assertTrue("Excpected remove of BasicFilter(42) succeeded.", mBeanServerPipeline.remove(f1)); + assertTrue("Excpected remove of BasicFilter(8) succeeded.", mBeanServerPipeline.remove(f2)); + assertTrue("Excpected remove of BasicFilter(13) succeeded.", mBeanServerPipeline.remove(f3)); + assertFalse("Excpected remove of BasicFilter(42) failed.", mBeanServerPipeline.remove(f1)); + } + + @Test + public void testContains() { + final BasicFilter f1 = new BasicFilter(7); + final BasicFilter f2 = new BasicFilter(13); + final BasicFilter f3 = new BasicFilter(9); + final BasicFilter f4 = new BasicFilter(4); + + assertFalse("Excpected pipeline does not contain BasicFilter(7).", mBeanServerPipeline.contains(f1)); + assertFalse("Excpected pipeline does not contain null.", mBeanServerPipeline.contains(null)); + + mBeanServerPipeline.insert(f1); + mBeanServerPipeline.insert(f2); + mBeanServerPipeline.insert(f3); + + assertTrue("Excpected pipeline contains BasicFilter(7).", mBeanServerPipeline.contains(f1)); + assertTrue("Excpected pipeline contains BasicFilter(13).", mBeanServerPipeline.contains(f2)); + assertTrue("Excpected pipeline contains BasicFilter(9).", mBeanServerPipeline.contains(f3)); + assertFalse("Excpected pipeline does not contain BasicFilter(4).", mBeanServerPipeline.contains(f4)); + + mBeanServerPipeline.remove(f1); + mBeanServerPipeline.remove(f2); + mBeanServerPipeline.remove(f3); + + assertFalse("Excpected pipeline does not contain BasicFilter(7).", mBeanServerPipeline.contains(f1)); + assertFalse("Excpected pipeline does not contain BasicFilter(13).", mBeanServerPipeline.contains(f2)); + assertFalse("Excpected pipeline does not contain BasicFilter(9).", mBeanServerPipeline.contains(f3)); + } + + @Test + public void testPipelineOrder() { + final List priorities = new ArrayList(); + final PriorityRecorder f1 = new PriorityRecorder(7, priorities); + final PriorityRecorder f2 = new PriorityRecorder(13, priorities); + final PriorityRecorder f3 = new PriorityRecorder(9, priorities); + final PriorityRecorder f4 = new PriorityRecorder(4, priorities); + final PriorityRecorder f5 = new PriorityRecorder(15, priorities); + final PriorityRecorder f6 = new PriorityRecorder(6, priorities); + final PriorityRecorder f7 = new PriorityRecorder(12, priorities); + final PriorityRecorder f8 = new PriorityRecorder(8, priorities); + + final int mBeanCount1 = mBeanServer.getMBeanCount(); + + mBeanServerPipeline.insert(f1); + mBeanServerPipeline.insert(f2); + mBeanServerPipeline.insert(f3); + mBeanServerPipeline.insert(f4); + mBeanServerPipeline.insert(f5); + mBeanServerPipeline.insert(f6); + mBeanServerPipeline.insert(f7); + mBeanServerPipeline.insert(f8); + + final int mBeanCount2 = mBeanServer.getMBeanCount(); + assertEquals("Expected MBean counts to be equal.", mBeanCount1, mBeanCount2); + + final int length = priorities.size(); + assertEquals("Expected priorities.size() == 8.", 8, length); + + for (int i = 0; i < length - 1; ++i) { + int t0 = priorities.get(i); + int t1 = priorities.get(i + 1); + assertTrue("Expected '" + t0 + "' >= '" + t1 + "'.", t0 >= t1); + } + } +} diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/jmx/internal/PlatformMBeanServerDelegateTest.java b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/jmx/internal/PlatformMBeanServerDelegateTest.java new file mode 100755 index 00000000000..9567278ecc2 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/jmx/internal/PlatformMBeanServerDelegateTest.java @@ -0,0 +1,31 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.kernel.boot.jmx.internal; + +import static org.junit.Assert.assertTrue; + +import javax.management.MBeanServerDelegate; + +import org.junit.Test; + +/** + * + */ +public class PlatformMBeanServerDelegateTest { + + @Test + public void testPlatformMBeanServerDelegateAttributes() throws Exception { + MBeanServerDelegate mBeanServerDelegate = new PlatformMBeanServerDelegate(); + assertTrue("Expected that server ID starts with WebSphere", + mBeanServerDelegate.getMBeanServerId().startsWith("WebSphere")); + } +} diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/security/WLPDynamicPolicyTest.java b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/security/WLPDynamicPolicyTest.java new file mode 100755 index 00000000000..66c666bfa4b --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/boot/security/WLPDynamicPolicyTest.java @@ -0,0 +1,163 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2016 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.kernel.boot.security; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.net.URL; +import java.security.AllPermission; +import java.security.CodeSource; +import java.security.Permission; +import java.security.PermissionCollection; +import java.security.Policy; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.jmock.Expectations; +import org.jmock.Mockery; +import org.jmock.integration.junit4.JUnit4Mockery; +import org.jmock.lib.legacy.ClassImposteriser; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +/** + * + */ +public class WLPDynamicPolicyTest { + + private static URL testURL1; + private static URL testURL2; + private static URL unlistedURL; + private static List urls; + + private final Mockery mockery = new JUnit4Mockery() { + { + setImposteriser(ClassImposteriser.INSTANCE); + } + }; + private Policy policy; + private WLPDynamicPolicy dynamicPolicy; + private final Permission allPermission = new AllPermission(); + private PermissionsCombiner permissionsCombiner; + private PermissionCollection combinedPermissions; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + testURL1 = new URL("file:///testURL1"); + testURL2 = new URL("file:///testURL2"); + unlistedURL = new URL("file:///unlistedURL"); + urls = new ArrayList(); + urls.add(testURL1); + urls.add(testURL2); + } + + /** + * @throws java.lang.Exception + */ + @AfterClass + public static void tearDownAfterClass() throws Exception {} + + @Before + public void setUp() throws Exception { + policy = Policy.getPolicy(); + dynamicPolicy = new WLPDynamicPolicy(policy, urls); + permissionsCombiner = mockery.mock(PermissionsCombiner.class); + } + + @After + public void tearDown() throws Exception { + Policy.setPolicy(policy); + mockery.assertIsSatisfied(); + } + + /** + * Test method for {@link com.ibm.ws.kernel.boot.internal.WLPDynamicPolicy#getPermissions(java.security.CodeSource)}. + */ + @Test + public void testGetPermissionsCodeSource_AllPermission() { + CodeSource codesource = new CodeSource(testURL1, (java.security.cert.Certificate[]) null); + PermissionCollection pemissionCollection = dynamicPolicy.getPermissions(codesource); + assertTrue("The AllPermission must be granted to the codesource.", pemissionCollection.implies(allPermission)); + } + + @Test + public void testGetPermissionsCodeSource_AllPermissionForDifferentCodeSource() { + CodeSource codesource = new CodeSource(testURL2, (java.security.cert.Certificate[]) null); + PermissionCollection pemissionCollection = dynamicPolicy.getPermissions(codesource); + assertTrue("The AllPermission must be granted to the codesource.", pemissionCollection.implies(allPermission)); + } + + @Test + public void testGetPermissionsCodeSource_AllPermissionForCodeSourceNotListedAndNoStaticPolicy() throws Exception { + dynamicPolicy = new WLPDynamicPolicy(null, urls); + CodeSource codesource = new CodeSource(unlistedURL, (java.security.cert.Certificate[]) null); + PermissionCollection pemissionCollection = dynamicPolicy.getPermissions(codesource); + assertTrue("The AllPermission must be granted to the codesource.", pemissionCollection.implies(allPermission)); + } + + @Test + public void testGetPermissionsCodeSource_StaticPermissionsForCodeSourceNotListed() throws Exception { + CodeSource codesource = new CodeSource(unlistedURL, (java.security.cert.Certificate[]) null); + PermissionCollection pemissionCollection = dynamicPolicy.getPermissions(codesource); + List staticPermissions = Collections.list(policy.getPermissions(codesource).elements()); + assertTrue("The static permissions must be granted to the codesource.", staticPermissions.equals(Collections.list(pemissionCollection.elements()))); + } + + @Test + public void testGetPermissionsCodeSource_StaticPermissionsForNullCodeSource() throws Exception { + dynamicPolicy.setPermissionsCombiner(permissionsCombiner); + CodeSource codesource = null; + + try { + List staticPermissions = Collections.list(policy.getPermissions(codesource).elements()); + PermissionCollection pemissionCollection = dynamicPolicy.getPermissions(codesource); + assertTrue("The static permissions must be granted to the codesource.", staticPermissions.equals(Collections.list(pemissionCollection.elements()))); + } catch (NullPointerException e) { + // Ignore NPE from policy.getPermissions(codesource) since Oracle's JDK does not support a null code source. + } + } + + @Test + public void testGetPermissionsCodeSource_StaticPermissionsForNullLocation() throws Exception { + dynamicPolicy.setPermissionsCombiner(permissionsCombiner); + CodeSource codesource = new CodeSource(null, (java.security.cert.Certificate[]) null); + List staticPermissions = Collections.list(policy.getPermissions(codesource).elements()); + PermissionCollection pemissionCollection = dynamicPolicy.getPermissions(codesource); + assertTrue("The static permissions must be granted to the codesource.", staticPermissions.equals(Collections.list(pemissionCollection.elements()))); + } + + @Test + public void testGetPermissionsCodeSource_CombinedPermissionsForCodeSourceNotListed() throws Exception { + dynamicPolicy.setPermissionsCombiner(permissionsCombiner); + + CodeSource codesource = new CodeSource(unlistedURL, (java.security.cert.Certificate[]) null); + createPermissionsCombinerExpectations(codesource); + PermissionCollection pemissionCollection = dynamicPolicy.getPermissions(codesource); + assertEquals("The combined permissions must be granted to the codesource.", combinedPermissions, pemissionCollection); + } + + private void createPermissionsCombinerExpectations(final CodeSource codesource) { + combinedPermissions = mockery.mock(PermissionCollection.class); + mockery.checking(new Expectations() { + { + one(permissionsCombiner).getCombinedPermissions(with(any(PermissionCollection.class)), with(codesource)); + will(returnValue(combinedPermissions)); + } + }); + } + +} diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/internal/classloader/JarFileClassLoaderTest.java b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/internal/classloader/JarFileClassLoaderTest.java new file mode 100755 index 00000000000..5bd444a0b47 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/internal/classloader/JarFileClassLoaderTest.java @@ -0,0 +1,217 @@ +package com.ibm.ws.kernel.internal.classloader; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.net.URLConnection; +import java.net.URLStreamHandler; +import java.util.Enumeration; +import java.util.Properties; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Ignore; +import org.junit.Test; + +import test.common.SharedOutputManager; + +public class JarFileClassLoaderTest { + + static SharedOutputManager outputMgr; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + // make stdout/stderr "quiet"-- no output will show up for test + // unless one of the copy methods or documentThrowable is called + outputMgr = SharedOutputManager.getInstance(); + outputMgr.captureStreams(); + } + + @AfterClass + public static void tearDownAfterClass() throws Exception { + // Make stdout and stderr "normal" + outputMgr.restoreStreams(); + } + + private JarFileClassLoader getFileURLClassLoader(boolean verify) throws Exception { + File badJar = new File("../com.ibm.ws.kernel.boot_test/unittest/test data/signed/bad.jar"); + assertTrue(badJar.exists()); + return new JarFileClassLoader(new URL[] { badJar.toURI().toURL() }, verify, null); + } + + @Test + public void testDirectoryClassPath() throws Exception { + File directory = new File("../com.ibm.ws.kernel.boot_test/unittest/test data/"); + assertTrue(directory.exists()); + JarFileClassLoader classloader = new JarFileClassLoader(new URL[] { directory.toURI().toURL() }, false, null); + assertNotNull(classloader.getResource("signed/bad.jar")); + } + + @Ignore + public void testFileURL() throws Exception { + JarFileClassLoader loader = null; + + loader = getFileURLClassLoader(true); + testClassLoaderVerify(loader); + + loader = getFileURLClassLoader(false); + testClassLoaderNoVerify(loader); + } + + private JarFileClassLoader getNonFileURLClassLoader(boolean verify) throws Exception { + final File badJar = new File("../com.ibm.ws.kernel.boot_test/unittest/test data/signed/bad.jar"); + assertTrue(badJar.exists()); + URLStreamHandler handler = (new URLStreamHandler() { + @Override + protected URLConnection openConnection(URL u) throws IOException { + return new URLConnection(u) { + @Override + public void connect() throws IOException {} + + @Override + public InputStream getInputStream() throws IOException { + return new FileInputStream(badJar); + } + }; + } + }); + URL url = new URL("foo", "", -1, badJar.getAbsolutePath(), handler); + return new JarFileClassLoader(new URL[] { url }, verify, null); + } + + @Ignore + public void testNonFileURL() throws Exception { + JarFileClassLoader loader = null; + + loader = getNonFileURLClassLoader(true); + System.out.println(loader); + System.out.println(loader.getURLs()); + testClassLoaderVerify(loader); + + loader = getNonFileURLClassLoader(false); + System.out.println(loader); + System.out.println(loader.getURLs()); + testClassLoaderNoVerify(loader); + } + + private void testClassLoaderNoVerify(JarFileClassLoader loader) throws Exception { + // test loadClass() + assertNotNull(loader.loadClass("org.eclipse.equinox.metatype.Extendable")); + + // test getResource() + URL resource = loader.getResource("org/eclipse/equinox/metatype/EquinoxMetaTypeService.class"); + assertNotNull(resource); + assertNotNull(resource.openStream()); + + // test getResources() + Enumeration resources = loader.getResources("org/eclipse/equinox/metatype/EquinoxMetaTypeInformation.class"); + assertNotNull(resources); + assertTrue(resources.hasMoreElements()); + assertNotNull(resources.nextElement().openStream()); + } + + private void testClassLoaderVerify(JarFileClassLoader loader) throws Exception { + // test loadClass() + try { + loader.loadClass("org.eclipse.equinox.metatype.Extendable"); + fail("Did not throw SecurityException"); + } catch (SecurityException e) { + // we expect SecurityException + } + + // test getResource() + URL resource = loader.getResource("org/eclipse/equinox/metatype/EquinoxMetaTypeService.class"); + assertNotNull(resource); + try { + resource.openStream(); + fail("Did not throw SecurityException"); + } catch (SecurityException e) { + // we expect SecurityException + } + + // test getResources() + Enumeration resources = loader.getResources("org/eclipse/equinox/metatype/EquinoxMetaTypeInformation.class"); + assertNotNull(resources); + assertTrue(resources.hasMoreElements()); + try { + resources.nextElement().openStream(); + fail("Did not throw SecurityException"); + } catch (SecurityException e) { + // we expect SecurityException + } + } + + private ClassLoader getResourceTestURLClassLoader(boolean urlLoader) throws MalformedURLException { + File parentJar = new File("../com.ibm.ws.kernel.boot_test/unittest/test data/resources/resources1.jar"); + assertTrue("No parent jar: " + parentJar, parentJar.exists()); + File childJar = new File("../com.ibm.ws.kernel.boot_test/unittest/test data/resources/resources2.jar"); + assertTrue("No child jar: " + childJar, childJar.exists()); + URLClassLoader parent = new URLClassLoader(new URL[] { parentJar.toURI().toURL() }); + URL[] childUrls = new URL[] { childJar.toURI().toURL() }; + if (urlLoader) { + return new BootstrapChildFirstURLClassloader(childUrls, parent); + } else { + return new BootstrapChildFirstJarClassloader(childUrls, parent); + } + } + + @Test + public void testChildFirstGetResource() throws MalformedURLException { + doTestChildFirstGetResource(getResourceTestURLClassLoader(true)); + doTestChildFirstGetResource(getResourceTestURLClassLoader(false)); + } + + public void doTestChildFirstGetResource(ClassLoader loader) { + URL bootResource = loader.getResource("com/ibm/ws/kernel/boot/test.properties"); + assertNotNull("no boot resource found.", bootResource); + URL testResource = loader.getResource("resources/test.properties"); + assertNotNull("no test resource found.", testResource); + assertResource(bootResource, "1"); + assertResource(testResource, "2"); + } + + private void assertResource(URL resource, String expected) { + Properties props = new Properties(); + try { + props.load(resource.openStream()); + } catch (IOException e) { + fail("Failed to load resource: " + e.toString()); + } + assertEquals("Wrong resource test value", expected, props.getProperty("test")); + } + + @Test + public void testChildFirstGetResources() throws MalformedURLException { + doTestChildFirstGetResources(getResourceTestURLClassLoader(true)); + doTestChildFirstGetResources(getResourceTestURLClassLoader(false)); + } + + public void doTestChildFirstGetResources(ClassLoader loader) { + try { + Enumeration bootResources = loader.getResources("com/ibm/ws/kernel/boot/test.properties"); + assertNotNull("no boot resource found.", bootResources); + Enumeration testResources = loader.getResources("resources/test.properties"); + assertNotNull("no test resource found.", testResources); + assertResources(bootResources, "1", "2"); + assertResources(testResources, "2", "1"); + } catch (IOException e) { + fail("Failed to get resources: " + e.toString()); + } + } + + private void assertResources(Enumeration testResources, String... expected) { + for (String expectedValue : expected) { + assertResource(testResources.nextElement(), expectedValue); + } + } + +} diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/internal/reference/Handler.java b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/internal/reference/Handler.java new file mode 100755 index 00000000000..e4ecccdc593 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/internal/reference/Handler.java @@ -0,0 +1,39 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.kernel.internal.reference; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.net.URLConnection; +import java.net.URLStreamHandler; + +/** + * + */ +public class Handler extends URLStreamHandler { + + /** {@inheritDoc} */ + @Override + protected URLConnection openConnection(URL arg0) throws IOException { + return new URLConnection(arg0) { + @Override + public void connect() throws IOException {} + + @Override + public InputStream getInputStream() { + return null; + } + }; + } + +} diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/launch/internal/FrameworkConfigurationTest.java b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/launch/internal/FrameworkConfigurationTest.java new file mode 100755 index 00000000000..687ca558952 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/launch/internal/FrameworkConfigurationTest.java @@ -0,0 +1,40 @@ +package com.ibm.ws.kernel.launch.internal; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import test.common.SharedOutputManager; + +public class FrameworkConfigurationTest { + + static SharedOutputManager outputMgr; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + // make stdout/stderr "quiet"-- no output will show up for test + // unless one of the copy methods or documentThrowable is called + outputMgr = SharedOutputManager.getInstance(); + outputMgr.captureStreams(); + } + + @AfterClass + public static void tearDownAfterClass() throws Exception { + // Make stdout and stderr "normal" + outputMgr.restoreStreams(); + } + + @After + public void tearDown() throws Exception { + // Clear the output generated after each method invocation, this keeps + // things sane + outputMgr.resetStreams(); + } + + @Test + public void testStub() { + // There are no longer and tests in this suite! + } + +} diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/launch/internal/FrameworkManagerTimeTest.java b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/launch/internal/FrameworkManagerTimeTest.java new file mode 100755 index 00000000000..f294374215b --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/launch/internal/FrameworkManagerTimeTest.java @@ -0,0 +1,276 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2014 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.kernel.launch.internal; + +import java.text.DecimalFormatSymbols; +import java.util.Locale; + +import junit.framework.Assert; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import test.common.SharedOutputManager; + +/** + * + */ +public class FrameworkManagerTimeTest { + static SharedOutputManager outputMgr; + static Locale saveLocale; + static FrameworkManager frameworkManager; + + /** + * @throws java.lang.Exception + */ + @BeforeClass + public static void setUpBeforeClass() throws Exception { + // make stdout/stderr "quiet"-- no output will show up for test + // unless one of the copy methods or documentThrowable is called + outputMgr = SharedOutputManager.getInstance(); + outputMgr.captureStreams(); + saveLocale = Locale.getDefault(); + frameworkManager = new FrameworkManager(); + } + + /** + * @throws java.lang.Exception + */ + @AfterClass + public static void tearDownAfterClass() throws Exception { + // Make stdout and stderr "normal" + outputMgr.restoreStreams(); + Locale.setDefault(saveLocale); + + } + + @Test + public void testgetElapsedTimeAsStringFromFrameworkManager_English() { + @SuppressWarnings("unused") + final String m = "testgetElapsedTimeAsStringFromFrameworkManager_English"; + String loc = "en"; //example: "pl" or "en" + DecimalFormatSymbols decimalFormatSymbols = new DecimalFormatSymbols(new Locale(loc)); + String days = " days, "; + String hours = " hours, "; + String min = " minutes, "; + String sec = " seconds"; + String decSep = decimalFormatSymbols.getDecimalSeparator() + ""; //Decimal Separator in English is '.' + String grpSep = decimalFormatSymbols.getGroupingSeparator() + ""; //Grouping Separator in English is ',' + + testgetElapsedTimeAsStringFromFrameworkManager(loc, days, hours, min, sec, decSep, grpSep); + + } + + @Test + public void testgetElapsedTimeAsStringFromFrameworkManager_Polish() { + @SuppressWarnings("unused") + final String m = "testgetElapsedTimeAsStringFromFrameworkManager_Polish"; + String loc = "pl"; //example: "pl" or "en" + DecimalFormatSymbols decimalFormatSymbols = new DecimalFormatSymbols(new Locale(loc)); + String days = " days, "; // dn. + String hours = " hours, ";// godz. + String min = " minutes, ";// min. + String sec = " seconds";// sek. + String decSep = decimalFormatSymbols.getDecimalSeparator() + ""; //Decimal Separator in Polish is ',' + String grpSep = decimalFormatSymbols.getGroupingSeparator() + ""; //Grouping Separator + + testgetElapsedTimeAsStringFromFrameworkManager(loc, days, hours, min, sec, decSep, grpSep); + + } + + private void testgetElapsedTimeAsStringFromFrameworkManager(String locale, String days, String hours, String min, String sec, String decSep, String grpSep) { + @SuppressWarnings("unused") + final String m = "testgetElapsedTimeAsStringFromFrameworkManager"; + Locale.setDefault(new Locale(locale)); //example: "pl" or "en" + long elapsedTimeVerify; + String[] processedTime = new String[48]; + String[] expectedResults = new String[48]; + + //Testing the first branch of the 'if' statement + //First Group- testing the mixed units + elapsedTimeVerify = 2007208124L;//The milliseconds of 23 days, 5 hours, 33 minutes, 28.124 seconds + expectedResults[0] = "23" + days + "5" + hours + "33" + min + "28" + decSep + "124" + sec; + processedTime[0] = frameworkManager.getElapsedTime(true, elapsedTimeVerify); + elapsedTimeVerify = 1989208124L;//The milliseconds of 23 days, 33 minutes, 28.124 seconds + expectedResults[1] = "23" + days + "33" + min + "28" + decSep + "124" + sec; + processedTime[1] = frameworkManager.getElapsedTime(true, elapsedTimeVerify); + elapsedTimeVerify = 2005228124L;//The milliseconds of 23 days, 5 hours, 28.124 seconds + expectedResults[2] = "23" + days + "5" + hours + "28" + decSep + "124" + sec; + processedTime[2] = frameworkManager.getElapsedTime(true, elapsedTimeVerify); + elapsedTimeVerify = 1987228124L;//The milliseconds of 23 days, 28.124 seconds + expectedResults[3] = "23" + days + "28" + decSep + "124" + sec; + processedTime[3] = frameworkManager.getElapsedTime(true, elapsedTimeVerify); + elapsedTimeVerify = 20008124L; //The milliseconds of 5 hours, 33 minutes, 28.124 seconds + expectedResults[4] = "5" + hours + "33" + min + "28" + decSep + "124" + sec; + processedTime[4] = frameworkManager.getElapsedTime(true, elapsedTimeVerify); + elapsedTimeVerify = 18028124L; //The milliseconds of 5 hours, 28.124 seconds + expectedResults[5] = "5" + hours + "28" + decSep + "124" + sec; + processedTime[5] = frameworkManager.getElapsedTime(true, elapsedTimeVerify); + elapsedTimeVerify = 2008124L; //The milliseconds of 33 minutes, 28.124 seconds + expectedResults[6] = "33" + min + "28" + decSep + "124" + sec; + processedTime[6] = frameworkManager.getElapsedTime(true, elapsedTimeVerify); + elapsedTimeVerify = 28124L; //The milliseconds of 28.124 seconds + expectedResults[7] = "28" + decSep + "124" + sec; + processedTime[7] = frameworkManager.getElapsedTime(true, elapsedTimeVerify); + elapsedTimeVerify = 28120L; //The milliseconds of 28.12 seconds + expectedResults[8] = "28" + decSep + "12" + sec; + processedTime[8] = frameworkManager.getElapsedTime(true, elapsedTimeVerify); + elapsedTimeVerify = 28100L; //The milliseconds of 28.1 seconds + expectedResults[9] = "28" + decSep + "1" + sec; + processedTime[9] = frameworkManager.getElapsedTime(true, elapsedTimeVerify); + elapsedTimeVerify = 28000L; //The milliseconds of 28 seconds + expectedResults[10] = "28" + sec; + processedTime[10] = frameworkManager.getElapsedTime(true, elapsedTimeVerify); + elapsedTimeVerify = 2000L; //The milliseconds of 2 seconds + expectedResults[11] = "2" + sec; + processedTime[11] = frameworkManager.getElapsedTime(true, elapsedTimeVerify); + elapsedTimeVerify = 200L; //The milliseconds of 0.2 seconds + expectedResults[12] = "0" + decSep + "2" + sec; + processedTime[12] = frameworkManager.getElapsedTime(true, elapsedTimeVerify); + elapsedTimeVerify = 20L; //The milliseconds of 0.02 seconds + expectedResults[13] = "0" + decSep + "02" + sec; + processedTime[13] = frameworkManager.getElapsedTime(true, elapsedTimeVerify); + elapsedTimeVerify = 2L; //The milliseconds of 0.002 seconds + expectedResults[14] = "0" + decSep + "002" + sec; + processedTime[14] = frameworkManager.getElapsedTime(true, elapsedTimeVerify); + elapsedTimeVerify = 1009L; //The milliseconds of 1.009 seconds + expectedResults[15] = "1" + decSep + "009" + sec; + processedTime[15] = frameworkManager.getElapsedTime(true, elapsedTimeVerify); + + //Second Group - testing with zero seconds + elapsedTimeVerify = 0L; //The milliseconds of 0 seconds + expectedResults[16] = "0" + sec; + processedTime[16] = frameworkManager.getElapsedTime(true, elapsedTimeVerify); + elapsedTimeVerify = 60000L; //The milliseconds of 1 minutes, 0 seconds + expectedResults[17] = "1" + min + "0" + sec; + processedTime[17] = frameworkManager.getElapsedTime(true, elapsedTimeVerify); + elapsedTimeVerify = 1987200000L;//The milliseconds of 23 days, 0 seconds + expectedResults[18] = "23" + days + "0" + sec; + processedTime[18] = frameworkManager.getElapsedTime(true, elapsedTimeVerify); + elapsedTimeVerify = 18000000L; //The milliseconds of 5 hours, 0 seconds + expectedResults[19] = "5" + hours + "0" + sec; + processedTime[19] = frameworkManager.getElapsedTime(true, elapsedTimeVerify); + elapsedTimeVerify = 1980000L; //The milliseconds of 33 minutes, 0 seconds + expectedResults[20] = "33" + min + "0" + sec; + processedTime[20] = frameworkManager.getElapsedTime(true, elapsedTimeVerify); + + //Third Group - testing with maximum value of Long + elapsedTimeVerify = Long.MAX_VALUE; //The milliseconds of 106,751,991,167 days, 7 hours, 12 minutes 55.635 seconds + //(Seconds rounded from 55.634688) However due in difference in calculation accuracy when the Remainder '%' is used on Long, the + // Value will be 55.807 + //Long.MAX_VALUE = 9223372036854775807 + expectedResults[21] = "106" + grpSep + "751" + grpSep + "991" + grpSep + "167" + days + "7" + hours + "12" + min + "55" + decSep + "807" + sec; + processedTime[21] = frameworkManager.getElapsedTime(true, elapsedTimeVerify); + + //Third Group - Negative testing + elapsedTimeVerify = -1L; // No Time in negative value - Currently return 0 seconds + expectedResults[22] = "0" + sec; + processedTime[22] = frameworkManager.getElapsedTime(true, elapsedTimeVerify); + elapsedTimeVerify = Long.MIN_VALUE; // No Time in negative value - Currently return 0 seconds + // Long.MIN_VALUE = -9223372036854775808 + expectedResults[23] = "0" + sec; + processedTime[23] = frameworkManager.getElapsedTime(true, elapsedTimeVerify); + + //Testing the second branch of the 'if' statement, the 'else' + //First Group + elapsedTimeVerify = 1009L; //The milliseconds of 1.009 seconds + expectedResults[24] = "1" + decSep + "009" + sec; + processedTime[24] = frameworkManager.getElapsedTime(false, elapsedTimeVerify); + elapsedTimeVerify = 0L; //The milliseconds of 0 seconds + expectedResults[25] = "0" + sec; + processedTime[25] = frameworkManager.getElapsedTime(false, elapsedTimeVerify); + elapsedTimeVerify = 2L; //The milliseconds of 0.002 seconds + expectedResults[26] = "0" + decSep + "002" + sec; + processedTime[26] = frameworkManager.getElapsedTime(false, elapsedTimeVerify); + elapsedTimeVerify = 20L; //The milliseconds of 0.02 seconds + expectedResults[27] = "0" + decSep + "02" + sec; + processedTime[27] = frameworkManager.getElapsedTime(false, elapsedTimeVerify); + elapsedTimeVerify = 200L; //The milliseconds of 0.2 seconds + expectedResults[28] = "0" + decSep + "2" + sec; + processedTime[28] = frameworkManager.getElapsedTime(false, elapsedTimeVerify); + elapsedTimeVerify = 2000L; //The milliseconds of 2 seconds + expectedResults[29] = "2" + sec; + processedTime[29] = frameworkManager.getElapsedTime(false, elapsedTimeVerify); + elapsedTimeVerify = 20000L; //The milliseconds of 20 seconds + expectedResults[30] = "20" + sec; + processedTime[30] = frameworkManager.getElapsedTime(false, elapsedTimeVerify); + elapsedTimeVerify = 200000L; //The milliseconds of 200 seconds + expectedResults[31] = "200" + sec; + processedTime[31] = frameworkManager.getElapsedTime(false, elapsedTimeVerify); + elapsedTimeVerify = 2000000L; //The milliseconds of 2,000 seconds + expectedResults[32] = "2" + grpSep + "000" + sec; + processedTime[32] = frameworkManager.getElapsedTime(false, elapsedTimeVerify); + elapsedTimeVerify = 20000000L; //The milliseconds of 20,000 seconds + expectedResults[33] = "20" + grpSep + "000" + sec; + processedTime[33] = frameworkManager.getElapsedTime(false, elapsedTimeVerify); + elapsedTimeVerify = 200000000L; //The milliseconds of 200,000 seconds + expectedResults[34] = "200" + grpSep + "000" + sec; + processedTime[34] = frameworkManager.getElapsedTime(false, elapsedTimeVerify); + elapsedTimeVerify = 2000000000L; //The milliseconds of 2,000,000 seconds + expectedResults[35] = "2" + grpSep + "000" + grpSep + "000" + sec; + processedTime[35] = frameworkManager.getElapsedTime(false, elapsedTimeVerify); + elapsedTimeVerify = 20000000000L; //The milliseconds of 20,000,000 seconds + expectedResults[36] = "20" + grpSep + "000" + grpSep + "000" + sec; + processedTime[36] = frameworkManager.getElapsedTime(false, elapsedTimeVerify); + elapsedTimeVerify = 200000000000L; //The milliseconds of 200,000,000 seconds + expectedResults[37] = "200" + grpSep + "000" + grpSep + "000" + sec; + processedTime[37] = frameworkManager.getElapsedTime(false, elapsedTimeVerify); + elapsedTimeVerify = 2000000000000L; //The milliseconds of 2,000,000,000 seconds + expectedResults[38] = "2" + grpSep + "000" + grpSep + "000" + grpSep + "000" + sec; + processedTime[38] = frameworkManager.getElapsedTime(false, elapsedTimeVerify); + elapsedTimeVerify = 20000000000000L; //The milliseconds of 20,000,000,000 seconds + expectedResults[39] = "20" + grpSep + "000" + grpSep + "000" + grpSep + "000" + sec; + processedTime[39] = frameworkManager.getElapsedTime(false, elapsedTimeVerify); + elapsedTimeVerify = 200000000000000L; //The milliseconds of 200,000,000,000 seconds + expectedResults[40] = "200" + grpSep + "000" + grpSep + "000" + grpSep + "000" + sec; + processedTime[40] = frameworkManager.getElapsedTime(false, elapsedTimeVerify); + elapsedTimeVerify = 2000000000000000L; //The milliseconds of 2,000,000,000,000 seconds + expectedResults[41] = "2" + grpSep + "000" + grpSep + "000" + grpSep + "000" + grpSep + "000" + sec; + processedTime[41] = frameworkManager.getElapsedTime(false, elapsedTimeVerify); + elapsedTimeVerify = 20000000000000000L; //The milliseconds of 20,000,000,000,000 seconds + expectedResults[42] = "20" + grpSep + "000" + grpSep + "000" + grpSep + "000" + grpSep + "000" + sec; + processedTime[42] = frameworkManager.getElapsedTime(false, elapsedTimeVerify); + elapsedTimeVerify = 200000000000000000L; //The milliseconds of 200,000,000,000,000 seconds + expectedResults[43] = "200" + grpSep + "000" + grpSep + "000" + grpSep + "000" + grpSep + "000" + sec; + processedTime[43] = frameworkManager.getElapsedTime(false, elapsedTimeVerify); + elapsedTimeVerify = 2000000000000000000L; //The milliseconds of 2,000,000,000,000,000 seconds + expectedResults[44] = "2" + grpSep + "000" + grpSep + "000" + grpSep + "000" + grpSep + "000" + grpSep + "000" + sec; + processedTime[44] = frameworkManager.getElapsedTime(false, elapsedTimeVerify); + //Second Group - testing with maximum value of Long + elapsedTimeVerify = Long.MAX_VALUE; //The milliseconds of 9,223,372,036,854,775.807 seconds + // Long.MAX_VALUE = 9223372036854775807 + // The double will convert these seconds to 9,223,372,036,854,776 seconds + expectedResults[45] = "9" + grpSep + "223" + grpSep + "372" + grpSep + "036" + grpSep + "854" + grpSep + "776" + sec; + processedTime[45] = frameworkManager.getElapsedTime(false, elapsedTimeVerify); + //Third Group - Negative testing + elapsedTimeVerify = -1L; // No Time in negative value - Currently return 0 seconds + expectedResults[46] = "0" + sec; + processedTime[46] = frameworkManager.getElapsedTime(false, elapsedTimeVerify); + elapsedTimeVerify = Long.MIN_VALUE; // No Time in negative value - Currently return 0 seconds + // Long.MIN_VALUE = -9223372036854775808 + expectedResults[47] = "0" + sec; + processedTime[47] = frameworkManager.getElapsedTime(false, elapsedTimeVerify); + + // Assisting the results + String whiteSpacePattern = "\\s"; + //int i = 47; + for (int i = 0; i < expectedResults.length; i++) { + boolean result = expectedResults[i].replaceAll(whiteSpacePattern, ""). + equalsIgnoreCase(processedTime[i].replaceAll(whiteSpacePattern, "")); + String errMsg = "Elapsed Time is not formated correctly for the " + Locale.getDefault() + " language.\n" + + "The expected result at test # [" + i + "] is: " + expectedResults[i] + "\n" + + "The actual result is: " + processedTime[i]; + Assert.assertEquals(errMsg, true, result); + } + } +} diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/launch/internal/LibertyProcessImplTest.java b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/launch/internal/LibertyProcessImplTest.java new file mode 100755 index 00000000000..60f26726b8e --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/launch/internal/LibertyProcessImplTest.java @@ -0,0 +1,84 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2010 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.kernel.launch.internal; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.util.ArrayList; +import java.util.Arrays; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import test.common.SharedOutputManager; + +/** + * + */ +public class LibertyProcessImplTest { + static SharedOutputManager outputMgr; + + /** + * @throws java.lang.Exception + */ + @BeforeClass + public static void setUpBeforeClass() throws Exception { + // make stdout/stderr "quiet"-- no output will show up for test + // unless one of the copy methods or documentThrowable is called + outputMgr = SharedOutputManager.getInstance(); + outputMgr.captureStreams(); + } + + /** + * @throws java.lang.Exception + */ + @AfterClass + public static void tearDownAfterClass() throws Exception { + // Make stdout and stderr "normal" + outputMgr.restoreStreams(); + } + + /** + * Test method for {@link com.ibm.ws.kernel.launch.internal.LibertyProcessImpl#getArgs()} . + */ + @Test + public void testGetArgs() { + final String m = "testGetArgs"; + + LibertyProcessImpl cmi; + String[] list; + + try { + cmi = new LibertyProcessImpl(null, null); + list = cmi.getArgs(); + assertNotNull(list); + assertEquals(0, list.length); + + cmi = new LibertyProcessImpl(new ArrayList(), null); + list = cmi.getArgs(); + assertNotNull(list); + assertEquals(0, list.length); + + final String dummy = "dummy"; + + cmi = new LibertyProcessImpl(Arrays.asList(new String[] { dummy }), null); + list = cmi.getArgs(); + assertNotNull(list); + assertEquals(1, list.length); + assertEquals(dummy, list[0]); + } catch (Throwable t) { + outputMgr.failWithThrowable(m, t); + } + } +} diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/launch/internal/NoRethrowSecurityManagerTest.java b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/launch/internal/NoRethrowSecurityManagerTest.java new file mode 100755 index 00000000000..7de936619d6 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/launch/internal/NoRethrowSecurityManagerTest.java @@ -0,0 +1,159 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2015 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.kernel.launch.internal; + +import static com.ibm.ws.kernel.launch.internal.NoRethrowSecurityManager.lineSep; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.FilePermission; +import java.security.AllPermission; +import java.security.CodeSource; +import java.security.Permission; +import java.security.Permissions; +import java.security.ProtectionDomain; +import java.security.SecureClassLoader; +import java.util.Enumeration; + +import org.jmock.Mockery; +import org.jmock.integration.junit4.JUnit4Mockery; +import org.jmock.lib.legacy.ClassImposteriser; +import org.junit.BeforeClass; +import org.junit.Test; + +/** + * Unit test for {@link NoRethrowSecurityManager} class. + */ +public class NoRethrowSecurityManagerTest { + + private static final Mockery mock = new JUnit4Mockery() { + { + setImposteriser(ClassImposteriser.INSTANCE); + } + }; + + private static final Permission PERMISSION1 = new FilePermission("<>", "read"); + private static final Permission PERMISSION2 = new AllPermission(); + + private static final CodeSource CODE_SOURCE2 = mock.mock(CodeSource.class, "source with no URL"); + + private static final Permissions PERMISSIONS = new Permissions(); + + private final ClassLoader CLASS_LOADER = ClassLoader.getSystemClassLoader(); + private final Class[] CLASS_ARRAY = { String.class, NoRethrowSecurityManager.class, + SecureClassLoader.class, org.osgi.service.permissionadmin.PermissionInfo.class }; + + private final String CS_STR_NULL_CODE_SOURCE = "null code source"; + private final String CS_STR_NULL_URL = "null code URL"; + + private final String PERMISSION_STR1 = "ClassLoader: Primordial Classloader" + lineSep + + " Permissions granted to CodeSource null" + lineSep + + " {" + lineSep + + " }"; + private String PERMISSION_STR2 = "ClassLoader: " + CLASS_LOADER.getClass().getName() + lineSep + + " Permissions granted to CodeSource " + CODE_SOURCE2 + lineSep + + " {" + lineSep + + " ;" + lineSep + + " ;" + lineSep + + " }"; + + @BeforeClass + public static void setup() { + PERMISSIONS.add(PERMISSION1); + PERMISSIONS.add(PERMISSION2); + } + + @Test + public void checkPermissionTest() { + NoRethrowSecurityManager secManager = new NoRethrowSecurityManager(); + try { + secManager.checkPermission(PERMISSION1); + } catch (Exception e) { + fail(e.getMessage()); + } + } + + @Test + public void handleSecurityExceptionTest() { + NoRethrowSecurityManager secManager = new NoRethrowSecurityManager(); + try { + secManager.checkPermission(PERMISSION2); + } catch (SecurityException e) { + fail(e.getMessage()); + } + } + + @Test + public void getCodeSorce() { + NoRethrowSecurityManager secManager = new NoRethrowSecurityManager(); + String csLocation = getClass().getProtectionDomain().getCodeSource().getLocation().toString(); + + ProtectionDomain protectionDomain = new ProtectionDomain(null, null); + String csstr = secManager.getCodeSource(protectionDomain); + assertTrue("The result code source string is incorrect, expected '" + CS_STR_NULL_CODE_SOURCE + + "' and got '" + csstr + "'.", CS_STR_NULL_CODE_SOURCE.equals(csstr)); + + protectionDomain = new ProtectionDomain(CODE_SOURCE2, null); + csstr = secManager.getCodeSource(protectionDomain); + assertTrue("The result code source string is incorrect, expected '" + CS_STR_NULL_URL + + "' and got '" + csstr + "'.", CS_STR_NULL_URL.equals(csstr)); + + protectionDomain = getClass().getProtectionDomain(); + csstr = secManager.getCodeSource(protectionDomain); + assertTrue("The result code source string is incorrect, expected '" + csLocation + + "' and got '" + csstr + "'.", csLocation.equals(csstr)); + } + + @Test + public void permissionToStringTest() { + NoRethrowSecurityManager secManager = new NoRethrowSecurityManager(); + String result = secManager.permissionToString(null, null, null); + assertTrue("The result string is incorrect, should be: \n" + PERMISSION_STR1 + + "\n and got : " + result, PERMISSION_STR1.equals(result)); + + configPermissionsString(); + result = secManager.permissionToString(CODE_SOURCE2, CLASS_LOADER, PERMISSIONS); + assertTrue("The result string is incorrect, should be: \n" + PERMISSION_STR2 + + "\n and got :" + result, PERMISSION_STR2.equals(result)); + } + + @Test + public void isOffendingClassTest() { + NoRethrowSecurityManager secManager = new NoRethrowSecurityManager(); + ProtectionDomain domain = getClass().getProtectionDomain(); + boolean result; + + result = secManager.isOffendingClass(CLASS_ARRAY, 0, domain, PERMISSION1); + assertFalse("The class " + CLASS_ARRAY[0] + " should not be offending class.", result); + + result = secManager.isOffendingClass(CLASS_ARRAY, 1, domain, PERMISSION1); + assertFalse("The class " + CLASS_ARRAY[1] + " should not be offending class.", result); + + result = secManager.isOffendingClass(CLASS_ARRAY, 2, domain, PERMISSION1); + assertFalse("The class " + CLASS_ARRAY[2] + " should not be offending class.", result); + + result = secManager.isOffendingClass(CLASS_ARRAY, 3, domain, PERMISSION1); + assertTrue("The class " + CLASS_ARRAY[3] + " should be offending class.", result); + + } + + private void configPermissionsString() { + Enumeration elements = PERMISSIONS.elements(); + int cont = 1; + while (elements.hasMoreElements()) { + Permission p = elements.nextElement(); + PERMISSION_STR2 = PERMISSION_STR2.replaceFirst("", p.toString()); + cont++; + } + } +} diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/launch/internal/ProvisionerTest.java b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/launch/internal/ProvisionerTest.java new file mode 100755 index 00000000000..8211c4d7697 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/launch/internal/ProvisionerTest.java @@ -0,0 +1,527 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2010, 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.kernel.launch.internal; + +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.io.File; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.jmock.Expectations; +import org.jmock.Mockery; +import org.jmock.integration.junit4.JMock; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestName; +import org.junit.rules.TestRule; +import org.junit.runner.RunWith; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.BundleException; +import org.osgi.framework.Constants; +import org.osgi.framework.startlevel.BundleStartLevel; +import org.osgi.framework.startlevel.FrameworkStartLevel; +import org.osgi.framework.wiring.BundleRevision; + +import com.ibm.ws.kernel.boot.LaunchException; +import com.ibm.ws.kernel.boot.SharedBootstrapConfig; +import com.ibm.ws.kernel.boot.internal.KernelResolver; +import com.ibm.ws.kernel.boot.internal.KernelStartLevel; +import com.ibm.ws.kernel.launch.internal.Provisioner.InvalidBundleContextException; +import com.ibm.ws.kernel.provisioning.BundleRepositoryRegistry; + +import test.common.SharedOutputManager; +import test.shared.TestUtils; + +@RunWith(JMock.class) +public class ProvisionerTest { + static SharedOutputManager outputMgr = SharedOutputManager.getInstance(); + static SharedBootstrapConfig config; + + @Rule + public TestName testName = new TestName(); + + @Rule + public TestRule outputRule = outputMgr; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + TestUtils.cleanTempFiles(); + TestUtils.setKernelUtilsBootstrapLibDir(new File("unittest/test data/lbr/lib")); + TestUtils.setUtilsInstallDir(new File("unittest/test data/lbr")); + + config = SharedBootstrapConfig.createSharedConfig(outputMgr); + BundleRepositoryRegistry.initializeDefaults(null, true); + } + + @AfterClass + public static void tearDownAfterClass() throws Exception { + TestUtils.cleanTempFiles(); + TestUtils.setKernelUtilsBootstrapLibDir(null); + } + + /** Trivial interface that groups Bundle & BundleStartLevel so mock can push through the adapt method */ + interface TestBundleStartLevel extends Bundle, BundleStartLevel {} + + /** Trivial interface that groups Bundle & BundleRevision so mock can push through the adapt method */ + interface TestBundleRevision extends Bundle, BundleRevision {} + + /** Trivial interface that groups Bundle & FrameworkStartLevel so mock can push through the adapt method */ + interface TestFrameworkStartLevel extends Bundle, FrameworkStartLevel {} + + Mockery context = new Mockery(); + + final Bundle mockBundle = context.mock(Bundle.class); + final BundleContext mockBundleContext = context.mock(BundleContext.class); + final TestBundleRevision mockBundleRevision = context.mock(TestBundleRevision.class); + final TestBundleStartLevel mockBundleStartLevel = context.mock(TestBundleStartLevel.class); + final TestFrameworkStartLevel mockFrameworkStartLevel = context.mock(TestFrameworkStartLevel.class); + + final ProvisionerImpl provisioner = new ProvisionerImpl(); + + @Before + public void setUp() throws Exception { + System.setProperty("java.protocol.handler.pkgs", "com.ibm.ws.kernel.internal"); + context.checking(new Expectations() { + { + atLeast(1).of(mockBundleContext).getBundle(Constants.SYSTEM_BUNDLE_LOCATION); + will(returnValue(mockFrameworkStartLevel)); + + one(mockFrameworkStartLevel).adapt(FrameworkStartLevel.class); + will(returnValue(mockFrameworkStartLevel)); + + one(mockFrameworkStartLevel).setInitialBundleStartLevel(KernelStartLevel.ACTIVE.getLevel()); + } + }); + } + + @Test + public void testInstallNonexistentBundle() throws Exception { + + BundleInstallStatus iStatus; + + // B -- non-existent bundle + + KernelResolver resolver = new KernelResolver(config.getInstallRoot(), null, "kernelCoreMissing-1.0", "defaultLogging-1.0", null); + config.setKernelResolver(resolver); + + provisioner.getServices(mockBundleContext); + iStatus = provisioner.installBundles(config); + + String listMissingBundles = iStatus.listMissingBundles(); + + assertTrue("B: Bundles notexist should be missing: " + listMissingBundles, iStatus.bundlesMissing()); + assertNotNull("B: listMissingBundles should not return null: " + listMissingBundles, listMissingBundles); + assertTrue("B: List of missing bundles should include p.q: " + listMissingBundles, listMissingBundles.contains("p.q")); + } + + @Test + public void testInstallBundle() throws Exception { + final String m = "testInstallBundle"; + + BundleInstallStatus iStatus; + + context.checking(new Expectations() { + { + one(mockBundleContext).installBundle(with(any(String.class)), with(any(InputStream.class))); + will(returnValue(mockBundle)); + + one(mockBundle).adapt(BundleStartLevel.class); + will(returnValue(mockBundleStartLevel)); + + one(mockBundle).adapt(BundleRevision.class); + will(returnValue(mockBundleRevision)); + + one(mockBundleRevision).getTypes(); + will(returnValue(0)); + + one(mockBundleStartLevel).getStartLevel(); + will(returnValue(1)); + + one(mockBundleStartLevel).setStartLevel(KernelStartLevel.BOOTSTRAP.getLevel()); + } + }); + + KernelResolver resolver = new KernelResolver(config.getInstallRoot(), null, "kernelCore-1.0", "emptyLogging-1.0", null); + config.setKernelResolver(resolver); + + provisioner.getServices(mockBundleContext); + iStatus = provisioner.installBundles(config); + + if (iStatus.bundlesMissing()) + System.out.println(iStatus.listMissingBundles()); + + assertFalse(m + " C: There should be no missing bundles", iStatus.bundlesMissing()); + assertNull(m + " C: The list of missing bundles should be null", iStatus.listMissingBundles()); + + recordExceptions(iStatus); // print any unexpected exceptions for + // debug + + assertFalse(m + " C: There should not be an install exception", iStatus.installExceptions()); + assertNull(m + " C: There should not be an exception to trace", iStatus.traceInstallExceptions()); + + if (iStatus.bundlesToStart()) + System.out.println(iStatus.getBundlesToStart()); + + assertTrue(m + " C: Bundles were installed", iStatus.bundlesToStart()); + assertTrue(m + " C: The list of bundles should contain the installed bundle", iStatus.getBundlesToStart().contains(mockBundle)); + } + + @Test + public void testInstallExistingBundle() throws Exception { + final String m = "testInstallExistingBundle"; + + BundleInstallStatus iStatus; + + KernelResolver resolver = new KernelResolver(config.getInstallRoot(), null, "kernelCore-1.0", "kernelCore-1.0", null); + config.setKernelResolver(resolver); + + File simple_1 = new File("unittest/test data/lbr/lib", "x.y_1.0.jar"); + final String locationString = "reference:" + simple_1.toURI().toURL().toString(); + + context.checking(new Expectations() { + { + one(mockBundleContext).installBundle("kernel@" + locationString, null); + will(returnValue(mockBundle)); + + one(mockBundle).adapt(BundleRevision.class); + will(returnValue(mockBundleRevision)); + + one(mockBundleRevision).getTypes(); + will(returnValue(0)); + + one(mockBundle).adapt(BundleStartLevel.class); + will(returnValue(mockBundleStartLevel)); + + one(mockBundleStartLevel).getStartLevel(); + will(returnValue(1)); + + one(mockBundleStartLevel).setStartLevel(KernelStartLevel.BOOTSTRAP.getLevel()); + } + }); + + provisioner.getServices(mockBundleContext); + iStatus = provisioner.installBundles(config); + + if (iStatus.bundlesMissing()) + System.out.println(iStatus.listMissingBundles()); + + assertFalse(m + " C: There should be no missing bundles", iStatus.bundlesMissing()); + assertNull(m + " C: The list of missing bundles should be null", iStatus.listMissingBundles()); + + recordExceptions(iStatus); // print any unexpected exceptions for + // debug + + assertFalse(m + " C: There should not be an install exception", iStatus.installExceptions()); + assertNull(m + " C: There should not be an exception to trace", iStatus.traceInstallExceptions()); + + if (iStatus.bundlesToStart()) + System.out.println(iStatus.getBundlesToStart()); + + assertTrue(m + " C: Bundles were installed", iStatus.bundlesToStart()); + assertTrue(m + " C: The list of bundles should contain the installed bundle", iStatus.getBundlesToStart().contains(mockBundle)); + } + + @Test + public void testInstallBundleException() throws Exception { + + BundleInstallStatus iStatus; + + // D -- existing bundle with EXCEPTION on install; + // one call to installBundle (that will throw exception) + // no calls to getHeaders + + final BundleException testEx = new BundleException("Expected exception installing bundle"); + + KernelResolver resolver = new KernelResolver(config.getInstallRoot(), null, "kernelCore-1.0", "emptyLogging-1.0", null); + config.setKernelResolver(resolver); + + context.checking(new Expectations() { + { + one(mockBundleContext).installBundle(with(any(String.class)), with(any(InputStream.class))); + will(throwException(testEx)); + + never(mockBundle).adapt(BundleRevision.class); + never(mockBundleRevision).getTypes(); + + never(mockBundle).adapt(BundleStartLevel.class); + never(mockBundleStartLevel).getStartLevel(); + never(mockBundleStartLevel).setStartLevel(with(any(int.class))); + } + }); + + provisioner.getServices(mockBundleContext); + iStatus = provisioner.installBundles(config); + + assertFalse("D: There should be no bundles installed", iStatus.bundlesToStart()); + assertTrue("D: There should be an install exception", iStatus.installExceptions()); + assertNotNull("D: There should be exceptions to trace", iStatus.traceInstallExceptions()); + + Map badness = iStatus.getInstallExceptions(); + System.out.println(badness); + + assertTrue("D: There should be an exception associated with bad bundle", badness.keySet().contains("x.y;version=\"[1.0.0,1.0.100)\"")); + assertEquals("D: The exception in the map should match the one thrown", badness.get("x.y;version=\"[1.0.0,1.0.100)\""), testEx); + } + + @Test + public void testInstallFragment() throws Exception { + + BundleInstallStatus iStatus; + + KernelResolver resolver = new KernelResolver(config.getInstallRoot(), null, "kernelCore-1.0", "emptyLogging-1.0", null); + config.setKernelResolver(resolver); + + // E -- existing FRAGMENT bundle; + // should not be added to list of "installed" bundles + context.checking(new Expectations() { + { + one(mockBundleContext).installBundle(with(any(String.class)), with(any(InputStream.class))); + will(returnValue(mockBundle)); + + one(mockBundle).adapt(BundleRevision.class); + will(returnValue(mockBundleRevision)); + + one(mockBundleRevision).getTypes(); + will(returnValue(BundleRevision.TYPE_FRAGMENT)); + + never(mockBundle).adapt(BundleStartLevel.class); + never(mockBundleStartLevel).getStartLevel(); + never(mockBundleStartLevel).setStartLevel(with(any(int.class))); + } + }); + + provisioner.getServices(mockBundleContext); + iStatus = provisioner.installBundles(config); + + assertFalse("E: The fragment bundle should not be in the list of installed bundles", iStatus.bundlesToStart()); + } + + @Test + public void testStartNullList() { + provisioner.getServices(mockBundleContext); + + // A -- null properties, empty array + + provisioner.startBundles(null); + provisioner.startBundles(new ArrayList()); + } + + @Test + public void testStartBundle() throws Exception { + BundleStartStatus sStatus; + provisioner.getServices(mockBundleContext); + + // B -- mock bundle; + // one call to b.start, bundle already started + + List bList = new ArrayList(); + bList.add(mockBundle); + + context.checking(new Expectations() { + { + one(mockBundle).getState(); + will(returnValue(org.osgi.framework.Bundle.RESOLVED)); + + one(mockBundle).start(with(any(int.class))); + } + }); + + sStatus = provisioner.startBundles(bList); + + assertFalse(sStatus.startExceptions()); + assertNull(sStatus.traceStartExceptions()); + + // C -- Felix path + context.checking(new Expectations() { + { + one(mockFrameworkStartLevel).adapt(FrameworkStartLevel.class); + will(returnValue(mockFrameworkStartLevel)); + + one(mockFrameworkStartLevel).setInitialBundleStartLevel(KernelStartLevel.ACTIVE.getLevel()); + + one(mockBundle).getState(); + will(returnValue(org.osgi.framework.Bundle.RESOLVED)); + + one(mockBundle).start(with(any(int.class))); + } + }); + + provisioner.getServices(mockBundleContext); + + sStatus = provisioner.startBundles(bList); + } + + @Test + public void testStartStartedBundle() throws Exception { + BundleStartStatus sStatus; + provisioner.getServices(mockBundleContext); + + // C -- mock bundle; + // one call to b.start, works fine + + List bList = new ArrayList(); + bList.add(mockBundle); + + context.checking(new Expectations() { + { + one(mockBundle).getState(); + will(returnValue(org.osgi.framework.Bundle.STARTING)); + + never(mockBundle).start(with(any(int.class))); + } + }); + + sStatus = provisioner.startBundles(bList); + + assertFalse(sStatus.startExceptions()); + assertNull(sStatus.traceStartExceptions()); + } + + @Test + public void testStartBundleException() throws Exception { + BundleStartStatus sStatus; + provisioner.getServices(mockBundleContext); + + // D -- existing bundle with EXCEPTION; + // one call to b.start, throws bundle exception + + final BundleException testEx = new BundleException("Expected exception starting bundle"); + + context.checking(new Expectations() { + { + one(mockBundle).getState(); + will(returnValue(org.osgi.framework.Bundle.RESOLVED)); + + one(mockBundle).start(with(any(int.class))); + will(throwException(testEx)); + + one(mockBundle).getSymbolicName(); + will(returnValue("mockBundle")); + } + }); + + List bList = new ArrayList(); + bList.add(mockBundle); + + sStatus = provisioner.startBundles(bList); + + assertTrue(sStatus.startExceptions()); + assertNotNull(sStatus.traceStartExceptions()); + + Map badness = sStatus.getStartExceptions(); + assertTrue(badness.keySet().contains(mockBundle)); + assertEquals(badness.get(mockBundle), testEx); + } + + @Test(expected = LaunchException.class) + public void testInstallStatusInstallException() { + final String m = "testInstallStatusInstallException"; + try { + final BundleInstallStatus iStatus = new BundleInstallStatus(); + iStatus.addInstallException("bundleName", new Throwable("pretend error")); + + provisioner.getServices(mockBundleContext); + provisioner.checkInstallStatus(iStatus); + } catch (LaunchException b) { + if (!b.getMessage().contains("installing")) + outputMgr.failWithThrowable(m, new AssertionError("exception message does not contain message about exceptions while installing bundles")); + + throw b; // expected + } + } + + @Test(expected = LaunchException.class) + public void testInstallStatusMissingBundles() { + final String m = "testInstallStatusMissingBundles"; + try { + final BundleInstallStatus iStatus = new BundleInstallStatus(); + iStatus.addMissingBundle("missing"); + + provisioner.getServices(mockBundleContext); + provisioner.checkInstallStatus(iStatus); + } catch (LaunchException b) { + if (!b.getMessage().contains("Missing")) + outputMgr.failWithThrowable(m, new AssertionError("exception message does not contain message about missing bundles")); + + throw b; // expected + } + } + + @Test(expected = LaunchException.class) + public void testInstallStatusNoBundles() { + final String m = "testInstallStatusNoBundles"; + + try { + final BundleInstallStatus iStatus = new BundleInstallStatus(); + + // no bundles to start.. + provisioner.getServices(mockBundleContext); + provisioner.checkInstallStatus(iStatus); + } catch (LaunchException b) { + if (!b.getMessage().contains("No required bundles")) + outputMgr.failWithThrowable(m, new AssertionError("exception message does not contain message about no bundles to start")); + + throw b; // expected + } + } + + @Test(expected = LaunchException.class) + public void testCheckStartStatusStartException() throws InvalidBundleContextException { + + context.checking(new Expectations() { + { + oneOf(mockBundle).getLocation(); + will(returnValue("bundle location")); + } + }); + + BundleStartStatus startStatus = new BundleStartStatus(); + startStatus.addStartException(mockBundle, new BundleException("fake exception")); + + provisioner.getServices(mockBundleContext); + provisioner.checkStartStatus(startStatus); + } + + @Test(expected = InvalidBundleContextException.class) + public void testCheckStartStatusInvalidContext() throws InvalidBundleContextException { + BundleStartStatus startStatus = new BundleStartStatus(); + startStatus.markContextInvalid(); + + provisioner.getServices(mockBundleContext); + provisioner.checkStartStatus(startStatus); + } + + protected void recordExceptions(BundleInstallStatus iStatus) { + + if (iStatus.installExceptions()) { + Map exceptions = iStatus.getInstallExceptions(); + for (String key : exceptions.keySet()) { + Throwable t = exceptions.get(key); + System.out.println("+UNEXPECTED EXCEPTION for " + key); + System.out.println("ex: " + t.getMessage()); + t.printStackTrace(System.out); + } + } + } + +} diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/provisioining/LocalBundleRepositoryTest.java b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/provisioining/LocalBundleRepositoryTest.java new file mode 100755 index 00000000000..8934454e7d6 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/provisioining/LocalBundleRepositoryTest.java @@ -0,0 +1,146 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.kernel.provisioining; + +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 org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestRule; +import org.osgi.framework.VersionRange; + +import test.common.SharedOutputManager; +import test.shared.TestUtils; + +import com.ibm.ws.kernel.provisioning.ContentBasedLocalBundleRepository; + +/** + * + */ +public class LocalBundleRepositoryTest { + private final SharedOutputManager outputMgr = SharedOutputManager.getInstance().trace("*=all"); + @Rule + public final TestRule outputRule = outputMgr; + + private static File cacheDir; + + @BeforeClass + public static void setupCache() throws IOException { + cacheDir = TestUtils.createTempDirectory("cache.data"); + } + + /** + * This method checks that if the location attribute identifies an exact file we use that rather than applying the iFix selection rules. + */ + @Test + public void testFullySpecifiedLocation() { + ContentBasedLocalBundleRepository lbr = new ContentBasedLocalBundleRepository(new File("unittest/test data/lbr"), cacheDir, true); + File f = lbr.selectBundle("lib/a.b_1.0.jar", "a.b", new VersionRange("0.0.0")); + assertNotNull("A file could not be located", f); + assertEquals("The file name is not correct", "a.b_1.0.jar", f.getName()); + assertTrue("The file is not a file", f.isFile()); + assertTrue("The file does not exist", f.exists()); + lbr.dispose(); + } + + /** + * This method tests that if we don't have iFixes, or fix pack updates to a bundle we install the correct bundle. This + * is very low level belts and braces. If we don't do this right all BVTs are going to fail. + */ + @Test + public void testSelectSingleMatch() { + ContentBasedLocalBundleRepository lbr = new ContentBasedLocalBundleRepository(new File("unittest/test data/lbr"), cacheDir, true); + File f = lbr.selectBundle("", "x.y", new VersionRange("[1.0.0,1.0.100)")); + assertNotNull("A file could not be located", f); + assertEquals("The file name is not correct", "x.y_1.0.jar", f.getName()); + assertTrue("The file is not a file", f.isFile()); + assertTrue("The file does not exist", f.exists()); + lbr.dispose(); + } + + /** + * This is the key iFix install routine. It is testing that when we have multiple iFixes for a fix pack we select the most + * recent one. It also checks that we ignore iFixes for fixpack jars that have not been installed. So this is really important. + */ + @Test + public void testSelectMultiMatch() { + ContentBasedLocalBundleRepository lbr = new ContentBasedLocalBundleRepository(new File("unittest/test data/lbr"), cacheDir, true); + File f = lbr.selectBundle("", "a.b", new VersionRange("[1.0.0,1.0.100)")); + assertNotNull("A file could not be located", f); + assertEquals("The file name is not correct", "a.b_1.0.1.v2.jar", f.getName()); + assertTrue("The file is not a file", f.isFile()); + assertTrue("The file does not exist", f.exists()); + assertTrue("The ifix warning message (CWWKE0060W) was not output", outputMgr.checkForMessages("CWWKE0060W")); + assertTrue("The ifix warning message did not identify the iFix a.b_1.0.2.v1.jar", outputMgr.checkForMessages("a.b_1.0.2.v1.jar")); + assertTrue("The ifix warning message did not identify the base a.b_1.0.2.v1.jar", outputMgr.checkForMessages("a.b_1.0.2.jar")); + lbr.dispose(); + } + + /** + * This test ensures that if you have different bundles with the same symbolic name but different versions, and the bundle versions don't have + * qualifiers i.e. they are not ifix/apar bundles, that the bundle with the highest version is selected. + */ + @Test + public void testMultipleVersionedBundlesWithNoQualifiers() { + // We specifically don't want the cache because we are using a different bundle repository. If we use the cache this goes boom. + ContentBasedLocalBundleRepository lbr = new ContentBasedLocalBundleRepository(new File("unittest/test data/nonIFixLBR"), null, true); + File f = lbr.selectBundle("", "a.b", new VersionRange("[1.0.0,1.0.100)")); + assertNotNull("A file could not be located", f); + assertEquals("The file name is not correct", "a.b_1.0.1.jar", f.getName()); + assertTrue("The file is not a file", f.isFile()); + assertTrue("The file does not exist", f.exists()); + lbr.dispose(); + } + + /** + * This method checks that we can select jars from two locations. We should pick the most recent from both locations. In + * the test the base jar 1.0.2 is in dev and the iFixes are in lib. We should pick up the iFixes and ignore the ones in + * dev. + */ + @Test + public void testMultipleLocations() { + ContentBasedLocalBundleRepository lbr = new ContentBasedLocalBundleRepository(new File("unittest/test data/lbr"), cacheDir, true); + File f = lbr.selectBundle("dev/,lib/", "a.b", new VersionRange("[1.0.0,1.0.100)")); + assertNotNull("A file could not be located", f); + assertEquals("The file name is not correct", "a.b_1.0.2.v1.jar", f.getName()); + assertTrue("The file is not a file", f.isFile()); + assertTrue("The file does not exist", f.exists()); + f = lbr.selectBundle("dev/", "a.b", new VersionRange("[1.0.0,1.0.100)")); + assertNotNull("A file could not be located", f); + assertEquals("The file name is not correct", "bad.jar", f.getName()); + assertTrue("The file is not a file", f.isFile()); + assertTrue("The file does not exist", f.exists()); + lbr.dispose(); + } + + /** + * This method checks that we can select and return jars that don't match the naming convetion, but where the content + * correctly identifies the jar. In this case we select dev and lib and select bundles up to 1.0.2, excluding iFixes. + * The jar is called bad.jar, but the SymbolicName is a.b and version is 1.0.2. + */ + @Test + public void testBadlyNamedJar() { + ContentBasedLocalBundleRepository lbr = new ContentBasedLocalBundleRepository(new File("unittest/test data/lbr"), cacheDir, true); + File f = lbr.selectBundle("dev/,lib/", "a.b", new VersionRange("[1.0.0,1.0.2]")); + assertNotNull("A file could not be located", f); + assertEquals("The file name is not correct", "bad.jar", f.getName()); + assertTrue("The file is not a file", f.isFile()); + assertTrue("The file does not exist", f.exists()); + lbr.dispose(); + } +} \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/provisioining/ServiceFingerprintTest.java b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/provisioining/ServiceFingerprintTest.java new file mode 100755 index 00000000000..cb97c3a8902 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/src/com/ibm/ws/kernel/provisioining/ServiceFingerprintTest.java @@ -0,0 +1,152 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.kernel.provisioining; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.util.Properties; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestRule; + +import test.common.SharedOutputManager; + +import com.ibm.ws.kernel.boot.internal.FileUtils; +import com.ibm.ws.kernel.provisioning.ServiceFingerprint; + +/** + * + */ +public class ServiceFingerprintTest { + private static File workArea = new File("build/service.print/workarea/"); + private static File installDir = new File("../build.image/wlp"); + @Rule + public TestRule sharedOutputRuleThingy = SharedOutputManager.getInstance(); + + @Before + public void setup() { + new File(workArea, "platform").mkdirs(); + ServiceFingerprint.hasServiceBeenApplied(installDir, workArea); + ServiceFingerprint.putInstallDir(null, installDir); + } + + /** + * Add a single file to the ServiceFingerprint. Then check to see if service has been applied. Since the file has not + * changed it should not have changed. + */ + @Test + public void checkServiceDetectionWithNoChanges() { + ServiceFingerprint.put(new File("resources/packages.list")); + assertFalse("We should not have detected a file change", ServiceFingerprint.hasServiceBeenApplied(installDir, workArea)); + } + + /** + * Add two files to the ServiceFingerprint. One doesn't change. One is deleted. Then check to see if service has been applied. + * Since a file is deleted it should return true for the final call to hasServiceBeenApplied. + */ + @Test + public void checkServiceDetectionWithFileDelete() throws IOException { + ServiceFingerprint.put(new File("resources/packages.list")); + File tmp = File.createTempFile("test", ".txt"); + PrintStream out = new PrintStream(tmp); + out.println("some data"); + out.close(); + ServiceFingerprint.put(tmp); + assertFalse("We should not have detected a file change", ServiceFingerprint.hasServiceBeenApplied(installDir, workArea)); + tmp.delete(); + assertTrue("We should have detected a file change", ServiceFingerprint.hasServiceBeenApplied(installDir, workArea)); + } + + /** + * Add two files to the ServiceFingerprint. One doesn't change. One doesn't exist when it is initially added. The + * file is then created before checking to see if service has been applied. + * Since a file is added it should return true for the final call to hasServiceBeenApplied. + */ + @Test + public void checkServiceDetectionWithFileCreation() throws IOException { + ServiceFingerprint.put(new File("resources/packages.list")); + File tmp = File.createTempFile("test", ".txt"); + tmp.delete(); + ServiceFingerprint.put(tmp); + assertFalse("We should not have detected a file change", ServiceFingerprint.hasServiceBeenApplied(installDir, workArea)); + PrintStream out = new PrintStream(tmp); + out.println("some data"); + out.close(); + assertTrue("We should have detected a file change", ServiceFingerprint.hasServiceBeenApplied(installDir, workArea)); + tmp.delete(); + } + + /** + * Add two files to the ServiceFingerprint. One doesn't change. One does. Then check to see if service has been applied. + * Since a file has changed it should return true for the final call to hasServiceBeenApplied. + */ + @Test + public void checkServiceDetectionWithFileChange() throws IOException { + ServiceFingerprint.put(new File("resources/packages.list")); + assertFalse("We should not have detected a file change", ServiceFingerprint.hasServiceBeenApplied(installDir, workArea)); + File tmp = File.createTempFile("test", ".txt"); + tmp.delete(); + PrintStream out = new PrintStream(tmp); + out.println("some data"); + out.close(); + ServiceFingerprint.put(tmp); + assertFalse("We should not have detected a file change", ServiceFingerprint.hasServiceBeenApplied(installDir, workArea)); + out = new PrintStream(tmp); + out.println("some totally new data"); + out.close(); + assertTrue("We should have detected a file change", ServiceFingerprint.hasServiceBeenApplied(installDir, workArea)); + tmp.delete(); + } + + /** + * Add two files to the ServiceFingerprint. One doesn't change. One is deleted. Then check to see if service has been applied. + * Since a file is deleted it should return true for the final call to hasServiceBeenApplied. + */ + @Test + public void checkServiceDetectionWithFileDeleteAndClear() throws IOException { + File tmpInstall = File.createTempFile("wlp", null); + tmpInstall.delete(); + File tmpVersions = new File(tmpInstall, "lib/versions/"); + tmpVersions.mkdirs(); + File tmpServiceFingerprint = new File(tmpVersions, "service.fingerprint"); + PrintStream out = new PrintStream(tmpServiceFingerprint); + out.println("some data"); + out.close(); + ServiceFingerprint.putInstallDir(null, tmpInstall); + assertFalse("We should not have detected a file change", ServiceFingerprint.hasServiceBeenApplied(tmpInstall, workArea)); + // rename the install area + File renameTmpInstall = new File(tmpInstall.getParentFile(), tmpInstall.getName() + "2"); + tmpInstall.renameTo(renameTmpInstall); + assertTrue("We should have detected a file change", ServiceFingerprint.hasServiceBeenApplied(tmpInstall, workArea)); + ServiceFingerprint.clear(); + ServiceFingerprint.putInstallDir(null, renameTmpInstall); + assertFalse("We should not have detected a file change", ServiceFingerprint.hasServiceBeenApplied(renameTmpInstall, workArea)); + FileUtils.recursiveClean(renameTmpInstall); + } + + @After + public void cleanup() throws FileNotFoundException, IOException { + Properties props = new Properties(); + props.store(new FileOutputStream(new File(workArea, "platform/service.fingerprint")), null); + ServiceFingerprint.hasServiceBeenApplied(installDir, workArea); + new File("build/service.print/workarea/platform/service.fingerprint").delete(); + } +} \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/src/test/shared/Constants.java b/dev/com.ibm.ws.kernel.boot_test/unittest/src/test/shared/Constants.java new file mode 100755 index 00000000000..46022b1432b --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/src/test/shared/Constants.java @@ -0,0 +1,52 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2010 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + * + * Change activity: + * + * Issue Date Name Description + * ----------- ----------- --------- ------------------------------------ + * Initial version + */ +package test.shared; + +import java.io.File; + +/** + * + */ +public class Constants { + /** + * Test data directory: note the space! always test paths with spaces. + * Dratted windows. + */ + public static final String TEST_DATA_DIR = "../com.ibm.ws.kernel.boot_test/build/unittest/test data/"; + + public static final File TEST_DATA_FILE = new File(TEST_DATA_DIR); + + /** Test dist dir: where our generated sample jars live */ + public static final String TEST_DIST_DIR = "../com.ibm.ws.kernel.boot_test/build/unittest/test data/lib/"; + + /** Test dist dir: where our generated sample jars live */ + public static final File TEST_DIST_DIR_FILE = new File(TEST_DIST_DIR); + + public static final String TEST_PLATFORM_DIR = "../com.ibm.ws.kernel.boot_test/build/unittest/test data/lib/platform/"; + + public static final String TEST_TMP_ROOT = "../com.ibm.ws.kernel.boot_test/build/tmp/"; + + public static final File TEST_TMP_ROOT_FILE = new File(TEST_TMP_ROOT); + + /** The dist dir containing the real jar file for the bootstrap */ + public static final String BOOTSTRAP_LIB_DIR = "../com.ibm.ws.kernel.boot/build/lib/"; + + public static final String BOOTSTRAP_PUBLISH_DIR = "../com.ibm.ws.kernel.boot/publish/"; + + public static final String MOCK_FRAMEWORK_LAUNCH = "MOCK_FRAMEWORK_LAUNCH"; +} diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/src/test/shared/DumpTimerRule.java b/dev/com.ibm.ws.kernel.boot_test/unittest/src/test/shared/DumpTimerRule.java new file mode 100755 index 00000000000..1c6b04e6fcb --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/src/test/shared/DumpTimerRule.java @@ -0,0 +1,91 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package test.shared; + +import java.io.File; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +import org.junit.rules.TestRule; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; + +import com.ibm.ws.kernel.boot.internal.commands.JavaDumpAction; +import com.ibm.ws.kernel.boot.internal.commands.JavaDumper; + +/** + * + */ +public class DumpTimerRule implements TestRule { + + private static ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); + + private final long timeoutMillis; + private final File outputDir; + private volatile boolean complete; + + public DumpTimerRule(long timeoutMillis, File outputDir) { + this.timeoutMillis = timeoutMillis; + this.outputDir = outputDir; + } + + /* + * (non-Javadoc) + * + * @see org.junit.rules.TestRule#apply(org.junit.runners.model.Statement, org.junit.runner.Description) + */ + @Override + public Statement apply(Statement statement, Description arg1) { + return new DumpTimerStatement(statement); + } + + private class DumpTimerStatement extends Statement { + private final Statement statement; + + private DumpTimerStatement(Statement statement) { + this.statement = statement; + } + + /* + * (non-Javadoc) + * + * @see org.junit.runners.model.Statement#evaluate() + */ + @Override + public void evaluate() throws Throwable { + DumpThreads dumper = new DumpThreads(); + ScheduledFuture future = scheduler.schedule(dumper, timeoutMillis, TimeUnit.MILLISECONDS); + try { + statement.evaluate(); + } finally { + complete = true; + future.cancel(false); + } + + } + + } + + private class DumpThreads implements Runnable { + + @Override + public void run() { + if (!complete) { + JavaDumper.getInstance().dump(JavaDumpAction.THREAD, outputDir); + } + + } + + } +} diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/src/test/shared/TestUtils.java b/dev/com.ibm.ws.kernel.boot_test/unittest/src/test/shared/TestUtils.java new file mode 100755 index 00000000000..05012f324c8 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/src/test/shared/TestUtils.java @@ -0,0 +1,141 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package test.shared; + +import java.io.File; +import java.io.FilenameFilter; +import java.io.IOException; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.concurrent.atomic.AtomicInteger; + +import com.ibm.ws.kernel.boot.cmdline.Utils; +import com.ibm.ws.kernel.boot.internal.KernelUtils; + +/** + * + */ +public class TestUtils { + private static AtomicInteger count = new AtomicInteger(0); + static Field bootJarField = null; + static Field bootLibDirField = null; + static Field utilsInstallDirField = null; + + public static File findBuiltKernelBundle() { + File root = new File(Constants.BOOTSTRAP_LIB_DIR); + + File fileList[] = root.listFiles(new FilenameFilter() { + @Override + public boolean accept(File dir, String name) { + return name.matches("com.ibm.ws.kernel.boot.*\\.jar"); + } + }); + + if (fileList == null || fileList.length < 1) + throw new RuntimeException("Unable to find com.ibm.ws.kernel.boot.*\\.jar in " + root.getAbsolutePath()); + + return fileList[0]; + } + + public static void setKernelUtilsBootstrapJar(File bootstrapJar) throws Exception { + if (bootJarField == null) { + bootJarField = KernelUtils.class.getDeclaredField("launchHome"); + bootJarField.setAccessible(true); + } + bootJarField.set(null, bootstrapJar); + } + + public static void setKernelUtilsBootstrapLibDir(File bootLibDir) throws Exception { + if (bootLibDirField == null) { + bootLibDirField = KernelUtils.class.getDeclaredField("libDir"); + bootLibDirField.setAccessible(true); + } + bootLibDirField.set(null, bootLibDir); + } + + public static void setUtilsInstallDir(File installDir) throws Exception { + if (utilsInstallDirField == null) { + utilsInstallDirField = Utils.class.getDeclaredField("installDir"); + utilsInstallDirField.setAccessible(true); + } + utilsInstallDirField.set(null, installDir); + } + + public static File createTempFile(String name, String suffix) throws IOException { + if (!Constants.TEST_TMP_ROOT_FILE.isDirectory()) { + Constants.TEST_TMP_ROOT_FILE.mkdirs(); + } + return File.createTempFile(name, suffix, Constants.TEST_TMP_ROOT_FILE); + } + + public static File createTempFile(String name, String suffix, File dir) throws IOException { + return File.createTempFile(name, suffix, dir); + } + + public static File createTempDirectory(String name) throws IOException { + File f = new File(Constants.TEST_TMP_ROOT_FILE, name + count.incrementAndGet()); + + if (!f.exists() && !f.mkdirs()) { + System.out.println("alex: file creation failed for: " + f.getAbsolutePath()); + throw new IOException("Unable to create temporary directory"); + } + return f; + } + + public static void cleanTempFiles(File dir) { + recursiveClean(dir); + } + + public static void cleanTempFiles() { + recursiveClean(Constants.TEST_TMP_ROOT_FILE); + } + + private static boolean recursiveClean(final File fileToRemove) { + if (fileToRemove == null) + return true; + + if (!fileToRemove.exists()) + return true; + + boolean success = true; + + if (fileToRemove.isDirectory()) { + File[] files = fileToRemove.listFiles(); + for (File file : files) { + if (file.isDirectory()) { + success |= recursiveClean(file); + } else { + success |= file.delete(); + } + } + files = fileToRemove.listFiles(); + if (files.length == 0) + success |= fileToRemove.delete(); + } else { + success |= fileToRemove.delete(); + } + return success; + } + + public static Method getMethod(Class subjectClass, String methodName, Class... parameterClasses) throws NoSuchMethodException { + try { + return subjectClass.getDeclaredMethod(methodName, parameterClasses); + } catch (NoSuchMethodException e) { + Class superClass = subjectClass.getSuperclass(); + if (superClass != null) { + return getMethod(superClass, methodName, parameterClasses); + } else { + throw new NoSuchMethodException(); + } + } + } +} diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/test data/dump/lib/md5-2.txt b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/dump/lib/md5-2.txt new file mode 100755 index 00000000000..91dbf2724c8 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/dump/lib/md5-2.txt @@ -0,0 +1 @@ +Another file for testing MD5. Do not change contents. \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/test data/dump/md5-1.txt b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/dump/md5-1.txt new file mode 100755 index 00000000000..31a2ac49f4e --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/dump/md5-1.txt @@ -0,0 +1 @@ +File for testing MD5. Do not change contents. \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/test data/dump/usr/ignored.txt b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/dump/usr/ignored.txt new file mode 100755 index 00000000000..c891e9054e0 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/dump/usr/ignored.txt @@ -0,0 +1 @@ +This file should be ignored by the file list generator. \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/dev/a.b_1.0.2.mf b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/dev/a.b_1.0.2.mf new file mode 100755 index 00000000000..177bf28b64a --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/dev/a.b_1.0.2.mf @@ -0,0 +1,3 @@ +Bundle-ManifestVersion: 2 +Bundle-SymbolicName: a.b +Bundle-Version: 1.0.2 diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/dev/bad.jar b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/dev/bad.jar new file mode 100755 index 0000000000000000000000000000000000000000..e72d9cdc23cd00438aca01c9fe68278444323359 GIT binary patch literal 373 zcmWIWW@Zs#-~htZwL2UbkN_tG3xls~h@-BjpPT-_Qw$8u3<2Kk93T};P-Ou)HH!dM zz%~0i`gyv!28ZbRx_$ONbK1vSSMMUPx31Q?Gv_x48C)@b@U%$ltoKPzSHUaBkDeCk zdHL#i`d%zu#lkuBrQ{K5X{`(kF_9-rv?`vdzRo;U`pfBT>+A%U>0Im1_?|j{(&wA^ z8Q-lz9#^~{J$>|)3GB%EWySxKfllZE;s9?(CJ_cyKf*i!@*^sMI~wF;bgjt7f_#Vo awm>FaE0TW$yjj^ms+fSV7Dzt=aTox8;8{Na literal 0 HcmV?d00001 diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/a.b_1.0.0.jar b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/a.b_1.0.0.jar new file mode 100755 index 0000000000000000000000000000000000000000..a8ad3ab74ddc315f70e34d5ce4f04943e548ae01 GIT binary patch literal 373 zcmWIWW@Zs#-~htUC8kacNPv@pg~8V~#8KDN&rSc|DFy~+h5&DN4v-2asImZ@nni#r z;F^6M{XE@VgG2Ou-9G!CIql=Et9OytTUYDcne&^246YbIcv_@&*88OARo-=Hd{3P} z>GRF|jPKSUk1O7fo)+nO`RaK3UMyY3qG@{BIN-vEl24%p=k&Es=zHlfN-gBP-j|~` zY305E>xY-z_QdRo0Xwonret9<&kPi{S a7RZEaMe=WeH!B-R6%!EF0_jH}4g&zkGFIpS literal 0 HcmV?d00001 diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/a.b_1.0.0.mf b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/a.b_1.0.0.mf new file mode 100755 index 00000000000..d1e287c057b --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/a.b_1.0.0.mf @@ -0,0 +1,3 @@ +Bundle-ManifestVersion: 2 +Bundle-SymbolicName: a.b +Bundle-Version: 1.0.0 diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/a.b_1.0.1.jar b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/a.b_1.0.1.jar new file mode 100755 index 0000000000000000000000000000000000000000..7a7d36cad5202d63926e8a7abfe5450571383a88 GIT binary patch literal 375 zcmWIWW@Zs#-~htUC8kacNPv@pg~8V~#8KDN&rSc|DFy~+h5&DN4v-2asImZ@nni#r z;F^6M{XE@VgG2Ou-9G!CIql=Et9OytTUYDcne&^246YbIcv_@&*88OARo-=Hd{3P} z>GRF|jPKSUk1O7fo)+nO`RaK3UMyY3qG@{BIN-vEl24%p=k&Es=zHlfN-gBP-j}m% zo?^@m@htV2TOHH8r*ngyc}a3zKq}A?T|gY*&B!Fefa*(_7eKy51#oAB{EV&@*;tSt c5x^G6glk3eaey}~8%Pxs5Y__eCm;?30CT=qUH||9 literal 0 HcmV?d00001 diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/a.b_1.0.1.mf b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/a.b_1.0.1.mf new file mode 100755 index 00000000000..04cf5ce5103 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/a.b_1.0.1.mf @@ -0,0 +1,3 @@ +Bundle-ManifestVersion: 2 +Bundle-SymbolicName: a.b +Bundle-Version: 1.0.1 diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/a.b_1.0.1.v1.jar b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/a.b_1.0.1.v1.jar new file mode 100755 index 0000000000000000000000000000000000000000..98bbadc01fc22c926194866ca98d9329c30e500a GIT binary patch literal 404 zcmWIWW@Zs#-~htUC8kacNPv@pg~8V~#8KDN&rSc|DFy~+h5&DN4v-2asImZ@nni#r z;F^6M{XE@VgG2Ou-9G!CIql=Et9OytTUYDcne&^246YbIcv_@&*88OARo-=Hd{3P} z>GRF|jPKSUk1O7fo)+nO`RaK3UMyY3qG@{BIN-vEl24%p=k&Es=zHlfN-aEjnpNcD z*E8Clx~I-uEj_))Lw8#c2ZxD?ky+#Ho}9V!7RJp~j5#L$N@)j|a-3eA9@r0|7o`6; z0bRHPhy%PCnM4>+g8=3~P!OO3xSv1)g021a2(^XzZ&fTeDOT?lz zSt_KZBxippvYh&C>60a|*utNwJ$;^{_FMJYvM5cJSE?V2EX9|qO1#sVhf&yJDvaukqBY-WC3D=4g5CPt-Y#>!kKv)Z;e}gy-0Ji^L ASpWb4 literal 0 HcmV?d00001 diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/a.b_1.0.1.v2.mf b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/a.b_1.0.1.v2.mf new file mode 100755 index 00000000000..98eddeddcfc --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/a.b_1.0.1.v2.mf @@ -0,0 +1,4 @@ +Bundle-ManifestVersion: 2 +Bundle-SymbolicName: a.b +Bundle-Version: 1.0.1.v2 +IBM-Test-Fixes: PK1234 diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/a.b_1.0.100.jar b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/a.b_1.0.100.jar new file mode 100755 index 0000000000000000000000000000000000000000..a9cbe374093734dc0fbb2b11c2b48835f3b2ece6 GIT binary patch literal 376 zcmWIWW@Zs#-~hreC8kacNPv@pg~8V~#8KDN&rSc|DFy~+h5&DN4v-2asImZ@nni#r z;F^6M{XE@VgG2Ou-9G!CIql=Et9OytTUYDcne&^246YbIcv_@&*88OARo-=Hd{3P} z>GRF|jPKSUk1O7fo)+nO`RaK3UMyY3qG@{BIN-vEl24%p=k&Es=zHlfN-gBP-j}m% z-a^JhG4U(b7O=YQiP;kacBf~I*RnLAD|&!9z?+dtgaOr?Fh792i3;HE26-A?E3&a5 dPa=RVkO|j{1a2(^XzZ&fTeDOT?lz zSt_KZBxippvYh&C>60a|*utNwJ$;^{_FMJYvM5cJSE?V2EX9|qO!@LIaJt}~E2NV|QT9J(f`5gglflRnoq>u>kW@Q7ZVgf>tgZ_Xx3;={n BVGRHP literal 0 HcmV?d00001 diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/a.b_1.0.2.v1.mf b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/a.b_1.0.2.v1.mf new file mode 100755 index 00000000000..6c3ffc629a3 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/a.b_1.0.2.v1.mf @@ -0,0 +1,4 @@ +Bundle-ManifestVersion: 2 +Bundle-SymbolicName: a.b +Bundle-Version: 1.0.2.v1 +IBM-Test-Fixes: PK1234 diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/a.b_1.0.jar b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/a.b_1.0.jar new file mode 100755 index 0000000000000000000000000000000000000000..56b4c60a31920a3ccaa866d3a5edd6f03e7e780a GIT binary patch literal 387 zcmWIWW@Zs#-~hreC8kacNPv@pg~8V~#8KDN&rSc|DFy~+h5&DN4v-2asImZ@nni#r z;F^6M{XE@VgG2Ou-9G!CIql=Et9OytTUYDcne&^246YbIcv_@&*88OARo-=Hd{3P} z>GRF|jPKSUk1O7r!ZgmE@jmaV%eZQbuBMjn)2BsxUcNe>z86bZvAi_BY#eamL&>Mm zf^+&>C-l8^7-y~IH0NKfx-UTefNF2W&WfF2CokG1+*1g2&`cl>@MdHZVLkP9ifk;%zX)IpWWu!~`98p#l?|kd2?%R}^al`!0RSs%T_gYi literal 0 HcmV?d00001 diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/a.b_1.0.mf b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/a.b_1.0.mf new file mode 100755 index 00000000000..b8f69510b0b --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/a.b_1.0.mf @@ -0,0 +1,3 @@ +Bundle-ManifestVersion: 2 +Bundle-SymbolicName: a.b; singleton:=true +Bundle-Version: 1.0 diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/dummy.jar b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/dummy.jar new file mode 100755 index 0000000000000000000000000000000000000000..3fbb1489bcde60a13cd01078ec0a9c9e50f5ba40 GIT binary patch literal 1756 zcmWIWW@Zs#-~hs%eLEZ&kN_tG3xls~h@-BjpPT-_Qw$8u3<2Kk93T};P-Ou)HH!dM zz%~0i`gyv!28ZbRx_$ONbK1vSSMMUPx31Q?Gv_x48C)@b@U%$J%U8$K_hRWP7S0(j zC67o;Yh_r7i9A`NRq;&qb>^p{k421N+Yif1eX;?X4Z;Z9jpuK301ChX50I6pmlSWP zX8?q`X~kM+y-#{x{R*|56K?mTqNWop;m_2bK2K5mt@>*Vp?g6W+gw8FAep|D6sYGDISQ$EH@=q zgM!uv#joc0EjA+GyI)WBKmz%AmuUm0#TIB5^CA1#fP$Fig~si@MRLcjfrfgc_}3E6 zTI7H>q9mYuzQ6+d%HkbwF#Y?!7c~oVA^DfoR2-=-lKyPz^Ci<5rrw+;GIiOZkV9Xk zUP%@}@{x{gt&0cH^avD>2cdZ!WPgQTB{(0EWPiwu&_j@11c}~ehQ{^gK*QX@)-f`P zFrbz>umS~C=AZ(2Ap$Ca0=!YRB9{iB5(fcnflRnor1A&Z1W>7goVh`z1_JB`GLg#= zWSyYQkDNzQb?Px9bb>M^vQAJQM$TlQq=f(rQFMZHG_qz;K19wasG6mKfe3Rjus8ta zN@UHTyo8+GL3s%QCL?PG=PYEspbUYWVo@#TVn$dD%^t{_L5UhUxq%WD0yHCOMs+YK gF(RiMRDI0Agn~$#0p6@^ATzmuFa+q8B5*PS03mh2mH+?% literal 0 HcmV?d00001 diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/platform/binaryLogging-1.0.mf b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/platform/binaryLogging-1.0.mf new file mode 100755 index 00000000000..242af6b39e9 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/platform/binaryLogging-1.0.mf @@ -0,0 +1,15 @@ +Subsystem-ManifestVersion: 1 +IBM-ShortName: binaryLogging-1.0 +Subsystem-SymbolicName: com.ibm.websphere.appserver.binary.logging-1.0; visibility:=private +Subsystem-Version: 1.0.0 + +WebSphere-LogProvider: com.ibm.ws.logging.internal.hpel.HpelLogProviderImpl + +## +## This relies on defaultLogging. We include a location hint to +## assist with bootstrapping. This is not generally applicable (don't copy). +## +Subsystem-Content: com.ibm.websphere.appserver.logging-1.0; location:="lib/platform/defaultLogging-1.0.mf"; type="osgi.subsystem.feature", + +Subsystem-Type: osgi.subsystem.feature +IBM-Feature-Version: 2 \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/platform/defaultLogging-1.0.mf b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/platform/defaultLogging-1.0.mf new file mode 100755 index 00000000000..f6f835186b7 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/platform/defaultLogging-1.0.mf @@ -0,0 +1,12 @@ +Subsystem-ManifestVersion: 1 +IBM-ShortName: defaultLogging-1.0 +Subsystem-SymbolicName: com.ibm.websphere.appserver.logging-1.0; visibility:=private +Subsystem-Version: 1.0.0 + +WebSphere-LogProvider: com.ibm.ws.logging.internal.impl.LogProviderImpl + +Subsystem-Content: a.b; version="[1,1.0.100)"; type="boot.jar", + a.b; version="[1,1.0.100)" + +Subsystem-Type: osgi.subsystem.feature +IBM-Feature-Version: 2 \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/platform/emptyLogging-1.0.mf b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/platform/emptyLogging-1.0.mf new file mode 100755 index 00000000000..4a524e0d0b3 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/platform/emptyLogging-1.0.mf @@ -0,0 +1,9 @@ +Subsystem-ManifestVersion: 1 +IBM-ShortName: emptyLogging-1.0 +Subsystem-SymbolicName: com.ibm.websphere.appserver.logging-1.0; visibility:=private +Subsystem-Version: 1.0.0 + +WebSphere-LogProvider: dummy.LogProvider + +Subsystem-Type: osgi.subsystem.feature +IBM-Feature-Version: 2 \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/platform/extension-1.0.mf b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/platform/extension-1.0.mf new file mode 100755 index 00000000000..de2a12fb769 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/platform/extension-1.0.mf @@ -0,0 +1,8 @@ +Subsystem-ManifestVersion: 1 +Subsystem-SymbolicName: com.ibm.websphere.appserver.logging-1.0; visibility:=private +Subsystem-Version: 1.0.0 + +Subsystem-Content: a.b; version="[1,1.0.100)"; type="boot.jar", + +Subsystem-Type: osgi.subsystem.feature +IBM-Feature-Version: 2 \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/platform/kernel-1.0.mf b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/platform/kernel-1.0.mf new file mode 100755 index 00000000000..fb9341772a5 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/platform/kernel-1.0.mf @@ -0,0 +1,64 @@ +Subsystem-ManifestVersion: 1 +Subsystem-SymbolicName: com.ibm.websphere.appserver.kernel-1.0; visibility:=private +Subsystem-Version: 1.0.0 +Subsystem-Content: README.TXT; location:="README.TXT"; type="file", + Copyright.txt; location:="Copyright.txt"; type="file", + isadc; location:="bin/isadc"; type="file", + isadc.bat; location:="bin/isadc.bat"; type="file", + productInfo; location:="bin/productInfo"; type="file", + productInfo.bat; location:="bin/productInfo.bat"; type="file", + securityUtility; location:="bin/securityUtility"; type="file", + securityUtility.bat; location:="bin/securityUtility.bat"; type="file", + featureManager; location:="bin/featureManager"; type="file", + featureManager.bat; location:="bin/featureManager.bat"; type="file", + server; location:="bin/server"; type="file", + server.bat; location:="bin/server.bat"; type="file", + ws-featurelist.jar; location:="bin/tools/ws-featurelist.jar"; type="file", + ws-featureManager.jar; location:="bin/tools/ws-featureManager.jar"; type="file", + ws-isadc.jar; location:="bin/tools/ws-isadc.jar"; type="file", + ws-productutil.jar; location:="bin/tools/ws-productutil.jar"; type="file", + ws-schemagen.jar; location:="bin/tools/ws-schemagen.jar"; type="file", + ws-securityutil.jar; location:="bin/tools/ws-securityutil.jar"; type="file", + cachespec.dtd; location:="dev/api/ibm/schema/cachespec.dtd"; type="file", + ibm-application-bnd_1_0.xsd; location:="dev/api/ibm/schema/ibm-application-bnd_1_0.xsd"; type="file", + ibm-application-bnd_1_1.xsd; location:="dev/api/ibm/schema/ibm-application-bnd_1_1.xsd"; type="file", + ibm-application-ext_1_0.xsd; location:="dev/api/ibm/schema/ibm-application-ext_1_0.xsd"; type="file", + ibm-application-ext_1_1.xsd; location:="dev/api/ibm/schema/ibm-application-ext_1_1.xsd"; type="file", + ibm-common-bnd_1_0.xsd; location:="dev/api/ibm/schema/ibm-common-bnd_1_0.xsd"; type="file", + ibm-common-bnd_1_1.xsd; location:="dev/api/ibm/schema/ibm-common-bnd_1_1.xsd"; type="file", + ibm-common-ext_1_0.xsd; location:="dev/api/ibm/schema/ibm-common-ext_1_0.xsd"; type="file", + ibm-common-ext_1_1.xsd; location:="dev/api/ibm/schema/ibm-common-ext_1_1.xsd"; type="file", + ibm-ejb-jar-bnd_1_0.xsd; location:="dev/api/ibm/schema/ibm-ejb-jar-bnd_1_0.xsd"; type="file", + ibm-ejb-jar-bnd_1_1.xsd; location:="dev/api/ibm/schema/ibm-ejb-jar-bnd_1_1.xsd"; type="file", + ibm-ejb-jar-ext_1_0.xsd; location:="dev/api/ibm/schema/ibm-ejb-jar-ext_1_0.xsd"; type="file", + ibm-ejb-jar-ext_1_1.xsd; location:="dev/api/ibm/schema/ibm-ejb-jar-ext_1_1.xsd"; type="file", + ibm-managed-bean-bnd_1_0.xsd; location:="dev/api/ibm/schema/ibm-managed-bean-bnd_1_0.xsd"; type="file", + ibm-web-bnd_1_0.xsd; location:="dev/api/ibm/schema/ibm-web-bnd_1_0.xsd"; type="file", + ibm-web-bnd_1_1.xsd; location:="dev/api/ibm/schema/ibm-web-bnd_1_1.xsd"; type="file", + ibm-web-ext_1_0.xsd; location:="dev/api/ibm/schema/ibm-web-ext_1_0.xsd"; type="file", + ibm-web-ext_1_1.xsd; location:="dev/api/ibm/schema/ibm-web-ext_1_1.xsd"; type="file", + com.ibm.websphere.appserver.spi.kernel.filemonitor; location:="dev/spi/ibm/com.ibm.websphere.appserver.spi.kernel.filemonitor_1.0.0.jar"; type="jar", + com.ibm.websphere.appserver.spi.kernel.service; location:="dev/spi/ibm/com.ibm.websphere.appserver.spi.kernel.service_1.0.0.jar"; type="jar", + com.ibm.websphere.appserver.spi.kernel.metatype; location:="dev/spi/ibm/com.ibm.websphere.appserver.spi.kernel.metatype_1.0.0.jar"; type="jar", + com.ibm.websphere.appserver.spi.logging; location:="dev/spi/ibm/com.ibm.websphere.appserver.spi.logging_1.1.0.jar"; type="jar", + com.ibm.websphere.appserver.spi.kernel.filemonitor_1.0-javadoc.zip; location:="dev/spi/ibm/javadoc/com.ibm.websphere.appserver.spi.kernel.filemonitor_1.0-javadoc.zip"; type="file", + com.ibm.websphere.appserver.spi.kernel.metatype_1.0-javadoc.zip; location:="dev/spi/ibm/javadoc/com.ibm.websphere.appserver.spi.kernel.metatype_1.0-javadoc.zip"; type="file", + com.ibm.websphere.appserver.spi.kernel.service_1.0-javadoc.zip; location:="dev/spi/ibm/javadoc/com.ibm.websphere.appserver.spi.kernel.service_1.0-javadoc.zip"; type="file", + com.ibm.websphere.appserver.spi.logging_1.1-javadoc.zip; location:="dev/spi/ibm/javadoc/com.ibm.websphere.appserver.spi.logging_1.1-javadoc.zip"; type="file", + com.ibm.websphere.appserver.spi.threading_1.0.0.jar; location:="dev/spi/ibm/com.ibm.websphere.appserver.spi.threading_1.0.0.jar"; type="jar", + com.ibm.websphere.appserver.spi.threading_1.0-javadoc.zip; location:="dev/spi/ibm/javadoc/com.ibm.websphere.appserver.spi.threading_1.0-javadoc.zip"; type="file", + osgi.core; location:="dev/spi/spec/com.ibm.wsspi.org.osgi.core.5.0.0_1.0.0.jar"; type="jar", + wlp-anttasks.jar; location:="dev/tools/ant/wlp-anttasks.jar"; type="file", + bootstrap-agent.jar; location:="lib/bootstrap-agent.jar"; type="file", + ws-launch.jar; location:="lib/ws-launch.jar"; type="file", + com.ibm.ws.org.apache.commons.lang.2.4_1.0.0.jar; location:="lib/com.ibm.ws.org.apache.commons.lang.2.4_1.0.0.jar"; type="jar", + com.ibm.rls.og_1.0.jar; location:="lib/com.ibm.rls.og_1.0.jar"; type="jar", + com.ibm.ws.anno.servlet_1.0.1.jar; location:="lib/com.ibm.ws.anno.servlet_1.0.1.jar"; type="jar", + com.ibm.ws.managedobject_1.0.jar; location:="lib/com.ibm.ws.managedobject_1.0.jar"; type="jar", + com.ibm.ws.product.utility_1.0.2.jar; location:="lib/com.ibm.ws.product.utility_1.0.2.jar"; type="jar", + com.ibm.ws.security.utility_1.0.3.jar; location:="lib/com.ibm.ws.security.utility_1.0.3.jar"; type="jar", + com.ibm.ws.timedoperations_1.0.jar; location:="lib/com.ibm.ws.timedoperations_1.0.jar"; type="jar", + internal-isadc.bat; location:="lib/tools/internal-isadc.bat";type="file", + .isadc; location:="lib/tools/.isadc";type="file" +Subsystem-Type: osgi.subsystem.feature +IBM-Feature-Version: 2 \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/platform/kernelCore-1.0.mf b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/platform/kernelCore-1.0.mf new file mode 100755 index 00000000000..e5fe928b845 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/platform/kernelCore-1.0.mf @@ -0,0 +1,13 @@ +Subsystem-ManifestVersion: 1 +IBM-ShortName: kernelCore-1.0 +Subsystem-SymbolicName: com.ibm.websphere.appserver.kernelCore-1.0; visibility:=private +Subsystem-Version: 1.0.0 + +WebSphere-LogProvider: dummy.LogProvider + +Subsystem-Content: com.ibm.websphere.appserver.kernel-1.0; type="osgi.subsystem.feature", + x.y; version="[1.0.0,1.0.100)"; type="boot.jar", + x.y; version="[1.0.0,1.0.100)"; start-phase:=BOOTSTRAP, + +Subsystem-Type: osgi.subsystem.feature +IBM-Feature-Version: 2 diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/platform/kernelCoreMissing-1.0.mf b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/platform/kernelCoreMissing-1.0.mf new file mode 100755 index 00000000000..bc67f16575f --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/platform/kernelCoreMissing-1.0.mf @@ -0,0 +1,10 @@ +Subsystem-ManifestVersion: 1 +Subsystem-SymbolicName: com.ibm.websphere.appserver.kernelCore-1.0; visibility:=private +Subsystem-Version: 1.0.0 + +Subsystem-Content: com.ibm.websphere.appserver.kernel-1.0; type="osgi.subsystem.feature", + x.y; version="[1.0.0,1.0.100)"; type="boot.jar", + p.q; version="[1.0.0,1.0.100)", + +Subsystem-Type: osgi.subsystem.feature +IBM-Feature-Version: 2 diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/platform/missingJar-1.0.mf b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/platform/missingJar-1.0.mf new file mode 100755 index 00000000000..5ddf4899c71 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/platform/missingJar-1.0.mf @@ -0,0 +1,10 @@ +Subsystem-ManifestVersion: 1 +IBM-ShortName: emptyLogging-1.0 +Subsystem-SymbolicName: com.ibm.websphere.appserver.logging-1.0; visibility:=private +Subsystem-Version: 1.0.0 + +Subsystem-Content: com.ibm.websphere.appserver.kernel-1.0; type="osgi.subsystem.feature", + p.q; version="[1.0.0,1.0.100)"; type="boot.jar" + +Subsystem-Type: osgi.subsystem.feature +IBM-Feature-Version: 2 \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/rebuildjars.bat b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/rebuildjars.bat new file mode 100755 index 00000000000..290d4f76350 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/rebuildjars.bat @@ -0,0 +1,15 @@ +set JAR=c:\java60\bin\jar + +for /r %%i in (*.jar) do ( + if exist %%~ni.mf ( + echo "%%~ni" + mkdir "%%~ni" + cd %%~ni + %JAR% xvf "%%i" + cd .. + del "%%i" + %JAR% cvmf "%%~ni.mf" "%%i" -C "%%~ni" . + del /s/q "%%~ni" + rmdir /s/q "%%~ni" + ) + ) \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/x.y_1.0.jar b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/x.y_1.0.jar new file mode 100755 index 0000000000000000000000000000000000000000..155f46165f9993e6371e5cce9b3783e6bc6dbbc6 GIT binary patch literal 371 zcmWIWW@Zs#-~hreC8kacNPv@pg~8V~#8KDN&rSc|DFy~+h5&DN4v-2asImZ@nni#r z;F^6M{XE@VgG2Ou-9G!CIql=Et9OytTUYDcne&^246YbIcv_@&*88OARo-=Hd{3P} z>GRF|jPKT<6&F@Nd0M3B<*VcAd$DvCi>B#i8JR>FP<;qIu0@wnX YaIHwb4e(}V1F2#H!df8x0K{Pc0Ch4|iU0rr literal 0 HcmV?d00001 diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/x.y_1.0.mf b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/x.y_1.0.mf new file mode 100755 index 00000000000..f430599b2d7 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lbr/lib/x.y_1.0.mf @@ -0,0 +1,3 @@ +Bundle-ManifestVersion: 2 +Bundle-SymbolicName: x.y +Bundle-Version: 1.0 diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lib/platform/include.properties b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lib/platform/include.properties new file mode 100755 index 00000000000..2b550e2ae72 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lib/platform/include.properties @@ -0,0 +1,3 @@ +bootstrap.include=peer.properties, ../platform/relative.properties +dummy=true +override=original \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lib/platform/peer.properties b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lib/platform/peer.properties new file mode 100755 index 00000000000..f1d7c4837a1 --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lib/platform/peer.properties @@ -0,0 +1,2 @@ +override=peer +peer=found \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lib/platform/relative.properties b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lib/platform/relative.properties new file mode 100755 index 00000000000..82d0ad91bcd --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lib/platform/relative.properties @@ -0,0 +1,2 @@ +override=relative +relative=found \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lib/platform/testDefNoEquals.map b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lib/platform/testDefNoEquals.map new file mode 100755 index 00000000000..38467bdd9ad --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lib/platform/testDefNoEquals.map @@ -0,0 +1,2 @@ +Alpine-ListVersion=a +TestStringNoValue \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lib/versions/WebSphereApplicationServer.properties b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lib/versions/WebSphereApplicationServer.properties new file mode 100755 index 00000000000..825482e73eb --- /dev/null +++ b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/lib/versions/WebSphereApplicationServer.properties @@ -0,0 +1,7 @@ +com.ibm.websphere.productId=com.ibm.websphere.appserver +com.ibm.websphere.productOwner=IBM +com.ibm.websphere.productVersion=$LIBERTY_VERSION$ +com.ibm.websphere.productName=WebSphere Application Server +com.ibm.websphere.productInstallType=Archive +com.ibm.websphere.productEdition=BASE_ILAN +com.ibm.websphere.productLicenseType=ILAN diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/test data/nonIFixLBR/lib/a.b_1.0.0.jar b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/nonIFixLBR/lib/a.b_1.0.0.jar new file mode 100755 index 0000000000000000000000000000000000000000..09cf269ca3a82ca30d3e620aaabdad6fcd9b65bc GIT binary patch literal 371 zcmWIWW@Zs#-~d9G`P&>AkN_tG3xls~h@-BjpPT-_Qw$8u3<2Kk93T};P-Ou)HH!dM zz%~0i`gyv!28ZbRx_$ONbK1vSSMMUPx31Q?Gv_x48C)@b@U%$ltoKPzS3wp|Yw@LO z)0QlIVHMica^?%qqh4N76B%x8JR>FP<;qIu0@wnX YaIHwb4e(}V1F2#H!df8x0K{Pc07({8@c;k- literal 0 HcmV?d00001 diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/test data/nonIFixLBR/lib/a.b_1.0.1.jar b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/nonIFixLBR/lib/a.b_1.0.1.jar new file mode 100755 index 0000000000000000000000000000000000000000..94f8985caa1a71156a88fdd3fc6da4a4e48c5038 GIT binary patch literal 373 zcmWIWW@Zs#-~htx`P&>AkN_tG3xls~h@-BjpPT-_Qw$8u3<2Kk93T};P-Ou)HH!dM zz%~0i`gyv!28ZbRx_$ONbK1vSSMMUPx31Q?Gv_x48C)@b@U%$ltoKPzSHUaBPo5U( zdHL#i`d%zu#lkuBrQ{K5X{`(kF_9-rv?`vdzRo;U`pfBT>+A%U>0Im1_?|j{(&wA^ z8Q-lz9#^~{J$>|)3GB!%5sJLYKqqtnaey}?lL!NjUkK|VwP aTObpz70JH=-mGjORZKuw3#1=`I1B(eU{-$s literal 0 HcmV?d00001 diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/test data/nonIFixLBR/lib/a.b_1.0.100.jar b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/nonIFixLBR/lib/a.b_1.0.100.jar new file mode 100755 index 0000000000000000000000000000000000000000..35bf68176aa5f47b8d276ea333b1f6ce81afda2d GIT binary patch literal 374 zcmWIWW@Zs#-~ht%`P&>AkN_tG3xls~h@-BjpPT-_Qw$8u3<2Kk93T};P-Ou)HH!dM zz%~0i`gyv!28ZbRx_$ONbK1vSSMMUPx31Q?Gv_x48C)@b@U%$ltoKPzSHUaBCJbH{ z;!D-0Em`)$Dzu5^>=&L#y}Y6(GTdB6L83OFCw(<}SXH}F?eJNHCU4g8XKGKMr>Ol_ zeYPx0Q{|QF$D)r#j9^#3`IBRr0(3(c5C?cOGKnytdJ^UXkS9?A+|?j2qiaPr7UV?) bumv*VT9G^);LXYgQpE&>wLtnYh{FH?iXK*H literal 0 HcmV?d00001 diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/test data/nonIFixLBR/lib/a.b_1.0.jar b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/nonIFixLBR/lib/a.b_1.0.jar new file mode 100755 index 0000000000000000000000000000000000000000..dc6ee8852999440214852172853301d64147e87d GIT binary patch literal 369 zcmWIWW@Zs#-~d9F1=}1LkN_tG3xls~h@-BjpPT-_Qw$8u3<2Kk93T};P-Ou)HH!dM zz%~0i`gyv!28ZbRx_$ONbK1vSSMMUPx31Q?Gv_x48C)@b@U%$ltoKPzSK$&pFJB!` z-;1TISU6|AlsqCWt(9RRCh}y7R>d>b*O`aD{&ezfeQn<4%^Lnp?dkIrwco1GmPKi* zyi)yG^s$H$?7(HrPlMxu*0%w1fHxzP2m`ABV2%g*4;8>24Dv0yR%ByAzC!?8AQP?? V$*%$4tZX1vOh8x*r0;<^3;04D0erIA^?+JR&Wvm0=+!@??ot#WU5{nTNjqbnGKq|->T1+MQMh- z2>n#_v4|1uK#iKo+v0)Nw*hg0HzSh>1FHXEjtBV<6~G+~@-4bnWMe_TLjYSK6Rs7> UuL0hyY#>!kKv)Z;?}0cB0JmIHM*si- literal 0 HcmV?d00001 diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/test data/resources/resources1.jar b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/resources/resources1.jar new file mode 100755 index 0000000000000000000000000000000000000000..be7b833e8d22dc80f75913a8da36d3ddb8155dc1 GIT binary patch literal 736 zcmWIWW@Zs#00I3RZFl2|&lA~zY!H?N;-b{z{L-T2)MEXT)Z!Aof};F_)S{A1ARCBm z4Flks{{S@u)x!Y?kd>UDtDl*atB+8{l#8m08%b4pF_J=dG=)N_3bRv-@=|k<)C-`g z7sskTDL=miNfWw<)o^RV;d@3V5eD3W2Q-d>kwF1O0RhgS4Dd!6gDn^#+691=Ef6CD z6`>1Tup)FNBk2MMGD0J^U`A-{LDdKkbcB9v!H&?s2djQ)Bp?jI77ZXnAVK#Lw;^be X65!1WO18kX%f`^p$iQF?#0(4ohw6ro literal 0 HcmV?d00001 diff --git a/dev/com.ibm.ws.kernel.boot_test/unittest/test data/resources/resources2.jar b/dev/com.ibm.ws.kernel.boot_test/unittest/test data/resources/resources2.jar new file mode 100755 index 0000000000000000000000000000000000000000..31d30e11c4f8cb94e970be650ddf656106ff2271 GIT binary patch literal 736 zcmWIWW@Zs#00HY9ZTHRt?|!fW*&r+l#6_va`K3k4sm1ywsl_FF1x5Ja)b3%F+Td;v&L|N_5g9wQB12MFZ$wvdWJ_=BiecJi=WofK+W)z&qOx z7~G?7${u66>`F7phYKj?`Q-QCBA49pV~faIr|PHbzeaw%i-Zxp=Z2(k$bLHQh(3SF zh=)X4-EOlgafEB(<~NM#u*o0*Cz*K{iKsXRrq(+TxDQACSk8x8#XrWE8JTo+gg3lE z{)XO$5AH!KOL_y~jn&rj2${IszX87kF$+O{DweK}yR-}w)9%n|4~5;df8fwk&u2qS zjp2G{pnAo4_f$KRb=v)q5$qG$d8$6MwNyp&;Oy&pU5|Z(7-~R(X(jZk-XG2$% zr+WbzJW&BQoI*7Aenw#Q$|p(}PXj{P&A9JWQPz?@e(gFE!*w>OOWrFz1>yVm*zUK) zw=3J#u*8NwgbW~{Z6IAqL8HeyG*Cz06jXPf8zk%Ge8kXi9SPWoDe{qc6+Anj`wyl@ z__J~99;KUb6OpRn)e7u7Gg+f~8~OcXMf=Mf)# zVjww-KZ$X@ohHn`N|K8AB}XddTQJO`(qNw6FV2&bmD^7G6scr~*Td9J<-8W27pa?`}~oF;@Nl90-xS)t4^9~}C<)N%Tl zltiel1W_T>@UkQlb|1_!FD)O1`iCxav~qL1*T@cv$)CO!NW2fl?nW$&2yhbHt*)D5 zqyB*6Zdsj>m&kZ1{E)vx^-TpiYp#f1FF+i}{Rg?NUn+e-?6^O0t%lodmOu^R$f>mM z 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 literal 0 HcmV?d00001 diff --git a/dev/com.ibm.ws.kernel.feature_test/bnd.bnd.gradle b/dev/com.ibm.ws.kernel.feature_test/bnd.bnd.gradle index f542f561a2c..f915f94644e 100644 --- a/dev/com.ibm.ws.kernel.feature_test/bnd.bnd.gradle +++ b/dev/com.ibm.ws.kernel.feature_test/bnd.bnd.gradle @@ -17,6 +17,7 @@ src: \ com.ibm.websphere.org.osgi.service.cm.1.5.0;version=latest,\ com.ibm.websphere.org.osgi.service.component.1.3.0;version=latest,\ com.ibm.ws.kernel.boot.core;version=latest,\ + com.ibm.ws.kernel.boot.nested;version=latest,\ com.ibm.ws.kernel.service;version=latest,\ com.ibm.ws.kernel.service.location;version=latest,\ com.ibm.ws.logging.core;version=latest,\ diff --git a/dev/com.ibm.ws.kernel.filemonitor_fat/.classpath b/dev/com.ibm.ws.kernel.filemonitor_fat/.classpath new file mode 100644 index 00000000000..c422489df40 --- /dev/null +++ b/dev/com.ibm.ws.kernel.filemonitor_fat/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/dev/com.ibm.ws.kernel.filemonitor_fat/.classpath.gradle b/dev/com.ibm.ws.kernel.filemonitor_fat/.classpath.gradle new file mode 100644 index 00000000000..c422489df40 --- /dev/null +++ b/dev/com.ibm.ws.kernel.filemonitor_fat/.classpath.gradle @@ -0,0 +1,7 @@ + + + + + + + diff --git a/dev/com.ibm.ws.kernel.filemonitor_fat/.gitignore b/dev/com.ibm.ws.kernel.filemonitor_fat/.gitignore new file mode 100644 index 00000000000..62c58326f56 --- /dev/null +++ b/dev/com.ibm.ws.kernel.filemonitor_fat/.gitignore @@ -0,0 +1,2 @@ +dropins +/nohup.out diff --git a/dev/com.ibm.ws.kernel.filemonitor_fat/.project b/dev/com.ibm.ws.kernel.filemonitor_fat/.project new file mode 100755 index 00000000000..ab03967beda --- /dev/null +++ b/dev/com.ibm.ws.kernel.filemonitor_fat/.project @@ -0,0 +1,23 @@ + + + com.ibm.ws.kernel.filemonitor_fat + + + + + + org.eclipse.jdt.core.javabuilder + + + + + bndtools.core.bndbuilder + + + + + + org.eclipse.jdt.core.javanature + bndtools.core.bndnature + + diff --git a/dev/com.ibm.ws.kernel.filemonitor_fat/.settings/org.eclipse.core.resources.prefs b/dev/com.ibm.ws.kernel.filemonitor_fat/.settings/org.eclipse.core.resources.prefs new file mode 100755 index 00000000000..25d9425fe34 --- /dev/null +++ b/dev/com.ibm.ws.kernel.filemonitor_fat/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,4 @@ +#Ant properties +#Automatically generated by the ant prepare.settings.files task +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/dev/com.ibm.ws.kernel.filemonitor_fat/.settings/org.eclipse.jdt.core.prefs b/dev/com.ibm.ws.kernel.filemonitor_fat/.settings/org.eclipse.jdt.core.prefs new file mode 100755 index 00000000000..f48ecd6cc60 --- /dev/null +++ b/dev/com.ibm.ws.kernel.filemonitor_fat/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,280 @@ +#Ant properties +#Automatically generated by the ant prepare.settings.files task +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.6 +org.eclipse.jdt.core.formatter.align_type_members_on_columns=false +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=0 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=18 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=2 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=2 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=18 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=2 +org.eclipse.jdt.core.formatter.alignment_for_assignment=0 +org.eclipse.jdt.core.formatter.alignment_for_binary_expression=18 +org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=0 +org.eclipse.jdt.core.formatter.alignment_for_enum_constants=16 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=18 +org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=18 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=18 +org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=0 +org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=20 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=4 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +org.eclipse.jdt.core.formatter.blank_lines_before_field=0 +org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 +org.eclipse.jdt.core.formatter.blank_lines_before_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 +org.eclipse.jdt.core.formatter.blank_lines_before_package=0 +org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 +org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 +org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false +org.eclipse.jdt.core.formatter.comment.format_block_comments=true +org.eclipse.jdt.core.formatter.comment.format_header=false +org.eclipse.jdt.core.formatter.comment.format_html=false +org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true +org.eclipse.jdt.core.formatter.comment.format_line_comments=false +org.eclipse.jdt.core.formatter.comment.format_source_code=true +org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true +org.eclipse.jdt.core.formatter.comment.indent_root_tags=true +org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert +org.eclipse.jdt.core.formatter.comment.line_length=180 +org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true +org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true +org.eclipse.jdt.core.formatter.compact_else_if=true +org.eclipse.jdt.core.formatter.continuation_indentation=4 +org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=4 +org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off +org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on +org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false +org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=false +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true +org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_empty_lines=false +org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true +org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true +org.eclipse.jdt.core.formatter.indentation.size=8 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert +org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.join_lines_in_comments=false +org.eclipse.jdt.core.formatter.join_wrapped_lines=false +org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false +org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false +org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false +org.eclipse.jdt.core.formatter.lineSplit=180 +org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=true +org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=true +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 +org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=false +org.eclipse.jdt.core.formatter.tabulation.char=space +org.eclipse.jdt.core.formatter.tabulation.size=4 +org.eclipse.jdt.core.formatter.use_on_off_tags=true +org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false +org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true +org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true diff --git a/dev/com.ibm.ws.kernel.filemonitor_fat/.settings/org.eclipse.jdt.ui.prefs b/dev/com.ibm.ws.kernel.filemonitor_fat/.settings/org.eclipse.jdt.ui.prefs new file mode 100755 index 00000000000..74d9c72c1f3 --- /dev/null +++ b/dev/com.ibm.ws.kernel.filemonitor_fat/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,113 @@ +#Ant properties +#Automatically generated by the ant prepare.settings.files task +cleanup.add_default_serial_version_id=false +cleanup.add_generated_serial_version_id=true +cleanup.add_missing_annotations=true +cleanup.add_missing_deprecated_annotations=true +cleanup.add_missing_methods=false +cleanup.add_missing_nls_tags=false +cleanup.add_missing_override_annotations=true +cleanup.add_missing_override_annotations_interface_methods=true +cleanup.add_serial_version_id=false +cleanup.always_use_blocks=true +cleanup.always_use_parentheses_in_expressions=false +cleanup.always_use_this_for_non_static_field_access=false +cleanup.always_use_this_for_non_static_method_access=false +cleanup.convert_to_enhanced_for_loop=false +cleanup.correct_indentation=true +cleanup.format_source_code=false +cleanup.format_source_code_changes_only=false +cleanup.make_local_variable_final=false +cleanup.make_parameters_final=true +cleanup.make_private_fields_final=false +cleanup.make_type_abstract_if_missing_method=false +cleanup.make_variable_declarations_final=false +cleanup.never_use_blocks=false +cleanup.never_use_parentheses_in_expressions=true +cleanup.organize_imports=false +cleanup.qualify_static_field_accesses_with_declaring_class=false +cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true +cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true +cleanup.qualify_static_member_accesses_with_declaring_class=true +cleanup.qualify_static_method_accesses_with_declaring_class=false +cleanup.remove_private_constructors=true +cleanup.remove_trailing_whitespaces=true +cleanup.remove_trailing_whitespaces_all=true +cleanup.remove_trailing_whitespaces_ignore_empty=false +cleanup.remove_unnecessary_casts=true +cleanup.remove_unnecessary_nls_tags=true +cleanup.remove_unused_imports=true +cleanup.remove_unused_local_variables=false +cleanup.remove_unused_private_fields=true +cleanup.remove_unused_private_members=false +cleanup.remove_unused_private_methods=true +cleanup.remove_unused_private_types=true +cleanup.sort_members=false +cleanup.sort_members_all=false +cleanup.use_blocks=true +cleanup.use_blocks_only_for_return_and_throw=false +cleanup.use_parentheses_in_expressions=true +cleanup.use_this_for_non_static_field_access=false +cleanup.use_this_for_non_static_field_access_only_if_necessary=true +cleanup.use_this_for_non_static_method_access=false +cleanup.use_this_for_non_static_method_access_only_if_necessary=true +eclipse.preferences.version=1 +editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true +org.eclipse.jdt.ui.ignorelowercasenames=true +org.eclipse.jdt.ui.importorder=java;javax;org;com; +org.eclipse.jdt.ui.javadoc=true +org.eclipse.jdt.ui.ondemandthreshold=99 +org.eclipse.jdt.ui.staticondemandthreshold=99 +org.eclipse.jdt.ui.text.custom_code_templates= +sp_cleanup.add_default_serial_version_id=true +sp_cleanup.add_generated_serial_version_id=false +sp_cleanup.add_missing_annotations=true +sp_cleanup.add_missing_deprecated_annotations=true +sp_cleanup.add_missing_methods=false +sp_cleanup.add_missing_nls_tags=false +sp_cleanup.add_missing_override_annotations=true +sp_cleanup.add_missing_override_annotations_interface_methods=true +sp_cleanup.add_serial_version_id=false +sp_cleanup.always_use_blocks=true +sp_cleanup.always_use_parentheses_in_expressions=false +sp_cleanup.always_use_this_for_non_static_field_access=false +sp_cleanup.always_use_this_for_non_static_method_access=false +sp_cleanup.convert_to_enhanced_for_loop=false +sp_cleanup.correct_indentation=false +sp_cleanup.format_source_code=true +sp_cleanup.format_source_code_changes_only=false +sp_cleanup.make_local_variable_final=false +sp_cleanup.make_parameters_final=false +sp_cleanup.make_private_fields_final=true +sp_cleanup.make_type_abstract_if_missing_method=false +sp_cleanup.make_variable_declarations_final=true +sp_cleanup.never_use_blocks=false +sp_cleanup.never_use_parentheses_in_expressions=true +sp_cleanup.on_save_use_additional_actions=true +sp_cleanup.organize_imports=true +sp_cleanup.qualify_static_field_accesses_with_declaring_class=false +sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_with_declaring_class=false +sp_cleanup.qualify_static_method_accesses_with_declaring_class=false +sp_cleanup.remove_private_constructors=true +sp_cleanup.remove_trailing_whitespaces=true +sp_cleanup.remove_trailing_whitespaces_all=true +sp_cleanup.remove_trailing_whitespaces_ignore_empty=false +sp_cleanup.remove_unnecessary_casts=true +sp_cleanup.remove_unnecessary_nls_tags=true +sp_cleanup.remove_unused_imports=true +sp_cleanup.remove_unused_local_variables=false +sp_cleanup.remove_unused_private_fields=true +sp_cleanup.remove_unused_private_members=false +sp_cleanup.remove_unused_private_methods=true +sp_cleanup.remove_unused_private_types=true +sp_cleanup.sort_members=false +sp_cleanup.sort_members_all=false +sp_cleanup.use_blocks=false +sp_cleanup.use_blocks_only_for_return_and_throw=false +sp_cleanup.use_parentheses_in_expressions=false +sp_cleanup.use_this_for_non_static_field_access=false +sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true +sp_cleanup.use_this_for_non_static_method_access=false +sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true diff --git a/dev/com.ibm.ws.kernel.filemonitor_fat/bnd.bnd b/dev/com.ibm.ws.kernel.filemonitor_fat/bnd.bnd new file mode 100644 index 00000000000..35ef5a473ba --- /dev/null +++ b/dev/com.ibm.ws.kernel.filemonitor_fat/bnd.bnd @@ -0,0 +1,16 @@ +-include= ~../cnf/resources/bnd/bundle.props +bVersion=1.0 + +src: \ + fat/src + +-buildpath: \ + ${javac.bootclasspath.java6}, \ + ../build.sharedResources/lib/junit/old/junit.jar;version=file, \ + ../build.sharedResources/lib/ws-junit/ws-junit.jar;version=file, \ + ../build.sharedResources/lib/hamcrest-all.jar;version=file, \ + ../build.sharedResources/lib/jmock/old/jmock-junit4.jar;version=file, \ + ../build.sharedResources/lib/jmock/old/jmock.jar;version=file, \ + fattest.simplicity;version=latest, \ + com.ibm.ws.jmx.connector.client.rest;version=latest, \ + com.ibm.ws.kernel.filemonitor;version=latest diff --git a/dev/com.ibm.ws.kernel.filemonitor_fat/bnd.bnd.gradle b/dev/com.ibm.ws.kernel.filemonitor_fat/bnd.bnd.gradle new file mode 100644 index 00000000000..35ef5a473ba --- /dev/null +++ b/dev/com.ibm.ws.kernel.filemonitor_fat/bnd.bnd.gradle @@ -0,0 +1,16 @@ +-include= ~../cnf/resources/bnd/bundle.props +bVersion=1.0 + +src: \ + fat/src + +-buildpath: \ + ${javac.bootclasspath.java6}, \ + ../build.sharedResources/lib/junit/old/junit.jar;version=file, \ + ../build.sharedResources/lib/ws-junit/ws-junit.jar;version=file, \ + ../build.sharedResources/lib/hamcrest-all.jar;version=file, \ + ../build.sharedResources/lib/jmock/old/jmock-junit4.jar;version=file, \ + ../build.sharedResources/lib/jmock/old/jmock.jar;version=file, \ + fattest.simplicity;version=latest, \ + com.ibm.ws.jmx.connector.client.rest;version=latest, \ + com.ibm.ws.kernel.filemonitor;version=latest diff --git a/dev/com.ibm.ws.kernel.filemonitor_fat/build-test.xml b/dev/com.ibm.ws.kernel.filemonitor_fat/build-test.xml new file mode 100755 index 00000000000..4862d2787e3 --- /dev/null +++ b/dev/com.ibm.ws.kernel.filemonitor_fat/build-test.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.filemonitor_fat/build.gradle b/dev/com.ibm.ws.kernel.filemonitor_fat/build.gradle new file mode 100644 index 00000000000..e69de29bb2d diff --git a/dev/com.ibm.ws.kernel.filemonitor_fat/delivery.sets b/dev/com.ibm.ws.kernel.filemonitor_fat/delivery.sets new file mode 100755 index 00000000000..674398425a0 --- /dev/null +++ b/dev/com.ibm.ws.kernel.filemonitor_fat/delivery.sets @@ -0,0 +1 @@ +SLE diff --git a/dev/com.ibm.ws.kernel.filemonitor_fat/fat/src/com/ibm/ws/kernel/filemonitor/fat/AbstractNotificationTest.java b/dev/com.ibm.ws.kernel.filemonitor_fat/fat/src/com/ibm/ws/kernel/filemonitor/fat/AbstractNotificationTest.java new file mode 100755 index 00000000000..4ab5fd62387 --- /dev/null +++ b/dev/com.ibm.ws.kernel.filemonitor_fat/fat/src/com/ibm/ws/kernel/filemonitor/fat/AbstractNotificationTest.java @@ -0,0 +1,291 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.kernel.filemonitor.fat; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintWriter; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.junit.BeforeClass; + +import componenttest.topology.impl.LibertyServer; +import componenttest.topology.impl.LibertyServerFactory; + +/** + * + */ +public class AbstractNotificationTest { + + protected static final String MESSAGE_LOG = "logs/messages.log"; + private static final String BUNDLE_NAME = "com.ibm.ws.kernel.filemonitor.monitor.test.bundle_1.0.0"; + private static final String FEATURE_NAME = "monitoringPrintingFeature-1.0"; + + // Not thread-safe, but this code is unlikely to run multi-threaded, being a unit test + private static final DateFormat DATE_FORMAT = new SimpleDateFormat("HH:mm:ss:SSS"); + + protected static LibertyServer server; + protected static File monitoredFolder; + protected static File monitoredFile; + protected static File nonexistentFolder; + protected static File nonexistentFile; + + @BeforeClass + public static void classSetUp() throws Exception { + server = LibertyServerFactory + .getLibertyServer("com.ibm.ws.kernel.filemonitor.server"); + // install our user feature + server.installUserBundle(BUNDLE_NAME); // NO HYPHENS! NO ".jar" SUFFIX! + server.installUserFeature(FEATURE_NAME); // NO UNDERSCORES! NO ".mf" SUFFIX! + server.startServer(); + + // Figure out where our test monitors are monitoring + String foldereyecatcher = "-MONITORED FOLDER-"; + String line = server.waitForStringInLog(foldereyecatcher); + assertNotNull("Our test feature should report the folder location we're monitoring.", line); + int index = line.indexOf(foldereyecatcher) + foldereyecatcher.length(); + // We create the file objects but not files on disk + monitoredFolder = new File(line.substring(index)); + + String fileeyecatcher = "-MONITORED FILE-"; + line = server.waitForStringInLog(fileeyecatcher); + assertNotNull("Our test feature should report the file location we're monitoring.", line); + index = line.indexOf(fileeyecatcher) + fileeyecatcher.length(); + // We create the file objects but not files on disk + monitoredFile = new File(line.substring(index)); + + String nonexistentfileeyecatcher = "-NONEXISTENT FILE-"; + line = server.waitForStringInLog(nonexistentfileeyecatcher); + assertNotNull("Our test feature should report the file location we're monitoring.", line); + index = line.indexOf(nonexistentfileeyecatcher) + nonexistentfileeyecatcher.length(); + // We create the file objects but not files on disk + nonexistentFile = new File(line.substring(index)); + + String nonexistentfoldereyecatcher = "-NONEXISTENT FOLDER-"; + line = server.waitForStringInLog(nonexistentfoldereyecatcher); + assertNotNull("Our test feature should report the folder location we're monitoring.", line); + index = line.indexOf(nonexistentfoldereyecatcher) + nonexistentfoldereyecatcher.length(); + // We create the folder objects but not folders on disk + nonexistentFolder = new File(line.substring(index)); + + } + + /** + * Waits for notifications to catch up after file changes that we're not especially + * interested in. This method should be used with caution since it resets + * the mark, so it should only be used when no monitor might want to see + * the changes that got notified. + */ + protected int flushNotifications(MonitorReader monitor) throws Exception { + // Wait for notifications to catch up + int count = monitor.scrapeLogsForChanges(); + monitor.clear(); + + server.setMarkToEndOfLog(); + + return count; + } + + protected void createFolder(File folder) { + assertTrue("Folder should have been created on the file system", folder.mkdirs()); + } + + /** + * Creates a file and also asserts we did actually create it + * (thus avoiding many puzzling notification failures). + */ + protected void createFile(File f) throws IOException { + assertTrue("File should have been created on the file system: " + f, f.createNewFile()); + } + + /** + * Deletes a file or folder and all its contents. + * If anything doesn't get deleted, an assertion will be failed. + */ + protected boolean deleteFile(File f) { + boolean success = false; + for (int pass = 0; !success && pass < 10; ++pass) + { + if (f.isDirectory()) { + File[] files = f.listFiles(); + for (File file : files) { + if (file.isDirectory()) { // Very minor efficiency hack, avoid last level of recursion + // Recurse + deleteFile(file); + } else { + file.delete(); // Failure here will be caught by the later f.delete. Ugly, but that's what we had. + } + } + } + success = f.delete(); + + if (!success) + { + try + { + Thread.sleep(500); + } catch (InterruptedException e) + { + // that's ok, just try it again + } + } + } + assertTrue("Should have been able to delete the file " + f, success); + return success; + } + + protected void appendSomething(File f) throws FileNotFoundException { + PrintWriter w = new PrintWriter(new FileOutputStream(f)); + w.println(new Date() + "Append some stuff\n\n"); + w.flush(); + w.close(); + } + + protected boolean updateTimestamp(File f) { + return f.setLastModified(System.currentTimeMillis() - (30 * 60 * 1000)); + } + + protected void assertNothingDeleted(final MonitorReader monitorReader) { + assertTrue( + "The following files were unexpectedly reported as deleted by the " + monitorReader.name + ":" + stringify(monitorReader.deleted), + monitorReader.deleted.isEmpty()); + } + + protected void assertNothingDeleted(String messagePrefix, final MonitorReader monitorReader) { + assertTrue(messagePrefix + + "the following files were unexpectedly reported as deleted by the " + monitorReader.name + ":" + stringify(monitorReader.deleted), + monitorReader.deleted.isEmpty()); + } + + protected void assertNothingModified(final MonitorReader monitorReader) { + assertTrue("The following files were unexpectedly reported as modified by the " + monitorReader.name + ":" + stringify(monitorReader.modified), + monitorReader.modified.isEmpty()); + } + + protected void assertNothingCreated(String messagePrefix, final MonitorReader monitorReader) { + assertTrue(messagePrefix + + "the following files were unexpectedly reported as created by the " + monitorReader.name + ":" + stringify(monitorReader.created), + monitorReader.created.isEmpty()); + } + + protected void assertNothingCreated(final MonitorReader monitorReader) { + assertTrue( + "The following files were unexpectedly reported as created by the " + monitorReader.name + ":" + stringify(monitorReader.created), + monitorReader.created.isEmpty()); + } + + protected void assertModified(final MonitorReader monitorReader, File... files) { + + final Collection collected = new ArrayList(); + for (File file : files) { + collected.add(file); + } + + assertNothingCreated(monitorReader); + assertNothingDeleted(monitorReader); + + assertFalse("A file should have been reported as modified by the " + monitorReader.name + ". \nGave up searching at " + DATE_FORMAT.format(monitorReader.lastSearchTime) + + ".", monitorReader.modified.isEmpty()); + assertEqualsOrderless("The wrong file was reported as modified by the " + monitorReader.name, collected, monitorReader.modified); + } + + protected void assertDeleted(final MonitorReader monitorReader, File... files) { + + final Collection collected = new ArrayList(); + for (File file : files) { + collected.add(file); + } + + assertNothingModified(monitorReader); + assertNothingCreated(monitorReader); + + assertFalse("A file should have been reported as deleted by the " + monitorReader.name + ". \nGave up searching at " + DATE_FORMAT.format(monitorReader.lastSearchTime) + + ".", monitorReader.deleted.isEmpty()); + assertEqualsOrderless("The wrong file was reported as deleted by the " + monitorReader.name, collected, monitorReader.deleted); + } + + protected void assertCreated(final MonitorReader monitorReader, File... files) { + + final Collection collected = new ArrayList(); + for (File file : files) { + collected.add(file); + } + + assertNothingModified(monitorReader); + assertNothingDeleted(monitorReader); + + assertFalse("A file should have been reported as created by the " + monitorReader.name + ". \nGave up searching at " + DATE_FORMAT.format(monitorReader.lastSearchTime) + + ".", monitorReader.created.isEmpty()); + assertEqualsOrderless("The wrong file was reported as created by the " + monitorReader.name, collected, monitorReader.created); + } + + protected void assertEqualsOrderless(String message, File[] expected, Collection actual) { + assertEqualsOrderless(message, Arrays.asList(expected), actual); + } + + /** + * Compares two collections for equality, ignoring the original order of elements + */ + private void assertEqualsOrderless(String message, Collection expected, Collection actual) { + // Compare by sorting before comparing + + // Put into a set to eliminate duplicates (we'll check for those in a moment) + Set actualSet = convertToSet(actual); + Set expectedSet = convertToSet(expected); + + // Convert to a list so we get ordering + List expectedList = convertToSortedList(expectedSet); + List actualList = convertToSortedList(actualSet); + + assertEquals(message, expectedList, actualList); + + // Now check for duplicates (unless we had the same duplicates in the expected list) + assertEquals("Although we were notified about the correct files, the same file was unexpectedly included multiple times in the list of changed files.", + convertToSortedList(expectedList), + convertToSortedList(actual)); + + } + + private String stringify(Collection list) { + return Arrays.toString(list.toArray()); + } + + private List convertToSortedList(Collection collection) { + List list = new ArrayList(); + list.addAll(collection); + Collections.sort(list); + + return list; + } + + private Set convertToSet(Collection collection) { + Set set = new HashSet(); + set.addAll(collection); + return set; + } +} diff --git a/dev/com.ibm.ws.kernel.filemonitor_fat/fat/src/com/ibm/ws/kernel/filemonitor/fat/FATSuite.java b/dev/com.ibm.ws.kernel.filemonitor_fat/fat/src/com/ibm/ws/kernel/filemonitor/fat/FATSuite.java new file mode 100755 index 00000000000..cc2f711d5a4 --- /dev/null +++ b/dev/com.ibm.ws.kernel.filemonitor_fat/fat/src/com/ibm/ws/kernel/filemonitor/fat/FATSuite.java @@ -0,0 +1,25 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.kernel.filemonitor.fat; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +/** + * + */ +@RunWith(Suite.class) +@SuiteClasses( { FileMonitorTest.class, FileNotificationMBeanTest.class }) +public class FATSuite { + +} diff --git a/dev/com.ibm.ws.kernel.filemonitor_fat/fat/src/com/ibm/ws/kernel/filemonitor/fat/FileMonitorTest.java b/dev/com.ibm.ws.kernel.filemonitor_fat/fat/src/com/ibm/ws/kernel/filemonitor/fat/FileMonitorTest.java new file mode 100755 index 00000000000..4117cc1c7c6 --- /dev/null +++ b/dev/com.ibm.ws.kernel.filemonitor_fat/fat/src/com/ibm/ws/kernel/filemonitor/fat/FileMonitorTest.java @@ -0,0 +1,1022 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.kernel.filemonitor.fat; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.io.File; + +import org.junit.After; +import org.junit.Test; + +import componenttest.custom.junit.runner.Mode; +import componenttest.custom.junit.runner.Mode.TestMode; + +/** + * + */ +public class FileMonitorTest extends AbstractNotificationTest { + + /** + * Cut-and-pasted from the test feature. No direct compile-time or run-time + * communication is possible, so we're fragile. + */ + private static final MonitorReader fileMonitor = new MonitorReader("-FILETESTMONITOROUTPUT-", "file monitor"); + private static final MonitorReader nonexistentFileMonitor = new MonitorReader("-FILENONEXISTENTTESTMONITOROUTPUT-", "file monitor for file which doesn't exist"); + private static final MonitorReader confusedFileMonitor = new MonitorReader("-FILEBUTACTUALLYMONITORINGDIRECTORYTESTMONITOROUTPUT-", "file monitor for a file which is actually a folder"); + private static final MonitorReader recursiveMonitor = new MonitorReader("-RECURSIVETESTMONITOROUTPUT-", "recursive folder monitor"); + private static final MonitorReader nonexistentFolderMonitor = new MonitorReader("-NONEXISTENTFOLDERTESTMONITOROUTPUT-", "folder monitor for folder which doesn't exist"); + private static final MonitorReader confusedFolderMonitor = new MonitorReader("-RECURSIVEBUTACTUALLYMONITORINGFILETESTMONITOROUTPUT-", "folder monitor for a folder which is actually a file"); + private static final MonitorReader filterMonitor = new MonitorReader("-FILTEREDTESTMONITOROUTPUT-", "filtered folder monitor"); + private static final MonitorReader filefilterMonitor = new MonitorReader("-FILEFILTERTESTMONITOROUTPUT-", "only-files filtered folder monitor"); + private static final MonitorReader directoryfilterMonitor = new MonitorReader("-DIRECTORYFILTERTESTMONITOROUTPUT-", "only-directories filtered folder monitor"); + private static final MonitorReader nonRecursiveMonitor = new MonitorReader("-NONRECURSINGTESTMONITOROUTPUT-", "non-recursive folder monitor"); + private static final MonitorReader nonRecursiveMonitorSelfMonitor = new MonitorReader("-NONRECURSEMONITORSELFTESTMONITOROUTPUT-", "non-recursive self-monitoring folder monitor"); + private static final MonitorReader monitorSelfMonitor = new MonitorReader("-MONITORSELFTESTMONITOROUTPUT-", "self-monitoring folder monitor"); + + @After + public void tearDown() throws Exception { + // Clear up after any tests which may have deleted the monitored folder + if (!monitoredFolder.exists()) { + monitoredFolder.mkdirs(); + // Get rid of any notifications from reinstating the folder + // This flush assumes that the monitor self monitor works + flushNotifications(monitorSelfMonitor); + } + + // Get rid of any dangling notifications from tests, using the monitor most likely to catch something + flushNotifications(recursiveMonitor); + + } + + @Test + public void testBaselineIsReported() throws Exception { + + recursiveMonitor.scrapeLogsForBaseline(); + + assertFalse("The baseline should not be empty", recursiveMonitor.baseline.isEmpty()); + // We're not monitoring the directory itself, so it won't get included in the baseline + } + + @Mode(TestMode.FULL) + @Test + public void testBaselineIncludesNestedFolders() throws Exception { + File baseline = new File(monitoredFolder, "baseline"); + File baseline1 = new File(monitoredFolder, "baseline1"); + File nested = new File(monitoredFolder, "nestedBaselineFolder"); + File nestedFile = new File(nested, "nestedBaselineFile"); + + recursiveMonitor.scrapeLogsForBaseline(); + + assertFalse("The baseline should not be empty", recursiveMonitor.baseline.isEmpty()); + assertEqualsOrderless("The baseline didn't have the expected files in it.", new File[] { baseline, baseline1, nested, nestedFile }, recursiveMonitor.baseline); + } + + @Test + public void testBaselineDoesNotIncludeNestedFoldersInNonRecursiveCase() throws Exception { + File baseline = new File(monitoredFolder, "baseline"); + File baseline1 = new File(monitoredFolder, "baseline1"); + File nested = new File(monitoredFolder, "nestedBaselineFolder"); + + nonRecursiveMonitor.scrapeLogsForBaseline(); + + assertFalse("The baseline should not be empty", nonRecursiveMonitor.baseline.isEmpty()); + assertEqualsOrderless("The baseline didn't have the expected files in it.", new File[] { baseline, baseline1, nested }, nonRecursiveMonitor.baseline); + } + + @Test + public void testBaselineIncludesSelfInSelfDirectoryCase() throws Exception { + File baseline = new File(monitoredFolder, "baseline"); + File baseline1 = new File(monitoredFolder, "baseline1"); + File nested = new File(monitoredFolder, "nestedBaselineFolder"); + File nestedFile = new File(nested, "nestedBaselineFile"); + + // Set the mark to the beginning of the log, since the baseline will happen at the beginning but + // this test could run in any order + // This will reset the marks, too + server.resetLogOffsets(); + monitorSelfMonitor.scrapeLogsForBaseline(); + + assertFalse("The baseline should not be empty", monitorSelfMonitor.baseline.isEmpty()); + assertEqualsOrderless("The baseline didn't have the expected files in it.", new File[] { monitoredFolder, baseline, baseline1, nested, nestedFile }, + monitorSelfMonitor.baseline); + } + + @Mode(TestMode.FULL) + @Test + public void testBaselineIncludesSelfInSelfNonRecursiveDirectoryCase() throws Exception { + File baseline = new File(monitoredFolder, "baseline"); + File baseline1 = new File(monitoredFolder, "baseline1"); + File nested = new File(monitoredFolder, "nestedBaselineFolder"); + + nonRecursiveMonitorSelfMonitor.scrapeLogsForBaseline(); + + assertFalse("The baseline should not be empty", nonRecursiveMonitorSelfMonitor.baseline.isEmpty()); + assertEqualsOrderless("The baseline didn't have the expected files in it.", new File[] { monitoredFolder, baseline, baseline1, nested }, + nonRecursiveMonitorSelfMonitor.baseline); + } + + @Test + public void testBaselineIsEmptyForNonExistentFile() throws Exception { + nonexistentFileMonitor.scrapeLogsForBaseline(); + + assertEquals("A baseline should have been reported, and been empty.", 0, nonexistentFileMonitor.baseline.size()); + } + + @Test + public void testFileCreationIsNotified() throws Exception { + // Don't assume test ordering + if (monitoredFile.exists()) { + assertTrue(monitoredFile.delete()); + flushNotifications(fileMonitor); + } + createFile(monitoredFile); + + fileMonitor.scrapeLogsForChanges(); + + assertCreated(fileMonitor, monitoredFile); + } + + @Test + public void testFileModificationIsNotified() throws Exception { + + // Make the file to modify + if (!monitoredFile.exists()) { + createFile(monitoredFile); + fileMonitor.scrapeLogsForChanges(); + server.setMarkToEndOfLog(); + } + + appendSomething(monitoredFile); + + fileMonitor.scrapeLogsForChanges(); + assertModified(fileMonitor, monitoredFile); + } + + @Test + public void testFileCreationAndModificationIsNotifiedAsCreation() throws Exception { + + // Don't assume test ordering + if (monitoredFile.exists()) { + assertTrue(monitoredFile.delete()); + fileMonitor.scrapeLogsForChanges(); + server.setMarkToEndOfLog(); + } + + createFile(monitoredFile); + appendSomething(monitoredFile); + + fileMonitor.scrapeLogsForChanges(); + assertCreated(fileMonitor, monitoredFile); + } + + @Mode(TestMode.FULL) + @Test + public void testTimestampChanging() throws Exception { + // Make a file to delete (and make sure we noticed it) + if (!monitoredFile.exists()) { + createFile(monitoredFile); + fileMonitor.scrapeLogsForChanges(); + server.setMarkToEndOfLog(); + } + + // Make it a lot older (~30min) than it is (should still be considered modified) + monitoredFile.setLastModified(System.currentTimeMillis() - (30 * 60 * 1000)); + + fileMonitor.scrapeLogsForChanges(); + assertModified(fileMonitor, monitoredFile); + + } + + @Test + public void testFileDeletionIsNotified() throws Exception { + // Make a file to delete (and make sure we noticed it) + if (!monitoredFile.exists()) { + createFile(monitoredFile); + fileMonitor.scrapeLogsForChanges(); + server.setMarkToEndOfLog(); + } + + // Delete the file: it should be added to the 'deleted' list + assertTrue("File should be deleted on the filesystem", monitoredFile.delete()); + fileMonitor.scrapeLogsForChanges(); + assertDeleted(fileMonitor, monitoredFile); + + } + + /** + * An easy test, as a sanity baseline. + */ + @Test + public void testNoNotificationsHappenWhenNothingChanges() throws Exception { + // Do nothing :) + int count = recursiveMonitor.scrapeLogsForChanges(); + // Sanity check - we didn't see anything, right? + assertEquals("We didn't change any files so we shouldn't have had any monitoring activity.", 0, count); + assertNothingCreated(recursiveMonitor); + assertNothingDeleted(recursiveMonitor); + assertNothingModified(recursiveMonitor); + } + + @Mode(TestMode.FULL) + @Test + public void testFileInFolderCreationIsNotified() throws Exception { + File f = new File(monitoredFolder, "monitoredFile"); + createFile(f); + + recursiveMonitor.scrapeLogsForChanges(); + + assertCreated(recursiveMonitor, f); + } + + @Test + public void testMultipleFileCreationInFolderIsNotified() throws Exception { + File f1 = new File(monitoredFolder, "testMultipleFileCreationIsNotified1"); + File f2 = new File(monitoredFolder, "testMultipleFileCreationIsNotified2"); + createFile(f1); + createFile(f2); + + recursiveMonitor.scrapeLogsForChanges(); + + assertCreated(recursiveMonitor, f1, f2); + } + + @Test + public void testFileCreationInNestedFoldersIsNotifiedDependingOnRecursionSetting() throws Exception { + File folder = new File(monitoredFolder, "nestedFolder"); + createFolder(folder); + File f = new File(folder, "testFileCreationInNestedFoldersIsNotifiedDependingOnRecursionSetting"); + createFile(f); + + nonRecursiveMonitor.scrapeLogsForChanges(); + recursiveMonitor.scrapeLogsForChanges(); + + assertCreated(recursiveMonitor, folder, f); + // The non-recursive monitor should only see the folder, not its contents + assertCreated(nonRecursiveMonitor, folder); + + } + + @Mode(TestMode.FULL) + @Test + public void testFileInFolderModificationIsNotified() throws Exception { + + // Make a file to modify (and make sure we noticed it) + File f = new File(monitoredFolder, "testFileModificationIsNotified"); + createFile(f); + flushNotifications(recursiveMonitor); + + appendSomething(f); + + recursiveMonitor.scrapeLogsForChanges(); + assertModified(recursiveMonitor, f); + } + + @Test + public void testFileInNestedFolderModificationIsNotifiedDependingOnRecursionSettings() throws Exception { + + // Make a file to modify (and make sure we noticed it) + // Make a file to delete (and make sure we noticed it) + File folder = new File(monitoredFolder, "nestedFolderForModification"); + createFolder(folder); + File f = new File(folder, "testFileInNestedFolderModificationIsNotifiedDependingOnRecursionSettings"); + createFile(f); + assertTrue("We should find a created notification to flush", flushNotifications(recursiveMonitor) > 0); + flushNotifications(nonRecursiveMonitor); + + appendSomething(f); + + recursiveMonitor.scrapeLogsForChanges(); + nonRecursiveMonitor.scrapeLogsForChanges(); + + assertModified(recursiveMonitor, f); + assertNothingModified(nonRecursiveMonitor); + + } + + @Test + public void testFileInNestedFolderCreationIsNotNotifiedWhenFileDoesNotMatchFilter() throws Exception { + + File folder = new File(monitoredFolder, "nestedFolderForFilteredCreation"); + createFolder(folder); + + File f = new File(folder, "testFileInNestedFolderCreationIsNotNotifiedWhenItDoesNotMatchFilterexcludedfile"); + createFile(f); + + filterMonitor.scrapeLogsForChanges(); + assertNothingCreated(filterMonitor); + assertNothingDeleted(filterMonitor); + assertNothingModified(filterMonitor); + + // Now check other files do get past the filter + File excluded = new File(folder, "testFileInNestedFolderCreationIsNotNotifiedWhenItDoesNotMatchFilterStillexcluded"); + createFile(excluded); + File passed = new File(folder, "testFileInNestedFolderCreationIsNotNotifiedWhenItDoesNotMatchFilterincluded"); + createFile(passed); + + filterMonitor.scrapeLogsForChanges(); + assertCreated(filterMonitor, passed); + } + + @Mode(TestMode.FULL) + @Test + public void testFileInNestedFolderModficationIsNotNotifiedWhenFileDoesNotMatchFilter() throws Exception { + + File folder = new File(monitoredFolder, "nestedFolderForFilteredModification"); + createFolder(folder); + + File f = new File(folder, "testFileInNestedFolderModificationIsNotNotifiedWhenItDoesNotMatchFilterexcludedfile"); + createFile(f); + File excluded = new File(folder, "testFileInNestedFolderModificationIsNotNotifiedWhenItDoesNotMatchFilterStillexcluded"); + createFile(excluded); + File passed = new File(folder, "testFileInNestedFolderModificationIsNotNotifiedWhenItDoesNotMatchFilterincluded"); + createFile(passed); + flushNotifications(filterMonitor); + + appendSomething(f); + filterMonitor.scrapeLogsForChanges(); + assertNothingModified(filterMonitor); + assertNothingDeleted(filterMonitor); + assertNothingModified(filterMonitor); + + // Now check other files do get past the filter + appendSomething(excluded); + appendSomething(passed); + filterMonitor.scrapeLogsForChanges(); + assertModified(filterMonitor, passed); + } + + @Mode(TestMode.FULL) + @Test + public void testFileInNestedFolderDeletionIsNotNotifiedWhenFileDoesNotMatchFilter() throws Exception { + + File folder = new File(monitoredFolder, "nestedFolderForFilteredDeletion"); + createFolder(folder); + + File f = new File(folder, "testFileInNestedFolderDeletionIsNotNotifiedWhenItDoesNotMatchFilterexcludedfile"); + createFile(f); + File excluded = new File(folder, "testFileInNestedFolderDeletionIsNotNotifiedWhenItDoesNotMatchFilterStillexcluded"); + createFile(excluded); + File passed = new File(folder, "testFileInNestedFolderDeletionIsNotNotifiedWhenItDoesNotMatchFilterincluded"); + createFile(passed); + flushNotifications(filterMonitor); + + deleteFile(f); + filterMonitor.scrapeLogsForChanges(); + assertNothingDeleted(filterMonitor); + assertNothingDeleted(filterMonitor); + assertNothingDeleted(filterMonitor); + + // Now check other files do get past the filter + deleteFile(excluded); + deleteFile(passed); + filterMonitor.scrapeLogsForChanges(); + assertDeleted(filterMonitor, passed); + } + + @Mode(TestMode.FULL) + @Test + public void testFileInNestedFolderCreationIsNotNotifiedWhenNeitherFolderNorFileMatchFilter() throws Exception { + + File includedFolder = new File(monitoredFolder, "includedNestedFolderForFilteredCreation"); + File excludedFolder = new File(monitoredFolder, "excludedNestedFolderForFilteredCreation"); + createFolder(includedFolder); + createFolder(excludedFolder); + + filterMonitor.scrapeLogsForChanges(); + // We should get told about only one of the folders + assertCreated(filterMonitor, includedFolder); + + // Update any marks so we don't see that notification again + flushNotifications(filterMonitor); + + // We should still be monitoring in both folders + File iif = new File(includedFolder, "testFileInNestedFolderCreationIsNotNotifiedWhenFolderDoesNotMatchFilterincludedfile"); + createFile(iif); + File ief = new File(includedFolder, "testFileInNestedFolderCreationIsNotNotifiedWhenFolderDoesNotMatchFilterexcludedfile"); + createFile(ief); + + File eif = new File(excludedFolder, "testFileInNestedFolderCreationIsNotNotifiedWhenFolderDoesNotMatchFilterincludedfile"); + createFile(eif); + File eef = new File(excludedFolder, "testFileInNestedFolderCreationIsNotNotifiedWhenFolderDoesNotMatchFilterexcludedfile"); + createFile(eef); + + filterMonitor.scrapeLogsForChanges(); + // We should get told about everything whose base name matches the filter + assertCreated(filterMonitor, iif, eif); + } + + @Test + public void testFileInNestedFolderModificationIsNotNotifiedWhenNeitherFolderNorFileMatchFilter() throws Exception { + + File includedFolder = new File(monitoredFolder, "includedNestedFolderForFilteredModification"); + File excludedFolder = new File(monitoredFolder, "excludedNestedFolderForFilteredModification"); + createFolder(includedFolder); + createFolder(excludedFolder); + + // We should still be monitoring in both folders + File iif = new File(includedFolder, "testFileInNestedFolderModificationIsNotNotifiedWhenFolderDoesNotMatchFilterincludedfile"); + createFile(iif); + File ief = new File(includedFolder, "testFileInNestedFolderModificationIsNotNotifiedWhenFolderDoesNotMatchFilterexcludedfile"); + createFile(ief); + + File eif = new File(excludedFolder, "testFileInNestedFolderModificationIsNotNotifiedWhenFolderDoesNotMatchFilterincludedfile"); + createFile(eif); + File eef = new File(excludedFolder, "testFileInNestedFolderModificationIsNotNotifiedWhenFolderDoesNotMatchFilterexcludedfile"); + createFile(eef); + + flushNotifications(filterMonitor); + + appendSomething(iif); + appendSomething(ief); + appendSomething(eif); + appendSomething(eef); + + filterMonitor.scrapeLogsForChanges(); + // We should get told about everything whose base name matches the filter + assertModified(filterMonitor, iif, eif); + } + + @Mode(TestMode.FULL) + @Test + public void testFileInNestedFolderDeletionIsNotNotifiedWhenNeitherFolderNorFileMatchFilter() throws Exception { + + File includedFolder = new File(monitoredFolder, "includedNestedFolderForFilteredDeletion"); + File excludedFolder = new File(monitoredFolder, "excludedNestedFolderForFilteredDeletion"); + createFolder(includedFolder); + createFolder(excludedFolder); + + // We should still be monitoring in both folders + File iif = new File(includedFolder, "testFileInNestedFolderDeletionIsNotNotifiedWhenFolderDoesNotMatchFilterincludedfile"); + createFile(iif); + File ief = new File(includedFolder, "testFileInNestedFolderDeletionIsNotNotifiedWhenFolderDoesNotMatchFilterexcludedfile"); + createFile(ief); + + File eif = new File(excludedFolder, "testFileInNestedFolderDeletionIsNotNotifiedWhenFolderDoesNotMatchFilterincludedfile"); + createFile(eif); + File eef = new File(excludedFolder, "testFileInNestedFolderDeletionIsNotNotifiedWhenFolderDoesNotMatchFilterexcludedfile"); + createFile(eef); + + flushNotifications(filterMonitor); + + deleteFile(iif); + deleteFile(ief); + deleteFile(eif); + deleteFile(eef); + + filterMonitor.scrapeLogsForChanges(); + // We should get told about everything whose base name matches the filter + assertDeleted(filterMonitor, iif, eif); + } + + @Test + public void testFileInNestedFolderCreationIsNotNotifiedForDirectoryTypeFilter() throws Exception { + + File folder = new File(monitoredFolder, "testFileInNestedFolderCreationIsNotNotifiedForDirectoryTypeFilter"); + createFolder(folder); + flushNotifications(directoryfilterMonitor); + + File childFile = new File(folder, "childFile"); + createFile(childFile); + File childFolder = new File(folder, "childFolder"); + createFolder(childFolder); + + directoryfilterMonitor.scrapeLogsForChanges(); + // We should get told about every directory + assertCreated(directoryfilterMonitor, childFolder); + } + + @Mode(TestMode.FULL) + @Test + public void testFileInNestedFolderCreationIsNotNotifiedForFileTypeFilter() throws Exception { + + File folder = new File(monitoredFolder, "testFileInNestedFolderCreationIsNotNotifiedForFileTypeFilter"); + createFolder(folder); + + File childFile = new File(folder, "childFile"); + createFile(childFile); + File childFolder = new File(folder, "childFolder"); + createFolder(childFolder); + + filefilterMonitor.scrapeLogsForChanges(); + // We should get told about every directory + assertCreated(filefilterMonitor, childFile); + } + + @Test + public void testFileInNestedFolderModificationIsNotNotifiedForDirectoryTypeFilter() throws Exception { + + File folder = new File(monitoredFolder, "testFileInNestedFolderModificationIsNotNotifiedForDirectoryTypeFilter"); + createFolder(folder); + + File childFile = new File(folder, "childFile"); + createFile(childFile); + File childFolder = new File(folder, "childFolder"); + createFolder(childFolder); + + flushNotifications(directoryfilterMonitor); + + appendSomething(childFile); + + // We don't check timestamps on folders, so these notifications should have no effect + updateTimestamp(folder); + updateTimestamp(childFolder); + // We're including self, so we expect to get notified about the root folder, too + updateTimestamp(monitoredFolder); + + directoryfilterMonitor.scrapeLogsForChanges(); + // We should get told about every directory + assertNothingModified(directoryfilterMonitor); + } + + @Test + public void testFileInNestedFolderModificationIsNotifiedForFileTypeFilter() throws Exception { + + File folder = new File(monitoredFolder, "testFileInNestedFolderModificationIsNotNotifiedForFileTypeFilter"); + createFolder(folder); + + File childFile = new File(folder, "childFile"); + createFile(childFile); + File childFolder = new File(folder, "childFolder"); + createFolder(childFolder); + + flushNotifications(filefilterMonitor); + + appendSomething(childFile); + updateTimestamp(folder); + updateTimestamp(childFolder); + updateTimestamp(monitoredFolder); + + filefilterMonitor.scrapeLogsForChanges(); + // We should get told about every directory + assertModified(filefilterMonitor, childFile); + } + + @Mode(TestMode.FULL) + @Test + public void testFileInNestedFolderDeletionIsNotifiedForDirectoryTypeFilter() throws Exception { + + File folder = new File(monitoredFolder, "testFileInNestedFolderDeletionIsNotNotifiedForDirectoryTypeFilter"); + // Get rid of any clutter we don't know about in the monitored folder (we want to make sure we notice it being deleted) + deleteFile(monitoredFolder); + createFolder(monitoredFolder); + createFolder(folder); + + File childFile = new File(folder, "childFile"); + createFile(childFile); + File childFolder = new File(folder, "childFolder"); + createFolder(childFolder); + + flushNotifications(directoryfilterMonitor); + + deleteFile(childFile); + deleteFile(childFolder); + deleteFile(folder); + deleteFile(monitoredFolder); + + directoryfilterMonitor.scrapeLogsForChanges(); + // We should get told about every directory, but not the file + assertDeleted(directoryfilterMonitor, monitoredFolder, folder, childFolder); + } + + @Test + public void testFileInNestedFolderDeletionIsNotifiedForFileTypeFilter() throws Exception { + + File folder = new File(monitoredFolder, "testFileInNestedFolderDeletionIsNotifiedForFileTypeFilter"); + createFolder(folder); + + File childFile = new File(folder, "childFile"); + createFile(childFile); + File childFolder = new File(folder, "childFolder"); + createFolder(childFolder); + + flushNotifications(filefilterMonitor); + + // deleteFile(childFile); + deleteFile(childFolder); + deleteFile(folder); + + filefilterMonitor.scrapeLogsForChanges(); + // We should get told about every file (but no folders) + assertDeleted(filefilterMonitor, childFile); + } + + @Mode(TestMode.FULL) + @Test + public void testFileInFolderCreationAndModificationIsNotifiedAsCreation() throws Exception { + + File f = new File(monitoredFolder, "testFileInFolderCreationAndModificationIsNotifiedAsCreation"); + createFile(f); + appendSomething(f); + + recursiveMonitor.scrapeLogsForChanges(); + assertCreated(recursiveMonitor, f); + } + + @Mode(TestMode.FULL) + @Test + public void testFileInFolderCreationAndDeletionIsNotNotifiedAtAll() throws Exception { + + File f = new File(monitoredFolder, "testFileInFolderCreationAndDeletionIsNotifiedAsCreation"); + createFile(f); + deleteFile(f); + + recursiveMonitor.scrapeLogsForChanges(); + assertNothingCreated(recursiveMonitor); + assertNothingDeleted(recursiveMonitor); + assertNothingModified(recursiveMonitor); + } + + @Test + public void testFileInFolderCreationAndThenModificationAndThenDeletionIsNotNotifiedAtAll() throws Exception { + + File f = new File(monitoredFolder, "testFileInFolderCreationAndDeletionIsNotifiedAsCreation"); + createFile(f); + appendSomething(f); + deleteFile(f); + + recursiveMonitor.scrapeLogsForChanges(); + assertNothingCreated(recursiveMonitor); + assertNothingDeleted(recursiveMonitor); + assertNothingModified(recursiveMonitor); + } + + @Mode(TestMode.FULL) + @Test + public void testFileInFolderCreationIsNotNotifiedWhenItDoesNotMatchFilter() throws Exception { + + File f = new File(monitoredFolder, "testFileInFolderCreationIsNotNotifiedWhenItDoesNotMatchFilterexcludedfile"); + createFile(f); + + filterMonitor.scrapeLogsForChanges(); + assertNothingCreated(filterMonitor); + assertNothingDeleted(filterMonitor); + assertNothingModified(filterMonitor); + + // Now check other files do get past the filter + File excluded = new File(monitoredFolder, "testFileInFolderCreationIsNotNotifiedWhenItDoesNotMatchFilterStillexcluded"); + createFile(excluded); + File passed = new File(monitoredFolder, "testFileInFolderCreationIsNotNotifiedWhenItDoesNotMatchFilterincluded"); + createFile(passed); + + filterMonitor.scrapeLogsForChanges(); + assertCreated(filterMonitor, passed); + } + + @Test + public void testFileInFolderModficationIsNotNotifiedWhenItDoesNotMatchFilter() throws Exception { + + File f = new File(monitoredFolder, "testFileInFolderModificationIsNotNotifiedWhenItDoesNotMatchFilterexcludedfile"); + createFile(f); + File excluded = new File(monitoredFolder, "testFileInFolderModificationIsNotNotifiedWhenItDoesNotMatchFilterStillexcluded"); + createFile(excluded); + File passed = new File(monitoredFolder, "testFileInFolderModificationIsNotNotifiedWhenItDoesNotMatchFilterincluded"); + createFile(passed); + flushNotifications(filterMonitor); + + appendSomething(f); + filterMonitor.scrapeLogsForChanges(); + assertNothingModified(filterMonitor); + assertNothingDeleted(filterMonitor); + assertNothingModified(filterMonitor); + + // Now check other files do get past the filter + appendSomething(excluded); + appendSomething(passed); + filterMonitor.scrapeLogsForChanges(); + assertModified(filterMonitor, passed); + } + + @Mode(TestMode.FULL) + @Test + public void testFileInFolderDeletionIsNotNotifiedWhenItDoesNotMatchFilter() throws Exception { + + File f = new File(monitoredFolder, "testFileInFolderDeletionIsNotNotifiedWhenItDoesNotMatchFilterexcludedfile"); + createFile(f); + File excluded = new File(monitoredFolder, "testFileInFolderDeletionIsNotNotifiedWhenItDoesNotMatchFilterStillexcluded"); + createFile(excluded); + File passed = new File(monitoredFolder, "testFileInFolderDeletionIsNotNotifiedWhenItDoesNotMatchFilterincluded"); + createFile(passed); + flushNotifications(filterMonitor); + + deleteFile(f); + filterMonitor.scrapeLogsForChanges(); + assertNothingDeleted(filterMonitor); + assertNothingDeleted(filterMonitor); + assertNothingDeleted(filterMonitor); + + // Now check other files do get past the filter + deleteFile(excluded); + deleteFile(passed); + filterMonitor.scrapeLogsForChanges(); + assertDeleted(filterMonitor, passed); + } + + @Test + public void testMonitoringOfFileAsADirectoryDoesNotProduceNotifications() throws Exception { + + appendSomething(monitoredFile); + confusedFolderMonitor.scrapeLogsForChanges(); + assertNothingCreated(confusedFolderMonitor); + assertNothingModified(confusedFolderMonitor); + assertNothingDeleted(confusedFolderMonitor); + + flushNotifications(confusedFolderMonitor); + deleteFile(monitoredFile); + confusedFolderMonitor.scrapeLogsForChanges(); + assertNothingCreated(confusedFolderMonitor); + assertNothingModified(confusedFolderMonitor); + assertNothingDeleted(confusedFolderMonitor); + + flushNotifications(confusedFolderMonitor); + createFile(monitoredFile); + confusedFolderMonitor.scrapeLogsForChanges(); + assertNothingCreated(confusedFolderMonitor); + assertNothingModified(confusedFolderMonitor); + assertNothingDeleted(confusedFolderMonitor); + } + + @Test + public void testMonitoringOfDirectoryAsAFileDoesNotProduceNotifications() throws Exception { + + File file = new File(monitoredFolder, "testMonitoringOfDirectoryAsAFileDoesNotProduceNotifications"); + createFile(file); + confusedFileMonitor.scrapeLogsForChanges(); + assertNothingCreated(confusedFileMonitor); + assertNothingModified(confusedFileMonitor); + assertNothingDeleted(confusedFileMonitor); + + flushNotifications(confusedFileMonitor); + deleteFile(file); + confusedFileMonitor.scrapeLogsForChanges(); + assertNothingCreated(confusedFileMonitor); + assertNothingModified(confusedFileMonitor); + assertNothingDeleted(confusedFileMonitor); + + flushNotifications(confusedFileMonitor); + createFile(file); + confusedFileMonitor.scrapeLogsForChanges(); + assertNothingCreated(confusedFileMonitor); + assertNothingModified(confusedFileMonitor); + assertNothingDeleted(confusedFileMonitor); + } + + @Mode(TestMode.FULL) + @Test + public void testFileCreationIsNotifiedWhenMonitoredFileDoesNotInitiallyExist() throws Exception { + + // Don't assume test ordering + if (nonexistentFile.exists()) { + deleteFile(nonexistentFile); + flushNotifications(nonexistentFileMonitor); + } + createFile(nonexistentFile); + nonexistentFileMonitor.scrapeLogsForChanges(); + assertCreated(nonexistentFileMonitor, nonexistentFile); + } + + @Mode(TestMode.FULL) + @Test + public void testFileModificationIsNotifiedWhenMonitoredFileDoesNotInitiallyExist() throws Exception { + // Don't assume test ordering + if (!nonexistentFile.exists()) { + createFile(nonexistentFile); + flushNotifications(nonexistentFileMonitor); + } + + appendSomething(nonexistentFile); + nonexistentFileMonitor.scrapeLogsForChanges(); + assertModified(nonexistentFileMonitor, nonexistentFile); + } + + @Test + public void testFileDeletionIsNotifiedWhenMonitoredFileDoesNotInitiallyExist() throws Exception { + // Don't assume test ordering + if (!nonexistentFile.exists()) { + createFile(nonexistentFile); + flushNotifications(nonexistentFileMonitor); + } + deleteFile(nonexistentFile); + nonexistentFileMonitor.scrapeLogsForChanges(); + assertDeleted(nonexistentFileMonitor, nonexistentFile); + } + + @Test + public void testFolderCreationIsNotifiedWhenMonitoredFolderDoesNotInitiallyExist() throws Exception { + + // Don't assume test ordering + if (!nonexistentFolder.exists()) { + createFolder(nonexistentFolder); + flushNotifications(nonexistentFolderMonitor); + } + File file = new File(nonexistentFolder, "testFolderCreationIsNotifiedWhenMonitoredFolderDoesNotInitiallyExist"); + createFile(file); + nonexistentFolderMonitor.scrapeLogsForChanges(); + assertCreated(nonexistentFolderMonitor, file); + } + + @Mode(TestMode.FULL) + @Test + public void testFolderModificationIsNotifiedWhenMonitoredFolderDoesNotInitiallyExist() throws Exception { + // Don't assume test ordering + if (!nonexistentFolder.exists()) { + createFolder(nonexistentFolder); + flushNotifications(nonexistentFolderMonitor); + } + + File file = new File(nonexistentFolder, "testFolderModificationIsNotifiedWhenMonitoredFolderDoesNotInitiallyExist"); + createFile(file); + flushNotifications(nonexistentFolderMonitor); + + appendSomething(file); + nonexistentFolderMonitor.scrapeLogsForChanges(); + assertModified(nonexistentFolderMonitor, file); + } + + @Mode(TestMode.FULL) + @Test + public void testFolderDeletionIsNotifiedWhenMonitoredFolderDoesNotInitiallyExist() throws Exception { + // Don't assume test ordering + if (!nonexistentFolder.exists()) { + createFolder(nonexistentFolder); + flushNotifications(nonexistentFolderMonitor); + } + + File file = new File(nonexistentFolder, "testFolderDeletionIsNotifiedWhenMonitoredFolderDoesNotInitiallyExist"); + createFile(file); + flushNotifications(nonexistentFolderMonitor); + + deleteFile(file); + nonexistentFolderMonitor.scrapeLogsForChanges(); + assertDeleted(nonexistentFolderMonitor, file); + } + + @Test + public void testFileInFolderTimestampChanging() throws Exception { + // Make a file to delete (and make sure we noticed it) + File f = new File(monitoredFolder, "testFileInFolderTimestampChanging"); + createFile(f); + flushNotifications(recursiveMonitor); + + // Make it a lot older than it is (should still be considered modified) + updateTimestamp(f); + + recursiveMonitor.scrapeLogsForChanges(); + assertModified(recursiveMonitor, f); + + } + + @Test + public void testFileInFolderDeletionIsNotified() throws Exception { + // Make a file to delete (and make sure we noticed it) + File f = new File(monitoredFolder, "testFileInFolderDeletionIsNotified"); + createFile(f); + flushNotifications(recursiveMonitor); + + // Delete the file: it should be added to the 'deleted' list + assertTrue("File should be deleted on the filesystem", f.delete()); + recursiveMonitor.scrapeLogsForChanges(); + assertDeleted(recursiveMonitor, f); + + } + + @Test + public void testAllContentsAreIncludedForFileInFolderDeletion() throws Exception { + // Make a file to delete (and make sure we noticed it) + File folder = new File(monitoredFolder, "testFileInFolderDeletionIsNotified"); + createFolder(folder); + File f = new File(folder, "childFile"); + createFile(f); + flushNotifications(recursiveMonitor); + + // Delete the folder: it and its contents should be added to the 'deleted' list + deleteFile(folder); + recursiveMonitor.scrapeLogsForChanges(); + assertDeleted(recursiveMonitor, f, folder); + } + + @Mode(TestMode.FULL) + @Test + public void testFileInNestedFolderDeletionIsNotified() throws Exception { + // Make a file to delete (and make sure we noticed it) + File folder = new File(monitoredFolder, "nestedFolderForDeletion"); + createFolder(folder); + File f = new File(folder, "testFileInNestedFolderDeletionIsNotified"); + createFile(f); + flushNotifications(recursiveMonitor); + flushNotifications(nonRecursiveMonitor); + + // Delete the file: it should be added to the 'deleted' list + deleteFile(f); + recursiveMonitor.scrapeLogsForChanges(); + nonRecursiveMonitor.scrapeLogsForChanges(); + assertDeleted(recursiveMonitor, f); + assertNothingDeleted(nonRecursiveMonitor); + + } + + @Test + public void testFileInNestedFolderFolderDeletionIsNotified() throws Exception { + File bfolder = new File(monitoredFolder, "testFileInNestedFolderFolderDeletionIsNotified"); + // Get rid of any clutter we don't know about in the monitored folder (we want to make sure we notice it being deleted) + // But don't assume test ordering -- don't try to delete if it doesn't exist! + if (monitoredFolder.exists()) + deleteFile(monitoredFolder); + createFolder(monitoredFolder); + createFolder(bfolder); + + File bchildFile = new File(bfolder, "childFile"); + createFile(bchildFile); + File bchildFolder = new File(bfolder, "childFolder"); + createFolder(bchildFolder); + + flushNotifications(recursiveMonitor); + + deleteFile(bchildFile); + deleteFile(bchildFolder); + deleteFile(bfolder); + deleteFile(monitoredFolder); + + recursiveMonitor.scrapeLogsForChanges(); + // We should get told about every directory + assertDeleted(recursiveMonitor, bfolder, bchildFolder, bchildFile); + + // Make a file to delete (and make sure we noticed it) + File folder = new File(monitoredFolder, "testFileInNestedFolderFolderDeletionIsNotified"); + createFolder(folder); + File childFolder = new File(folder, "testFileInNestedFolderDeletionIsNotified"); + createFile(childFolder); + flushNotifications(recursiveMonitor); + flushNotifications(nonRecursiveMonitor); + + // Delete the folder: it and its contents should be added to the 'deleted' list + deleteFile(childFolder); + deleteFile(folder); + recursiveMonitor.scrapeLogsForChanges(); + nonRecursiveMonitor.scrapeLogsForChanges(); + assertDeleted(recursiveMonitor, folder, childFolder); + assertDeleted(nonRecursiveMonitor, folder); + + } + + @Test + public void testCreationOfMonitoredFolderIsNotifiedOnlyWhenIgnoreSelfIsTrue() throws Exception { + // Get rid of anything in the monitored folder so we can make it again + deleteFile(monitoredFolder); + flushNotifications(recursiveMonitor); + flushNotifications(monitorSelfMonitor); + + monitoredFolder.mkdirs(); + recursiveMonitor.scrapeLogsForChanges(); + monitorSelfMonitor.scrapeLogsForChanges(); + assertNothingCreated(recursiveMonitor); + assertCreated(monitorSelfMonitor, monitoredFolder); + + // Now wait and make sure we don't get told again about the deleted file + flushNotifications(recursiveMonitor); + flushNotifications(monitorSelfMonitor); + recursiveMonitor.scrapeLogsForChanges(); + monitorSelfMonitor.scrapeLogsForChanges(); + assertNothingCreated(recursiveMonitor); + assertNothingCreated("After an initial (correct) creation report, ", monitorSelfMonitor); + + } + + @Mode(TestMode.FULL) + @Test + public void testDeletionOfMonitoredFolderIsNotifiedOnlyWhenIgnoreSelfIsTrue() throws Exception { + // Get rid of anything in the monitored folder so we can safely delete it (by deleting it) + deleteFile(monitoredFolder); + // Now make the actual folder back (so when we delete it we know what notification to expect) + monitoredFolder.mkdirs(); + flushNotifications(recursiveMonitor); + flushNotifications(monitorSelfMonitor); + + deleteFile(monitoredFolder); + // Delete the whole folder: it should be added to the 'deleted' list + recursiveMonitor.scrapeLogsForChanges(); + monitorSelfMonitor.scrapeLogsForChanges(); + assertNothingDeleted(recursiveMonitor); + assertDeleted(monitorSelfMonitor, monitoredFolder); + + // Now wait and make sure we don't get told again about the deleted file + flushNotifications(recursiveMonitor); + flushNotifications(monitorSelfMonitor); + recursiveMonitor.scrapeLogsForChanges(); + monitorSelfMonitor.scrapeLogsForChanges(); + assertNothingDeleted(recursiveMonitor); + assertNothingDeleted("After an initial (correct) deletion report, ", monitorSelfMonitor); + + } +} diff --git a/dev/com.ibm.ws.kernel.filemonitor_fat/fat/src/com/ibm/ws/kernel/filemonitor/fat/FileNotificationMBeanTest.java b/dev/com.ibm.ws.kernel.filemonitor_fat/fat/src/com/ibm/ws/kernel/filemonitor/fat/FileNotificationMBeanTest.java new file mode 100755 index 00000000000..6a2f2827273 --- /dev/null +++ b/dev/com.ibm.ws.kernel.filemonitor_fat/fat/src/com/ibm/ws/kernel/filemonitor/fat/FileNotificationMBeanTest.java @@ -0,0 +1,778 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * + * WLP Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.kernel.filemonitor.fat; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.UndeclaredThrowableException; +import java.net.ConnectException; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.cert.X509Certificate; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Collection; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; + +import javax.management.JMX; +import javax.management.MBeanServerConnection; +import javax.management.MalformedObjectNameException; +import javax.management.ObjectName; +import javax.management.remote.JMXConnector; +import javax.management.remote.JMXConnectorFactory; +import javax.management.remote.JMXServiceURL; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.ibm.websphere.filemonitor.FileNotificationMBean; +import com.ibm.ws.jmx.connector.client.rest.ClientProvider; +import componenttest.custom.junit.runner.Mode; +import componenttest.custom.junit.runner.Mode.TestMode; + +/** + * + */ +public class FileNotificationMBeanTest extends AbstractNotificationTest { + + /** Used for sanity checks of changes in the timed scan case */ + private static final MonitorReader recursiveMonitor = new MonitorReader("-RECURSIVETESTMONITOROUTPUT-", "recursive folder monitor"); + private static final MonitorReader manualMonitor = new MonitorReader("-MANUALMONITOROUTPUT-", "externally triggered folder monitor"); + + private static JMXConnector jmxConnector; + private static FileNotificationMBean mbean; + + /** + * JUnit guarantees that this gets run after the static set up in the superclass (as long as the names are different). + */ + @BeforeClass + public static void jmxSetUp() throws Exception { + + // Wait for the JMX server to be started + assertNotNull("The application 'IBMJMXConnectorREST' did not report it was started", + server.waitForStringInLog("CWWKT0016I.*IBMJMXConnectorREST")); + // Wait for secure port to be ready + assertNotNull("SSL port is not ready", + server.waitForStringInLog("CWWKO0219I.*ssl")); + assertNotNull("The server is not ready to run a smarter planet", + server.waitForStringInLog("CWWKF0011I")); + assertNotNull("The security service is not ready", + server.waitForStringInLog("CWWKS0008I")); + + trustEverything(); + + Map fileTransferConfig = new HashMap(); + fileTransferConfig.put("jmx.remote.protocol.provider.pkgs", "com.ibm.ws.jmx.connector.client"); + fileTransferConfig.put(JMXConnector.CREDENTIALS, new String[] { "theUser", "thePassword" }); + fileTransferConfig.put(ClientProvider.DISABLE_HOSTNAME_VERIFICATION, true); + fileTransferConfig.put(ClientProvider.READ_TIMEOUT, 2 * 60 * 1000); + + JMXServiceURL jmxServiceUrl = new JMXServiceURL("REST", server.getHostname(), server + .getHttpDefaultSecurePort(), "/IBMJMXConnectorREST"); + long connectTime = System.currentTimeMillis(); + try { + jmxConnector = JMXConnectorFactory.connect(jmxServiceUrl, fileTransferConfig); + + MBeanServerConnection mbeanConn = jmxConnector.getMBeanServerConnection(); + final ObjectName name = new ObjectName(com.ibm.ws.kernel.filemonitor.FileNotificationMBean.INSTANCE_NAME); + mbean = JMX.newMBeanProxy(mbeanConn, name, + FileNotificationMBean.class); + + assertNotNull("We should have got access to the FileNotificationMBean", mbean); + } catch (ConnectException e) { + DateFormat formatter = new SimpleDateFormat("dd/MMM/yyyy HH:mm:ss:SSS z"); + String timestamp = formatter.format(new Date(connectTime)); + fail("Could not get a connection to the JMX server using URL " + jmxServiceUrl + ".\n Tried at " + timestamp + ".\n The exception was " + e); + } + + } + + /** + * Adjusts our SSL code so that it doesn't complain when we connect to servers using untrusted + * certificates. + * + * @throws NoSuchAlgorithmException + * @throws KeyManagementException + */ + private static void trustEverything() throws NoSuchAlgorithmException, KeyManagementException { + TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() { + @Override + public X509Certificate[] getAcceptedIssuers() { + return null; + } + + @Override + public void checkClientTrusted(X509Certificate[] certs, String authType) {} + + @Override + public void checkServerTrusted(X509Certificate[] certs, String authType) {} + } }; + + SSLContext sc = SSLContext.getInstance("SSL"); + sc.init(null, trustAllCerts, new SecureRandom()); + HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); + + } + + @AfterClass + public static void classTearDown() throws MalformedObjectNameException, NullPointerException, IOException { + if (jmxConnector != null) { + jmxConnector.close(); + } + } + + @Before + public void setUp() throws Exception { + + } + + @After + public void tearDown() throws Exception { + // Clear up after any tests which may have deleted the monitored folder + if (!monitoredFolder.exists()) { + monitoredFolder.mkdirs(); + // Nothing we're using is monitoring the folder itself + } + + // Get rid of any dangling notifications from tests + flushNotifications(recursiveMonitor); + flushNotifications(); + + } + + @Test + public void testFileInFolderCreationIsNotNotifiedWithoutMBeanRequest() throws Throwable { + + File f = new File(monitoredFolder, "testFileInFolderModificationIsNotNotifiedWithoutMBeanRequest"); + createFile(f); + + manualMonitor.scrapeLogsForChanges(); + // We shouldn't be told about anything, since we haven't triggered the scan + assertNothingCreated(manualMonitor); + assertNothingDeleted(manualMonitor); + assertNothingModified(manualMonitor); + + // Sanity check - the recursive monitor should have noticed + HashSet created = new HashSet(); + created.add(f); + recursiveMonitor.scrapeLogsForExpectedChanges(created, null, null); + assertCreated(recursiveMonitor, f); + } + + @Test + public void testFileInFolderCreationIsNotNotifiedForMBeanRequestOnUnrelatedFile() throws Throwable { + + File f = new File(monitoredFolder, "testFileInFolderCreationIsNotNotifiedForMBeanRequestOnUnrelatedFile"); + createFile(f); + + Collection fileSet = new HashSet(); + fileSet.add(f.getAbsolutePath()); + + Collection wrongFileSet = new HashSet(); + wrongFileSet.add(monitoredFile.getAbsolutePath()); + + try { + // Notify changes, but for the wrong file + mbean.notifyFileChanges(wrongFileSet, null, null); + manualMonitor.scrapeLogsForChanges(); + // We shouldn't be told about anything since we passed through the wrong file + assertNothingCreated(manualMonitor); + assertNothingDeleted(manualMonitor); + assertNothingModified(manualMonitor); + } catch (UndeclaredThrowableException e) { + // Unwrap the exception (but rethrow, so we get a nice stack trace in the failure report) + throw e.getCause(); + } + } + + @Test + public void testFileInFolderCreationIsNotNotifiedForMBeanRequestOfWrongChangeType() throws Throwable { + + File f = new File(monitoredFolder, "testFileInFolderCreationIsNotNotifiedForMBeanRequestOfWrongChangeType"); + createFile(f); + + Collection fileSet = new HashSet(); + fileSet.add(f.getAbsolutePath()); + + Collection wrongFileSet = new HashSet(); + wrongFileSet.add(monitoredFile.getAbsolutePath()); + + try { + // Now request a notification, but of modification, so the wrong type + mbean.notifyFileChanges(null, fileSet, null); + manualMonitor.scrapeLogsForChanges(); + // We shouldn't be told about anything, since we have the right file but the wrong type + assertNothingCreated(manualMonitor); + assertNothingDeleted(manualMonitor); + assertNothingModified(manualMonitor); + + } catch (UndeclaredThrowableException e) { + // Unwrap the exception (but rethrow, so we get a nice stack trace in the failure report) + throw e.getCause(); + } + } + + /** + * In the externally triggered case, we need to be specific about what we think might have changed. + * If we have a recursive monitor, and we pass the parent folder as the parameter on the mbean call, + * we won't get told about things inside that folder which have changed. + */ + @Mode(TestMode.FULL) + @Test + public void testFileInFolderModificationIsNotNotifiedWhenWePassBackTheParentFolder() throws Throwable { + + File f = new File(monitoredFolder, "testFileInFolderModificationIsNotNotifiedWhenWePassBackTheParentFolder"); + createFile(f); + + Collection folderSet = new HashSet(); + folderSet.add(monitoredFolder.getAbsolutePath()); + Collection created = new HashSet(); + created.add(monitoredFolder); + + try { + mbean.notifyFileChanges(folderSet, null, null); + manualMonitor.scrapeLogsForExpectedChanges(created, null, null); + assertNothingCreated(manualMonitor); + assertNothingDeleted(manualMonitor); + assertNothingModified(manualMonitor); + } catch (UndeclaredThrowableException e) { + // Unwrap the exception (but rethrow, so we get a nice stack trace in the failure report) + throw e.getCause(); + } + } + + @Test + public void testFileInFolderCreationIsNotifiedAfterRequest() throws Throwable { + + File f = new File(monitoredFolder, "testFileInFolderCreationIsNotifiedAfterRequest"); + createFile(f); + + // Sanity check - the recursive monitor should have noticed + recursiveMonitor.scrapeLogsForChanges(); + assertCreated(recursiveMonitor, f); + + Collection fileSet = new HashSet(); + fileSet.add(f.getAbsolutePath()); + Collection created = new HashSet(); + created.add(f); + + try { + // Ok, let's actually get our notification now + mbean.notifyFileChanges(fileSet, null, null); + //manualMonitor.scrapeLogsForChanges(); + manualMonitor.scrapeLogsForExpectedChanges(created, null, null); + assertCreated(manualMonitor, f); + } catch (UndeclaredThrowableException e) { + // Unwrap the exception (but rethrow, so we get a nice stack trace in the failure report) + throw e.getCause(); + } + } + + @Test + public void testFileInFolderModificationIsNotifiedAfterRequest() throws Throwable { + + File f = new File(monitoredFolder, "testFileInFolderModificationIsNotifiedAfterRequest"); + createFile(f); + + Collection fileSet = new HashSet(); + fileSet.add(f.getAbsolutePath()); + Collection changed = new HashSet(); + changed.add(f); + + try { + // Setup for test + mbean.notifyFileChanges(fileSet, null, null); // Need to let them know we created a file that we are going to modify later + manualMonitor.scrapeLogsForExpectedChanges(changed, null, null); + assertCreated(manualMonitor, f); + flushNotifications(recursiveMonitor); // Need to clear recursive monitor + + //////// Actual test + // Now let's make a change and get that notification + appendSomething(f); + mbean.notifyFileChanges(null, fileSet, null); + manualMonitor.scrapeLogsForExpectedChanges(null, changed, null); + assertModified(manualMonitor, f); + } catch (UndeclaredThrowableException e) { + // Unwrap the exception (but rethrow, so we get a nice stack trace in the failure report) + throw e.getCause(); + } + } + + @Test + public void testFileInFolderDeletionIsNotifiedAfterRequest() throws Throwable { + + File f = new File(monitoredFolder, "testFileInFolderDeletionIsNotifiedAfterRequest"); + createFile(f); + + Collection fileSet = new HashSet(); + fileSet.add(f.getAbsolutePath()); + Collection deleted = new HashSet(); + deleted.add(f); + + try { + // Setup for test + mbean.notifyFileChanges(fileSet, null, null); // Need to let them know we created a file that we are going to modify later + manualMonitor.scrapeLogsForExpectedChanges(deleted, null, null); + assertCreated(manualMonitor, f); + flushNotifications(recursiveMonitor); // Need to clear recursive monitor + + // Now let's make a change and get that notification + deleteFile(f); + mbean.notifyFileChanges(null, null, fileSet); + manualMonitor.scrapeLogsForExpectedChanges(null, null, deleted); + assertDeleted(manualMonitor, f); + } catch (UndeclaredThrowableException e) { + // Unwrap the exception (but rethrow, so we get a nice stack trace in the failure report) + throw e.getCause(); + } + } + + @Test + public void testFileInNestedFolderCreationIsNotifiedAfterRequestAboutFolder() throws Throwable { + + File folder = new File(monitoredFolder, "testFileInNestedFolderCreationIsNotifiedAfterRequestAboutFolder"); + createFolder(folder); + + File f = new File(folder, "childFile"); + createFile(f); + + // Sanity check - the recursive monitor should have noticed + recursiveMonitor.scrapeLogsForChanges(); + assertCreated(recursiveMonitor, f, folder); + + Collection fileSet = new HashSet(); + fileSet.add(folder.getAbsolutePath()); + Collection created = new HashSet(); + created.add(folder); + + try { + // Ok, let's actually get our notification now + mbean.notifyFileChanges(fileSet, null, null); + manualMonitor.scrapeLogsForExpectedChanges(created, null, null); + assertCreated(manualMonitor, folder); + } catch (UndeclaredThrowableException e) { + // Unwrap the exception (but rethrow, so we get a nice stack trace in the failure report) + throw e.getCause(); + } + } + + @Test + public void testFileInNestedFolderModificationIsNotNotifiedAfterRequestAboutFolder() throws Throwable { + + File folder = new File(monitoredFolder, "testFileInNestedFolderModificationIsNotifiedAfterRequestAboutFolder"); + createFolder(folder); + + File f = new File(folder, "childFile"); + createFile(f); + + // Sanity check - the recursive monitor should have noticed + recursiveMonitor.scrapeLogsForChanges(); + assertCreated(recursiveMonitor, f, folder); + + Collection fileSet = new HashSet(); + fileSet.add(folder.getAbsolutePath()); + + try { + flushNotifications(); + + // Now let's make a change and get that notification + appendSomething(f); + updateTimestamp(folder); + mbean.notifyFileChanges(null, fileSet, null); + manualMonitor.scrapeLogsForChanges(); + // We could only get told about the folder modification, and we don't tend to generate those + // events except for delete-create cycles + assertNothingModified(manualMonitor); + } catch (UndeclaredThrowableException e) { + // Unwrap the exception (but rethrow, so we get a nice stack trace in the failure report) + throw e.getCause(); + } + } + + @Test + public void testFileInNestedFolderDeletionIsNotifiedAfterRequestAboutFolder() throws Throwable { + + File folder = new File(monitoredFolder, "testFileInNestedFolderDeletionIsNotifiedAfterRequestAboutFolder"); + + createFolder(folder); + Collection fileSet = new HashSet(); + Collection files = new HashSet(); + fileSet.add(folder.getAbsolutePath()); + files.add(folder); + mbean.notifyFileChanges(fileSet, null, null); // Need to let them know we created a file that we are going to modify later + manualMonitor.scrapeLogsForExpectedChanges(files, null, null); + assertCreated(manualMonitor, folder); + + try { + + // Setup for test + // Create folder + mbean.notifyFileChanges(fileSet, null, null); // Need to let them know we created a file that we are going to modify later + manualMonitor.scrapeLogsForExpectedChanges(files, null, null); + assertCreated(manualMonitor, folder); + flushNotifications(recursiveMonitor); // Need to clear recursive monitor + // Create nested file + File f = new File(folder, "childFile"); + createFile(f); + Collection fileSet2 = new HashSet(); + fileSet2.add(f.getAbsolutePath()); + Collection created = new HashSet(); + created.add(f); + mbean.notifyFileChanges(fileSet2, null, null); // Need to let them know we created a file that we are going to modify later + manualMonitor.scrapeLogsForExpectedChanges(created, null, null); + assertCreated(manualMonitor, f); + flushNotifications(recursiveMonitor); // Need to clear recursive monitor + + // Now let's make a change and get that notification + deleteFile(folder); + mbean.notifyFileChanges(null, null, fileSet); + manualMonitor.scrapeLogsForExpectedChanges(null, null, created); + assertDeleted(manualMonitor, folder); + } catch (UndeclaredThrowableException e) { + // Unwrap the exception (but rethrow, so we get a nice stack trace in the failure report) + throw e.getCause(); + } + } + + @Test + public void testFileInNestedFolderCreationIsNotifiedAfterRequestAboutFile() throws Throwable { + + File folder = new File(monitoredFolder, "testFileInNestedFolderCreationIsNotifiedAfterRequestAboutFile"); + createFolder(folder); + + File f = new File(folder, "childFile"); + createFile(f); + + // Sanity check - the recursive monitor should have noticed + recursiveMonitor.scrapeLogsForChanges(); + assertCreated(recursiveMonitor, f, folder); + + Collection fileSet = new HashSet(); + fileSet.add(f.getAbsolutePath()); + Collection created = new HashSet(); + created.add(f); + created.add(folder); + + try { + // Ok, let's actually get our notification now + mbean.notifyFileChanges(fileSet, null, null); + manualMonitor.scrapeLogsForExpectedChanges(created, null, null); + // defect 87702 requires that we generate events for parent directories of paths that we found files for + // even if the external scan has not requested them. + assertCreated(manualMonitor, f, folder); + } catch (UndeclaredThrowableException e) { + // Unwrap the exception (but rethrow, so we get a nice stack trace in the failure report) + throw e.getCause(); + } + } + + @Test + public void testFileInNestedFolderModificationIsNotifiedAfterRequestAboutFile() throws Throwable { + + File folder = new File(monitoredFolder, "testFileInNestedFolderModificationIsNotifiedAfterRequestAboutFile"); + createFolder(folder); + Collection fileSet = new HashSet(); + Collection files = new HashSet(); + fileSet.add(folder.getAbsolutePath()); + files.add(folder); + mbean.notifyFileChanges(fileSet, null, null); // Need to let them know we created a file that we are going to modify later + manualMonitor.scrapeLogsForExpectedChanges(files, null, null); + assertCreated(manualMonitor, folder); + + try { + + // Setup for test + // Create folder + mbean.notifyFileChanges(fileSet, null, null); // Need to let them know we created a file that we are going to modify later + manualMonitor.scrapeLogsForExpectedChanges(files, null, null); + assertCreated(manualMonitor, folder); + flushNotifications(recursiveMonitor); // Need to clear recursive monitor + // Create nested file + File f = new File(folder, "childFile"); + createFile(f); + Collection fileSet2 = new HashSet(); + fileSet2.add(f.getAbsolutePath()); + Collection created = new HashSet(); + created.add(f); + mbean.notifyFileChanges(fileSet2, null, null); // Need to let them know we created a file that we are going to modify later + manualMonitor.scrapeLogsForExpectedChanges(created, null, null); + assertCreated(manualMonitor, f); + flushNotifications(recursiveMonitor); // Need to clear recursive monitor + + // Actual test + // Now let's make a change and get that notification + appendSomething(f); + updateTimestamp(folder); + mbean.notifyFileChanges(null, fileSet2, null); + manualMonitor.scrapeLogsForChanges(); + // defect 87702 requires that we generate events for parent directories of paths that we found files for + // even if the external scan has not requested them, but only for deletion and creation, not modification + assertModified(manualMonitor, f); + } catch (UndeclaredThrowableException e) { + // Unwrap the exception (but rethrow, so we get a nice stack trace in the failure report) + throw e.getCause(); + } + } + + @Test + public void testFileInNestedFolderDeletionIsNotifiedAfterRequestAboutFile() throws Throwable { + + File folder = new File(monitoredFolder, "testFileInNestedFolderDeletionIsNotifiedAfterRequestAboutFile"); + createFolder(folder); + Collection fileSet = new HashSet(); + Collection files = new HashSet(); + fileSet.add(folder.getAbsolutePath()); + files.add(folder); + mbean.notifyFileChanges(fileSet, null, null); // Need to let them know we created a file that we are going to modify later + manualMonitor.scrapeLogsForExpectedChanges(files, null, null); + assertCreated(manualMonitor, folder); + + try { + + // Setup for test + // Create folder + mbean.notifyFileChanges(fileSet, null, null); // Need to let them know we created a file that we are going to modify later + manualMonitor.scrapeLogsForExpectedChanges(files, null, null); + assertCreated(manualMonitor, folder); + flushNotifications(); + // Create nested file + File f = new File(folder, "childFile"); + createFile(f); + + // We're only interested in changes to the file, not the folder + // This file: + Collection fileSet2 = new HashSet(); + fileSet2.add(f.getAbsolutePath()); + Collection created = new HashSet(); + created.add(f); + mbean.notifyFileChanges(fileSet2, null, null); // Need to let them know we created a file that we are going to modify later + manualMonitor.scrapeLogsForExpectedChanges(created, null, null); + assertCreated(manualMonitor, f); + flushNotifications(); + + // Now let's make a change and get that notification + deleteFile(folder); + mbean.notifyFileChanges(null, null, fileSet2); + manualMonitor.scrapeLogsForChanges(); + // defect 87702 requires that we generate events for parent directories of paths that we found files for + // even if the external scan has not requested them. + assertDeleted(manualMonitor, f, folder); + } catch (UndeclaredThrowableException e) { + // Unwrap the exception (but rethrow, so we get a nice stack trace in the failure report) + throw e.getCause(); + } + } + + private void flushNotifications() throws Exception { + flushNotifications(manualMonitor); + } + + /* + * The FileNotificationMbean method for notifyFileChanges will now + * cache unrequested/unnotified file changes, so that they can be requested on + * later calls. However, this means that certain unrequested options + * can become invalid based on later filesystem changes. + */ + + // State change loop to track the status of changed files. + // D = Delete, C = Create, M = modified, - = not in any list, X = not possible + // Example, "CM = C" would mean create followed by a modify would + // result in the file being in the create list + // C = C + // D = D + // M = M + // CC = X + // CD = - // testPersistedNotificationCaseCD() + // CM = C // testPersistedNotificationCaseCM() + // DC = M // testPersistedNotificationCaseCM() + // DD = X + // DM = X + // MC = X + // MD = D // testPersistedNotificationCaseMD() + // MM = M + + @Test + public void testPersistedNotificationCaseCD() throws Throwable { + + File folder = new File(monitoredFolder, "testPersistedNotificationCaseCD"); + + try { + + createFolder(folder); + File f = new File(folder, "childFile1"); + createFile(f); + + Collection fileSet = new HashSet(); + fileSet.add(f.getAbsolutePath()); + Collection created = new HashSet(); + created.add(f); + created.add(folder); + + mbean.notifyFileChanges(null, null, null); // Does not notify of a new file create + assertNothingChanged(manualMonitor); + deleteFile(folder); // Now remove this new file from the filesystem + mbean.notifyFileChanges(fileSet, null, null); // Now ask to create the file, but its gone + manualMonitor.scrapeLogsForChanges(); + assertNothingChanged(manualMonitor); + + } catch (UndeclaredThrowableException e) { + // Unwrap the exception (but rethrow, so we get a nice stack trace in the failure report) + throw e.getCause(); + } + } + + @Test + public void testPersistedNotificationCaseCM() throws Throwable { + + File folder = new File(monitoredFolder, "testPersistedNotificationCaseCM"); + + try { + + createFolder(folder); + File f = new File(folder, "childFile1"); + createFile(f); + Collection fileSet = new HashSet(); + fileSet.add(f.getAbsolutePath()); + Collection created = new HashSet(); + created.add(f); + created.add(folder); + mbean.notifyFileChanges(null, null, null); // Does not notify of a new file create + manualMonitor.scrapeLogsForChanges(); + assertNothingChanged(manualMonitor); + appendSomething(f); // Modify this new file + mbean.notifyFileChanges(null, fileSet, null); // Notify of a modify, but we didn't request create yet + manualMonitor.scrapeLogsForChanges(); + assertNothingChanged(manualMonitor); + mbean.notifyFileChanges(fileSet, null, null); // Notify of a create now, this is valid + manualMonitor.scrapeLogsForExpectedChanges(created, null, null); + assertCreated(manualMonitor, folder, f); // Should be shown as created now. + + } catch (UndeclaredThrowableException e) { + // Unwrap the exception (but rethrow, so we get a nice stack trace in the failure report) + throw e.getCause(); + } + } + + @Mode(TestMode.FULL) + @Test + public void testPersistedNotificationCaseMD() throws Throwable { + + File folder = new File(monitoredFolder, "testPersistedNotificationCaseMD"); + + try { + + createFolder(folder); + File f = new File(folder, "childFile1"); + createFile(f); + Collection fileSet = new HashSet(); + fileSet.add(f.getAbsolutePath()); + Collection created = new HashSet(); + created.add(f); + created.add(folder); + mbean.notifyFileChanges(fileSet, null, null); // Create a new file + manualMonitor.scrapeLogsForExpectedChanges(created, null, null); + assertCreated(manualMonitor, folder, f); // Should be shown as created now. + flushNotifications(); + appendSomething(f); // Modify this new file + mbean.notifyFileChanges(null, null, null); // Don't notify of the modify + manualMonitor.scrapeLogsForChanges(); + assertNothingChanged(manualMonitor); + flushNotifications(); + deleteFile(f); // Remove the file that has a pending create being stored in monitorholder + mbean.notifyFileChanges(fileSet, null, null); // Now try to notify of a create + manualMonitor.scrapeLogsForChanges(); + assertNothingChanged(manualMonitor); // The create is no longer valid, so nothing should change + mbean.notifyFileChanges(null, null, fileSet); // Now ask for the delete + manualMonitor.scrapeLogsForExpectedChanges(null, null, created); + assertDeleted(manualMonitor, f); + + } catch (UndeclaredThrowableException e) { + // Unwrap the exception (but rethrow, so we get a nice stack trace in the failure report) + throw e.getCause(); + } + } + + @Mode(TestMode.FULL) + @Test + public void testPersistedNotificationCaseDC() throws Throwable { + + File folder = new File(monitoredFolder, "testPersistedNotificationCaseDC"); + + try { + + createFolder(folder); + File f = new File(folder, "childFile1"); + createFile(f); + // Sanity check - the recursive monitor should have noticed + recursiveMonitor.scrapeLogsForChanges(); + assertCreated(recursiveMonitor, f, folder); + Collection fileSet = new HashSet(); + fileSet.add(f.getAbsolutePath()); + Collection created = new HashSet(); + created.add(f); + created.add(folder); + mbean.notifyFileChanges(fileSet, null, null); // Create a new file + manualMonitor.scrapeLogsForExpectedChanges(created, null, null); + assertCreated(manualMonitor, folder, f); // Should be shown as created now. + flushNotifications(); + deleteFile(f); // Remove the file that has a pending create being stored in monitorholder + mbean.notifyFileChanges(null, null, null); // Don't notify of the delete + manualMonitor.scrapeLogsForChanges(); + assertNothingChanged(manualMonitor); + flushNotifications(); + createFile(f); // Now recreate this file on the filesystem again + // Now try to notify of a create, but the only valid option + // is a modify, because we never notified of a delete + mbean.notifyFileChanges(fileSet, null, null); + manualMonitor.scrapeLogsForChanges(); + assertNothingChanged(manualMonitor); // Nothing should have changed + // Let's ask for a delete too, this was once a valid option + mbean.notifyFileChanges(null, null, fileSet); + manualMonitor.scrapeLogsForChanges(); + assertNothingChanged(manualMonitor); + flushNotifications(); + // Now notify for a modify, this is the only valid option + mbean.notifyFileChanges(null, fileSet, null); + manualMonitor.scrapeLogsForExpectedChanges(null, created, null); + assertModified(manualMonitor, f); + + } catch (UndeclaredThrowableException e) { + // Unwrap the exception (but rethrow, so we get a nice stack trace in the failure report) + throw e.getCause(); + } + } + + /** + * @param manualMonitor + */ + private void assertNothingChanged(MonitorReader manualMonitor) { + assertNothingModified(manualMonitor); + assertNothingCreated(manualMonitor); + assertNothingDeleted(manualMonitor); + } + +} \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.filemonitor_fat/fat/src/com/ibm/ws/kernel/filemonitor/fat/MonitorReader.java b/dev/com.ibm.ws.kernel.filemonitor_fat/fat/src/com/ibm/ws/kernel/filemonitor/fat/MonitorReader.java new file mode 100755 index 00000000000..b8836c047e0 --- /dev/null +++ b/dev/com.ibm.ws.kernel.filemonitor_fat/fat/src/com/ibm/ws/kernel/filemonitor/fat/MonitorReader.java @@ -0,0 +1,223 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.kernel.filemonitor.fat; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +class MonitorReader { + /** + * The interval on the monitors is 150ms. Allow a big multiple of that, since we also have to wait + * for the LibertyServer to poll the log for changes, and it only checks every 300ms. As the number + * of monitors we have increases, it also takes longer for each notification to get into the log. + * (I've counted intervals of 1s from the first notification to the last one.) + * + * However, since we're waiting for updates to stop, we would prefer that this timeout not be too long, + * since it sets a minimum delay for the last "no more changes" cycle. We *could* add onScanStart() and + * onScanEnd() events, but by the design of the monitors there's no promise that all results come in + * during a single scan. + * + * Inherently fragile, if net or server runs slower than expected. + * + * Better solution is to avoid relying on it -- use scrapeLogsForExpectedChanges. + */ + static final int TIMEOUT = 2410; + + // Not thread-safe, but this code is unlikely to run multi-threaded, being a test helper + private static final DateFormat DATE_FORMAT = new SimpleDateFormat("HH:mm:ss:SSS"); + + final String name; + + final Collection baseline = new ArrayList(); + final List created = new ArrayList(); + final List modified = new ArrayList(); + final List deleted = new ArrayList(); + + // When we gave up scraping the log for a string + long lastSearchTime; + + private final String baselineMarker; + private final Pattern baselineRegexp; + private final String changeMarker; + private final Pattern changeRegexp; + + MonitorReader(String eyeCatcher, String name) { + this.name = name; + baselineMarker = eyeCatcher + "onBaseline"; + baselineRegexp = Pattern.compile(baselineMarker + "\\[(.*)\\]"); + changeMarker = eyeCatcher + "onChange"; + changeRegexp = Pattern.compile(changeMarker + "\\[(.*)\\]\\[(.*)\\]\\[(.*)\\]"); + } + + void clear() { + baseline.clear(); + created.clear(); + modified.clear(); + deleted.clear(); + } + + /** + * The only way we have of communicating with our monitor running in the server is by the logs. + * (Well, unless we write a restful API for it, but that introduces dependencies into the test + * that I don't think we want.) + * + * This method (unlike the scrapeLogsForChanges methods) will reset all marks to the + * beginning of the log, since that's where baselines live. + * + * It also assumes (and asserts) that a baseline will always be present. + */ + void scrapeLogsForBaseline() throws Exception { + + // Set the mark to the beginning of the log, since the baseline will happen at the beginning but + // the calling test could run in any order + // This will reset the marks, too + FileMonitorTest.server.resetLogOffsets(); + + int count = 0; + clear(); + + // Assume we'll only get one baseline + String line = FileMonitorTest.server.waitForStringInLogUsingMark(baselineMarker); + if (line != null) { + Matcher matcher = baselineRegexp.matcher(line); + boolean matches = matcher.find(); + if (matches) { + count++; + baseline.addAll(parseArray(matcher.group(1))); + } + } + assertTrue("A baseline should have been reported on the " + baselineMarker + " monitor. Stopped searching at " + DATE_FORMAT.format(System.currentTimeMillis()), count > 0); + assertEquals("A baseline should have been reported on the " + baselineMarker + " monitor.", 1, count); + } + + /** + * This method must *not* set marks since multiple readers may read the same log. + * + * @param whether a change is atomic. A large write or multi-stage changes are not atomic. + * Non-atomic changes may receive more than one notification, and we want to notice + * them all. + * @return Number of matched lines scraped from the log. Not really useful. + * @throws Exception + * @see scrapeLogsForExpectedChanges + */ + int scrapeLogsForChanges() throws Exception { + int count = 0; + clear(); + + // We are trying to test timeliness of notification, so do specify a timeout + // WARNING: That timeout may be overoptimistic on today's + String line = FileMonitorTest.server.waitForStringInLogUsingMark(changeMarker, TIMEOUT); + while (line != null) { + Matcher matcher = changeRegexp.matcher(line); + boolean matches = matcher.find(); + if (matches) { + count++; + created.addAll(parseArray(matcher.group(1))); + modified.addAll(parseArray(matcher.group(2))); + deleted.addAll(parseArray(matcher.group(3))); + } + + // If a change isn't atomic, a single change by a test could be split across two + // notifications, so give a chance for a straggling split notification to limp in + // Since we're waiting for "no more", this slows us down but avoids intermittent failures. + // See scrapeLogsForExpectedChanges(), which instead exits once conditions are met + line = FileMonitorTest.server.waitForStringInLogUsingLastOffset(changeMarker, TIMEOUT); + + } + lastSearchTime = FileMonitorTest.server.searchStopTime; + + return count; + } + + /** + * This method must *not* set marks since multiple readers may read the same log. + * + * Unlike scrapeLogsForChanges(), this method exits as soon as the "expected" file alterations have been detected. + * This avoids the "loop until no more changes seen" approach, which permits a longer wait (less sensitive to timing + * problems) without significantly slowing down the test except in the failure case. + * + * The main risk is that it may not report _unexpected_ changes which arrive late... but we don't seem to be doing + * a lot of "and only these" tests right now. It also won't report error if the response is slow, but given that + * our current test platform's performance is variable, and that this is supposed to be a functional test rather than + * a performance test, that should be acceptable. + * + * @param whether a change is atomic. A large write or multi-stage changes are not atomic. + * Non-atomic changes may receive more than one notification, and we want to notice + * them all. + * @return Number of matched lines scraped from the log. Not really useful. + * @throws Exception + * @see scrapeLogsForChanges + */ + int scrapeLogsForExpectedChanges(Collection expectedCreates, Collection expectedModifies, Collection expectedDeletes) throws Exception { + int count = 0; + clear(); + + // We were trying to test timeliness of notification, so we specified timeouts + // Unfortunately our current test platform sometimes introduces long delays + // Hence we've switched back to default (longish) timeouts for functional test, + // and advised that performance should be tested separately. + String line = FileMonitorTest.server.waitForStringInLogUsingMark(changeMarker); + while (line != null) { + Matcher matcher = changeRegexp.matcher(line); + boolean matches = matcher.find(); + if (matches) { + count++; + created.addAll(parseArray(matcher.group(1))); + modified.addAll(parseArray(matcher.group(2))); + deleted.addAll(parseArray(matcher.group(3))); + } + + if ((expectedCreates == null || created.containsAll(expectedCreates)) && + (expectedModifies == null || modified.containsAll(expectedModifies)) && + (expectedDeletes == null || deleted.containsAll(expectedDeletes))) + { + line = null; // We found what we expected. We really don't care if there's more. Stop scanning. + } + else + { + // If a change isn't atomic, a single change by a test could be split across two + // notifications, so give a chance for a straggling split notification to limp in + // (this shouldn't slow things down if the expected info DOES eventually arrive) + line = FileMonitorTest.server.waitForStringInLogUsingLastOffset(changeMarker); + } + } + lastSearchTime = FileMonitorTest.server.searchStopTime; + + return count; + } + + /** + * @param group + * @return + */ + private List parseArray(String group) { + List files = new ArrayList(); + String[] names = group.split(","); + for (String name : names) { + if (name.trim().length() > 0) { + files.add(new File(name.trim())); + } + } + + return files; + } + +} \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.filemonitor_fat/publish/.gitignore b/dev/com.ibm.ws.kernel.filemonitor_fat/publish/.gitignore new file mode 100644 index 00000000000..0968b1bceb6 --- /dev/null +++ b/dev/com.ibm.ws.kernel.filemonitor_fat/publish/.gitignore @@ -0,0 +1 @@ +/bundles diff --git a/dev/com.ibm.ws.kernel.filemonitor_fat/publish/features/monitoringPrintingFeature-1.0.mf b/dev/com.ibm.ws.kernel.filemonitor_fat/publish/features/monitoringPrintingFeature-1.0.mf new file mode 100755 index 00000000000..6c43b6a8132 --- /dev/null +++ b/dev/com.ibm.ws.kernel.filemonitor_fat/publish/features/monitoringPrintingFeature-1.0.mf @@ -0,0 +1,7 @@ +Subsystem-ManifestVersion: 1 +IBM-ShortName: monitoringPrintingFeature-1.0 +Subsystem-SymbolicName: com.ibm.ws.kernel.filemonitor.monitoringfeature-1.0; visibility:=public +Subsystem-Version: 1.0.0 +Subsystem-Content: com.ibm.ws.kernel.filemonitor.monitor.test.bundle; version="[1,1.0.100)", +Subsystem-Type: osgi.subsystem.feature +IBM-Feature-Version: 2 diff --git a/dev/com.ibm.ws.kernel.filemonitor_fat/publish/servers/com.ibm.ws.kernel.filemonitor.server/bootstrap.properties b/dev/com.ibm.ws.kernel.filemonitor_fat/publish/servers/com.ibm.ws.kernel.filemonitor.server/bootstrap.properties new file mode 100755 index 00000000000..31f32c6fd52 --- /dev/null +++ b/dev/com.ibm.ws.kernel.filemonitor_fat/publish/servers/com.ibm.ws.kernel.filemonitor.server/bootstrap.properties @@ -0,0 +1 @@ +bootstrap.include=../testports.properties \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.filemonitor_fat/publish/servers/com.ibm.ws.kernel.filemonitor.server/server.xml b/dev/com.ibm.ws.kernel.filemonitor_fat/publish/servers/com.ibm.ws.kernel.filemonitor.server/server.xml new file mode 100755 index 00000000000..8201a2072a5 --- /dev/null +++ b/dev/com.ibm.ws.kernel.filemonitor_fat/publish/servers/com.ibm.ws.kernel.filemonitor.server/server.xml @@ -0,0 +1,15 @@ + + + + + + + usr:monitoringPrintingFeature-1.0 + restConnector-1.0 + + + + + + + diff --git a/dev/com.ibm.ws.kernel.filemonitor_fat/test-bundles/com.ibm.ws.kernel.filemonitor.monitor.test.bundle/bnd.bnd b/dev/com.ibm.ws.kernel.filemonitor_fat/test-bundles/com.ibm.ws.kernel.filemonitor.monitor.test.bundle/bnd.bnd new file mode 100755 index 00000000000..8b1b7f5d3a2 --- /dev/null +++ b/dev/com.ibm.ws.kernel.filemonitor_fat/test-bundles/com.ibm.ws.kernel.filemonitor.monitor.test.bundle/bnd.bnd @@ -0,0 +1,14 @@ +Bundle-Vendor: IBM +bVersion=1.0.0 +Bundle-Version: 1.0.0 +Bundle-Name: Feature which uses the file monitor SPI +Bundle-SymbolicName: com.ibm.ws.kernel.filemonitor.monitor.test.bundle + +Private-Package: \ + com.ibm.ws.kernel.filemonitor.monitor.test + +Service-Component: \ + com.ibm.ws.kernel.filemonitor.test.bundle.monitor; \ + implementation:=com.ibm.ws.kernel.filemonitor.monitor.test.FileMonitorRegistrationHandler; \ + immediate:=true + \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.filemonitor_fat/test-bundles/com.ibm.ws.kernel.filemonitor.monitor.test.bundle/src/com/ibm/ws/kernel/filemonitor/monitor/test/FileMonitorPrintingImplementation.java b/dev/com.ibm.ws.kernel.filemonitor_fat/test-bundles/com.ibm.ws.kernel.filemonitor.monitor.test.bundle/src/com/ibm/ws/kernel/filemonitor/monitor/test/FileMonitorPrintingImplementation.java new file mode 100755 index 00000000000..3d84befc597 --- /dev/null +++ b/dev/com.ibm.ws.kernel.filemonitor_fat/test-bundles/com.ibm.ws.kernel.filemonitor.monitor.test.bundle/src/com/ibm/ws/kernel/filemonitor/monitor/test/FileMonitorPrintingImplementation.java @@ -0,0 +1,56 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.kernel.filemonitor.monitor.test; + +import java.io.File; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Collection; + +import com.ibm.wsspi.kernel.filemonitor.FileMonitor; + +public class FileMonitorPrintingImplementation implements FileMonitor { + // Not thread-safe, so keep as an instance variable + private final DateFormat DATE_FORMAT = new SimpleDateFormat("HH:mm:ss:SSS"); + + private static final String EOR = ""; + private final String eyecatcher; + + public FileMonitorPrintingImplementation(String eyecatcher) { + this.eyecatcher = eyecatcher; + } + + @Override + public void onBaseline(Collection baseline) { + System.out.println(timestamp() + "onBaseline" + toString(baseline) + EOR); + + } + + @Override + public void onChange(Collection createdFiles, + Collection modifiedFiles, Collection deletedFiles) { + System.out.println(timestamp() + "onChange" + toString(createdFiles) + toString(modifiedFiles) + toString(deletedFiles) + EOR); + } + + private String toString(Collection files) { + return Arrays.toString(files.toArray()); + } + + /** + * @return + */ + private String timestamp() { + return DATE_FORMAT.format(System.currentTimeMillis()) + eyecatcher; + } + +} diff --git a/dev/com.ibm.ws.kernel.filemonitor_fat/test-bundles/com.ibm.ws.kernel.filemonitor.monitor.test.bundle/src/com/ibm/ws/kernel/filemonitor/monitor/test/FileMonitorRegistrationHandler.java b/dev/com.ibm.ws.kernel.filemonitor_fat/test-bundles/com.ibm.ws.kernel.filemonitor.monitor.test.bundle/src/com/ibm/ws/kernel/filemonitor/monitor/test/FileMonitorRegistrationHandler.java new file mode 100755 index 00000000000..d697f9b8b8a --- /dev/null +++ b/dev/com.ibm.ws.kernel.filemonitor_fat/test-bundles/com.ibm.ws.kernel.filemonitor.monitor.test.bundle/src/com/ibm/ws/kernel/filemonitor/monitor/test/FileMonitorRegistrationHandler.java @@ -0,0 +1,204 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.kernel.filemonitor.monitor.test; + +import java.io.File; +import java.io.IOException; +import java.util.Collection; +import java.util.HashSet; +import java.util.Hashtable; + +import org.osgi.framework.BundleContext; +import org.osgi.service.component.ComponentContext; + +import com.ibm.wsspi.kernel.filemonitor.FileMonitor; + +public class FileMonitorRegistrationHandler { + + private final long monitorInterval = 150; + + public void activate(ComponentContext cc) throws IOException { + System.out.println("FAT test code is registering FileMonitor implementations."); + + File tmpFile = File.createTempFile(FileMonitorRegistrationHandler.class.getName(), "file"); + + // Make a temporary folder to monitor + File tmpFolder = File.createTempFile(FileMonitorRegistrationHandler.class.getName(), "folder"); + tmpFolder.delete(); + tmpFolder.mkdirs(); + + File nonExistentFile = File.createTempFile(FileMonitorRegistrationHandler.class.getName(), "nonexistentfile"); + nonExistentFile.delete(); + + // Make a temporary folder to monitor + File nonExistentFolder = File.createTempFile(FileMonitorRegistrationHandler.class.getName(), "nonexistentfolder"); + nonExistentFolder.delete(); + + // We need to make baseline files before we register + File baseline = new File(tmpFolder, "baseline"); + baseline.createNewFile(); + File baseline1 = new File(tmpFolder, "baseline1"); + baseline1.createNewFile(); + File nestedFolder = new File(tmpFolder, "nestedBaselineFolder"); + nestedFolder.mkdirs(); + File nestedFile = new File(nestedFolder, "nestedBaselineFile"); + nestedFile.createNewFile(); + + // This output is important to the FAT test + System.out.println("-MONITORED FOLDER-" + tmpFolder.getAbsolutePath()); + System.out.println("-MONITORED FILE-" + tmpFile.getAbsolutePath()); + System.out.println("-NONEXISTENT FOLDER-" + nonExistentFolder.getAbsolutePath()); + System.out.println("-NONEXISTENT FILE-" + nonExistentFile.getAbsolutePath()); + + BundleContext bundleContext = cc.getBundleContext(); + + Collection folderSet = new HashSet(); + folderSet.add(tmpFolder.getAbsolutePath()); + + Collection fileSet = new HashSet(); + fileSet.add(tmpFile.getAbsolutePath()); + + Collection nonExistentFolderSet = new HashSet(); + nonExistentFolderSet.add(nonExistentFolder.getAbsolutePath()); + + Collection nonExistentFileSet = new HashSet(); + nonExistentFileSet.add(nonExistentFile.getAbsolutePath()); + + registerRecursiveMonitor(bundleContext, "-RECURSIVETESTMONITOROUTPUT-", folderSet); + registerRecursiveMonitor(bundleContext, "-NONEXISTENTFOLDERTESTMONITOROUTPUT-", nonExistentFolderSet); + // Register something monitoring a directory, where there's actually a file in that spot + registerRecursiveMonitor(bundleContext, "-RECURSIVEBUTACTUALLYMONITORINGFILETESTMONITOROUTPUT-", fileSet); + + // Also register a monitor with filters + registerRegexFilteredFileMonitor(bundleContext, folderSet); + registerFileFilteredFileMonitor(bundleContext, folderSet); + registerDirectoryFilteredFileMonitor(bundleContext, folderSet); + + // Also register a non-recursive monitor + registerNonRecursiveMonitor(bundleContext, folderSet); + + // Also register a monitor which isn't watching its own folder + registerMonitorSelfMonitor(bundleContext, folderSet); + registerNonRecursiveMonitorSelfMonitor(bundleContext, folderSet); + + // Also register a monitor watching a file + registerFileMonitor(bundleContext, "-FILETESTMONITOROUTPUT-", fileSet); + registerFileMonitor(bundleContext, "-FILENONEXISTENTTESTMONITOROUTPUT-", nonExistentFileSet); + // Register something monitoring a directory, where there's actually a file in that spot + registerFileMonitor(bundleContext, "-FILEBUTACTUALLYMONITORINGDIRECTORYTESTMONITOROUTPUT-", folderSet); + + // Register an externally driven monitor watching a folder + registerManualMonitor(bundleContext, folderSet); + + } + + /** + * A monitor which really is of file-type to monitor just files (not folders). + */ + private void registerFileMonitor(BundleContext bundleContext, String fileEyecatcher, Collection fileSet) { + final Hashtable fileMonitorProps = new Hashtable(); + fileMonitorProps.put(FileMonitor.MONITOR_FILES, fileSet); + fileMonitorProps.put(FileMonitor.MONITOR_INTERVAL, monitorInterval); + bundleContext.registerService(FileMonitor.class, new FileMonitorPrintingImplementation(fileEyecatcher), fileMonitorProps); + } + + private void registerMonitorSelfMonitor(BundleContext bundleContext, Collection folderSet) { + String monitorSelfEyecatcher = "-MONITORSELFTESTMONITOROUTPUT-"; + final Hashtable monitorSelfFileMonitorProps = new Hashtable(); + monitorSelfFileMonitorProps.put(FileMonitor.MONITOR_DIRECTORIES, folderSet); + monitorSelfFileMonitorProps.put(FileMonitor.MONITOR_INCLUDE_SELF, true); + monitorSelfFileMonitorProps.put(FileMonitor.MONITOR_RECURSE, true); + monitorSelfFileMonitorProps.put(FileMonitor.MONITOR_INTERVAL, monitorInterval); + bundleContext.registerService(FileMonitor.class, new FileMonitorPrintingImplementation(monitorSelfEyecatcher), monitorSelfFileMonitorProps); + } + + private void registerNonRecursiveMonitorSelfMonitor(BundleContext bundleContext, Collection folderSet) { + String monitorSelfEyecatcher = "-NONRECURSEMONITORSELFTESTMONITOROUTPUT-"; + final Hashtable monitorSelfFileMonitorProps = new Hashtable(); + monitorSelfFileMonitorProps.put(FileMonitor.MONITOR_DIRECTORIES, folderSet); + monitorSelfFileMonitorProps.put(FileMonitor.MONITOR_INCLUDE_SELF, true); + monitorSelfFileMonitorProps.put(FileMonitor.MONITOR_RECURSE, false); + monitorSelfFileMonitorProps.put(FileMonitor.MONITOR_INTERVAL, monitorInterval); + bundleContext.registerService(FileMonitor.class, new FileMonitorPrintingImplementation(monitorSelfEyecatcher), monitorSelfFileMonitorProps); + } + + private void registerNonRecursiveMonitor(BundleContext bundleContext, Collection folderSet) { + // Avoid overlap with the eyecatcher for the recursive monitor to avoid regexp horribleness + String nonRecursiveEyecatcher = "-NONRECURSINGTESTMONITOROUTPUT-"; + final Hashtable nonRecursiveFileMonitorProps = new Hashtable(); + nonRecursiveFileMonitorProps.put(FileMonitor.MONITOR_DIRECTORIES, folderSet); + nonRecursiveFileMonitorProps.put(FileMonitor.MONITOR_INCLUDE_SELF, false); + nonRecursiveFileMonitorProps.put(FileMonitor.MONITOR_RECURSE, false); + nonRecursiveFileMonitorProps.put(FileMonitor.MONITOR_INTERVAL, monitorInterval); + bundleContext.registerService(FileMonitor.class, new FileMonitorPrintingImplementation(nonRecursiveEyecatcher), nonRecursiveFileMonitorProps); + } + + /** + * A monitor which monitors a folder recursively (but doesn't include itself). + */ + private void registerRecursiveMonitor(BundleContext bundleContext, String recursiveEyecatcher, Collection fileSet) { + final Hashtable recursiveFileMonitorProps = new Hashtable(); + recursiveFileMonitorProps.put(FileMonitor.MONITOR_DIRECTORIES, fileSet); + recursiveFileMonitorProps.put(FileMonitor.MONITOR_INCLUDE_SELF, false); + recursiveFileMonitorProps.put(FileMonitor.MONITOR_RECURSE, true); + recursiveFileMonitorProps.put(FileMonitor.MONITOR_INTERVAL, monitorInterval); + bundleContext.registerService(FileMonitor.class, new FileMonitorPrintingImplementation(recursiveEyecatcher), recursiveFileMonitorProps); + } + + private void registerRegexFilteredFileMonitor(BundleContext bundleContext, Collection fileSet) { + final Hashtable fileMonitorProps = new Hashtable(); + fileMonitorProps.put(FileMonitor.MONITOR_DIRECTORIES, fileSet); + fileMonitorProps.put(FileMonitor.MONITOR_INCLUDE_SELF, false); + fileMonitorProps.put(FileMonitor.MONITOR_RECURSE, true); + fileMonitorProps.put(FileMonitor.MONITOR_INTERVAL, monitorInterval); + // Use the middle of the file's name as a filter + String filter = ".*include.*"; + fileMonitorProps.put(FileMonitor.MONITOR_FILTER, filter); + String eyecatcher = "-FILTEREDTESTMONITOROUTPUT-"; + bundleContext.registerService(FileMonitor.class, new FileMonitorPrintingImplementation(eyecatcher), fileMonitorProps); + } + + private void registerFileFilteredFileMonitor(BundleContext bundleContext, Collection fileSet) { + final Hashtable fileMonitorProps = new Hashtable(); + fileMonitorProps.put(FileMonitor.MONITOR_DIRECTORIES, fileSet); + fileMonitorProps.put(FileMonitor.MONITOR_INCLUDE_SELF, false); + fileMonitorProps.put(FileMonitor.MONITOR_RECURSE, true); + fileMonitorProps.put(FileMonitor.MONITOR_INTERVAL, monitorInterval); + fileMonitorProps.put(FileMonitor.MONITOR_FILTER, FileMonitor.MONITOR_FILTER_FILES_ONLY); + String eyecatcher = "-FILEFILTERTESTMONITOROUTPUT-"; + bundleContext.registerService(FileMonitor.class, new FileMonitorPrintingImplementation(eyecatcher), fileMonitorProps); + } + + private void registerDirectoryFilteredFileMonitor(BundleContext bundleContext, Collection fileSet) { + final Hashtable fileMonitorProps = new Hashtable(); + fileMonitorProps.put(FileMonitor.MONITOR_DIRECTORIES, fileSet); + fileMonitorProps.put(FileMonitor.MONITOR_INCLUDE_SELF, true); + fileMonitorProps.put(FileMonitor.MONITOR_RECURSE, true); + fileMonitorProps.put(FileMonitor.MONITOR_INTERVAL, monitorInterval); + fileMonitorProps.put(FileMonitor.MONITOR_FILTER, FileMonitor.MONITOR_FILTER_DIRECTORIES_ONLY); + String eyecatcher = "-DIRECTORYFILTERTESTMONITOROUTPUT-"; + bundleContext.registerService(FileMonitor.class, new FileMonitorPrintingImplementation(eyecatcher), fileMonitorProps); + } + + private void registerManualMonitor(BundleContext bundleContext, Collection fileSet) { + final Hashtable monitorProps = new Hashtable(); + monitorProps.put(FileMonitor.MONITOR_DIRECTORIES, fileSet); + monitorProps.put(FileMonitor.MONITOR_INCLUDE_SELF, true); + monitorProps.put(FileMonitor.MONITOR_RECURSE, true); + monitorProps.put(FileMonitor.MONITOR_INTERVAL, monitorInterval); + monitorProps.put(FileMonitor.MONITOR_TYPE, FileMonitor.MONITOR_TYPE_EXTERNAL); + + String eyecatcher = "-MANUALMONITOROUTPUT-"; + bundleContext.registerService(FileMonitor.class, new FileMonitorPrintingImplementation(eyecatcher), monitorProps); + } + +} diff --git a/dev/com.ibm.ws.kernel.metatype.helper_fat/.classpath b/dev/com.ibm.ws.kernel.metatype.helper_fat/.classpath new file mode 100755 index 00000000000..c422489df40 --- /dev/null +++ b/dev/com.ibm.ws.kernel.metatype.helper_fat/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/dev/com.ibm.ws.kernel.metatype.helper_fat/.classpath.gradle b/dev/com.ibm.ws.kernel.metatype.helper_fat/.classpath.gradle new file mode 100644 index 00000000000..c422489df40 --- /dev/null +++ b/dev/com.ibm.ws.kernel.metatype.helper_fat/.classpath.gradle @@ -0,0 +1,7 @@ + + + + + + + diff --git a/dev/com.ibm.ws.kernel.metatype.helper_fat/.gitignore b/dev/com.ibm.ws.kernel.metatype.helper_fat/.gitignore new file mode 100644 index 00000000000..5d00910f3a6 --- /dev/null +++ b/dev/com.ibm.ws.kernel.metatype.helper_fat/.gitignore @@ -0,0 +1 @@ +/coverage.ec diff --git a/dev/com.ibm.ws.kernel.metatype.helper_fat/.project b/dev/com.ibm.ws.kernel.metatype.helper_fat/.project new file mode 100755 index 00000000000..c91b986c5aa --- /dev/null +++ b/dev/com.ibm.ws.kernel.metatype.helper_fat/.project @@ -0,0 +1,23 @@ + + + com.ibm.ws.kernel.metatype.helper_fat + + + + + + org.eclipse.jdt.core.javabuilder + + + + + bndtools.core.bndbuilder + + + + + + org.eclipse.jdt.core.javanature + bndtools.core.bndnature + + diff --git a/dev/com.ibm.ws.kernel.metatype.helper_fat/.settings/org.eclipse.core.resources.prefs b/dev/com.ibm.ws.kernel.metatype.helper_fat/.settings/org.eclipse.core.resources.prefs new file mode 100755 index 00000000000..25d9425fe34 --- /dev/null +++ b/dev/com.ibm.ws.kernel.metatype.helper_fat/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,4 @@ +#Ant properties +#Automatically generated by the ant prepare.settings.files task +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/dev/com.ibm.ws.kernel.metatype.helper_fat/.settings/org.eclipse.jdt.core.prefs b/dev/com.ibm.ws.kernel.metatype.helper_fat/.settings/org.eclipse.jdt.core.prefs new file mode 100755 index 00000000000..72a0b4c067c --- /dev/null +++ b/dev/com.ibm.ws.kernel.metatype.helper_fat/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,281 @@ +#Ant properties +#Automatically generated by the ant prepare.settings.files task +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.6 +org.eclipse.jdt.core.formatter.align_type_members_on_columns=false +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=0 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=18 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=2 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=2 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=18 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=2 +org.eclipse.jdt.core.formatter.alignment_for_assignment=0 +org.eclipse.jdt.core.formatter.alignment_for_binary_expression=18 +org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=0 +org.eclipse.jdt.core.formatter.alignment_for_enum_constants=16 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=18 +org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=18 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=18 +org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=0 +org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=20 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=4 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +org.eclipse.jdt.core.formatter.blank_lines_before_field=0 +org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 +org.eclipse.jdt.core.formatter.blank_lines_before_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 +org.eclipse.jdt.core.formatter.blank_lines_before_package=0 +org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 +org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 +org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false +org.eclipse.jdt.core.formatter.comment.format_block_comments=true +org.eclipse.jdt.core.formatter.comment.format_header=false +org.eclipse.jdt.core.formatter.comment.format_html=false +org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true +org.eclipse.jdt.core.formatter.comment.format_line_comments=false +org.eclipse.jdt.core.formatter.comment.format_source_code=true +org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true +org.eclipse.jdt.core.formatter.comment.indent_root_tags=true +org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert +org.eclipse.jdt.core.formatter.comment.line_length=180 +org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true +org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true +org.eclipse.jdt.core.formatter.compact_else_if=true +org.eclipse.jdt.core.formatter.continuation_indentation=4 +org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=4 +org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off +org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on +org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false +org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=false +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true +org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_empty_lines=false +org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true +org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true +org.eclipse.jdt.core.formatter.indentation.size=8 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert +org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.join_lines_in_comments=false +org.eclipse.jdt.core.formatter.join_wrapped_lines=false +org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false +org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false +org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false +org.eclipse.jdt.core.formatter.lineSplit=180 +org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=true +org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=true +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 +org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=false +org.eclipse.jdt.core.formatter.tabulation.char=space +org.eclipse.jdt.core.formatter.tabulation.size=4 +org.eclipse.jdt.core.formatter.use_on_off_tags=true +org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false +org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true +org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true diff --git a/dev/com.ibm.ws.kernel.metatype.helper_fat/.settings/org.eclipse.jdt.ui.prefs b/dev/com.ibm.ws.kernel.metatype.helper_fat/.settings/org.eclipse.jdt.ui.prefs new file mode 100755 index 00000000000..c92277a371a --- /dev/null +++ b/dev/com.ibm.ws.kernel.metatype.helper_fat/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,62 @@ +#Ant properties +#Automatically generated by the ant prepare.settings.files task +eclipse.preferences.version=1 +editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true +org.eclipse.jdt.ui.ignorelowercasenames=true +org.eclipse.jdt.ui.importorder=java;javax;org;com; +org.eclipse.jdt.ui.javadoc=true +org.eclipse.jdt.ui.ondemandthreshold=99 +org.eclipse.jdt.ui.staticondemandthreshold=99 +org.eclipse.jdt.ui.text.custom_code_templates= +sp_cleanup.add_default_serial_version_id=true +sp_cleanup.add_generated_serial_version_id=false +sp_cleanup.add_missing_annotations=true +sp_cleanup.add_missing_deprecated_annotations=true +sp_cleanup.add_missing_methods=false +sp_cleanup.add_missing_nls_tags=false +sp_cleanup.add_missing_override_annotations=true +sp_cleanup.add_missing_override_annotations_interface_methods=true +sp_cleanup.add_serial_version_id=false +sp_cleanup.always_use_blocks=true +sp_cleanup.always_use_parentheses_in_expressions=false +sp_cleanup.always_use_this_for_non_static_field_access=false +sp_cleanup.always_use_this_for_non_static_method_access=false +sp_cleanup.convert_to_enhanced_for_loop=false +sp_cleanup.correct_indentation=false +sp_cleanup.format_source_code=true +sp_cleanup.format_source_code_changes_only=false +sp_cleanup.make_local_variable_final=false +sp_cleanup.make_parameters_final=false +sp_cleanup.make_private_fields_final=true +sp_cleanup.make_type_abstract_if_missing_method=false +sp_cleanup.make_variable_declarations_final=true +sp_cleanup.never_use_blocks=false +sp_cleanup.never_use_parentheses_in_expressions=true +sp_cleanup.on_save_use_additional_actions=true +sp_cleanup.organize_imports=true +sp_cleanup.qualify_static_field_accesses_with_declaring_class=false +sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_with_declaring_class=false +sp_cleanup.qualify_static_method_accesses_with_declaring_class=false +sp_cleanup.remove_private_constructors=true +sp_cleanup.remove_trailing_whitespaces=true +sp_cleanup.remove_trailing_whitespaces_all=true +sp_cleanup.remove_trailing_whitespaces_ignore_empty=false +sp_cleanup.remove_unnecessary_casts=true +sp_cleanup.remove_unnecessary_nls_tags=true +sp_cleanup.remove_unused_imports=true +sp_cleanup.remove_unused_local_variables=false +sp_cleanup.remove_unused_private_fields=true +sp_cleanup.remove_unused_private_members=false +sp_cleanup.remove_unused_private_methods=true +sp_cleanup.remove_unused_private_types=true +sp_cleanup.sort_members=false +sp_cleanup.sort_members_all=false +sp_cleanup.use_blocks=false +sp_cleanup.use_blocks_only_for_return_and_throw=false +sp_cleanup.use_parentheses_in_expressions=false +sp_cleanup.use_this_for_non_static_field_access=false +sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true +sp_cleanup.use_this_for_non_static_method_access=false +sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true diff --git a/dev/com.ibm.ws.kernel.metatype.helper_fat/bnd.bnd b/dev/com.ibm.ws.kernel.metatype.helper_fat/bnd.bnd new file mode 100644 index 00000000000..0822f646bcf --- /dev/null +++ b/dev/com.ibm.ws.kernel.metatype.helper_fat/bnd.bnd @@ -0,0 +1,12 @@ +-include= ~../cnf/resources/bnd/bundle.props +bVersion=1.0 + +src: \ + fat/src + +-buildpath: \ + ${javac.bootclasspath.java6}, \ + ../build.sharedResources/lib/junit/old/junit.jar;version=file, \ + fattest.simplicity;version=latest, \ + ../fattest.simplicity/lib/public.api.jar;version=file, \ + com.ibm.ws.kernel.metatype.helper;version=latest diff --git a/dev/com.ibm.ws.kernel.metatype.helper_fat/bnd.bnd.gradle b/dev/com.ibm.ws.kernel.metatype.helper_fat/bnd.bnd.gradle new file mode 100644 index 00000000000..0822f646bcf --- /dev/null +++ b/dev/com.ibm.ws.kernel.metatype.helper_fat/bnd.bnd.gradle @@ -0,0 +1,12 @@ +-include= ~../cnf/resources/bnd/bundle.props +bVersion=1.0 + +src: \ + fat/src + +-buildpath: \ + ${javac.bootclasspath.java6}, \ + ../build.sharedResources/lib/junit/old/junit.jar;version=file, \ + fattest.simplicity;version=latest, \ + ../fattest.simplicity/lib/public.api.jar;version=file, \ + com.ibm.ws.kernel.metatype.helper;version=latest diff --git a/dev/com.ibm.ws.kernel.metatype.helper_fat/build-test.xml b/dev/com.ibm.ws.kernel.metatype.helper_fat/build-test.xml new file mode 100755 index 00000000000..c82e346aeec --- /dev/null +++ b/dev/com.ibm.ws.kernel.metatype.helper_fat/build-test.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.metatype.helper_fat/build.gradle b/dev/com.ibm.ws.kernel.metatype.helper_fat/build.gradle new file mode 100644 index 00000000000..e69de29bb2d diff --git a/dev/com.ibm.ws.kernel.metatype.helper_fat/delivery.sets b/dev/com.ibm.ws.kernel.metatype.helper_fat/delivery.sets new file mode 100755 index 00000000000..674398425a0 --- /dev/null +++ b/dev/com.ibm.ws.kernel.metatype.helper_fat/delivery.sets @@ -0,0 +1 @@ +SLE diff --git a/dev/com.ibm.ws.kernel.metatype.helper_fat/fat/src/com/ibm/ws/kernel/metatype/helper/fat/FATTest.java b/dev/com.ibm.ws.kernel.metatype.helper_fat/fat/src/com/ibm/ws/kernel/metatype/helper/fat/FATTest.java new file mode 100755 index 00000000000..144ab84c85b --- /dev/null +++ b/dev/com.ibm.ws.kernel.metatype.helper_fat/fat/src/com/ibm/ws/kernel/metatype/helper/fat/FATTest.java @@ -0,0 +1,370 @@ +package com.ibm.ws.kernel.metatype.helper.fat; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Ignore; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestName; + +import com.ibm.websphere.simplicity.RemoteFile; +import com.ibm.websphere.simplicity.log.Log; +import componenttest.topology.impl.LibertyServer; +import componenttest.topology.impl.LibertyServerFactory; +import componenttest.topology.utils.LibertyServerUtils; + +public class FATTest { + + private static final LibertyServer server = LibertyServerFactory + .getLibertyServer("com.ibm.ws.kernel.metatype.helperServer"); + private static final String baseURL = "http://" + server.getHostname() + ":" + server.getHttpDefaultPort() + + "/fileset"; + private final Class c = FATTest.class; + + // Servlet Strings + private static final String BASE = "This is Fileset servlet."; + private static final String BASE_ERROR = "The servlet was not available or did not return the expected content"; + private static final String SERVICE = "Found 1 fileset service."; + private static final String SERVICE_ERROR = "The Fileset service was not found, or too many were found."; + private static final String FILES = "Fileset contained file: "; + private static final String FILES_ERROR = "The fileset retrieved by the servlet did not match that expected."; + + private static final String TEST_FOLDER = "usr/shared/resources/fileset_test_bundles"; + private static final String GEN_JAR_NAME = "test3.jar"; + private static final String GEN_JAR_PATH = TEST_FOLDER + "/" + GEN_JAR_NAME; + + private static final String INIT_MSG_RE = "FileMonitor init completed for fileset"; + private static final String SCAN_MSG_RE = "FileMonitor scan completed for fileset"; + + // default to timeout after 5 seconds for the servlet content to be what we expect + // and for log/trace messages we are waiting for to appear + private static final int CONTENT_TIMEOUT = 5; + + @BeforeClass + public static void setUp() throws Exception { + // clean up from any failed runs + cleanUpGeneratedFiles(); + } + + @Rule + public TestName name = new TestName(); + + public String testName = ""; + public String currentLog = ""; + + @Before + public void setServerConfig() throws Exception { + // set the current test name + testName = name.getMethodName(); + + Log.info(c, testName, "=== Preparing for test " + testName + " ==="); + server.copyFileToLibertyInstallRoot("lib/features", "internalFeatureForFat/filesetfatlibertyinternals-1.0.mf"); + + server.startServer(testName + "_console.log"); + Log.info(c, testName, "===== Starting test " + testName + " ====="); + } + + @After + public void cleanUpAfter() throws Exception { + Log.info(c, testName, "=== Cleaning up from test " + testName + " ==="); + + cleanUpGeneratedFiles(); + + //stop the server and collect the logs + server.stopServer(true); + + // switch back to the monitored_fileset/server.xml after each test + setConfigurationFile("monitored_fileset"); + } + + private static void cleanUpGeneratedFiles() throws Exception { + server.deleteFileFromLibertyInstallRoot(GEN_JAR_PATH); + } + + @AfterClass + public static void cleanUpSharedFolder() throws Exception { + server.deleteFileFromLibertyInstallRoot(TEST_FOLDER); + } + + @Test + public void testServlet() throws Exception { + String[] expected = new String[] { BASE }; + + verifyContent("", expected, BASE_ERROR); + } + + @Test + public void testFilesetService() throws Exception { + String[] expected = new String[] { BASE, SERVICE }; + + verifyContent("Service", expected, SERVICE_ERROR); + } + + @Test + public void testFilesetFiles() throws Exception { + + verifyJarsOneAndTwo(); + } + + @Test + public void testFilesetFilesUpdatedByMonitor() throws Exception { + + // check the fileset has only one and two + verifyJarsOneAndTwo(); + + // now copy three into place + copyTestJar(); + + // wait for the scan complete message + waitForTraceMessage(SCAN_MSG_RE); + + // verify that the fileset has jars one, two and three + verifyJarsOneTwoThree(); + } + + @Test + public void testFilesetFilesMonitorDisabled() throws Exception { + + // hack to give time for setup to copy files over since monitor will be disabled. This + // should ensure the server gets a snapshot of the directory after the setup copy + // has completed. Ideally it would be good to have some mechanism to detect when setup has + // completed but since the problem is occurring frequently the tactical hack + // was opted for to try and keep the builds green. + try { + Thread.sleep(1000); + } catch (Exception ex) { + } + + // change the configuration to disable monitoring and wait for the + // update trace + setConfigurationFileAndWait("unmonitored_fileset"); + + // verify that the fileset contains jars one and two + verifyJarsOneAndTwo(); + + // move the test3.jar into the fileset location + copyTestJar(); + + // check that the test3.jar has not appeared in the list of fileset + // files because we are not monitoring + verifyJarsOneAndTwo(); + + // since we are not scanning there aren't really any messages we can + // check for + // instead we'll just verify again that the third jar hasn't appeared + verifyJarsOneAndTwo(); + } + + @Test + public void testFilesetFilesMonitorReenabled() throws Exception { + + // disable the monitor and check for jars one and two + setConfigurationFileAndWait("unmonitored_fileset"); + verifyJarsOneAndTwo(); + + // update the config to re-enable the monitor + setConfigurationFileAndWait("monitored_fileset"); + + // move the test3.jar into the fileset location + copyTestJar(); + + //we should see two init complete messages, one from when the server came up + //and a second for when monitoring was re-enabled. + waitForTraceToMatchExpression(".*" + INIT_MSG_RE + ".*" + INIT_MSG_RE + ".*"); + + // check that the fileset has been updated + verifyJarsOneTwoThree(); + + } + + @Test + public void testCommaSeparatedFiles() throws Exception { + + // move the test3.jar into the fileset location + copyTestJar(); + + //verify that fileset can be specified with comma separated jar files + setConfigurationFileAndWait("fileset_list"); + verifyJarsOneTwoThree(); + } + + @Test + // recursion is no longer supported + @Ignore + public void testFilesetFilesUpdatedByConfig() throws Exception { + + // set the modified server.xml to be the server configuraiton + setConfigurationFileAndWait("config_change_fileset"); + + // now check that the fileset returns jars one, two and four + String[] expected = new String[] { BASE, FILES + "test1.jar", FILES + "test2.jar", FILES + "test4.jar" }; + + verifyContent("Files", expected, FILES_ERROR); + } + + private void copyTestJar() throws Exception { + // process to get a new jar into the resource folder + // use the FAT utility to copy the test3.jar to the install root + server.copyFileToLibertyInstallRoot(GEN_JAR_NAME); + // copy form the install root to the resources location + RemoteFile jarDest = new RemoteFile(server.getMachine(), LibertyServerUtils.makeJavaCompatible(server + .getInstallRoot() + + "/" + GEN_JAR_PATH)); + RemoteFile rootJar = server.getFileFromLibertyInstallRoot(GEN_JAR_NAME); + assertTrue("Copy of the generated jar file failed, the test will fail.", rootJar.copyToDest(jarDest)); + // now delete the original in the install root + if (rootJar.exists()) + rootJar.delete(); + + // now sleep for a second to allow the FileMonitor to run (it is set to + // run every 500ms) + Thread.sleep(1000); + } + + private List getContent(String urlQuerySuffix) throws Exception { + String logMsg = "getContent - " + testName; + String suffix = ("".equals(urlQuerySuffix)) ? "" : "?" + urlQuerySuffix; + URL url = new URL(baseURL + suffix); + Log.info(c, logMsg, "Calling servlet URL=" + url.toString()); + + HttpURLConnection con = (HttpURLConnection) url.openConnection(); + con.setDoInput(true); + con.setDoOutput(true); + con.setUseCaches(false); + con.setRequestMethod("GET"); + InputStream is = con.getInputStream(); + InputStreamReader isr = new InputStreamReader(is); + BufferedReader br = new BufferedReader(isr); + + // read the page contents + String line = br.readLine(); + List lines = new ArrayList(); + while (line != null) { + lines.add(line); + line = br.readLine(); + } + con.disconnect(); + Log.info(c, logMsg, "Retrieved content: " + lines); + return lines; + } + + private void verifyContent(String urlQuerySuffix, String[] expect, String message) throws Exception { + + List actualContent = null; + Collection expectedContent = Arrays.asList(expect); + + long timeout = System.currentTimeMillis() + (CONTENT_TIMEOUT * 1000); + while (!!!expectedContent.equals(actualContent) && System.currentTimeMillis() < timeout) { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + /* ignore */ + } + actualContent = getContent(urlQuerySuffix); + } + + assertEquals(message, expectedContent, actualContent); + } + + private void verifyJarsOneAndTwo() throws Exception { + String[] expected = new String[] { BASE, FILES + "test1.jar", FILES + "test2.jar" }; + + verifyContent("Files", expected, FILES_ERROR); + } + + private void verifyJarsOneTwoThree() throws Exception { + String[] expected = new String[] { BASE, FILES + "test1.jar", FILES + "test2.jar", FILES + "test3.jar" }; + + verifyContent("Files", expected, FILES_ERROR); + } + + private void setConfigurationFile(String serverxmlPathPrefix) throws Exception { + // set the server configuration file + server.setServerConfigurationFile(serverxmlPathPrefix + "/server.xml"); + } + + private void setConfigurationFileAndWait(String serverxmlPathPrefix) throws Exception { + setConfigurationFile(serverxmlPathPrefix); + + //wait 5 seconds for the config updated or config didn't change messages + server.waitForStringInLog("CWWKG0017|CWWKG0018", 5000); + } + + private RemoteFile getTraceFile() throws Exception { + // first wait up to 5 seconds for the log file to appear + RemoteFile logFile = null; + long timeout = System.currentTimeMillis() + 5000; + while (logFile == null && System.currentTimeMillis() < timeout) { + logFile = server.getMatchingLogFile("trace.*"); + if (logFile == null) { + Thread.sleep(500); + } + } + return logFile; + } + + private void waitForTraceMessage(String msgToWaitFor) throws Exception { + // search the trace log to check for the update + String found = server.waitForStringInLog(msgToWaitFor, 5000, getTraceFile()); + if (found == null) { + Log.warning(c, "Did not find the string \"" + msgToWaitFor + "\" in the log"); + } else { + Log.info(c, "waitForTraceMessage", "Found message " + msgToWaitFor); + } + } + + private void waitForTraceToMatchExpression(String regEx) throws Exception { + + RemoteFile traceFile = getTraceFile(); + + StringBuilder traceContent = new StringBuilder(); + + BufferedReader reader = new BufferedReader(new InputStreamReader(traceFile.openForReading())); + try { + long timeout = System.currentTimeMillis() + (CONTENT_TIMEOUT * 1000); + boolean matched = false; + Pattern p = Pattern.compile(regEx); + while (System.currentTimeMillis() < timeout) { + String nextLine = reader.readLine(); + if (nextLine != null) { + traceContent.append(nextLine); + } else { + //if we reached the end of the file we should wait a while before looping again + Thread.sleep(100); + } + Matcher m = p.matcher(traceContent.toString()); + if (m.matches()) { + matched = true; + break; + } + } + + // search the trace log to check for the update + if (!!!matched) { + Log.warning(c, "Did not find the expression \"" + regEx + "\" in the log"); + } else { + Log.info(c, "waitForTraceMessages", "Found expression " + regEx); + } + } finally { + reader.close(); + } + } + +} diff --git a/dev/com.ibm.ws.kernel.metatype.helper_fat/publish/files/config_change_fileset/server.xml b/dev/com.ibm.ws.kernel.metatype.helper_fat/publish/files/config_change_fileset/server.xml new file mode 100755 index 00000000000..8b6fbc0f317 --- /dev/null +++ b/dev/com.ibm.ws.kernel.metatype.helper_fat/publish/files/config_change_fileset/server.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.metatype.helper_fat/publish/files/fileset_list/server.xml b/dev/com.ibm.ws.kernel.metatype.helper_fat/publish/files/fileset_list/server.xml new file mode 100755 index 00000000000..f8402002d66 --- /dev/null +++ b/dev/com.ibm.ws.kernel.metatype.helper_fat/publish/files/fileset_list/server.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.metatype.helper_fat/publish/files/internalFeatureForFat/filesetfatlibertyinternals-1.0.mf b/dev/com.ibm.ws.kernel.metatype.helper_fat/publish/files/internalFeatureForFat/filesetfatlibertyinternals-1.0.mf new file mode 100755 index 00000000000..1cf06cdf6f4 --- /dev/null +++ b/dev/com.ibm.ws.kernel.metatype.helper_fat/publish/files/internalFeatureForFat/filesetfatlibertyinternals-1.0.mf @@ -0,0 +1,7 @@ +Subsystem-ManifestVersion: 1 +Subsystem-SymbolicName: filesetfatlibertyinternals-1.0;visibility:=public +Subsystem-Version: 1.0.0 +Subsystem-Type: osgi.subsystem.feature +IBM-API-Package: com.ibm.wsspi.config; type="internal", + org.osgi.framework; type="spec" +IBM-Feature-Version: 2 diff --git a/dev/com.ibm.ws.kernel.metatype.helper_fat/publish/files/monitored_fileset/server.xml b/dev/com.ibm.ws.kernel.metatype.helper_fat/publish/files/monitored_fileset/server.xml new file mode 100755 index 00000000000..c599ced1ecc --- /dev/null +++ b/dev/com.ibm.ws.kernel.metatype.helper_fat/publish/files/monitored_fileset/server.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.metatype.helper_fat/publish/files/test3.jar b/dev/com.ibm.ws.kernel.metatype.helper_fat/publish/files/test3.jar new file mode 100755 index 0000000000000000000000000000000000000000..1e1ca9e87dd1a16c0b9e9a7b68d715e09e6e4cbc GIT binary patch literal 427 zcmWIWW@Zs#-~d7yHz|7tB*4kQ!r%MB zNsWvOtDjmH&&5Tbh^tOx5Y75j^s$H$Z2dlE>;1Ms!|i|=WIY$yDSup1-41ePNosM4 zUP(nsfHxzP2m`7gVIBba5f#844e~L%R%FXTK12YJli*sB{0lOHivhPI5hm;bG7(N@ RWdq4D1L0;M{RqTi0066#NEQG9 literal 0 HcmV?d00001 diff --git a/dev/com.ibm.ws.kernel.metatype.helper_fat/publish/files/unmonitored_fileset/server.xml b/dev/com.ibm.ws.kernel.metatype.helper_fat/publish/files/unmonitored_fileset/server.xml new file mode 100755 index 00000000000..4e3f3950ad2 --- /dev/null +++ b/dev/com.ibm.ws.kernel.metatype.helper_fat/publish/files/unmonitored_fileset/server.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.metatype.helper_fat/publish/servers/com.ibm.ws.kernel.metatype.helperServer/.gitignore b/dev/com.ibm.ws.kernel.metatype.helper_fat/publish/servers/com.ibm.ws.kernel.metatype.helperServer/.gitignore new file mode 100644 index 00000000000..383c36189fb --- /dev/null +++ b/dev/com.ibm.ws.kernel.metatype.helper_fat/publish/servers/com.ibm.ws.kernel.metatype.helperServer/.gitignore @@ -0,0 +1,2 @@ +/dropins +/server.xml diff --git a/dev/com.ibm.ws.kernel.metatype.helper_fat/publish/servers/com.ibm.ws.kernel.metatype.helperServer/bootstrap.properties b/dev/com.ibm.ws.kernel.metatype.helper_fat/publish/servers/com.ibm.ws.kernel.metatype.helperServer/bootstrap.properties new file mode 100755 index 00000000000..9af719cbc7a --- /dev/null +++ b/dev/com.ibm.ws.kernel.metatype.helper_fat/publish/servers/com.ibm.ws.kernel.metatype.helperServer/bootstrap.properties @@ -0,0 +1,5 @@ +bootstrap.include=../testports.properties +# Trace format (basic or enhanced or advanced) +com.ibm.ws.logging.trace.format=advanced +# Trace settings string - this string enables all trace +com.ibm.ws.logging.trace.specification=*=info:com.ibm.ws.kernel.metatype.helper.internal.FilesetImpl=all=enabled:com.ibm.ws.kernel.filemonitor.internal.CoreServiceImpl=all=enabled:com.ibm.ws.kernel.filemonitor.internal.MonitorHolder=all=enabled:logservice=all=enabled \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.metatype.helper_fat/publish/shared/config/com.ibm.ws.kernel.metatype.helperServer.xml b/dev/com.ibm.ws.kernel.metatype.helper_fat/publish/shared/config/com.ibm.ws.kernel.metatype.helperServer.xml new file mode 100755 index 00000000000..2a8534bc0a4 --- /dev/null +++ b/dev/com.ibm.ws.kernel.metatype.helper_fat/publish/shared/config/com.ibm.ws.kernel.metatype.helperServer.xml @@ -0,0 +1,12 @@ + + + + + + servlet-3.0 + filesetfatlibertyinternals-1.0 + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.metatype.helper_fat/publish/shared/resources/fileset_test_bundles/repo.xml b/dev/com.ibm.ws.kernel.metatype.helper_fat/publish/shared/resources/fileset_test_bundles/repo.xml new file mode 100755 index 00000000000..e69de29bb2d diff --git a/dev/com.ibm.ws.kernel.metatype.helper_fat/publish/shared/resources/fileset_test_bundles/test.txt b/dev/com.ibm.ws.kernel.metatype.helper_fat/publish/shared/resources/fileset_test_bundles/test.txt new file mode 100755 index 00000000000..e69de29bb2d diff --git a/dev/com.ibm.ws.kernel.metatype.helper_fat/publish/shared/resources/fileset_test_bundles/test1.jar b/dev/com.ibm.ws.kernel.metatype.helper_fat/publish/shared/resources/fileset_test_bundles/test1.jar new file mode 100755 index 00000000000..e69de29bb2d diff --git a/dev/com.ibm.ws.kernel.metatype.helper_fat/publish/shared/resources/fileset_test_bundles/test2.jar b/dev/com.ibm.ws.kernel.metatype.helper_fat/publish/shared/resources/fileset_test_bundles/test2.jar new file mode 100755 index 00000000000..e69de29bb2d diff --git a/dev/com.ibm.ws.kernel.metatype.helper_fat/publish/shared/resources/fileset_test_bundles/test_subfolder/test4.jar b/dev/com.ibm.ws.kernel.metatype.helper_fat/publish/shared/resources/fileset_test_bundles/test_subfolder/test4.jar new file mode 100755 index 00000000000..e69de29bb2d diff --git a/dev/com.ibm.ws.kernel.metatype.helper_fat/test-applications/fileset/resources/WEB-INF/web.xml b/dev/com.ibm.ws.kernel.metatype.helper_fat/test-applications/fileset/resources/WEB-INF/web.xml new file mode 100755 index 00000000000..b942041fd65 --- /dev/null +++ b/dev/com.ibm.ws.kernel.metatype.helper_fat/test-applications/fileset/resources/WEB-INF/web.xml @@ -0,0 +1,22 @@ + + + + + fileset + This is a servlet designed to exercise Fileset functionality. + + + + Fileset Servlet + Fileset Servlet + + com.ibm.ws.kernel.metatype.helper.test.app.FilesetTestServlet + + + + + + Fileset Servlet + /* + + diff --git a/dev/com.ibm.ws.kernel.metatype.helper_fat/test-applications/fileset/src/com/ibm/ws/kernel/metatype/helper/test/app/FilesetTestServlet.java b/dev/com.ibm.ws.kernel.metatype.helper_fat/test-applications/fileset/src/com/ibm/ws/kernel/metatype/helper/test/app/FilesetTestServlet.java new file mode 100755 index 00000000000..737225d9434 --- /dev/null +++ b/dev/com.ibm.ws.kernel.metatype.helper_fat/test-applications/fileset/src/com/ibm/ws/kernel/metatype/helper/test/app/FilesetTestServlet.java @@ -0,0 +1,82 @@ +package com.ibm.ws.kernel.metatype.helper.test.app; + +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; + +import javax.servlet.Servlet; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.osgi.framework.BundleContext; +import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.ServiceReference; + +import com.ibm.wsspi.config.Fileset; + +public class FilesetTestServlet extends HttpServlet { + + private static final long serialVersionUID = 2268417347748420049L; + + // Hacky way to get a BundleContext so we can check and use services... ick! + BundleContext context = FrameworkUtil.getBundle(Servlet.class).getBundleContext(); + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + PrintWriter writer = resp.getWriter(); + resp.setStatus(HttpServletResponse.SC_OK); + resp.setContentType("text/plain"); + writer.println("This is Fileset servlet."); + + String test = req.getQueryString(); + + try { + if (test != null) { + if (test.equals("Service")) { + testFilesetServiceRegistered(writer); + } else if (test.equals("Files")) { + printFilesetFiles(writer); + } + } + } catch (Exception e) { + e.printStackTrace(writer); + } finally { + writer.flush(); + writer.close(); + } + } + + private void testFilesetServiceRegistered(PrintWriter writer) throws Exception { + Collection> filesets = context.getServiceReferences(Fileset.class, "(id=testFileset)"); + + // output how many filesets we found + writer.println("Found " + filesets.size() + " fileset service."); + } + + private void printFilesetFiles(PrintWriter writer) throws Exception { + Collection> filesets = context.getServiceReferences(Fileset.class, "(id=testFileset)"); + for (ServiceReference filesetRef : filesets) { + Fileset fset = null; + try { + fset = context.getService(filesetRef); + Collection files = fset.getFileset(); + ArrayList sortedFileNames = new ArrayList(files.size()); + for (File f : files) { + sortedFileNames.add(f.getName()); + } + Collections.sort(sortedFileNames); + for (String name : sortedFileNames) { + writer.println("Fileset contained file: " + name); + } + } finally { + if (fset != null) + context.ungetService(filesetRef); + } + } + } +} diff --git a/dev/com.ibm.ws.kernel.metatype.helper_test/.classpath b/dev/com.ibm.ws.kernel.metatype.helper_test/.classpath new file mode 100644 index 00000000000..bd880329225 --- /dev/null +++ b/dev/com.ibm.ws.kernel.metatype.helper_test/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/dev/com.ibm.ws.kernel.metatype.helper_test/.classpath.gradle b/dev/com.ibm.ws.kernel.metatype.helper_test/.classpath.gradle new file mode 100644 index 00000000000..bd880329225 --- /dev/null +++ b/dev/com.ibm.ws.kernel.metatype.helper_test/.classpath.gradle @@ -0,0 +1,7 @@ + + + + + + + diff --git a/dev/com.ibm.ws.kernel.metatype.helper_test/.gitignore b/dev/com.ibm.ws.kernel.metatype.helper_test/.gitignore new file mode 100644 index 00000000000..5d00910f3a6 --- /dev/null +++ b/dev/com.ibm.ws.kernel.metatype.helper_test/.gitignore @@ -0,0 +1 @@ +/coverage.ec diff --git a/dev/com.ibm.ws.kernel.metatype.helper_test/.project b/dev/com.ibm.ws.kernel.metatype.helper_test/.project new file mode 100755 index 00000000000..b4e6457ec4d --- /dev/null +++ b/dev/com.ibm.ws.kernel.metatype.helper_test/.project @@ -0,0 +1,23 @@ + + + com.ibm.ws.kernel.metatype.helper_test + + + + + + org.eclipse.jdt.core.javabuilder + + + + + bndtools.core.bndbuilder + + + + + + org.eclipse.jdt.core.javanature + bndtools.core.bndnature + + diff --git a/dev/com.ibm.ws.kernel.metatype.helper_test/.settings/org.eclipse.core.resources.prefs b/dev/com.ibm.ws.kernel.metatype.helper_test/.settings/org.eclipse.core.resources.prefs new file mode 100755 index 00000000000..25d9425fe34 --- /dev/null +++ b/dev/com.ibm.ws.kernel.metatype.helper_test/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,4 @@ +#Ant properties +#Automatically generated by the ant prepare.settings.files task +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/dev/com.ibm.ws.kernel.metatype.helper_test/.settings/org.eclipse.jdt.core.prefs b/dev/com.ibm.ws.kernel.metatype.helper_test/.settings/org.eclipse.jdt.core.prefs new file mode 100755 index 00000000000..72a0b4c067c --- /dev/null +++ b/dev/com.ibm.ws.kernel.metatype.helper_test/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,281 @@ +#Ant properties +#Automatically generated by the ant prepare.settings.files task +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.6 +org.eclipse.jdt.core.formatter.align_type_members_on_columns=false +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=0 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=18 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=2 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=2 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=18 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=2 +org.eclipse.jdt.core.formatter.alignment_for_assignment=0 +org.eclipse.jdt.core.formatter.alignment_for_binary_expression=18 +org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=0 +org.eclipse.jdt.core.formatter.alignment_for_enum_constants=16 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=18 +org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=18 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=18 +org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=0 +org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=20 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=4 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +org.eclipse.jdt.core.formatter.blank_lines_before_field=0 +org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 +org.eclipse.jdt.core.formatter.blank_lines_before_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 +org.eclipse.jdt.core.formatter.blank_lines_before_package=0 +org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 +org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 +org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false +org.eclipse.jdt.core.formatter.comment.format_block_comments=true +org.eclipse.jdt.core.formatter.comment.format_header=false +org.eclipse.jdt.core.formatter.comment.format_html=false +org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true +org.eclipse.jdt.core.formatter.comment.format_line_comments=false +org.eclipse.jdt.core.formatter.comment.format_source_code=true +org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true +org.eclipse.jdt.core.formatter.comment.indent_root_tags=true +org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert +org.eclipse.jdt.core.formatter.comment.line_length=180 +org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true +org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true +org.eclipse.jdt.core.formatter.compact_else_if=true +org.eclipse.jdt.core.formatter.continuation_indentation=4 +org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=4 +org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off +org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on +org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false +org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=false +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true +org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_empty_lines=false +org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true +org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true +org.eclipse.jdt.core.formatter.indentation.size=8 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert +org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.join_lines_in_comments=false +org.eclipse.jdt.core.formatter.join_wrapped_lines=false +org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false +org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false +org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false +org.eclipse.jdt.core.formatter.lineSplit=180 +org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=true +org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=true +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 +org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=false +org.eclipse.jdt.core.formatter.tabulation.char=space +org.eclipse.jdt.core.formatter.tabulation.size=4 +org.eclipse.jdt.core.formatter.use_on_off_tags=true +org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false +org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true +org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true diff --git a/dev/com.ibm.ws.kernel.metatype.helper_test/.settings/org.eclipse.jdt.ui.prefs b/dev/com.ibm.ws.kernel.metatype.helper_test/.settings/org.eclipse.jdt.ui.prefs new file mode 100755 index 00000000000..c92277a371a --- /dev/null +++ b/dev/com.ibm.ws.kernel.metatype.helper_test/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,62 @@ +#Ant properties +#Automatically generated by the ant prepare.settings.files task +eclipse.preferences.version=1 +editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true +org.eclipse.jdt.ui.ignorelowercasenames=true +org.eclipse.jdt.ui.importorder=java;javax;org;com; +org.eclipse.jdt.ui.javadoc=true +org.eclipse.jdt.ui.ondemandthreshold=99 +org.eclipse.jdt.ui.staticondemandthreshold=99 +org.eclipse.jdt.ui.text.custom_code_templates= +sp_cleanup.add_default_serial_version_id=true +sp_cleanup.add_generated_serial_version_id=false +sp_cleanup.add_missing_annotations=true +sp_cleanup.add_missing_deprecated_annotations=true +sp_cleanup.add_missing_methods=false +sp_cleanup.add_missing_nls_tags=false +sp_cleanup.add_missing_override_annotations=true +sp_cleanup.add_missing_override_annotations_interface_methods=true +sp_cleanup.add_serial_version_id=false +sp_cleanup.always_use_blocks=true +sp_cleanup.always_use_parentheses_in_expressions=false +sp_cleanup.always_use_this_for_non_static_field_access=false +sp_cleanup.always_use_this_for_non_static_method_access=false +sp_cleanup.convert_to_enhanced_for_loop=false +sp_cleanup.correct_indentation=false +sp_cleanup.format_source_code=true +sp_cleanup.format_source_code_changes_only=false +sp_cleanup.make_local_variable_final=false +sp_cleanup.make_parameters_final=false +sp_cleanup.make_private_fields_final=true +sp_cleanup.make_type_abstract_if_missing_method=false +sp_cleanup.make_variable_declarations_final=true +sp_cleanup.never_use_blocks=false +sp_cleanup.never_use_parentheses_in_expressions=true +sp_cleanup.on_save_use_additional_actions=true +sp_cleanup.organize_imports=true +sp_cleanup.qualify_static_field_accesses_with_declaring_class=false +sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_with_declaring_class=false +sp_cleanup.qualify_static_method_accesses_with_declaring_class=false +sp_cleanup.remove_private_constructors=true +sp_cleanup.remove_trailing_whitespaces=true +sp_cleanup.remove_trailing_whitespaces_all=true +sp_cleanup.remove_trailing_whitespaces_ignore_empty=false +sp_cleanup.remove_unnecessary_casts=true +sp_cleanup.remove_unnecessary_nls_tags=true +sp_cleanup.remove_unused_imports=true +sp_cleanup.remove_unused_local_variables=false +sp_cleanup.remove_unused_private_fields=true +sp_cleanup.remove_unused_private_members=false +sp_cleanup.remove_unused_private_methods=true +sp_cleanup.remove_unused_private_types=true +sp_cleanup.sort_members=false +sp_cleanup.sort_members_all=false +sp_cleanup.use_blocks=false +sp_cleanup.use_blocks_only_for_return_and_throw=false +sp_cleanup.use_parentheses_in_expressions=false +sp_cleanup.use_this_for_non_static_field_access=false +sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true +sp_cleanup.use_this_for_non_static_method_access=false +sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true diff --git a/dev/com.ibm.ws.kernel.metatype.helper_test/bnd.bnd b/dev/com.ibm.ws.kernel.metatype.helper_test/bnd.bnd new file mode 100755 index 00000000000..3d59e7ca35f --- /dev/null +++ b/dev/com.ibm.ws.kernel.metatype.helper_test/bnd.bnd @@ -0,0 +1,20 @@ +-include= ~../cnf/resources/bnd/liberty-release.props +bVersion=1.0 + +-nobundles=true + +src: \ + unittest/src + +-buildpath: \ + ${javac.bootclasspath.java6}, \ + ../build.sharedResources/lib/junit/old/junit.jar;version=file, \ + ../build.sharedResources/lib/ws-junit/ws-junit.jar;version=file, \ + ../build.sharedResources/lib/hamcrest-all.jar;version=file, \ + ../build.sharedResources/lib/jmock/old/jmock-junit4.jar;version=file, \ + ../build.sharedResources/lib/jmock/old/jmock.jar;version=file, \ + com.ibm.websphere.org.osgi.core.6.0.0;version=latest,\ + com.ibm.websphere.org.osgi.service.component.1.3.0;version=latest, \ + com.ibm.websphere.appserver.spi.kernel.filemonitor;version=latest,\ + com.ibm.websphere.appserver.spi.kernel.service;version=latest,\ + com.ibm.ws.kernel.metatype.helper;version=latest diff --git a/dev/com.ibm.ws.kernel.metatype.helper_test/bnd.bnd.gradle b/dev/com.ibm.ws.kernel.metatype.helper_test/bnd.bnd.gradle new file mode 100755 index 00000000000..3d59e7ca35f --- /dev/null +++ b/dev/com.ibm.ws.kernel.metatype.helper_test/bnd.bnd.gradle @@ -0,0 +1,20 @@ +-include= ~../cnf/resources/bnd/liberty-release.props +bVersion=1.0 + +-nobundles=true + +src: \ + unittest/src + +-buildpath: \ + ${javac.bootclasspath.java6}, \ + ../build.sharedResources/lib/junit/old/junit.jar;version=file, \ + ../build.sharedResources/lib/ws-junit/ws-junit.jar;version=file, \ + ../build.sharedResources/lib/hamcrest-all.jar;version=file, \ + ../build.sharedResources/lib/jmock/old/jmock-junit4.jar;version=file, \ + ../build.sharedResources/lib/jmock/old/jmock.jar;version=file, \ + com.ibm.websphere.org.osgi.core.6.0.0;version=latest,\ + com.ibm.websphere.org.osgi.service.component.1.3.0;version=latest, \ + com.ibm.websphere.appserver.spi.kernel.filemonitor;version=latest,\ + com.ibm.websphere.appserver.spi.kernel.service;version=latest,\ + com.ibm.ws.kernel.metatype.helper;version=latest diff --git a/dev/com.ibm.ws.kernel.metatype.helper_test/build-unittest.xml b/dev/com.ibm.ws.kernel.metatype.helper_test/build-unittest.xml new file mode 100755 index 00000000000..20cf72888c1 --- /dev/null +++ b/dev/com.ibm.ws.kernel.metatype.helper_test/build-unittest.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.kernel.metatype.helper_test/build.gradle b/dev/com.ibm.ws.kernel.metatype.helper_test/build.gradle new file mode 100644 index 00000000000..e69de29bb2d diff --git a/dev/com.ibm.ws.kernel.metatype.helper_test/delivery.sets b/dev/com.ibm.ws.kernel.metatype.helper_test/delivery.sets new file mode 100755 index 00000000000..674398425a0 --- /dev/null +++ b/dev/com.ibm.ws.kernel.metatype.helper_test/delivery.sets @@ -0,0 +1 @@ +SLE diff --git a/dev/com.ibm.ws.kernel.metatype.helper_test/unittest/src/com/ibm/wsspi/config/internal/AbstractFilesetTestHelper.java b/dev/com.ibm.ws.kernel.metatype.helper_test/unittest/src/com/ibm/wsspi/config/internal/AbstractFilesetTestHelper.java new file mode 100755 index 00000000000..2bfb468024f --- /dev/null +++ b/dev/com.ibm.ws.kernel.metatype.helper_test/unittest/src/com/ibm/wsspi/config/internal/AbstractFilesetTestHelper.java @@ -0,0 +1,187 @@ +package com.ibm.wsspi.config.internal; + +import java.io.File; +import java.net.URI; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.UUID; + +import junit.framework.Assert; + +import com.ibm.wsspi.config.Fileset; +import com.ibm.wsspi.config.internal.FilesetImpl; +import com.ibm.wsspi.config.internal.ConfigTypeConstants.FilesetAttribute; +import com.ibm.wsspi.kernel.filemonitor.FileMonitor; +import com.ibm.wsspi.kernel.service.location.WsLocationAdmin; +import com.ibm.wsspi.kernel.service.location.WsResource; + +public class AbstractFilesetTestHelper { + + static protected void setLocationService(FilesetImpl fset) { + fset.setLocationAdmin(new WsLocationAdmin() { + + @Override + public WsResource addLocation(String fileName, String symbolicName) { + // TODO Auto-generated method stub + return null; + } + + @Override + public WsResource asResource(File file, boolean isFile) { + // TODO Auto-generated method stub + return null; + } + + @Override + public File getBundleFile(Object caller, String relativeBundlePath) { + // TODO Auto-generated method stub + return null; + } + + @Override + public WsResource getRuntimeResource(String relativeRuntimePath) { + // TODO Auto-generated method stub + return null; + } + + @Override + public UUID getServerId() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getServerName() { + // TODO Auto-generated method stub + return null; + } + + @Override + public WsResource getServerOutputResource(String relativeServerPath) { + // TODO Auto-generated method stub + return null; + } + + @Override + public WsResource getServerResource(String relativeServerPath) { + // TODO Auto-generated method stub + return null; + } + + @Override + public WsResource getServerWorkareaResource(String relativeServerWorkareaPath) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Iterator matchResource(String resourceGroupName, String resourceRegex, int limit) { + // TODO Auto-generated method stub + return null; + } + + @Override + public String printLocations(boolean useLineBreaks) { + // TODO Auto-generated method stub + return null; + } + + @Override + public WsResource resolveResource(String resourceURI) { + // TODO Auto-generated method stub + return null; + } + + @Override + public WsResource resolveResource(URI resourceURI) { + // TODO Auto-generated method stub + return null; + } + + @Override + public String resolveString(String string) { + // TODO Auto-generated method stub + return ""; + } + + }); + } + + static Map getDefaultAttributes() { + return getAttributes(null, null, null, null, null); + } + + protected static Map getAttributes(String dir, Boolean sensitive, String includes, + String excludes, Long scanInterval) { + Map attrs = new HashMap(); + attrs.put("id", "FilesetID"); + if (dir == null) + dir = "."; + attrs.put(FilesetAttribute.dir.toString(), dir); + if (sensitive == null) + sensitive = true; + attrs.put(FilesetAttribute.caseSensitive.toString(), sensitive); + if (includes == null) + includes = "*"; + attrs.put(FilesetAttribute.includes.toString(), includes); + if (excludes == null) + excludes = ""; + attrs.put(FilesetAttribute.excludes.toString(), excludes); + + if (scanInterval != null) { + attrs.put(FilesetAttribute.scanInterval.toString(), scanInterval); + } + return attrs; + } + + static void setAttributes(FilesetImpl fset, String dir, Boolean sensitive, String includes, String excludes) { + setAttributes(fset, dir, sensitive, includes, excludes, null); + } + + static void setAttributes(FilesetImpl fset, String dir, Boolean sensitive, String includes, String excludes, Long scanInterval) { + Map props = fset.modified(getAttributes(dir, sensitive, includes, excludes, scanInterval)); + Collection dirs = (Collection) props.get(FileMonitor.MONITOR_DIRECTORIES); + Assert.assertEquals("wrong size", 1, dirs.size()); + Assert.assertEquals("wrong dir", fset.getDir(), dirs.iterator().next()); + + Object interval = props.get(FileMonitor.MONITOR_INTERVAL); + if (scanInterval == null || scanInterval.equals(FilesetImpl.MONITOR_OFF)) { + Assert.assertNull("interval present: " + interval, interval); + } else { + Assert.assertEquals("wrong interval", scanInterval, interval); + } + + Collection files = Collections.emptyList(); + Collection emptyFiles = Collections.emptyList(); + fset.onBaseline(emptyFiles); + File dirFile = new File(dir); + if (dirFile.exists()) { + files = recursivelyListFiles(dirFile); + } + // mock the effect of the FileMonitor + // call initComplete with the + // files we found in the dir + fset.onBaseline(files); + } + + static void setDefaultAttributes(Fileset fset) { + ((FilesetImpl) fset).modified(getDefaultAttributes()); + } + + static Collection recursivelyListFiles(File dir) { + Collection files = new ArrayList(); + for (File f : dir.listFiles()) { + if (f.isDirectory()) { + files.addAll(recursivelyListFiles(f)); + } else { + files.add(f); + } + } + return files; + } + +} diff --git a/dev/com.ibm.ws.kernel.metatype.helper_test/unittest/src/com/ibm/wsspi/config/internal/FilesetNameFilterTest.java b/dev/com.ibm.ws.kernel.metatype.helper_test/unittest/src/com/ibm/wsspi/config/internal/FilesetNameFilterTest.java new file mode 100755 index 00000000000..1ac27653088 --- /dev/null +++ b/dev/com.ibm.ws.kernel.metatype.helper_test/unittest/src/com/ibm/wsspi/config/internal/FilesetNameFilterTest.java @@ -0,0 +1,346 @@ +package com.ibm.wsspi.config.internal; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.FilenameFilter; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import org.jmock.Expectations; +import org.jmock.Mockery; +import org.jmock.integration.junit4.JUnit4Mockery; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.osgi.framework.BundleContext; +import org.osgi.service.component.ComponentContext; + +import com.ibm.wsspi.config.internal.FilesetImpl; +import com.ibm.wsspi.config.internal.FilesetImpl.FilterType; + +/** + * The fileset configuration element uses include and exclude filters to provide + * a set of file names. This class provides tests to check the behaviour of the + * filters is correct for many different cases. + * + * The implementation of the {@link FilenameFilter} is a private class inside + * the {@link FilesetImpl} so reflection is used to access the methods required + * to test them, primarily the accept method. + */ +public class FilesetNameFilterTest extends AbstractFilesetTestHelper { + + // the basedir we will use + private static final File DIR = new File("test" + File.separator + "path"); + // a sub directory of basedir + private static final File SUB_DIR = new File(DIR, "sub"); + // another level of sub directory + private static final File SUB2_DIR = new File(SUB_DIR, "sub2"); + // an alternate dir to test files from a different dir + private static final File ALT_DIR = new File("some" + File.separator + "otherpath"); + + // create a Fileset with the default attributes as we will set them as + // required in the tests + static FilesetImpl fset = new FilesetImpl(); + + // The reflective filter which delegates to the real (private) object + // inside the FilesetImpl + private static ReflectiveFilter filter; + + private final Mockery context = new JUnit4Mockery(); + private ComponentContext mockComponentContext; + + @BeforeClass + public static void setupReflectiveFields() throws Exception { + Field filterField = fset.getClass().getDeclaredField("filter"); + filterField.setAccessible(true); + filter = new ReflectiveFilter(filterField.get(fset)); + + } + + @Before + public void setup() throws Exception { + setLocationService(fset); + // clear the filters before each test + filter.clearFilters(); + // set the dir on the fileset + mockComponentContext = context.mock(ComponentContext.class); + fset.activate(mockComponentContext, getAttributes(DIR.toString(), null, null, null, null)); + + final BundleContext mockBundleContext = context.mock(BundleContext.class); + context.checking(new Expectations() { + { + allowing(mockComponentContext).getBundleContext(); + will(returnValue(mockBundleContext)); + allowing(mockComponentContext).getProperties(); + ignoring(mockBundleContext); + } + }); + + } + + @Test + public void testDefaultAccept() throws Exception { + // the default include is "*" which applies to anything in the same + // directory, we have to add it here even though it is the default, + // because we are just testing a filter object not a Fileset one + filter.addFilter(FilterType.INCLUDE, "*"); + assertTrue(filter.accept(DIR, "testFile")); + assertTrue(filter.accept(DIR, "testFile2")); + assertTrue(filter.accept(DIR, "anything")); + // if the directory is different it shouldn't be included + assertFalse(filter.accept(ALT_DIR, "anything")); + // even a sub folder shouldn't be accepted + assertFalse(filter.accept(SUB_DIR, "anything")); + } + + @Test + public void testDotEscape() throws Exception { + filter.addFilter(FilterType.INCLUDE, "testFile.txt"); + // check that we get true for a file name with a . + assertTrue(filter.accept(DIR, "testFile.txt")); + // check that we get false for a file name with another + // character in place of the . (because regex . is any character) + assertFalse(filter.accept(DIR, "testFile,txt")); + } + + @Test + public void testCaseSensitiveDefault() throws Exception { + filter.addFilter(FilterType.INCLUDE, "testfile"); + // lower case OK + assertTrue(filter.accept(DIR, "testfile")); + // upper case F should fail + assertFalse(filter.accept(DIR, "testFile")); + } + + @Test + public void testCaseInsensitive() throws Exception { + try { + setAttributes(fset, DIR.toString(), false, null, null); + filter.addFilter(FilterType.INCLUDE, "testfile"); + // lower case OK + assertTrue(filter.accept(DIR, "testfile")); + // upper case F should pass + assertTrue(filter.accept(DIR, "testFile")); + } finally { + // return back to the default for other tests + setAttributes(fset, DIR.toString(), true, null, null); + } + } + + @Test + public void testWildcardIncludeAccept() throws Exception { + filter.addFilter(FilterType.INCLUDE, "*"); + // should get anything in the dir + assertTrue(filter.accept(DIR, "testFile")); + // should not get a file from the sub dir + assertFalse(filter.accept(SUB_DIR, "testFile")); + } + + @Test + public void testNameIncludeAccept() throws Exception { + filter.addFilter(FilterType.INCLUDE, "testFile"); + assertTrue(filter.accept(DIR, "testFile")); + } + + @Test + public void testFullpathIncludeAccept() throws Exception { + filter.addFilter(FilterType.INCLUDE, "sub/testFile"); + assertTrue(filter.accept(SUB_DIR, "testFile")); + } + + @Test + public void testWildcardExcludeAccept() throws Exception { + filter.addFilter(FilterType.EXCLUDE, "*"); + assertFalse(filter.accept(DIR, "testFile")); + } + + @Test + public void testNameExcludeAccept() throws Exception { + filter.addFilter(FilterType.EXCLUDE, "testFile"); + assertFalse(filter.accept(DIR, "testFile")); + } + + @Test + public void testFullpathExcludeAccept() throws Exception { + filter.addFilter(FilterType.EXCLUDE, "sub/testFile"); + assertFalse(filter.accept(SUB_DIR, "testFile")); + } + + @Test + public void testSpaceSeparatedAccept() throws Exception { + filter.addFilter(FilterType.INCLUDE, "testFile testFile2"); + assertTrue(filter.accept(DIR, "testFile")); + assertTrue(filter.accept(DIR, "testFile2")); + } + + @Test + public void testCommaSeparatedAccept() throws Exception { + filter.addFilter(FilterType.INCLUDE, "testFile,testFile2"); + assertTrue(filter.accept(DIR, "testFile")); + assertTrue(filter.accept(DIR, "testFile2")); + } + + @Test + public void testCommaAndSpaceSeparatedAccept() throws Exception { + filter.addFilter(FilterType.INCLUDE, "testFile , testFile2"); + assertTrue(filter.accept(DIR, "testFile")); + assertTrue(filter.accept(DIR, "testFile2")); + } + + @Test + public void testCommaAndSpaceSeparatedAccept2() throws Exception { + filter.addFilter(FilterType.INCLUDE, "testFile , testFile2"); + assertTrue(filter.accept(DIR, "testFile")); + assertTrue(filter.accept(DIR, "testFile2")); + } + + @Test + public void testExcessSpacesAccept() throws Exception { + filter.addFilter(FilterType.INCLUDE, " testFile "); + assertTrue(filter.accept(DIR, "testFile")); + } + + @Test + public void testIncludeAndExcludeAccept() throws Exception { + filter.addFilter(FilterType.INCLUDE, "testFile"); + filter.addFilter(FilterType.EXCLUDE, "testFile2"); + assertTrue(filter.accept(DIR, "testFile")); + assertFalse(filter.accept(DIR, "testFile2")); + } + + @Test + public void testNameEmbeddedWildCard() throws Exception { + filter.addFilter(FilterType.INCLUDE, "test*"); + assertTrue(filter.accept(DIR, "testFile")); + assertFalse(filter.accept(DIR, "filetestFile")); + assertFalse(filter.accept(DIR, "")); + } + + @Test + public void testNameLeadingWildCard() throws Exception { + filter.addFilter(FilterType.INCLUDE, "*TestFile"); + assertTrue(filter.accept(DIR, "fileTestFile")); + // require at least one character for star + assertFalse(filter.accept(DIR, "TestFile")); + // check that path boundaries aren't crossed + assertFalse(filter.accept(SUB_DIR, "fileTestFile")); + assertFalse(filter.accept(SUB2_DIR, "fileTestFile")); + assertFalse(filter.accept(DIR, "filetestFile")); + } + + @Test + public void testPathEmbeddedWildCard() throws Exception { + filter.addFilter(FilterType.INCLUDE, "./*/testFile"); + // /test/path/testFile (will be false because there is no folder between + // . and testFile + assertFalse(filter.accept(DIR, "testFile")); + assertTrue(filter.accept(SUB_DIR, "testFile")); + assertFalse(filter.accept(ALT_DIR, "testFile")); + assertFalse(filter.accept(SUB2_DIR, "testFile")); + } + + @Test + public void testLeadingPathEmbeddedWildCard() throws Exception { + filter.addFilter(FilterType.INCLUDE, "*/testFile"); + assertFalse(filter.accept(DIR, "testFile")); + assertTrue(filter.accept(SUB_DIR, "testFile")); + assertFalse(filter.accept(ALT_DIR, "testFile")); + assertFalse(filter.accept(SUB2_DIR, "testFile")); + } + + @Test + public void testMultiplePathEmbeddedWildCards() throws Exception { + filter.addFilter(FilterType.INCLUDE, "./*/*/testFile"); + assertFalse(filter.accept(DIR, "testFile")); + assertFalse(filter.accept(SUB_DIR, "testFile")); + assertFalse(filter.accept(ALT_DIR, "testFile")); + assertTrue(filter.accept(SUB2_DIR, "testFile")); + } + + @Test + public void testPathAndNameEmbeddedWildCards() throws Exception { + filter.addFilter(FilterType.INCLUDE, "./*/test*"); + assertFalse(filter.accept(DIR, "testFile")); + assertTrue(filter.accept(SUB_DIR, "testFile")); + assertFalse(filter.accept(DIR, "filetestFile")); + assertFalse(filter.accept(SUB_DIR, "filetestFile")); + } + + @Test + public void testRecursiveWildCard() throws Exception { + filter.addFilter(FilterType.INCLUDE, "./**/testFile"); + assertFalse(filter.accept(DIR, "testFile")); + assertTrue(filter.accept(SUB_DIR, "testFile")); + assertTrue(filter.accept(SUB2_DIR, "testFile")); + assertFalse(filter.accept(ALT_DIR, "testFile")); + } + + @Test + public void testLeadingRecursiveWildCard() throws Exception { + filter.addFilter(FilterType.INCLUDE, "**/testFile"); + assertFalse(filter.accept(DIR, "testFile")); + assertTrue(filter.accept(SUB_DIR, "testFile")); + assertTrue(filter.accept(SUB2_DIR, "testFile")); + assertFalse(filter.accept(ALT_DIR, "testFile")); + } + + @Test + public void testOnlyRecursiveWildCard() throws Exception { + filter.addFilter(FilterType.INCLUDE, "**"); + assertTrue(filter.accept(DIR, "testFile")); + assertTrue(filter.accept(SUB_DIR, "testFile")); + assertTrue(filter.accept(SUB2_DIR, "testFile")); + assertFalse(filter.accept(ALT_DIR, "testFile")); + } + + @Test + public void testComplexWildCards() throws Exception { + filter.addFilter(FilterType.INCLUDE, "**/some/**/path/*/*test*.*"); + assertFalse(filter.accept(DIR, "testFile")); + assertTrue(filter.accept(new File("test/path/sub1/sub2/some/sub3/sub4/sub5/path/dir"), "AtestfileB.txt")); + assertFalse(filter.accept(new File("test/path/sub1/sub2/some/sub3/sub4/sub5/path/dir"), "testfileB")); + assertFalse(filter.accept(new File("test/path/sub1/sub2/some/sub3/sub4/sub5/path/dir"), "AtestfileB")); + assertFalse(filter.accept(new File("some/path/dir"), "AtestfileB.txt")); + assertFalse(filter.accept(new File("test/path/sub1/sub2/some/sub3/sub4/sub5/path"), "AtestfileB.txt")); + } + + /** + * This class uses reflection to delegate to the real filter Object which is + * privately constructed and used inside the FilesetImpl. + * + */ + private static final class ReflectiveFilter { + private final Object realFilter; + private final Method clearFiltersMethod; + private final Method addFilterMethod; + private final Method acceptMethod; + + ReflectiveFilter(Object realFilter) throws SecurityException, NoSuchMethodException { + this.realFilter = realFilter; + clearFiltersMethod = realFilter.getClass().getDeclaredMethod("clearFilters", new Class[0]); + clearFiltersMethod.setAccessible(true); + addFilterMethod = realFilter.getClass().getDeclaredMethod("addFilter", FilterType.class, String.class); + addFilterMethod.setAccessible(true); + acceptMethod = realFilter.getClass().getDeclaredMethod("accept", File.class, String.class); + acceptMethod.setAccessible(true); + + } + + public void clearFilters() throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { + clearFiltersMethod.invoke(realFilter, new Object[0]); + } + + public void addFilter(FilterType type, String filter) throws IllegalArgumentException, IllegalAccessException, + InvocationTargetException { + addFilterMethod.invoke(realFilter, type, filter); + } + + public boolean accept(File dir, String name) throws IllegalArgumentException, IllegalAccessException, + InvocationTargetException { + return (Boolean) acceptMethod.invoke(realFilter, dir, name); + } + } +} diff --git a/dev/com.ibm.ws.kernel.metatype.helper_test/unittest/src/com/ibm/wsspi/config/internal/FilesetTest.java b/dev/com.ibm.ws.kernel.metatype.helper_test/unittest/src/com/ibm/wsspi/config/internal/FilesetTest.java new file mode 100755 index 00000000000..527753b9b49 --- /dev/null +++ b/dev/com.ibm.ws.kernel.metatype.helper_test/unittest/src/com/ibm/wsspi/config/internal/FilesetTest.java @@ -0,0 +1,238 @@ +package com.ibm.wsspi.config.internal; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import org.jmock.Expectations; +import org.jmock.Mockery; +import org.jmock.integration.junit4.JUnit4Mockery; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.osgi.framework.BundleContext; +import org.osgi.service.component.ComponentContext; + +import com.ibm.wsspi.config.internal.FilesetImpl; + +public class FilesetTest extends AbstractFilesetTestHelper { + + // the basedir we will use + private static final File DIR = new File("./test"); + private static final File NODIR = new File("./notADir"); + private static final File TEST_FILE = new File(DIR, "testfile.txt"); + private static final File TEST_FILE_2 = new File(DIR, "testfile2"); + private static final Collection TEST_FILES = new ArrayList(); + private static final Collection EMPTY_FILESET = Collections.emptySet(); + + static { + TEST_FILES.add(TEST_FILE); + TEST_FILES.add(TEST_FILE_2); + } + + // create a Fileset with no attributes as we will set them as required in + // the tests + FilesetImpl fset; + + private final Mockery context = new JUnit4Mockery(); + private ComponentContext mockComponentContext; + + private static void recursiveDelete(File dir) { + if (dir.exists()) { + for (File f : dir.listFiles()) { + if (f.isDirectory()) { + recursiveDelete(f); + } else { + f.delete(); + } + } + dir.delete(); + } + } + + @BeforeClass + public static void setUpFiles() throws Exception { + // clean up first, just in case clean up failed + // or was interrupted previously + cleanUpFiles(); + // set up a directory with some test files in + DIR.mkdir(); + for (File test_file : TEST_FILES) { + test_file.createNewFile(); + } + } + + @AfterClass + public static void cleanUpFiles() throws Exception { + // recursively remove the test directory + recursiveDelete(DIR); + } + + @Before + public void setUp() throws Exception { + fset = new FilesetImpl(); + setLocationService(fset); + mockComponentContext = context.mock(ComponentContext.class); + final BundleContext mockBundleContext = context.mock(BundleContext.class); + context.checking(new Expectations() { + { + allowing(mockComponentContext).getBundleContext(); + will(returnValue(mockBundleContext)); + allowing(mockComponentContext).getProperties(); + ignoring(mockBundleContext); + } + }); + + fset.activate(mockComponentContext, getAttributes(DIR.getName(), null, null, null, null)); + setAttributes(fset, DIR.getName(), null, null, null); +// fset.initComplete(Collections.singleton(DIR)); + } + + private String getFilterFromCollection(Collection collection) { + Collection names = new ArrayList(collection.size()); + for (File f : collection) { + names.add(f.getName()); + } + + // turn the names collection into a ", " separated String + String filter = names.toString(); + // trim the [ and ] from the String + filter = filter.substring(1, filter.length() - 1); + return filter; + } + + private Collection getResolvedAndSortedNames(Collection files) throws Exception { + List fileAbsolutePaths = new ArrayList(files.size()); + for (File f : files) { + fileAbsolutePaths.add(f.getCanonicalPath()); + } + Collections.sort(fileAbsolutePaths); + return fileAbsolutePaths; + } + + private void assertFilesetsEqual(String msg, File expected, Collection actual) throws Exception { + assertFilesetsEqual(msg, Arrays.asList(new File[] { expected }), actual); + } + + private void assertFilesetsEqual(String msg, Collection expected, Collection actual) throws Exception { + assertEquals("Unexpected files returned", getResolvedAndSortedNames(expected), + getResolvedAndSortedNames(actual)); + } + + @Test + public void testSetDir() throws Exception { + // check that setDir has an effect and returns the expected files + setAttributes(fset, DIR.getName(), null, null, null); + assertFilesetsEqual("Unexpected files returned", TEST_FILES, fset.getFileset()); + // check that changing setDir changes the returned collection + setAttributes(fset, NODIR.getName(), null, null, null); + assertFilesetsEqual("Unexpected files returned", EMPTY_FILESET, fset.getFileset()); + } + + @Test + public void testSetCaseSensitive() throws Exception { + // the default filter is *, which isn't going to be case sensitive + // either way + // so set the includes filter to be the list of TEST_FILES + setAttributes(fset, DIR.getName(), true, getFilterFromCollection(TEST_FILES), null); + // check that it works as is + assertFilesetsEqual("Unexpected files returned", TEST_FILES, fset.getFileset()); + Collection wrongcaseFiles = Arrays.asList(new File[] { new File(DIR, "testFile.txt"), + new File(DIR, "testFile2") }); + // apply the wrong case filter + setAttributes(fset, DIR.getName(), true, getFilterFromCollection(wrongcaseFiles), null); + // check that no files come back for the wrong case + assertFilesetsEqual("Was not case sensitive when should have been", EMPTY_FILESET, fset.getFileset()); + // make it insensitive and check result + setAttributes(fset, DIR.getName(), false, getFilterFromCollection(wrongcaseFiles), null); + assertFilesetsEqual("Was case sensitive when should not have been", TEST_FILES, fset.getFileset()); + // return to sensitive and check + setAttributes(fset, DIR.getName(), true, getFilterFromCollection(wrongcaseFiles), null); + assertFilesetsEqual("Was not case sensitive when should have been", EMPTY_FILESET, fset.getFileset()); + } + + @Test + public void testSetIncludesAttribute() throws Exception { + setAttributes(fset, DIR.getName(), null, TEST_FILE.getName(), null); + assertFilesetsEqual("Inlcude filter was incorrectly applied", TEST_FILE, fset.getFileset()); + } + + @Test + public void testSetExcludesAttribute() throws Exception { + setAttributes(fset, DIR.getName(), null, null, TEST_FILE.getName()); + assertFilesetsEqual("Exlcude filter was incorrectly applied", TEST_FILE_2, fset.getFileset()); + } + + @Test + public void testGetFileset() throws Exception { + Collection files = fset.getFileset(); + assertNotNull(files); + assertFilesetsEqual("Unexpected files returned", TEST_FILES, fset.getFileset()); + } + + @Test + public void testNotifyFileChanged() throws Exception { + // check that nothing is returned for testfile3 + setAttributes(fset, DIR.getName(), null, "testfile3", null); + Collection retrieved = fset.getFileset(); + assertFilesetsEqual("No files should have been returned", EMPTY_FILESET, retrieved); + // change the contents of the DIR and notify that it was changed + File testFile3 = new File(DIR, "testfile3"); + testFile3.createNewFile(); + // when the disk contents change the FileMonitor service will call + // scanComplete(...) + // mock that call here with a new listing of the files in the DIR and + // remove the existing retrieved files + fset.onChange(recursivelyListFiles(new File(DIR.getName())), retrieved, EMPTY_FILESET); + // check that the fileset now contains the new file + /* + * assertNotSame("The cached fileset should have been refreshed", + * EMPTY_FILESET, fset.getFileset()); + */ + retrieved = fset.getFileset(); + assertFilesetsEqual("The new file should have been returned", testFile3, retrieved); + + testFile3.setLastModified(testFile3.lastModified() + 5000); + fset.onChange(EMPTY_FILESET, retrieved, EMPTY_FILESET); + retrieved = fset.getFileset(); + assertFilesetsEqual("The same file should have been returned", testFile3, retrieved); + + testFile3.delete(); + fset.onChange(EMPTY_FILESET, EMPTY_FILESET, retrieved); + retrieved = fset.getFileset(); + assertFilesetsEqual("No files should have been returned", EMPTY_FILESET, retrieved); + } + + @Test + public void testRecursion() throws Exception { + try { + File sub = new File(DIR, "some/sub/dir"); + sub.mkdirs(); + File subFile = new File(sub, "subfile.txt"); + subFile.createNewFile(); + + setAttributes(fset, DIR.getName(), null, "**/subfile.txt", null); + + assertFilesetsEqual("The sub directory file should have been returned", subFile, fset.getFileset()); + + } finally { + // delete the file we made so it doesn't influence + // other tests + recursiveDelete(new File(DIR, "some")); + } + } + + @Test + public void verifyProperties() { + setAttributes(fset, DIR.getName(), null, null, null, 0L); + setAttributes(fset, DIR.getName(), null, null, null, 1L); + setAttributes(fset, DIR.getName(), null, null, null, -5L); + } +} diff --git a/dev/com.ibm.ws.logging.hpel_fat/.classpath b/dev/com.ibm.ws.logging.hpel_fat/.classpath new file mode 100644 index 00000000000..c422489df40 --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/dev/com.ibm.ws.logging.hpel_fat/.classpath.gradle b/dev/com.ibm.ws.logging.hpel_fat/.classpath.gradle new file mode 100644 index 00000000000..c422489df40 --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/.classpath.gradle @@ -0,0 +1,7 @@ + + + + + + + diff --git a/dev/com.ibm.ws.logging.hpel_fat/.gitignore b/dev/com.ibm.ws.logging.hpel_fat/.gitignore new file mode 100644 index 00000000000..27e131e35a6 --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/.gitignore @@ -0,0 +1 @@ +/bootstrapping.properties diff --git a/dev/com.ibm.ws.logging.hpel_fat/.project b/dev/com.ibm.ws.logging.hpel_fat/.project new file mode 100755 index 00000000000..ff567ad067e --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/.project @@ -0,0 +1,23 @@ + + + com.ibm.ws.logging.hpel_fat + + + + + + org.eclipse.jdt.core.javabuilder + + + + + bndtools.core.bndbuilder + + + + + + org.eclipse.jdt.core.javanature + bndtools.core.bndnature + + diff --git a/dev/com.ibm.ws.logging.hpel_fat/.settings/org.eclipse.core.resources.prefs b/dev/com.ibm.ws.logging.hpel_fat/.settings/org.eclipse.core.resources.prefs new file mode 100755 index 00000000000..25d9425fe34 --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,4 @@ +#Ant properties +#Automatically generated by the ant prepare.settings.files task +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/dev/com.ibm.ws.logging.hpel_fat/.settings/org.eclipse.jdt.core.prefs b/dev/com.ibm.ws.logging.hpel_fat/.settings/org.eclipse.jdt.core.prefs new file mode 100755 index 00000000000..f48ecd6cc60 --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,280 @@ +#Ant properties +#Automatically generated by the ant prepare.settings.files task +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.6 +org.eclipse.jdt.core.formatter.align_type_members_on_columns=false +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=0 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=18 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=2 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=2 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=18 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=2 +org.eclipse.jdt.core.formatter.alignment_for_assignment=0 +org.eclipse.jdt.core.formatter.alignment_for_binary_expression=18 +org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=0 +org.eclipse.jdt.core.formatter.alignment_for_enum_constants=16 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=18 +org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=18 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=18 +org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=0 +org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=20 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=4 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +org.eclipse.jdt.core.formatter.blank_lines_before_field=0 +org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 +org.eclipse.jdt.core.formatter.blank_lines_before_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 +org.eclipse.jdt.core.formatter.blank_lines_before_package=0 +org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 +org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 +org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false +org.eclipse.jdt.core.formatter.comment.format_block_comments=true +org.eclipse.jdt.core.formatter.comment.format_header=false +org.eclipse.jdt.core.formatter.comment.format_html=false +org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true +org.eclipse.jdt.core.formatter.comment.format_line_comments=false +org.eclipse.jdt.core.formatter.comment.format_source_code=true +org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true +org.eclipse.jdt.core.formatter.comment.indent_root_tags=true +org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert +org.eclipse.jdt.core.formatter.comment.line_length=180 +org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true +org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true +org.eclipse.jdt.core.formatter.compact_else_if=true +org.eclipse.jdt.core.formatter.continuation_indentation=4 +org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=4 +org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off +org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on +org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false +org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=false +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true +org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_empty_lines=false +org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true +org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true +org.eclipse.jdt.core.formatter.indentation.size=8 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert +org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.join_lines_in_comments=false +org.eclipse.jdt.core.formatter.join_wrapped_lines=false +org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false +org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false +org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false +org.eclipse.jdt.core.formatter.lineSplit=180 +org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=true +org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=true +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 +org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=false +org.eclipse.jdt.core.formatter.tabulation.char=space +org.eclipse.jdt.core.formatter.tabulation.size=4 +org.eclipse.jdt.core.formatter.use_on_off_tags=true +org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false +org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true +org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true diff --git a/dev/com.ibm.ws.logging.hpel_fat/.settings/org.eclipse.jdt.ui.prefs b/dev/com.ibm.ws.logging.hpel_fat/.settings/org.eclipse.jdt.ui.prefs new file mode 100755 index 00000000000..c92277a371a --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,62 @@ +#Ant properties +#Automatically generated by the ant prepare.settings.files task +eclipse.preferences.version=1 +editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true +org.eclipse.jdt.ui.ignorelowercasenames=true +org.eclipse.jdt.ui.importorder=java;javax;org;com; +org.eclipse.jdt.ui.javadoc=true +org.eclipse.jdt.ui.ondemandthreshold=99 +org.eclipse.jdt.ui.staticondemandthreshold=99 +org.eclipse.jdt.ui.text.custom_code_templates= +sp_cleanup.add_default_serial_version_id=true +sp_cleanup.add_generated_serial_version_id=false +sp_cleanup.add_missing_annotations=true +sp_cleanup.add_missing_deprecated_annotations=true +sp_cleanup.add_missing_methods=false +sp_cleanup.add_missing_nls_tags=false +sp_cleanup.add_missing_override_annotations=true +sp_cleanup.add_missing_override_annotations_interface_methods=true +sp_cleanup.add_serial_version_id=false +sp_cleanup.always_use_blocks=true +sp_cleanup.always_use_parentheses_in_expressions=false +sp_cleanup.always_use_this_for_non_static_field_access=false +sp_cleanup.always_use_this_for_non_static_method_access=false +sp_cleanup.convert_to_enhanced_for_loop=false +sp_cleanup.correct_indentation=false +sp_cleanup.format_source_code=true +sp_cleanup.format_source_code_changes_only=false +sp_cleanup.make_local_variable_final=false +sp_cleanup.make_parameters_final=false +sp_cleanup.make_private_fields_final=true +sp_cleanup.make_type_abstract_if_missing_method=false +sp_cleanup.make_variable_declarations_final=true +sp_cleanup.never_use_blocks=false +sp_cleanup.never_use_parentheses_in_expressions=true +sp_cleanup.on_save_use_additional_actions=true +sp_cleanup.organize_imports=true +sp_cleanup.qualify_static_field_accesses_with_declaring_class=false +sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_with_declaring_class=false +sp_cleanup.qualify_static_method_accesses_with_declaring_class=false +sp_cleanup.remove_private_constructors=true +sp_cleanup.remove_trailing_whitespaces=true +sp_cleanup.remove_trailing_whitespaces_all=true +sp_cleanup.remove_trailing_whitespaces_ignore_empty=false +sp_cleanup.remove_unnecessary_casts=true +sp_cleanup.remove_unnecessary_nls_tags=true +sp_cleanup.remove_unused_imports=true +sp_cleanup.remove_unused_local_variables=false +sp_cleanup.remove_unused_private_fields=true +sp_cleanup.remove_unused_private_members=false +sp_cleanup.remove_unused_private_methods=true +sp_cleanup.remove_unused_private_types=true +sp_cleanup.sort_members=false +sp_cleanup.sort_members_all=false +sp_cleanup.use_blocks=false +sp_cleanup.use_blocks_only_for_return_and_throw=false +sp_cleanup.use_parentheses_in_expressions=false +sp_cleanup.use_this_for_non_static_field_access=false +sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true +sp_cleanup.use_this_for_non_static_method_access=false +sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true diff --git a/dev/com.ibm.ws.logging.hpel_fat/bnd.bnd b/dev/com.ibm.ws.logging.hpel_fat/bnd.bnd new file mode 100644 index 00000000000..fd6aab88c9d --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/bnd.bnd @@ -0,0 +1,15 @@ +-include= ~../cnf/resources/bnd/bundle.props +bVersion=1.0 + +src: \ + fat/src + +-buildpath: \ + ${javac.bootclasspath.java6}, \ + ../build.sharedResources/lib/junit/old/junit.jar;version=file, \ + ../build.sharedResources/lib/httpunit/1.7/lib/httpunit.jar;version=file, \ + fattest.simplicity;version=latest, \ + ../fattest.simplicity/lib/public.api.jar;version=file, \ + lib/fat.harness.jar;version=file, \ + lib/phased.junit.jar;version=file, \ + com.ibm.ws.logging.hpel;version=latest diff --git a/dev/com.ibm.ws.logging.hpel_fat/bnd.bnd.gradle b/dev/com.ibm.ws.logging.hpel_fat/bnd.bnd.gradle new file mode 100644 index 00000000000..fd6aab88c9d --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/bnd.bnd.gradle @@ -0,0 +1,15 @@ +-include= ~../cnf/resources/bnd/bundle.props +bVersion=1.0 + +src: \ + fat/src + +-buildpath: \ + ${javac.bootclasspath.java6}, \ + ../build.sharedResources/lib/junit/old/junit.jar;version=file, \ + ../build.sharedResources/lib/httpunit/1.7/lib/httpunit.jar;version=file, \ + fattest.simplicity;version=latest, \ + ../fattest.simplicity/lib/public.api.jar;version=file, \ + lib/fat.harness.jar;version=file, \ + lib/phased.junit.jar;version=file, \ + com.ibm.ws.logging.hpel;version=latest diff --git a/dev/com.ibm.ws.logging.hpel_fat/build-test.xml b/dev/com.ibm.ws.logging.hpel_fat/build-test.xml new file mode 100755 index 00000000000..600e17237a6 --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/build-test.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.logging.hpel_fat/build.gradle b/dev/com.ibm.ws.logging.hpel_fat/build.gradle new file mode 100644 index 00000000000..e69de29bb2d diff --git a/dev/com.ibm.ws.logging.hpel_fat/delivery.sets b/dev/com.ibm.ws.logging.hpel_fat/delivery.sets new file mode 100755 index 00000000000..674398425a0 --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/delivery.sets @@ -0,0 +1 @@ +SLE diff --git a/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/setup/HpelSetup.java b/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/setup/HpelSetup.java new file mode 100755 index 00000000000..7972cd831c0 --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/setup/HpelSetup.java @@ -0,0 +1,281 @@ +//%Z% %I% %W% %G% %U% [%H% %T%] +/* + * Change History: + * + * Reason Version Date User id Description + * -------------------------------------------------------------------------------- + * F000896.23216 8.0 06/11/2010 shighbar Add in removal of excess servers in topology to conserve resources & keep more legacy log history for legacy test cases PD. + * 681388 8.0 12/07/2010 shighbar Override startup of server resources to correct issues seen in z/OS and make bucket efficient. + */ +package com.ibm.ws.fat.hpel.setup; + +import java.util.List; +import java.util.Vector; + +import junit.framework.Test; + +import com.ibm.websphere.simplicity.ApplicationServer; +import com.ibm.websphere.simplicity.Cell; +import com.ibm.websphere.simplicity.Node; +import com.ibm.websphere.simplicity.Server; +import com.ibm.websphere.simplicity.Topology; +import com.ibm.websphere.simplicity.WebSphereVersion; +import com.ibm.ws.fat.ExpensiveTestSetup; +import com.ibm.ws.fat.ras.util.CommonTasks; +import com.ibm.ws.fat.util.CommonActions; + +/** + * Setups key resources for HPEL test cases. + * + * @author Scott Highbarger + * + */ +public class HpelSetup extends ExpensiveTestSetup { + + /** + * The name of the server configured by this fixture + */ + public static final String SERVER_NAME = "HpelServer"; + public static final String SERVER2_NAME = "HpelServer2"; + + /** + * The name of the application configured by this fixture + */ + public static final String APP_NAME = "HpelFat"; + + /** + * The name of the EAR file for the application. + */ + public static final String EAR_NAME = "HpelFatEAR.ear"; + + /** + * Required for compatibility with JUnit/Phased JUnit/command-line invocation of TestSetup. + * + * @param test + * The Test or TestSuite to enclose with this test fixture + */ + public HpelSetup(Test test) { + super(test); + } + + /** + * The amount of nodes the the cell must have for this test bucket to execute. + * + */ + @Override + public int requiredNodesPerCell() { + return 1; + } + + /** + * Provides the amount of time that the harness waits before starting tests. The harness will wait this long to allow the environment to settle. + * + */ + @Override + public long getStartUpWaitTime() { + return TWENTY_SECONDS; + } + + /** + * Setup resources which the test bucket requires, including the creation of application servers and installation of test applications. + * + */ + @Override + public void setUpResources() throws Exception { + // Simplicity in Liberty at the moment sets up just one server located in publish/servers + Topology.init(); + +// // initialize common variables +// WsadminLib wsadminlib = new WsadminLib(getCellUnderTest()); +// +// ApplicationServer server = CommonActions.removeAndCreateApplicationServer(wsadminlib, getNodeUnderTest(), SERVER_NAME); +// SimpleApplication hpelApp = new SimpleApplication(); +// hpelApp.setName(APP_NAME); +// hpelApp.setEar(new File(Props.getProperty(Props.DIR_BUILD_EARS), EAR_NAME)); +// hpelApp.install(server); +// +// //Some test cases will require two servers. +// ApplicationServer server2 = CommonActions.removeAndCreateApplicationServer(wsadminlib, getNodeUnderTest(), SERVER2_NAME); +// SimpleApplication hpelApp2 = new SimpleApplication(); +// hpelApp2.setName(APP_NAME + "2"); +// hpelApp2.setEar(new File(Props.getProperty(Props.DIR_BUILD_EARS), EAR_NAME)); +// hpelApp2.install(server2); +// +// // Remove other servers in topology to conserve resources. +// Set keepServers = new HashSet(); +// keepServers.add(server); +// keepServers.add(server2); +// CommonTasks.removeUnusedServers(getCellUnderTest(), keepServers); +// +// //Expand the number of historical logs to keep for legacy server side tests. +// wsadminlib.setServerSysout(server.getNodeName(), server.getName(), 5, 25); +// +// // save and synchronize changes +// wsadminlib.save(); + } + + /** + * Intended to return a list of all the servers which are being tested. At this time this method will only return a + * single server, and it equivalent to calling the getServerUnderTest() method. + * + */ + @Override + public List getServersUnderTest() throws Exception { + Vector myServers = new Vector(0, 1); + myServers.addElement(getServerUnderTest()); + Server secondServer = getServer2UnderTest(); + if (secondServer != null) { + myServers.addElement(secondServer); // the 2nd server configured by setUpResources + } + return myServers; + } + + /** + * Clean up resources created by the test bucket. + * + */ + @Override + public void tearDownResources() throws Exception { + super.tearDownResources(); + // WsadminLib wsadminlib = new WsadminLib(getCellUnderTest()); + // CommonActions.deleteServer(wsadminlib, getNodeUnderTest(), SERVER_NAME); + // wsadminlib.save(); + } + + /** + * Override the default requiredWebSphereVersion as HPEL currently requires and is only supported on WAS version 8. + * + */ + @Override + public WebSphereVersion requiredWebSphereVersion() { + return new WebSphereVersion("8.0"); + } + + /** + * Retrieve a reference to the Cell configured by this test fixture. + * + * @return a reference to the Cell chosen for configuration of this test fixture + * @throws Exception + * if a Simplicity error occurs + */ + public static Cell getCellUnderTest() throws Exception { + return Topology.getCells().get(0); // first cell in bootstrapping.properties + } + + /** + * Retrieve a reference to the Node configured by this test fixture. + * + * @return a reference to the Node chosen for configuration of this test fixture + * @throws Exception + * if a Simplicity error occurs + */ + public static Node getNodeUnderTest() throws Exception { + Cell cell = getCellUnderTest(); + return CommonActions.getSortedDefaultNodes(cell).get(0); // first Node by alphabetized name + } + + /** + * Retrieve a reference to the ApplicationServer configured by this test fixture. + * + * @return a reference to the server named SERVER_NAME + * @throws Exception + * if a Simplicity error occurs + */ + public static ApplicationServer getServerUnderTest() throws Exception { + Node node = getNodeUnderTest(); + Server server = node.getServerByName(SERVER_NAME); + return server == null ? null : new HPELApplicationServer(server); // the server configured by setUpResources + } + + /** + * Retrieve a reference to the ApplicationServer configured by this test fixture. + * + * @return a reference to the server named SERVER_NAME + * @throws Exception + * if a Simplicity error occurs + */ + public static ApplicationServer getServer2UnderTest() throws Exception { + Node node = getNodeUnderTest(); + Server server = node.getServerByName(SERVER2_NAME); + return server == null ? null : new HPELApplicationServer(server); // the 2nd server configured by setUpResources + } + + @Override + public boolean skipTest() { + /* + * May want to look into using this method, or calling super.skipTest() and overriding some of these methods: + * requiredCells() requiredNodesPerCells() requiredWebSphereVersion() requiredWebSphereEdition() + * requiredOperatingSystems() + * + * etc. so that certain tests are only ran on z/OS or certain levels etc. as needed. + */ + // There's not MixedCell topologies in Liberty yet. + return false; + +// // HpelSetup is not able to work on MixedCell topologies at this time. +// CommonTasks.writeLogMsg(Level.INFO, "Checking if we should skip HpelSetup or not."); +// try { +// return MixedCellTopologyHelper.isTopologyMixed(); +// } catch (Exception e) { +// e.printStackTrace(); +// return true; // Don't execute if we can't tell what topology we are on. +// } + } + + /** + * Ensures that all the resources needed by your test fixture are running. + * This step typically involves starting a series of servers, so the + * "getServersUnderTest" method aims to accommodate this step. By default, + * the startResources method calls getServersUnderTest to find a list of + * servers, and then it starts that list of servers. + * + * @throws Exception If a anything goes wrong + */ + @Override + public void startResources() throws Exception { + // We don't want to start resources, they will need to be bounced in legacy setup anyways. + // Also see issues trying to start both back to back using standard harness framework methods on slower z/OS + // systems. + } + + /** + * Version of HPELApplicationServer which copies log records into logs/messages.log file to + * be recognized as a started server. + */ + private static class HPELApplicationServer extends ApplicationServer { + + protected HPELApplicationServer(Server delegate) throws Exception { + super(delegate.getBackend(), delegate.getNode()); + } + + /* + * (non-Javadoc) + * + * @see com.ibm.websphere.simplicity.ApplicationServer#start() + */ + @Override + public void start() throws Exception { + // If HPEL is enabled we need start a thread copying log messages from repository into messages.log + if (CommonTasks.isHpelEnabled(this)) { + //88513 - Reading HPEL logs (HpelSetup.TextCopyThread code) get intermixed with the thread deleting 'logs' directory + //before starting the server (LibertyServer.preStartServerLogsTidy() code executed when we call super.start() in HpelSetup.start() method). + //To avoid such problem its better to delete 'logs' directory ourself in HpelSetup.start() method before starting our reading thread. + //This way LibertyServer.preStartServerLogsTidy() will notice that 'logs' directory is gone already and won't do anything at all. + getBackend().deleteFileFromLibertyServerRoot("logs"); + } + super.start(); + } + + /* + * (non-Javadoc) + * + * @see com.ibm.websphere.simplicity.ApplicationServer#start(int) + */ + @Override + public void start(int mbeanWaitDuration) throws Exception { + this.start(); + } + + } + +} diff --git a/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/suites/FATSuite.java b/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/suites/FATSuite.java new file mode 100755 index 00000000000..6949534ad29 --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/suites/FATSuite.java @@ -0,0 +1,105 @@ +//%Z% %I% %W% %G% %U% [%H% %T%] +/* + * Change History: + * + * Reason Version Date User id Description + * ---------------------------------------------------------------------------------------------------- + * F017049-21927 8.0 01/28/2010 shighbar Add testcase for trace to memory buffer by wsadmin + * 635940 8.0 01/25/2010 spaungam Add testcase for testing *=all + * F017049-19395 8.0 07/21/2010 shighbar Add remote reader test on HPEL mBean via JMX. + * F017049-33795 8.0 11/02/2010 shighbar Add SSFAT test HpelClassificationOnlyTraceSSFAT. + * F004749-35525 8.0 12/07/2010 shighbar Add SSFAT test HpelRawTraceListSSFAT. + * 682506 8.0 12/15/2010 shighbar Add RAS Raw Trace Filter test cases. + * 688984 8.0 02/10/2011 shighbar Add HpelMBeanOp tests. + * F017049-41948 8.0 03/30/2011 shighbar Add VerifyServiceLogConfig test case. + * 699970 8.0 04/05/2011 shighbar Add HpelInternalTrace test case. + * 711532 8.0 07/21/2011 shighbar Remove StartServerWithVerboseLogging from DR suite. + * 703214 8.0 07/22/2011 shighbar Add Internal trace guard RawTraceSpecVerifier / MBeanOpTest test. + * 714823 8.0 08/29/2011 shighbar Reorder to avoid logViewer monitor hang from impacting follow on tests. + * 702533 8.0 09/03/2011 olteamh Add HpelDeleteEmptyDirectories test case. + * PM48157 8.0 10/03/2011 shighbar HPEL TextLog retention policy does not remove previous server instances logs. + * F1344-49496 8.0 10/29/2011 belyi Add TestLogRecordContextSSFAT test + * F1344-56880 8.5 01/14/2012 belyi Add VerifyJmxLogNotification test + * 95518 8.5.5 03/07/2012 dbourne remove text log tests + */ +package com.ibm.ws.fat.hpel.suites; + +import junit.framework.Test; +import junit.framework.TestSuite; + +import com.ibm.ws.fat.hpel.setup.HpelSetup; +import com.ibm.ws.fat.hpel.tests.BinaryLogExec; +import com.ibm.ws.fat.hpel.tests.BinaryLogRecordContextTest; +import com.ibm.ws.fat.hpel.tests.ConcurrentLoggingAccuracyTest; +import com.ibm.ws.fat.hpel.tests.HpelDeleteEmptyDirectories; +import com.ibm.ws.fat.hpel.tests.TraceSpecificationSetToAllTest; +import com.ibm.ws.fat.hpel.tests.VerifyRepositoryAccuracy; + +/** + * Packages all our HPEL FAT tests + */ +public class FATSuite { + + /** + * Builds a TestSuite of HPEL Functional Acceptance tests + * + * @return a JUnit TestSuite + */ + public static Test suite() { + TestSuite suite = new TestSuite("Hpel FAT suite"); + +/* + * The RasServerSideUnitTestSuite is not really related to HPEL at all, but had to be included here in the HPEL + * suite instead of being called directly by the Full Regression because it makes use of FAT resources such as + * HpelSetup.getServerUnderTest(). Until we refactor the setup of the servers etc. out of HpelSetup and into + * RASSetup etc. It must be called from here. + */ + // server side ras legacy test suite +// suite.addTest(RasServerSideUnitTestSuite.suite()); +// +// // ========== RAS FAT test cases ======== +// suite.addTestSuite(com.ibm.ws.fat.ras.tests.AttributeSetTestingByWsadmin.class); +// suite.addTestSuite(com.ibm.ws.fat.ras.tests.TraceServiceTestingByWsAdmin.class); +// suite.addTestSuite(MBeanOpTest.class); +// suite.addTestSuite(VerifyServiceLogConfig.class); +// +// // ========== FAT test cases ============ +// suite.addTestSuite(EnableHPELByWsadmin.class); + suite.addTestSuite(BinaryLogRecordContextTest.class); + suite.addTestSuite(VerifyRepositoryAccuracy.class); + suite.addTestSuite(BinaryLogExec.class); +// suite.addTestSuite(EnableTextLogByWsadmin.class); +// suite.addTestSuite(EnableRuntimeTraceSpecByWsadmin.class); +// suite.addTestSuite(ChangeRepositoryDirectoryByWsAdmin.class); + suite.addTestSuite(ConcurrentLoggingAccuracyTest.class); +// suite.addTestSuite(LogViewerFormatValidation.class); +// suite.addTestSuite(MergedRepositories.class); +// suite.addTestSuite(com.ibm.ws.fat.hpel.tests.AttributeSetTestingByWsadmin.class); +// suite.addTestSuite(ControlTraceMemoryByWsadmin.class); +// suite.addTestSuite(DisableHPELByWsadmin.class); +// suite.addTestSuite(HpelRemoteReaderMBeanByJMX.class); +// suite.addTestSuite(VerifyJmxLogNotification.class); +// suite.addTestSuite(TestOwnershipVerification.class); +// suite.addTestSuite(RawTraceSpecVerifier.class); + suite.addTestSuite(HpelDeleteEmptyDirectories.class); +// suite.addTestSuite(HpelTextLogRetention.class); +// +// // =========== FAT Server Side test cases ========== +// suite.addTestSuite(HpelMBeanOpSSFAT.class); +// suite.addTestSuite(HpelLogEventNotificationsSSFAT.class); +// suite.addTestSuite(HpelMemoryBufferSSFAT.class); +// suite.addTestSuite(HpelReadWriteSSFAT.class); +// suite.addTestSuite(HpelClassificationOnlyTraceSSFAT.class); +// suite.addTestSuite(HpelRetentionSSFAT.class); +// suite.addTestSuite(HpelLogManResetSSFAT.class); +// suite.addTestSuite(HpelRawTraceListSSFAT.class); +// suite.addTestSuite(HpelInternalTraceSSFAT.class); +// suite.addTestSuite(TestLogRecordContextSSFAT.class); +// suite.addTestSuite(LogViewerSSFAT.class); + suite.addTestSuite(TraceSpecificationSetToAllTest.class); +// removing temporarily for defect 158844 suite.addTestSuite(HpelPurgeMaxSizeIgnoreTest_2.class); +// removing temporarily for defect 158844 suite.addTestSuite(HpelPurgeMaxSizeIgnoreTest_1.class); + + return new HpelSetup(suite); + } +} diff --git a/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/BinaryLogExec.java b/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/BinaryLogExec.java new file mode 100755 index 00000000000..9b53db127cd --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/BinaryLogExec.java @@ -0,0 +1,496 @@ +//%Z% %I% %W% %G% %U% [%H% %T%] +/** + * + * IBM Confidential OCO Source Material + * 5639-D57 (C) COPYRIGHT International Business Machines Corp. 2002 + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + * + * + * DESCRIPTION: + * + * Change History: + * + * Reason Version Date User id Description + * ---------------------------------------------------------------------------- + * 95263 8.5.5 06/13/2013 sumam Fixed the test case for binaryLog utility command + * + */ + +package com.ibm.ws.fat.hpel.tests; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.Random; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import com.ibm.websphere.simplicity.ApplicationServer; +import com.ibm.websphere.simplicity.Node; +import com.ibm.websphere.simplicity.OperatingSystem; +import com.ibm.websphere.simplicity.ProgramOutput; +import com.ibm.websphere.simplicity.RemoteFile; +import com.ibm.ws.fat.VerboseTestCase; +import com.ibm.ws.fat.hpel.setup.HpelSetup; +import com.ibm.ws.fat.ras.util.CommonTasks; +import com.ibm.ws.logging.hpel.FormatSet; + +public class BinaryLogExec extends VerboseTestCase { + + private static final Logger thisLogger = Logger.getLogger(BinaryLogExec.class.getName()); + private final String outFileName = this.getName() + "_" + new Date().getTime() + ".lv_out.log"; + RemoteFile rOutLog = null; + RemoteFile rProfRootDir = null; + RemoteFile rProfBinFile = null; + + private ApplicationServer appServ = null; + + RemoteFile backup = null; + + public BinaryLogExec(String name) { + super(name); + } + + @Override + public void setUp() throws Exception { + // Call super.SetUp() cause we still want it's setup as well + super.setUp(); + appServ = HpelSetup.getServerUnderTest(); + // Confirm HPEL is enabled + if (!CommonTasks.isHpelEnabled(appServ)) { + // HPEL is not enabled. + this.logStep("HPEL is not enabled on " + appServ.getName() + ", attempting to enable."); + CommonTasks.setHpelEnabled(appServ, true); + // Restart now to complete switching to HPEL + appServ.restart(); + this.logStepCompleted(); + } + + // Liberty profile root is the install root. + rProfRootDir = new RemoteFile(HpelSetup.getNodeUnderTest().getMachine(), HpelSetup.getServerUnderTest().getBackend().getInstallRoot()); +// rProfRootDir = new RemoteFile(HpelSetup.getNodeUnderTest().getMachine(), HpelSetup.getNodeUnderTest().getProfileDir()); + rProfBinFile = new RemoteFile(HpelSetup.getNodeUnderTest().getMachine(), rProfRootDir, "bin"); + // Setting the bootstrap with trace specification to get the trace logs. + CommonTasks.addBootstrapProperty(appServ, "com.ibm.ws.logging.trace.specification", "*=fine=enabled"); + appServ.stop(); + appServ.start(); + + } + + /** + * Tests that binaryLog correctly report an invalid option when one is passed to it. e.g. binaryLog -invalidAction + * + * @throws Exception + */ + public void testbinaryLogInvalidOption() throws Exception { + this.logStep("executing binaryLog on " + HpelSetup.getNodeUnderTest().getProfileName()); + // generate a random option that is between 3 and 15 characters long starting with "bad". + String alphabet = "abcdefghijklmnopqrstuvwxyz"; + StringBuffer invalidOption = new StringBuffer(); + invalidOption.append("-bad"); // need the option flag first. + Random rnd = new Random(); + for (int i = 1; i <= rnd.nextInt(12); i++) { + invalidOption.append(alphabet.charAt(rnd.nextInt(alphabet.length()))); + } + + StringBuffer expectedResponse = new StringBuffer(); + // (WI 234118) We cannot check for message text that gets translated, because it causes the test to fail in non-English locales. + // Updating this match to only use the non-translated words and argument in the message text. + // expectedResponse.append("The specified action "); + // expectedResponse.append(invalidOption); + // expectedResponse.append(" is not valid."); + // expectedResponse.append("\\s+"); //match as a regular expression + // expectedResponse.append("For usage information use binaryLog help."); + expectedResponse.append(".*" + invalidOption + ".*\\s+"); + expectedResponse.append(".*binaryLog help.*"); + ProgramOutput lvPrgmOut = exeBinaryLog(new String[] { invalidOption.toString() }); + this.logVerificationPoint("Verifying binaryLog std out/err and status return code."); + logMsg(" === BinaryLog's stdout: === "); + logMsg(lvPrgmOut.getStdout()); + logMsg(" "); + if (lvPrgmOut.getStderr().length() > 0) { + // LogViewer reported some errors. + logMsg(" === BinaryLogs's std.err: ==="); + logMsg(lvPrgmOut.getStderr()); + } + + assertTrue("Failed assertion that logViewer exited with an error return code", (lvPrgmOut.getReturnCode() != 0)); + assertTrue("Failed assertion that logViewer reported invalid option. Where //s is any number of spaces, expected=" + + expectedResponse.toString().trim() + ". result=" + lvPrgmOut.getStdout().trim(), + Pattern.matches(expectedResponse.toString(), lvPrgmOut.getStdout().trim())); + + this.logVerificationPassed(); + this.logStepCompleted(); + } + + /** + * Tests that binaryLog copy action works as expected. + * Steps: + * 1. Create log entries and than use copy action to move the logs file to new location with minDate and maxDate specified. + * 2. view the log entries again with minDate and maxDate specified + * 3. Both isoDateFormat and the default dateFormat are tested for minDate and maxDate + * + * @throws Exception + */ + public void testbinaryLogCopyExecutes() throws Exception { + // need to have messages for the binaryLog to process. + long entry1Time = System.currentTimeMillis(); + CommonTasks.createLogEntries(HpelSetup.getServerUnderTest(), BinaryLogExec.class.getName(), "Some Msg goes here", null, 50, CommonTasks.LOGS, -1); + long entry2Time = System.currentTimeMillis(); + + Date minDate = new Date(entry1Time); + Date maxDate = new Date(entry2Time); + + DateFormat formatterISO = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); + DateFormat formatterDefault = FormatSet.customizeDateFormat(DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.MEDIUM)); + + Node node = HpelSetup.getNodeUnderTest(); + rOutLog = new RemoteFile(node.getMachine(), node.getMachine().getTempDir(), outFileName); + + this.logStep("executing binaryLog on " + node.getProfileName()); + + String arg1 = "copy"; + String arg2 = rOutLog.getAbsolutePath(); + String arg3 = "--minDate=" + formatterDefault.format(minDate); + String arg4 = "--maxDate=" + formatterISO.format(maxDate); + + ProgramOutput lvPrgmOut; + + lvPrgmOut = exeBinaryLog(new String[] { arg1, CommonTasks.getBinaryLogDir(HpelSetup.getServerUnderTest()).getAbsolutePath(), arg2, arg3, arg4 }); + this.logVerificationPoint("Verifying binaryLog std out/err and status return code."); + logMsg(" === BinaryLog's stdout: === return code is : " + lvPrgmOut.getReturnCode()); + logMsg(lvPrgmOut.getStdout()); + logMsg(" "); + if (lvPrgmOut.getStderr().length() > 0) { + // LogViewer reported some errors. + logMsg(" === BinaryLog's std.err: ==="); + logMsg(lvPrgmOut.getStderr()); + } + assertTrue("Failed assertion that binaryLog exited with successful return code", (lvPrgmOut.getReturnCode() == 0)); // Test that output returns Success Code (0) + assertTrue("Failed assertion that binaryLog did produce an output file", rOutLog.exists()); // Test output repository exists + + ProgramOutput lvPrgmOut2 = exeBinaryLog(new String[] { "view", arg2, arg3, arg4 }); + assertTrue("Failed assertion that binaryLog exited with successful return code", (lvPrgmOut2.getReturnCode() == 0)); + assertTrue("Failed assertion that binaryLog did produce an output file", lvPrgmOut2.getStdout().contains("Some Msg goes here")); + this.logVerificationPassed(); + this.logStepCompleted(); + + } + + /** + * Tests that binaryLog view action works as expected. + * Steps: + * 1. Create log entries and than use view action to view the contents of log in text format. + * 2. View the log entries again using --isoDateFormat option + * + * @throws Exception + */ + public void testbinaryLogViewExecutes() throws Exception { + // need to have messages for the binaryLog to process. + CommonTasks.createLogEntries(HpelSetup.getServerUnderTest(), BinaryLogExec.class.getName(), "Some Msg goes here", null, 25, CommonTasks.LOGS, -1); + + Node node = HpelSetup.getNodeUnderTest(); + rOutLog = new RemoteFile(node.getMachine(), node.getMachine().getTempDir(), outFileName); + + this.logStep("executing binaryLog on " + node.getProfileName()); + + String arg1 = "view"; + String arg2 = "--isoDateFormat"; + + ProgramOutput lvPrgmOut; + + lvPrgmOut = exeBinaryLog(new String[] { arg1, CommonTasks.getBinaryLogDir(HpelSetup.getServerUnderTest()).getAbsolutePath() + "/logdata" }); + + this.logVerificationPoint("Verifying binaryLog std out/err and status return code."); + logMsg(" === BinaryLog's stdout: === "); + logMsg(lvPrgmOut.getStdout()); + logMsg(" "); + if (lvPrgmOut.getStderr().length() > 0) { + // LogViewer reported some errors. + logMsg(" === BinaryLog's std.err: ==="); + logMsg(lvPrgmOut.getStderr()); + } + + Pattern p1 = Pattern.compile("\\d{1,2}/\\d{1,2}/\\d{1,2} \\d{1,2}:\\d{1,2}:\\d{1,2}:\\d\\d\\d"); + Matcher m1 = p1.matcher(lvPrgmOut.getStdout()); + assertTrue("Failed assertion that binaryLog exited with successful return code", (lvPrgmOut.getReturnCode() == 0)); + assertTrue("Failed assertion that binaryLog did produce an output file", lvPrgmOut.getStdout().contains("Some Msg goes here")); + assertTrue("Failed assertion that binaryLog displayed default date format", m1.find()); + + lvPrgmOut = exeBinaryLog(new String[] { arg1, CommonTasks.getBinaryLogDir(HpelSetup.getServerUnderTest()).getAbsolutePath() + "/logdata", arg2 }); + logMsg(" === BinaryLog's stdout: === "); + logMsg(lvPrgmOut.getStdout()); + logMsg(" "); + if (lvPrgmOut.getStderr().length() > 0) { + // LogViewer reported some errors. + logMsg(" === BinaryLog's std.err: ==="); + logMsg(lvPrgmOut.getStderr()); + } + + Pattern p2 = Pattern.compile("\\d\\d\\d\\d-\\d\\d-\\d\\dT\\d\\d:\\d\\d:\\d\\d\\.\\d\\d\\d"); + Matcher m2 = p2.matcher(lvPrgmOut.getStdout()); + assertTrue("Failed assertion that binaryLog exited with successful return code", (lvPrgmOut.getReturnCode() == 0)); + assertTrue("Failed assertion that binaryLog did produce an output file", lvPrgmOut.getStdout().contains("Some Msg goes here")); + assertTrue("Failed assertion that binaryLog displayed default date format", m2.find()); + this.logVerificationPassed(); + this.logStepCompleted(); + + } + + /** + * Tests that binaryLog view action works as expected. + * Steps: + * 1.Create log entries and then use listInstances action to view instances of the binary logs. + * 2.use listInstances again with --isoDateFormat option + * + * @throws Exception + */ + public void testbinaryLogListInstancesExecutes() throws Exception { + // need to have messages for the binaryLog to process. + CommonTasks.createLogEntries(HpelSetup.getServerUnderTest(), BinaryLogExec.class.getName(), "Some Msg goes here", null, 25, CommonTasks.LOGS, -1); + + Node node = HpelSetup.getNodeUnderTest(); + rOutLog = new RemoteFile(node.getMachine(), node.getMachine().getTempDir(), outFileName); + + this.logStep("executing binaryLog on " + node.getProfileName()); + + String arg1 = "listInstances"; + String arg2 = "--isoDateFormat"; + + ProgramOutput lvPrgmOut; + + lvPrgmOut = exeBinaryLog(new String[] { arg1, CommonTasks.getBinaryLogDir(HpelSetup.getServerUnderTest()).getAbsolutePath() + "/logdata" }); + + this.logVerificationPoint("Verifying binaryLog std out/err and status return code."); + logMsg(" === BinaryLog's stdout: === "); + logMsg(lvPrgmOut.getStdout()); + logMsg(" "); + if (lvPrgmOut.getStderr().length() > 0) { + // LogViewer reported some errors. + logMsg(" === BinaryLog's std.err: ==="); + logMsg(lvPrgmOut.getStderr()); + } + + Pattern p1 = Pattern.compile("\\d{1,2}/\\d{1,2}/\\d{1,2} \\d{1,2}:\\d{1,2}:\\d{1,2}:\\d\\d\\d"); + Matcher m1 = p1.matcher(lvPrgmOut.getStdout()); + assertTrue("Failed assertion that binaryLog exited with successful return code", (lvPrgmOut.getReturnCode() == 0)); + // (WI 234118) We cannot perform this check because "Instance ID" is translated, which causes the test to fail in non-English locales. There is no ID or + // non-translated portion of the message to even try to match. + // assertTrue("Failed assertion that binaryLog did produce an output file", lvPrgmOut.getStdout().contains("Instance ID ")); + assertTrue("Failed assertion that binaryLog displayed default date format", m1.find()); + + lvPrgmOut = exeBinaryLog(new String[] { arg1, CommonTasks.getBinaryLogDir(HpelSetup.getServerUnderTest()).getAbsolutePath() + "/logdata", arg2 }); + logMsg(" === BinaryLog's stdout: === "); + logMsg(lvPrgmOut.getStdout()); + logMsg(" "); + if (lvPrgmOut.getStderr().length() > 0) { + // LogViewer reported some errors. + logMsg(" === BinaryLog's std.err: ==="); + logMsg(lvPrgmOut.getStderr()); + } + Pattern p2 = Pattern.compile("\\d\\d\\d\\d-\\d\\d-\\d\\dT\\d\\d:\\d\\d:\\d\\d\\.\\d\\d\\d"); + Matcher m2 = p2.matcher(lvPrgmOut.getStdout()); + assertTrue("Failed assertion that binaryLog exited with successful return code", (lvPrgmOut.getReturnCode() == 0)); + // (WI 234118) We cannot perform this check because "Instance ID" is translated, which causes the test to fail in non-English locales. There is no ID or + // non-translated portion of the message to even try to match. + // assertTrue("Failed assertion that binaryLog did produce an output file", lvPrgmOut.getStdout().contains("Instance ID ")); + assertTrue("Failed assertion that binaryLog displayed default date format", m2.find()); + this.logVerificationPassed(); + this.logStepCompleted(); + + } + + /** + * Testing the listInstances action of BinaryLog command. Also testing --includeInstance Filter option of View. + * + * @throws Exception + */ + public void testHeaderProcessName() throws Exception { + this.logStep("get instance list from " + HpelSetup.getNodeUnderTest().getProfileName()); + + ProgramOutput lvPrgmOut = exeBinaryLog(new String[] { "listInstances", CommonTasks.getBinaryLogDir(HpelSetup.getServerUnderTest()).getAbsolutePath() }); + String out = lvPrgmOut.getStdout(); + + // (WI 234118) We cannot rely on matching "Instance ID" as the header because that message is translated when running in non-English locales, causing this + // test to fail. Instead, match the lines starting with a number assuming those are the instance IDs. + // Collect IDs belonging to the current instance run. + int indx; + String controllerID = null; + ArrayList ids = new ArrayList(); + for (String outLine : out.split("\\r?\\n")) { + Pattern p = Pattern.compile("^\\s*(\\d+(?:/\\S+)?)\\s"); + Matcher m = p.matcher(outLine); + if (m.find()) { + String newID = m.group(1); + logMsg("Processing instance id " + newID); + indx = newID.indexOf('/'); + String newControllerID = indx < 0 ? newID : newID.substring(0, indx); + logMsg("It belongs to controller " + newControllerID); + if (controllerID == null || !controllerID.equals(newControllerID)) { + // It's a new controller's instance, reset the list of IDs. + logMsg("It's a new controller, reset list of instances"); + ids.clear(); + controllerID = newControllerID; + } + ids.add(newID); + } + } + + assertFalse("No instance IDs found", ids.isEmpty()); + this.logStepCompleted(); + + this.logStep("Verify procName and procId for each retrieved instance"); + + boolean isZOS = HpelSetup.getNodeUnderTest().getMachine().getOperatingSystem().equals(OperatingSystem.ZOS); + boolean hasController = false; + boolean hasServant = false; + ApplicationServer server = HpelSetup.getServerUnderTest(); + for (String id : ids) { + this.logVerificationPoint("Verifying instance " + id); + + // c:\sumam\Liberty\workspace3\build.image\wlp\bin>binaryLog view server1 --includeInstance=latest + + lvPrgmOut = exeBinaryLog(new String[] { "view", CommonTasks.getBinaryLogDir(HpelSetup.getServerUnderTest()).getAbsolutePath(), "--includeInstance=" + id }); + + out = lvPrgmOut.getStdout(); + this.logMsg("id ouptut : " + out); + // Should be okay matching the English text here because this is not a translated message. + int indx1 = out.indexOf(" running with process name "); + int indx2 = out.indexOf(" and process id ", indx1); + assertTrue("Instance with ID " + id + " does not have proper header", indx1 > 0 && indx2 > indx1); + String procName = out.substring(indx1 + 27, indx2); + String procId = out.substring(indx2 + 16).split("\\s*\\n\\s*", 2)[0]; + String expProcName; + String expProcId; + if (isZOS) { + indx = id.indexOf("/"); + if (indx < 0) { + // This is controller, take name values from Simplicity, can't verify jobID this way though + expProcName = server.getShortName(); + hasController = true; + } else { + // This is servant, take values from instance ID. + indx1 = id.indexOf("-", indx); + indx2 = id.indexOf("_", indx1); + assertTrue("Instance ID " + id + " is incorrectly formatted", indx1 > indx && indx2 > indx1); + expProcName = id.substring(indx1 + 1, indx2); + expProcId = id.substring(indx2 + 1); + hasServant = true; + assertEquals("Process ID is incorrect", expProcId, procId); + } + } else { + // On Liberty procName is just the server name. + expProcName = server.getBackend().getServerName(); +// expProcName = server.getCellName() + "\\" + server.getNodeName() + "\\" + server.getName(); + // Don't verify process Id since it is not available in Liberty FAT +// expProcId = server.getProcessIdString(); +// assertEquals("Process ID is incorrect", expProcId, procId); + } + assertEquals("Process Name is incorrect", expProcName, procName); + + this.logVerificationPassed(); + } + + this.logVerificationPoint("Verifying completeness of the test"); + if (isZOS) { + if (!hasController && !hasServant) { + fail("Test on zOS is missing both controller and servant instances"); + } + if (!hasController) { + fail("Test on zOS is missing controller instance"); + } + if (!hasServant) { + fail("Test on zOS is missing at least one servant instance"); + } + } else if (ids.size() == 0) { + fail("Test on distributed has no instances to verify"); + } + this.logVerificationPassed(); + + this.logStepCompleted(); + } + + /** + * A method to drive the execution of the binaryLog tool on the remote machine/server that is being tested. + * + * @throws Exception + */ + private ProgramOutput exeBinaryLog(String[] cmdLineOptions) throws Exception { + // make platform agnostic to handle .sh and .bat + String exeExt = ""; + final String BINARY_LOG = "binaryLog"; + + //if non-iSeries +// if (!HpelSetup.getNodeUnderTest().getMachine().getOperatingSystem().equals(OperatingSystem.ISERIES)){ + if (HpelSetup.getNodeUnderTest().getMachine().getOperatingSystem().equals(OperatingSystem.WINDOWS)) { + exeExt = ".bat"; +// } else { +// exeExt = ".sh"; + } + + StringBuilder cmd = new StringBuilder(100); + cmd.append(rProfBinFile.getAbsolutePath()).append(HpelSetup.getNodeUnderTest().getMachine().getOperatingSystem().getFileSeparator()); + cmd.append(BINARY_LOG).append(exeExt).append(" "); + + for (String cmdOption : cmdLineOptions) { + if (!cmdOption.isEmpty()) { + cmd.append("\"" + cmdOption + "\" "); + } + } + + logMsg("executing: " + cmd.toString()); +// logMsg("executing: " + rProfBinFile.getAbsolutePath() + HpelSetup.getNodeUnderTest().getMachine().getOperatingSystem().getFileSeparator() + cmd.toString()); +// return HpelSetup.getNodeUnderTest().getMachine().execute(LOG_VIEWER + exeExt, cmdLineOptions, rProfBinFile.getAbsolutePath()); + return HpelSetup.getNodeUnderTest().getMachine().execute(cmd.toString(), rProfBinFile.getAbsolutePath()); + +// } +// //iSeries LogViewer needs to be executed in the shell qsh +// else{ +// return HpelSetup.getNodeUnderTest().getMachine().executeQSH(LOG_VIEWER, cmdLineOptions, rProfBinFile.getAbsolutePath(), null); +// } + } + + @Override + public void tearDown() throws Exception { + // Restore values we saw before changing them in setUp() + this.logStep("Resetting configuration to pre test values."); + if (backup != null && backup.exists()) { + appServ.getBackend().getServerConfigurationFile().copyFromSource(backup); + } + this.logStepCompleted(); + + // call the super + super.tearDown(); + } + + /** + * Determine if we should or should not execute this test. Returns true if the test should NOT be ran. + **/ + @Override + public boolean skipTest() { + // Test does not do any good on z/OS since TextLog is for Controller only - so we can't generate logs to fill up + // TextLog repository. This may need to be revisited if we implement TextLog for servant. + try { + return HpelSetup.getNodeUnderTest().getMachine().getOperatingSystem().equals(OperatingSystem.ZOS); + } catch (Exception e) { + CommonTasks.writeLogMsg(Level.SEVERE, "Unable to determine if we are on z/OS or not. Not skipping test"); + e.printStackTrace(System.err); + } + return false; + } + + /** + * A simple method used to log messages from this test case to the test case's logs + */ + public void logMsg(String msg) { + if (thisLogger.isLoggable(Level.INFO)) { + thisLogger.info(msg); + } + } + +} \ No newline at end of file diff --git a/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/BinaryLogRecordContextTest.java b/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/BinaryLogRecordContextTest.java new file mode 100755 index 00000000000..53770950096 --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/BinaryLogRecordContextTest.java @@ -0,0 +1,151 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2014 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.fat.hpel.tests; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.ProtocolException; +import java.net.URL; + +import com.ibm.websphere.simplicity.ApplicationServer; +import com.ibm.websphere.simplicity.OperatingSystem; +import com.ibm.websphere.simplicity.ProgramOutput; +import com.ibm.websphere.simplicity.RemoteFile; +import com.ibm.ws.fat.VerboseTestCase; +import com.ibm.ws.fat.hpel.setup.HpelSetup; +import com.ibm.ws.fat.ras.util.CommonTasks; + +/** + * + */ +public class BinaryLogRecordContextTest extends VerboseTestCase { + private ApplicationServer appServ = null; + RemoteFile rProfRootDir = null; + RemoteFile rProfBinFile = null; + String localLogsRepositoryPath = null; + String extension1 = "userName=[hpel]"; + String extension2 = "productId=[liberty]"; + + /** + * @param name + */ + public BinaryLogRecordContextTest(String name) { + super(name); + // TODO Auto-generated constructor stub + } + + @Override + public void setUp() throws Exception { + // Call super.SetUp() cause we still want it's setup as well + super.setUp(); + appServ = HpelSetup.getServerUnderTest(); + // Confirm HPEL is enabled + if (!CommonTasks.isHpelEnabled(appServ)) { + // HPEL is not enabled. + this.logStep("HPEL is not enabled on " + appServ.getName() + ", attempting to enable."); + CommonTasks.setHpelEnabled(appServ, true); + // Restart now to complete switching to HPEL + appServ.restart(); + this.logStepCompleted(); + } + + // Liberty profile root is the install root. + rProfRootDir = new RemoteFile(HpelSetup.getNodeUnderTest().getMachine(), HpelSetup.getServerUnderTest().getBackend().getInstallRoot()); +// rProfRootDir = new RemoteFile(HpelSetup.getNodeUnderTest().getMachine(), HpelSetup.getNodeUnderTest().getProfileDir()); + rProfBinFile = new RemoteFile(HpelSetup.getNodeUnderTest().getMachine(), rProfRootDir, "bin"); + // Setting the bootstrap with trace specification to get the trace logs. + CommonTasks.addBootstrapProperty(appServ, "com.ibm.ws.test", "*=all=enabled"); + appServ.stop(); + appServ.start(); + + } + + /** + * This method creates a connection to a webpage and then reutrns the connection + * + * @param url The Http Address to connect to + * @return The connection to the http address + */ + private HttpURLConnection getHttpConnection(URL url) throws IOException, ProtocolException { + HttpURLConnection con = (HttpURLConnection) url.openConnection(); + con.setDoInput(true); + con.setDoOutput(true); + con.setUseCaches(false); + con.setRequestMethod("GET"); + return con; + } + + public void testBinaryLogRecordExtension() throws Exception { + System.out.println("----------testLogRecordServer starts 2-------------"); + String arg1 = "view"; + + //Access the application + URL url = new URL("http://" + appServ.getBackend().getHostname() + ":" + appServ.getBackend().getHttpDefaultPort() + "/LogFat?userName=hpel&productId=liberty"); + System.out.println("appServ.getBackend().getHttpDefaultPort() :" + appServ.getBackend().getHttpDefaultPort()); + HttpURLConnection con = getHttpConnection(url); + System.out.println("URL :" + url); + System.out.println("Response Code :" + con.getResponseCode()); + Thread.sleep(TWENTY_SECONDS); + ProgramOutput lvPrgmOut = exeBinaryLog(new String[] { arg1, appServ.getBackend().getServerName(), "--format=advanced", "--includeInstance=latest" }); + System.out.println("appServ.getBackend().getServerName() :" + appServ.getBackend().getServerName()); + String out = lvPrgmOut.getStdout(); + System.out.println("Log view server --format=advanced :" + out); + assertTrue("Extensions are added to LogRecordContext", out.contains(extension1) && out.contains(extension2)); + } + + /** + * A method to drive the execution of the binaryLog tool on the remote machine/server that is being tested. + * + * @throws Exception + */ + private ProgramOutput exeBinaryLog(String[] cmdLineOptions) throws Exception { + // make platform agnostic to handle .sh and .bat + String exeExt = ""; + final String BINARY_LOG = "binaryLog"; + + //if non-iSeries +// if (!HpelSetup.getNodeUnderTest().getMachine().getOperatingSystem().equals(OperatingSystem.ISERIES)){ + if (HpelSetup.getNodeUnderTest().getMachine().getOperatingSystem().equals(OperatingSystem.WINDOWS)) { + exeExt = ".bat"; +// } else { +// exeExt = ".sh"; + } + rProfRootDir = new RemoteFile(HpelSetup.getNodeUnderTest().getMachine(), HpelSetup.getServerUnderTest().getBackend().getInstallRoot()); +// rProfRootDir = new RemoteFile(HpelSetup.getNodeUnderTest().getMachine(), HpelSetup.getNodeUnderTest().getProfileDir()); + rProfBinFile = new RemoteFile(HpelSetup.getNodeUnderTest().getMachine(), rProfRootDir, "bin"); + StringBuilder cmd = new StringBuilder(100); + cmd.append(rProfBinFile.getAbsolutePath()).append(HpelSetup.getNodeUnderTest().getMachine().getOperatingSystem().getFileSeparator()); + cmd.append(BINARY_LOG).append(exeExt).append(" "); + + for (String cmdOption : cmdLineOptions) { + if (!cmdOption.isEmpty()) { + cmd.append("\"" + cmdOption + "\" "); + } + } + + System.out.println("executing: " + cmd.toString()); +// logMsg("executing: " + rProfBinFile.getAbsolutePath() + HpelSetup.getNodeUnderTest().getMachine().getOperatingSystem().getFileSeparator() + cmd.toString()); +// return HpelSetup.getNodeUnderTest().getMachine().execute(LOG_VIEWER + exeExt, cmdLineOptions, rProfBinFile.getAbsolutePath()); + return HpelSetup.getNodeUnderTest().getMachine().execute(cmd.toString(), rProfBinFile.getAbsolutePath()); + +// } +// //iSeries LogViewer needs to be executed in the shell qsh +// else{ +// return HpelSetup.getNodeUnderTest().getMachine().executeQSH(LOG_VIEWER, cmdLineOptions, rProfBinFile.getAbsolutePath(), null); +// } + } + + @Override + public void tearDown() throws Exception { + super.tearDown(); + } +} \ No newline at end of file diff --git a/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/ConcurrentLoggingAccuracyTest.java b/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/ConcurrentLoggingAccuracyTest.java new file mode 100755 index 00000000000..2eec3c51676 --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/ConcurrentLoggingAccuracyTest.java @@ -0,0 +1,277 @@ +//%Z% %I% %W% %G% %U% [%H% %T%] +/* + * Change History: + * + * Reason Version Date User id Description + * ---------------------------------------------------------------------------- + * F017049-18796.1 8.0 01/08/2010 spaungam Update test to support subdirectories + * F000896.23216 1.6 06/14/2010 shighbar Update test case for z/OS support. + */ +package com.ibm.ws.fat.hpel.tests; + +import java.io.File; +import java.util.Date; +import java.util.logging.Level; + +import com.ibm.websphere.logging.hpel.reader.RepositoryLogRecord; +import com.ibm.websphere.logging.hpel.reader.RepositoryReaderImpl; +import com.ibm.websphere.logging.hpel.reader.ServerInstanceLogRecordList; +import com.ibm.websphere.simplicity.Machine; +import com.ibm.websphere.simplicity.RemoteFile; +import com.ibm.ws.fat.Props; +import com.ibm.ws.fat.VerboseTestCase; +import com.ibm.ws.fat.hpel.setup.HpelSetup; +import com.ibm.ws.fat.ras.util.CommonTasks; + +/** + * Tests that more than one thread can correctly write to a single repository at the same time. + * + */ +public class ConcurrentLoggingAccuracyTest extends VerboseTestCase { + int loggerCount = 40; + int iterations = 40; + int secondsToSleep = 169; // milliseconds + int totalCount = loggerCount * iterations; + private final String[] loggers = new String[loggerCount]; + String localLogsRepositoryPath = null; + String localTraceRepositoryPath = null; + String uniqueLoggerID_Tag; + String loggerName = "ConAccLogger"; + final String TRACE_SPECIFICATION = "ConAccLogger*=all"; // trace spec needed for this test case. + + public ConcurrentLoggingAccuracyTest(String name) { + super(name); + } + + @Override + public void setUp() throws Exception { + // Call super.SetUp() cause we still want it's setup as well + super.setUp(); + + // Confirm HPEL is enabled + if (!CommonTasks.isHpelEnabled(HpelSetup.getServerUnderTest())) { + // HPEL is not enabled. + this.logStep("HPEL is not enabled on " + HpelSetup.getServerUnderTest().getName() + ", attempting to enable."); + CommonTasks.setHpelEnabled(HpelSetup.getServerUnderTest(), true); + // if HPEL was not enabled, make sure trace spec is not valid to ensure restart below. + CommonTasks.setHpelTraceSpec(HpelSetup.getServerUnderTest(), null); + this.logStepCompleted(); + } + + /* + * Since we have multiple test methods in this test case, we will only restart if the spec is not already set to + * what we need. This will avoid extra server restarts which adds to the bucket execution time. + */ + this.logStep("Checking the HPEL trace spec for " + this.getName()); + if (!CommonTasks.getHpelTraceSpec(HpelSetup.getServerUnderTest()).equals(TRACE_SPECIFICATION)) { + // The current spec is not what we need for this test - update spec and bounce server to take effect + this.logStep("Updating the hpel trace spec to " + TRACE_SPECIFICATION + " as part of setup for " + this.getName()); + CommonTasks.setHpelTraceSpec(HpelSetup.getServerUnderTest(), TRACE_SPECIFICATION); + + // need to restart the application server now + // Stop Server first. + this.logStep("Bouncing server for new spec to take effect. Stopping application server"); + HpelSetup.getServerUnderTest().stop(); + this.logStepCompleted(); + + Thread.sleep(10000); // stop operation blocks, but want short pause before restarting. + + // Start Server + this.logStep("Restarting the application server"); + HpelSetup.getServerUnderTest().start(); + + this.logStep("Checking the trace spec post app server restart: " + + CommonTasks.getHpelTraceSpec(HpelSetup.getServerUnderTest())); + assertTrue("Failed assertion that HPEL trace specification is set to " + TRACE_SPECIFICATION, TRACE_SPECIFICATION + .equals(CommonTasks.getHpelTraceSpec(HpelSetup.getServerUnderTest()))); + this.logStepCompleted(); + } + } + + private void setupLoggers() { + // setup a new unique identifier for the logger name + Date d = new Date(); + for (int i = 0; i < loggers.length; i++) { + loggers[i] = loggerName + d + "_" + i; + } + } + + /** + * A utility method to get all of the repository logs as well as the trace logs. + */ + private void getLogsFromServer() throws Exception { + RemoteFile remoteLogsDir = CommonTasks.getBinaryLogDir(HpelSetup.getServerUnderTest()); + RemoteFile localLogsResultsDir = new RemoteFile(Machine.getLocalMachine(), Props.getFileProperty(Props.DIR_LOG) + .getCanonicalPath() + + File.separator + ConcurrentLoggingAccuracyTest.class.getSimpleName()); + + // Save off the path of the repository log files directory + localLogsRepositoryPath = localLogsResultsDir.getAbsolutePath(); + + localLogsResultsDir.copyFromSource(remoteLogsDir, true, true); + } + + /** + * Tests that HPEL accurately reports the number of logs records entered. Assumes that HPEL is enabled on the active + * server + */ + public void testConcurrentLoggingAccuracyCheck() throws Exception { + this.logStep("Creating logger name"); + setupLoggers(); + this.logStepCompleted(); + + this.logStep("Creating the log entries"); + createLogEntries(); + this.logStepCompleted(); + + Thread.sleep(10000); // wait to ensure logs are written out. Default flash is 10 secs. + + // Get the logs from the server to check what is in them + this.logStep("Getting the message logs from the server"); + getLogsFromServer(); + this.logStepCompleted(); + + // Go read the repository and see if it has what we are looking for + this.logStep("Use API to read HPEL repository"); + + // Go read the repository and see if it has what we are looking for + RepositoryReaderImpl logRepository = new RepositoryReaderImpl(localLogsRepositoryPath); + ServerInstanceLogRecordList CurrentProcessLogList = logRepository.getLogListForCurrentServerInstance(); + // record list is the list of records we will compare against. Assume it's the currentServerInstance list by + // default. + Iterable recordList = CurrentProcessLogList; + + /* + * Note, if we are on z/OS the CurrentProcessLogList represents only the controller's logs. Our test log entries + * will be written by servant though. Will setup a Merged repository to include all the logs from sub-process + * instances. + */ + //The problem is with how test counts records on zOS. HPEL allows server to have a parent process (controller) with a set of child processes (servants). + //For such servers result for a server instance has none empty result from getChildren() call. The test problem is that it assumes that logs recorded by an application on zOS can be found _only_ in children processes. + //On Liberty that is not the case since even on zOS server consists of a single process processing all the requests. + + //The problem can be solved in two ways. 1. Remove 'if zOS' condition since the test is maintained separately on Liberty. + //2. Adjust test to do merge between parent and children logs for all OSs. Following the first solution here. + + //if (HpelSetup.getNodeUnderTest().getMachine().getOperatingSystem().equals(OperatingSystem.ZOS)) { + //this.logStep("Since this is z/OS - using a MergedRepository representing all the servant and adjunct sub-processes"); + //recordList = new MergedRepository(CurrentProcessLogList.getChildren().values()); + //} + + this.logStep("Counting log records by level"); + int severe = 0; + int warning = 0; + int info = 0; + int fine = 0; + int finer = 0; + int finest = 0; + for (RepositoryLogRecord record : recordList) { + // process a record + if (record.getLoggerName().startsWith((loggerName))) { + switch (record.getLevel().intValue()) { + case 1000: // SEVERE == 1000 + severe++; + break; + case 900: // WARNING == 900 + warning++; + break; + case 800: // INFO == 800 + info++; + break; + case 500: // FINE == 500 + fine++; + break; + case 400: // FINER == 400 + finer++; + break; + case 300: // FINEST == 300 + finest++; + break; + } + } + } + this.logStepCompleted(); + + this.logVerificationPoint("Verifying the repository log (Level.SEVERE) count against the expected count."); + assertTrue("The repository does not contain the number of records it had wrote for Level.SEVERE {counted:wrote} {" + severe + + ":" + totalCount + "}", severe == totalCount); + this.logVerificationPassed(); + + this.logVerificationPoint("Verifying the repository log (Level.WARNING) count against the expected count."); + assertTrue("The repository does not contain the number of records it had wrote for Level.WARNING {counted:wrote} {" + warning + + ":" + totalCount + "}", warning == totalCount); + this.logVerificationPassed(); + + this.logVerificationPoint("Verifying the repository log (Level.INFO) count against the expected count."); + assertTrue("The repository does not contain the number of records it had wrote for Level.INFO {counted:wrote} {" + info + ":" + + totalCount + "}", info == totalCount); + this.logVerificationPassed(); + + this.logVerificationPoint("Verifying the repository trace count (Level.FINE) against the expected count."); + assertTrue("The repository does not contain the number of records it had wrote for Level.FINE {counted:wrote} {" + fine + ":" + + totalCount + "}", fine == totalCount); + this.logVerificationPassed(); + + this.logVerificationPoint("Verifying the repository trace count (Level.FINER) against the expected count."); + assertTrue("The repository does not contain the number of records it had wrote for Level.FINER {counted:wrote} {" + finer + + ":" + totalCount + "}", finer == totalCount); + this.logVerificationPassed(); + + this.logVerificationPoint("Verifying the repository trace count (Level.FINEST) against the expected count."); + assertTrue("The repository does not contain the number of records it had wrote for Level.FINEST {counted:wrote} {" + finest + + ":" + totalCount + "}", finest == totalCount); + this.logVerificationPassed(); + } + + /** + * Driver method for executing all the LoggerThread instances. This method will not return until all the Loggers + * have completed writing their records. + * + */ + public void createLogEntries() throws Exception { + LoggerThread[] lt = new LoggerThread[loggerCount]; + + for (int i = 0; i < loggers.length; i++) { + lt[i] = new LoggerThread(loggers[i]); + } + + for (int i = 0; i < lt.length; i++) { + lt[i].start(); + } + + // cycle thru all the threads until each one has finished + for (int i = 0; i < lt.length; i++) { + while (lt[i].isAlive()) { + try { + Thread.sleep(500); + } catch (InterruptedException ie) { + // do nothing in this case. + } + } + } + } + + /** + * Thread definition that will be writing to the repository. + * + * @author schleus + * + */ + class LoggerThread extends Thread { + private String loggerName = null; + + public LoggerThread(String name) { + this.loggerName = name; + } + + @Override + public void run() { + try { + CommonTasks.createLogEntries(HpelSetup.getServerUnderTest(), loggerName, "Hi from logger " + loggerName + " in this thread", Level.ALL, iterations, + CommonTasks.LOGS_TRACE, secondsToSleep); + } catch (Exception e) { + // nothing for now + } + } + } +} diff --git a/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/HPELDataDirFalsePositiveWarningTest.java b/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/HPELDataDirFalsePositiveWarningTest.java new file mode 100755 index 00000000000..992733943df --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/HPELDataDirFalsePositiveWarningTest.java @@ -0,0 +1,129 @@ +//%Z% %I% %W% %G% %U% [%H% %T%] +/** + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + * + * DESCRIPTION: + * + * Change History: + * + * Reason Version Date User id Description + * ---------------------------------------------------------------------------- + * 91932 8.5.5 13/06/2013 sumam Test case for defect 91932. + * + */ + +package com.ibm.ws.fat.hpel.tests; + +import java.io.File; +import java.util.List; +import java.util.logging.Logger; + +import com.ibm.websphere.simplicity.ApplicationServer; +import com.ibm.websphere.simplicity.RemoteFile; +import com.ibm.ws.fat.VerboseTestCase; +import com.ibm.ws.fat.hpel.setup.HpelSetup; +import com.ibm.ws.fat.ras.util.CommonTasks; + +/** + * Test case for defect 91932: HPEL gives false positive warning on disk space after changing dataDirectory + * Test Scenario: Start the server by logDirectory as logs → modify it to logX and delete the old directory (logs) , no warning message should be generated. + * + */ + +public class HPELDataDirFalsePositiveWarningTest extends VerboseTestCase { + + private final static String loggerName = HPELDataDirFalsePositiveWarningTest.class.getName(); + private final static Logger logger = Logger.getLogger(loggerName); + private final static String MESSAGE_LOG = "logs/console.log"; + + private ApplicationServer appServ = null; + + RemoteFile backup = null; + + public HPELDataDirFalsePositiveWarningTest(String name) { + super(name); + } + + @Override + public void setUp() throws Exception { + // Call super.SetUp() cause we still want it's setup as well + super.setUp(); + appServ = HpelSetup.getServerUnderTest(); + // Confirm HPEL is enabled + if (!CommonTasks.isHpelEnabled(appServ)) { + // HPEL is not enabled. + this.logStep("HPEL is not enabled on " + appServ.getName() + ", attempting to enable."); + CommonTasks.setHpelEnabled(appServ, true); + // Restart now to complete switching to HPEL + appServ.stop(); + appServ.start(); + this.logStepCompleted(); + } + + this.logStep("Configuring server for test case."); + backup = new RemoteFile(appServ.getBackend().getMachine(), new File(appServ.getBackend().getServerRoot(), "server-backup.xml").getPath()); + if (!backup.exists()) { + backup.copyFromSource(appServ.getBackend().getServerConfigurationFile()); + } + appServ.getBackend().updateServerConfiguration(new File(appServ.getBackend().pathToAutoFVTTestFiles, "server-HPELDeleteLogDirectory_1.xml")); + if (!appServ.getBackend().isStarted()) { + appServ.start(); + } + + this.logStepCompleted(); + + } + + /** + * Test that HPEL's logDirectory change does not give any warning message. + * Start the server with logDirectory as "LogX1", during the runtime change the logDirectory to "logX2" and delete the old directory i.e. logX1, + * No warning message should be created for deleting the old unused directory + * + **/ + public void testLogDirectoryChange() throws Exception { + + this.logStep("Configuring server for test case."); + appServ.getBackend().updateServerConfiguration(new File(appServ.getBackend().pathToAutoFVTTestFiles, "server-HPELDeleteLogDirectory_2.xml")); + this.logStepCompleted(); + + // Deleting the old directory and checking for the warning message. + + this.logStep(" Deleting the logs directory to check the warning message"); + appServ.getBackend().deleteFileFromLibertyServerRoot("logX1"); + this.logStepCompleted(); + + this.logVerificationPoint("Verifying no warning message generated for old log directory deleted ."); + logger.info("The console.log should not have a error message HPEL0161W "); + checkWarningMessageForDirectoryDelete(); + this.logVerificationPassed(); + + } + + //Check we dont have any warning message for old directory deleted. + protected void checkWarningMessageForDirectoryDelete() throws Exception { + List lines = appServ.getBackend().findStringsInFileInLibertyServerRoot("HPEL0161W", MESSAGE_LOG); + assertEquals("Message HPEL0161W appeared in the console file", 0, lines.size()); + } + + @Override + public void tearDown() throws Exception { + // Restore values we saw before changing them in setUp() + this.logStep("Resetting configuration to pre test values."); + if (backup != null && backup.exists()) { + appServ.getBackend().getServerConfigurationFile().copyFromSource(backup); + } + this.logStepCompleted(); + + // call the super + super.tearDown(); + } + +} \ No newline at end of file diff --git a/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/HPELLogDirectoryPurgeMaxSizeTest.java b/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/HPELLogDirectoryPurgeMaxSizeTest.java new file mode 100755 index 00000000000..d592d005992 --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/HPELLogDirectoryPurgeMaxSizeTest.java @@ -0,0 +1,146 @@ +//%Z% %I% %W% %G% %U% [%H% %T%] +/** + * + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + * + * DESCRIPTION: + * + * Change History: + * + * Reason Version Date User id Description + * ---------------------------------------------------------------------------- + * 91930 8.5.5 13/06/2013 sumam Test case for defect 91930. + */ + +package com.ibm.ws.fat.hpel.tests; + +import java.io.File; +import java.text.NumberFormat; +import java.util.logging.Logger; + +import com.ibm.websphere.simplicity.ApplicationServer; +import com.ibm.websphere.simplicity.RemoteFile; +import com.ibm.ws.fat.VerboseTestCase; +import com.ibm.ws.fat.hpel.setup.HpelSetup; +import com.ibm.ws.fat.ras.util.CommonTasks; + +/** + * Test case for defect 91930: HPEL log ignores purgeMaxSize after dataDirectory is changed. + * While changing the path of logDirectory to new location it should use the should follow the same purgeMaxSize property. + * Testing scenario: Start the server with logDirectory as logs and purgeMaxSize = 29 → during runtime change the logDirectory as logX and check for the purgeMaxSize property for + * the new repository, it should not exceed 29 MB. + * + */ + +public class HPELLogDirectoryPurgeMaxSizeTest extends VerboseTestCase { + + private final static String loggerName = HpelLogDirectoryChangeTest.class.getName(); + private final static Logger logger = Logger.getLogger(loggerName); + private final static int MAX_DEFAULT_PURGE_SIZE = 30; + + private ApplicationServer appServ = null; + + RemoteFile backup = null; + + public HPELLogDirectoryPurgeMaxSizeTest(String name) { + super(name); + } + + @Override + public void setUp() throws Exception { + // Call super.SetUp() cause we still want it's setup as well + super.setUp(); + appServ = HpelSetup.getServerUnderTest(); + // Confirm HPEL is enabled + if (!CommonTasks.isHpelEnabled(appServ)) { + // HPEL is not enabled. + this.logStep("HPEL is not enabled on " + appServ.getName() + ", attempting to enable."); + CommonTasks.setHpelEnabled(appServ, true); + // Restart now to complete switching to HPEL + appServ.stop(); + appServ.start(); + this.logStepCompleted(); + } + + this.logStep("Configuring server for test case."); + backup = new RemoteFile(appServ.getBackend().getMachine(), new File(appServ.getBackend().getServerRoot(), "server-backup.xml").getPath()); + if (!backup.exists()) { + backup.copyFromSource(appServ.getBackend().getServerConfigurationFile()); + } + appServ.getBackend().updateServerConfiguration(new File(appServ.getBackend().pathToAutoFVTTestFiles, "server-HpelDirChangePurgeMaxTest_1.xml")); + if (!appServ.getBackend().isStarted()) { + appServ.start(); + } + + this.logStepCompleted(); + + } + + /** + * Test that logs generated are retaining the purgeMaxSize value for new location. + * Start the server with logDirectory as logs and purgeMaxSize as 29 MB, during runtime change the logDirectory to logx and run quick log + * the new repository should not exceed size more than 29 MB. + **/ + public void testLogDirectoryChange() throws Exception { + RemoteFile binaryLogDir = null; + NumberFormat nf = NumberFormat.getInstance(); + + this.logStep("Configuring server for test case."); + appServ.getBackend().updateServerConfiguration(new File(appServ.getBackend().pathToAutoFVTTestFiles, "server-HpelDirChangePurgeMaxTest_2.xml")); + this.logStepCompleted(); + + // write enough records to new log repository updated. + this.logStep("Writting log records to fill binary log repository."); + long loopsPerFullRepository = (MAX_DEFAULT_PURGE_SIZE * 1024 * 1024) / 200; + logger.info("writting " + nf.format(loopsPerFullRepository) + " log loops to produce " + MAX_DEFAULT_PURGE_SIZE + + " MB of data."); + CommonTasks.createLogEntries(appServ, loggerName, "Sample log record for the test case " + this.getName() + ".", null, + (int) loopsPerFullRepository, CommonTasks.LOGS, 0); + this.logStepCompleted(); + + this.logVerificationPoint("Verifying the repository size for new location is same as old"); + binaryLogDir = appServ.getBackend().getFileFromLibertyServerRoot("logx/logdata"); + long binaryLogSize = getSizeOfBinaryLogs(binaryLogDir); + logger.info("The current size of BinaryLog files in " + binaryLogDir.getAbsolutePath() + " is " + nf.format(binaryLogSize)); + assertTrue("BinaryLog Repository size should be less than 29 MB ", + binaryLogSize < (29 * 1024 * 1024) && binaryLogSize > ((MAX_DEFAULT_PURGE_SIZE - 5) * 1024 * 1024)); + this.logVerificationPassed(); + + } + + /** + * Returns the total size of log files in the given directory + * + * @throws Exception + **/ + private long getSizeOfBinaryLogs(RemoteFile dirToCheck) throws Exception { + long totalgRepositorySize = 0; + RemoteFile[] allLogFiles = dirToCheck.list(true); + for (RemoteFile i : allLogFiles) { + totalgRepositorySize += i.length(); + } + return totalgRepositorySize; + } + + @Override + public void tearDown() throws Exception { + // Restore values we saw before changing them in setUp() + this.logStep("Resetting configuration to pre test values."); + if (backup != null && backup.exists()) { + appServ.getBackend().getServerConfigurationFile().copyFromSource(backup); + } + this.logStepCompleted(); + + // call the super + super.tearDown(); + } + +} \ No newline at end of file diff --git a/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/HPELPurgeMaxSizeErrorTest.java b/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/HPELPurgeMaxSizeErrorTest.java new file mode 100755 index 00000000000..c871f8af582 --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/HPELPurgeMaxSizeErrorTest.java @@ -0,0 +1,116 @@ +//%Z% %I% %W% %G% %U% [%H% %T%] +/** + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + * + * DESCRIPTION: + * + * Change History: + * + * Reason Version Date User id Description + * ---------------------------------------------------------------------------- + * 91947 8.5.5 13/06/2013 sumam Test case for defect 91947. + */ + +package com.ibm.ws.fat.hpel.tests; + +import java.io.File; +import java.util.List; +import java.util.logging.Logger; + +import com.ibm.websphere.simplicity.ApplicationServer; +import com.ibm.websphere.simplicity.RemoteFile; +import com.ibm.ws.fat.VerboseTestCase; +import com.ibm.ws.fat.hpel.setup.HpelSetup; +import com.ibm.ws.fat.ras.util.CommonTasks; + +/** + * Test case for defect 91947 : HPEL purgeMaxSize/purgeMinTime should follow convention for min value from logging + * Test scenario: Set the server.xml purgeMaxSize = -1 and start the server warning message should be generated + */ + +public class HPELPurgeMaxSizeErrorTest extends VerboseTestCase { + + private final static String loggerName = HPELPurgeMaxSizeErrorTest.class.getName(); + private final static Logger logger = Logger.getLogger(loggerName); + private final static String MESSAGE_LOG = "logs/console.log"; + + private ApplicationServer appServ = null; + + RemoteFile backup = null; + + public HPELPurgeMaxSizeErrorTest(String name) { + super(name); + } + + @Override + public void setUp() throws Exception { + // Call super.SetUp() cause we still want it's setup as well + super.setUp(); + appServ = HpelSetup.getServerUnderTest(); + // Confirm HPEL is enabled + if (!CommonTasks.isHpelEnabled(appServ)) { + // HPEL is not enabled. + this.logStep("HPEL is not enabled on " + appServ.getName() + ", attempting to enable."); + CommonTasks.setHpelEnabled(appServ, true); + // Restart now to complete switching to HPEL + appServ.stop(); + appServ.start(); + this.logStepCompleted(); + } + + this.logStep("Configuring server for test case."); + backup = new RemoteFile(appServ.getBackend().getMachine(), new File(appServ.getBackend().getServerRoot(), "server-backup.xml").getPath()); + if (!backup.exists()) { + backup.copyFromSource(appServ.getBackend().getServerConfigurationFile()); + } + // Setting the server.xml with purgeMaxSize = -1 + appServ.getBackend().updateServerConfiguration(new File(appServ.getBackend().pathToAutoFVTTestFiles, "server-HPELPurgeMaxSizeInvalid.xml")); + if (!appServ.getBackend().isStarted()) { + appServ.start(); + } + + this.logStepCompleted(); + + } + + /** + * Test that server gives error message for setting purgeMaxSize = -1 + * Set the purgeMaxSize property = -1 in server.xml for both and , start the server and check for the warning message for invalid purgeMaxSize. + **/ + public void testPurgeMaxSizeProperty() throws Exception { + + this.logVerificationPoint(" Verifying the console.log should have a error message for invalid purgeMaxSize property "); + logger.info(" The console.log should have a error message CWWKG0075E for setting purgeMaxSize property to -1 "); + checkErrorMessageForInvalidPurgeMaxSizeExists(); + this.logVerificationPassed(); + + } + + //Check if we have one Error Message for invalid purgeMaxSize property. + protected void checkErrorMessageForInvalidPurgeMaxSizeExists() throws Exception { + List lines = appServ.getBackend().findStringsInFileInLibertyServerRoot("CWWKG0075E", MESSAGE_LOG); + assertTrue(" Message CWWKG0075E did not appear in console.log ", lines.size() > 0); + } + + @Override + public void tearDown() throws Exception { + // Restore values we saw before changing them in setUp() + this.logStep("Resetting configuration to pre test values."); + if (backup != null && backup.exists()) { + appServ.getBackend().getServerConfigurationFile().copyFromSource(backup); + } + this.logStepCompleted(); + + // call the super + super.tearDown(); + } + +} \ No newline at end of file diff --git a/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/HpelDeleteEmptyDirectories.java b/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/HpelDeleteEmptyDirectories.java new file mode 100755 index 00000000000..8a2ed23cac2 --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/HpelDeleteEmptyDirectories.java @@ -0,0 +1,312 @@ +//%Z% %I% %W% %G% %U% [%H% %T%] +/** + * COMPONENT_NAME: WAS.ras.fvt + * + * ORIGINS: 27 (used for IBM originated files) + * + * IBM Confidential OCO Source Material + * 5639-D57 (C) COPYRIGHT International Business Machines Corp. 2002 + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + * + * @author olteamh + * + * DESCRIPTION: + * + * Change History: + * + * Reason Version Date User id Description + * ---------------------------------------------------------------------------- + * 702533 8.0 09/01/2011 olteamh Check that empty hpel instance directories are deleted. + */ + +package com.ibm.ws.fat.hpel.tests; + +import java.io.File; +import java.util.ArrayList; +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.ibm.websphere.simplicity.ApplicationServer; +import com.ibm.websphere.simplicity.Machine; +import com.ibm.websphere.simplicity.RemoteFile; +import com.ibm.ws.fat.VerboseTestCase; +import com.ibm.ws.fat.hpel.setup.HpelSetup; +import com.ibm.ws.fat.ras.util.CommonTasks; + +/** + * Test case for defect 702533: Hpel leaves empty instance repositories behind + * + * @author olteamh + * + */ + +public class HpelDeleteEmptyDirectories extends VerboseTestCase { + + private final static String loggerName = HpelDeleteEmptyDirectories.class.getName(); + private final static Logger logger = Logger.getLogger(loggerName); + private final static String tempTraceSpec = "*=info:" + loggerName + "*=all"; // trace spec needed for this test case. + String defaultTraceSpec = null; // original trace spec + boolean defaultLogPurgeEnabled; // original purgeBySize + boolean defaultTracePurgeEnabled; // original purgeBySize + int defaultLogPurgeSize; + int defaultTracePurgeSize; + + RemoteFile backup = null; + + public HpelDeleteEmptyDirectories(String name) { + super(name); + } + + @Override + public void setUp() throws Exception { + // Call super.SetUp() cause we still want it's setup as well + super.setUp(); + ApplicationServer appServ = HpelSetup.getServerUnderTest(); + // Confirm HPEL is enabled + if (!CommonTasks.isHpelEnabled(appServ)) { + // HPEL is not enabled. + this.logStep("HPEL is not enabled on " + appServ.getName() + ", attempting to enable."); + CommonTasks.setHpelEnabled(appServ, true); + appServ.stop(); + appServ.start(); + this.logStepCompleted(); + } + + backup = new RemoteFile(appServ.getBackend().getMachine(), new File(appServ.getBackend().getServerRoot(), "server-backup.xml").getPath()); + if (!backup.exists()) { + backup.copyFromSource(appServ.getBackend().getServerConfigurationFile()); + } + appServ.getBackend().updateServerConfiguration(new File(appServ.getBackend().pathToAutoFVTTestFiles, "server-HpelDeleteEmptyDirectories.xml")); + +// ConfigObject logChild = CommonTasks.getBinaryLogChild(appServ); +// defaultLogPurgeEnabled = logChild.getAttributeByName("purgeBySizeEnabled").getValueAsBoolean(); +// // Test requires that purgeBySize be enabled. +// logChild.getAttributeByName("purgeBySizeEnabled").setValue(true); +// defaultLogPurgeSize = logChild.getAttributeByName("purgeMaxSize").getValueAsInt(); +// // Speed up test by setting purge size to minimum possible +// logChild.getAttributeByName("purgeMaxSize").setValue(10); +// +// ConfigObject traceChild = CommonTasks.getBinaryTraceChild(appServ); +// defaultTracePurgeEnabled = traceChild.getAttributeByName("purgeBySizeEnabled").getValueAsBoolean(); +// // Test requires that purgeBySize be enabled. +// traceChild.getAttributeByName("purgeBySizeEnabled").setValue(true); +// defaultTracePurgeSize = traceChild.getAttributeByName("purgeMaxSize").getValueAsInt(); +// // Speed up test by setting purge size to minimum possible +// traceChild.getAttributeByName("purgeMaxSize").setValue(10); + + defaultTraceSpec = CommonTasks.getHpelTraceSpec(appServ); + CommonTasks.setHpelTraceSpec(appServ, tempTraceSpec); + + // Sync changes before restarting the server. + HpelSetup.getCellUnderTest().getWorkspace().saveAndSync(); + + // stop the server + if (appServ.getBackend().isStarted()) { +// if (appServ.getServerStatus().equals(ProcessStatus.RUNNING)) { + // The server is running. + this.logStep("The server is running, attempting to stop."); + appServ.stop(); + this.logStepCompleted(); + } + + // restart the server + if (!appServ.getBackend().isStarted()) { +// if (!appServ.getServerStatus().equals(ProcessStatus.RUNNING)) { + // The server is not running. + this.logStep("The server is not running, attempting to start."); + appServ.start(); + this.logStepCompleted(); + } + } + + /** + * This test writes enough entries to cause HPEL to delete the .wbl files from the + * previous server instance and checks that the parent directories are deleted when empty + **/ + public void testHPELDeleteEmptyInstanceDirectories() throws Exception { + String repositoryDirString = null; + int logPurgeMaxSize = 0; + int tracePurgeMaxSize = 0; + int logLoopsToDo = 0; + int traceLoopsToDo = 0; + ApplicationServer appServ = null; + RemoteFile serverLogdataDir = null; + RemoteFile serverTracedataDir = null; + Machine remoteMachine = null; + + this.logStep("Building parameters"); + appServ = HpelSetup.getServerUnderTest(); + remoteMachine = appServ.getNode().getMachine(); + + RemoteFile repositoryDir = CommonTasks.getBinaryLogDir(HpelSetup.getServerUnderTest()); + repositoryDirString = repositoryDir.getAbsolutePath(); + + serverLogdataDir = new RemoteFile(remoteMachine, repositoryDir, "logdata"); + serverTracedataDir = new RemoteFile(remoteMachine, repositoryDir, "tracedata"); + + logPurgeMaxSize = 10; //CommonTasks.getBinaryLogChild(appServ).getAttributeByName("purgeMaxSize").getValueAsInt(); + tracePurgeMaxSize = 10; //CommonTasks.getBinaryTraceChild(appServ).getAttributeByName("purgeMaxSize").getValueAsInt(); + logger.log(Level.INFO, "HPEL trace spec is: " + CommonTasks.getHpelTraceSpec(appServ)); + logger.log(Level.INFO, "Running the test case for repository directory: " + repositoryDirString); + logger.log(Level.INFO, "Running the test case for logdata directory: " + serverLogdataDir); + logger.log(Level.INFO, "Running the test case for tracedata directory: " + serverTracedataDir); + logger.log(Level.INFO, "Running the test case with trace purge size: " + tracePurgeMaxSize); + logger.log(Level.INFO, "Running the test case with log purge size: " + logPurgeMaxSize); + logger.log(Level.INFO, "Application server is named: " + appServ.getName()); + + //Make sure the arguments are valid + assertNotNull("The repository directory is null", repositoryDirString); + assertNotNull("The repository log directory is null", serverLogdataDir); + assertNotNull("The repository tracedirectory is null", serverTracedataDir); + + //Get list of all directories in repository before the test starts + RemoteFile[] preLogDirs = listInstanceDirectories(serverLogdataDir); + RemoteFile[] preTraceDirs = listInstanceDirectories(serverTracedataDir); + + //all empty instance repository dirs should have been deleted when the server starts + for (int m = 0; m < preLogDirs.length; m++) { + assertTrue("An empty log instance directory " + preLogDirs[m] + " has been found after server start up", preLogDirs[m].list(true).length != 0); + } + + for (int m = 0; m < preTraceDirs.length; m++) { + assertTrue("An empty trace instance directory " + preTraceDirs[m] + " has been found after server start up", preTraceDirs[m].list(true).length != 0); + } + + // Calculate number of loops of logging to perform + int logBytesToGo = (logPurgeMaxSize * 1024 * 1024); // bytes remaining before max + int traceBytesToGo = (tracePurgeMaxSize * 1024 * 1024); + logLoopsToDo = (logBytesToGo / 100); + traceLoopsToDo = (traceBytesToGo / 100); + logger.log(Level.INFO, "Maximum log iterations: " + logLoopsToDo); + logger.log(Level.INFO, "Maximum trace iterations: " + traceLoopsToDo); + + // Log messages on application server. + this.logStep("Creating log messages."); + + // Write some log records to have a reference point for the big loop bellow. + CommonTasks.createLogEntries(appServ, loggerName, "Initial log record for delete empty instance repositories test.", + null, 10, CommonTasks.LOGS, 0); + + RemoteFile logFile = getMostRecentLog(serverLogdataDir); + assertNotNull("Did not find any WBL files in log directory " + serverLogdataDir, logFile); + for (int i = 0; i < logLoopsToDo; i += 100) { + CommonTasks.createLogEntries(appServ, loggerName, "Log record for delete empty instance repositories test.", + null, 100, CommonTasks.LOGS, 0); + // Keep logging until all files we had before the test are purged + if (!logFile.exists()) { + logger.log(Level.INFO, "Exiting writting log records after {0} loops", i); + break; + } + } + + // Write some trace records to have a reference point for the big loop bellow. + CommonTasks.createLogEntries(appServ, loggerName, "Initial trace record for delete empty instance repositories test.", + null, 10, CommonTasks.TRACE, 0); + + RemoteFile traceFile = getMostRecentLog(serverTracedataDir); + assertNotNull("Did not find any WBL files in trace directory " + serverTracedataDir, traceFile); + for (int i = 0; i < traceLoopsToDo; i += 100) { + CommonTasks.createLogEntries(appServ, loggerName, "Trace record for delete empty instance repositories test.", + null, 100, CommonTasks.TRACE, 0); + // Keep logging until all files we had before the test are purged + if (!traceFile.exists()) { + logger.log(Level.INFO, "Exiting writting trace records after {0} loops", i); + break; + } + } + + this.logStepCompleted(); + + // Short pause to ensure that any deletes HPEL did are processed before we recalculate. + Thread.sleep(2500); + + RemoteFile[] postLogDirs = listInstanceDirectories(serverLogdataDir); + RemoteFile[] postTraceDirs = listInstanceDirectories(serverTracedataDir); + + //Check that there are no empty instance directories at the end of the test + for (int m = 0; m < postLogDirs.length; m++) { + assertTrue("An empty log instance directory has been found", postLogDirs[m].list(true).length != 0); + + } + for (int m = 0; m < postTraceDirs.length; m++) { + assertTrue("An empty trace instance directory has been found", postTraceDirs[m].list(true).length != 0); + } + + } + + @Override + public void tearDown() throws Exception { + ApplicationServer appServ = HpelSetup.getServerUnderTest(); + + // Restore values we saw before changing them in setUp() + this.logStep("Resetting configuration to pre test values."); + if (backup != null && backup.exists()) { + appServ.getBackend().getServerConfigurationFile().copyFromSource(backup); + } + +// ConfigObject logChild = CommonTasks.getBinaryTraceChild(appServ); +// logChild.getAttributeByName("purgeBySizeEnabled").setValue(defaultLogPurgeEnabled); +// logChild.getAttributeByName("purgeMaxSize").setValue(defaultLogPurgeSize); +// +// ConfigObject traceChild = CommonTasks.getBinaryTraceChild(appServ); +// traceChild.getAttributeByName("purgeBySizeEnabled").setValue(defaultTracePurgeEnabled); +// traceChild.getAttributeByName("purgeMaxSize").setValue(defaultTracePurgeSize); + + CommonTasks.setHpelTraceSpec(appServ, defaultTraceSpec); + + HpelSetup.getCellUnderTest().getWorkspace().saveAndSync(); + + // No need to restart server in Liberty if it's not bootstrap.properties changes. +// this.logStep("Restarting server " + appServ.getName() + " to enable settings available before the test."); +// appServ.stop(); +// appServ.start(); +// this.logStepCompleted(); + + // call the super + super.tearDown(); + } + + // Find most recent WBL file in the repository + private RemoteFile getMostRecentLog(RemoteFile repositoryBase) throws Exception { + assertNotNull("RepositoryBase was unexpectedly null", repositoryBase); + assertTrue(repositoryBase + " does not exist", repositoryBase.exists()); + assertTrue(repositoryBase + " is not a directory", repositoryBase.isDirectory()); + RemoteFile[] fileArray = repositoryBase.list(true); + assertNotNull("Failed to list files in " + repositoryBase, fileArray); + RemoteFile result = null; + long timestamp = -1; + for (RemoteFile curFile : fileArray) { + String name = curFile.getName(); + if (curFile.isFile() && name.endsWith(".wbl")) { + long otherTimestamp = Long.parseLong(name.substring(0, name.length() - 4)); + if (otherTimestamp > timestamp) { + result = curFile; + timestamp = otherTimestamp; + } + } + } + return result; + } + + private RemoteFile[] listInstanceDirectories(RemoteFile repositoryBase) throws Exception { + assertNotNull("RepositoryBase was unexpectedly null", repositoryBase); + ArrayList curFiles = new ArrayList(); + + assertTrue(repositoryBase + " does not exist", repositoryBase.exists()); + assertTrue(repositoryBase + " is not a directory", repositoryBase.isDirectory()); + RemoteFile[] fileArray = repositoryBase.list(true); + assertNotNull("Failed to list files in " + repositoryBase, fileArray); + // recursive=true cause all files and directories return from the call, so no need to make calls in subdirectories. + for (RemoteFile curFile : fileArray) { + if (curFile.isDirectory()) { + curFiles.add(curFile); + } + } + + logger.log(Level.INFO, "Listing " + repositoryBase + " found " + curFiles.size() + " directories"); + return curFiles.toArray(new RemoteFile[curFiles.size()]); + } + +} \ No newline at end of file diff --git a/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/HpelLogDirectoryChangeTest.java b/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/HpelLogDirectoryChangeTest.java new file mode 100755 index 00000000000..29fb3485132 --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/HpelLogDirectoryChangeTest.java @@ -0,0 +1,149 @@ +//%Z% %I% %W% %G% %U% [%H% %T%] +/** + * + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + * + * DESCRIPTION: + * + * Change History: + * + * Reason Version Date User id Description + * ---------------------------------------------------------------------------- + * 98216 8.5.5 13/06/2013 sumam Test case for defect 98216. + * + */ + +package com.ibm.ws.fat.hpel.tests; + +import java.io.File; +import java.text.NumberFormat; +import java.util.logging.Logger; + +import com.ibm.websphere.simplicity.ApplicationServer; +import com.ibm.websphere.simplicity.RemoteFile; +import com.ibm.ws.fat.VerboseTestCase; +import com.ibm.ws.fat.hpel.setup.HpelSetup; +import com.ibm.ws.fat.ras.util.CommonTasks; + +/** + * Test case for defect 98216 : HPEL doesn't change location of logdata/tracedata when logDirectory changes. + * While changing the logDirectory attribute of element, the new logs were going inside the old directory. + * Test Scenario -> Start the server with logDirectory as logs → during runtime change the logDirectory to logX and run quick log, new logs should be generated under the logx + * repository. + * + */ + +public class HpelLogDirectoryChangeTest extends VerboseTestCase { + + private final static String loggerName = HpelLogDirectoryChangeTest.class.getName(); + private final static Logger logger = Logger.getLogger(loggerName); + private final static int MAX_DEFAULT_PURGE_SIZE = 30; + + private ApplicationServer appServ = null; + + RemoteFile backup = null; + + public HpelLogDirectoryChangeTest(String name) { + super(name); + } + + @Override + public void setUp() throws Exception { + // Call super.SetUp() cause we still want it's setup as well + super.setUp(); + appServ = HpelSetup.getServerUnderTest(); + // Confirm HPEL is enabled + if (!CommonTasks.isHpelEnabled(appServ)) { + // HPEL is not enabled. + this.logStep("HPEL is not enabled on " + appServ.getName() + ", attempting to enable."); + CommonTasks.setHpelEnabled(appServ, true); + // Restart now to complete switching to HPEL + appServ.stop(); + appServ.start(); + + this.logStepCompleted(); + } + this.logStep("Configuring server for test case."); + backup = new RemoteFile(appServ.getBackend().getMachine(), new File(appServ.getBackend().getServerRoot(), "server-backup.xml").getPath()); + if (!backup.exists()) { + backup.copyFromSource(appServ.getBackend().getServerConfigurationFile()); + } + // Setting the log directory of logs + appServ.getBackend().updateServerConfiguration(new File(appServ.getBackend().pathToAutoFVTTestFiles, "server-HpelLogDirectoryChange_1.xml")); + if (!appServ.getBackend().isStarted()) { + appServ.start(); + } + + this.logStepCompleted(); + + } + + /** + * Testing the logDirectory attribute by changing to new location and running the quick logs. + * Start the server with logDirectory as logs, during runtime change the value of logDirectory to logx, run quick logs + * and check the location where logs are getting stored. + **/ + public void testLogDirectoryChange() throws Exception { + RemoteFile binaryLogDir = null; + NumberFormat nf = NumberFormat.getInstance(); + + this.logStep("Configuring server for test case by setting the logDirectory to logx"); + appServ.getBackend().updateServerConfiguration(new File(appServ.getBackend().pathToAutoFVTTestFiles, "server-HpelLogDirectoryChange_2.xml")); + this.logStepCompleted(); + + // write enough records to new log repository updated. + this.logStep("Writting log records to fill binary log repository."); + long loopsPerFullRepository = (MAX_DEFAULT_PURGE_SIZE * 1024 * 1024) / 200; + logger.info("writting " + nf.format(loopsPerFullRepository) + " log loops to produce " + MAX_DEFAULT_PURGE_SIZE + + " MB of data."); + CommonTasks.createLogEntries(appServ, loggerName, "Sample log record for the test case " + this.getName() + ".", null, + (int) loopsPerFullRepository, CommonTasks.LOGS, 0); + + this.logStepCompleted(); + + this.logVerificationPoint("Verifying the repository used for log is new location (logx)."); + binaryLogDir = appServ.getBackend().getFileFromLibertyServerRoot("logx/logdata"); + long binaryLogSize = getSizeOfBinaryLogs(binaryLogDir); + logger.info("The current size of BinaryLog files in " + binaryLogDir.getAbsolutePath() + " is " + nf.format(binaryLogSize)); + assertTrue("BinaryLog Repository should be the new location logx ", + binaryLogSize > ((MAX_DEFAULT_PURGE_SIZE - 5) * 1024 * 1024) && binaryLogSize < (50 * 1024 * 1024)); + this.logVerificationPassed(); + + } + + /** + * Returns the total size of log files in the given directory + * + * @throws Exception + **/ + private long getSizeOfBinaryLogs(RemoteFile dirToCheck) throws Exception { + long totalgRepositorySize = 0; + RemoteFile[] allLogFiles = dirToCheck.list(true); + for (RemoteFile i : allLogFiles) { + totalgRepositorySize += i.length(); + } + return totalgRepositorySize; + } + + @Override + public void tearDown() throws Exception { + // Restore values we saw before changing them in setUp() + this.logStep("Resetting configuration to pre test values."); + if (backup != null && backup.exists()) { + appServ.getBackend().getServerConfigurationFile().copyFromSource(backup); + } + this.logStepCompleted(); + + // call the super + super.tearDown(); + } + +} \ No newline at end of file diff --git a/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/HpelLoggingElementDeleteTest.java b/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/HpelLoggingElementDeleteTest.java new file mode 100755 index 00000000000..4140ca33ba3 --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/HpelLoggingElementDeleteTest.java @@ -0,0 +1,212 @@ +//%Z% %I% %W% %G% %U% [%H% %T%] +/** + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + * + * DESCRIPTION: + * + * Change History: + * + * Reason Version Date User id Description + * ---------------------------------------------------------------------------- + * 91946 8.5.5 13/06/2013 sumam Test case for defect 91946. + */ +package com.ibm.ws.fat.hpel.tests; + +import java.io.File; +import java.text.NumberFormat; +import java.util.logging.Logger; + +import com.ibm.websphere.simplicity.ApplicationServer; +import com.ibm.websphere.simplicity.RemoteFile; +import com.ibm.ws.fat.VerboseTestCase; +import com.ibm.ws.fat.hpel.setup.HpelSetup; +import com.ibm.ws.fat.ras.util.CommonTasks; + +/** + * Test case for defect 91946 : HPEL configuration value doesn't revert to default when cleared from server.xml + * While deleting the element purgeMaxSize property is not set to default value. + * Test scenario + * 1. Bootstrap = 91 , server.xml= 201 for Trace remove the entire element Trace = 91 and Log = 50 + * 2. server.xml= 201 for Trace remove the entire element Trace = 50 and Log = 50 + */ + +public class HpelLoggingElementDeleteTest extends VerboseTestCase { + + private final static String loggerName = HpelLoggingElementDeleteTest.class.getName(); + private final static Logger logger = Logger.getLogger(loggerName); + private final static int MAX_DEFAULT_PURGE_SIZE = 100; + + private ApplicationServer appServ = null; + + RemoteFile backup = null; + + public HpelLoggingElementDeleteTest(String name) { + super(name); + } + + @Override + public void setUp() throws Exception { + // Call super.SetUp() cause we still want it's setup as well + super.setUp(); + appServ = HpelSetup.getServerUnderTest(); + // Confirm HPEL is enabled + if (!CommonTasks.isHpelEnabled(appServ)) { + // HPEL is not enabled. + this.logStep("HPEL is not enabled on " + appServ.getName() + ", attempting to enable."); + CommonTasks.setHpelEnabled(appServ, true); + // Restart now to complete switching to HPEL + appServ.stop(); + appServ.start(); + this.logStepCompleted(); + } + // Setting the bootstrap with trace specification to get the trace logs. + + CommonTasks.addBootstrapProperty(appServ, "com.ibm.ws.logging.trace.specification", "*=fine=enabled"); + appServ.stop(); + appServ.start(); + + this.logStep("Configuring server for test case."); + backup = new RemoteFile(appServ.getBackend().getMachine(), new File(appServ.getBackend().getServerRoot(), "server-backup.xml").getPath()); + if (!backup.exists()) { + backup.copyFromSource(appServ.getBackend().getServerConfigurationFile()); + } + appServ.getBackend().updateServerConfiguration(new File(appServ.getBackend().pathToAutoFVTTestFiles, "server-HpelLogElementDelete_1.xml")); + if (!appServ.getBackend().isStarted()) { + appServ.start(); + } + + this.logStepCompleted(); + + } + + /** + * Test 1. Set server.xml Trace = 201, during runtime remove the entire element, + * run quick log and check for the repository size, both logdata and tracedata should not exceed more than 50 MB. + **/ + + public void testLoggingElementDelete_1() throws Exception { + RemoteFile binaryLogDir = null; + RemoteFile binaryTraceDir = null; + + NumberFormat nf = NumberFormat.getInstance(); + + this.logStep("Configuring server for test case."); + appServ.getBackend().updateServerConfiguration(new File(appServ.getBackend().pathToAutoFVTTestFiles, "server-HpelLogElementDelete_2.xml")); + this.logStepCompleted(); + + // write enough records to new log repository updated. + this.logStep("Writting log records to fill binary log repository."); + long loopsPerFullRepository = (MAX_DEFAULT_PURGE_SIZE * 1024 * 1024) / 200; + logger.info("writting " + nf.format(loopsPerFullRepository) + " log loops to produce " + MAX_DEFAULT_PURGE_SIZE + + " MB of data."); + CommonTasks.createLogEntries(appServ, loggerName, "Sample log record for the test case " + this.getName() + ".", null, + (int) loopsPerFullRepository, CommonTasks.LOGS_TRACE, 0); + + this.logStepCompleted(); + + this.logVerificationPoint("Verifying the repository size after deleting the logging element."); + binaryLogDir = appServ.getBackend().getFileFromLibertyServerRoot("logs/logdata"); + long binaryLogSize = getSizeOfBinaryLogs(binaryLogDir); + binaryTraceDir = appServ.getBackend().getFileFromLibertyServerRoot("logs/tracedata"); + long binaryTraceSize = getSizeOfBinaryLogs(binaryTraceDir); + + logger.info("The current size of BinaryLog files in " + binaryLogDir.getAbsolutePath() + " is " + nf.format(binaryLogSize)); + assertTrue("BinaryLog Repository size should be less than 50 MB ", + binaryLogSize > (45 * 1024 * 1024) && binaryLogSize < (50 * 1024 * 1024)); + logger.info("The current size of BinaryTrace files in " + binaryTraceDir.getAbsolutePath() + " is " + nf.format(binaryTraceSize)); + assertTrue("BinaryTrace Repository size should be less than 50 MB ", + binaryTraceSize > (45 * 1024 * 1024) && binaryTraceSize < (50 * 1024 * 1024)); + + this.logVerificationPassed(); + + } + + /** + * Test 1. Bootstrap Trace = 91 ,in server.xml Trace = 201, during runtime remove the entire element + * and run quick log, check the size of the repository it should not exceed more than 91 MB for trace data and 50 MB for log data. + **/ + public void testLoggingElementDelete_2() throws Exception { + RemoteFile binaryLogDir = null; + RemoteFile binaryTraceDir = null; + NumberFormat nf = NumberFormat.getInstance(); + + CommonTasks.addBootstrapProperty(appServ, "com.ibm.hpel.trace.purgeMaxSize", "90"); + appServ.stop(); + appServ.start(); + + this.logStep("Configuring server for test case."); + appServ.getBackend().updateServerConfiguration(new File(appServ.getBackend().pathToAutoFVTTestFiles, "server-HpelLogElementDelete_1.xml")); + this.logStepCompleted(); + + appServ.stop(); + appServ.start(); + + this.logStep("Configuring server for test case."); + appServ.getBackend().updateServerConfiguration(new File(appServ.getBackend().pathToAutoFVTTestFiles, "server-HpelLogElementDelete_2.xml")); + this.logStepCompleted(); + + // write enough records to new log repository updated. + this.logStep("Writting log records to fill binary log repository."); + long loopsPerFullRepository = (MAX_DEFAULT_PURGE_SIZE * 1024 * 1024) / 200; + logger.info("writting " + nf.format(loopsPerFullRepository) + " log loops to produce " + MAX_DEFAULT_PURGE_SIZE + + " MB of data."); + CommonTasks.createLogEntries(appServ, loggerName, "Sample log record for the test case " + this.getName() + ".", null, + (int) loopsPerFullRepository, CommonTasks.LOGS_TRACE, 0); + + this.logStepCompleted(); + + this.logVerificationPoint("Verifying the repository size after deleting the logging element ."); + binaryLogDir = appServ.getBackend().getFileFromLibertyServerRoot("logs/logdata"); + long binaryLogSize = getSizeOfBinaryLogs(binaryLogDir); + binaryTraceDir = appServ.getBackend().getFileFromLibertyServerRoot("logs/tracedata"); + long binaryTraceSize = getSizeOfBinaryLogs(binaryTraceDir); + + logger.info("The current size of BinaryLog files in " + binaryLogDir.getAbsolutePath() + " is " + nf.format(binaryLogSize)); + assertTrue("BinaryLog Repository size should be less than 50 MB ", + binaryLogSize > (45 * 1024 * 1024) && binaryLogSize < (50 * 1024 * 1024)); + logger.info("The current size of BinaryTrace files in " + binaryTraceDir.getAbsolutePath() + " is " + nf.format(binaryTraceSize)); + assertTrue("BinaryTrace Repository size should be less than 91 MB ", + binaryTraceSize > (85 * 1024 * 1024) && binaryTraceSize < (91 * 1024 * 1024)); + + this.logVerificationPassed(); + + } + + /** + * Returns the total size of log files in the given directory + * + * @throws Exception + **/ + private long getSizeOfBinaryLogs(RemoteFile dirToCheck) throws Exception { + + long totalBinaryLogRepositorySize = 0; + RemoteFile[] allBinaryLogFiles = dirToCheck.list(true); + for (RemoteFile i : allBinaryLogFiles) { + totalBinaryLogRepositorySize += i.length(); +// } + } + return totalBinaryLogRepositorySize; + } + + @Override + public void tearDown() throws Exception { + // Restore values we saw before changing them in setUp() + this.logStep("Resetting configuration to pre test values."); + if (backup != null && backup.exists()) { + appServ.getBackend().getServerConfigurationFile().copyFromSource(backup); + } + this.logStepCompleted(); + + // call the super + super.tearDown(); + } + +} \ No newline at end of file diff --git a/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/HpelPurgeMaxSizeBackupFileTest.java b/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/HpelPurgeMaxSizeBackupFileTest.java new file mode 100755 index 00000000000..7f87628208b --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/HpelPurgeMaxSizeBackupFileTest.java @@ -0,0 +1,195 @@ +//%Z% %I% %W% %G% %U% [%H% %T%] +/** + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + * + * DESCRIPTION: + * + * Change History: + * + * Reason Version Date User id Description + * ---------------------------------------------------------------------------- + * 98078 8.5.5 13/06/2013 sumam Test case for defect 98078. + */ + +package com.ibm.ws.fat.hpel.tests; + +import java.io.File; +import java.text.NumberFormat; +import java.util.logging.Logger; + +import com.ibm.websphere.simplicity.ApplicationServer; +import com.ibm.websphere.simplicity.RemoteFile; +import com.ibm.ws.fat.VerboseTestCase; +import com.ibm.ws.fat.hpel.setup.HpelSetup; +import com.ibm.ws.fat.ras.util.CommonTasks; + +/** + * Test case for defect 98078 : HPEL purgeMinTime default setting causes all backup log/trace files to be deleted + * Test scenario + * 1. Start the server with purgeMaxSize as 0 for Trace and Log, run quick log Log directory size should be unlimited + * 2. Change the size of purgeMaxSize to 10 for Log and Trace Log directory should be purged to 10MB + * 3. Run quick log again Log directory should remain within 10 MB + */ + +public class HpelPurgeMaxSizeBackupFileTest extends VerboseTestCase { + + private final static String loggerName = HpelLogDirectoryChangeTest.class.getName(); + private final static Logger logger = Logger.getLogger(loggerName); + private final static int MAX_DEFAULT_PURGE_SIZE = 50; + + private ApplicationServer appServ = null; + + RemoteFile backup = null; + + public HpelPurgeMaxSizeBackupFileTest(String name) { + super(name); + } + + @Override + public void setUp() throws Exception { + // Call super.SetUp() cause we still want it's setup as well + super.setUp(); + appServ = HpelSetup.getServerUnderTest(); + // Confirm HPEL is enabled + if (!CommonTasks.isHpelEnabled(appServ)) { + // HPEL is not enabled. + this.logStep("HPEL is not enabled on " + appServ.getName() + ", attempting to enable."); + CommonTasks.setHpelEnabled(appServ, true); + // Restart now to complete switching to HPEL + appServ.stop(); + appServ.start(); + this.logStepCompleted(); + } + + // Setting the bootstrap with trace specification to get the trace logs. + CommonTasks.addBootstrapProperty(appServ, "com.ibm.ws.logging.trace.specification", "*=fine=enabled"); + appServ.stop(); + appServ.start(); + + this.logStep("Configuring server for test case."); + backup = new RemoteFile(appServ.getBackend().getMachine(), new File(appServ.getBackend().getServerRoot(), "server-backup.xml").getPath()); + if (!backup.exists()) { + backup.copyFromSource(appServ.getBackend().getServerConfigurationFile()); + } + appServ.getBackend().updateServerConfiguration(new File(appServ.getBackend().pathToAutoFVTTestFiles, "server-HPELPurgeMinTimeTest_1.xml")); + if (!appServ.getBackend().isStarted()) { + appServ.start(); + } + + this.logStepCompleted(); + + } + + /** + * Test that HPEL's TextLog size based retention policy works. Both within a single server instance and across + * server restarts. + **/ + public void testPurgeMinTime() throws Exception { + RemoteFile binaryLogDir = null; + RemoteFile binaryTraceDir = null; + NumberFormat nf = NumberFormat.getInstance(); + + // write enough records to log repository updated. + this.logStep("Writting log records to fill binary log repository."); + long loopsPerFullRepository = (MAX_DEFAULT_PURGE_SIZE * 1024 * 1024) / 200; + logger.info("writting " + nf.format(loopsPerFullRepository) + " log loops to produce " + MAX_DEFAULT_PURGE_SIZE + + " MB of data."); + CommonTasks.createLogEntries(appServ, loggerName, "Sample log record for the test case " + this.getName() + ".", null, + (int) loopsPerFullRepository, CommonTasks.LOGS_TRACE, 0); + + this.logStepCompleted(); + + this.logVerificationPoint("Verifying the repository size."); + binaryLogDir = appServ.getBackend().getFileFromLibertyServerRoot("logs/logdata"); + long binaryLogSize = getSizeOfBinaryLogs(binaryLogDir); + binaryTraceDir = appServ.getBackend().getFileFromLibertyServerRoot("logs/tracedata"); + long binaryTraceSize = getSizeOfBinaryLogs(binaryTraceDir); + + logger.info("The current size of BinaryLog files in " + binaryLogDir.getAbsolutePath() + " is " + nf.format(binaryLogSize)); + assertTrue("BinaryLog Repository size should have logs created", + binaryLogSize > ((MAX_DEFAULT_PURGE_SIZE - 2) * 1024 * 1024)); + logger.info("The current size of BinaryTrace files in " + binaryTraceDir.getAbsolutePath() + " is " + nf.format(binaryTraceSize)); + assertTrue("BinaryTrace Repository size should have logs created", + binaryTraceSize > ((MAX_DEFAULT_PURGE_SIZE - 2) * 1024 * 1024)); + + this.logVerificationPassed(); + + this.logStep("Configuring server for test case."); + appServ.getBackend().updateServerConfiguration(new File(appServ.getBackend().pathToAutoFVTTestFiles, "server-HPELPurgeMinTimeTest_2.xml")); + this.logStepCompleted(); + + this.logVerificationPoint("Verifying the repository used for log is new location."); + binaryLogSize = getSizeOfBinaryLogs(binaryLogDir); + binaryTraceSize = getSizeOfBinaryLogs(binaryTraceDir); + + logger.info("The current size of BinaryLog files in " + binaryLogDir.getAbsolutePath() + " is " + nf.format(binaryLogSize)); + assertTrue("BinaryLog Repository size should have logs created", + binaryLogSize > (5 * 1024 * 1024) && binaryLogSize < (10 * 1024 * 1024)); + logger.info("The current size of BinaryTrace files in " + binaryTraceDir.getAbsolutePath() + " is " + nf.format(binaryTraceSize)); + assertTrue("BinaryTrace Repository size should have logs created", + binaryTraceSize > (5 * 1024 * 1024) && binaryTraceSize < (10 * 1024 * 1024)); + + this.logVerificationPassed(); + + this.logStep("Writting log records to fill binary log repository."); + loopsPerFullRepository = (MAX_DEFAULT_PURGE_SIZE * 1024 * 1024) / 600; + logger.info("writting " + nf.format(loopsPerFullRepository) + " log loops to produce " + MAX_DEFAULT_PURGE_SIZE + + " MB of data."); + CommonTasks.createLogEntries(appServ, loggerName, "Sample log record for the test case " + this.getName() + ".", null, + (int) loopsPerFullRepository, CommonTasks.LOGS_TRACE, 0); + + this.logStepCompleted(); + + this.logVerificationPoint("Verifying the repository size for new logs generated"); + binaryLogSize = getSizeOfBinaryLogs(binaryLogDir); + binaryTraceSize = getSizeOfBinaryLogs(binaryTraceDir); + + logger.info("The current size of BinaryLog files in " + binaryLogDir.getAbsolutePath() + " is " + nf.format(binaryLogSize)); + assertTrue("BinaryLog Repository size should have logs created", + binaryLogSize > (5 * 1024 * 1024) && binaryLogSize < (10 * 1024 * 1024)); + logger.info("The current size of BinaryTrace files in " + binaryTraceDir.getAbsolutePath() + " is " + nf.format(binaryTraceSize)); + assertTrue("BinaryTrace Repository size should have logs created", + binaryTraceSize > (5 * 1024 * 1024) && binaryTraceSize < (10 * 1024 * 1024)); + + this.logVerificationPassed(); + + } + + /** + * Returns the total size of log files in the given directory + * + * @throws Exception + **/ + private long getSizeOfBinaryLogs(RemoteFile dirToCheck) throws Exception { + + long totalBinaryLogRepositorySize = 0; + RemoteFile[] allBinaryLogFiles = dirToCheck.list(true); + for (RemoteFile i : allBinaryLogFiles) { + totalBinaryLogRepositorySize += i.length(); +// } + } + return totalBinaryLogRepositorySize; + } + + @Override + public void tearDown() throws Exception { + // Restore values we saw before changing them in setUp() + this.logStep("Resetting configuration to pre test values."); + if (backup != null && backup.exists()) { + appServ.getBackend().getServerConfigurationFile().copyFromSource(backup); + } + this.logStepCompleted(); + + // call the super + super.tearDown(); + } + +} \ No newline at end of file diff --git a/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/HpelPurgeMaxSizeIgnoreTest_1.java b/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/HpelPurgeMaxSizeIgnoreTest_1.java new file mode 100755 index 00000000000..61c4d34b02d --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/HpelPurgeMaxSizeIgnoreTest_1.java @@ -0,0 +1,501 @@ +//%Z% %I% %W% %G% %U% [%H% %T%] +/** + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + * + * DESCRIPTION: + * + * Change History: + * + * Reason Version Date User id Description + * ---------------------------------------------------------------------------- + * 97932 8.5.5 13/06/2013 sumam Test case for defect 97932. + */ +package com.ibm.ws.fat.hpel.tests; + +import java.io.File; +import java.text.NumberFormat; +import java.util.logging.Logger; + +import com.ibm.websphere.simplicity.ApplicationServer; +import com.ibm.websphere.simplicity.RemoteFile; +import com.ibm.ws.fat.VerboseTestCase; +import com.ibm.ws.fat.hpel.setup.HpelSetup; +import com.ibm.ws.fat.ras.util.CommonTasks; + +/** + * Test case for defect 97932 : HPEL ignores purgeMaxSize + * Test scenario + * 1. Bootstrap = 91 , server.xml= 201 for Trace Trace = 201, Log = 50 + * 2. No Config specified Trace = 50, Log = 50 + * 3. Bootstrap = 91 for Trace Trace = 91 and Log = 50 + * 4. Server.xml= 55 for Log Trace = 50 and Log = 55 + * 5. Server.xml= 1024 for Trace ( Used 200 for trace instead of 1024 ) Trace = 1024 and Log = 50 + * 6. Server start without any settings -> during run time, add purgeMaxSize for log to 100 Trace = 50 and Log = 100 + * 7. Server start with log settings as 100 -> during run time, remove the attribute Trace = 50 and Log = 50 + * 8. Server start with log settings as 100 -> during run time, remove entire element (binaryLog) Trace = 50 and Log = 50 + * 9. Server start with log settings as 100 -> during run time, remove entire element (logging) Trace = 50 and Log = 50 + * + */ + +public class HpelPurgeMaxSizeIgnoreTest_1 extends VerboseTestCase { + + private final static String loggerName = HpelLogDirectoryChangeTest.class.getName(); + private final static Logger logger = Logger.getLogger(loggerName); + private final static int MAX_DEFAULT_PURGE_SIZE = 50; + + private ApplicationServer appServ = null; + + RemoteFile backup = null; + + public HpelPurgeMaxSizeIgnoreTest_1(String name) { + super(name); + } + + @Override + public void setUp() throws Exception { + // Call super.SetUp() cause we still want it's setup as well + super.setUp(); + appServ = HpelSetup.getServerUnderTest(); + // Confirm HPEL is enabled + if (!CommonTasks.isHpelEnabled(appServ)) { + // HPEL is not enabled. + this.logStep("HPEL is not enabled on " + appServ.getName() + ", attempting to enable."); + CommonTasks.setHpelEnabled(appServ, true); + // Restart now to complete switching to HPEL + appServ.stop(); + appServ.start(); + this.logStepCompleted(); + } + + // Setting the bootstrap with trace specification to get the trace logs. + CommonTasks.addBootstrapProperty(appServ, "com.ibm.ws.logging.trace.specification", "*=fine=enabled"); + appServ.stop(); + appServ.start(); + + this.logStep("Configuring server for test case."); +// backup = new RemoteFile(appServ.getBackend().getMachine(), new File(appServ.getBackend().getServerRoot(), "server-backup.xml").getPath()); +// if (!backup.exists()) { +// backup.copyFromSource(appServ.getBackend().getServerConfigurationFile()); +// } + appServ.getBackend().updateServerConfiguration(new File(appServ.getBackend().pathToAutoFVTTestFiles, "server-HpelLogDirectoryChange_1.xml")); + if (!appServ.getBackend().isStarted()) { + appServ.start(); + } + + this.logStepCompleted(); + + } + + /** + * Test No config specified. Run quick log and check the size of repository. Both Tracedata and Logdata should not exceed 50 MB. + **/ + + public void testPurgeMaxSize_1() throws Exception { + RemoteFile binaryLogDir = null; + RemoteFile binaryTraceDir = null; + NumberFormat nf = NumberFormat.getInstance(); + + this.logStep("Setting server configuration to default.."); + appServ.getBackend().updateServerConfiguration(new File(appServ.getBackend().pathToAutoFVTTestFiles, "server-HpelLogDirectoryChange_1.xml")); + this.logStepCompleted(); + + // write enough records to new log repository updated. + this.logStep("Writting log records to fill binary log repository."); + long loopsPerFullRepository = (MAX_DEFAULT_PURGE_SIZE * 1024 * 1024) / 200; + logger.info("writting " + nf.format(loopsPerFullRepository) + " log loops to produce " + MAX_DEFAULT_PURGE_SIZE + + " MB of data."); + CommonTasks.createLogEntries(appServ, loggerName, "Sample log record for the test case " + this.getName() + ".", null, + (int) loopsPerFullRepository, CommonTasks.LOGS_TRACE, 0); + + this.logStepCompleted(); + + this.logVerificationPoint("Verifying the repository size "); + binaryLogDir = appServ.getBackend().getFileFromLibertyServerRoot("logs/logdata"); + binaryTraceDir = appServ.getBackend().getFileFromLibertyServerRoot("logs/tracedata"); + + long binaryLogSize = getSizeOfBinaryLogs(binaryLogDir); + long binaryTraceSize = getSizeOfBinaryLogs(binaryTraceDir); + + logger.info("The current size of BinaryLog files in " + binaryLogDir.getAbsolutePath() + " is " + nf.format(binaryLogSize)); + assertTrue("BinaryLog Repository size should be less than 50 MB ", + binaryLogSize < (50 * 1024 * 1024)); + logger.info("The current size of BinaryTrace files in " + binaryTraceDir.getAbsolutePath() + " is " + nf.format(binaryTraceSize)); + assertTrue("Binarytrace Repository size should be less than 50 MB ", + binaryTraceSize < (50 * 1024 * 1024)); + + this.logVerificationPassed(); + + } + + /** + * Test In Server.xml set log = 55. Run quick log and check the size of repository. + * Trace data should not exceed more than 50 MB and Log data should not exceed more than 55 MB. + **/ + + public void testPurgeMaxSize_2() throws Exception { + RemoteFile binaryLogDir = null; + RemoteFile binaryTraceDir = null; + NumberFormat nf = NumberFormat.getInstance(); + + appServ.getBackend().updateServerConfiguration(new File(appServ.getBackend().pathToAutoFVTTestFiles, "server-HPELPurgeMaxSizeTest_1.xml")); + appServ.stop(); + appServ.start();; + + // write enough records to new log repository updated. + this.logStep("Writting log records to fill binary log repository."); + long loopsPerFullRepository = (MAX_DEFAULT_PURGE_SIZE * 1024 * 1024) / 200; + logger.info("writting " + nf.format(loopsPerFullRepository) + " log loops to produce " + MAX_DEFAULT_PURGE_SIZE + + " MB of data."); + CommonTasks.createLogEntries(appServ, loggerName, "Sample log record for the test case " + this.getName() + ".", null, + (int) loopsPerFullRepository, CommonTasks.LOGS_TRACE, 0); + this.logStepCompleted(); + + this.logVerificationPoint("Verifying the repository size "); + binaryLogDir = appServ.getBackend().getFileFromLibertyServerRoot("logs/logdata"); + binaryTraceDir = appServ.getBackend().getFileFromLibertyServerRoot("logs/tracedata"); + + long binaryLogSize = getSizeOfBinaryLogs(binaryLogDir); + long binaryTraceSize = getSizeOfBinaryLogs(binaryTraceDir); + + logger.info("The current size of BinaryLog files in " + binaryLogDir.getAbsolutePath() + " is " + nf.format(binaryLogSize)); + assertTrue("BinaryLog Repository size should be less than 55 MB ", + binaryLogSize < (55 * 1024 * 1024)); + logger.info("The current size of BinaryTrace files in " + binaryTraceDir.getAbsolutePath() + " is " + nf.format(binaryTraceSize)); + assertTrue("BinaryTrace Repository size should be less than 50 MB ", + binaryTraceSize < (50 * 1024 * 1024)); + + this.logVerificationPassed(); + + } + + /** + * Test In server.xml set Trace = 200MB. Start the server and run quick log and check the repository size. + * Trace data size should not exceed more than 200 MB and log data size should not exceed more than 50 MB. + **/ + public void testPurgeMaxSize_3() throws Exception { + RemoteFile binaryLogDir = null; + RemoteFile binaryTraceDir = null; + NumberFormat nf = NumberFormat.getInstance(); + + appServ.getBackend().updateServerConfiguration(new File(appServ.getBackend().pathToAutoFVTTestFiles, "server-HPELPurgeMaxSizeTest_2.xml")); + appServ.stop(); + appServ.start(); + + // write enough records to new log repository updated. + this.logStep("Writting log records to fill binary log repository."); + long loopsPerFullRepository = (200 * 1024 * 1024) / 200; + logger.info("writting " + nf.format(loopsPerFullRepository) + " log loops to produce " + 200 + + " MB of data."); + CommonTasks.createLogEntries(appServ, loggerName, "Sample log record for the test case " + this.getName() + ".", null, + (int) loopsPerFullRepository, CommonTasks.LOGS_TRACE, 0); + + this.logStepCompleted(); + + this.logVerificationPoint("Verifying the repository size "); + binaryLogDir = appServ.getBackend().getFileFromLibertyServerRoot("logs/logdata"); + binaryTraceDir = appServ.getBackend().getFileFromLibertyServerRoot("logs/tracedata"); + + long binaryLogSize = getSizeOfBinaryLogs(binaryLogDir); + long binaryTraceSize = getSizeOfBinaryLogs(binaryTraceDir); + + logger.info("The current size of BinaryLog files in " + binaryLogDir.getAbsolutePath() + " is " + nf.format(binaryLogSize)); + assertTrue("BinaryLog Repository size should be less than 50 MB ", + binaryLogSize < (50 * 1024 * 1024)); + logger.info("The current size of BinaryTrace files in " + binaryTraceDir.getAbsolutePath() + " is " + nf.format(binaryTraceSize)); + assertTrue("Binarytrace Repository size should be less than 200 MB ", + binaryTraceSize < (200 * 1024 * 1024)); + + this.logVerificationPassed(); + + } + + /** + * Server start without any setting -> during runtime add purgeMaxSize for log to 100 and run the quick log. + * Check the size of repository, it should not exceed 100 MB for log and 50 MB for trace. + */ + + public void testPurgeMaxSize_4() throws Exception { + RemoteFile binaryLogDir = null; + RemoteFile binaryTraceDir = null; + NumberFormat nf = NumberFormat.getInstance(); + + appServ.getBackend().updateServerConfiguration(new File(appServ.getBackend().pathToAutoFVTTestFiles, "server-HPELPurgeMaxSizeTest_3.xml")); + appServ.stop(); + appServ.start(); + + appServ.getBackend().updateServerConfiguration(new File(appServ.getBackend().pathToAutoFVTTestFiles, "server-HPELPurgeMaxSizeTest_4.xml")); + + // write enough records to new log repository updated. + this.logStep("Writting log records to fill binary log repository."); + long loopsPerFullRepository = (100 * 1024 * 1024) / 200; + logger.info("writting " + nf.format(loopsPerFullRepository) + " log loops to produce " + 100 + + " MB of data."); + CommonTasks.createLogEntries(appServ, loggerName, "Sample log record for the test case " + this.getName() + ".", null, + (int) loopsPerFullRepository, CommonTasks.LOGS_TRACE, 0); + + this.logStepCompleted(); + + this.logVerificationPoint("Verifying the repository size "); + binaryLogDir = appServ.getBackend().getFileFromLibertyServerRoot("logs/logdata"); + binaryTraceDir = appServ.getBackend().getFileFromLibertyServerRoot("logs/tracedata"); + + long binaryLogSize = getSizeOfBinaryLogs(binaryLogDir); + long binaryTraceSize = getSizeOfBinaryLogs(binaryTraceDir); + + logger.info("The current size of BinaryLog files in " + binaryLogDir.getAbsolutePath() + " is " + nf.format(binaryLogSize)); + assertTrue("BinaryLog Repository size should be less than 100 MB ", + binaryLogSize < (100 * 1024 * 1024)); + logger.info("The current size of BinaryTrace files in " + binaryTraceDir.getAbsolutePath() + " is " + nf.format(binaryTraceSize)); + assertTrue("Binarytrace Repository size should be less than 50 MB ", + binaryTraceSize < (50 * 1024 * 1024)); + + this.logVerificationPassed(); + + } + + /** + * Server start with log settings as 100 -> during run time, remove the attribute "purgeMaxSize" from element. + * Run the quick log and check the size of the repository, it should not exceed 50 MB for tracedata and logdata. + **/ + public void testPurgeMaxSize_5() throws Exception { + RemoteFile binaryLogDir = null; + RemoteFile binaryTraceDir = null; + NumberFormat nf = NumberFormat.getInstance(); + + appServ.getBackend().updateServerConfiguration(new File(appServ.getBackend().pathToAutoFVTTestFiles, "server-HPELPurgeMaxSizeTest_4.xml")); + appServ.stop(); + appServ.start(); + + appServ.getBackend().updateServerConfiguration(new File(appServ.getBackend().pathToAutoFVTTestFiles, "server-HPELPurgeMaxSizeTest_5.xml")); + + // write enough records to new log repository updated. + this.logStep("Writting log records to fill binary log repository."); + long loopsPerFullRepository = (MAX_DEFAULT_PURGE_SIZE * 1024 * 1024) / 200; + logger.info("writting " + nf.format(loopsPerFullRepository) + " log loops to produce " + MAX_DEFAULT_PURGE_SIZE + + " MB of data."); + CommonTasks.createLogEntries(appServ, loggerName, "Sample log record for the test case " + this.getName() + ".", null, + (int) loopsPerFullRepository, CommonTasks.LOGS_TRACE, 0); + + this.logStepCompleted(); + + this.logVerificationPoint("Verifying the repository size "); + binaryLogDir = appServ.getBackend().getFileFromLibertyServerRoot("logs/logdata"); + binaryTraceDir = appServ.getBackend().getFileFromLibertyServerRoot("logs/tracedata"); + + long binaryLogSize = getSizeOfBinaryLogs(binaryLogDir); + long binaryTraceSize = getSizeOfBinaryLogs(binaryTraceDir); + + logger.info("The current size of BinaryLog files in " + binaryLogDir.getAbsolutePath() + " is " + nf.format(binaryLogSize)); + assertTrue("BinaryLog Repository size should be less than 50 MB ", + binaryLogSize < (50 * 1024 * 1024)); + logger.info("The current size of BinaryTrace files in " + binaryTraceDir.getAbsolutePath() + " is " + nf.format(binaryTraceSize)); + assertTrue("Binarytrace Repository size should be less than 50 MB ", + binaryTraceSize < (50 * 1024 * 1024)); + + this.logVerificationPassed(); + } + + /** + * Server start with log settings as 100 -> during run time, remove entire element (binaryLog) from server.xml + * run the quick log and check the size of the repository it should not exceed 50 MB for both logdata and tracedata. + **/ + public void testPurgeMaxSize_6() throws Exception { + RemoteFile binaryLogDir = null; + RemoteFile binaryTraceDir = null; + NumberFormat nf = NumberFormat.getInstance(); + + appServ.getBackend().updateServerConfiguration(new File(appServ.getBackend().pathToAutoFVTTestFiles, "server-HPELPurgeMaxSizeTest_4.xml")); + appServ.stop(); + appServ.start(); + + appServ.getBackend().updateServerConfiguration(new File(appServ.getBackend().pathToAutoFVTTestFiles, "server-HPELPurgeMaxSizeTest_6.xml")); + + // write enough records to new log repository updated. + this.logStep("Writting log records to fill binary log repository."); + long loopsPerFullRepository = (50 * 1024 * 1024) / 50; + logger.info("writting " + nf.format(loopsPerFullRepository) + " log loops to produce " + MAX_DEFAULT_PURGE_SIZE + + " MB of data."); + CommonTasks.createLogEntries(appServ, loggerName, "Sample log record for the test case " + this.getName() + ".", null, + (int) loopsPerFullRepository, CommonTasks.LOGS_TRACE, 0); + + this.logStepCompleted(); + + this.logVerificationPoint("Verifying the repository size "); + binaryLogDir = appServ.getBackend().getFileFromLibertyServerRoot("logs/logdata"); + binaryTraceDir = appServ.getBackend().getFileFromLibertyServerRoot("logs/tracedata"); + + long binaryLogSize = getSizeOfBinaryLogs(binaryLogDir); + long binaryTraceSize = getSizeOfBinaryLogs(binaryTraceDir); + + logger.info("The current size of BinaryLog files in " + binaryLogDir.getAbsolutePath() + " is " + nf.format(binaryLogSize)); + assertTrue("BinaryLog Repository size should be less than 50 MB ", + binaryLogSize < (50 * 1024 * 1024)); + logger.info("The current size of BinaryTrace files in " + binaryTraceDir.getAbsolutePath() + " is " + nf.format(binaryTraceSize)); + assertTrue("Binarytrace Repository size should be less than 50 MB ", + binaryTraceSize < (50 * 1024 * 1024)); + + this.logVerificationPassed(); + } + + /** + * Server start with log settings as 100 -> during run time, remove entire element (logging) + * Run the quick log and check the size of the repository, it should not exceed 50 MB for both logdata and tracedata. + **/ + public void testPurgeMaxSize_7() throws Exception { + RemoteFile binaryLogDir = null; + RemoteFile binaryTraceDir = null; + NumberFormat nf = NumberFormat.getInstance(); + + appServ.getBackend().updateServerConfiguration(new File(appServ.getBackend().pathToAutoFVTTestFiles, "server-HPELPurgeMaxSizeTest_4.xml")); + appServ.stop(); + appServ.start(); + + appServ.getBackend().updateServerConfiguration(new File(appServ.getBackend().pathToAutoFVTTestFiles, "server-HPELPurgeMaxSizeTest_7.xml")); + + // write enough records to new log repository updated. + this.logStep("Writting log records to fill binary log repository."); + long loopsPerFullRepository = (50 * 1024 * 1024) / 200; + logger.info("writting " + nf.format(loopsPerFullRepository) + " log loops to produce " + 50 + + " MB of data."); + CommonTasks.createLogEntries(appServ, loggerName, "Sample log record for the test case " + this.getName() + ".", null, + (int) loopsPerFullRepository, CommonTasks.LOGS_TRACE, 0); + + this.logStepCompleted(); + + this.logVerificationPoint("Verifying the repository size "); + binaryLogDir = appServ.getBackend().getFileFromLibertyServerRoot("logs/logdata"); + binaryTraceDir = appServ.getBackend().getFileFromLibertyServerRoot("logs/tracedata"); + + long binaryLogSize = getSizeOfBinaryLogs(binaryLogDir); + long binaryTraceSize = getSizeOfBinaryLogs(binaryTraceDir); + + logger.info("The current size of BinaryLog files in " + binaryLogDir.getAbsolutePath() + " is " + nf.format(binaryLogSize)); + assertTrue("BinaryLog Repository size should be less than 50 MB ", + binaryLogSize < (50 * 1024 * 1024)); + logger.info("The current size of BinaryTrace files in " + binaryTraceDir.getAbsolutePath() + " is " + nf.format(binaryTraceSize)); + assertTrue("Binarytrace Repository size should be less than 50 MB ", + binaryTraceSize < (50 * 1024 * 1024)); + + this.logVerificationPassed(); + } + + /** + * Set Bootstrap Trace = 91 , server.xml Trace = 201, run the quick log and check the size of the repository. + * It should not exceed 201 MB for tracedata and 50 MB for logdata. + **/ + public void testPurgeMaxSize_8() throws Exception { + RemoteFile binaryLogDir = null; + RemoteFile binaryTraceDir = null; + NumberFormat nf = NumberFormat.getInstance(); + + CommonTasks.addBootstrapProperty(appServ, "com.ibm.hpel.trace.purgeMaxSize", "91"); + appServ.stop(); + appServ.start(); + + this.logStep("Configuring server for test case."); + appServ.getBackend().updateServerConfiguration(new File(appServ.getBackend().pathToAutoFVTTestFiles, "server-HpelLogElementDelete_1.xml")); + this.logStepCompleted(); + + // write enough records to new log repository updated. + this.logStep("Writting log records to fill binary log repository."); + long loopsPerFullRepository = (201 * 1024 * 1024) / 200; + logger.info("writting " + nf.format(loopsPerFullRepository) + " log loops to produce " + 201 + + " MB of data."); + CommonTasks.createLogEntries(appServ, loggerName, "Sample log record for the test case " + this.getName() + ".", null, + (int) loopsPerFullRepository, CommonTasks.LOGS_TRACE, 0); + + this.logStepCompleted(); + + this.logVerificationPoint("Verifying the repository size ."); + binaryLogDir = appServ.getBackend().getFileFromLibertyServerRoot("logs/logdata"); + binaryTraceDir = appServ.getBackend().getFileFromLibertyServerRoot("logs/tracedata"); + long binaryLogSize = getSizeOfBinaryLogs(binaryLogDir); + long binaryTraceSize = getSizeOfBinaryLogs(binaryTraceDir); + + logger.info("The current size of BinaryLog files in " + binaryLogDir.getAbsolutePath() + " is " + nf.format(binaryLogSize)); + assertTrue("BinaryLog Repository size should be less than 50 MB", + binaryLogSize > (45 * 1024 * 1024)); + logger.info("The current size of BinaryTrace files in " + binaryTraceDir.getAbsolutePath() + " is " + nf.format(binaryTraceSize)); + assertTrue("BinaryTrace Repository size should be less than 201 MB", + binaryTraceSize > (190 * 1024 * 1024)); + + this.logVerificationPassed(); + } + + /** + * Set Bootstrap Trace = 91 and run the quick log and check the size of the repository. + * It should not exceed 91 MB for tracedata and 50 MB for logdata + **/ + public void testPurgeMaxSize_9() throws Exception { + RemoteFile binaryLogDir = null; + RemoteFile binaryTraceDir = null; + NumberFormat nf = NumberFormat.getInstance(); + + CommonTasks.addBootstrapProperty(appServ, "com.ibm.hpel.trace.purgeMaxSize", "91"); + appServ.stop(); + appServ.start(); + + // write enough records to new log repository updated. + this.logStep("Writting log records to fill binary log repository."); + long loopsPerFullRepository = (91 * 1024 * 1024) / 200; + logger.info("writting " + nf.format(loopsPerFullRepository) + " log loops to produce " + 91 + + " MB of data."); + CommonTasks.createLogEntries(appServ, loggerName, "Sample log record for the test case " + this.getName() + ".", null, + (int) loopsPerFullRepository, CommonTasks.LOGS_TRACE, 0); + + this.logStepCompleted(); + + this.logVerificationPoint("Verifying the repository size ."); + binaryLogDir = appServ.getBackend().getFileFromLibertyServerRoot("logs/logdata"); + binaryTraceDir = appServ.getBackend().getFileFromLibertyServerRoot("logs/tracedata"); + long binaryLogSize = getSizeOfBinaryLogs(binaryLogDir); + long binaryTraceSize = getSizeOfBinaryLogs(binaryTraceDir); + + logger.info("The current size of BinaryLog files in " + binaryLogDir.getAbsolutePath() + " is " + nf.format(binaryLogSize)); + assertTrue("BinaryLog Repository size should be less than 50 MB", + binaryLogSize > (45 * 1024 * 1024)); + logger.info("The current size of BinaryTrace files in " + binaryTraceDir.getAbsolutePath() + " is " + nf.format(binaryTraceSize)); + assertTrue("BinaryTrace Repository size should be less than 91 MB", + binaryTraceSize > (85 * 1024 * 1024)); + + this.logVerificationPassed(); + } + + /** + * Returns the total size of Log files in the given directory + * + * @throws Exception + **/ + private long getSizeOfBinaryLogs(RemoteFile dirToCheck) throws Exception { + + long totalBinaryLogRepositorySize = 0; + RemoteFile[] allBinaryLogFiles = dirToCheck.list(true); + for (RemoteFile i : allBinaryLogFiles) { + totalBinaryLogRepositorySize += i.length(); +// } + } + return totalBinaryLogRepositorySize; + } + + @Override + public void tearDown() throws Exception { + // Restore values we saw before changing them in setUp() +// this.logStep("Resetting configuration to pre test values."); +// if (backup != null && backup.exists()) { +// appServ.getBackend().getServerConfigurationFile().copyFromSource(backup); +// } +// this.logStepCompleted(); + + // call the super + super.tearDown(); + } + +} \ No newline at end of file diff --git a/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/HpelPurgeMaxSizeIgnoreTest_2.java b/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/HpelPurgeMaxSizeIgnoreTest_2.java new file mode 100755 index 00000000000..25153140f84 --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/HpelPurgeMaxSizeIgnoreTest_2.java @@ -0,0 +1,168 @@ +//%Z% %I% %W% %G% %U% [%H% %T%] +/** + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + * + * DESCRIPTION: + * + * Change History: + * + * Reason Version Date User id Description + * ---------------------------------------------------------------------------- + * 97932 8.5.5 13/06/2013 sumam Test case for defect 97932. + */ +package com.ibm.ws.fat.hpel.tests; + +import java.io.File; +import java.text.NumberFormat; +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.ibm.websphere.simplicity.ApplicationServer; +import com.ibm.websphere.simplicity.OperatingSystem; +import com.ibm.websphere.simplicity.RemoteFile; +import com.ibm.ws.fat.VerboseTestCase; +import com.ibm.ws.fat.hpel.setup.HpelSetup; +import com.ibm.ws.fat.ras.util.CommonTasks; + +/** + * Test case for defect 97932 : HPEL ignores purgeMaxSize + * Test scenario + * 10. Server start without any settings -> during run time, add purgeMaxSize for log to 100, stop server, remove purgeMaxSize attribute, start server --> expect output: trace=50, + * log=50 + * + */ + +public class HpelPurgeMaxSizeIgnoreTest_2 extends VerboseTestCase { + + private final static String loggerName = HpelLogDirectoryChangeTest.class.getName(); + private final static Logger logger = Logger.getLogger(loggerName); + private final static int MAX_DEFAULT_PURGE_SIZE = 50; + + private ApplicationServer appServ = null; + + RemoteFile backup = null; + + public HpelPurgeMaxSizeIgnoreTest_2(String name) { + super(name); + } + + @Override + public void setUp() throws Exception { + // Call super.SetUp() cause we still want it's setup as well + super.setUp(); + appServ = HpelSetup.getServerUnderTest(); + // Confirm HPEL is enabled + if (!CommonTasks.isHpelEnabled(appServ)) { + // HPEL is not enabled. + this.logStep("HPEL is not enabled on " + appServ.getName() + ", attempting to enable."); + CommonTasks.setHpelEnabled(appServ, true); + // Restart now to complete switching to HPEL + appServ.stop(); + appServ.start(); + this.logStepCompleted(); + } + + // Setting the bootstrap with trace specification to get the trace logs. + CommonTasks.addBootstrapProperty(appServ, "com.ibm.ws.logging.trace.specification", "*=fine=enabled"); + appServ.stop(); + appServ.start(); + + } + + /** + * Test Server start without any settings -> during run time, add purgeMaxSize for log to 100, stop server, remove purgeMaxSize attribute, start server --> expect output: + * trace=50, + * log=50 + **/ + public void testPurgeMaxSize_10() throws Exception { + RemoteFile binaryLogDir = null; + RemoteFile binaryTraceDir = null; + NumberFormat nf = NumberFormat.getInstance(); + + appServ.getBackend().updateServerConfiguration(new File(appServ.getBackend().pathToAutoFVTTestFiles, "server-HPELPurgeMaxSizeTest_4.xml")); + appServ.stop(); + + appServ.getBackend().updateServerConfiguration(new File(appServ.getBackend().pathToAutoFVTTestFiles, "server-HPELPurgeMaxSizeTest_5.xml")); + appServ.start(); + + // write enough records to new log repository updated. + this.logStep("Writting log records to fill binary log repository."); + long loopsPerFullRepository = (MAX_DEFAULT_PURGE_SIZE * 1024 * 1024) / 200; + logger.info("writting " + nf.format(loopsPerFullRepository) + " log loops to produce " + MAX_DEFAULT_PURGE_SIZE + + " MB of data."); + CommonTasks.createLogEntries(appServ, loggerName, "Sample log record for the test case " + this.getName() + ".", null, + (int) loopsPerFullRepository, CommonTasks.LOGS_TRACE, 0); + + this.logStepCompleted(); + + this.logVerificationPoint("Verifying the repository size "); + binaryLogDir = appServ.getBackend().getFileFromLibertyServerRoot("logs/logdata"); + binaryTraceDir = appServ.getBackend().getFileFromLibertyServerRoot("logs/tracedata"); + + long binaryLogSize = getSizeOfBinaryLogs(binaryLogDir); + long binaryTraceSize = getSizeOfBinaryLogs(binaryTraceDir); + + logger.info("The current size of BinaryLog files in " + binaryLogDir.getAbsolutePath() + " is " + nf.format(binaryLogSize)); + assertTrue("BinaryLog Repository size should be less than 50 MB ", + binaryLogSize < (MAX_DEFAULT_PURGE_SIZE * 1024 * 1024)); + logger.info("The current size of BinaryTrace files in " + binaryTraceDir.getAbsolutePath() + " is " + nf.format(binaryTraceSize)); + assertTrue("Binarytrace Repository size should be less than 50 MB ", + binaryTraceSize < (MAX_DEFAULT_PURGE_SIZE * 1024 * 1024)); + + this.logVerificationPassed(); + } + + /** + * Returns the total size of log files in the given directory + * + * @throws Exception + **/ + private long getSizeOfBinaryLogs(RemoteFile dirToCheck) throws Exception { + + long totalBinaryLogRepositorySize = 0; + RemoteFile[] allBinaryLogFiles = dirToCheck.list(true); + for (RemoteFile i : allBinaryLogFiles) { + totalBinaryLogRepositorySize += i.length(); +// } + } + return totalBinaryLogRepositorySize; + } + + @Override + public void tearDown() throws Exception { + // Restore values we saw before changing them in setUp() + this.logStep("Resetting configuration to pre test values."); + if (backup != null && backup.exists()) { + appServ.getBackend().getServerConfigurationFile().copyFromSource(backup); + } + this.logStepCompleted(); + + // call the super + super.tearDown(); + } + + /** + * Determine if we should or should not execute this test. Returns true if the test should NOT be ran. + * **/ + @Override + public boolean skipTest() { + // Test does not do any good on z/OS since TextLog is for Controller only - so we can't generate logs to fill up + // TextLog repository. This may need to be revisited if we implement TextLog for servant. + try { + return HpelSetup.getNodeUnderTest().getMachine().getOperatingSystem().equals(OperatingSystem.ZOS); + } catch (Exception e) { + CommonTasks.writeLogMsg(Level.SEVERE, "Unable to determine if we are on z/OS or not. Not skipping test"); + e.printStackTrace(System.err); + } + return false; + } + +} \ No newline at end of file diff --git a/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/HpelTextLogRetention.java b/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/HpelTextLogRetention.java new file mode 100755 index 00000000000..517a1f5cf1d --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/HpelTextLogRetention.java @@ -0,0 +1,213 @@ +//%Z% %I% %W% %G% %U% [%H% %T%] +/** + * COMPONENT_NAME: WAS.ras.fvt + * + * ORIGINS: 27 (used for IBM originated files) + * + * IBM Confidential OCO Source Material + * 5639-D57 (C) COPYRIGHT International Business Machines Corp. 2002 + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + * + * + * DESCRIPTION: + * + * Change History: + * + * Reason Version Date User id Description + * ---------------------------------------------------------------------------- + * PM48157 8.0 10/03/2011 shighbar HPEL TextLog retention policy does not remove previous server instances logs. + */ + +package com.ibm.ws.fat.hpel.tests; + +import java.io.File; +import java.text.NumberFormat; +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.ibm.websphere.simplicity.ApplicationServer; +import com.ibm.websphere.simplicity.OperatingSystem; +import com.ibm.websphere.simplicity.RemoteFile; +import com.ibm.ws.fat.VerboseTestCase; +import com.ibm.ws.fat.hpel.setup.HpelSetup; +import com.ibm.ws.fat.ras.util.CommonTasks; + +/** + * Test case for defect PM48157 : Hpel TextLog files retention policy not working. The retention policy was previously + * working per server instance but not across multiple instances. As a result the size of the total TextLogs was able to + * grow by up to purgeMaxSize each time there was a new instance (server bounce). Test case needs to check for retention + * not only in a single run but across multiple runs to cover this case. + * + */ + +public class HpelTextLogRetention extends VerboseTestCase { + + private final static String loggerName = HpelTextLogRetention.class.getName(); + private final static Logger logger = Logger.getLogger(loggerName); + private final static int MAX_TEXTLOG_PURGE_SIZE = 10; + private ApplicationServer appServ = null; + + boolean default_TextPurgeEnabled; // original purgeBySize for TextLog + int default_TextPurgeSize; + String default_outOfSpaceAction; + + RemoteFile backup = null; + + public HpelTextLogRetention(String name) { + super(name); + } + + @Override + public void setUp() throws Exception { + // Call super.SetUp() cause we still want it's setup as well + super.setUp(); + appServ = HpelSetup.getServerUnderTest(); + // Confirm HPEL is enabled + if (!CommonTasks.isHpelEnabled(appServ)) { + // HPEL is not enabled. + this.logStep("HPEL is not enabled on " + appServ.getName() + ", attempting to enable."); + CommonTasks.setHpelEnabled(appServ, true); + // Restart now to complete switching to HPEL + appServ.restart(); + this.logStepCompleted(); + } + + this.logStep("Configuring server for test case."); + backup = new RemoteFile(appServ.getBackend().getMachine(), new File(appServ.getBackend().getServerRoot(), "server-backup.xml").getPath()); + if (!backup.exists()) { + backup.copyFromSource(appServ.getBackend().getServerConfigurationFile()); + } + appServ.getBackend().updateServerConfiguration(new File(appServ.getBackend().pathToAutoFVTTestFiles, "server-HpelTextLogRetention.xml")); + + if (!appServ.getBackend().isStarted()) { + appServ.start(); + } +// ConfigObject textChild = CommonTasks.getTextLogChild(appServ); +// default_TextPurgeEnabled = textChild.getAttributeByName("purgeBySizeEnabled").getValueAsBoolean(); +// // Test requires that purgeBySize be enabled. +// textChild.getAttributeByName("purgeBySizeEnabled").setValue(true); +// default_TextPurgeSize = textChild.getAttributeByName("purgeMaxSize").getValueAsInt(); +// // Speed up test by setting purge size to minimum possible +// textChild.getAttributeByName("purgeMaxSize").setValue(MAX_TEXTLOG_PURGE_SIZE); +// // Check that outOfSpaceAction is set to PurgeOld +// default_outOfSpaceAction = textChild.getAttributeByName("outOfSpaceAction").getValueAsString(); +// textChild.getAttributeByName("outOfSpaceAction").setValue("PurgeOld"); +// +// // Sync changes before restarting the server. +// HpelSetup.getCellUnderTest().getWorkspace().saveAndSync(); + this.logStepCompleted(); + + // restart the server +// this.logStep("Starting/restarting application server to apply config changes."); +// appServ.stop(); +// appServ.start(); +// this.logStepCompleted(); + + } + + /** + * Test that HPEL's TextLog size based retention policy works. Both within a single server instance and across + * server restarts. + **/ + public void testHPELTextLogSizeRetention() throws Exception { + RemoteFile TextLogDir = CommonTasks.getTextLogDir(appServ); + NumberFormat nf = NumberFormat.getInstance(); + + // write enough records to force size based retention policy to kick in. + // there is ~600 bytes per log record. Using 200 to allow buffer. + this.logStep("Writting log records to fill TextLog repository."); + long loopsPerFullRepository = (MAX_TEXTLOG_PURGE_SIZE * 1024 * 1024) / 200; + logger.info("writting " + nf.format(loopsPerFullRepository) + " log loops to produce " + MAX_TEXTLOG_PURGE_SIZE + + " MB of data."); + CommonTasks.createLogEntries(appServ, loggerName, "Sample log record for the test case " + this.getName() + ".", null, + (int) loopsPerFullRepository, CommonTasks.LOGS, 0); + this.logStepCompleted(); + + this.logVerificationPoint("Verifying that repository has not grown above max purge size."); + long logsSize = getSizeOfTextLogs(TextLogDir); + logger.info("The current size of TextLog files in " + TextLogDir.getAbsolutePath() + " is " + nf.format(logsSize)); + assertTrue("TextLog Repository size shouldn't be larger than purgeMaxSize", + logsSize <= (MAX_TEXTLOG_PURGE_SIZE * 1024 * 1024)); + this.logVerificationPassed(); + + this.logStep("Restarting Server in preperation to check that retention policy spans server instances"); + appServ.stop(); + appServ.start(); + + this.logStep("Writting log records to repository"); + // We don't have to fill the repository - half the repository size will work fine. + logger.info("writting " + nf.format((int) (loopsPerFullRepository / 2)) + " log loops to produce " + MAX_TEXTLOG_PURGE_SIZE + / 2 + " MB of data."); + CommonTasks.createLogEntries(appServ, loggerName, "Sample log record for the test case " + this.getName() + ".", null, + (int) (loopsPerFullRepository / 2), CommonTasks.LOGS, 0); + this.logStepCompleted(); + + this.logVerificationPoint("Verifying that the repository size is still below max purge size."); + logsSize = getSizeOfTextLogs(TextLogDir); + logger.info("The current size of TextLog files in " + TextLogDir.getAbsolutePath() + " is " + nf.format(logsSize)); + assertTrue("TextLog Repository size shouldn't be larger than purgeMaxSize after server restart.", + logsSize <= (MAX_TEXTLOG_PURGE_SIZE * 1024 * 1024)); + this.logVerificationPassed(); + } + + /** + * Returns the total size of TextLog files in the given directory + * + * @throws Exception + **/ + private long getSizeOfTextLogs(RemoteFile dirToCheck) throws Exception { + long TotalTextRepositorySize = 0; + RemoteFile[] AllTextLogFiles = dirToCheck.list(false); + for (RemoteFile i : AllTextLogFiles) { + if (i.getName().startsWith("TextLog_")) { + // counting this as a valid TextLog log file. + TotalTextRepositorySize += i.length(); + } + } + return TotalTextRepositorySize; + } + + @Override + public void tearDown() throws Exception { + // Restore values we saw before changing them in setUp() + this.logStep("Resetting configuration to pre test values."); + if (backup != null && backup.exists()) { + appServ.getBackend().getServerConfigurationFile().copyFromSource(backup); + } +// ConfigObject textChild = CommonTasks.getTextLogChild(appServ); +// textChild.getAttributeByName("purgeBySizeEnabled").setValue(default_TextPurgeEnabled); +// textChild.getAttributeByName("purgeMaxSize").setValue(default_TextPurgeSize); +// textChild.getAttributeByName("outOfSpaceAction").setValue(default_outOfSpaceAction); +// +// HpelSetup.getCellUnderTest().getWorkspace().saveAndSync(); + this.logStepCompleted(); + + // No need to restart server in Liberty if it's not bootstrap.properties changes. +// this.logStep("Restarting server " + appServ.getName() + " to enable settings available before the test."); +// appServ.stop(); +// appServ.start(); +// this.logStepCompleted(); + + // call the super + super.tearDown(); + } + + /** + * Determine if we should or should not execute this test. Returns true if the test should NOT be ran. + * **/ + @Override + public boolean skipTest() { + // Test does not do any good on z/OS since TextLog is for Controller only - so we can't generate logs to fill up + // TextLog repository. This may need to be revisited if we implement TextLog for servant. + try { + return HpelSetup.getNodeUnderTest().getMachine().getOperatingSystem().equals(OperatingSystem.ZOS); + } catch (Exception e) { + CommonTasks.writeLogMsg(Level.SEVERE, "Unable to determine if we are on z/OS or not. Not skipping test"); + e.printStackTrace(System.err); + } + return false; + } + +} \ No newline at end of file diff --git a/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/LogViewerExec.java b/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/LogViewerExec.java new file mode 100755 index 00000000000..9ff6ce72bb1 --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/LogViewerExec.java @@ -0,0 +1,347 @@ +//%Z% %I% %W% %G% %U% [%H% %T%] +/* + * Change History: + * + * Reason Version Date User id Description + * ---------------------------------------------------------------------------- + * F000896.23216 8.0 08/25/2010 shighbar Update test case for z/OS support. + * 653858 8.0 09/08/2010 spaungam Invalid option test doesn't work in CT + * 677722 8.0 11/05/2010 mcasile msgid key removed from logviewer nls + * 677210 8.0 11/05/2010 spaungam logviewer script is missing from iSeries + * 690576 8.0 02/16/2011 spaungam use qsh shell on iSeries with new simplicity + * 695788 8.0 03/09/2011 shighbar Always set repositoryDir param to avoid LV hang on user input. + * 712273 8.0 09/16/2011 belyi Add test for process name in the header. + */ +package com.ibm.ws.fat.hpel.tests; + +import java.util.ArrayList; +import java.util.Random; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import com.ibm.websphere.simplicity.ApplicationServer; +import com.ibm.websphere.simplicity.Machine; +import com.ibm.websphere.simplicity.Node; +import com.ibm.websphere.simplicity.OperatingSystem; +import com.ibm.websphere.simplicity.ProgramOutput; +import com.ibm.websphere.simplicity.RemoteFile; +import com.ibm.ws.fat.Props; +import com.ibm.ws.fat.VerboseTestCase; +import com.ibm.ws.fat.hpel.setup.HpelSetup; +import com.ibm.ws.fat.ras.util.CommonTasks; + +/** + * This task is to read from an active servers HPEL repository in basic format and to verify there are no errors and to + * check for key output. + * + * + */ +public class LogViewerExec extends VerboseTestCase { + + private static final Logger thisLogger = Logger.getLogger(LogViewerExec.class.getName()); + private final String outFileName = this.getName() + ".lv_out.log"; + RemoteFile rOutLog = null; + RemoteFile rProfRootDir = null; + RemoteFile rProfBinFile = null; + + /** + * Constructs a single instance of this Test (one test method). + * + * @param name + * The name of the test method to run + */ + public LogViewerExec(String name) { + super(name); + } + + /** + * Configures instance resources to initialize this TestCase. + * + * @throws Exception + * if a problem happens while configuring the test fixture. + */ + @Override + public void setUp() throws Exception { + // Call super.SetUp() cause we still want it's setup as well + super.setUp(); + + // Confirm HPEL is enabled + if (!CommonTasks.isHpelEnabled(HpelSetup.getServerUnderTest())) { + // HPEL is not enabled. + this.logStep("HPEL is not enabled on " + HpelSetup.getServerUnderTest().getName() + ", attempting to enable."); + CommonTasks.setHpelEnabled(HpelSetup.getServerUnderTest(), true); + // HpelSetup.getServerUnderTest().restart(); Bug# 17199 + HpelSetup.getServerUnderTest().stop(); + HpelSetup.getServerUnderTest().start(); + this.logStepCompleted(); + } + + assertTrue("Failed assertion that HPEL is enabled", CommonTasks.isHpelEnabled(HpelSetup.getServerUnderTest())); + + // Liberty profile root is the install root. + rProfRootDir = new RemoteFile(HpelSetup.getNodeUnderTest().getMachine(), HpelSetup.getServerUnderTest().getBackend().getInstallRoot()); +// rProfRootDir = new RemoteFile(HpelSetup.getNodeUnderTest().getMachine(), HpelSetup.getNodeUnderTest().getProfileDir()); + rProfBinFile = new RemoteFile(HpelSetup.getNodeUnderTest().getMachine(), rProfRootDir, "bin"); + + } + + /** + * A method to drive the execution of the logViewer tool on the remote machine/server that is being tested. + * + * @throws Exception + */ + private ProgramOutput exeLogViewer(String[] cmdLineOptions) throws Exception { + // make platform agnostic to handle .sh and .bat + String exeExt = ""; + final String LOG_VIEWER = "logViewer"; + + //if non-iSeries +// if (!HpelSetup.getNodeUnderTest().getMachine().getOperatingSystem().equals(OperatingSystem.ISERIES)){ + if (HpelSetup.getNodeUnderTest().getMachine().getOperatingSystem().equals(OperatingSystem.WINDOWS)) { + exeExt = ".bat"; +// } else { +// exeExt = ".sh"; + } + + StringBuilder cmd = new StringBuilder(100); + cmd.append(rProfBinFile.getAbsolutePath()).append(HpelSetup.getNodeUnderTest().getMachine().getOperatingSystem().getFileSeparator()); + cmd.append(LOG_VIEWER).append(exeExt).append(" "); + + for (String cmdOption : cmdLineOptions) { + if (!cmdOption.isEmpty()) { + cmd.append("\"" + cmdOption + "\" "); + } + } + logMsg("executing: " + cmd.toString()); +// logMsg("executing: " + rProfBinFile.getAbsolutePath() + HpelSetup.getNodeUnderTest().getMachine().getOperatingSystem().getFileSeparator() + cmd.toString()); +// return HpelSetup.getNodeUnderTest().getMachine().execute(LOG_VIEWER + exeExt, cmdLineOptions, rProfBinFile.getAbsolutePath()); + return HpelSetup.getNodeUnderTest().getMachine().execute(cmd.toString(), rProfBinFile.getAbsolutePath()); +// } +// //iSeries LogViewer needs to be executed in the shell qsh +// else{ +// return HpelSetup.getNodeUnderTest().getMachine().executeQSH(LOG_VIEWER, cmdLineOptions, rProfBinFile.getAbsolutePath(), null); +// } + } + + /** + * Tests that LogViewer can be executed on the target machine and that no error's are thrown. If the repositories + * are in the default location - logViewer will execute against default values; i.e. against the log and trace data + * located in the profile's log directory etc. If the configuration shows that the logdata is being written to + * another location; that location will be passed to logViewer. In the case where the log data is being written to + * another location, only the log data will be ran against. + * + * @throws Exception + */ + public void testLogViewerExecutes() throws Exception { + // need to have messages for the logViewer to process. + CommonTasks.createLogEntries(HpelSetup.getServerUnderTest(), LogViewerExec.class.getName(), "Some Msg goes here", null, 25, CommonTasks.LOGS, -1); + + Node node = HpelSetup.getNodeUnderTest(); + rOutLog = new RemoteFile(node.getMachine(), node.getMachine().getTempDir(), outFileName); + + this.logStep("executing logViewer on " + node.getProfileName()); + + String arg1 = "-outLog"; + String arg2 = rOutLog.getAbsolutePath(); + + ProgramOutput lvPrgmOut; + + lvPrgmOut = exeLogViewer(new String[] { arg1, arg2, "-repositoryDir", CommonTasks.getBinaryLogDir(HpelSetup.getServerUnderTest()).getAbsolutePath() }); + + this.logVerificationPoint("Verifying logViewer std out/err and status return code."); + logMsg(" === LogViewer's stdout: === "); + logMsg(lvPrgmOut.getStdout()); + logMsg(" "); + if (lvPrgmOut.getStderr().length() > 0) { + // LogViewer reported some errors. + logMsg(" === LogViewer std.err: ==="); + logMsg(lvPrgmOut.getStderr()); + } + assertTrue("Failed assertion that logViewer exited with successful return code", (lvPrgmOut.getReturnCode() == 0)); + + assertTrue("Failed assertion that logViewer did produce an output file", rOutLog.exists()); + this.logVerificationPassed(); + this.logStepCompleted(); + + // pull the resulting text based log over to test machine. + this.logStep("Pulling logViewer output file ( " + outFileName + " ) to results dir"); + RemoteFile lResultsDir = new RemoteFile(Machine.getLocalMachine(), Props.getFileProperty(Props.DIR_LOG).getCanonicalPath()); + RemoteFile lOutLog = new RemoteFile(Machine.getLocalMachine(), lResultsDir, outFileName); + + lOutLog.copyFromSource(rOutLog, true); // Even though file is text we are getting transfer exceptions that + // appear to be because logViewer output is UTF8 or contains other + // special characters. Transferring in binary seems to correct this. + this.logStepCompleted(); + } + + /** + * Tests that logViewer correctly report an invalid option when one is passed to it. + * + * @throws Exception + */ + public void testLogViewerInvalidOption() throws Exception { + this.logStep("executing logViewer on " + HpelSetup.getNodeUnderTest().getProfileName()); + // generate a random option that is between 3 and 15 characters long starting with "bad". + String alphabet = "abcdefghijklmnopqrstuvwxyz"; + StringBuffer invalidOption = new StringBuffer(); + invalidOption.append("-bad"); // need the option flag first. + Random rnd = new Random(); + for (int i = 1; i <= rnd.nextInt(12); i++) { + invalidOption.append(alphabet.charAt(rnd.nextInt(alphabet.length()))); + } + + StringBuffer expectedResponse = new StringBuffer(); + expectedResponse.append("Unknown Argument: "); + expectedResponse.append(invalidOption); + expectedResponse.append("\\s+"); //match as a regular expression + expectedResponse.append("Use option -help for usage information."); + + ProgramOutput lvPrgmOut = exeLogViewer(new String[] { invalidOption.toString() }); + this.logVerificationPoint("Verifying logViewer std out/err and status return code."); + logMsg(" === LogViewer's stdout: === "); + logMsg(lvPrgmOut.getStdout()); + logMsg(" "); + if (lvPrgmOut.getStderr().length() > 0) { + // LogViewer reported some errors. + logMsg(" === LogViewer std.err: ==="); + logMsg(lvPrgmOut.getStderr()); + } + + assertTrue("Failed assertion that logViewer exited with an error return code", (lvPrgmOut.getReturnCode() != 0)); + assertTrue("Failed assertion that logViewer reported invalid option. Where //s is any number of spaces, expected=" + + expectedResponse.toString().trim() + ". result=" + lvPrgmOut.getStdout().trim(), + Pattern.matches(expectedResponse.toString(), lvPrgmOut.getStdout().trim())); + + this.logVerificationPassed(); + this.logStepCompleted(); + } + + public void testHeaderProcessName() throws Exception { + this.logStep("get instance list from " + HpelSetup.getNodeUnderTest().getProfileName()); + + ProgramOutput lvPrgmOut = exeLogViewer(new String[] { "-listInstances", "-repositoryDir", CommonTasks.getBinaryLogDir(HpelSetup.getServerUnderTest()).getAbsolutePath() }); + String out = lvPrgmOut.getStdout(); + + // (WI 234118) We cannot rely on matching "Instance ID" as the header because that message is translated when running in non-English locales, causing this + // test to fail. Instead, match the lines starting with a number assuming those are the instance IDs. + // Collect IDs belonging to the current instance run. + int indx; + String controllerID = null; + ArrayList ids = new ArrayList(); + for (String outLine : out.split("\\r?\\n")) { + Pattern p = Pattern.compile("^\\s*(\\d+(?:/\\S+)?)\\s"); + Matcher m = p.matcher(outLine); + if (m.find()) { + String newID = m.group(1); + logMsg("Processing instance id " + newID); + indx = newID.indexOf('/'); + String newControllerID = indx < 0 ? newID : newID.substring(0, indx); + logMsg("It belongs to controller " + newControllerID); + if (controllerID == null || !controllerID.equals(newControllerID)) { + // It's a new controller's instance, reset the list of IDs. + logMsg("It's a new controller, reset list of instances"); + ids.clear(); + controllerID = newControllerID; + } + ids.add(newID); + } + } + + assertFalse("No instance IDs found", ids.isEmpty()); + this.logStepCompleted(); + + this.logStep("Verify procName and procId for each retrieved instance"); + + boolean isZOS = HpelSetup.getNodeUnderTest().getMachine().getOperatingSystem().equals(OperatingSystem.ZOS); + boolean hasController = false; + boolean hasServant = false; + ApplicationServer server = HpelSetup.getServerUnderTest(); + for (String id : ids) { + this.logVerificationPoint("Verifying instance " + id); + + lvPrgmOut = exeLogViewer(new String[] { "-instance", id, "-repositoryDir", CommonTasks.getBinaryLogDir(HpelSetup.getServerUnderTest()).getAbsolutePath() }); + out = lvPrgmOut.getStdout(); + // Should be okay matching the English text here because this is not a translated message. + int indx1 = out.indexOf(" running with process name "); + int indx2 = out.indexOf(" and process id ", indx1); + assertTrue("Instance with ID " + id + " does not have proper header", indx1 > 0 && indx2 > indx1); + String procName = out.substring(indx1 + 27, indx2); + String procId = out.substring(indx2 + 16).split("\\s*\\n\\s*", 2)[0]; + String expProcName; + String expProcId; + if (isZOS) { + indx = id.indexOf("/"); + if (indx < 0) { + // This is controller, take name values from Simplicity, can't verify jobID this way though + expProcName = server.getShortName(); + hasController = true; + } else { + // This is servant, take values from instance ID. + indx1 = id.indexOf("-", indx); + indx2 = id.indexOf("_", indx1); + assertTrue("Instance ID " + id + " is incorrectly formatted", indx1 > indx && indx2 > indx1); + expProcName = id.substring(indx1 + 1, indx2); + expProcId = id.substring(indx2 + 1); + hasServant = true; + assertEquals("Process ID is incorrect", expProcId, procId); + } + } else { + // On Liberty procName is just the server name. + expProcName = server.getBackend().getServerName(); +// expProcName = server.getCellName() + "\\" + server.getNodeName() + "\\" + server.getName(); + // Don't verify process Id since it is not available in Liberty FAT +// expProcId = server.getProcessIdString(); +// assertEquals("Process ID is incorrect", expProcId, procId); + } + assertEquals("Process Name is incorrect", expProcName, procName); + + this.logVerificationPassed(); + } + + this.logVerificationPoint("Verifying completeness of the test"); + if (isZOS) { + if (!hasController && !hasServant) { + fail("Test on zOS is missing both controller and servant instances"); + } + if (!hasController) { + fail("Test on zOS is missing controller instance"); + } + if (!hasServant) { + fail("Test on zOS is missing at least one servant instance"); + } + } else if (ids.size() == 0) { + fail("Test on distributed has no instances to verify"); + } + this.logVerificationPassed(); + + this.logStepCompleted(); + } + + /** + * Clean up instance resources to initialize this TestCase. + * + * @throws Exception + * if a problem happens while configuring the test fixture. + */ + @Override + public void tearDown() throws Exception { + // delete the output log on the remote machine. + if ((rOutLog != null) && (rOutLog.exists())) + rOutLog.delete(); + + // call the super + super.tearDown(); + } + + /** + * A simple method used to log messages from this test case to the test case's logs + */ + public void logMsg(String msg) { + if (thisLogger.isLoggable(Level.INFO)) { + thisLogger.info(msg); + } + } + +} diff --git a/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/TraceSpecificationSetToAllTest.java b/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/TraceSpecificationSetToAllTest.java new file mode 100755 index 00000000000..28cc7a15ea1 --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/TraceSpecificationSetToAllTest.java @@ -0,0 +1,150 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2014 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.fat.hpel.tests; + +import java.io.BufferedReader; +import java.net.HttpURLConnection; +import java.net.URL; + +import com.ibm.websphere.simplicity.ApplicationServer; +import com.ibm.websphere.simplicity.OperatingSystem; +import com.ibm.websphere.simplicity.ProgramOutput; +import com.ibm.websphere.simplicity.RemoteFile; +import com.ibm.websphere.simplicity.log.Log; +import com.ibm.ws.fat.VerboseTestCase; +import com.ibm.ws.fat.hpel.setup.HpelSetup; +import com.ibm.ws.fat.ras.util.CommonTasks; +import componenttest.topology.utils.HttpUtils; + +/** + * This FAT test is written against RTC defect 137645 and 99171 + */ +public class TraceSpecificationSetToAllTest extends VerboseTestCase { + +// private static LibertyServer server = LibertyServerFactory.getLibertyServer("HpelServer"); + private ApplicationServer server = null; + private static final int CONN_TIMEOUT = 60; + private final Class c = TraceSpecificationSetToAllTest.class; + + RemoteFile rProfRootDir = null; + RemoteFile rProfBinFile = null; + + private static final String traceSpecification = "com.ibm.ws.logging.*=all"; + + public TraceSpecificationSetToAllTest(String name) { + super(name); + } + + @Override + public void setUp() throws Exception { + server = HpelSetup.getServerUnderTest(); + + if (!CommonTasks.isHpelEnabled(server)) { + // HPEL is not enabled. + this.logStep("HPEL is not enabled on " + server.getName() + ", attempting to enable."); + CommonTasks.setHpelEnabled(HpelSetup.getServerUnderTest(), true); + // if HPEL was not enabled, make sure trace spec is not valid to ensure restart below. + this.logStepCompleted(); + } + + CommonTasks.setHpelTraceSpec(HpelSetup.getServerUnderTest(), traceSpecification); + + CommonTasks.addBootstrapProperty(server, "com.ibm.ws.logging.trace.specification", "com.ibm.ws.logging.*=all:com.ibm.ws.org.*=all=enabled"); + + this.logStep("Bouncing server for new spec to take effect. Stopping application server"); + HpelSetup.getServerUnderTest().stop(); + this.logStepCompleted(); + + // Start Server + this.logStep("Starting the application server"); + HpelSetup.getServerUnderTest().start(); + this.logStepCompleted(); + + this.logStep("Checking the trace spec post app server restart: " + + CommonTasks.getHpelTraceSpec(HpelSetup.getServerUnderTest())); + this.logStepCompleted(); + assertTrue("Failed assertion that HPEL trace specification is set to " + traceSpecification, + traceSpecification.contains(CommonTasks.getHpelTraceSpec(HpelSetup.getServerUnderTest()))); + } + + /** + * This fat test ensures that if we set trace specification as "com.ibm.ws.logging.trace.specification=*=all" + * and write the entry, exit level messages then servlet request goes well and + * server does not throw StackOverflow exception. + * + * RTC WI : 137645 + * + * @throws Exception + */ + public void testResourceInjectionWorkNotGivingStackOverflow() throws Exception { + String arg1 = "view"; + String compareString; + + String txt = "http://" + server.getBackend().getHostname() + ":" + server.getBackend().getHttpDefaultPort() + "/HpelFat/WritingCustomLogServlet"; + URL url = new URL(txt); + Log.info(c, "testResourceInjectionWorkNotGivingStackOverflow", "Calling customLogger Application with URL=" + url.toString()); + + HttpURLConnection con = HttpUtils.getHttpConnection(url, HttpURLConnection.HTTP_OK, CONN_TIMEOUT); + BufferedReader br = HttpUtils.getConnectionStream(con); + String line = br.readLine(); + assertTrue("The response did not contain \'Servlet successfullly completed\' it's content was: " + line, + line.contains("Servlet successfullly completed")); + + compareString = "StackOverFlow"; + ProgramOutput lvPrgmOut = exeBinaryLog(new String[] { arg1, server.getBackend().getServerName(), "--includeInstance=latest" }); + Log.info(c, "testResourceInjectionWorkNotGivingStackOverflow", "Server Name : " + server.getBackend().getServerName()); + + String out = lvPrgmOut.getStdout(); + assertFalse(compareString, out.contains(compareString)); + + /** + * This assert verify RTC WI : 99171 + * Defect says that HPEL logs does not matches with text log. And comparison string used was + * "Event:org.osgi.framework.BundleEvent[source=com.ibm.ws.logging.osgi" + * We have replicated the same scenario here. + */ + compareString = "BundleEvent STARTING"; + assertTrue(compareString, out.contains(compareString)); + + compareString = "Event:org.osgi.framework.BundleEvent[source=com.ibm.ws.logging.osgi"; + assertTrue(compareString, out.contains(compareString)); + } + + /** + * A method to drive the execution of the binaryLog tool on the remote machine/server that is being tested. + * + * @throws Exception + */ + private ProgramOutput exeBinaryLog(String[] cmdLineOptions) throws Exception { + // make platform agnostic to handle .sh and .bat + String exeExt = ""; + final String BINARY_LOG = "binaryLog"; + + if (HpelSetup.getNodeUnderTest().getMachine().getOperatingSystem().equals(OperatingSystem.WINDOWS)) { + exeExt = ".bat"; + } + rProfRootDir = new RemoteFile(HpelSetup.getNodeUnderTest().getMachine(), HpelSetup.getServerUnderTest().getBackend().getInstallRoot()); + rProfBinFile = new RemoteFile(HpelSetup.getNodeUnderTest().getMachine(), rProfRootDir, "bin"); + StringBuilder cmd = new StringBuilder(100); + cmd.append(rProfBinFile.getAbsolutePath()).append(HpelSetup.getNodeUnderTest().getMachine().getOperatingSystem().getFileSeparator()); + cmd.append(BINARY_LOG).append(exeExt).append(" "); + + for (String cmdOption : cmdLineOptions) { + if (!cmdOption.isEmpty()) { + cmd.append("\"" + cmdOption + "\" "); + } + } + + Log.info(c, "exeBinaryLog", "executing: " + cmd.toString()); + return HpelSetup.getNodeUnderTest().getMachine().execute(cmd.toString(), rProfBinFile.getAbsolutePath()); + } +} diff --git a/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/VerifyRepositoryAccuracy.java b/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/VerifyRepositoryAccuracy.java new file mode 100755 index 00000000000..671b73a37bd --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/hpel/tests/VerifyRepositoryAccuracy.java @@ -0,0 +1,337 @@ +//%Z% %I% %W% %G% %U% [%H% %T%] +/* + * Change History: + * + * Reason Version Date User id Description + * ---------------------------------------------------------------------------- + * F017049-18796.1 8.0 1/08/2010 spaungam Update test to support subdirectories + * F000896.23216 8.0 06/10/2010 shighbar Update to work on z/OS requires support for reading servants. Refactored initialize method into setup to reduce restarts which was impacting test on z/OS. + */ +package com.ibm.ws.fat.hpel.tests; + +import java.io.File; +import java.util.Date; + +import com.ibm.websphere.logging.hpel.reader.RepositoryLogRecord; +import com.ibm.websphere.logging.hpel.reader.RepositoryReaderImpl; +import com.ibm.websphere.logging.hpel.reader.ServerInstanceLogRecordList; +import com.ibm.websphere.simplicity.Machine; +import com.ibm.websphere.simplicity.RemoteFile; +import com.ibm.ws.fat.Props; +import com.ibm.ws.fat.VerboseTestCase; +import com.ibm.ws.fat.hpel.setup.HpelSetup; +import com.ibm.ws.fat.ras.util.CommonTasks; + +/** + * This test is about verifying that HPEL is accurately reporting the number of messages sent to it. + * + * The test outline is as follows: 1: Create an HTTP client to the LogCreator JSP that logs messages (use the + * CommonTasks object) 2: Enable tracing so a tracedata directory and repository is created 3: Call the HTTP client with + * a known number of logging entries 4: Get the log records from the repository and count them 5: Do they match? Yes, + * pass, No, fail + * + */ +public class VerifyRepositoryAccuracy extends VerboseTestCase { + String localLogsRepositoryPath = null; + String localTraceRepositoryPath = null; + String uniqueLoggerID_Tag; + String loggerName = "VRAccuracyLogger"; + String logMessage = "VRAccuracy Message for FAT testing"; + final String TRACE_SPECIFICATION = "VRAccuracyLogger*=all"; // trace spec needed for this test case. + int logCount = 49; + boolean loggerSetup = false; + + public VerifyRepositoryAccuracy(String name) { + super(name); + } + + /** + * Configures instance resources to initialize this TestCase. + * + * @throws Exception + * if a problem happens while configuring the test fixture. + */ + @Override + public void setUp() throws Exception { + // Call super.SetUp() cause we still want it's setup as well + super.setUp(); + + // Confirm HPEL is enabled + if (!CommonTasks.isHpelEnabled(HpelSetup.getServerUnderTest())) { + // HPEL is not enabled. + this.logStep("HPEL is not enabled on " + HpelSetup.getServerUnderTest().getName() + ", attempting to enable."); + CommonTasks.setHpelEnabled(HpelSetup.getServerUnderTest(), true); + // if HPEL was not enabled, make sure trace spec is not valid to ensure restart below. + CommonTasks.setHpelTraceSpec(HpelSetup.getServerUnderTest(), null); + this.logStepCompleted(); + } + + /* + * Since we have multiple test methods in this test case, we will only restart if the spec is not already set to + * what we need. This will avoid extra server restarts which adds to the bucket execution time. + */ + this.logStep("Checking the HPEL trace spec for " + this.getName()); + if (!CommonTasks.getHpelTraceSpec(HpelSetup.getServerUnderTest()).equals(TRACE_SPECIFICATION)) { + // The current spec is not what we need for this test - update spec and bounce server to take effect + this.logStep("Updating the hpel trace spec to " + TRACE_SPECIFICATION + " as part of setup for " + this.getName()); + CommonTasks.setHpelTraceSpec(HpelSetup.getServerUnderTest(), TRACE_SPECIFICATION); + + // need to restart the application server now + // Stop Server first. + this.logStep("Bouncing server for new spec to take effect. Stopping application server"); + HpelSetup.getServerUnderTest().stop(); + this.logStepCompleted(); + + Thread.sleep(10000); // stop operation blocks, but want short pause before restarting. + + // Start Server + this.logStep("Restarting the application server"); + HpelSetup.getServerUnderTest().start(); + + this.logStep("Checking the trace spec post app server restart: " + + CommonTasks.getHpelTraceSpec(HpelSetup.getServerUnderTest())); + assertTrue("Failed assertion that HPEL trace specification is set to " + TRACE_SPECIFICATION, TRACE_SPECIFICATION + .equals(CommonTasks.getHpelTraceSpec(HpelSetup.getServerUnderTest()))); + this.logStepCompleted(); + + } + } + + private void setupLogger() { + if (!loggerSetup) { + // setup a new unique identifier for the logger name + Date d = new Date(); + loggerName = loggerName + d.getTime(); + this.logStep("Creating a new logger named: " + loggerName); + this.logStepCompleted(); + loggerSetup = true; + } + } + + /* + * Tests that HPEL accurately reports the number of logs records entered. Assumes that HPEL is enabled on the active + * server + */ + public void testLogRecordCountAccuracyCheck() throws Exception { + // Create the following log entries in the repository + // Levels: All (pass null) + // LoggerName: com.ibm.ws.fat.hpel.tests.VRAccuracy + uniqueLoggerID_Tag + // Log Message: VRAccuracy Message for FAT testing + // Iterations: 49 (just picked a random number) + + setupLogger(); + + this.logStep("Creating the log entries"); + CommonTasks.createLogEntries(HpelSetup.getServerUnderTest(), loggerName, logMessage, null, logCount, CommonTasks.LOGS, -1); + this.logStepCompleted(); + + Thread.sleep(10 * 1000); // sleep for 10 seconds + + // Get the logs from the server to check what is in them + this.logStep("Getting the message logs from the server"); + getLogsFromServer(CommonTasks.LOGS); + this.logStepCompleted(); + + // Go read the repository and see if it has what we are looking for + RepositoryReaderImpl logRepository = new RepositoryReaderImpl(localLogsRepositoryPath); + ServerInstanceLogRecordList CurrentProcessLogList = logRepository.getLogListForCurrentServerInstance(); + // record list is the list of records we will compare against. Assume it's the currentServerInstance list by + // default. + Iterable recordList = CurrentProcessLogList; + + /* + * Note, if we are on z/OS the CurrentProcessLogList represents only the controller's logs. Our test log entries + * will be written by servant though. Will setup a Merged repository to include all the logs from sub-process + * instances. + */ + //The problem is with how test counts records on zOS. HPEL allows server to have a parent process (controller) with a set of child processes (servants). + //For such servers result for a server instance has none empty result from getChildren() call. The test problem is that it assumes that logs recorded by an application on zOS can be found _only_ in children processes. + //On Liberty that is not the case since even on zOS server consists of a single process processing all the requests. + + //The problem can be solved in two ways. 1. Remove 'if zOS' condition since the test is maintained separately on Liberty. + //2. Adjust test to do merge between parent and children logs for all OSs. Following the first solution here. + + //if (HpelSetup.getNodeUnderTest().getMachine().getOperatingSystem().equals(OperatingSystem.ZOS)) { + //this.logStep("Since this is z/OS - using a MergedRepository representing all the servant and adjunct sub-processes"); + //recordList = new MergedRepository(CurrentProcessLogList.getChildren().values()); + //} + + this.logStep("Counting log records by level"); + int severe = 0; + int warning = 0; + int info = 0; + for (RepositoryLogRecord record : recordList) { + // process a record + if (record.getLoggerName().equals(loggerName)) { + switch (record.getLevel().intValue()) { + case 1000: // SEVERE == 1000 + severe++; + break; + case 900: // WARNING == 900 + warning++; + break; + case 800: // INFO == 800 + info++; + break; + } + } + } + this.logStepCompleted(); + + // Verify the results + this.logVerificationPoint("Verifying the repository log (Level.SEVERE) count against the expected count."); + assertTrue("The repository does not contain the number of records it had wrote for Level.SEVERE {counted:wrote} {" + severe + + ":" + logCount + "}", severe == logCount); + this.logVerificationPassed(); + + this.logVerificationPoint("Verifying the repository log (Level.WARNING) count against the expected count."); + assertTrue("The repository does not contain the number of records it had wrote for Level.WARNING {counted:wrote} {" + warning + + ":" + logCount + "}", warning == logCount); + this.logVerificationPassed(); + + this.logVerificationPoint("Verifying the repository log (Level.INFO) count against the expected count."); + assertTrue("The repository does not contain the number of records it had wrote for Level.INFO {counted:wrote} {" + info + ":" + + logCount + "}", info == logCount); + this.logVerificationPassed(); + } + + /* + * Tests that HPEL accurately reports the number of logs records entered. Assumes that HPEL is enabled on the active + * server + */ + public void testTraceRecordCountAccuracyCheck() throws Exception { + // Create the following log entries in the repository + // Levels: All (pass null) + // LoggerName: com.ibm.ws.fat.hpel.tests.VRAccuracy + uniqueLoggerID_Tag + // Log Message: VRAccuracy Message for FAT testing + // Iterations: 476 (just picked a random number) + + setupLogger(); + + this.logStep("Creating the trace entries"); + CommonTasks.createLogEntries(HpelSetup.getServerUnderTest(), loggerName, logMessage, null, logCount, CommonTasks.TRACE, -1); + this.logStepCompleted(); + + Thread.sleep(10 * 1000); // sleep for 10 seconds + + // Get the logs from the server to check what is in them + this.logStep("Getting the trace logs from the server"); + getLogsFromServer(CommonTasks.TRACE); + this.logStepCompleted(); + + // =================================== + + // Go read the repository and see if it has what we are looking for + RepositoryReaderImpl logRepository = new RepositoryReaderImpl(localTraceRepositoryPath); + ServerInstanceLogRecordList CurrentProcessLogList = logRepository.getLogListForCurrentServerInstance(); + // record list is the list of records we will compare against. Assume it's the currentServerInstance list by + // default. + Iterable recordList = CurrentProcessLogList; + + /* + * Note, if we are on z/OS the CurrentProcessLogList represents only the controller's logs. Our test log entries + * will be written by servant though. Will setup a Merged repository to include all the logs from sub-process + * instances. + */ + //The problem is with how test counts records on zOS. HPEL allows server to have a parent process (controller) with a set of child processes (servants). + //For such servers result for a server instance has none empty result from getChildren() call. The test problem is that it assumes that logs recorded by an application on zOS can be found _only_ in children processes. + //On Liberty that is not the case since even on zOS server consists of a single process processing all the requests. + + //The problem can be solved in two ways. 1. Remove 'if zOS' condition since the test is maintained separately on Liberty. + //2. Adjust test to do merge between parent and children logs for all OSs. Following the first solution here. + + //if (HpelSetup.getNodeUnderTest().getMachine().getOperatingSystem().equals(OperatingSystem.ZOS)) { + //this.logStep("Since this is z/OS - using a MergedRepository representing all the servant and adjunct sub-processes"); + //recordList = new MergedRepository(CurrentProcessLogList.getChildren().values()); + //} + + this.logStep("Counting log records by level"); + int fine = 0; + int finer = 0; + int finest = 0; + for (RepositoryLogRecord record : recordList) { + // process a record + if (record.getLoggerName().equals(loggerName)) { + switch (record.getLevel().intValue()) { + case 500: // FINE == 500 + fine++; + break; + case 400: // FINER == 400 + finer++; + break; + case 300: // FINEST == 300 + finest++; + break; + default: + System.out.println("loggerName expected: " + loggerName); + System.out.println("loggerName found: " + record.getLoggerName()); + System.out.println("level: " + record.getLevel()); + System.out.println("level in value: " + record.getLevel().intValue()); + } + } + } + this.logStepCompleted(); + + // Verify the results + this.logVerificationPoint("Verifying the repository trace count (Level.FINE) against the expected count."); + assertTrue("The repository does not contain the number of records it had wrote for Level.FINE {counted:wrote} {" + fine + ":" + + logCount + "}", fine == logCount); + this.logVerificationPassed(); + + this.logVerificationPoint("Verifying the repository trace count (Level.FINER) against the expected count."); + assertTrue("The repository does not contain the number of records it had wrote for Level.FINER {counted:wrote} {" + finer + + ":" + logCount + "}", finer == logCount); + this.logVerificationPassed(); + + this.logVerificationPoint("Verifying the repository trace count (Level.FINEST) against the expected count."); + assertTrue("The repository does not contain the number of records it had wrote for Level.FINEST {counted:wrote} {" + finest + + ":" + logCount + "}", finest == logCount); + this.logVerificationPassed(); + + } + + /* + * This is a utility method to get all of the repository logs as well as the trace logs. + * + * @ param filesToGet This is a switch for which files to get. Options are CommonTasks.LOGS or CommonTasks.TRACE, + */ + private void getLogsFromServer(String filesToGet) throws Exception { + if (filesToGet.equals(CommonTasks.LOGS)) { + // Set up the Simplicity objects to the remote files + RemoteFile remoteLogsDir = new RemoteFile(HpelSetup.getNodeUnderTest().getMachine(), CommonTasks.getBinaryLogDir(HpelSetup + .getServerUnderTest()), "logdata"); + + // Set up the Simplicity object to the local results directory + RemoteFile localLogsResultsDir = new RemoteFile(Machine.getLocalMachine(), Props.getFileProperty(Props.DIR_LOG) + .getCanonicalPath() + + File.separator + VerifyRepositoryAccuracy.class.getSimpleName() + File.separator + "logs"); + + // Save off the path of the repository log files directory + localLogsRepositoryPath = localLogsResultsDir.getAbsolutePath(); + localLogsResultsDir.copyFromSource(remoteLogsDir, true, true); + } else if (filesToGet.equals(CommonTasks.TRACE)) { + RemoteFile remoteTraceDir = new RemoteFile(HpelSetup.getNodeUnderTest().getMachine(), CommonTasks + .getBinaryTraceDir(HpelSetup.getServerUnderTest()), "tracedata"); + RemoteFile localTraceResultsDir = new RemoteFile(Machine.getLocalMachine(), Props.getFileProperty(Props.DIR_LOG) + .getCanonicalPath() + + File.separator + VerifyRepositoryAccuracy.class.getSimpleName() + File.separator + + "trace"); + + // Save off the path of the repository trace files directory + localTraceRepositoryPath = localTraceResultsDir.getAbsolutePath(); + localTraceResultsDir.copyFromSource(remoteTraceDir, true, true); + } + } + + @Override + public void tearDown() throws Exception { + /* + * Not disabling the spec in tearDown because we would only re-enable for the second test Method. By not + * disabling it we avoid the extra bounce. We assume that any future test cases will update the spec if + * required. + */ + + // call the super + super.tearDown(); + } +} diff --git a/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/ras/util/CommonTasks.java b/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/ras/util/CommonTasks.java new file mode 100755 index 00000000000..af0a3ddcd99 --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/fat/src/com/ibm/ws/fat/ras/util/CommonTasks.java @@ -0,0 +1,1036 @@ +//%Z% %I% %W% %G% %U% [%H% %T%] +/* + * Change History: + * + * Reason Version Date User id Description + * ---------------------------------------------------------------------------- + * F017049-28712 8.0 06/29/2010 shighbar Updates for SSFAT test cases and new useful methods in prep for z/OS support. + * F17049-32205 8.0 10/04/2010 shighbar Generalize common methods to support additional ServerTypes. + * 681388 8.0 12/07/2010 shighbar Add method to start server with non-standard mBean timeout. + * 689639.fvt 8.0 02/09/2011 spaungam sensitive filtering needs to be enabled earlier + * 695538 8.0 03/08/2011 shighbar testMergedRepositories failures on z/OS. + * 707366 8.0 06/01/2011 shighbar Hpel Internal Trace failures / test case expansion + * PM41930 8.0 08/23/2011 spaungam FFDC loggers to be asynchronous + * 721541 8.0 10/26/2011 spaungam Ensure exceptions appear with logging + */ +package com.ibm.ws.fat.ras.util; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.MalformedURLException; +import java.util.Properties; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.xml.sax.SAXException; + +import com.ibm.websphere.simplicity.ApplicationServer; +import com.ibm.websphere.simplicity.Cell; +import com.ibm.websphere.simplicity.Machine; +import com.ibm.websphere.simplicity.Node; +import com.ibm.websphere.simplicity.RemoteFile; +import com.ibm.websphere.simplicity.Server; +import com.ibm.websphere.simplicity.ServerType; +import com.ibm.websphere.simplicity.config.ServerConfiguration; +import com.ibm.websphere.simplicity.runtime.ProcessStatus; +import com.ibm.ws.fat.hpel.setup.HpelSetup; +import com.ibm.ws.fat.util.CommonActions; +import com.ibm.ws.fat.util.StopWatch; +import com.meterware.httpunit.PostMethodWebRequest; +import com.meterware.httpunit.WebConversation; +import com.meterware.httpunit.WebRequest; +import com.meterware.httpunit.WebResponse; +import componenttest.topology.impl.LibertyServer; + +/** + * Holding class for driving common logic across multiple test cases/drivers + * + */ +public class CommonTasks { + + public static final String HPEL_APP_CONTEXT_ROOT = "HpelFat"; + public static final String HPEL_APP_GENLOG_JSP = "ivtLogSleep.jsp"; + public static final String HPEL_APP_CREATE_LOG_JSP = "LogCreator.jsp"; + public static final String RAS_ZIPPER_UTIL_JSP = "RasZipper.jsp"; + public static final String LOGS = "Logs"; + public static final String TRACE = "Trace"; + public static final String LOGS_TRACE = "LogsAndTrace"; + + public static enum zOSProcessType { + Control, Adjunct, Servant + } + + private static final int SERVER_START_MBEAN_TIMEOUT = 240; + +// private static final String JYTHON_RAS_RAWTRACE_SWITCH = "RasConfigEnableRawTrace.jy"; + + /** + * Makes use of the ivtLogSleep.jsp in the sample application to drive creation of log records. + * + * @param numCycles + * How many iterations to run (each iteration generates multiple log records, one of each level). Must be + * a positive integer, or else only onecycle will be ran + * + * @param cycleDelay + * The delay you want between each cycle in seconds. Useful for having steady stream of log entries + * created. If not a positive number, zero will be used. + * @throws Exception + * @throws SAXException + * @throws IOException + * @throws MalformedURLException + */ +// @Deprecated +// public static void genLogEntries(int numCycles, int cycleDelay) throws MalformedURLException, IOException, SAXException, Exception { +// if (numCycles <= 0) { +// numCycles = 1; +// } +// if (cycleDelay <= 0) { +// cycleDelay = 0; +// } +// +// String jsp = "/" + HPEL_APP_CONTEXT_ROOT + "/" + HPEL_APP_GENLOG_JSP; +// String jspParams = "?ActionParm=trace&NumberOfIterations=" + Integer.toString(numCycles) + "&CycleDelay=" +// + Integer.toString(cycleDelay); +// +// WebConversation wc = new WebConversation(); +// writeLogMsg(Level.INFO, " Getting URL: " + CommonActions.getUrl(HpelSetup.getServerUnderTest(), jsp + jspParams, false)); +// WebResponse response = wc.getResponse(CommonActions.getUrl(HpelSetup.getServerUnderTest(), jsp + jspParams, false)); +// +// int rc = response.getResponseCode(); +// writeLogMsg(Level.INFO, " Response Code for jsp is: " + Integer.toString(rc)); +// +// } + + /** + * @Deprecated A shortcut to createLogEntries(ApplicationServer appServer, String loggerName, String message, Level + * level, int iterations, String repository, int sleepTime) with no sleep time and assuming executing + * against the default application server for the test bucket. + */ +// @Deprecated +// public static WebResponse createLogEntries(String loggerName, String message, Level level, int iterations, String repository) +// throws MalformedURLException, IOException, SAXException, Exception { +// return createLogEntries(loggerName, message, level, iterations, repository, -1); +// } + + /** + * @Deprecated A shortcut to createLogEntries(ApplicationServer appServer, String loggerName, String message, Level + * level, int iterations, String repository, int sleepTime) without the requirement to pass in + * application server. + */ +// @Deprecated +// public static WebResponse createLogEntries(String loggerName, String message, Level level, int iterations, String repository, +// int sleepTime) throws MalformedURLException, IOException, SAXException, Exception { +// return createLogEntries(HpelSetup.getServerUnderTest(), loggerName, message, level, iterations, repository, sleepTime); +// } + + /** + * Makes use of the LogCreator.jsp in the RAS sample application to drive creation of log records. + * + * @param appServer + * The application server on which the log entries should be created. + * @param loggerName + * The name of the logger the JSP is to use. Default loggerName: Default_HPELTestLogger + * @param message + * The message the logger is to log. Default message: Default HPEL Message + * @param level + * The level of message to be logged. Choices are ALL, SEVERE, WARNING, INFO, FINE, FINER, FINEST Default + * value: ALL + * @param iterations + * How many iterations to run (each iteration generates multiple log records, one of each level). Must be + * a positive integer. Default value: 49 + * @param repository + * The repository to create the messages into. There are 3 choices, CommonTasks.LOGS, CommonTasks.TRACE + * or CommonTasks.LOGS_TRACE Default value: CommonTasks.LOGS + * @param sleepTime + * The time between iterations in milliseconds. + * @param async + * Value of the logger's (if it is a WAS WsLogger) async value to be set to. + * + * @return WebResponse + * + * @throws Exception + * @throws SAXException + * @throws IOException + * @throws MalformedURLException + */ + public static WebResponse createLogEntries(ApplicationServer appServer, String loggerName, String message, Level level, + int iterations, String repository, int sleepTime, boolean async) throws MalformedURLException, IOException, SAXException, Exception { + String jspParams = "?ActionParam="; + String jsp = "/" + HPEL_APP_CONTEXT_ROOT + "/" + HPEL_APP_CREATE_LOG_JSP; + String actionParam = CommonTasks.LOGS; + + // make the generation of both messages and logs the default + if (repository != null) { + actionParam = repository; + } + jspParams += actionParam + "&"; + + // check to see if anything was passed, if nothing was, all of the JSP's defaults can be used + if ((loggerName != null) || (message != null) || (level != null) || (iterations > 0)) { + String s1, s2, s3, s4, s5 = null, s6; + + if (loggerName != null) { + s1 = "LoggerName=" + loggerName; + } else { + s1 = "LoggerName=Default_HPELTestLogger"; + } + if (message != null) { + s2 = "Message=" + message; + } else { + s2 = "Message='Default HPEL Message'"; + } + if (level != null) { + s3 = "Level=" + level.getName(); + } else { + s3 = "Level=ALL"; + } + if (iterations > 0) { + s4 = "Iterations=" + Integer.toString(iterations); + } else { + s4 = "Iterations=49"; + } + + if (sleepTime > -1) + s5 = "Sleep=" + sleepTime; + + s6 = async ? "Async=true" : "Async=false"; + + jspParams += s1 + "&" + s2 + "&" + s3 + "&" + s4 + "&" + s5 + "&" + s6; + } + + WebConversation wc = new WebConversation(); + WebResponse response = wc.getResponse(CommonActions.getUrl(appServer, jsp + jspParams, false)); + + return response; + } + + /** + * Makes use of the LogCreator.jsp in the RAS sample application to drive creation of log records. + * + * @param appServer + * The application server on which the log entries should be created. + * @param loggerName + * The name of the logger the JSP is to use. Default loggerName: Default_HPELTestLogger + * @param message + * The message the logger is to log. Default message: Default HPEL Message + * @param level + * The level of message to be logged. Choices are ALL, SEVERE, WARNING, INFO, FINE, FINER, FINEST Default + * value: ALL + * @param iterations + * How many iterations to run (each iteration generates multiple log records, one of each level). Must be + * a positive integer. Default value: 49 + * @param repository + * The repository to create the messages into. There are 3 choices, CommonTasks.LOGS, CommonTasks.TRACE + * or CommonTasks.LOGS_TRACE Default value: CommonTasks.LOGS + * @param sleepTime + * The time between iterations in milliseconds. + * + * @return WebResponse + * + * @throws Exception + * @throws SAXException + * @throws IOException + * @throws MalformedURLException + */ + public static WebResponse createLogEntries(ApplicationServer appServer, String loggerName, String message, Level level, + int iterations, String repository, int sleepTime) throws MalformedURLException, IOException, SAXException, Exception { + + return createLogEntries(appServer, loggerName, message, level, iterations, repository, sleepTime, false); + } + + /** + * Returns a ConfigObject representing the RAS Logging Service configuration in the model. + * + * @param aServer + * aServer The server you want the RAS Logging Service ConfigObject for + * + * @return ulsConfigObj + */ +// public static ConfigObject getLegacyLoggingService(Server aServer) throws Exception { +// ConfigObject ulsConfigObj = ConfigObject.getConfigObject(aServer, aServer.getConfigId(), "RASLoggingService"); +// return ulsConfigObj; +// } + + /** + * Returns a ConfigObject representing the HPEL configuration in the model. + * + * @param aServer + * aServer The server you want the HPEL ConfigObject for + * + * @return ulsConfigObj + */ +// public static ConfigObject getUnifiedLoggingService(Server aServer) throws Exception { +// ConfigObject ulsConfigObj = ConfigObject.getConfigObject(aServer, aServer.getConfigId(), "HighPerformanceExtensibleLogging"); +// return ulsConfigObj; +// } + + /** + * Returns a ConfigObject representing the child HPEL configuration in the model. + * + * @param aServer + * The server you want the child HPEL ConfigObject for. + * @param childName + * The name of the child configuration object you want to retrieve. + * + * @return ulsConfigObj + */ +// private static ConfigObject getUnifiedLoggingServiceChild(Server aServer, String childName) throws Exception { +// // this fails due to bug in Simplicity. +// // return ConfigObject.getConfigObject(HpelSetup.getServerUnderTest(), +// // getUnifiedLoggingService().getConfigIdentifier(), childName); +// +// List binChild1 = getUnifiedLoggingService(aServer).getChildObjectListByName(childName); +// if (binChild1.iterator().hasNext()) +// return binChild1.iterator().next(); // We should only get one child back. +// else +// return null; +// } + + /** + * Returns a ConfigObject representing the HPEL Binary Log configuration in the model. + * + * @param aServer + * The server you want the HPEL Binary Log ConfigObject for. + * + * @return The ConfigObject for the HPEL Binary Log. + */ +// public static ConfigObject getBinaryLogChild(Server aServer) throws Exception { +// return getUnifiedLoggingServiceChild(aServer, "HPELLog"); +// } + + /** + * Returns a ConfigObject representing the HPEL Binary Trace configuration in the model. + * + * @param aServer + * The server you want the HPEL Binary Trace ConfigObject for. + * + * @return The ConfigObject for the HPEL Binary Trace. + */ +// public static ConfigObject getBinaryTraceChild(Server aServer) throws Exception { +// return getUnifiedLoggingServiceChild(aServer, "HPELTrace"); +// } + + /** + * Returns a ConfigObject representing the HPEL Text Log configuration in the model. + * + * @param aServer + * The server you want the HPEL Text Log ConfigObject for. + * + * @return The ConfigObject for the HPEL Text Log. + */ +// public static ConfigObject getTextLogChild(Server aServer) throws Exception { +// return getUnifiedLoggingServiceChild(aServer, "HPELTextLog"); +// } + +// @Deprecated +// public static boolean isHpelEnabled() throws Exception { +// return isHpelEnabled(HpelSetup.getServerUnderTest()); +// } + + public static boolean isHpelEnabled(Server aServer) throws Exception { + LibertyServer server = aServer.getBackend(); + RemoteFile bootstrapFile = server.getServerBootstrapPropertiesFile(); + if (bootstrapFile == null || !bootstrapFile.exists()) { + return false; + } + Properties bootstrapProps = new Properties(); + bootstrapProps.load(bootstrapFile.openForReading()); + String logProvider = bootstrapProps.getProperty("websphere.log.provider"); + return logProvider != null && logProvider.startsWith("binaryLogging-"); +// if (getUnifiedLoggingService(aServer) == null) { +// // For backward compatibility - we assume if HPEL config object is null then server.xml is not updated and +// // therefore HPEL must not be enabled since the ConfigObject is returning null. +// writeLogMsg(Level.SEVERE, "isHpelEnabled method got null back from UnifiedLoggingService"); +// if (aServer == null) { +// writeLogMsg(Level.SEVERE, "The application server passed to isHpelEnabled is null"); +// } +// return false; +// } +// boolean tempresult = (getUnifiedLoggingService(aServer).getAttributeByName("enable").getValueAsBoolean() && !getLegacyLoggingService( +// aServer).getAttributeByName("enable").getValueAsBoolean()); +// return tempresult; + } + + public static boolean isHpelSensitiveTraceEnabled(Server aServer) throws Exception { + //if in hpel mode, get HighPerformanceExtensibleLogging +// ConfigObject configObj = getUnifiedLoggingService(aServer).getAttributeByName("rawTraceFilterEnabled"); +// +// if (configObj != null) { +// return configObj.getValueAsBoolean(); +// } +// +// writeLogMsg(Level.INFO, "isHpelSensitiveTraceEnabled configObj is null"); + return false; + } + + public static boolean setHpelSensitiveTraceEnabled(Server aServer, boolean enable) throws Exception { + if (enable == isHpelSensitiveTraceEnabled(aServer)) { + // the server is already set to the value we are trying to set. So do nothing. + return false; + } + + throw new UnsupportedOperationException("SensitiveTrace is not supported yet"); +// Workspace tempWorkSpace = HpelSetup.getCellUnderTest().getWorkspace(); +// getUnifiedLoggingService(aServer).getAttributeByName("rawTraceFilterEnabled").setValue(enable); +// tempWorkSpace.saveAndSync(); +// return true; + } + + public static boolean isRasSensitiveTraceEnabled() throws Exception { + throw new UnsupportedOperationException("SensitiveTrace is not supported yet"); +// String[] scriptArgs = null; +// scriptArgs = new String[3]; +// scriptArgs[0] = HpelSetup.getCellUnderTest().getName(); +// scriptArgs[1] = HpelSetup.getNodeUnderTest().getName(); +// scriptArgs[2] = HpelSetup.getServerUnderTest().getName(); + +// String result = RASWsadminScripts.exeJythonScript(JYTHON_RAS_RAWTRACE_SWITCH, scriptArgs); +// writeLogMsg(Level.INFO, "isRasSensitiveTraceEnabled result of wsadmin: " + result); +// +// return "true".equalsIgnoreCase(result); + } + + public static boolean setRasSensitiveTraceEnabled(boolean enable) throws Exception { + if (enable == isRasSensitiveTraceEnabled()) { + // the server is already set to the value we are trying to set. So do nothing. + return false; + } + + throw new UnsupportedOperationException("SensitiveTrace is not supported yet"); +// String[] scriptArgs = null; +// scriptArgs = new String[5]; +// scriptArgs[0] = HpelSetup.getCellUnderTest().getName(); +// scriptArgs[1] = HpelSetup.getNodeUnderTest().getName(); +// scriptArgs[2] = HpelSetup.getServerUnderTest().getName(); +// scriptArgs[3] = "set"; +// scriptArgs[4] = Boolean.toString(enable); +// +// String result = RASWsadminScripts.exeJythonScript(JYTHON_RAS_RAWTRACE_SWITCH, scriptArgs); +// writeLogMsg(Level.INFO, "setRasSensitiveTraceEnabled result of wsadmin: " + result); +// +// return true; + + } + + /** + * Sets if HPEL is enabled or not in the configuration. + * + * @param aServer + * The server you want to enable or disable HPEL on. + * + * @return True if changes were needed / made. False no changes were required, as in the configuration already matched what was requested. + */ + public static boolean setHpelEnabled(Server aServer, boolean enable) throws Exception { + if (enable == isHpelEnabled(aServer)) { + // the server is already set to the value we are trying to set. So do nothing. + return false; + } + LibertyServer server = aServer.getBackend(); + RemoteFile bootstrapFile = server.getServerBootstrapPropertiesFile(); + if (bootstrapFile == null) { + return false; + } + Properties bootstrapProps = new Properties(); + bootstrapProps.setProperty("websphere.log.provider", "binaryLogging-1.0"); + bootstrapProps.store(bootstrapFile.openForWriting(true), null); + return true; +// Workspace tempWorkSpace = HpelSetup.getCellUnderTest().getWorkspace(); +// getUnifiedLoggingService(aServer).getAttributeByName("enable").setValue(enable); +// getLegacyLoggingService(aServer).getAttributeByName("enable").setValue(!enable); +// tempWorkSpace.saveAndSync(); +// return true; + + // TODO Enabling or disabling HPEL requires us to bounce the server - don't know if we should do that here or + // not though? for now that is the caller's responsibility as they may not want it restarted and or have other + // changes they are making before the restart. + } + + /** + * Sets if HPEL is enabled or not in the configuration, and bounces the application server if needed. + * + * @param aServer + * The server you want to enable or disable HPEL on. The server will only be bounced if the configuration does not already match what was requested. + * + * @return True if changes were needed/made, and the server was bounced. False - no changes were required, as in the configuration already matched what was requested. + */ + public static boolean setHpelEnabledAndBounce(Server aServer, boolean enable) throws Exception { + if (setHpelEnabled(aServer, enable)) { + aServer.stop(); + aServer.start(); + return true; + } + return false; + } + + public static boolean isTextLogEnabled(Server aServer) throws Exception { + LibertyServer server = aServer.getBackend(); + BufferedReader config = new BufferedReader(new InputStreamReader(server.getServerConfigurationFile().openForReading())); + String line; + boolean result = false; + boolean inLogging = false; + while ((line = config.readLine()) != null) { + int index = 0; + if (!inLogging) { + int index1 = line.indexOf("= 0) { + inLogging = true; + index = index1; + } + } + if (inLogging) { + if (!result) { + int index2 = line.indexOf("= 0) { + result = true; + index = index2; + } + } + int index2 = line.indexOf("", index); + if (index2 >= 0) { + inLogging = false; + } + } + } + return result; +// return (getTextLogChild(aServer).getAttributeByName("enabled").getValueAsBoolean()); + } + + public static String getHpelTraceSpec(Server aServer) throws Exception { + LibertyServer server = aServer.getBackend(); + String traceSpec = server.getServerConfiguration().getLogging().getTraceSpecification(); + return traceSpec == null ? "" : traceSpec; +// return (getUnifiedLoggingService(aServer).getAttributeByName("startupTraceSpec").getValueAsString()); + } + + /** + * Sets the HPEL trace specification in the application server's configurations. Changes to the trace specification + * with this method will not take effect until after the application server is bounced. + * + * @param aServer + * The server you want the new trace specification applied to. + * @param newTraceSpec + * The new trace specification, such as 'com.ibm.myClass*=all' etc. Passing a null String is equivalent + * to specifying a trace string of '*=info' + * + * @throws Exception + */ + public static void setHpelTraceSpec(Server aServer, String newTraceSpec) throws Exception { + if (null == newTraceSpec) { + // null spec is equivalent to default no trace spec. + newTraceSpec = "*=info"; + } + + // check if we need to update the spec or if it's already set to what we want. + if (getHpelTraceSpec(aServer).equals(newTraceSpec)) { + writeLogMsg(Level.FINE, "HPEL Trace Spec already set to " + newTraceSpec + ". No change needed."); + return; + } else { + LibertyServer server = aServer.getBackend(); + ServerConfiguration config = server.getServerConfiguration(); + config.getLogging().setTraceSpecification(newTraceSpec); + server.updateServerConfiguration(config); +// writeLogMsg(Level.FINE, "Setting the HPEL Trace Spec to " + newTraceSpec); +// Workspace tmpWS = HpelSetup.getCellUnderTest().getWorkspace(); +// getUnifiedLoggingService(aServer).getAttributeByName("startupTraceSpec").setValue(newTraceSpec); +// tmpWS.saveAndSync(); + } + + } + + public static RemoteFile getBinaryLogDir(Server aServer) throws Exception { + String logDir = aServer.getBackend().getServerConfiguration().getLogging().getLogDirectory(); + return logDir == null ? aServer.getBackend().getFileFromLibertyServerRoot("logs") : + new RemoteFile(HpelSetup.getNodeUnderTest().getMachine(), logDir); +// return new RemoteFile(HpelSetup.getNodeUnderTest().getMachine(), aServer.expandString(getBinaryLogChild(aServer) +// .getAttributeByName("dataDirectory").getValueAsString())); + } + + public static RemoteFile getBinaryTraceDir(Server aServer) throws Exception { + String logDir = aServer.getBackend().getServerConfiguration().getLogging().getLogDirectory(); + return logDir == null ? aServer.getBackend().getFileFromLibertyServerRoot("logs") : + new RemoteFile(HpelSetup.getNodeUnderTest().getMachine(), logDir); +// return new RemoteFile(aServer.getNode().getMachine(), aServer.expandString(getBinaryTraceChild(aServer) +// .getAttributeByName("dataDirectory").getValueAsString())); + } + + public static RemoteFile getTextLogDir(Server aServer) throws Exception { + String logDir = aServer.getBackend().getServerConfiguration().getLogging().getLogDirectory(); + return logDir == null ? aServer.getBackend().getFileFromLibertyServerRoot("logs") : + new RemoteFile(HpelSetup.getNodeUnderTest().getMachine(), logDir); +// return new RemoteFile(aServer.getNode().getMachine(), aServer.expandString(getTextLogChild(aServer).getAttributeByName( +// "dataDirectory").getValueAsString())); + } + + /** + * A utility method to get log repository from a remote application server. The entire log repository will be copied + * to the location specified. + * + * @param aServer + * The Application Server from which to retrieve the log repository from. + * + * @param destinationDir + * A RemoteFile handle to the directory where you want the log repository copied to. + * + * @return true if the copy was successful. + */ + public static boolean getLogRepositoryFromServer(Server aServer, RemoteFile destinationDir) throws Exception { + RemoteFile remoteLogsDir = CommonTasks.getBinaryLogDir(aServer); + RemoteFile remoteLogRepository = new RemoteFile(remoteLogsDir.getMachine(), remoteLogsDir, "logdata"); + + return destinationDir.copyFromSource(remoteLogRepository, true, true); + } + + /** + * A utility method to get a compressed log repository from a remote application server. The entire log repository + * will be copied to the location specified. + * + * @param aServer + * The Application Server from which to retrieve the log repository from. + * + * @param destinationZipFile + * A RemoteFile handle to the zip file where you want the zipped log repository copied to to. Note if the + * file already exists it will be overwritten. + * + * @return true if the copy was successful. + */ + public static boolean getZippedLogRepositoryFromServer(Server aServer, RemoteFile destinationZipFile) throws Exception { + return zipAndCopyARepositoryFromServer(aServer, destinationZipFile, CommonTasks.LOGS); + } + + /** + * A utility method to get trace repository from a remote application server. The entire trace repository will be + * copied to the location specified. + * + * @param aServer + * The Application Server from which to retrieve the trace repository from. + * + * @param destinationDir + * A RemoteFile handle to the directory where you want the trace repository copied to. + * + * @return true if the copy was successful. + */ + public static boolean getTraceRepositoryFromServer(Server aServer, RemoteFile destinationDir) throws Exception { + RemoteFile remoteTraceDir = CommonTasks.getBinaryTraceDir(aServer); + RemoteFile remoteTraceRepository = new RemoteFile(remoteTraceDir.getMachine(), remoteTraceDir, "tracedata"); + + return destinationDir.copyFromSource(remoteTraceRepository, true, true); + } + + /** + * A utility method to get a compressed trace repository from a remote application server. The entire trace repository + * will be copied to the location specified. + * + * @param aServer + * The Application Server from which to retrieve the log repository from. + * + * @param destinationZipFile + * A RemoteFile handle to the zip file where you want the zipped log repository copied to to. Note if the + * file already exists it will be overwritten. + * + * @return true if the copy was successful. + */ + public static boolean getZippedTraceRepositoryFromServer(Server aServer, RemoteFile destinationZipFile) throws Exception { + return zipAndCopyARepositoryFromServer(aServer, destinationZipFile, CommonTasks.TRACE); + } + + private static boolean zipAndCopyARepositoryFromServer(Server aServer, RemoteFile destinationZipFile, String repositoryType) throws Exception { + RemoteFile remoteRepositoryDir = null; + String repositorySubDirName = "logdata"; // default is logs + if (repositoryType.equals(CommonTasks.TRACE)) { + remoteRepositoryDir = CommonTasks.getBinaryTraceDir(aServer); + repositorySubDirName = "tracedata"; + } else + remoteRepositoryDir = CommonTasks.getBinaryLogDir(aServer); + + Machine rMachine = remoteRepositoryDir.getMachine(); + RemoteFile remoteRepository = new RemoteFile(rMachine, remoteRepositoryDir, repositorySubDirName); + + String tmpZipFileName = ".tmp_" + Thread.currentThread().getId() + "_" + System.currentTimeMillis() + ".zip"; + RemoteFile rProfileLogsDir = new RemoteFile(rMachine, aServer.getNode().getProfileDir() + rMachine.getOperatingSystem().getFileSeparator() + "logs"); + RemoteFile tmpZipFile = new RemoteFile(rMachine, rProfileLogsDir, tmpZipFileName); + + // 1. Have the files zipped up on the server. + // Build the URL to this test case + String URLsuffix = "/" + HPEL_APP_CONTEXT_ROOT + "/" + RAS_ZIPPER_UTIL_JSP; + String URL = CommonActions.getUrl((ApplicationServer) aServer, URLsuffix, false); + + writeLogMsg(Level.FINE, "Calling RazZipper to compress remote files"); + writeLogMsg(Level.FINE, "URL: " + URL); + writeLogMsg(Level.FINE, "inputFile: " + remoteRepository.getAbsolutePath()); + writeLogMsg(Level.FINE, "outputZipArchive: " + tmpZipFile.getAbsolutePath()); + + WebRequest request = new PostMethodWebRequest(URL); + request.setParameter("inputFile", remoteRepository.getAbsolutePath()); + request.setParameter("outputZipArchive", tmpZipFile.getAbsolutePath()); + // request.setParameter("archiveComment", "" ); + + WebConversation wc = new WebConversation(); + WebResponse response = null; + response = wc.getResponse(request); + if (response == null) + writeLogMsg(Level.WARNING, "The response from RasZipper is null"); + if (response.getResponseCode() != 200) + writeLogMsg(Level.WARNING, "Unxpected response code from RasZipper. Recieved response code of: " + + response.getResponseCode()); + + // 2. Copy the zip file to the destination + boolean returneCode = destinationZipFile.copyFromSource(tmpZipFile, true, true); + if (!tmpZipFile.delete()) // clean up our tmp file. + writeLogMsg(Level.WARNING, "Could not delete tmp zip file " + tmpZipFile.getAbsolutePath()); + return returneCode; + } + + /** + * A utility method to get log and trace repository from a remote application server. The entire repository will be + * copied to the location specified. + * + * @param aServer + * The Application Server from which to retrieve the repository from. + * + * @param destinationDir + * A RemoteFile handle to the directory where you want the repository copied to. + * + * @return true if the copy was successful. + */ + public static boolean getRepositoryFromServer(Server aServer, RemoteFile destinationDir) throws Exception { + RemoteFile rRepLogDataDir = new RemoteFile(aServer.getNode().getMachine(), CommonTasks.getBinaryLogDir(aServer), "logdata"); + RemoteFile rRepTraceDataDir = new RemoteFile(aServer.getNode().getMachine(), CommonTasks.getBinaryTraceDir(aServer), + "tracedata"); + boolean logCopyResult = false; + boolean traceCopyResult = false; + if (rRepLogDataDir.exists()) { + // copy the logdata dir + RemoteFile destLogDataDir = new RemoteFile(destinationDir.getMachine(), destinationDir, "logdata"); + logCopyResult = destLogDataDir.copyFromSource(rRepLogDataDir, true, true); + } + if (rRepTraceDataDir.exists()) { + // copy the logdata dir + RemoteFile destTraceDataDir = new RemoteFile(destinationDir.getMachine(), destinationDir, "tracedata"); + traceCopyResult = destTraceDataDir.copyFromSource(rRepTraceDataDir, true, true); + } + + return (logCopyResult && traceCopyResult); + } + + /** + * A simple method used to log messages to the output.txt log + * + * @param logLevel + * The level you want the message written as. If null will default to INFO + * + * @param msg + * The message to log. + */ + public static void writeLogMsg(Level logLevel, String msg) { + // default to INFO if level is null + if (logLevel == null) + logLevel = Level.INFO; + // determine who called me + StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace(); + StackTraceElement element = stackTraceElements[3]; // get the latest entry after the calls to get stracktrace + Logger bucketLogger = Logger.getLogger(element.getClassName()); + bucketLogger.logp(logLevel, element.getClassName(), element.getMethodName(), msg); + } + + /** + * A simple method used to log messages to the output.txt log + * + * @param logLevel + * The level you want the message written as. If null will default to INFO + * + * @param msg + * The message to log. + * @param thrown + * Throwable to be logged + */ + public static void writeLogMsg(Level logLevel, String msg, Throwable thrown) { + // default to INFO if level is null + if (logLevel == null) + logLevel = Level.INFO; + // determine who called me + StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace(); + StackTraceElement element = stackTraceElements[3]; // get the latest entry after the calls to get stracktrace + Logger bucketLogger = Logger.getLogger(element.getClassName()); + bucketLogger.logp(logLevel, element.getClassName(), element.getMethodName(), msg, thrown); + } + + /** + * Stops and removes all Application Servers, Web Servers, and Proxy Servers in the specified cell, except for those + * specified in the excludes set + * + * @param cell + * The cell where you want to remove servers. + * @param excludedServers + * The Set of servers you want to keep. + * @throws Exception + * Thrown if any server can't be removed + */ + public static void removeUnusedServers(Cell cell, Set excludedServers) throws Exception { + if (cell == null) { + return; + } + try { + Set allServers = cell.getServers(); + for (Server server : allServers) { + ServerType type = server.getServerType(); + if (ServerType.PROXY_SERVER.equals(type) || ServerType.WEB_SERVER.equals(type) + || ServerType.APPLICATION_SERVER.equals(type)) { + if (!excludedServers.contains(server)) { + writeLogMsg(Level.INFO, "Removing the server " + server.getName()); + remove(server); + } + } + } + } catch (Exception e) { + throw new Exception("Unable to remove unused Servers in the Cell named " + cell.getName(), e); + } + } + + /** + * Removes a Server from the WebSphere configuration (and Simplicity object model) using Simplicity. If the server + * is currently running, it will be stopped before it's removed. + * + * @param server + * The Server you wish to remove. + * @throws Exception + * If Simplicity fails to remove the server. + */ + public static void remove(Server server) throws Exception { + if (server == null) { + return; // nothing to do + } + Level logAtlevel = Level.INFO; + writeLogMsg(logAtlevel, "Removing a Server..."); + ProcessStatus status = server.getServerStatus(); + String serverName = server.getName(); + + writeLogMsg(logAtlevel, " Type: " + server.getServerType().toString()); + writeLogMsg(logAtlevel, " Name: " + serverName); + Node node = server.getNode(); + if (node == null) { + writeLogMsg(logAtlevel, " Node: null"); + } else { + writeLogMsg(logAtlevel, " Node: " + node.getName()); + Cell cell = node.getCell(); + if (cell == null) { + writeLogMsg(logAtlevel, " Cell: null"); + } else { + writeLogMsg(logAtlevel, " Cell: " + cell.getName()); + } + } + writeLogMsg(logAtlevel, " Status: " + server.getName()); + + StopWatch timer = new StopWatch(); + timer.start(); + if (ProcessStatus.RUNNING.equals(status)) { + writeLogMsg(logAtlevel, "Since the server is currently running, it will be stopped and then removed."); + server.stop(); + } + server.getNode().deleteServer(serverName); + timer.stop(); + + writeLogMsg(logAtlevel, "The Server was removed after: " + timer.getTimeElapsedAsString()); + + } + + /** + * Starts a server and explicitly sets the timeout value for the mBean start operation. On slower systems, + * especially z/OS where the server startup takes longer use of this start method may be needed. Using this method + * uses a higher timeout value when starting the application server. + * + * @param serverToStart + * The Server you wish to start. + * @throws Exception + * If Simplicity fails to start the server. + */ + public static void startServer(Server serverToStart) throws Exception { + serverToStart.start(SERVER_START_MBEAN_TIMEOUT); + } + + /** + * To add new properties to bootstrap file + * + * @param appServer + * @param propertyName + * @param propertyValue + * @throws Exception + */ + public static void addBootstrapProperty(Server appServer, String propertyName, String propertyValue) throws Exception { + + LibertyServer server = appServer.getBackend(); + RemoteFile bootstrapFile = server.getServerBootstrapPropertiesFile(); + Properties bootstrapProps = new Properties(); + bootstrapProps.setProperty(propertyName, propertyValue); + bootstrapProps.store(bootstrapFile.openForWriting(true), null); + + } + + /** + * Returns a ConfigObject representing the JVMEntries for an Application Server. The JVMEntries is a child object of + * processDefinition. It's useful for getting at the systemProperties / customProperties configured for an + * application server. + * + * @param appServ + * The Server you want the JVMEntries ConfigObject for. + * @param procType + * Optional. Specifies which zOSProcessType type for this server you want to get the JVMEntries for. If + * the value is null, then Servant is used as a default. This parameter is ignored on non z/OS platforms. + * + * @throws Exception + */ +// public static ConfigObject getJVMEntries(Server appServ, zOSProcessType procType) throws Exception { +// if (procType == null) +// procType = zOSProcessType.Servant; +// +// ConfigObject jvmProcessDefCfgObj = null; +// if (appServ.getNode().getMachine().getOperatingSystem().equals(OperatingSystem.ZOS)) { +// // We are on z/OS. Need to get the process def for the procType. +// CommonTasks.writeLogMsg(Level.INFO, "z/OS detected. Getting the Process Definition ConfigObject for " + procType.toString()); +// List jvmProcessDefCfgObjList = ConfigObject.getConfigObjectList(appServ, appServ.getConfigId(), +// "JavaProcessDef"); +// for (ConfigObject cfgObj : jvmProcessDefCfgObjList) { +// if (cfgObj.getAttributeByName("processType").getValueAsString().equals(procType.toString())) { +// // We have the zOSProcessType process def. +// CommonTasks.writeLogMsg(Level.INFO, "Found the " + procType + " Process Definition."); +// jvmProcessDefCfgObj = cfgObj; +// break; // no need to complete the for loop +// } else { +// CommonTasks.writeLogMsg(Level.INFO, "Found the Process Definition for " +// + cfgObj.getAttributeByName("processType").getValueAsString()); +// } +// } +// } else { +// // distributed systems have only one JavaProcessDef configObject +// CommonTasks.writeLogMsg(Level.INFO, "Getting the Process Definition ConfigObject"); +// jvmProcessDefCfgObj = ConfigObject.getConfigObject(appServ, appServ.getConfigId(), "JavaProcessDef"); +// } +// if (jvmProcessDefCfgObj == null) +// CommonTasks.writeLogMsg(Level.WARNING, "Warning Process Definition ConfigObject is null."); +// ConfigObject jvmEntriesCfgObj = ConfigObject.getConfigObject(appServ, jvmProcessDefCfgObj.getConfigIdentifier(), +// "JavaVirtualMachine"); +// return jvmEntriesCfgObj; +// } + + /** + * Sets JVM system property / custom JVM property. + * + * @param theServer + * The application server on which to set the JVM system property. + * @param zProcType + * The zOSProcessType to use if on z/OS platform. Determine which process type updated on z/OS. + * @param propertyName + * The property name. + * @param propertyValue + * The value to set the property to. If the value passed in is null, and a property already exists in the + * config, the property will be removed from the config. + * @param requiredProp + * A boolean representing if the property is required or not. + * @return boolean Boolean value of true if changes to the configuration were required, false if no changes were + * needed. + * */ +// public static boolean setCustomJVMPropertyInConfig(ApplicationServer theServer, CommonTasks.zOSProcessType zProcType, +// String propertyName, String propertyValue, boolean requiredProp) throws Exception { +// CommonTasks.writeLogMsg(Level.INFO, "Setting custom property " + propertyName + " with a value of " + propertyValue); +// Workspace tmpWS = theServer.getNode().getCell().getWorkspace(); +// ConfigObject jvmEntriesCfgObj = CommonTasks.getJVMEntries(theServer, zProcType); +// if (null == jvmEntriesCfgObj) +// throw new Exception("Could not obtain Process JVMEntries"); +// +// // Check if and entry for propertyName already exists +// ConfigObject aProperty = null; +// List jvmCustomProps = jvmEntriesCfgObj.getChildObjects(); +// if (null == jvmCustomProps) +// throw new Exception("Could not obtain JVM Properties"); +// +// for (ConfigObject i : jvmCustomProps) { +// // check if we have an existing matching property. +// if ((i.getName().equals("systemProperties")) +// && i.getAttributeByName("name").getValueAsString().equalsIgnoreCase(propertyName)) { +// CommonTasks.writeLogMsg(Level.INFO, "Found system Propery " + propertyName + " in config with a value of " +// + i.getAttributeByName("value").getValueAsString()); +// aProperty = i; +// break; +// } +// } +// +// if (aProperty != null) { +// // The property already exists in the configuration. +// if (null == propertyValue) { // remove the property since the value passed in was null. +// CommonTasks.writeLogMsg(Level.FINE, "Removing the systemPropery " + propertyName + " since set value is null."); +// jvmCustomProps.remove(aProperty); +// } else { +// if ((propertyValue.equals(aProperty.getAttributeByName("value").getValueAsString())) +// && (requiredProp == aProperty.getAttributeByName("required").getValueAsBoolean())) { +// // The property is already set to what we want. Do nothing. +// CommonTasks.writeLogMsg(Level.INFO, "The property " + propertyName + " already set to " + propertyValue +// + ". No changes were made."); +// return false; // return that no changes were needed. +// } else { +// // The property is not set to what we want. Change the value. +// aProperty.getAttributeByName("value").setValue(propertyValue); +// aProperty.getAttributeByName("required").setValue(requiredProp); +// CommonTasks.writeLogMsg(Level.INFO, "Updated JVM custom property " + propertyName + " with a value of " +// + propertyValue); +// } +// } +// } else { +// if (null != propertyValue) { // don't create if propertyValue was null +// // The property does not already exist. +// CommonTasks.writeLogMsg(Level.FINE, "The property " + propertyName + " does not exists."); +// +// // we need to create the property and set it's value. +// CommonTasks.writeLogMsg(Level.INFO, "Creating the new JVM custom / System property " + propertyName); +// ConfigObject newJvmProperty = ConfigObject.createConfigObject(theServer, "Property", jvmEntriesCfgObj); +// CommonTasks.writeLogMsg(Level.FINE, "Setting attributes / name and value for new JVM custom property"); +// newJvmProperty.getAttributeByName("name").setValue(propertyName); +// newJvmProperty.getAttributeByName("value").setValue(propertyValue); +// newJvmProperty.getAttributeByName("required").setValue("false"); +// } +// } +// +// // if we have not already returned false, then we changed something and need to save & sync before we return +// // true that we have changed the configuration. +// CommonTasks.writeLogMsg(Level.FINE, "Calling saveAndSync() on the workspace to persist changes."); +// tmpWS.saveAndSync(); +// return true; +// } + + /** + * Gets the value as a String of a JVM system property / custom JVM property. If the property does not exist a value + * of null is returned. + * + * @param theServer + * The application server on which to set the JVM system property. + * @param zProcType + * The zOSProcessType to use if on z/OS platform. Determine which process type updated on z/OS. + * @param propertyName + * The property name. + * @return propertyValue The value to set the property to. Returns null if property is not found. + * */ +// public String getCustomJVMPropertyInConfig(ApplicationServer theServer, CommonTasks.zOSProcessType zProcType, String propertyName) +// throws Exception { +// CommonTasks.writeLogMsg(Level.INFO, "Getting custom property " + propertyName); +// ConfigObject jvmEntriesCfgObj = CommonTasks.getJVMEntries(theServer, zProcType); +// if (null == jvmEntriesCfgObj) +// throw new Exception("Could not obtain Process JVMEntries"); +// +// // Check if and entry for propertyName already exists +// List jvmCustomProps = jvmEntriesCfgObj.getChildObjects(); +// if (null == jvmCustomProps) +// throw new Exception("Could not obtain JVM Properties"); // there may not be any child props but there should +// // be child objects still. +// +// for (ConfigObject i : jvmCustomProps) { +// // check if we have an existing property. +// if ((i.getName().equals("systemProperties")) +// && i.getAttributeByName("name").getValueAsString().equalsIgnoreCase(propertyName)) { +// CommonTasks.writeLogMsg(Level.INFO, "Found system Propery " + propertyName + " in config with a value of " +// + i.getAttributeByName("value").getValueAsString()); +// return i.getAttributeByName("value").getValueAsString(); +// } +// } +// return null; +// } +} diff --git a/dev/com.ibm.ws.logging.hpel_fat/lib/fat.harness.jar b/dev/com.ibm.ws.logging.hpel_fat/lib/fat.harness.jar new file mode 100755 index 0000000000000000000000000000000000000000..7656962e7570ce1147634f68baecde6853577df1 GIT binary patch literal 80237 zcmaI7Q*tkes&B5=;_mgQ_}fjcrz61f^__^V}% zp2HkPL8!VW%c!)NU;VUDxaE#}T&hnN2rO`!P;Ka)iLIV9Up*sdF{zw3bv#Y$b2l*? znvV!V*W5inp;ti`?M|JAW~boAc@S;J=F6ipA*nKw4D68Xy_enY%R#DJ8sbXNQJXGs zlsLJy9&t7zYn_Fpf{(nP+D_0B{{t5rJNX-goiC=zO|gAmY`XH;REVzRgw z%R&R=mFyU;icrkipmxMmhvg_ZLWxA9OgX=jtMIuS%gbXhFk`0w*Qs<%3h+{oPHUwA4TTRDDaE>BHu1d3A z^ahZ;m*rFW75q99hd-RG?)>bm0M=~<-6P-Zqb5ngyJ<4V;t77 z{*M83)Zz%pVKnos`jv9#&l^^v3E*!7>w!C=_yBrZPrl7xh!|jPvRk14lG^dN$eozm z6%SnY{Kayae;KB{qCJ{L*8eh0^#pm(8V;WSOW6x5KyfF3W)wLzPmUHZvYX_I;H`H6 zYpH%9eMTEuUg#j}3;kX<%s&4@(Tn``>p=Sq5P4dNO<@o+DqQ8;p(Gxg<`n-YtfKMV z>*7_$wz+(tozuUlEPlm)VNw&`qexWGi*shu@c&}%|6mT;H6BMPHVDW#8wd!^{|j^6 zTwEROth~)k)y!O6Ro$#y&He|6YPDfK_0%y1PiH9}*u1QgCl--PSxOn@vpKBbFnIMz zmR$7sZ55I{bbss_ky$Hgw$l#Fa=v?^3QT;H8H`SCcL!-s z-nz!lIl7S7CuLG$*Sja-XxGtXC~O;5nevS;#K!A6yTPBE`-n`pvDp^2d5~zWE|qZ&f-;6?AfN z>1|z?c^h0D5XJg%BH8!`j&^axS#Fg(^^GdWLUZ&g9cGL=#iHX;a}q6kwvGC55G}rv z#WK4;_&AE7bc!9ya_&^$nc4d@8`j-n+V>{ymfw9G`=m*~en*TFyFIjgvTAqNWeCmwm3@E}ek~d0Zm$d!q6Fc#_Dx0*ygtZ2{=kiOpgozp zcf-TB@vSC!=ixqv;QUwkj~;Wd!HKd#SRcZ?BeW|?0o6;>>K@0 z#)^maomL4qe?7H&k=wn*fE?q{`kw_?uHz$u*g{8TQ(l$X#3w^|LPdAQcmeW<^<7rX zyUa7WctTXW4wj$oSMT!NLZG~7ep4g6Se1Tb^2CSKoZofXePfDNpMJ6VtFO>_KT4(# zF{46gpTu2n)Ss%c0aU^HvJW-U`Ae_Z_MP$>pQXO}>F7T)hlW#o+;~44y?slskZ-+b zC+SBJK5s8f-@(!JoZrRS|4_MZ_JyoIo3eixE?;ix@qR{T0*>9pGrZKx4Cx1N-7Ur0JVTACJXCE= zNE(`JokZD_%b$Ywem4lBUENe7QyA}m=b6cc*5d!Iv)h?=jcLh}3n70>v{Xb+yVSko zGzM$o-y&A1F?Cj(+nqeJjdI78Q`H^%lF)6cUy5jf<|7ZYMMZ=p*9~rLh`E-wDB>ot z$XddSdR__V`?&BJyX*>%d@nQQN4 zVQ!5u_PPq2XTNMt>QSOABMLo3D-}VqGX_U>`wS7vJJ_jsimYkks?B0gxLgDY6G@_9 zgk*~w1vY#zlGKp}B^v3^{yjrv4g9DNHw5&b;k{Zm*`ygCki_P-p;XAU zc+-~e8#i$Hn$g613N0y&L(p_%wFowWj~`<}eP5kBP;72UW95^u)1MtXElR=FTG`{qBVe>)+_nfw zaZqqdzn?RVAP|F42U6cxX})_IzZ%_T`WfTzlSfR|4i7c^XT}v zl0?lZ#VHf>eZL*!Fs)f>vO!>d;f8bb9)kBsOjpF06L#!`RXd!=QwKQ~*4f1d%CF{F z0zh9(vjSZ4K*_lx&Y+YQ1kNau<{u^`C8H=m(Dwz4iLyguJo$ecXTDN#mUSertC@C~ zB>mBG;K)0Z%n0#(4=Oa!qG*VZ>mCRKZ{;(86h|MuC>Y*eWZ0iVSdAt_TdgshNuw)K zLW>_olSm(d7@hTJr=J#lZ?yvfn*pE`%s{z>#YmZoWXXeoIW~?Y6a?jp2-^v#(IhDF zznInT`g&jIlR5c;1l*-G`K42!@ z`717Ca0m3=5`Wi>Int)raj2Kjx6y?yk2aZL!+bBdW;{arnHTOyyML@YfW`|}QXcgF z(*n+=pK9ee9+Xqy1qKDY{_m z3`Q}{mG&mV*}%L4T~|>rqmQRc4;q)ENSvlu{d2+tu3b1u0XhlQS%ndUP(r)LVVXLh zBQYl;;m*201=ro%*~y!0P?GNI9cvI?@vzL(nWf-B>Th?R-Z`2c@!lB&VU509AkUmr z$SwQ0ZY84xpociiY9{2L^fa=Q1KW0dTu_F{2orSg3T8VoHYolPHm1(3*G|Hs-}Sd4olk5c8Fq6V3b%v|?s7}u^9;UKH)`@kWmW7D zGTaJd{K`Ihyk320ZDCh{2KqQ|$5-^zow(JYaT7&dGM^|P*(8v1rh zF4P;MbWr*&m9cX0l8{cSm9eNHe-+44ksw9dTR8^yf=*%wOS#T37(y>y065abn>D|V z)|!1+7I1gr4w=Oc~A`);E z(`n9tKP_96N@>b<-TjN!>!V6WtdH=vTKRKwgMz3L3^!=slg*mbn_&#%rdCxgrl)e5 z&y|AdB3vR#xm= zBsE2^0&8_hV%v?M5i=zIsDXoyC`~_-*+~oh6Fmv{rlhZoR?@AEUU6Sj_)bDJD%F8_ zB0|N0At4wp@)^A40;i%ka)q(t!n#hEJKH2wcsxK!uaF(N;YAEdXHvZ%Fd$!}^at@~ zxkab)e{rhp>Fkv2;a2a7?Rg(~)Y(|=7cP%~kqgZoayr*hWRmO>7Xia8&e$;RdBb?Y zf&H*Drg2HnZLoAV1~0juLEqkr_m`h*#{Jh7IuDjavMfMr&o-y4LzYEHL|66Dq#vWA z;yNF)k!WQ=^!}zz*LcUZcH@}(#si*XKLl9=$HmDJy8(J$sq=^m;g>A(s3^MjM|;)@f3$8)qJ_&6N8<6Lzq|v>j)? z>1DVCZ1^e**Ge0*Th-0CxMFAxxo*MrK|4`>cJ~6ZKzAS|twt0}9yu8krJg`~1ll=Oj@v+C7`jV2-gwH_|BhU2 zC6>3sQ{T}hANTK|rL7JJ9vb5fahji%T;)yJ5>b)ZPP62e?v;Z-CU^_koN=4_XY)vUJXH{8bZ&hXgi zwwYJ^_qN>B+4oJ#1I}AG>99(J)qp030t!xG^+=d>S7|O{y4mg*Rq*e(U++&{6ao$W zE#_oU&i*WFu?~V88?eI0ZZ*288w^rklKw%kaj9S_9 zpA!u9v)h0zEx_8;5*lpuDJ#bKs$5e68zCyq^@y3oy<=T%Fp%GFGtoLQHJFNG6u@0z>-2ug4s1i@FY`u{1 zL?k;7WS=;8g#c|yA>nFWkVn<`%*byS?^O|V>^+PV!Bb@mB9bvsXC&2uSko6|rG2n? zn-HK8-Q+X@na3Eo+SNjMCy zYtbp^Gqb?TnTKnBx`r2@be?%~)}Cd=`@QqHkfsE?aeP#O$&sodqEfEPo-4d*iD_59 zvK+YpQd>x>BdfW<+nJ_whNa^WRRqUD;7TuGAp=atJI8*Mg(;TWIk77QZi;lQ9!_Bm zGd%E91C90AMVeof#j87b|LO^#^3P5M)y<}k`J#Ib(3E5;OSMoXxrAWFfz_b*f9-7v zvrkC6R0MJ@Vfl8Q8+T$DhSO$p(MfIwE+E~{19+}G{sMIE z5H{fOwlT^m^g(p|3RIb;?~8EHN%E}-91K}Le3$e`(~=b zj>pjmWS(0d7B16m4RIlRt-&RXU4yqBIdI`BGEyf>>z6&SOS)LV6<0t0N3s8`uAJ`- zsxw?r9Qs_sJI21~W}#f3v_6EVF1+6#c^`BBSm})TEFNX`gXC6dVXELAlsE1>CJ&t> zzd*A90qi*T5xd_>XKQr>9_MStHC>bR`R|#V>{S(pp8UXPbwdrL<74)CN8br7N1i-B z(t7-g>+Zim+lh=pT0~X?vLf@wDnH%!b+qba~J?J*A z6Q!j?313=@TAF7x@~(nx&qyj|ba>?hR#h5!KdW^QBqXwG#nAqW5zmSD?~u+taiXDm zLv65Qf!-S_%K#nb(*+KohX|5knejW^;Mg|Hj?X^V$GIo(uZJ^1h{Srb-&@Fkal&Nz zLDG3(7zL#?mq&Uv;cC3#ge}t;|D8m)SLhPN2ca(;Go!PShi( zrS|Kmp6ATK=M{jtX`XjYVH1?tmm#*areUv^rEIm%tKAV}N3rD^WJsMR1x*Iw=9dpn z1|5II@e3T*0ne}x6K*|O-Z;j8P{6#x%uR;8wDkWh17Rl4)k?}Rr4%ek=(zU_X#Z+K zP<|~93t)OWFN5vP9*Il?8r+j;SpdfDU0UqPTh8uaOow=@I?9urYq6r(&Gv+yw{E}t zIdb~Ooe>oktL-c}X%){xwd0g_C?Hf<8}N&I9_S0aK0&;TA+XS@ z6Y`h15i3&9=8GiKPzxvlPUo z)6wno2d-i4u=BW2ln>ho<~Z3yS+3#SLlNKguy&h_-Xy3E57W?`3wxYHfmYTXdgv*f z;? zj%$XTc(t3;i&hu?YOb~@qI^0$-Drd^PlSa-c`#7RxZ zwfV6~Xqg*w31nzAIL`&9YtazTxFvOb3Ba(#IwDbs zZ-Fm()W=;tNe5^0o)P>63FAj3L(!Z28P^bG@?-wlY37E5^z}lS^~y4*z^s{2Yx1sT z5}OMwCYAU`-JbE0i@6%UsE*;rgmNCPd$qApy^B|#bO4f5$02Qof1)Th>{Fy#4N!csKtD3*P$U!yNA0yV+p9bKj61CqV@Vp8O-g?5Ss6rqB*m zJ$PlFtS4M*W#1C_jGppEjx_g!8dIsvDPEKdu203}9hAWAv7Rty+^O=ycOZS`^c~+3 z8SManTzW!o2?YJ=*h;ou=$7gvAesY6X7w5t9^28!z(R^e}#9YaV;lA;*S}scMO7oaP13Dlygve zq}vxY`vCJI$+9NdVA|R8>7YMW@y*ev_mSh4KDnp&{LQw&uo^%h zH*{u0n9cR3BBFD(=|puR6fs~$o1RhRy_lt|URwF|?VUxSb*6eni+GOv2p$vDAOKx{ z;MEEDrg*6et~%%Mt_XW~7DL=Tx7{ms&C_`Xw3zv~?y5(jz-Q|dVcCr-lYe!>MWkY> zh+wR%flTU^Bx*y<$*ptM@qhSPU$XRupaXwsd#Vmh)>IA2rX9FEGqx|JU+aXZW4EcU z_99IYGq0b;D0sYJEuY>YYi_53&;Vx+D{$=$Q5309pcB3`6@+Zb8kKcsI=I&~P*6l# z^0+A$;n{`pyAgDbIBoQTXp{CurPu;N%(2!WE3Y(g303FbF7uwf{f7SErT*7vhIVpj z5Ri%gjMJ$9yVNi4>1bx}V&!i3UrN83tDEEhQ2JvvbRF?EalcoUYg&r9Ds$InO4X?3 z57#2qWu#>YL$@S%=nZFfajq*vKx!@^eKD*esrIRr~f`4}QT zEaIhx+8V}=GRzh@c6K#MbYJ>x4gI0J<-3K#2~&PffWNgfLmmMkar8(so_!?deVonF zHtY}`Eg>ypuKMBfo>rB8wTa$PT9*A|ilJK=sG3^i;oVv==QhP*@wcsheiU+?JW^~P z(cMS>p#oB-*OEYuk&U8p>#&jQ2A8vS@9+HhvXn!ltIT7;yw;g4#8cyrQ-A}2C)Ax z-9T^1Te9O&9P!edBB4Q*X5EUjX3LgTw6ydjWn?YADyRaYpVMV>)zQL)C(mt>5knE* zo|iri*9;e%!;)G$@Kr`qRyyGQ1~OpIhhQfy5PL5y$YLi zz*Q6XS;k(tdgKMpgQiHLg0Q=Z6h*iZPAC+4pcU^>pZK1@HvU3*fh z5(hO+tZW8yU1PZJgmQ6rmv~h1Rsx51z!QDiUGwn8yTnunx3Isicq=YhJu?Ei1Ib*j zYf=yg_K>lgaFoxJJ0|}?A8nn!I-?$Aq`ju6xiv`jNgFHxtekU8h{6^fzNKK1vQTH3 zQOrDJH6mNR#Vn+^$g|y)j=FaE$Kursr4QyX{WUd=kTyVxNS<8IdqJh{0_pJbRRX0i zji3*ERMa3Q>HENX6R^~t8>P79{%ST7GURU-LQEQ1OSh&Cx~U5;TmRcobUXJzlSBg7 zAC^AMTVdYg@4SBBF4}qk`i<3@K?^tJoj;Cd2t?n2L&pSEIINi>W=|`NQuI85DbKxB7!uD^{cj0t~#T zDULW*^tFfK9Gbg)(d6k^*y02gl^?4;uDGNbRBlsX*o?r8{oG54dD^p&#IDTt%+95ym0@~&RR8UmR=^3bj^r~VnJ4D^ zjyO<%lnPg0yrSN3h-|PYx;^wl*XE+D>LR`|aW;FyL062Ak@r<+*u0Y=xV1E9wS!GZ zlN?XqUI?WEaAobfCNnkLk7!%%HE#QX26|Ocmp5c(d;9IiFx*&-9&qgJk1--hCN+YGo(U;I>qYNv=>>tP1$ zl>mBwTdZsS8Oul>(+-ZN7)LJ|O{O?jr8r)ieqyJXZLZmKp*Vh^IF6<`mZdnJqBy2Z zy2teHkx}WDQ0a}cX^#=QXM3hqT%{wpRI@HEFTR@xJ* z=bc}nsjWzQ z;QjYHtK{t9_&<#(wOX*g1jlXxifJvyD_Ti^lNgBCqU~(8CFuJz{*Z>G0+UvCuA{b7 zV>*VV@T5&{{xR@13zERf&y`3QdVrJ4gUJ^#$|E2(1)*;^$#V3z6{v?vi*gm0)7Ql z%oD>-64O6YgZ)&B1eDF^L!UFBAqxLYfqbbad}n=ANnM^f1gDhr!Ov%leBNO4R?iE; z6b7iB@fn}zgFVi{eaWIY|5VNQK~`pe>;L&tI?ECH!7ccKQ^_#UJnK4m>BD>{9=PuV z>n@$&gi9W*aSR@`!LV2JtR0kxgT~Onu-D+JaExYo2pgpHJ#YirqC@CLEfKa4*4(O_ zcY&+d1s`uHalv9TgDXWQe=wtlw@~?)xHsKJhU(& z=Du+#I0&?#XV7ZZXebBjX2;i-7m|Bf)DrpEX; zaye|t0lwqs=tq;6Mdu=hW0naPlp&2w=S!;^4P90&O>=FcLLZ{Vk*mx@ zri=tg`No@6Q`?`)(D9o@ZBJ2qb&kAjAoqY&Z7x8N8%4kM5?b;mR^Ypf3%rz3OqX@{ z<53cI>1nT$(0gS~8I0Qro>!lUeEl=1`8T2I5N45+6HfmH$vbeM!&`Y^^HKf~Hnjff znGB{_Tew5P7(fvE=tCJ~a_}C-yFd8hIC`-B+tHCB&Fx-hA3viL+L0{NmY0_mRWVL( zYJD*?GG3A5Ao%Vo5zqVOHywb0I8#ot`A)6LoR-4bxis%t%$g;uLS27?o4T@$x+vIW z0hI^C?4p7J@b8@-yeUBnc(F*b6c)7|=*qy$l^anuGKd0PVTu_GJ4il+8)HJ5h>=8x zxnvPb5?xZgb9F}(j4xwL)rx(^pNNrIVm-Aa{0ibAP#oS{6~kbaF2y8z(xfU{SN5X( zS5I*;ftM*tvpSS{Ht)%QUSZ!kOM}Cu;3Pk{LyNIp00?KZmBoP+(4L(;E3M&5UJ{?4 z(Prc>O+^S4FfQ(~)GFGunDOmnO}-H_dYZFoRedVj!wUCR17z`39F5iQeU;~}{ zIb1q5D%jcrY20;6ue7!sjGo~QaQ>qJ8@?=~Ru)58Y+KhlwpPbk>N!UF!fCtl*HJq) zlLvaXY16kgyQuHdbvZdZ?x0MpbUNoxx-|oswS#e+^|DsN2}cW(?NJA67f;XO=?KfR z!T8IZgT}yf)Bq#sC^t?cFI61UEX{mKzbyfWOzo&dapptd$Ll7Ygmq=+JZO;>zT}7R zd?^64b#FnvM=o?G-FLk;t|7p3Xl?kl__o)KI!{RZ+PH8!0j&(|Zf_FCUX0A#d@~&( zshE9n_k(AlRx2ul{uDG%^*x26QMRwvaW)S3Ss1TdG1=##+$J@AkwR#?gjs#(QU2Nn zBTXZE8do|u9KeK1g}?N^))&7@)E(5~+}oDXn$nNSXu9GNtS921GJohK6HI`;=DC?S zq@Tt7^y!R<=Qz!IbE|exZt(tOT1hZ54SolpXBbFnm(@DwPp9{_gstI~b@S`r3~nim zx7-5586=-d(4R@XgMM~?N{%xPfTp4(F#~i63l&ybG!_&%9Vot&zbw1*yy2 z(Mz&&uc5`^(O4`~NPu9HcDaQPtBH^YHz#U6TX=)^C@p(Ccm9yYBUa8AKJ#{KCZ&^- z1C{zSLWqUfg%;?C~p;=UL>8`yc zGa^2-*kjuw(`+5l`x)iR<9xMke6r((0xu8~-3i`0y2DheayO?7RQo3U+R+RLnY zxK`ip7vnD*=5Z8}$}_lDKDf{c+Bv&4KWv9ath5eRa*tb|YpRBE^L~jOEmgbpWH%On zlaQ$=`An@Q5lAQlD8cCo1>C6XJA+qK4%@;QZvNes!=4Me@qoQD$ry`S=)C$nC={7u z%bviZT8){**Fort2H-DgB1PIWI~n&jm%Bq$^$k(!NqK|%T={6KR(aeQT*hTD;7(1a z+WCP2B2Xu|=ojo4Z^Sl=?(6(L9!z`Kl@kWAPOyRXqei~rB&!M@iZg$SRm~_3F0t}U z*#A|(2tm9mbiDc8O-9q}ojaLtj1pNW*-4^6wFGIiINEh8TUNs%M#aIj4IF7WuWkC*D9c+kkWz(W4MD4A8Pe;318NJQ#VM`zj^gRgXxAFwu9&i1DSPDT zRQn4L(h||%LS(?qI*|2=pq6j3ORUzS(k^m?xG)!X%yitTf*xqJ6?(h3s5I6~c@ZL4 zVH3$E_-j*C|Fq&G;uU)XD3>j&JG;25giSQ%x^URACWgO&wdzCkV*E4Qri#8RjPI4l z)hwaw8TNe3@N`c=cvOsWXj0;|vo4O4_e^$WjEx8kZCzsXn^^Fs7dXDY(lfL8q&bVA zrmns_DxBv6ca`5TgY16bTCIEa#V=9x@!vEgdI=?abNj7wO9=9d zy55+)BW^~iXFtyQK0&>+g~q$yhxLW_}2`uFNg>esTYpH1qP@UE9dU{I_X0&EFAsC%Y}o zHsR=z;0S+dv@tEHtLtVb$_^tBu2LIasx~}X!QEL@1QVy(+CSK}esBdWwQ1kl{`(HF z6LcI9)ZZ*O`fyqk1m83axu!Pys4?|vbLiS^`$7=7Tqlw^j@VfQ-IOl`FAu$&52W-) zj>&swY>86npBr3s!Pt9H>AScEaxb|&c9%aOd=A3SYu&Kv=l+s0e8||uL*mUn_;se! zc8^3>{!RyQBSf2^4SYFhRP5HfDZ@hRMb91`Baeaj!fHgkj(o+`nc6KO35eEtRR>1> zou@M>=Ly(!YQ(m;9sMFpvO;W`M^w;75ypMkGKdCI3v%8ON&q()vq#0(DtlpEKwPQl z>N%9Bg<|waFetzlz|{0|QWu{>x1Lpbe1s$1O?9p4Me^P8;Z2$+%|U$1D|bKYphJQ# z#O3+)yq@5Ikg`&;^b=L$eMu-+?pAMoRd;pMe4!B`Z{JW}4wjsc4Ns$Kl^de}S02V> zZL>yWW%tq&CHLJ~{Dl9w=?090sV$bps4sS-2L97gzr5kmF)Y*Muf_5lmIuPJuF-%w z!q5?uy6JTr9#o8#M5DC6t?#Eu44EyjIYL$Ow=&MO*DC`y%&icNh;7O7 zIl}N+(Z?^k$1NcVilyJ;v>UjAJ#74d{_hQ5{dBI^KO_*4(f_EZRR6ufQ?;^lv^5iU zbhNcHF>W6^!?QJJfRHIzCk2s>q>NT+E7_coBs_2%eCoXtX)CMjFbc}~1aLHwtX5dNrNuJX z#}D)841to=t+l@0t8TB|r{0&JxR=K*T}1)JJ(c%_Fel%cc$jY$qB-kV`p=f2Qx2lf zSpIJfqJZ*)3b}yo_`Wf24*qzD$y;5zUdG@6rQ4t|uh*=ooAI0Idr#>RA-Ee4_3oNN zu-&Cwzt3MI$Y!@uXZr)yY_EY~#QS4#21~#9s70PT!}1UE)js8hgboeWKC8p>53%8P z=9QRrzU7Dd4uwo_WxYPj6MoXWdnyn5)Ia09zhz=x4Ke%D1{~D7OZV-9L`n|)QztV* zC)MvO)e2QgV=z+HQa|ae=!ldnWrieJ?a0sR)HN3fvZm0i@?;*=s}h~;Fc}L%@3l(i zjS;_qB~cfabuzME{ZqweY<23E9bp2lfil?l^}c;lv2{V!M#ZyzlExJ`eP?&SqFX413ry2}!Tc((r&8 z9@V#^zzAs?Zg8hTf^;?vn{_O>Y%&uU8oZ{qTi>q@0l6(yeDi}2fx?RQ^azB^yMcbC zH4Jd$fnT1ABt%J07sYc#@Y*4%0s~qllpGjVnGHG;VD3}DXxNCjHpj+>3V-(_jTF^L z;c{LJjwL}p*+kb$G%iBGU&5b`w98;E&{k)pr|oHnr)Fgv=JQd;$k14?2Rde;RL*T! zBWWL+m~YuO4sR*3m@2kD-ra9TS?1@_C+J(r{;Tp+9?Qp``$d1#ZZ?XX<@6U;=d`c@ zz+}8OWI{RpOhf2sn$tIu>P|B2PgRp&D-$GyI^*dr51Y(4?YOp1U^tKQj>hCX4l8MK z9ihkZiPfgDPwP?bN}m=1J!7y$6pi@6!ce$~4-@Bv(nwyWnNTDPi$M-cX}e)3VcePt z);p@#6KMG-IM?yXi;-%CiArubQ-Z=StD}U;W9p@|2F#o9_qNO$s|)Jj??(DjACsZT z1}ntTt?gzguOLc|wZaH3H)a1aCzYK)g!sGo4Z$W&LG4zQgIr^BQ;!!P>l%`8_UVCM z*vBXB6L+q8__?_iGpEp%jJAWLnPT#HS6Z{qu$pQ2rz4TLIoVoIykNXV z(imkUc;<7rk+k$$^v0V*=;ko!U5>R?VwxwRW2=KA%NL6=mu zhME-U4td4;59B`Dz7b4OWkUcx6O8%;a6lpG=E9P5AqfPfuIz+$QWln6U~qPoJ7|at zZg7>`OAygK2PSf%W?6*)B9y#S_WI0=`?%94C9Dlo(5)0LzjWmOi#T*=vuxP(*~(v9N2$Q9ap*)D4-4#JIi?+5MH*oH8qFH>Ep)TY2!8SXfNPz}?S=>uiW{)lvt=Im#$!7Y-8Djza56SiQ-h7l9lDE&r-SitTSD+11oxcH>UTQ+{kp4cc^ z-t(w12)T6PC9(}NR>YW{V9i6&hYy;a-ltgpV+BX*+vlA~5e|Vg}If zUpLF|n|Qc|fgh#;Y^54m!_e=*?w(L>YTNlq4%!x#1Qq+)M$r;~0cq`_!b)9n{`JBu zDz(;*WcoX4xb3@8T9SnPr9tjDHV`cZOZcacQ zwGmVr`NFkv#iMkuH4-yvZPxrmmm5AbUq(_ipU8rpicQoa9_J`nYLQ zwohd@RLde^JN$O`6qpkq<`s^F!p)evX=)Zz)S!SGHOV!`V~3mfNzLREA~k*@_QkVZ zrldz5ZJUeMywzF*mW#9)A`;#{TT(Npd|r4ot;_px$svvK^%gwsFcA(!=ZP-w8QQF! z?{e!Tq;~a2-X8dRMSx?)rx7W|@-ZvZn_+Y7O#X*Pyi+?bz)M*8;*3mer;YaUA+2WOXGW`|HTyLIZn60j zoU4krnYvky5++--?BbahdIxE-RXv-WdP$70Um{B8IyahKsxZCj&zA(_Pw&TcWN$%r z$_UMx_sPRzwQe55O}`?G;OusT=rr~lkRG?4qsF5y2{s#|_w9x)AfTqTsD@(CjCOn4 z6HiHCa1_^X;eG&226!NjV;gnWM@Vf73fxTjro=_f*wN;2ZB#aI03% zwkf1GUlcF(c@{Uj;0umhho?VKvEx|Mo_M<62s*TPn}uEvo;O+oRZMU1w%PC{mdV{+ z{{R#ToW5rb*5{0kfobG>jk`ZeaYplkGrGtRj;~E(Pkap$W~)6v%0n3GSF*h9 z=+tE5QeqDW&Tji0Ie?~~*hT(Yo9q%-91y`$$+hCpn+;2PHjUW4zp&G};P}q}M!0Ax zF7x|amsc0}JW%)DtGig88Ee(~0vDv3kn-}21Iw&CY}*Eow(we1gCVCu6&u^7In5&k zT!Rj{xUKN8JR{!N*YX>Z3$O4cA3Vr+OX8kkk`3Ic2Uz%PTh=a>Q%3&Hi8A~T z+K)yJAEbAT;iMy<5PfcZ`kuh&vOd^WARi&C$NoRC6KW-QvUo2SaB`zW+0-NwhbAKBPlN9I2-4%Xuq!(2@gC0rR?*1^#PvCTZaJd} z9yJW&5ok{Z(`zxnj|FwTjiub62NI^V+6lgEKdME02(Hu0D~aIIwC3SZ_aK{Z$gbb# zv4-S`q$=G;rXoV6eZol8siNqFChLCVTJ?dTZ_H^=(9PHwdyu}+E52T#buWF~FSC3L z$Pf0QuUEoP`?%kyDpQzxz36c9%B`KFyB=s8(rT22#6z0fFUb}5Rhh}dTUWOXC)a$T zZ=9Uc%T4$;$y!RT{-kr9Iip2ZQdkdLofK&l%G`)6D(TkRXjA2do&BYqETUvVx_)lG z67H*3ddoUaSfjn2aIEJT8bFQJwZc? zrTo-QOtJ^}m6lv3mUS6AaTOIEY&Hz|ZYuy=42pEVg065;2!tYM{y!bB5KP0=0F8Lk zKhOa80OI%qAV~Zon{OaOP61X<3H>dF zop4g8Q%r{%6?YVVyge_CfrFODw3t@(h^*HPQq}5ZKde&~oRrC2%CYDHf4*zCR3-A$WIy)&C4G zr{g7WEh-5Nrc^i$L{>U2l!d9SdA<4TW{nF-uM02rwp_iPnrGl=K)^vjUk4ye4jr0LAB25^% zW_HgT%;Hu?6LlwnTXKm=`b_%DPF*023&YyGJi>g?kIcIdfd_GS4|F>Ae!tA*)ic)_ ziM#E+9NQyW>X!PB2^CukF)RtDYy`1fFk{TIR#MF+umY$m$q!YQHWQ|n!}Hzh|5+P8 zYwT*M^P;t{kt1@JDOVO}j4Ko{)Zhi5I$X<;YDAi9LVmheU5Tb&vZru=C_L+i%<4!? znH$I#?#q#0Wl6+X_67{Lw)%rL@2?|84vY{KmOV47Dju_>?U9>0SMQ84AP@GJp(n_Q zcg)+GlOHX91-q<1=znv`+4H?PRO&#EcM|*rXa*&F<^+DAoE}i$QiKl$1Cw9AFm%0{ z5dqD|VAeV2XD;}v8Yd7?jVp#@xcnn~KXO&uPG&jc;@1D70f<=-n$2oLUjJFT^x@b= z#B|>ZL>Kr($lrsFETS`abQvI{7RlZ}JW!KPFN``=E=SBHl0AL1z;RhzoEb~c{nkHj zI=bFDHnd|TlNKYE3n;$SrNKuj5un~8wO=|Cpx zFZo2083012^k3e0-_QNdkHEuFNAoV|S_t>h+8<>^6QkulcR#ojc=gZ{Yr#;uk2Ya2uesawInJV!*w6wCQA*gqAyGV{)!T?5M~8s9v$KK!gR*yw z5;fS8L{HTz+qP}nwr$(CZQHhO+f}D*8>d_~b?0_Z_uTHD_1;?F-~1JsU+#<@5xYOf zzZ-(!GjvLw(I)fk?4|5RX$ z@2oIgeNRJCW#EyTl>1W6JQq-q;?bQOd?y2WsZ)~Qv0X(l2D4(M5h%yv5(k1(jI$jfx2L}V$ zPF(aPT)nH0K#p>YCJ~@ateM-^9a_sS60UpQq6h?phL22K6pF}SSLo2O?SHq&Rqt`$oS(lW7!VYP5uC<0MW{VJY5A z^FO%@@V6O)?g~4Aps6PEc3o*mbg$)xzz_*aZT6-;mlB5V3QC3U3P1$W83rd=KX@ld z#@F({WL8mZl1rbSzjuf4La<|zS~T*|K~u~hO9zo4Piob zP#`fTv>fJBLE_`crBUU`*Hs9#rV?Lg0#Hd4BaE16nbPb?8h1iU=i{xY|Iu8|2AQrj z)*3|x?;U&CzYv;&D9HZ{eT}Iwr*Sn9k8!!IJh>%Y1u&U7=`~cznaaFCT$>ls7pg6~ zA~D!>d!*3zC7&YJ>{+(1T)qI1>1O1fD=Diz7BfU`WWqo&-Lmb*Kab=Q!f!rhOxL!S z!C5I%{VwA}J%7%bTRxIdwrXNbQC50KaJ@ANs&bW`?{bUX3?K!D-!%SpV%a3Ujh$tA z*o`oi3CU=is<(|X^~5y_8F|3Mvo-XIF_XXc#wgbV_SoVG1=^{a2cv2Ls!I8wu{Mqf zrqX$uOiQ>Kg)>o9ZC!T6sOJ@#5x$1LbeyN65mo4KFA*uC)2e6B`c2{L@w(HfXCKzM zWD&mX6V1UMbeK2JPn)hYPFMWS!4quW6)%!$-f~z{JTR^E^^CklMw%YeWOvPUE=!mt zILP%C;T_!ZoL`PBP`%Y3DtD)E`c7_Ed2**Xgchas2u-tHay*+YaxkL89Ew~#YHL3} zgf2uN&CWFHV78YuI8i~7DuMhqrLSD{wDTmOP;1R!>y1;rxh#XPz=2?1YUHd_K$}vf zW5gNO5p+TwX2->M`8GFE>fDwryfS-_p?3ylz#GmUq~8^?VTVHa0#o>cWB7vZx~sYw zzC-8F`x02?|Mafwn=euKVW%6D(>@9U;eSo8JTCo@mwn^$vFMoR+RtGn@Y~?=c-b0wy`mG_&1?!lBFyLKT^mJzaBtqbHJ01 zrnNFn%5sDTWOK7p6*4Wr!K#Tryeeu6Rb+{8{&z`6*;%NM^#bnlZ|*9PVXqk35=HzO zAB&n9c50FxHa8U=IZ%m2be5l$6%oIoOBXqoDxempAuk;nO_kc^nx7b(9sYzkXdGJ5 z=R?B_Rw%wWZ8_>y5c^o9jYiy>xHXrovL3ToXX-!ph=u4VpO|EGSeBOzLqg?y;@7yE z*B&&4qLpxD4&W(E6*i3bGPohQciWq2^XDH;VlXq#DrSs5iCq+l2!oHgMfuD}(LXX% z;Ab$ldtg!D1*lNc1AVz(RHz>^0G=lPh`S)R$4`TG2RzX$U-0nB4+vL`q6`D{8wwwi z;}Ys)WEog))6Z)XftE}ct}|ebSDC1CTF;$X<_czB!B@-kSXvZ0p#-aK0>biuo|*0A z9D*ZSI>)H>7t9r}O9NbOHOiKcFs)pV!h*4oL!|1cr?mTJxC)RwY`Vm?s}XvIJ~oo5 z*Y)a%%Tocr@`X2SYnLzhOKBE=58r~pKt&GZq0W$21bdLamT#6}=k+2-*vZ|%h|=`; zBp&tUVN-V<*y#fb8a=HRidh5IRm*eXL+3NE%&qgGdix>8Olb|wQ?W=U9$VF$KGj*$ zm*bOEl`@^B5svM$j`kbtwYnj^R^51)!)a-Wq$?m%DIPcI!#k17$ zNkke^!!I&azlE%X8{&j(YSmlTpyeC@%R9k86A{k?z?RT$?J8Iq;KBKM`GcOsnH^Db zafM1!P1;y@{X7RI6D(hSB7i8H??E+{%$Hdfw-R*J2* zs-1_m=UbFYino?KEG{goS45R7E-Y26U$nNIx3n*wvpgBor=WuLo*&e|(;R0HTzyWS zU%q@!T#p%hJwFJ4sf>^Oayg*?T?%-+Yro8;Z%~Bs?dMxHLgPi`7rQUM{GR6T3xVes zoB0y-=A*zYTYgmf`vr*y8*kcF=|O$jONRNoDq}X&tpr534;A^dk))>xM7O42^;UVA z%XHT=;_?EdCtrr!df$EcF_WYRxzFn(GMsgJcjKiX{HE;ARoY87y4Py=-D0P=;&?~t z;rH^#+)$^~2bted#69rSXMH#$i4Q`bY;qg#@T}CP<^BnYPriz;`R>l|H9uWoJ4hev zeO{@L((s+Kc|{T&x;tGGpGvTAPQUN|Z;Ti1U)e8hlmn3fPUJP&fQmy%vE<4nZph<` zMDV!Oq+b@B1R?k)d=+=v6r=!x7Etv-{(ozvy}dm3dZwOdaO8d zuq=>YIz3vfFHVuCoK+nExD^n`V_@t%NTT+-XvkN`k{*z^Ttcw zUR|&?ZK$4ff#|v_2hgPJrp#&TbR_h=a`JVu9Z&%+HJBfoG2^Hixh`Vm#F_;|aT!)1 zq`vDWqy}Z64xG1|l;P}VO|C~?<>Ac4v{o*{0y9zO(U41?AqIw|h+MHWbpRLT^VN6; zewYy!S2X=QEc*VGt_(ftqUe{FEe3`XJ85w<9R;&t-bsvzi!ME6cz4;K;(}n`O4=ht z*Ep7ut{h#4<6Y zxYT~MiE!2M{P#@U^>=JK&rf~@Ud~YxelwuuYDo|F*%BX3%GKt8zA1xw>BdhzD3aZA zwHX@4fvL%nm~O=sUk5spPECG1Id~F zQOs);{=)$E%1$35#v#mgVuPu75XE+)S6y!6(CiDiWR-z+4`Q2avti~F<6(!XcSUsP z$~i&fr?unF-MpGsF8dl!1tr_zB|p+Nh5Y+Azsj+k4i{7;LaI8o)2S@E(@VX(e8?Js zZn+5O{)!M|#TxI4Kka+?r&&>3NEKO;W0g&5f0Q^}0chw~M-gn$Wh(1)pdZgD%q+E( zsh^62A0V7_f_a6N>K-qJ|HkZ@ja*NcN5l>>OedVNnU6t9(hO9i=tOge08wv}IHTwU zUjR2w%45nxoo=y_pU%rW#69d?+A&Rzz>GSaHDynQK)S%1Di)Hfn1K%7NwINMG^sSJ zy3r-Wh$il}F*q=ogenH=OPWY@6E_;Q5IYhXjcG~hkUUTw+HDSiDnH)cj7lzFyjp>z@cmhbpkmfpDRhy^j8N|)`(kdHI(1_SZ6?(m_awL%tRxhN4v<^;uz=t zJdAI@%m{euV^fv-L_R3g%(f)iO_Flw9DLkgyK$Ec&XhwtVQSG!f~^%H%IpfzkKKo1~ostK@H+@JbA^ajk7{|=V!a+e6(P~^Z+ z{#>|A(BcfJ7DoNsPGpgNsf!TVLZnL?98>&$Ps$v>`lq`&v?Ke*RLnRtlG zxN^O^J^!P&+!(on(0jHllP=StM2(#(39+I#$_?Xc+tUSL!Zmv~ieYZS(W7c-dLYSR zY^KBa7>HEs`}Ql^GI zM4XQ&6APBC!eGdFg*tiJtO5r%4EBqZ5*6J!2UMPbYs z2_>+tsF$8Pnxz*u=z;4Aqv%?^{fzU{HM(p@vvch)w~M4h!WK|m!76)8bS!FtA;|pn z6$j5Cm~_5RXfaxkn#&o&4o@q~?O(^i+D3OcZ5aRTMx2e3daC4%rQC+(dhnp;=Xu-o z;>7h2iLOu)COVO2lK)1vL8J(QQd~^ z+rR$k;?Rvqs@}^R+&T7)efXi`1z#yU2-?Y;`(mvIvQN!Ub%Zt1{-oc2}ok z3s^Myh5YOZC>S3n$AdDT5xaNT`cPds9h;85bh|$rrj>Jix>ARr2tUmTb+(4&YVXLM zD*UAx@hL24a_KJP`<+2}U9(H_pU9_>^Q=N?Swlg1vulW&OB%frcPNHRtf(p#wDu;r z*3nxF8J!hw07uF#rabx+Y{R;euzn2|rlli8KTC%A%VO_+`-uV)%!USitIl2mh;NN7l&zD5ezheu5 z1#zj--pVXb?GZheJ6D*u7!NHRj-0~Jcu>0v0?r78Gg?v7ueY+acC?#UHZF&fX%8ul zG;=XkF$uol+*^gCO5);2M+k2{S3T0LBW14Q!)muZf&6!q;dkiK`laD@ZzJl3^0Ibo zcY%=0n)|0?o;Dy2mOXE%`7dqu6^p5Af#?J+owV8{akL8!x@>!S85?esMcGwX4?8h}@1c=wj#P@kcAe+pc&iPw3bb@? zgS{y!@7w~qG(@;G;^@igey z=?UeG-1_*neL=E9I{u?oOh;h#Wo#=B$mERJ>}npHhIMez#Hl5NNoeKqm$B)f*tg~g zt|Wc=Qb-omzHvRO=Z?MBHjJd@!Mz9Ze2ijk6ZDSlemUDs8P~%8KqTF6sr0F>`F(#% z8MY?$@#HCY{%o_3+mPbZo8_Y`+N;aoD|-6;^!N($D1lj%7#%jAj217=MwDq^+H`>3 z5bU!Z@_vN;lA;xiJF)D>-_cy_iOzD+(-X7PJN$0;fJQrIxIXx77k3OfE0>Inn12eicP$RBtob?<-iqV@9Z`s@=!}8Q- z8u|8J?^N3BbfPz$jk_Oxa;ddZ%pa zaPAp$ejv*(vucPB?7y=!|22ge`MIKTqi^2LWhf<7Q8A4R z(k^t4$Blct@wF)`@;17UZgTCKXq`O;X5edA78Z+LwagFk@O$IjvoQG(0S8 zo||iy%Dd|O+VICN_g5%5F-YzPRzScqE0yKAwFJZW>LX}2=E-wQf|jtz%@e1w=vm3r0)?wEc2_-a(Q6I*$@k`wPY8G>%(1QZ659ZGF+JT>uJg1 z)}Zkn#{-pCJgVCb#rgn$TSznTs$y)gKTqx*lXuYx`})HwaOj8drdCaruSSKJ6TdO^ z#rF0<#Z8hOwsuw5`4`~-ygyL>oBi>R{M!Ern*L`3ZgL>2g3-?gar|NZSpLT~0?y`E zMn8QjbCZ7)b^dRc{D0)(CM%4~0P@3mPqT2uP*H&GBX9$NYIa+2i9Hg`{|*{5WMo=r z8%$Flnq7#*kpB3^JE6u+K+44ys;aGAtE2q%c(S?y>gR2hL04yxXGY+Uj7VH{uK0&< zxDP|{SS(t}Z7Qy6xf80qWHlA4Jq2Sta_maHm(T-7I7K6eI;-Y3`7dd|l3O8QNMOoU zyVjEy56lZ+5LcKI*>4{N^3t8;9t<+gpb1Q8Be)jl>o|PuM6`)!4@h)*;v@%i6ny+CQ(!E;2hiN;2Y(WrH$ zY~6fm;enBLVAZ&Q?&=K>9^>Nnj3~b$Zp5^@@!YrFgwNBPa7qQ#iNGV5>V<-j%6GM> zl<;D6M5c7UK>i);f8yr1BB0>%gImH6ZvRbkvEx6n{`ZspA4mnukIM|w!FgY!U;t{b zY5XOCv4&O4ifqGU;{yVfBaX4L#3MGZV9WPH(JB)n=JAUai298*MBtS+pXu)NFyiCm z?gdyE9T84-3{90LcB-||ZlyOb1R@EN0$oLCVJFK2V3)+u7oe2;$!UvmR9P6)O6%uXo}iXVe32`U8iS|kpEE%BzTl5 z?|>fTZIRPZ7tx$6L_Ao=t0VTC+d5nS;CmVUejUeE_$DE@siOg#L9Jl%)xfI7!q?%i zR=$#;uW0+*yX104nO?w`YVHqcSp~vjiY7^mPxx!zn>ht(;gRf8icQ;KLH9|GWO*+> zuW;jSsu=k8JVN(nJb_EU7YL1J#An+uFQgF>)$kCB7sz9sNyQrd&;^>5rgA)i|8MNx z^Hvabf3TDN!H(j8JaZz>R#pnerVhrAj{iqR9WB2h0Vt28J-V^RL$S^n0f**SyJ!bavXTnPIzViL$Hw369;=Ex&+FE&J2ftd-{MvDN#98Ga`bT`BYiL~=rG@m z?1Ch7$0cb|FV419?>K|~7RSShbvROga%d~U`|-@A5tUVKwJr>B!8_z{3H16uf;il> zs0cA@XZv&p9y#<0pi1=MFdhJ{;$R6D3?Ll{k$yMehHcKkbyxM`|CP{~mCQ#f2m(G= zBQkI&PlF0>IGq18c)t1n@4Ef@mpc9H-?WA)nOp8B{y!f6zrAk%x#Zst7U&UG^AsrM2ukilCLB#!IlR+sRXA-PWP z!AfGF309en)-YsLofk(S!}KQkjt6JwW)Sq2E)jR{0XOLmU&m`LR`d@3i;HBhkjH9t z)X3{cH)re>0N|xCQflOtkqyq{+HyPt90u3`B8`9-g$I);+A3LKR`j5}trCl4Q(yLoHd+ zEN|%`FlnYQDO)eKl>;s6;N>(_e1o#4L{y%7T48;k!#LM4};`@FodS*z?d$u?&jS-eYSK3xy-uCN^u@yC~!xtMN3MZ;Nd|W zcYZL$HMBfQXvu=)g%(nET*g>h$`O_wR_(4P)oBerbz$su0$g&@AACVYYEB_md|$ev z={Ri_FwAFE>5GK$2{A4Aqw1(id&ba7xNQjdhY7n1jFb=p0 zGjc}_Mw3GB<4BVlT}RNgYgP>QKr84JB@i)N8r??Kw-~jQtiC z@%-ZSgLAG;07cmir5oGR(tbb{cdbUkb_|>{TQ&7z))a+P_=d+&rW5{R)baqChryi< zxyQ%n*qp+O5#R(DNLpd(@W;)}&SELed}+%^n+{LI(Kq0LBMjK%-O^}-qT;h?3-VRh zD!d~}SnN$XK*8M-g_p@c#v4=dW2;Y;=;4MJ7F+Ot_<Z@Iq(_}9VAigwiy0J$p zgeC#?*w!y6n87=)Gd-tOAZ|`*aXaR%QqSrvH!ww*JM;7slI);oiep0jVLEN%mwvJ> zg{Kft;F`k}_P*f|PVDUf1u5u`zwY1uS`+I!IfQea(z)s*Z>q^zILffQ%+m$9dVC)aw*I(Zu)^dWWm4g@YvkXd(Qt+jjTEspTtp6&oC)VV zyKpSy-0P>=6mFbmr*S#}+npjHO4eY-5{A8sr)m{Y3I>7#(wZOP6Gpin@gs$-Jw>dq zjN{luw$9;@o$LOkF6T)Eyyct&tkiMK;Dx=N#|r5i$^>hSgLzzEe+I0S-5zkxCynBt z*W{bJ=L@vyhug9hF?n{P9wIiLJ{t|jXx)k zUZvG14TwrN(C7*=(AqtS`eTHWA_W8W5*_IQzjsrB&=2Ndfxf_rq41^bQ3TJS^?3*-|2$*}idX#=GH zT5dW!nOpq}Ymg(uPE7w(oHqQ-I%51ER`6TdnduuCJDD3Q8rs?!3)))S={x8<+5Vdx zBw10~c99Rx`+|+$*&0J)U4ch{JeUJ_SZQCVKun&vD54At!Q(&=GttU;H040<4fKV% z-3}Z9bf_AE7lQsGEg?>&2z2(cC)@qOWaa%~we{xL-}+L4enDi07A3BMmVi+Thc)?I zp?*c+PN;T{n}@dkIC_ausC)j~ZDTd_yB<%bM{Cw|wHDDa3rahxo3)6xwbDGS=NG?z zD|UZdhYeO)&|^?amQecVsS?z`R2$Lli!K3k++ZJb5mjtq7El+BR;GKnBdDu|6|Nl3 zAa~?4fbjj62eg5fumd@m?Zo4x#{5i*70cz_|U|sh$k}ydq`NhAW)qm7ejAm z={d_c8Mc>*tKpUpVR)%L+^CM(oQS0FP?FZ$SDJTnPERe{?(Jb=Bg)N*^fR;4)}Vu9 z_PX};@B7JyJ|t{RRQ$_&c}00u`2iGzf4`Z{)rPG@x-GXT1;2Jg&>&Ks1%7l42ZWQQ zAP^$v72hsccRsBwg3SG9Eoa{g`H-57$B7c5k6I3oZfG`hk`r;I$Ky1MHR3t(vnjm+ z-r_OL4edZvf~1wwfOd$K;4IOb1hYeO3LUd?VE|+*Gxb{BqAZLFA_J3!6KD#_J@gEP zksQJaz!NF*c=nb=mVvjON=G>LJYwgz(rAls2FiJ2DOD@x#M0&zGE7IAN!{@l9-^-S z{Ise*d^HQKA}&tmm5B;(!sOVlb?I3bL>7)ENjWXF@k;tPiCTM+z5gPj;BzF;&iW~$ z8>s)=Li&I2*`FOV4yIt9Tn`hS?R;0^i(KTl^(q%qXb}a+!5F5jF1$I9zVF*s78AUZ` zIcnHZ*v&n7h*%`)J(ySpx2C{sE|I#mt52Q&S8ML(WJSBw@&&9B_@aWQaQv@ND=XW3N(p~;B#Ty*Jg;_wI+;RJcehE zVAccRZri0m1)6mBK!P!csiX}aDIsc= z*Qi4>kbA~vF0i_EfX=bE^-iK)wu4SpSC!khsG*ggn5AYqtTkFyt`|S9j%*l>UN%q} zkCvEgG?W`t%nO*;jWK#0bo08g2alZH&hf>db+f7r(>R~?5{dlb`d>pfn zFBZ~8!t7lG{4{hIyE^QJBRktItQi$`x;EC9Ry7qhLFcn125r+M(;Fa6YYiKeLA&bM z8fI=UptZBBJ<8NApUwt8{X`$C7X?C2MRnJwUMNK)<|nwLjtiq#AsnLv-xxP=%;cVT5--t8j4wQwoWcgd6Na0 zgYI)xzx7xPLnGB{xN!-94Q;B@P-asuj1 z9WHh{Qx)JThYZ6hVKH-ZdB}lG%w(pIAd!HrqU$S)7^cx@n_CTtRhNe{G2)RlYw8f7 z7bYmDk37w4%hILv28%Z&52IJxlUp5kM7#8wxCHB&*f(^dZ^Vnk5U#svS%hiLVgq6; z^Up5`RU!Bp+$?cn`%x`U^)Fvgvs3MEGG>RCzd@z4&xM3-PB2ERP%s+IvtM<%%Y)Ht z`i{_JsztI)%P8kIbO?apZR%(6^GPl-b@fLff`HN9SXd_VPlT#o^NlTaQ$Dg(PntrE z@V|cGXC+bPaKm-6P$L0em)g#Rt+M1^hcZDh9R(Mo&Y!h&>I4)&Id_a2%me_?QZlBA z6FDrVs>_#*XybP?&Q+_vb}!>=Gd=;Z8?7s*HMmv7T5ih>>Y6su%;?qltLJ(j57}9@ z9zUX2-+GbN;@K)!f>a|$Vb=f$Udy=_Du1V?!0_}IQ*73ir0)5fDB-Rk1FV+#tyww{ zI}~1BFZyX;(yacIp7us(Ve-K%ht5^?xOND)E*vOs2<@i0*fcqDN#2QIelg4q9RWawiQa%H_8muvWNi&lDHUQeJ90;0hU4>3L5f0KuCy~OJQsj z!59s7jPNSf%fZe_)v=-%o67j6{rh|@RiliJiO;ev7&nzSVh|_(Z4c$RfY!dudDs9R zu`{c-k7v(8SQZ%2N43H$Sq|sIff;1@PD1MN8a&gZbgnI<*W$#|?$D(@LjWKa2d2|P zHO$}Ay>xekCb{j6<#SAAjGJvYV8fv58JET~dX z?2YOxfR9|U;-eznz`7)rmxZ^#!!Qqk0i9(S0Yyk%2mn}Qcln3p4^e}=A4uVwjob1- zNWn`XG0hNPO2*h?sh=vE1JhMwmnw=^34MA>9++95?4&pAXwD-Dd4VA9;v;o5>Q3r{ z-P>BV0hX?vLEA#V{u(zSdz(0>8=sx4@M``AqIhsFglX*`XX))6xyrGre*C#zq)M&7 z6(}3Hw7pkp8NB90J)~(#ZjWwFGw5{2`OA^&1KlUZTz){K8$df?E8$f1SE}wP5}sdk z`5;tDnb=%&6iv$rC=f8>pjs@kv30>LxE&UXrR}&|IlW^F;%@{5-TFT#sYK7mK%&$< zrByMJ!vgQG*t&Ke7k$jQLx0%88OgP!4vji$-8gaO+f!pl+K43u3@=#fAa{Vo&+8>2 zu+Byv#YcOc3`e8=afjH3S6Qm8f`*-33D|hi_2-*-41Y$ue759ti+dpgt>5{#vve=@ z6>5^$9St)`uC85 z{FN=&13GR*c1s3%`%ec3Qjfd9FlQKj4%agAL?$}-@$|6+uNd<}(5!W22C?P<)8;^a z4p}U|0*NrPApW=nD0ld7?lk(c%zeR`0B4^G0w@D0oYXXbG63P#j-w$N?x9sLE#~=m zjoxxi*QU=Ebl@4h3#|DaUp)2+ZXp{dUZPHC|GvFXonO5sc@#(s9zefXOVikgJAFV2 z%BdQVQg%j&%cF?c=3ToIlxaKbR7h400(29J-Dl+Tq?{dhwd5C-R@>@(O7h!_dn)oJ zbV72)iKpgi2LV7R$7Pd$*@M@*cQf;JD?VqM2i3*x?Wr-hkmck;G{<4yh`XXAq5<*< zYHJ#aocj4zi;E zf|bqivIP+{-N6g>H=;n57>4!U76{#{4xQ@DmJt4(t51 zn@oY`oM{L0mHtxDmo@k&$YXEH9B#>cr=XsJz;nZ`22V?VKXG81Y;3RhMBfs z9EKPYx~24Y?jsTIVv;LUp%UgnBg4$|=(_rpb;Rc~aUF~a&X9RZdXaNOZTH|Dkc5dC zdPWRdX#pooFB2uC7oAn@rNhhb1Un+Y`?Hft!j8W}+L?6GaEr@^>&>}%Wc1))W!CHQjY5nt+E;*;o8DbQ&N?!5hr*W-l8-4S(MS!SjVs=N zr*RbrCYD-}-D~-OXoXK{1xM*dN9hJe=|)D~2#wT&y1Njbc=F|78WndzI{%elT2qzB zmn~@N@%MP6*#fxVgeKVheSi7e{TkT)Zy*;aUk>Qk>bN5ju=_$m0T;LX%ybynNioT6 z7SbWS4R^R4Pp}+Mv>Z>M98aViPpI7A03uQT9NPdc__&i7-E6MzG}#2xwIMS1^(@E5 zU~?S?cZvhS6UqCeq2z6;kTtJJG)RQ-`Z|1d3wZ|c1Yim(#z;hU1$BK%6io!;p@pW9 z6k%eTFgaz7{G%1CWq6JF1Qkg7c4i$$wtkfo(zRhGoZede&{{&z9bk$cP^By&iZ7h9 z7tp+YXt>MJB^h1;`A>SXCq$zMByL&W;qPyu-1%8IgwL$fMNKWS-rd(n$(lS@H{k9` zj&4-a6xi1krvMYsFYiRFx$+3aO6ZpeF$4GgAq#Q-s%@kpiO4kNv+!mQJA-A7p$0@>H2e=B{0}6cH>jaE#IPrJXGT(Z%KPH*CjkfpY{9gc z#YmL;)7CnI0VA=Y+&m7vf}Q~ubKYpOI(AHgrM54)qx?Ta8Ne*Nhm{{ce{OOWE4UdK~OD~3*Y;1++kTzanbGt@J3xl0L3@kj+Uf;2qG5%F&TCaB?UA1@kyyhXMtSTTirRtj~ez)Tsa z3q(3VY|3)Pf5SX#h*;M#>m9>@YeFQG@p9FE#%S*Qy|g|;SS87ke`5co!IZfd<{PSH zfXh6p5$anB#=D?Y+n3_NP5QI}B&cHDxe!Hzgx?WmlL?qxVLxIzo*aI#GMdr3=U8xT zD{DJMYi8dN76wWs+N`Zx|K(NQI9MSwZ&Ou;Rz^DZ{xX#9o43RwX|ah%kZMpxw0FBZ zxFOTe*Y$`BsRT@bgj6*pV>g$+yK6j0ITqv3z{D%+v^gKMh0Y^l60D$<$JTit-)vJE zESrAK^tVOQ(_3y^=m4%hQf$xpa2J{>f^`AyXE3unWAYt}#c_30HtopxJ_5%W2KP+$ zBbUUV$;)EgyteM?t4AK!Idhg%#qAN6o+Q!w*wO~w0{zHjc%)5VBr{RT-2meY&|hD4 zQ!ENA0aQp+*<=&ELLomAKq4`g?r4HfLOtTp?NVW~#ack^Qu%ZrKZY0>pl>yn}SJ z^6+-VS|6tUR;itMcO+zQtseAVA`#R9^u%k~hYvO*n<{K5Ug z2b)M?7IVm?l&_-(oNzxWJWMVFa|L)WT;=h7+aQO@1T%+^NH-Ns4ZjY#f?U9>iK z`agCv`7H@dexxrG*Tm_PN)q#`<}YEmsLHlSjk9PxqyUI`ztlvwk@#sUD-w$uD@dIe z76^%cNZh_q3hu^uIm5mNyP0(MlXrH`SznyoUtYrwIOtOzcDKVp?5L15DCk(joB{bt zoChadQEe8X&e>wi+XiD<4`r+io3=UODJ3Q@niS=|^i?W520MT&7)8y9xQJUy(iHWp z7fiwqW0~?4aIJ1jyWvbHsgk0(6EuOYeTWTZ!UMa$suDz;@HZ~N%`6txZHN;lq+O>W zq*|fe)P=WswX%lFHMPr;Zb%ExT7mwq^tWIG?EEu!US@U z*eQ^Zk&q)QAZf?*FRZH!9KzzkPe?)ePj>r%6YclUPQiaVl>c;oW~)R0kgmz!xF!kD z4DNA8bpCvEd0_aA;z+LyL40GNK==Mce)uR};yMZb<5C=qKbcsXEzMUp&KET+E43QK z6dKLSd4gsdt1gs(2VHnAtUEs)HncacTw32hyF0$$w=>6$7~-74?ppRCMYl25(`d$P*krWjvZPdh8O z73aN$hq{Zm+PEJQv(HN3pMW(V!T>&gxNo%W_GqA z-bX_V8$y!qAbfko-HIeqn=_Q&iTqfT;Q6I3fPg)x)7VXjtJ3<+Vuh;I9M_^otJzZj zst>A6ML=l?6}15#3PQqL9( z8gSk_9Ro|f;8@e7cX03Q=q%IMcVt44O^Y7_VC3R|isaDrbaigUGQYm&nCqxbUB?iJ zmn)FpE!Xh$Gnk&oZ$NeqB2ZZ!TJuA`U4lAdau1ki;7te z1{pcuMy|zVL5vailqC@tMuG0V@_LZU@0w?_p~R0 zso_h(P$g;2Xye}3+hh^1b3)mO3E$JlY`s!Wbv99cYje0c30EHs*tIP%^?5HLBzx|0 zKd|uD;gq$U7?@{&V7H4}i)4%)M24#xS8620fYvl2YQ?$vr3xJBcnhhbY%Js~O2#8< zCKlFvwS-I(na8FXMtL{aiC$pLc<}eojlxCMIGkxJre36i{1iM|Xlh6(iXgMmdXhYG zal1LapmXZQOhBDp^aHC=h5;Tb7z8ojY$z(8Y?@q}bbJD`jmWS)xzuP_iufl&s2vE? z%w(8! zAY3Vq>~is)9&l<6Ogokc>~SB9!X3iUBrM8U`LnUPvZx|DBR;>bgT2y0=YO&Fj={M^ z?Y4GobH&DrovhflZQHhO=ZWoP#kOtRwpMiVp8cKk?W(h@x@!LD{xiF3cF%c_F|KHEX9$!Y%`b%WlSQe6P~xctw@Oj0DS+vH+!5 zyeDT75^efvwx!-M`;ll5inp>iuW~z8P6gN(=!%ov@RUKFhXip7c`^rfA#+nh`36Lk z8{8KGS{_^R>P1FFM?N9$iAwl3*&23x9ABv zB(Io;9$Xgh^pgD5d0P;s8r7ppb7LShwaJtHBh}#EubQ6J3PoCexW#a_=G%nm1-ZMc_ic09-?q zYSpTXnHtC2w)9V?TSmyPt~@43W79Cl!mzQ045SE2OHxyN5KQKe50M*W4hQ{*%{+&lW2zu#_dULWH(F zwrI@WUNjO#KM3@3vdWfoh<`7Cj#iI`h_S(ZK(0R-{dCTZ_9F&w{Cpd9Y;3IH zp-}RWWD|=}&2$Rb(JwUZWX5jL97xsju}ADz`Bg7Vx;ZxCCoQufL4jrVWm^nNirUq4RI|VAzcf<+h(1OQb?jcLd8zo)+D@}I zP=U>xT<-V}w$|KpKBhJh`MvXMP=U*hY4j-!p-LEz2#S1nh)D$t_)>$dzP8s(9M(7M z0Q^HO;Kg)yLf?KeGU@7_!wJ;OAXm)?_`Y-M-uL~63)VVCH)78<7A_2$pcirtvrKSA z*9#;w1y>BIM0HQTWsZXe$`|^qe#c1VS2a=x6T*nfRWgN)K}iwm_lC@Okgi8F zzRy45#GBH7|J?J!?BV~NZPA|g8EkAbjgW6zgb5cihEABN^M5PNwftRe`gsQLx8cz2jwZ!y(Co(f@3y}Q zBCYVyq?i_EwOf(hFsIDOsrDhkwWpQtEP&uuNRtC(hWP>A#=U!UX*a^#E#nx(e8Y=i6Yn zc-EQ?zR95B&v38P?o=o9C`<9SMuCqhFp5LVQ-hhKhk!6frui+X9_b(`c^gk78>Bhm z`~ilV3i6}?=u2WNbL+^XJ5hQ-s|^9IaAHMYS-8w@GUGVueWyWvGIO`Nydb(LQvkpB z36N43X2(uiJ?4qwmH^&T@qwlqC<_Uz|2vG8ieKfxQ0d?(9|=>W*0RB`*DpFFYFEzw z+HV176lofKo|zJt)#)^hml1YimMp?Q`U`GV6o6?; zJ!egtxiL#6bDD^^NUGO)_{Q8FmB1v$#nLQujRWu>$%Hz`mzOuGg5qQbV zZN>*<`PiugT{foyD1<+%f=64&4?Xelp6;{jGwP(mzKWDJfZVgZP8WoIU!Eo`tff7b zFf^-crHs&tv{jq3&Dt&u#q0YZwVtlwXNb7&)wq<|FHwHHI`H>@1_&5HraeG5~t7~JbN#Gn=vm(CCOZgE|Dl`&c3M+pM+ z5x2RHt=8A|BJfjZOn;H)AIL zK{asUHh*z)Rd{w1wSA%6-jPvAh{&G?sX&96ugn`@a?e0@l+>z?`RHjFE#zZZF&$d*B{U@SbMinE7M$`)BwQI{Dx(JiRaRC+xuy zpML!0Hj?zNLc8~Z>38*g;$@1|{K!|hw+it+E7xGC2Eln1Pon-@xZ$M%XV0iTXMf!r zcL^cf6qzf~aV0}P=BKoq@pM#Iu*gdNdPe_{xA`)ap;R=3N3lvtMxe9z)5C zA|yTSE9=Wwv1i2Sjhh=Evy;r%LssgeNav$F0PDDCXZ4y*$%}ploy zxM1m&7y!loiLy;FUJj|Ta2M@eVQ(W3=)Zn!lDZidbU@cM3#`%nQ>cTLQZAu?^+m@ zXlF9x8r4~2NP#n3wVOeFdIV8))hh3rE--B&2UxY!cR5c|qJ?_NLIn?B;xcXw%S@z~ zp_##*wDKx36a~1d(gSAkl$t-ME6y?jZ6l-Y13WQ? z5p=T!Tn#A&25rj5MnTo!nGGTp+m@+Uf!EmE&mdtd#TVx} zp%ug2?0D=Lr&;D>cVyMZX*zP&zZs&jsLg2Xo0CW2t(LQmjD`uJKar>E9J^N&T;M9W zOu2@MMrxADFXyb6DbwQCONKrZ;TP4a>K_Y?V~o(Q-j0??eYbq6T|3T-IfKGw$h$TY zbwt-MiI#v~L04*EMXuLUm|-AVDABObD%auMoLT@IYHXXL4NR$4waY{WX{I-+*kTP0 zo)Qugayy@~8CfRb+5=-3Yc35QUE~%RaSy>TvQ^d`51|LFntz?zEj;d3u^Q$SEhJ+I zTCDm@Q?;5VxFj2o_wCB+@hLTWa)`ck45==I8$$g9OCj$(Ku zb{w$@l^UIbQEUTLYPbik^PY|R=bNowIAj z*vax5xoN{L?A$&wvZ)z?2V7R7UCAD^u959Hq|~z8s#0n7l50&-Vt5_K9M@PS9f|aw zcjnb>pC3CKZWZTgEe>|{u1aR<$mZj>Qit-Q9?}z8;JM5WBXnriZ4Dj-Sy@s40?qb} zeS31cS`;})%O90z{_W>C+fnI=ec>(P5w|9S-bI^WO{)vgryc2j!bgqGF;{^vFJetB zVb&mEOfV!rD;{MvfcMM~l_)DFN6xWMu$spyQ^YE{!=A0sQoIa0;MPVS{3|&aFd-rNL~6-NvJAZnA|d$=o}!F=0Ai z7~jZIR*-YCembGh6NQ>(d;>8jD{EX-GS8m2q+BBr9^+6i!D$o3m-^g@Eh#3#M8_6I z>rk&!RMbdISA&8F(v@bi#h6h7Cq;gi%AXo-7|eBG*s)3^pFV$5oT;%fp4EUZrk2UH zrWu{;+{R@#DiD>xPGG=!08k-;XAiK73{w#aq4292~R zE61R!&8kLL! zKa7W(Zs=c+)mB|(i!!nP=Ot_3UEJv6;Ti)b5*h3nb4)Oj_uiH|God$6Du0UufQLK# zP6Q~K9qbbuZ6CE0nGcIsXr!#VxIDyOGMT+(%dONR+_VA$L|>LwbbJLVMoTzvCJd!! zTIMAF*3qnN>sZ-YuLn6^+vEMqw2L!wo@%PR2|UQ^GRA8- z^aO9Plv8;NWzU`Mn*`e_S1<~QP`AwJ-Za=F2(>_BzH2wRq|R5pq@^ryNv);Ygj zqyWisL@FiSfgK<7qZ{1{U!H6A67XEIv@ozlK3u!TDm5xg)jiqJ9k_ zI;zx~FTRlca#Py*?=`^#eQw9ErjQ&^wq`!N{odK}_NuM=&(ZW7OL zR~`E#7#r`lQ7|s*U&~I*h;p#kOVvn1GzI0Py3uC?R&@k=5Z-eW^d1oQq0#c zj&8TUex}evrHOU7Y2#4T@vhd!MZhTSKM5MmArugpw=A-vhR!0^;F4GY_Vf*8wjQpV zT>V5VeBmH@A@0%B2Xv2~dZRnNVoM_rbP-1cu0|BB!b{-_N{H~r{qjwzFZU3Tg4>akBMa6!(J}KAtL)5YCe_7 z+S;8)bc26p?HTBQ^84iy)`eWCb_?_RN^bsl7nAR{z8w=y&{E4~j@4}c4!cqxq&@hy zAm%3n+rHRoNm$vxxB?u+q+L6ut_rwiWr1pM7{sB_JooPTfTI{_Sx1I$26#mk{W82+>IdveXxtR#?EMRT^GU^p$IAcJh z5$vzm(p0VFWL@=ic2J!Wd-wjOP@7dW7gBJc-n*iCGYfw)(ahJi?=l z6|KP@$sErnSf8E2pPdtWa(Hx%9lCfB6Xx(=Kfw?mI*t%&Pbd$%j> zgA;udOMOhhw%2Ai3Do1-EHXPD-kDx>ChzfI0f^fIw^^!zZZ#(N6ZR>sH4r@{y*Isb z@2_~TSOh&mDScG~d>cr9=Gm_;D1MLc{eEb1Z?8L~b|$OGR#Z+*jNJHW$K8Wde_^5q zX}=5zZlt0~b?bw*(il9YMl`H@!ao<5{&5Y@Z|v#(qT6kb%Nd9zX&Qh`t0i+xKMI?1 z(51Q=1m5ZAq2WamL&mHX&f*BY+UM{bg1$thU?jaBtQ@R#DCG#TaKO~Q%iO(ey3qg|db&9lI=md0UxzV46cZ@YPWd~v&?ebe=eG}jPt~GrzkxSK&tQGm#}}DqH|+nB@c-Xj5%iCQFC(HX zKr10D`rp*w78!5e3H6HJs-N3(KML@F;z$4YF&P0_2~iOxWjYyApIAoNeg>qF7yd6H zQ9P6?D8c6Sav=fv&A4Yt#dT8Bl|DbaCa7lc5wDxAcU|!5=5%ph2J(w+j0{fu)D8kN zM0p&vB(@B*6bDsduzpe998KIMiOX>*G8lrOIR1s1oCdAl_2%ZU&3oH&Fk0o+bn_l1OMY;FopvH!uy$>k(~{_g`o|-n-jgMfiu0(Pc+5Z!1gET zZE4_YP@QTgx6h9>tT$1*`WQ2t9;v%1Y}g6IQ!S{~A>w!^-H;6aeA&~up)~!vW!J1) z%yK7A6cE34{gGo9wskf*=tasL*-0tC$|0YlXd>xeI;SsyOZMTE6T9Fpi&{~1J7|V~ z0Ba&V!jaoqC^24u)c?P}^IKVr;_X~$KZO;n(UmN7YO>t;_yi(uK-dO;3!%2TcZ!FIx zX9@gvF*z)jokTYFG7K`X{-Bwk0hrcv0rXbnOm}2`B~E+N#^c97(b_O17~&ajDauVF z-sqM+B&%4i#^4UzHgGFIVi6`!$cFuidBxT9WC9UfcaW7w<1uN7U{~Uh7zP*1k(R_^ zjBS7(;CtalzpmXosq>FSIAlnVcN}gVb(eT<9J0jTbm!fQy}o8M7zzJ|>oD*{xRAgBsIf zh54dtD_-WCl-fTsmAsCp`U(@l47Tb@K$n)ljZHkN6N5asOKoPzKV@t56Ht}1(k%C@ zEDvz5YWXAh#3;O}<+~W53G`bHpE_4A<#)PedZ!sP^v5^y6F8V6Tfu|;^|reQ#}FE~ zrMXx3r&r0DySa*i@d9d3FEgQpZ}aWB`gv7^p4*1?DBG$jVRL8`1Ino{nG0cAf%aX zi^loaI|L`B&EfwRfb#}0y)hZn_q<Y}085g# z>DdopXg8E2VMProT0q0CcCo<5)5I^xa3Bb598sk`gczhXWJC+Mwj9pU<`x!MP?lP_ z*A8H@*SOeZr0cM>w+vIJb8N#CTRsE<5 z+{3M+XSk0RgP6O;a)r22AJ^sMn(JehZ^GNCP0IGBm8A+oG(#fB{R$=Uawy1txY4zj zs|&vl!G9pog6hFx>};E8o=(4qgj$17QR<(fsXaw&-PJ}(ZJEP#j0eaAnv@KTSz;Fz z0cFl(PPU5&mBXU6e2%EJy>|#bAC7T8W3ofhNRay(I=X<*Ng&_{bS3tvCAK6=)5(Uw$#h0C8WJHn+>djEHNk)rnv^Cmj{b>HICh$%GE0`QQyAKr&m&76taq8*9biU z1jh{0Gai>~&pkg0Y7?tGj5|oS6bb`eax+BSasebG(U3MDc;I1^P z?=2p$g%K*kg#+^#M4s-nYrB71kb<-Yc!7rz3z^~IB317$Y_Z?42ZmzMD$C2Hqu&hrcT#%qThc&pMUTREUPACsFAl{ z(?Iudc?O6%m6%=8e`KHL^MU73xsLZBg~{g~>R^KR*!05%q@NldMy4jn5=<7+@c0`v z8&HRy&J<8qfSp%v64%H9wz2WxS|Vn_W*LMJa4tPSSki=-&6i5j;b@EnfIr&{mfwlL zvLFMK4ca^34VcU@opNCFub9|0>pdiO8||3+he>zrba&$P{c-jr(IdsSf*Lot&IHn}lmxwr1!%g&x9jH}x^vE=g*>k@=ULPNp?hXFi zzxKT9yqGcfnZ<&Ug{pSQP@_!el(*L*1JM}nlJUT(Vv zWh40g+62h(&ShxB%lcxwM>RolQe4=fyYK?MTe-K|GeMj$_V4T+ou0r%BCg$7$qsB% zT%HUVw!2dqOgeJd3&(DMdlKs?$%SdVBq)7E37*;aNl^co%}0$=CjO3__3e@FCmA;4 z3MIjS;P??~n*(Lr6d{#nOyX2IXJdMng>4;2(~qu&xHH&CF%H5R3qb>8mLw<2VLWix zs6j@{q4&}Z4~a42Dd9m@tZO2NwwWj;fu?|M#yG#4X7&`f-3PEKo?Kbt%|gO>Bvc`- znu!P^V?|jAzzAJVxl^HzIqehw<;tjxmL$NaQVsy-0zcKM-+(Jf8IYBcxl+_1{N$pH zOB1iFBQ`ZQk2n(>*e*TKM>J(u{w@ON7p$_+Fw*|(+}P;jra7)m>2;#L_=$N5F=L_3)xZGP zfw8-V{t&ZNa8r@n5}b?O7+|FilCzt>=&pWv;g6t3w#b%Dgn)6>oKAb2+XnLkeJB=Z+jdyy`hX$zY zCZ1A24@BsxWM8f;#9^5g$E%onkEuO_yaxucuTBts&j_tAyi!iVbz@WewcPWhOrA~p zu~YRTUp-?<3%{%K;h$aOvkUcegRvlug8piCelpZ3nswF8Qtt>UyP@;jSPJlDaa_mv zkRJ6@$~2|9c(s93Rs9VJyf}V{jAzDC2ePc{=4K?#ux38rx0Ew8v zLOs;=^F;1+P7`vD80q=b9Loe+8`T8~@ zniZz@gZnPZAI{` zzIX`BoM`Z5$6V3Lw`AVntjm+0+cImBZU5( z+m0bqkxmb?pbQ~I!5UYvC-uFIF_!D*3Q|NAc1xgBBFMP=j}n!ZW3lcSipH#XItoGXX0HmZVU__JYoQ#iVe$q89rx zK%bv?J(-mc7w*FnAP%`PCw~r8v30B5>AEZvXLao_?+<64eKO`xN~k&Wk}L1JpoCep zAPrSyA+HCq1nl0{xAht$P$Q9N+HGau0}c{@`s>n7&*jV><0IBKe=$kAj;X;$IlzqR zApv5#*0z4S^ygzd^C4*AeZZRH5PfG2ALdIGr`KtE4_}VCP7<*5{=TjMgF=6a`dE^I z>}sLc$3RbdkOmecd;A-;t#2xy<~U$sQP}9Bu&TPSJ{7ji2l8GzWBWb{>&nwFd-B|B zMO*OK_=sWoM%M({W-{meB=tOvLLtHaV0)s~-~Ji2a{A6SE>#ZLaw~wNVeOg`Yz^Ye zg1s3+lOYR_>-GkNM_Uuf>z%)5Bc>%MkrHj~Nn2!n&WIFG-_4FD(X3~s#nvwW&K zhfb?QB!*Y0UrA=)?*t1J7^s5TJPZN&+%=~Smnc<3S2~O|l8ZKkBP6X2(+B;um7?&y zYTekeldA5FcHCVR5t*v~7?#Xz4$O1y2sUy{L;q_w*BNkRIQ_6H=I)W(phN8UUX;Vc z8Y3tjL6@L3?Bip1iONtgfN26HQA$tIHwL#5-0hHSF!E})u8{g zSuvinuq8khA@LY}q=R!&Q$YfH3AUld zK|f@oPMu1CD)lvQ_tiSqeUH%g&+~>05bq3@BBF8keDNr7pd)j>2)f zZQwNJqc0pWQq_th5y)l`_;7YUtq|UAXQ-jzOep6_lOT4fd(U8W-RGW5s)_6-u zq;7B^FJlSqfY7CicbwYy3tV;l<}n?b2O7WP6{3uc@V1EikUO%50ESu#kW?gK?#7(2 z#Z&27zhO4+KwMvCCEfA#_r{IhN}h_lhD_wS;3oRPJ=={s9F#KE_9II^q~2VX%>*E} zV=&V?uX|DLD@}BofrcMpdA6>*hz$-4MSTnZ08?EJVIUpbhbPCdhGve$v-x4>Sf^PG zjNZQoG9tIwmRat!w`<8LRPPkvO%rg?MX4*$u6Pl_nQ{Or_6Vtcacci9L ztE8u&4aJS@Ns9PtGb?x|UU0>3JX0S^PE>XVnS#D?8zTQ^!sfW~cgqV-XO+%bc%Po% zL}$UQzL{0%Va?D9p`qgq*;i2RG8jY4R;v3{QIvn;blq*KfH5xD19qsp{4<~(LNBNeHyo>08ylln%In#Kx3l& z>cNgKzyR{GXk2p&*Q&hc#Co zvAEZ4FW9WaA3yIa)WpOV*J&M4np6HLOAXWeP%LHE&s^Rr7`=`{5H(|FctH0d^%Qw! zKAN;=|LM;tJdQrPui>w+^UxtJxr5o92D`Rm2OykPj&PhpY^5s9|Bb=MNw@`6LPC>~ z_@0@hO<=*wpBT;7Uf#2)o~vNcI;QNg<2Dm)x#a4F3&ZZngVBjy(pv9;Dke#(G_+qK zqING5%`BLTG#%1q@9%di)&IKfD9o~Y!68x)3Q*I_-iSb@EJy6yk5Xa7(g?|%w>|3fT7#NFP+*2%*4e|K>FFNpGg zN)t;O8;%Wj~sj69Y+4HLz*vJ3jwdjvXv5SqP9h1&h^F=uiKDo)NbCBUCT2(pi)TC zF*wWeZo+R4o6{@xQ(LW5O7kid&xi+5*UKljF(W)}@L-D|;SVhQH!dg{mbz0_kxX<+ z!QfFf{KF)WMzbEr-MMuY_ogBfb4#u0fWD@@38h*0lJe|zejDsh;Gpcz|A0rfe z{QDiAqZDAXh6Q_ZjTToem2}RnN3B$4-CfawTbKSBe#O1pk)Gjk#L|Hk`H@XPiJD{Z z8y29I^*bry_-cv@k}LauiG`V3`!js4L_e3t05}5CCvTp@vR`%MOfMNig>xd%Fj+qV zp~!T3DBFX|g@tBs?+@T7FU6DtCOM(s46?8w1J<-$b%KaaRwVHR>H7`3vX zgQPTqc#J49o#^dOEL|bRkExlVo>+EI!l00!lbk~HO4-ET;mh3Hl{-gU*W1CfCkOtP zb}sx#ycg+RE4dwYS|Xq4o3cXE!o^rBsqD#20?RrZ^wRB_S9|Z+?c={^@5k#3JDsFv9#}-gUlIsK{0V7RLm`J`duKc7`&ppcX!l7y^1{5W zRPf7W_tD;+`saIhn+?%X<+e%nBKa<6BY_6judTX4Lwsk;YYL-zK&l_+PF zJ$vCVVK{2q>ywjkBJ4#eNmC@v7fk^R+{33^UMEG@C^aEGn)?S5rr5Oj=))^EqS4YYFEoJG}gT2JAHB(zPMy!dS zJ4neW&$?&Dle;Lj`yRyUSD2ATOn|jP?W;>3qjhu-ZM=7Lc(rt)fTqAMcIJfe0^6>3 zwNxf%OSV7m-ZvRbqDVH(%zI`bJ5sPqNvxN?t~*X~Ra!A*C5^9QGEH(SUZtZ<9b?XW11&=3*oH}VvaYa!wsgV?8{>$y>5 ztemVaKFj;-xv$Bb^~plldS#m3rOHnFI~H#>J5e&N>eGy(+edio9t4)n;aP1%l#}ZC z@B(PD%Au6%6mW4MIc;CnnK3+hXH)Y!iZe{FU@KVSFS*y0w}|Q&$}CH^_A@lNqKKJ@ zanGTZ)s3Po-h?@k&|jxvYys`nyH&?AxB_{G1hQBJ$TrS-tTm604JCfjXT+uVD!KV| zPk8U@%wET;pf#R1F3l_=)_uskO73LGpCGxq!bcD^e-JR#T~gKL`~9*n@Y8JOWRu=4dm#7ZHthIx4$%mCP!R=H-;} z(49zs2^FPn`EWfUmVyYy2Vo5)?pZICBu5OYGjQ$u7*9fwvZPHJGXmZQ+9oQn+F6Rq z3eh9p)|zeO+wN*>8vep4ZGOgZsK)tPNEAEdh!L6SU@88w0i%o)%`gpE^|`dzixok) z{&icPQC(DRe4XHs#|qo4%F(pKS6wl~Lxc1k6;egz>}pgY(nYsvLQjlEaR$Y&@?a8a zqT~A2!j7!Z`@jT-*__`^T@*{GohBp(8_e*Mg4pZ=XSm9~dx_aR&TRiUt`sLAR%?B% zI%y@XM0Q{#G6u9U19Zmqt{DT?#rE*D!57w&W>;%VK2Q(#yxT!E(}i4hJl#>KOjF83 zGG_!(5B`+V-8Ay38Q-+7!4n5VC663X`eXlLEH zoXFC88>N-RslR`|xdsXv8-d&A0RD2--N*RgwyXO2p1Zz3u{sFVDrB27OZM?8+WwhG zZ;7MujEV2Vhy5g>kwQqZSwrbF;$5yuy&e5W%4SN8^HIBPN-4n7PDe*IH7>fv0d*pBqelmmYUbvfwCP+n81C=rq){ zIW?ZBzsC2Xj!;gg?GY&UA9#N=WCt%tl(gtcA%Ot+17K!ngYYs+0A+^vC`N{x?*-}c zf&zp8d$ET3oAnEoQT#$*hZf=q8!r89xFnS#g5-u(iNK?0A+hDu7ml6P143qV?(>DG z3$m|!bnzwhP)3Ehf#pbd1$Df4W6@l8+Y1#VLCq#^NqJ%OxCu2b2wqrvg#f<`;tHqo zuMQTt%UoW*gWyoLP(VY2zLn8|DMvjxZz?C4#~bSgoG;!$3F%@r8zQpxqt_%_c%^}a z7es)Pi^4nQd9@xXqe%@jaSqI7MutGCmr-vG>dVQ<^BLEP6gx*bUHXUY+mwom@n@BR zmEXT6pLev}H#Qb^T};(xPNIBfgiUK z-(N0Tb?&sxHr|!Yp-6`n^j8bIRgxFf{EW=M3^-XHhE$+?j9B{L5sLM(B>17?Ja)?< zXo2MbGUT{o7)iNd!I89xN1l_7emh2dcMfbt&_j&Zr7&dN^42zog?6bZdGgI zbPUFaRA4>vwD+%h1ED@1eJ~63_Q3~nvW7NfWtnamcGHGnG4611o@2%_oCuBx`DQ^q zd}Ol#nCYOwm+Y3LQ?n1EPdC7iP7<)nm=*xBjV}ULb@2;{@R{k9=8en?Ns5bGk~Kd8 z1)i24F(Ext9IOVYo%bB*k2ln!lDs}58QT>9Iq^?vib1~?o@REm_f7hDoQz8FFKA(Z zEA-P9QiFXQ37@xzKt3P^EN1s^;cM@s`_;NsM$5^tGx=6Wsx58lC_a>n_HMYoW9+rw zoODv-tX1Frs1S%qUL*>%{kFj6Hhr0sEAZQ-`=?6DUw+E-MxM~Een!NR%E|@$s~Y=2 zOh8eom9IELzK03Q5vKVw3Mg20#gfGGrI4xO19`4I=$(-ogm7mR=ps_X6jTu!D4sx$ zV~=p3E}<$wkw9Dl9!agk_xkfBLE&M$*8mxkJ1yeCRlOXu+tfGFKp5Ytay@mQJ-_cm zXhO{TdhI%?ItzF{T|mg#AY|7sD-kykM>;`&+#i7`2-o4`@qJB$Hu{jna&;8}v=UgW z+1mBr)sLiC;DWe(Qfu+N`95`fJkZmZ|QDb=YUJJPH2|%m? z>}kN6*oZ%s7R-E^c`Ih1fBUIcg3!neyN^;o6%m1RtzBr*bJz`S)jy&(iQ$oK^pP|` z*Km^I2pgwq*_X)BO5XbUzO8yWA5!jPl?WJDs!n#$A8{A@@B!D=1iDfm-Uw0zDmeg% z%cHnixMFp?PPg>_OLVEl2?4h-lk2u`O>RQirlmx!(b{8GYk`p=<#&6TF>#~JT*n=Oo7jQQEy>sD z0M*CZcrfBZ1ek3OPrybYD?7BJR)ZYuFBEBDG7+h84&V#i z$Er~m9+lR|pce{A2sPL>0n%|BA%Ilt0A`x}V#MGCVI06Cmo$EM6QyTSkipF!6&2gM z+q&ZA1<6>oEg~{hHz_>c!$2K6;bgCxA^*qNGv51zD%WZ1GCQrKZddyRdHuGpb=>n^$sjXflZ8W$sHFm2gn?3hH)R;E zDe+K}Klr7FG(Y?-@_4UH8Ay768#j}Bep?ueTGyVBnY|BJ>)CenO;}JLxg7YsJCox* zQ9`x~$>^Gn(H(jj4zbcICJ@%@Sef~nAfzG4$4Vo;0Fxb~^XHpgj~U)g7{lzR%KF)R zNbF_{=HmF6=M@S8*=j(q`RZD^oG?%*pY$c0sDK#iC&=+a#9)uzj*EG(2jc?$vSA;?B9>;?88|XS{7p*Vnxpx<^e>g7WiNxv-0w zs=giUHAp--G(i2upouT`1sl0ABoXaz-&$%c=T=CD=3q}l61EqhgMmu$IwL#UBuy3pz4#7jbKUeAmy1 zPC595pGSxYX`4Q1j5aM23_W$KAPhH(3!hHGI49g$Yg(GgwaZn}q99_O^BPb?q9+|2 zG3Jz-tn;QCY%pP|7`V5)L>d#R3)5RdcF2rVFZl6K8O+nm=RJTl)0TygoPX}}6e z7=33@FIuTi8m#Fo4UXz-JP$Y$h!UIibREw1_cDfW5gt?VzBJB6{T zz0QlX0l0%)2+vYX1G7$$PH!4$dt_K1wgtd@K+srb`kNZm{?Vuz)u(EtildQ&RDhJ= zJ=fWJ_R8LVU7@OvIpj<-Myyw}X%&1ux!=Uv?7Z=5#c3Yt>YKu_QOS1!+Q?;)Sys~+ zT8nLqS3NM$&@1x(YX?|Bb_0K?Uqz8iGpSo^VVyTx^fp@WzB(g+KuP4tYTCD0yol#{ip$Dc$V7(=`3RA8ijRu;HIX`=^gaVOLR{eG(b@r?M@VAi2@B7MZlq*9nc7yAWzsuEFq@Y z5a-7|x<_&qKjJ6K%)qnA&mD;LwSo-h3Y>5*Z^d=p=-GVP7;u4;k^*`xlo|0c8rb8z0ewiAD;3Mf;^M2G9iW40_DaEM4jHgSoLr+bX7=SOI! zaR4ctA*%A<6)Hh@6b_)M*EDt`vnKH35v-%n_PS7#HiJ?e=i9Q{BTq%!?wMnw8Xrfr zK`ZaGlXUA2z-$-DZ*n9{tzI~SEKuFY_#kG#YAFIX2-EW9uIbY02?7fOmQzrRFH&j|x|~EKlRah%)`% zTWM%=V{i9Z&vU6t@W1%_2F6gMCCS*fZQHh!8{0N-Y}>YN^TxJq+s@7Ay_wzF_hxqg z!s+ij)u+0;YS(xV&qS-Mhx1Q;i3XtjFc&uBNRx`+*p=Yv#NBpix0-*b`;;S&1UJS8 zbz{|{80?gMZmr&$zIH8lievai{^Vu!`iJfx=*UMK>=u{6J+ejfgE&TY7_H}&_^Okc z#Jd*Wzim2V#<#&tif+#*W2-k?m$SsEA1TIFjxdQt&=)Elvvl2ODTEEb@u#Ur--_B> z;{e+r$yqq3m?)0!WX6LFs{kaF%a9E<0xaRxd!p9WR=P8<&P4r+2eSl+5&5*YZc;H9`b!x7?=b|CISeHUD(d-UhcdYj{>p5(YYbk$#Od!_F)< z5x_Lvhi|L;_`a1!)?y*wbf2icDU`No&XXeosafmmVjcl6mB8Anr~X{ja)1w@a^4wEF{0;as3NR>0QC zwgxVI+1^ha=iow1Q#L#qRfneirCN|nSG1&9pA2Xk-`+r@Nrne6#H6MX25f-$9exLK z!vd~%-Pg+XpJjN>4yQdnV{WE9S)s>3!ITWF^RuHZ3dFV$!@>k$3C{I451FKUQ20DZ z5a4K`-eg*w*P|_Nud^^6(n~j`YbygrDK$6`CFq_gLcO8LUs!XjTChZOdC&Y9`*y#D zxPGQd9@Gpl~XsbHU+#)A0OhSgT94Du02{?mC@W7(I2P$Gp<|=uQ7TZwqFb;y$sS%;27s@Y9Ae-_H z*XE=hp~UErvcN>8)1fzzmpfY-a8-4}#BNwKGJMfEEPcjT8jKS6+DLD4!XqxJU*}wR z{2NRNL(!)G@T=?7b^Qbln|mFkRb@UwnDd4Vn#QmuBI5dOa@6N%HZf%&jkF9E!d0^o zqlE&2Xx*kK%GffU>@s5rzL}>ZCZ5=5>M2*bGzTe!`wkRu(?;f!b|PVGJfa)y8V zJmdeXie4AUS-1lFM@9c*4@dgn2`D9tf8>)2+S^uQ^zAq0^IV6G%g&|R(O7Brp`Lv`u zRhAKIeKKj``@^S;RPX!8yMvXs*QG2(3%7{Dp!o99unZ^3d6`M34g&jh2+{dZu4Bh( zG7vBbR7ZE%!8PyimP1W!hNrsw)c`Q|6q>e)`Lhq0H?8y_94gl&*TK^nes~ ziaps$;u_UGh9PR3Jj4lG`)#&`7i71lk}& zR3mE~{s<9|)O@wd>d+m*HPg%ICJPItogPnFzGBF1n+f~ikR+Mx2+5x6>8~;JaAlU5 zKc=_#sY9sAJ0xxTmKbqr{ilk$eUW6GxLs@@$r67QQKtxFz~J$mM}ZyV!?7i@5+*fZ zHse5*oEYP|_#Fl)^2dS>!#fAq>((R8pE2G(A73#j-D!jz`!5?089p-%?!$+mlr)7X zWTZ_QuBbclEEoxc312`KPGKOUrRwj{zQ2W>^r?x}ya3H>6Pfxut<0(qw{GViw zG1E@Lq06Atl79hoy~~$6#hHGBSpxfuLmkU=mfXjW`+++?ns8u!`LOZul7-4<++D)gW#+L>JO8T3`pVQkQ$Q`|00%YcN1U4@`$sxEQjLgQS|Y*4P$Ca4Jz3(}sYaFS1C9a#Bh*(PK!jN| z>#ffWqTHP~4bR$Y_l$yct#1#UFSQQ0TItl}3nYcC80La4>lvko0)@(QsFo>%Qs z%-=AWgyOzjI_8x=lKrn>L; z5F}X*6DzS1DfVUC{PQMHv_HXXBG{8N15s6b}d!N zY{k2F8OqIGR=S5j(Xz|pVzdLRD*6lE?aNInbuL2_CK_bD znN3Pd`z=5_Osm;qs~&Z?uXF~R^tYz*P1WnmZG{t;9ZQZC?92*1oxii`UJn6t!N8J2 zwTVzl5wQKQ`Gd&K@Mk(h$2H+ovRPt{V+5^G!>ri%aY-bb$twXKG85mLNh z&wHOL*Kw0R&OzU56oFZa{m6*@R?XlW(rDs}81Yg>ypSHpx90igg_En1M#%ZY+U`2A z-V#n}Kk1nWIh1vJTWQm0TNTY10EP!)6hPDjUrwjow5|O{j3Bu$t?qayS81?g>0|kI zVn(Dn@r+6ld}eBdhl;RbWmo$n`Soer)VvTYZpPbCKCxkbW;m}oKzk&Hu*x=ULb{gR zb=@?Hm77!f7p56smT$vhnk`uhQeWsT1lE${=>GDx@|szb3|>i$n_LS-=mcnL2to-o zvY~@r00#O(jqZUkZ4<&u?grJz90P96FN#(6r@#8nmJIxp>&+TNvt8WM4%N|KCedQh ztpR|$+yrbE$5kR$_iEJkNKVgmC+6G7$U z_HrRpT->B}dA$FAjwRxvw#(tV&QhEcfsAy{JJ>knqpPCR1nN8pjVLw`3pD2_}lixsaEcL{==<+HT+U^fZ4D&=II= zpy6f1h}6JDEW8nE0E#uM%Y~R&YbscE!(g)LVpy*hEInh`U^np@sz*mr=j|Naf!po1 z4F28l`-?SYGuyERynO3n1g{Q$aq&Cwqwg+YmlycHkTbI9%znVe9ydZQ>g(Ho0@v?1 zM+unVOECZ6WoR-s``DN5-}PScy>j-Q8WfOxJON_LsH2g&GOY=8)8!e`5oHYyga zPbJ;zxe+|+05ud$G0%*m{j&|-dX)5?e4Z#&kEy1l{I@W=AudA>7ejA&tn0KWufmoO zu~gH=e_LxOecdg#JK4|`jh<%;As8M|h`gU#ZO;^1tzyzLzOWaxg`4zb+pZZnnq<9Y zLtA3|*w%%N-*LdPgQGyUDaC5rE%lUyLrQoO$64R~iU1Lh8lFfQp;e~K6O&7p)P)iN zfV>6OrV?!?G;$eGpX!juk-BFHo)2qx^ZlvMy|=JPZrydJK@Wu+1s(3+X7&4-d zfvf#lXhEn=w2Ufzg304G@=NkqoRi$49q43Zs&*5R?W-}PL)U0Vh~J{^O{kGs z(YNv7Y5jddvQ=>{H66md9{W{0s~0E4+#9nkf^*xwi`wBWRaSIr{bfqVI|P$0FXTEM zHmU>f{&q@P0cgt(dWJZB&z1=C@m#3y*a?n@<&lHMppI9NHig96Vow63zDTo5cMkObAIS6srv@72{ zitF7}XZ*r7l~G^S-sY#X@2HbW>af>FwWLU=X4!>2Po}E|rpa`#( zW%FL^G!kJvQ%^`e)$gN(MX_0|j&(YklLzdtcHcYA*L zdHGVowv0ecx~}`Y)vIpBvvP~za^Fd_;-R}Ic~c=a;R=m9u$|E7#}LM~NnKiA>DJ7C zbg*whBXUkuuHXx_Zvr`(s7^ zRZPTLdiMF48`nDwI;V7o2myXCToSozZ-FhTWJV2!XCcW;dALVOyA^PPC?hQBfUw>- z;IcZ#9`%(H%c#U3Hlr#4OTdwF0RimDDY-$a+Yaie8O5Q7Cbrpb9*d&=aL{Gp18!b* z&syuI?9;H8<9$wCRHEjj4sP2Tgi{w-z=Rsx;CGxVB3?hI;1dzsN#N@$HH4JgkjK@+ zPoTozOT$K|jkkZBHjl7Nx{8AV03@LU01*H8X8$K<-q6nJpJF;;11FRJX!X^9v~+9; z-YGpmbJE3w1CQ+)&O{rQ=gY12*^hI;@zT(YkaYkQ8aDSgTROU=zha0x7ff-aN&Ex1 z8avHWr;Xj{Zv=wKU>9j%Q|Q8q@n1furlOwq8?{FXUZ^0EoLoyEb?l*_C5B^pM&#>Y z`?(zBriuekoobTd>E1qIIedfk>?bx>YCray1t7?cQ7CJpQo4N>ns0w$v7w?X$!;U29`?X|EIXhJ0>Rf)1HNgDEk!-I3F z$*DF56-mR>0Q-*M_IVJu!(e1m{OSmZAG=IYGSc#sC)yF`17?RK)k~;;%@ZZ$GIJQH zyaMXXe!noiI2jE^OAQ&=HdEtwU75Yn{33k6=}IQVOOiMlEbY%-mvg(#BPL%iN5zN) zQ53)$jGvp9et&lTvolepDFH8m?}!+oj<~b3oxm?%ns{-s@i4Zg+_k|&v3n56eS5+b zyl378Trmpf;BmJ%@CaoPVYRO2h0PX9AO;+ONG-&r`)4KQigcv8S>IF!NbzA9nH{oQ zQ()wPP0UK;kNDY&a1Xqb4De4oF*7EG0jqT#=@b~|L)ZO!MSR>42Ezf@1S*5z1q5>x zhs%nTT$EiqcUJo~d{wE<&7?g^Vev))?tAQ)0=^HV(MT0wC<;<9!e2*p z?3h1Gjm$hKww~|L1c(ASDOrJiQAbwSl@zlmB+5w!fv<$ZXcF^eL-o0tL8?mVJ*v?l z8m3SmN7M+GTWm4i?*h-+hULpPBlJEvDq&4R-#fhRPsvfSwt zR>zt>28w*>E0o>Y9rXWBV~tuIVJ0@V?j?;d`8sIpXw=EGirpvnPFpk4K`o!20;kfzA=I3M^V{Cj zjWzqz$CHhh@6C;kia{!*F5HaP7EW{PLVqeP@Vu@21-_;?|CKWX3Cu37y#xLlp6d>8 ze)51o(a`aA8zzE{10&j#KBNoRjHkrA5hwk0c7O3lsP9nXS=(aS;nR_t&tZfb(Eu{R zO!+L?uyI7V+&EBAt?xd*8E~(nrw- zMm9%;LysdX0AR+o_nKWn<%C)fN9f%?O4JT=-5J!z6M_0{Gh@hpo^CTVlqNpngI2d% z<}dKE?Uc3gaR1cWqVo2Eb5yoFbd`H5g&yW3ypA1=>}^GQEe2N@-8p%hjB>%!q?#sQ zg~wQp;nBy@b|IBI&!~My^Wf=J4d1oRw9RKYZe^!9j1)H5!E(mQV~E-EDxRXivEAv5 zyqk{bK4{fC#rriA?Zh^(YHoEy7K3sz_E9CBZC`+&d1%aTEVJOs9gHfBn7WY{-jZ89 z6->+x%qPq~MkBi$OS%^1TM^GTt3Dqq>!0|{X3oHFY;W-xmcBgOJNi>@>a7YNYMbts zd>0fp$M)C2=tVxajCbb6-yzkNR4={gYD@jOtR`DQhWXxtCR6sC_*=Y!Kfwj~-^Mvd>7DF2GV-X2h05 zy4()(N7v(5Hx;pVpOm|#hh7`QU#wprid9dhy_!1*tu)g~y5Cmc|3*4#F&2~b{X`Pz zf&&0h{eN*t!Tbk^6kTj>f6^!ZA?@B$*>GHEK=_e%8{*4`AmR(mLrQ834cPRaQ4?Pd zmBpK=B}k^peRor*qolH&nUv6*fW;N_c8Z(P*SNj+It4Y+q^YA{&eg%Telehks#rqj zzQ#1JLyZ}yp9mdUM{y^8u}`1jyG#gI2bo|`L3`0W0cT#!8(O|;8h*28f<){5?6gLX z#lmPbAAvQ3alBZ8pMQrmH$H^%GwCi$y;(g?PYZDb7E=TrVp&7}j#O}nj^L5Bl|f%_ z2BnjQB#H0`iYAPXZbYR*rfiiUu+7GAtw+|FB2|w7ZD~Q zDe$Y*q;}#s4OZz+A+iY=5MR8Q--UGOC6A&AvN41K@A!!6Pn5%UWI z7fkLwZ>}f7Q=&a-xH2}^%8^C~EC=})m61#Kx*~Jz9e=9xI5d5eudO%IiCA%0K?QLH zCQf8T-;+L9Hfa*PLUWRifCa*9c_d}_lypAL`77nnc!Z)L;eEA>MCZ~`VSsseDEy1E zChkn7cmd1WM|;>@d`Rh5{v?QhIW^b)OwsuY!|P6y1@pWQ!e_#QgDC@s&1f-0uZwQy zI+!N=Wfq)>dERnKIed!5S8}Xe&_JtA$Z*yxPHP^OM+ad=A%;O9v7TlT| zw7Xqf)^Izq7i1{RFxkUCbac7ZVbNPQHy(8uqtN02*o+cayJ)KWS`@a7o?I8Lz+&h` zj`r-WDzF2$_^RX9K$9*_vOrO!9cOqzbLBQr9eaG-0M{&{Xobt8rA+9TZ%)9KM7;sK ze`R0Sjt}?X;Q;^?`Tj>g&;P3-`>*YWD=izR4K}2|*56RdFNBJPM(=Fh>0Pq88&_|1 z^~~{^)869>B*uF}h&%yJ)xYm|Zq`5r0#Hb)E!NLiQ`1ROAZXA!XZSjy`$e<5qHBvJ z9;p-`RGf_pM74Rjc$6!JQj=d@y>P`{iW^R=5=^wu?&ppRPsWvj^=1xdThn_w6yH=H zwRI<~SDZfSCj=6?)Kr=%4wAd(jy6seLn7gLyhvrULA5MeC{9Y$#}&oEu$iG)6bs!aOj-vkSTs_Yh&Z;^`QWe)RT0~)z)!+F0EJ*C4 zgX&yrlcqULn$l4xT(nCuJwjTdB1LC!?!f&m>G174mZ?xusac^(Yu%tZslb6DrL`Bq zC1-q|E{YZ!X3{tcUM~WKAcsvaZm~9B9Lk-lm1rxBry1WQi^e@jfn}Iesh97nV@FI+ zL@)gA4RS28oajL|h;B$x$3TE&8V#YXE6NX+nn|D@#pDKxm!cM@*tLoS_2ojLo|78%V>i#MULL*?Z6rJ zXnn3l&X>hzjSv$YJVgLp-3I0vOxQqm$Q0$blCV#RY#7kcna7X zpzI)FF(Bt?mWeeXJ&n3*HFn*@&F6YFVokFYrPweUwtxR`{AHB(F372&jy?#^HSj%- zr$Ax}ARRS^5Sfu>YjFQPITD;^MNWsX198>W(1)}tNVn#`Nj?L8X=X&z@(UOqY7I>b z4Gm2E=~qdhSXO{R<4N6-(_q+JKlax6=Gksfwg!igs&Bf3OF2~Qui&T382q6Ocqm|1o0N^pR@7g1T_&p=oz z0Q6%u4}eynjSBtrpd|qXFIC5^WxZ%uY(w)7FlOTWlR)XXPjevk*+DB%=SQW6-80(= z1WsNu)?O0?0uZz=*0IL=TOVhOnfl0vfOApLLd~r3trh?uZH_0pbf-u|iHo@gbPrHQ z=i@#Ti<^|ykWwL;CG)IAD>kn`w`%Gi?9-E>9)gU1&K%3d9m4v&;ALLS5+ZL93^1UuxH*jVamU zWu1|~(j=}Fe&|x0ZP_Rx@)LD|@{bAj{yh>!D9>gO?1eZg^A1+D*^%#-lpIzSSXhj7fA|D(gY$p|51ZP<&6&L&q$1mX+ zr#Ck|9n76|h=gp!>K1xQY#lj!z#PdDC(_a#PFn>Ss|-r1SzSWz7Q2^8d8c`XlM4&H z;Ri%HJ`~?^D8#;XGKbM3NCN3knwKKa%CfHmdck;8ByW#aFE%3N4ye$s-v)t_x+V;! z4CMGE3`JCaBiF(v*6vQ?zZp94?ClSdqCG3x#93uCm}b?af^~V#XrbD#(f>UP$|tCsXFu{IMXr{9M6a)m!7=R$w{T^lr6Kkx2V=tO zVkjWG>z=YkoBqozRG@23=rPRpNKozG(0&lurF zBGctBYR4oX(t&@3Mbeh!h#GX#&9)vd;IfR9#&uuY?j?n*O$Juk_+YucO9lkg`Gl>8 z#{LY6M8KCfes6PFvOhZpw#u)`U@A>Y<20z=EJ3i#*vo&YidL)HFXQdw+NmRGwSbYf ze%oVPP1|_%Cj`G+3NhC^FlDFJYl3r84Jiq1acZ0~sSz z&laUEPnn=S7=ebe$ZP&J|4`n{@wJOBT@hsyz8Xd)#VbzP^US0{3XR4-h82IOqjZkb z`5yCTLRYJtGvK;R9|^mj5ma3j|8+2>b0Y6+0odFOnrQ{QJ|=wmYvw0BA+u9geS;5? zUXK3T$Kl@ed8RSdj!xbz)w~|=^%8ke^t&Lt^t-U};fDS+9lZvI^<}e;$D!JH(TDwb zY_S%%Y^d#P+tP7&m{=73_aO^Mc-n8}tcW=)I5@uPdlzTL)b8_q$+uhDE--GEDP?%@ z!jG*72un(Ms@JKC5}Bv8isRB65nrOubnhfW{a0QKWIA+4PL+JZ|~} z%=Ib;kv3Cb@@gol*WSMjc>kmh`Y_VYl2)p8-{X7Ue+;~65pzh}EV>T8ErV`8bfWRHjP873lA2$PV3w*wvRlQo z1791U#mX}Lc-{ju?KIQQDOxeaHfsVY%4gQpMV#Ji^tTrRcM@jaIG=`xjZw&oqf-nm zYD3H%I*Ox%+ZA@i!exsQ3ITZnE~LMMD5>Sry1*Z5vjLNM%#q202X5-^!8XJE&4+J- zJvXSShsY(H$3#JFxCD7CDXMrp-K5QQon^*nS;4(B8ti*|TEyN{O4V%fwxPXq_*Y>I z|AXyml0k_TBvdyqS2WP6a*rhpklS%pxl0WwBdkZoW(yRvXiDj&;R4cXqE_YfVO32s zQ&d^Y-5m(GX74Bd4U-q^ST3Q}4ydt|UKR*?dzrKA=&oYS`6{#EqmbJX=f(@k-n?!0 z;F_ZI0r0%|QB3%fx<6Evo4qS>%Ul7RndRQ7s4>6l1Mt%GTGzqH>)A%mAdtU_u9jo4 zCzr_Koqf{Rc7GEhfXw+X0?itvdh2yIBlnsd9Im_E0-$?$_a${*YdLN}tHVey6n2%v z?b+-wId+P$!VW)EE4Y&DW+J)sS^iY?$08PYWHey2P4^uk=m_ZnAlih>ceUb6LOlQX z5}=S5s1SY!D#X+4lr-r_M0egx8&kBHjqlg=HprXF?d)L(C+*#S?vNN4m36Gt-!j!L z8$z+m*}M1Co)5~3CKXq4$rVsdhChvDvy z=`mxz0vl;|hPesx#1pl9xzjeicoyFebgozOaxJ&s2Sh%@w|c1!VX4}cUdp4703(x{ zQ8HGYo!?M(kEXQT`XY7>xB^0ftusoru;8fOXE>mmUo{Mykd$Q+Mg4*^;Xp<_1RK*k znciACuT@4l{0>yFzTzKN$OAQGG!h8-<=k6r2Zg0ExEt?NiW2ymH}QgO3hjDSXIF}+ z46a>aiN)jf5Z_TPz{XV- z5KTUGc7jZ>ds?_erb$U5ho4@72v?QGgpj<5Bk1(HIB%TYW{s)hBc*@WI(ZX^?Ld1w zJL4OUJ&~Vdq6P_UxM)YgR{L{;Y;(?rgmZ@2Rx=D+IvD5NMO|Zt-+`yy0#P0Vt1fAE zeb4858Z9GPJ-hP^Tsx55q)%z2I!eaS`)FFJTXxKDTQpQR9gxYc_KlR6)-xNv)P>lWC5~ck4lK818?i6c^l1r`3UxHZFaB0P76c^821=I2^26d{k%6)|h*5 zdwm>7vg_G2+RegU+o}C+7C~Y*UwKHR72E1wu4C*5n6$9wo#q`BSTkC>yy<8^=g>c%9qc-}TMii4;c?O07Q@R_dU^CKtuK+-+4t{^ z;B^2|sE)AQDu&m13eJb=mR4P{1f$f`EM$s0@`EI@5Xey7P8o+U+Hbo%AW7 zh8bJFZ;R5LHY1%jfaN)$Ko0B?7iUFuODG^+ihwI*D-6I~Mmi0Z4f84B)@zwsOs2rF zOyT4fQikmeoS!%elc#XM2fSE@BC!PnlH>xu&H_=yOcy#vj?w)LDV96YOYT6+*MI2) zyQ=ULA=ArodfNL7FcU2f$57Pb(%nzG4z2(>z`QYv2vj>3ofnVc&Nk{wO;O4eCY{^hAup#i7hGv@@_aZh z;e$iI`(%Jce0nq}H2SDEo#YI+{(CSa!L1>aHNdQv79y_diHQ`OeMv=faRyU88seJb=dC}?^3 zlMWU=DDe832qL5ZgcTiAWojcvMp`P2z)l|Bv_R($3^-^Vi%6F!|!rwxG~RuZy+ z=-nOms@*Y*d_df2tLNY2R#LjWzWe)TTMn~-2PWw#w$o@POENlA6oeu7mN>D;G+=S_ zaT%j#xo=EenYfsuU+|E-I{~^icH;s}2x`UNowKF@2BH}Irw}|t?I=Onk=j4wCV9jJ zUU6YJAM+m2QFe-3a6aNfVc4j=x}XnpNEGKe3_fe*rp9r-ozi z|GXhNEg3lutc^3-N2>IcKv&@RJcq}G94FL)W%n{?_|!SA3_nGfdbW=AuD|EsbRzNd zlxbd=%@#@mt+6r5yc}5H|dSew077^8a9&^K(}@JN<72{Kp;jpZ?ft zKZ;&91Rpftp$z$^qx?+1VO6q02A)$Z%O}yKFd#Dr&UgBKnGGgG#!SFqU9aqA)N4M+_u*|G?{9f2|MW#bDWz0+BHOe zMEsHQA*2qk-?o$HZu#TboRmQy_lUV*&ceaP0kI3fcPo^#P7(435Mt>*jZAC|$pn1i z7bvR&V=inAG&C83xvTjw50N4~oL-K)VhopzVLmXPRE|PNvX(-car^2=35N<*Xe$Ht z_>!|^N{UJ&0_eL~vG}*|m%@@X3_?Pd1#GEn)UE;y)@$~jNreG1!z($2STd4TRH!}1 z;7<5VK;!^bmT{z4liEyRG6>{)Ms2PWW$nB=+Cq0!C-`)k79Y}*^6#Optw&*r zfLWzPF1nAWjXn|Tv+i+HBO?B(tSdl7P=ks!Nm!JEPgj?Y*X%fMadd()Sa!@hugW@Gar7J z718ZM2OyfCKNLHTMcNb5wQ^Xv7sak+lwqzA7x&Pc6FN}aPLiGSg=+gkIML~S(oNXYx~u(eJlo*ZTGrAm>x^|f$7_hciVdVXgZ7bHsM0hk9LcNCOruFO??_Fk zpUm>!nYVhA-!V&%gJk_5X!7NNnJU|Q0nC!A$Oj;r;ie{kdz8qbzP1K$n(y18$0k}f zzcmVHxEAQxW0_i#kgAhwQd_R!SKlxv&WLWn3izLLwx79{(G_3dK`}hi-PUaD=NeaH zoR$gl=EQCL8M~W@cHARMS5{8U8qfAG&+k7zA0N~nN4{$qOGYi5p1##z-I9+-up6!H zS|5+AJW42#G)^dKa&e8eP&`ds5~FtsU(x^dCRDp$jaB$BrEqaT35P5@T@wP5+9Lg zFf5f%&lN%dqD^Cb<=T-(`HC4TT?q&!>Ffo6~$qAM$a+zPhE6zoMew z{ad3^a<6Q!_>{;Hj91zV*%$T_e&XrJEKp5ZH zAn16a8&nK>X&%TGLajLThzO545rUK#md1D$Y8n- zFDHT|Ef+j-3$&iPg0Xj8+YK*tCFwmI6U&SE=<`uLDgh}@7zedAP>g$yP&SaU3Bzz| zQp2-utL}IEaozf}{Ck2$m}Z(JGShY6LSlOv#hNl};Eb5@wzs?)psnRZv=}dvu(3M# ztjH9^A`aB$d=2GMAep@<1pe{XN!UY0hSXD~kpxhI;UgZ17khegl1-&=icK*ZdA|~n zzU6>Hv2HbhgxoL+90?SlTM)*ypnOP8er4rM zuw*r;k3r`8IUx5L=9?_i>&qu1BzfDMq*ZHU~P;m_3zM0jw;G5cGoA_K^z5GDfv-FwO9y&W~8#;&$9 zaChtM1~?ycEQyrs%q6~MBNjs?{G@6`KQm$%V#Z$h;~E}CoF6Oo8-uNjsnEFVDX;Yl zTJhcpA%x@f7Jzvl0Ef4KjFC`gUl4D%jwpinT$G=GSo;o?xm`*x%Xio*K3shwsTzpa zEZo>Q6Ej;Nu7-vC`w)8kTo#fhFRb;RkWn2=@G&AG4GzP)U|zE`sc(^`_43j5lW`*p ze&C^(E;6P3eu&frtt#>YQ9T>D0*ps-^7Wj#1V@ zKQljRuq6Kq#HW+RH4`@;SfO+iH0K1@00?I@{VYnbR#(&lW1SLD)li&v)>{yzG`#VX zLl0dC$Suq_c?{=ia?>E0g!U#400(0@pK~#nuKFJNkD@ zY?@Mvox*4Yaa#24393^^Z)nODAe)irn7C&dAd#H;+SPo@vWuR(IQ_5Yh+p6m{AscL zwd%{je@xi&f30>IEKY0YO*W`tn_f}goswFrHD6pad>7{;0vv(oy!wgv0TE$Wp;D*# zHXkcyn)wZS)#v=?H_0}(=I4>bGvx?DHcJASVr>lURwy5GA2rIO;njir;s(ZcZAS2| zG{z#XXJ9_9?$c#2?EZ_>b~5MT+a`Ygee#FljuH`Zmbh>lK7APWb?2<^?$+9^{}n|w zWy;UAB;q(}5i)HhBmc|*VpSg5Wp)R*Dr<1!9`&um3bH2V;{3g!Ah)L?j_5-TnV|Zp ze_9R-9XnfwW3?d{+I@U8$XHPwQB@( zjC@~eCXl}$irQgJ6)DiDXZL7fEK%X=M~ht<3`vl3-AR&cl9|S`d0A9)CpDupgqdo9 z6cBohxb5_&77)L1NGKpd(h3)4l!;ibYYDtQNMxy=;j?HFJhX(4?J1>{@kmdFl}*Wo zObh&e=2H}C)~xUZ8oyvfMfs$iwhebwT_j&hE!~V?H!(k!v9z&q_4uuX@p*`?hyxH+ z%20i_<8`luz3$Vk)@Evus$(mclZw_o8CvRm(FVs`F0JBlW0bVkC?2C1B_BCeVU7IR zB_J%VdNYPXKD*YM_`nu=6z9=38~e9^)smM993e<=u|y+DL`OD7+1-AZG|3QYS8@J^%7}EVIAud^68eoSK4ey&|L#xJ zA?QP$^F@RADO!2nDiU~8Su7ElStgf^n5gszhByc6F9NPlHW;A@X2?nB1vFU6+yO{4 zjA%cZcIIOLF?=bz661jd1abj3EGDgQ_gufY_E0NAr_w6w8(@M$@-8S&;XDPSDNu>sG5gI>6HuQu2JpM_7aold{+TYt*i>lAIY~sRaesZ_G`Nvy^V8S}D)~KW=%b zKA~&_s+jnNS=%6Lz$1!)d4ih{(htCOAZ z(m{%O1&@78Px_{W5aW~FOI_6FW?#L@3XnxGpa^!FOIS`Il3&p|a^m9*G7P2C!*J|jSqs1+aNzJ|hjGvnm4Y2< zewb?;l(lStu{TOy=dZ}rU|}O zga(Nhsr%FOXVC^dU_HzmaiCP2?TyrdC=C&o41vsIHOOw*UYDYx0I0#uRMRy_9K0{@ zHv%CB3F&Hi8ur*}>~Fy+r511~a55$$XLtpKmA;`bz&=9}&8+m(LQ=b<(A5`$etzHj zcWnA@!?$+E@LnC*?j37Fv{}C!-~2kZS}tCkO-GU@NEQ$G!DuhcNTqgy6G@ZD=5lL1 z4^8A0G`r3J)!12wMY(l25D&|q&tW1?(XjHZlt9dKvKGql929B0SW1l5CPxu z_;@@b=ltG#u8WyJ*q^<2uDS2o-?d`j94-0+v&3-WZ#eChpQnzv_V~oBtnPD2q!3po z`Fl)Ix4D~ct73Jv>t>ki>l<79lZ4ig0mW$(7x@L9&WuOxo^owA;Ns}$U8sh51T)9|~-SBuss_}XOqjGpV z+`~eT8NiYa*io<%-~|#lh$0QxrYv!apk{^zrhramam71XMzwFoqpUbri=J)Qosai-V>a+u9 zgYeYx$2=8OuTj*Nt^IK~Q%K!JzX=)=U89jI-rA_T=%Uczo+UgYlK@R=Gh^WzHH0pV zrsoEB6@#YPD@6tZsc?81ic?)BDv_$wPI3msDL^b~=?NvyT3+lF9jGT11PipG0U6L3 zr7M2U1(ISHi?$l|9SMWlS)EgSoAAA*WQcTDO<6`3G~|ISwTp+?Wo)E^?{}h0lEG-@xod~ zsCuk&p5D_P8jQ?Sa2PNm1-JZ(0;B;<=9ayvSx>k=xAufK$tC9;RetnaU$_f5CQNGe zhM|s!Ni%p)sr2=UnqB!zLw@+t{5mIpTL)oq!1+Ye(`>K$7y3ChmK zWw$@EmG8xQ+iKrf1_F=YifC8$#ThiSU(FiT> zajaI3?VI4Do%#k1C$1(0PmHD(@i~t84%fdYfTXanM!}5kcyp*Esr*&) zB#gEfPt3n`g+tucM$!x zt8;kg=9*{6sNu^wJxQ#(i2%l;d+$ca@^s$p##_KsB{)f52iOq>V>&Jg`|!aHxfHZ- z44u^o?(?>dF1@yR-d}@OXQYS_x~vRa1WX-iodj&4JgxkDd>^^1G@OX z?n>m`oy=@)6y0r{^xgh?^f?T=DZyhy{(dx5g;1kOe#TaOaxS@|I zF0N7g<25A)5zc5*-AeJqN+)WJ$b=ovwHGjiU6jTrUg%;h7`%`Hl$jA9WvDy7+-a1k zz0fhFQ>8E@pCCIVVpEVP(~&0#7pX-l<_O2PP|40G(y*eD7`26wJ`(_IN%({gz@+^2 zhV7Vt(d}j5p83FaLO4Ex?Tf7qJfG-@5pIq&ch`aRC`G~$(CyS@v~n5i$*KB`D)iAYqkUkP(G&D>b00s8H|rA3 zja9P6{KO0|pQ8~(^=+rhCM-eK>hUlR1Jz^4%A}5?aN<>;H@?`Itl~f%=Z(}?Wte5f z__F%YfquhR(Jwo<&6y`>Olv3~Bbr7DdGvvzEr3T*NtsZZg3XXAy*Bhz479e|l59p4 zgJsYnGWj4IW@1Qp@qTLykkO~9M3|~t-0=KZt`cCuVfeRz~+vHgMea7FbNL>f1<~ufqC4E-ulvvhfeg{ zC4zyz$%3=wp)8*;AFp2P7b~*(Wciw&452y(;T%w!EI7!@#?mCz95ZfNM^c+WbvWo= z@?Kn%!(raxSnPT*2s}K8iTsKK7j_f~izSAxyy4C%yzCEz!q}up0gJQ>3y)1d5OCn+ zpaLyv`T0nm57c-tOBc$Mu|dtlVnS7pLSihxfO|QMXuv5Ms5HP44&*Qxt`R=gD2w|TJxxuwsjwl;aqmS_q43#4Qo+TNq5%eYqKnPn%<#m*O&1-uAw!vJs9}($Sca7JNMw9d zQ#)h1wx%<4N>?xU{3Z~V@7Z#AC0H?!Z>?! z$B68(`FbxBy3i~{lRj*|((gDA6?aaIAZV=ohNwar7KHVh<$E(xI0!OD@sH=oP+2&FWQmv|B zI^F=TFQ^PvgJ&jCD~dnFJUq|%6G;eSMyOna8RJ?&+7x&15T*oC;%jht{{*x_`YsAv zzIn|Mlk%4F;@Cls>dR;uNEMh%ksBQ8V_yTM=v8X)N0#uNM4Vru@tn(i|m^TK3U;Ek`rxn9oF zcdL!KjlCOnvx77?k{skz&zBQy4clr?^uQ73wq}$BFQAywfGkSSO$zlP$ETis)vbsb z$0vxRkwzkssuBsE<|>Hh&C`JuQj`R~+n=R6t^29ZXq;M>b?;Q&vvkcp3>I&OK{eVR za%|RjX+=K@-f z6!6R8fhv=u?~2k_Ao(ra<%vV(Z%$){%vcPDnu!4?8}LD_=e24r*3aC#N*k8xF6d{l z$sNb_h&G;~B$_RSYD=+6SWqfPkNYfD5~;*^Y42Bv@`6%E zl+G8tTLK@d969}z&xnGLZZPQ2HihBa3sQRJUL7mO3%kA}eJc}O@R^ES-Csjv z?K)QGgWd5*51EFyZk{T*RdyTJFgXl+QJ%j3XjJ;fbDX$owb<*;&#Rhp_rr-*Iam&Q zJV(It<5^7m*{@0<)+Hmu)ia)dj{ZdXVJ$jKKb1bd7F)x3y?9P^W|6ykEnV|6^Lo<^ zk6}oEfFpI)(iJ<1H`SgbWwt9sO+#e?!m(iVa*d!V{gjx=8xm4lCx*( z9zDSh6j-fh2*dm$|MX_i2^wYk>(vC6Rd5&R8G2$4c4_h+^HYN;eADK5#@$m$u4$~8 zYxMkiye<-{ebUejvvh!4R?0l_ASwRS&Byzre2#Ak;L=$d-tq^{enNk%-;iob^j_!` z(Hk;x_A3|e&DSHzGb$Rpw~FdxN=(WHU`^33n^lfEVhjox6qno1v0ZeZiyLmq*h zLADWZ8{D=pa2R=vBlJyq3p&4-Ld^5Zb`U8o`IpX1q|+Sj9+7rAHKuMKM$rfa7R+*#VgaO*1~teq6rXA;F4>TyeVU_h zzNm?MHKc;_iMF4(RJ9}ZIlt;kdYXuqgoUF*?Ue+h(uS(l^_DlIoA@DS+Ya)`>*0)B z4QR{FR-wIl7r<)(Zo9R0%Y^mLh||1tS@$!QJaHG<=Am>#wj(#8+#&IhH_B)UTQsq) z!SVTA$VO#5RQ+$|U^@&Hsr+Ptgpl)BFchfs9}IMA*YgauM=2kF$g?~{EVXBuRYiKA znC`sJ-VujLvru#@q3d@>rxAQ|1a$vkcwx>DPQ#H0i&3!(!H$idLe&ihZOIaV?NRbmk{y^XGi!5#m~3jy@o{8V++~GjcZU~S+7G~cl^8QIOlIlA7b8*@SRT#s zE)rai%8aKCha8^`l#2Yt3zS{{lz|1)(CbU;zN{-7Jn)F4)>&@ufttzj$JX$iGkGxwZ9+)2EQB4t%bl8wD)QAgV#k&x2HP zm(*)4R!`5&&%XVB*Vi`YH7*9qg)AuiV1R_b?)p?6^^L5}ZKTW%{<`P;ryS4m#Y?=W z%Pw1OWYY98XRot#nUd3e8k_q0$;fia9}$2rsBnEbYG?ryivt>o+Z-MWF}<;V*%8=t zSQDuYM(yU+wH?qy9r=+t^3aKSgS;e4Dw~jCpiHg+lpa`9CKjkPyv>v?YPzn%A9#MW z)?n0A{Pu4*%LOPu^{NA;^`T|&~G(&obP(vC9{Z(@mG zO6dDlAJ4uv=dm`Q%H6RZSZrYEFv`$6Q&eEK-64$Fy1XYov)zZwQJJdXPFZvzC79D z8*>tP9S736Q5C4xA*6QG8U^Eh)5<{4;|<2zbMKKaNb2l?7gYnM4m#jaVjYOHY-vfr z39mHxMA1$oNs}N}D~%qucRMh<*!i7&$KO)k2AoK`(7m`Qp>{mb!6(F=MjzVTI;3?b zFGL)sWCAzQuk)WH3=M@9p|Z6H9QW~y%Av^4cPH|bxp=rRz4B^i=kV>)fzo@NE9$8K z+>Ja$baXaHji9<_(Di6V3q0U9>ULkZ3ue^-bhMo`UPpaoRja+->(<=smZ0{)rBOnTtQ`sh^M8iZKRW&<4j2-ZU7Q;tNS^mRlr#wGuaAxJv_Y%8ZhQ z)Q=URPW~C98%1t~X$Hi*?HnT`yT~T9FZdnc(K$?6fg2Q7%|;0eU2}+15t&9hN+G$X z5KZHZex1q|fUHg7MuL|Hsnh6vy_3v|h(i!AB_iX3lVw8zco2`s{KS=T&nHRYn|k~& zQ3}WXMot2@9gjDnD1a{WcjQqDr8YBnNBxO`~e2GDMU4lniOK)nX!UTxA zaRMs?>;uMcRPY0_dLtD!PhDx|11!y;rHLE)7ZLMudRwal^Ywh?i2R+cc1-Nht1QtW z?$T+JxGA*5J!1$iqWaa@BOB2_V5W_Auv0*{$#U9A*$EINSF<}Pke{wuN!p#}~U?k+y5O)$lr`&T$WRfG% zmxcZ2Yw_)b-|i8!rz2q`&hfF>>M*!o!vUnONOlZA+SvZGKJX{Zt!7?~e z%v1bEhFoRk-t~+dC}2<|Zea>m!d|JaOa*-fkq-V`82TeElN?3VPyiiRlmx68d;0~8 zK5Aa7X461b-gaDf7q0`Wlc89274pW{xa0#fuak?@oiO1GhmK}#C|gmhOm0$E_P`HN zBz%T}g|#t2d|PAc<3P$`2ea%uP7Zf(-Zpl;c1{w1UN+q7Dku{)8CtYUlJcn3?gCmk zyGDeYl=P#dBusq1x)-)wh`XIKMOj-g>MJqyD{ks$7cNLRTgqwg)JWdfSM=1TWe1iD z`OO64&Ny!Aq=izRai}@74Vm|da0ky@h?q!;lM-jp38#}2d9&c}szQVdfYNk&x04}M`ebuv~4 z(c=#_V?;-(GeRR_eI2)(GKZ6#388@Xa&Bw{sk28$MXE#Mcsop6sZ_rT{FEj&_d^y# zSPfR?eyrJWH5LA|K$oQIgBG)?%x%tRP!d?(?KEOQ1t~(_xzE+;&_y@|aekb;0a7Ip zDKKDm#gXcm5Kk7_-=L{Qmc5VF!Dk^t4-~DbO};DPaSNHZu>4f2 z^;z>{(?%_|R$0pM(6JQKXksF_B}K8akmd0%{q#;PC8#+p`na#pcdc+J*(yv}VSQwf zF5!wPI5v92%J>^xK4~1N9q_X#Dz||m8iRx~+s8`eQC@N#67YbYB10Y>!Fv6`Z5^ii zq$OeZZ$`c!ONCbO@$YJ~Q&6$s7zf_RYFKu^SQ{37KKq%MtOyE^} zYC0S-c2=QKqQqlUpsX}0x;R;Mt&ClI5>2OS@%i*(nr>ux%hdxfjf6)OF3c(T+-V$D z_c?K@uKfjlsE3};AYZ{?=33g@dLih(!jQo8vauBNXozoDliyRxtaFE1Iw?Z+&xyp; z2ZbHgRdr)Yxb)FxqRf(Y)qu;5dJ3mK%qj#mNYr}Hd2-D!as>{EM#Mpwmn5-1R=Zf+C7-YuFB|y8u5Ro5e7;`4P1UZch*5|%9zG<}s zhW~P&!R#*J_T2OR5-+{$oGE%D*b;FQB};7>$B55!M|uIsZ_GOf=@H!XWEO8e!c1`K zO*+<09m@NamloG+*vN_2ku3|~CC2lp5mfE+2Gd??7ncNB81=oh$~|IDcEcC?0*2}T zN@O1kiE93lN73?gV&m$q<-3q0* zH6EhKL8D57ICeB>`vW1?RR$IBLczEe<|8Dfm+L$7UM*qSI5!IES#n);O4iS7dU`37 zpEHF(%o6SvTMO`a?=+v3Jc)%ED(CwOmtB*i`^3_`1ZnLK1qT!Na`fYTwp1dZ!m@wD zx-o>ZWgLjmOwQhlS)B6$YU`6rr(P`ST5`K3_ePwO>te8_dG-Zof{a;T0`q}k`BS$> zZ^RV{>#@ww9B+&)*BK9F&Kr9o5RMJ*idT_(D|nVwyh~eE#f!zUfU;#Oh#6<=oi9DN zF`w7A(A8+Hnd2+i!-r>>dMhMl9T1coTG2^mlNrjLaxQ4Lvg(hIxOf8g8OS)Hp@L@W zJCbs&m@$QD`o?=%b(+s3?`jkKwV(=b?sCSC@a5xP>#+(-Z^K*ExvgC{-OOKFZ?}}f zYFVb95HTJHKT#42$tJ(c7$j7?MlD6NuaZtx4qr_{$sxY2hjyJPN&6&ci>I_$-D7}E zatauxGp21EYVa=zfm8Wp&0}EY*#;DNzru}+u%?B>ne0N7AvV){D|4iuek{H3%2`3k z3~!myJ?cD5l0({M5_)Vz2+b7yj#WWcGvM19M2d5N<<-ni~dmpu+sE!wuH(-5U^PqrO^-Ao3A-A zud_Msq{L>$uV5L2wBh^PlMXJr1{z32fVLURV%?E=yqQEHV_zaV ziUsxp*}UFL>pEncn^IH`g;O)GkW6h1k#2y8=U6aB`0A9-v@MEe&MoXJGsBKAR~R>K zugjVd-KtGNvD*NqgwS=IL?6*Upk6pWm2;TMiN-0|t)aU6aLyC&3}#sK95SW_w)e?_ zu#N3)O6%esF<^O%QOZII^ZXb#0z%AvMJWA=l|n*6UR4?q-P1WR;o0{3LJ3ph4?P2F znF4lx7&=qVb_|^rE`?m(MX7XBws?1J(yKW36qB$xFi!

&7{$l5CW8pFMh;3#<*| zuZ{A8{-El4kGeGFO8>AEJaE}A?hZpsbw zW}{&wS@}pnx>KWNpuSuv<3Q$ZZ3W%DVS?rweGPXgpVlkW%4>Tz-EQxf??inYKYd#s z$0U$LAx2y9wjp47XYDBhC~qZ!ysEv_hN+ZE4YBcQ1y`T3Mt@3JgP?4Z&jY_+do5&b zNcWPu#k|wd)mC!ddohcP&#VjBeT`?@`gX(35^4PX9UAkjfzd0lz+5$dD)X2RVuQ_E z=a7?+l7~)!CB_+k(1^lG*pCTZYxMj)aP~b5^bC+H=bu_Aup#SL1lC2tSSKB#&a6UF zOdzxBitgmUVkk}E_D^FD(Ip%szo^d_Va(z2+=jblhCwVdKY`%Qtmz8X|5`S$%S7>^ z&j(i!4hJ7;=^1LJAdc_ZI+rhOa2R0IezsY_S%dDa zXa94mt9`eWE@KD#0%9d#;ds*WYwmi@NnV-RBURa`15CUuTp_9&(Z}=n3N6gxp%b;3 zmX~hn(#5#Iy2T_iZ#Tk|YA-^fW#B5Z{UTijZqMqMoOq{H%G|}pNR=*MJ`X*`tHgcP z)kYn~S2MHxxX|U?WOVx~jpZ*5>b$H`mT;@mWv>EHl`Y~`t;h;#_;$92!p6)_sz+a? z4j-p&lj7{k^to%6i%vSt=6$VmI!$47$y3^<^s!Yr=*W&1vUxowfxPSDyqgK%ItAmH z7m?vqZlz}FBCRh@Sfx-Xz?sSK9j)vk?qq1(UuGBxGEA74Hh- zxC-8+@R8e=^R_izL#YoImJSZ?jjlYs!GcSawn(tjnYewSWlogdmnr!c_ICYg%QJo! z?8X@Pozc(H6eyxpv)aDF?e95Yg{LQu#wC{aUVpl@VmYvzuouOd3aUkjBr|c)|9l9X zGDUtPKR&V;CGJ&ONaU6u5WD1REv=WE4`;`niu zm#!fn_IT6_s0iuyFLe^O<~+>X*+su99309?k2f&54akw)piww|UNv;pRjU9$$tiqc zuH|N*5b>Onur_9m&uv`ogvYbWLrS-u5Lqx9aX~*>V$ZpekK1ptVz%@3*llVs@QUE> zTc_=G7s)XwLKZj#IwU;koH7_#BS_Hn*N6Z80m(W3ccFqE2z>u&Xlo6M?fCB{Ksl5D zcYQBG^1l-12LD|O6bJqvrNsVG%GL2ds{?6G{!!5W_kt$+PX8zj_gCv=nF_D&KT~PM(%J=WW`-A#GBI*aBqu^wb#h_CK z-`kA)lL&gx_opHK1NtNR~LaEo6-gX{#N()>o;0sI&7pF!Uq1Q%0T zLSTWK&j7OX`{9hASH3^3#D9T*D1PrD|6FbuKY3u^7f*=VAIKjv;`{Run1+1?83h?{zK1tum655LcbY71s6~q@t`_>Uxe{m|7PdU*8io(e31GzXXc46 zh$;)Beh(D*^UC*^(fK#(JxSs{?w`H-`)Hr*{=xkrnY-Vq<;+Pua-ePY<>ULKO{w=U zi2t?shwASCv@7O9zyQcjcg0|UR zvt@$T@hQl---qw6>JR7xe*Pim{jAPEo1O2!+WZIeSB~fV?Y*Cy=NCqA_z%pVUj8A= z?neOsg_NHE19{)cKLorV%Jmm;diB46|Mc+>aqmaQ{KZ{a|1a*ZpdR;o^L}WMUqt%T zKZrj({7(nW=%`^IurTFMnWvxYgf$;zP{)D$ZX_uDd^&f4RhecW4js@5>K=@z=jS z%>Uh=J;c0!c=#974HTo|-k$gHQR4d}cK?^@Uq~C=hmrsA2tRCu27L_&1A7j7>4CmG KUs8YfxBm~{RYjrz literal 0 HcmV?d00001 diff --git a/dev/com.ibm.ws.logging.hpel_fat/lib/htmlunit-2.4.jar b/dev/com.ibm.ws.logging.hpel_fat/lib/htmlunit-2.4.jar new file mode 100755 index 0000000000000000000000000000000000000000..8a5bb3cff12521a7b3aff1d1b71a48b6e0af3043 GIT binary patch literal 724012 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"zM z6?q6YvP)3PNgSljNZx16e@LPN-L>7jVo#ulxX_qxP>DsScE=kg6y{|y9uAC2}E z&gqm0am7GIY?p03aJ3OOjV~1a`DD(OWX?~v z7$%)ix6822s$jp^pEGKdhlzN>oUy|-HT{VM+izk=6gRHh>4z3+%Wf}tU|d6+B+shV zy6xaUO9OordpP&K&Ronc;)uwqWA};9T)JAQ;^5X5r9gUCSoe>o|>rJ;O~$odv|w`d{r)C92h8)&_2McbyLms4|f6DPUE}xL68=n%2M-H&b zsP~95#M<-qQRKr#J?gGatElnZN4s}cL>Pcr+~gojioXW3C%&&=so7^$ zn?Khm8I&ztl$iI9tyPe=P1!({EhxG|Ow>P)(o@3^10O>m;fS(R@wNa7i~mZ~nnNG4 zdg2vU$A`P8o{0A0%TeIdY;P`gD6D&Le9P24{WG32yHAEju~Pu#b_5mn z;Eo^LRJ05n7CxwRd$=}sy(Yiq`_~6>hY085S}lQKQXS9l(!A0zPW3AgoP8e>XO*fA z7?zS-?Z@Y7iKQJL*;$0E_gHQ%Q)zShw|f?B5-#nbD@)$XJ0TdUb}(*2mQW2f`%VkyH-guzovARHT`S zfGQxl@vm)e`Gpx0(10f~-tVTZ@{PyJTlPK5MK9u~8qZ~&{&W*SHVq`CMpd8w5ehnP zRas!Ijx9-4@POr9zK#`go5eB9iUG9Nj?#HIM<1M*y--r>)tnk6wJV8RAWX)Y%#=m? zy03AE9M}bg^M`V;+UB*$=>R2ZFozxc*jOlNi?cq4vpqx_4HXbhgUkX=lpMifK}s}$ z+8m5oZips|>qR~))<89)uc3o1NPP-1&K0WB+R+13mF3DO(CIj}6W2HG z;Wqa=989@(3-bOiMTF}>8qe@e;uHuGAwH4*`ZfBn#ann;?j@QPn$SDj=_1NgkOwv0 zDV;OKr8}SH7$z>Lv56qoF@3%QTWvjl;yN@N-QwGQ>F%t(BrMGn<(pEzqJq<)Z&`?m2`N7LN zjogXyS4rK}AUDAk8?A#q$cQU|FbAD|X-=xMUBP)*Z+>)2wG$(A-txW_mgJ=eR;8AQ znIlLIGU&$`oH|S$`fNs_R<;`HE*s71%6X^NX@TZqu!0xeiy>ufOUFEm1C7{O>$x_A zvA5>yD@c3H6)%+9cpin@pE;ltEieWoMC*zRdY7|osd$v$D-} z0`WoHir29VGL>Q3z?Bhg{BD^RQ$sYrq=}1asxwqCz4>=A`W4lbcBPx@UuKHYBHqix zMcETljYoX^0dStJzEzncM4+)mSyqwA7?@seg!FRz3F}lByb~Dq^WNU8R*O&feE6K( zog|y5bGLI#1?hl*J-=Ogg&IJm1jf=5p0B4E?;#sL7f6AtDw0*Pmyt; zL%v1-0s2IN>zEQ39XViT%=1!BZsUFHXzF9_mskP)9d`#>{qfx1F_KmXc2+0$lA1<2 z@w+kTo}31>5>EA$DcXV_=)@02_~S%AP}shzrDU_$)>ogMu3uaNk2~Dvx})+pksRF9 z7t*8{`6OwAM`7?2?wt_epQ|=rFxhVIrdXf0(or7M4V~F>r#F*Y?rvFAXULCGvJqMH zhKiGC?|1!VNaUHI3n-m7(m%O$D-mEHp7fPYG}2C%V(!`E%X*(l&ODd&%!e^)?45XW zB6nN${9dySvUBxRXVBzkRvc29qQi#{8E9u3`E?Dx@9NZ%+u9T})XLKX05cN?r}vE& z3+FGjyANo0^*r+Ax1apF>6SU!93APH-&bU7UhcK&rg!hOu|t-Kmqklu{b(1n{@ha_u-Mypif_RNt4Eab?+s23US{dO^PyvD)pVi+K4F zRYF`|4|m{g1X?T@Y(6kL|F(#)HRxd%@6exfD%;lI$l+UOJ#dM?@$cKfL>5bXgv`LP z;)^>eqolKNMURm9gHdfA?#SMl3b~@Re4$O!RAT(#ygQpt4{Hs6DD`WR;~Ha+v{D=lz*@}aR(mhFqLiVIU~u$btlYc_i{ zSb>PUR*b*M8CzNdPAWH*aM0TolCXKA=r-Vt9Pt%n$F3V})97e1UfKlBCa<0e@l6GD zY@4?xOMnhAz;N#R%u21vGwNWpfTK2PXG=J)U!cq+KmpfEwj*v*V3Z2{&0zg`Gww}w z4g<85G;8}LX3wRs8A@Yb;ggR*nJL9ff>fc?+CzadUtR14J#tTFmFf@dpmq&w#DguKt#q9` zY>8K|*tWjQ4X_uiy&dS3I&J)7)n<#IV9OoDc^{GQSpManRXwwlS#4i?f9Q2&efh12 zR@Y%Aw}n;YI$k24MVE9;Kk+h_NOna_Rw!IBA3H*t0`{S$RRaO4Gtjq!u`8LOStIZ4PbGdVUeBi5r^8pd#$OYITy zEG`kb(JmR>6;SS`BOO6z7{(8zwfG*|{5(+9no zKb^2AM(Lu<)Es^ABkSD`TfBB`T)XvFtm8(uam6aXxnuV9 zzxjNmM|p|yI8Or#2%4^@m>kYn*{M>isRu7Vm^4A(jIEq3{7{8#(u|3K*6nUkXue0-)e+es8^BriO0^WY z80=FC)VhV*@4t8Amd?I8YSx;mV$^b_v}8~lqxCR~T7#3}?Q?`&rf&JO?`+?mtT;Fn zh?WDffOAUOZKZp%_TReU_NEvoO++*OFc5FX=2YfIEN$vsR5CNNz-yD zl(SC|6Lk(9@Js<+=kp?#N)3$>_eho|%!n_Uf=U&aOhz8PYON!!__Y(ltHUo;ZgviQ zAC+RkG+{2syr4TU9t!LY#lBCx~B<7cvyjSn-e9W(#eenF!1c95T>A#Yx^ z5@hMr{k}piJ%fA=fVFw$f$5i6MzFvS9&rpW4KQjQ+yf|}FCv>T>TlE4=~B)?fZJ_R z6QgNw8cYR?XdRlNRpY{6@P&P|SH>8QS4KO)DfsdiLB4ZpR0|_hW`6GW=Zy7L?%^5M zHDQGg;UES|Kt0O@m)UU0lLRe>zc02g0E{Ifs0g~EH*l9+jPs0n_C>_Jg20hgX`Zkn z-f<`o@FYIN1!oICbW&-dGWKcoGi!UP>6CRiW*51cE?=x&ta|q^tp#ymnV4M6&^Z)v zNW&vv>% z-}wS85*)M{Tp(qFgjlR2;DuiqpM(Ld3c3=BjvnX=1fyTdylMD4XaUV)kb;lg;*m1oZt(WntKl}xbZ;0X-JOhRT0(1@Ej77ethl?9 zVdvABp$Ko#8+#*ycVC3aIa;NfHqk*@Hu1@DmzGiDzCc-!eP)#s*V)tvh=7ult_h^VVa0HRin^;8(1XkE_kkY zgjt01Wi=Z9&agYRff{1UdnQV5{lQ#<(-+?07F)$(0&RgeLv^8+u3RO%p#x+{a{QpY zJ&N1dOe0~Tw@%GYPL4&;R+gSF_yR7(DGtZShcd<_*jATEpakib$AR@SClR6@*`4ihk3IjTWW1?JqVaCEw!}7DyqC^;y#6$10g^{nxwPm zrvVacf)IZ!pp$+!w2!Yly&LkYVrVT7=mweD)5#i{x$SdQbd{f*uB4Nng>>9Tt+vZ{ z{GA>IbMIU}L-==RT33CLcyXnpp!?Z0;%%7-=vYZKLY#@DY!OtarzIyycy|E7y~F}_ zKR`iJh`%aUvGa?%@|)i}k6tiqvfe#Od<^nr&-$;++baK5wJjWS%@B;rlod{20IpzA zXjxRf&o-UCtr^(1#f}C{R-}oN_-gn**t+=Le(ZM|HZTw}X}DK-XT|FUc(B-uO*|?U zQRXh^Ic+K{X zMZ_ow<_0Q|bg|U4%GS84z>S0x))`*&bU#CSQ9ovFlW>c+OH|ph7XXSgtXKmwH5JKE z!=MCfQ)Y~cAv`~@?F_9NqbGjEuv}NCW8pz~1J6MC_Yy^(L5h0rChk|D4Vkb0s0bOI z-YxL$!KGF1LNA2_#cvqOw>YyDLx5QKRX0DxrG@RwCYPr0-9w z?>6E-5K#hEOk@3S#g(}I+0Xai2OEysrp!;}Sg(ur{W&ybRQ{X?U zBj)U4-uH8$A?VNL<^4@<6T?_4xw_e!8=10Yhng%(SMtl*Y7CVfc3c@t?ph6S8wq|5 z2jVVL?ija%$7(~^bTw%cjrV$`Is5>#=nfKZSLbFCcHubqRe#S(D|~hB9o#Z1{+$Kv zT1Lr+Kx6Tz&DL!ctWcjGbDil-jW?M(vmW9Nc>&x&I^>I@a6fnN2j)nZR%%Jtc z_;2RC9wXCc-#&Rl)TLBl0;{w%?B>9wkcEi2XVX&=c6MC|C!+9}Qvm_Ny#W*LOejus z;C_M$PHRFT5vYJybl)3BAWT>@{lqUtY&MT@0zCkLEV&eFgTivE1VvC6?heP&2(pk< zEJg`oZihv{=i8nIJ5HyU_GXVW(Q5B zAw*HI)wB)mG|r0I2`#JrRgV!Z5N_wEdnI#oX%$y)o_iKsby@Cj-A-Hc03YjSo=5Rg zB@Dao-E2N_({8oZ5+;obbd$?=dIEoDe7}EhX8A?e{_c-$kKbhH+1loKl=$w~r0!E<2Q7={MAmNj;S|B@5RPu~-Sj3>0srzCVIPa{_V0>t?myd6V50_K0{Z7m`BA~h<^#;MpcC-ZlkNG%Pld(b{gzG4a>fyE3o!U1 za~J9ra#X%l+^#P!aA5IxB0lP#y{`PO?mM3OpUs|TdI&xs^6~P%DTXA=$}?dZ-?@V) z?g3#tW_nyRat$2nkwYgVkuyOR0juu20zE2*V2bDl51)f2j}aoLLlZ;gj5UQe(z27L z`}QRzAeS+!nyF$*m05rdCI}MRS$;o*Jaih`bogbZ!X|4RLXzQE%PhB9kqdQ{jV!07 zO)Q-R-+#8UFEu2MMSaTs+@5U04eUmdTrrobD67H-K8<0pm1cw@&5VE93QLD|{VVEJ zWvX^C?>1Fh_G&P3W+kcsseuONP)C_f(icaybdW5!~RZl5YD zvC3|$(-QZ0neg6l#fbp3qIp{N9ZYTgtRe(V@NqR$8^%02#qTSBmgR|wP~IH?^s|8LAKVj<^*>0!d9{mr zGlQ2eTT~l<;J6+yNsvd^a;2-PXX0tjj^(P@6c7Qn91cmH*$J>(h;w$nrD)2smEW(I zJ%?*BV~BxU`5b0gnat<5u1~8sPQsh}Q)R%A(KgzG@o)u~&x`G9s|ESJl8sm($$BIaABBUh=c41~WEQ+83uGrj7al#g|&Kt1Zh^cfc(O zg-oh77U!jE)RG)!vACdLdUYt3QLAC@m|d7Uru*%1)-`%_{gOFG_iWUz&9yfDo;6wa zveQ~XnZqx|3jV3`P*?7$$ka!!aG%i@ujg1+IH;ZYF&Ij#LzS9vj-ZO)jXW9q48>sH zd^uD%YC$Wif&~7vrqN;P3cV}?&n!;0sya|mM8v^(KV=~?7J+re+y9yQgv|* zVo@0)b;Tg2dJJbFX&O{C&}{f+6Le=J9=vCYIzJ7}j>K*$t|AxAkZa#j!{$+r=h)B9 zQ&08jT<|-4Fiq-tN)#4$VLkB)q1`R|=rp)%cQ?|u)x?+@z=e~?Uw1Tzqf2JEYc@Rl zd%zcla{V?oY{?{d1e$nHb0`r6MR$w575IYYPKQM5V(5yOLx$U$ct0VW;F8+lwKjXX zolxZVV?YL`xCW*?GqTMGSU*|9hrF3(A=^-1@z`3Gj&ovoh2$94DlLn5R%nfm(NUj_ zfSW<8*W{j3+Ll0IG)2CuTImg|d+BUT<#Kvasy5C|QoVOTa&Hk0b}~=!jl1mbw*>+c z0iqQ1dW-YR3OZkUlHEQxUMJ3T_NA_Zn}wDRDnGXhoZpZi_i0!oJ64Ii`{-}!o+7Uq zX}d?jZ$ar}2rkoBg_z(~Fgn9ORI4J&K-zD(#pIn%^iSa7cL}?s(d_r(lAN4RJK9Ls z;1(fbl0Rt3-aeVf{FB=gcHZlFz6UTZlk|Ic!m1;fsJ+d_@PD&$z_-Eg=2b5Vm56Z! z96AEHIURl;cz!WVGd(c$MNJOeKXB%-PdjBh4j{QG#JSA+p9AXzAjUm;-pwLnkK8v^ z7Bu5^2mFsDQ%In{+yDq;PnhhV>{3~n|7tfN?q+ZDSEA-Wx`8PT95vLhEnhfN732iv z0@ZqBxFGj@e^kgq^q4sCijpDiIc_O~{#`~D3-S-=gWH~bdfj#-qnY||PC;%qd}m7W z?M^51Ul5PoW2AC~?a~-t*IRE_A6xMr*EzoT&uKhB{FXNPcYTFIux5$nj5ZCE^$g6FOxjvJVIN}sKn2}Dk0X%$)Y^yv4WcOji zVy%AV_P92ZiO|t(KdsRdCfa&cEe6PwY<&ou30?$4z-&H*iT!{svo$MUcp6pkMwKF}eE%;8X7aA+y_U|9`# z-7p(r&F0NO$)IfSqwN#@Sq{`d{f6F$U)1>Nr&Den95dAny3v4!Ln=Bl%#w!!m$a_VW*Q}SYem#?=Fdl@#wbMMC~rXozcUm z_3Be{UCG?WFja4nT1Y!(44xDIWrOU1$;IdM6D&+1S7yKcMCS-OR+E2jgVpk^h)VbS zFrW!Lta{L9ij^vB%+`X1&7WH55jp(jS_t9mB$ANSCq#irtDkob{^bPt(`gN;JmrG; zcqn~9ZU{M^=@D0jXgfJ$jtA1B1#v9&n$UYggMZRSSAPMX`;>-vx@kO`7GQ*XYt|-J zsW=HwGTs?4-Xng2Ubr_k*AYo)&M)B_8;~anAZ5?LFR?8OVN~Z?w9hyrwI!L}*(=(R zL}Yi&MxfrKf0C2X7Gskb@^4irRB z83+n$sntBFh5-n{%DWi+NQPa5%zMdytmCAE`XJ{a5aa1(Rc^`9SlWI9fcrn;CnOk0>hf?QfiEZFO!*jnR~=@LVthoe8K<( z;luz6hmoOc?5s7i#Clr*8}1ZWd@d`V9?SeQF(@dD+a3xtwbuaZ(r~?E;~r!yS!TIG z&6%!NJu?nuq%scjqMS#64PJQU`BNFPBs}FSh8u?@cHb4+PTRU#n+dxAqG=6gTnkI~i1(mm;BaUh=QR~HQ7XVY= zcg8iYIS0D0#s?Hf{A}vbDfa00$eKTP|@9`1bwU9>D79`<_uflzJlak zM@xa=PF!L#H_WCvPGFlIGG$1%e_#ykcnJO2f$h?@<3#{Lv72ZCx9vQ6kX)VOU`k|2 zVG_LV5HbjZm$XkI9dl9ST{+a7bm7VcK9y>i&7EcA7hLz4M;^>W>k;ya0}N{4(lk-s zgK~ElMQ90p2oRMoORktS%A0o$Wk*j@F_&sjTFoyw`4VZ{T=(nPY)$ zjS``pRr~_6bd2fFWoj3Tx&mos%J>Tc`MNbcCXaeER*zlj*XTkC6d4*S{&!i_#L?o} z`1_3nJHeXk^xq5(ox_cB3Ax=g%1B`SXV!O8=!}mFeGCo7Hhb@`H@9Vm$>31*(NS zEsg1qqI@FY%3+8w@`%FZa;e;uQbM|M;NNx?BT?BUZR^c+3|hY4UVMGN%@!abg0K~I zBgiZsuX~BKU35v8BltSHM^Sh5zDe=X^beug5G0xS*xX^_gHJP^v)0N<8I3DdE4Wf>m>I+?<+TLWT)dA zF_4>SCZ^a^u#boV`X=xj%uT*6JdNilOe@zt-kPrlJA%(GA1|>_ytfm1H$z0c*DYsm z!T<#tZ}F}bgY->cw8i1Q7Mg(KZT7|IY>Y84!}F&kJHzPl2(^mgLR7wW!Vr$*#6xG4#$QZHM- z5LW+~33M86JCy`wv?AIbQefaRcHG(Ru_R^UEXrm(BmPFx>_PS16{bPUkHVZWN7_vM zT(tPd)7wLK7f$Qj!lg=#>UGEE3NgCs6X+D$9n^MCRU9ZWAM1_eTgRr-sF+NXIZjb8AQMO9|p@*`L=@AUz`IYnl)(l(jK zooPJ#{<~>S2RjAIZIli4Ih6XV!|#f^wOi>IaX$+8OsjSCe#J(-B{k>NTY9unpdpN* ztYFhywJ69n6ZBZ|)6KOnd@{*>^kADH#2Ll5vRs~m$zhqWn0av~9=?@xsd!B$8%IA> zOYyB2dth;MNd9bCKtEgJnkC-*bzI;v#EvzL3tlyulcnQ!F=CJK{3Q0^Zi09g`Kv@K z3mGDMzkJ%1R=)Ybj(XqQL-bm9xn?#Q$3)M$ImLz&kjd`DPNwc|yN~@enh8TIHW|taK4vGZ!9gBEyrrHr&JDKzRRnI7WN& zM{|Muc+OHNq!&(_eXx7Au0N(G9^G_Je*ik2B_uy#Q!|Trv6zW8n?*}DOg|bXNPeYJ zGZOeYfFX-y^!0+77==^)#;x?liistn$1o%Dk~Lmmwyc}%BO`e? zcK-?>fgA5@jc*6$G8zY(crMWCr$mb)bz-z3_g5j?SZ~xScbBm>w353-#fw(SAX#ms z>TZy{D=}PRBtJ3-Z7dEK>Zi>%ZGX`c>wqb?ZR{F=@y=)kFNA)xi%dN3I zalcV6>zSjps5eECRj#A+TGvH5PleO#1vYBMSnhOLAmo4N-|0cUmu{5s7amqnB=e-L z*Bg|XaW=AwyteMJ)s!-X z?dBoHhqp=LFFNqk&)*Z(EH(gFqZR^;Qz#b^g~Q3kP3p-tSW zDpn;$@1VpslM74oI*BbU>|!v=ekamTu$8hSfKT)AGHRie{vNZ*!2KlwIy!@uF>MI( zJ5rD}4Hh%~MOH3F3g&l*yaWJ&?c<#t66-B&qX{41> zab#wZdV%ZkvZXQlD|L}P%FCgt*!1c!Rfhr!+@b2Ckln1MaU7={N^FtT5PoK)bECnK zZ3mxq?Fjmm_$-DiNFc6D`$!TUatb?Ga-Jqq%&eAV0CM}OEBg&-$8M1cNA*+QvAC07 zyqc!6yruT#xo9vHf+kup>m6 zSTrpY@+ifWL+!C&)NI$y$xI#_6ZO>|WQd7Dlolg}!a+)T%A^JfnwiFV%D8dPFXItW zZnO?hQX|G7rg|3NY)pN)8!V;h__MzjmrakxZNry+M`;)&lxuF*m=q4rk|nZp8og)1 zIV?zhqH{q_fvjvf^p{%S=Du8;QQt`i&BuJ|2eu!pC10c*_#1x_$In}FeWP4l?jD?7 zcI`1`JclA^<~}+m>wQ$?bDI>y!8M@;hdgp()etSuDu9wX^=)w=x%kJ}^JWNOtmEd` zMz7v<>~ZqP2w<+J--LfO^_vZdt!{5a)hN z=>(<+e-Z^jDmB;%;C?&6yXswcZK!<|LR5boKz-zX-$PVGDy<{bo+9b0vjiydBp}C1 z-|Jg~Qd+5gUlu~d7Y|-Neem)yjnseiyu^n7{05FWy=3Cqf5BjTISA?xCVphY%>a}Q#=|rVBQ{!$5LsDa=z?a9mSzx_r5MZ6T9DcEj+1T( znq(oI4p(2!Lr+rP_Dsi(NzKQ_#V2O*P|S=<%nVG-m`sci1DmdJ{v~EK<(6=bD4p?n zurwGL6$?B92@fdLYtJ&8P|_7D7PwV6CZm@QtjqYW`YUwIF8eF4_#N_Vj`*GOtFHJR z^XOVELi646?9}_`uR6mi&Lt2dNoOYEylxhFN1SB7u!XEnLffDLi3cX83##+;wg~qtvmkZ0#0nz{7V(LqS?FG%9mLD{&2(O2*SR~db-HX%n>5GYS|{%Kg0-O5cZJQ9j0oi@N@dPl z5kQQ)`lFt(#d_jvaplfuOv>dfX)stLs3tA3N}KZTcZEX)x;U(dmX*CTdRqt^cWD|U!NM*9o?T%2&G)xuE^?YMPS+)}Y?cqqucE-_N z3fY)OceX|q!{<7qIbeqV+4>O*I8tBewNfP)@-<0PE8b3RSDbrqe$Zf6r{D&rWO?!70}j?{YPPCsqI6$TinpN@~vFnZ15g4^as8BnejgC~{_ zpWFOv^0H4nzPBIZBlV`gRI1a0RY>i2hHs)tN5XK|^SEK#oa2CWG}Kx{wXZx_usHVh zy~+qsm;`xmC~)ADdf^$ZKzWb9O*s|* zZC)T-d)G@t2@)w5qGfiu^ZMIp6^+3!nM6ZU$dYAq;$s6_=w5E*B*xCc!=IabA{7mMKxc*I{D9h>#0I|9W z8*|`rXF~~{A17`FHm+YxobAt)mFg>>NU5pv|M4$dU2ZxXZfuiuCQ&|0!tZ=XgmYvA`DXS+N zp=9{)u2;Z$KMIR_eX<^s`r&oLKOuCNp?1`51FU)^Of|F7a z#gw=}KoO!qK&t=mNbvuZyY-)o+8OQtfP*grXXecI%${13>*8&|TEghW(G|c8V86g5 z1wnp|A2NDML6EatOp6L$?W$F~+6&3(SZAx-irIoj=y2Fr-x%w(wsyNUy4m08zyF=} zwbwUK0#5RK^Y!nG=Wy>o`@9+3!4d8tDg#Vd5a|*6!e7o_>`iS{&k3;IjT%bSS{^6qf ze^M+U`R%vy0Q}Btd0+1Pg+(BsIu7}6Bp~oR{$u_A!NTn8%!hYm44nV=$+0;e0n2Ay zLFX-E|05$leiAzV^9}0VcX3Q%;%Zl40W?W}(x^dnpG^w#ymzd>%6R>g z{mBy#;Ip^p9y0Tf1i{~lG5@p=1K6MHeDx!LxZ;T4KX_}DK? zk8Y`Si$GPkv8zbz0-6g7$qH6?7VsgWXGX)(8nuTtnBvA%IOqIcX6N1oeYs^tfh zP_4{PN|j__>=uHI>Jx!wtV^nStTs@?+(hYUDOxZr2En^b${`N?QA5c+8&G|CY@|%? zw1$?T$nSpt+QeX*sl(h|&cw;!jXttXv$Q2OZ+&*TX+XXL!yI>3 zIV+h2n7L3F%_s&1QUQ==vM;GUC}yvWrf4uZvn-8=q_!wy4~%*k=cdXEA$Fnopcc~% zJ!XQSbdV#Vp(H?{ZsN6aDLsWfz$>H)50%TGfK z^C#&;AQ0TD&z{C!d=lWw4dHb)p&!{8=ZM)CRIhI3y(8m7bzRCnx$fz$?JLMzGEXJn zv|009wuU#WMR?=JGQ2C8cag1T#Cio6 z4PvI6ZiFbDEZ-{JeS=&V3t3bOvOH%^HHmbVLk+iqu>CJWRv~V5UCw~4XjQQ|TW6+M z0US;F?HLD(;X7rc5@9^{zL7?cDyg6z7s+eNNO9xt8g`DUz{_jdOB;p-l0J1|35E95 z@dTwr#8jri?M&TXlX5h9HgOR~3vpU%S&l$6@_riIx1>buQnpA=bh#T>DcJl;I(W!{ z?O!D889TFm>=gWwrfp2<*YcvuX?m+O>@050dTmtp*O8%SDCth!T)BkZGv@1n#&+yX zVL^QiNaTe)_9;BJHe!z20f&&IQd^@CVy^{7R_wiH>+{@eK~*q4V^< zS_;%qN&1=6l5z#?-!ZmFZG9d$SOcBbcgE%C;oj~W+*c_F=88!iRYOv~5FO1oT$((+ zW$YX1HY&0(=$RTrhK+2eX^)I3zys%Z&^M07>>Sb}q^Io1g&KWGDPstv)?(J=Vk3Ya z8O+O>Ihygu%dv=%`826$b$Bua$51hQN49{z+H}M2& zK{h`rS+LX$ZWX=Jbxh%e2)qg46M5Cpw~KdR(x%EBUf(bvwNvy2mm8f2u1n{9RiYn+ zLy?5o;>{N?p9Q2NO4hYmDVLtDlva|4o{QB7nz@#&{K!1$0);|m@<(9D;|)Emc(yih zkAG~!5mf&LY%Ei&sYJ@4;7ryli{E}R_!*GgCpUNCv!S4;!fNFjQdC>1Nc{xnCBLdX zxKn6~sHLs=8oxf4ZYakH&=Sgt2)cO?ZJ3b`C0-zXRnbrWk^jqhA;k^Gb1~-TNx1># zV-{hgOn}FHvG$xL)n8(8P|(Xy-UFfXP=I?EOkoT?rX}(&t5)#!dm1K;nl+V5Hua42 zfMrHIOEREmCs$pT0hSEb+>B_$dg`}W8Fd=?SkC?%ZHDn4vPx?%Nf|a(zLFK| zQc&R()+w?);3F;E*j9R|G9B~EhE-qTEYnKoC9lXzrd6PJ#waSJIa6KPbhC?R91EAM zqq;3K(y9;P#Ej!+o5D}g^I7(@hS!i{w5)4j*SzXW6>#;bFctJiqNjd!Ds|)Ao36s*> zyFJLkrheq%Ol6j?HED33R=JJqO~wqX*hdmrp70En7zhwsN5{@?pg&0+_)u>J_XQ<% z=ep2fD&F06flEA~yGqdfTzQcUEGuGGwUycjh%4Ma9^@KXKIkH@YuQ%86_+E=v~7SG zLat~MIeO71UFS?&<+9BRaxAOlN_LuzJ@i(!50b{8A6w|v4m~|9CzN_dPyGDgc<4;4 za9TWdTXGIb9nejW#uRiJ02KpAXB?8aG~@?@M?G00yN+4{E<~a6Th}A-5b_;XkTY<%Zc4LL-Bkdf4>=7wCi(TyT?wCX1Tf zLH4@5imdL%JaWa3roBU2Wn_fYDjYK@U1#%bPTY>qbmb<7LZx+Tjji5^yqn_4$d21$ zo#hnXd$h-Bj???!k!6P9Fs3X+G%wogkm{_V+w!eq>iTCZVnbxRlL#B(Zc)Wili(27 z_hJLleru}5<;~@CqgMTOW-8~vrgyuO3V*d^l+#1jRLg#o$KJy_PLz}VjN52RMO7^M zOP2RtjY~L_tc=GHFWahD-tm>MGtT#clvFFzL|A;POTNP?mt=~XY=;omhy!)El^!W6 zJT|JZZ+D=5v}Wgx8f%0FEVD+7tv$i$N$e7rWi3H_b1GcOiOV8l`u_`(P-MjBzFB5Sg4t zM9;AQ?783Yl4Fn@*StWHB2%@6hzxwk5iz z{8P|#B3&~Qmvs1vE;bHSHBVKnwadui2-g9=L1HoAQ74NpLg8K%%Hu81dE4x55=?gv z-gtK7xb_?8!t94Bw?w|DF&XYNgt@u-$ELgygws$%2TKTC0@H+?M_s2e3yJdvXbp~O zskNOfrV7&&7=nZ`*!WLU<;Wwu@s)jCI0@2L*Rylvnp54lGxySrp{%~NilLuGJlN2M z2(#?9GPi?;jw&4|WQ({VuQ6ls2ONYOW@|8kCDlcw>&O=I%?F=SwsM2W`W@LjSZN zCpNrxVKTyle#B3Lj-hVlaeot2__HQnq5G{;J=@HKyHKs_Rn2AGPLg4*)w-P``C1dm zKG)uE$Y@F( zAdsqaFc2ArV%3rI_2JvUk=n5Ynl`mkWR%pdCE z=MMQW(h~^!Fu{5$t`Nvm@(-Fk=ANq+2>n=k_Dq=*y@7cad-j29rJ+P{Evk}^sjd0I zt(2g=!+OLgkEch)EB%r)+Z8e8Rf{C*n^PJb@)~3~;tBP6vm-*V1vlBM2x&9P#$!$U zecoJ=w0VIk9@ExdU~x_(+V!lK0MajEP;7xGTz07OlezwiiIu1Sc+5xXPh8>tc)5#d z?vtD6Y(8Da%Vz>6Anm#DuL3wAqV`Fd4&MQcc#Yd3c7#g<7|Q&E`z~bjqYboJ`;nJE zJs+*L>jzV;*>1}CBKk^0%j!*X!Rt=US>ggU<#GjtsXW>0#yUlR443|ZEaF(A?ts1T#W1-WF4wYV+7(-M z<<1uI=n3*+KJfZNwoU;3bU*Wj_h8sOc0eC{&bu8cVK+k+;dEazf@f9p`MQX^>J!9P z-xfd6u}J`amx-`8#*?q8z9=CoJ};8Z5WZ2$35{i%seD>uhsoa+W0|43d6uQn+%S{N z(Nwohu_@<;DiExwTibb8mT0lqYY;$efUCl&WYqZAI{{Y&S48lKti~%M`J!sOFvJ#q zTJrklm>XtlPv?r{2hHDxPx8lPA}p*h#^M;Vf{YVeN+P-3ig`iN#Eo_Bl@kC3bhhN^ zmk|`*SWzz%M!MLS5CHa}&$&OCzQF=!O7a)ya69#{GKM!&0WShF%YTuWiGFWDo3mP| zt+243QqCahp4BDgRgthV#M9StpHnZ2GT-w-WAVbD=9M^Ra6(xb0AFQC$9}*a*?e@i zO*^_k^n#!Sq9pTRh37osveBe`V}91w@Nx?3Ks9D8OGOMP|aPd@sgooHaElfM#*MV#V;C-5R~g| z3C^|@+JfHZ!{ztHoN@}T_(4p2PFC>Y8{?CCNpz2fXvq??1wy(85{4PDE>~~zYOPqX z2WUtW5q=4{;;@_>k_-y^LNCqOatqx$4U~Dq`_|vOH2(ngN<3N;dzSb>Isa@1?d7{< zz~1U##5qSgKjX?9HF(#e<`kA$se_4sho{ zx`m%icMnNp1_4YNCMZ6v3ZO`^r*UGCtDnL+QJAuZGex_P2sJR3k+T6Y??vx^#qTe? zWNgI;`<|i_wQboPJNVfgAclIGpo00<~ZC;g-h;Iyk90C!Q^ayDmh; zP{hGmp5^!Az*wl&J(RvAu6a?YNscdI#!`Ogkj7YKu6g5DtQ0(dXHZA;_fHQl$lnd; zBZY`7t=9Zm?=etz+f%uC`-Ppdy|l$y-E9;&PbaUQUb__0no=9?zSR)__-^RBF#;d8 zVuo|0?B}{c-hEt4zh#pi)AQbU*(7r#aSWaEEl6Ah;S9m>Ucs4uPN>5Xkc)XwNV+shX?D z+##t-ktGue5~>}23GE#p|Lg5j?ua{t|Ikr&;HWZ&VqP*&6opF?jW_f39#wnXViBA- zHOm9L_0fe=5&TAUy*s9w=oY&x&tf4~SEl_z%Y|dEEdB|Xd;IB~i9fq<`fQ%#UH1cc zZK1jcs7N3`+5<`BDbxp_;ecI#cBe;}W^YC@bnD!6Hry-Ig~K0 zNdPUu#)2m=G8w~{G+q2+0Q-_AerytgV5}4Vb?!lR?hBZH?PbM_`a`8AH8NwG;c?85PJ&B?$GwXS<%pL_JA07@ zrFn&4J&@Jch{^4g_I}#FaSNqxEn0L7WwXC9-Fh1FMm6V(CIg6`5R{Aw)I3i~s`JzE zO}z6L6gk`#7gt$0sSd3*bcjP_HkMJHptlfj9@D@Bu z=T)$|;_A&Nx0HEt{?agq`BauzCn1xlaC)4kqgz3Asmj;My=8io@*@`MAkotn|4nDb z5we(x*c^2A_*?8p#z`^{f&y@-ewF7N@EKql(x2jb+n8?d3GG78Vc24tJEBzruY1xN z1J=Gy*04^bII&cfZF35cv>!z(DxXwxq#X0Zj!&C)@ z%zha@ODu!JGAtZoA$2J1d=eLNX6@iUzF|OM2;{GD@w#!kqYe`_ui)Tk2N> zuZ&~%;F21sylPcS)XFb8{rSAZB;{L62PS2qt>J4hCwd!Gd}bK$YQ5Qm?uw>MM7EXDyL8y2U`DKok-CoHO%=*NXlQtZN^+0j{`2zu%Eg zPY$D--T~%j-Kkj?q={%nb+u1mykp}y_qZW>y6she-r73}VlI$VS7e!0$zqk&P!(5L z!LR3@(djj>Iz^`EBta|GUzMmZ-(tH`|6{SFJL6a3>=&C0`mbNI` zrEpg1Wutzuw>4sjLKhG}B>_EmK_o`fSr_S?t5jY#d8WB@FFLsMkQCWZTp+RmcqB)@ zdL%~&^4|iI2d%bY8VE_;;~wXP8iQltKWJ7groK?7y`iJkwX9mU#g&)JRq8yL-Qhq>XaN^D0TTeHz{|wCM)q zJ5~Y?9of(;e5xhzrU}ab{^#MN)?tD%p+c{qgfE#tEqSo(eJ}JN&77 z29Mb^JfrS8MC!W0#CpT$mF1{UxylfE_Ui=eKKb=1ZY2)yjkCnx1suAig&BzWc@Do& z%ip#1YQzKj9)3~BZ9h8r0qP|Dx_O=Ii%P_#@XeyAyt%SMC*0Q9XGfa^f=3SxQ@uV4=>Rr1frTezH3~ImS%$Cv|CTXOe=M zruXDos{OHYdh+`_b!hp6a)RwJK2E9l1DdVcqEf;)w@!6#;pGy?CHVt=r?yW9a{1{Q=>_kj#VZiL3gZIm1=&~5 zH(y^>pg?0~>Y3t2#7pHn17=0RqviukK}Fz<>k_R`@H+@+g<;2~KU2E{OZ#xeebMRQ zxRhJkDLM}6W&8#DMaz#K`D10XCCCM){vew4<}`E`@7faVr1b+?npO7EsF%Lon63K` zN@Hzxka@NH4#qk6Pb^cWJx*L1pY+y;0oS$6KAYlRtEOqN{-rU$!5>D3flf~%&mV;U zzL^ZtsFYv$r{+cZ=OYsOzu8Qx0BryDl>Ju=kdd*C8R`F2@Rq8`*)Itq`fio5u|vof z`lQB#6p~h|szky--;@?1Cl!XP_S$dPHZOQ_Xxj^Z(Igb4a^8c!DMe_ZfI;&WJR9Ck z_hfRgbhGUF`+P$f!YKTMHP}W-?j+lzy+D6Jd4DyGHXMgFS@D^in{`qx1#SKIQ7mE} zyX9*q#_Lj+YjL@V=s!}kJ6SLF)rw0!UxOx~Tp-CxPs(w_blW`JzrbZ?b)QKz>`0QL z+m)XTY=Fc!(VUf?T_I{;yize)N}mG?duv_&eM_yc7DT)Cl)kW86eeuZSr->ehqbzu z>8^mbCe|f@8M*z!{Wl8}+nn(+G!IzJm!+|DJ-P2Pbt5I4KPbzu)Y*)>GMeKz+>BB{ zI1~PXV+;_6afs!JN06&mjWg?5!u0CcJX@ROd&ZeaBCtK9A^h#*O0huk=@J`}Z`dDECl{|7rG&K$d1Pnsy174u}l$U;Gv=nCH-l zaj(RZvl4Ha<()T>Rlbqm<(m{`0%8jZ%(}!}ugqe4qiSyxdZVpWL$4`B*M1ONoI?M+ z974t9|FjEV(E~DTjlv$mhPbA_OFn%SnGoFG4i2-{g?9k(&nE>1{OC>U7s?ZQ9;+)#^3d?Nr}%Ni6+! zzgtPAjiLJ`;6m_E$;|h&_k`R3a<#TcT2%U_8~|}a;pEvKWj-$e>F^E+_zC@C6Lh|? z@cU>7YF+53c_x7Vwg>=uMiKZ<-}a|ZHvp@M@}pw;(NX_9sqmKs>}O3u0qp$m`Cm}h zWIsBRJMfGQw7QBi@;cS^;sy+Yjqvyyu=P2$72JKRP__FLDQE@wd0r$Nh_$y)_0!e& z&c3X2hu~>TRS&BGh9dxTu@wE%39|_KEbKjP9$n7qxTYe#vl;9*L?@SEwMWJEUGMj@|+FM{18P+N_!+s@%s-t8-UhJ^GS*4AmTz+gJr# zZxHVuCIQ{&7ERQoLGIDoe89WE01vLo`F*r+ebx7J#G5nF_VDxiyTlB=vaMP(lEXtu=jP+XO5v=LMP4r;AWaUJ-Sz<@JV-wX%jSxs}WF9EP9A=)0EV0>rBL^EwB;Hln5-$tAM#PN)UnMhUgO4~O55D3zW7;ADB ziwc=CvE)V<-mVQ+~m5)MEW-J`Bk_I28g{oLz?^Zt)RK5$%N#u9lC|Uh| zi-5fz<_J&?kty>4Pbju@6+F|uG)71ctgN)jj0Uu&ASPBU6?1y*}vz5=`e0hiyh1^XFJ#f|KN_0dAdMb~#X3Zw9N#?Uo9^YvQT0|l)kF5XTP zqoAUX&ICIsHO-E zy2g-deA=?cV`C}8hyaardipaN5_5?`_4KHn!c+$Z-5jpHblq(Ptf-V$UhmMibRL-Gdu!UP;}3H3 z)$sf$5X+m!!;2eyU5Se^ z$mM#xZWS+A6QsC$kD4u(56~1^R^G;)C3^gsr}5y+n30?91Y8<>2&PkOUW#*B3%0A= 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®4c}~ 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 z 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

(a|KA05N-4)pm_RB^G@}!yDw!<%*K3& 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≈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

+*QiDfX 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≠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%0A4@}cJdsPwGP87y+BzOK@t)k3th-={4d}QHK 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 PR!}W37q6y-vo-l2`jB5V literal 0 HcmV?d00001 diff --git a/dev/com.ibm.ws.logging.hpel_fat/lib/phased.junit.jar b/dev/com.ibm.ws.logging.hpel_fat/lib/phased.junit.jar new file mode 100755 index 0000000000000000000000000000000000000000..16828055661407cd74cc6942ab29798643d64856 GIT binary patch literal 24864 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 XWjXlk^!L4cc-Nnl>yefA&9DChjs5AW literal 0 HcmV?d00001 diff --git a/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HPELDeleteLogDirectory_1.xml b/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HPELDeleteLogDirectory_1.xml new file mode 100755 index 00000000000..96ca53fe151 --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HPELDeleteLogDirectory_1.xml @@ -0,0 +1,12 @@ + + + jsp-2.2 + + + + + + + + + diff --git a/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HPELDeleteLogDirectory_2.xml b/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HPELDeleteLogDirectory_2.xml new file mode 100755 index 00000000000..3001d33bb9b --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HPELDeleteLogDirectory_2.xml @@ -0,0 +1,12 @@ + + + jsp-2.2 + + + + + + + + + diff --git a/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HPELPurgeMaxSizeInvalid.xml b/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HPELPurgeMaxSizeInvalid.xml new file mode 100755 index 00000000000..fa0ff63a17f --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HPELPurgeMaxSizeInvalid.xml @@ -0,0 +1,12 @@ + + + jsp-2.2 + + + + + + + + + diff --git a/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HPELPurgeMaxSizeTest_1.xml b/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HPELPurgeMaxSizeTest_1.xml new file mode 100755 index 00000000000..7afb6ad18dc --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HPELPurgeMaxSizeTest_1.xml @@ -0,0 +1,12 @@ + + + jsp-2.2 + + + + + + + + + diff --git a/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HPELPurgeMaxSizeTest_2.xml b/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HPELPurgeMaxSizeTest_2.xml new file mode 100755 index 00000000000..a5aee2c82e5 --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HPELPurgeMaxSizeTest_2.xml @@ -0,0 +1,12 @@ + + + jsp-2.2 + + + + + + + + + diff --git a/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HPELPurgeMaxSizeTest_3.xml b/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HPELPurgeMaxSizeTest_3.xml new file mode 100755 index 00000000000..9e2e53c5ed9 --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HPELPurgeMaxSizeTest_3.xml @@ -0,0 +1,12 @@ + + + jsp-2.2 + + + + + + + + + diff --git a/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HPELPurgeMaxSizeTest_4.xml b/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HPELPurgeMaxSizeTest_4.xml new file mode 100755 index 00000000000..427e7cad047 --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HPELPurgeMaxSizeTest_4.xml @@ -0,0 +1,13 @@ + + + jsp-2.2 + + + + + + + + + + diff --git a/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HPELPurgeMaxSizeTest_5.xml b/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HPELPurgeMaxSizeTest_5.xml new file mode 100755 index 00000000000..10d2f6784e6 --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HPELPurgeMaxSizeTest_5.xml @@ -0,0 +1,14 @@ + + + jsp-2.2 + + + + + + + + + + + diff --git a/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HPELPurgeMaxSizeTest_6.xml b/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HPELPurgeMaxSizeTest_6.xml new file mode 100755 index 00000000000..2656bcc6e17 --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HPELPurgeMaxSizeTest_6.xml @@ -0,0 +1,12 @@ + + + jsp-2.2 + + + + + + + + + diff --git a/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HPELPurgeMaxSizeTest_7.xml b/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HPELPurgeMaxSizeTest_7.xml new file mode 100755 index 00000000000..767564cbe87 --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HPELPurgeMaxSizeTest_7.xml @@ -0,0 +1,11 @@ + + + jsp-2.2 + + + + + + + + diff --git a/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HPELPurgeMinTimeTest_1.xml b/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HPELPurgeMinTimeTest_1.xml new file mode 100755 index 00000000000..f6c503a3be0 --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HPELPurgeMinTimeTest_1.xml @@ -0,0 +1,14 @@ + + + jsp-2.2 + + + + + + + + + + + diff --git a/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HPELPurgeMinTimeTest_2.xml b/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HPELPurgeMinTimeTest_2.xml new file mode 100755 index 00000000000..e1b2e9b159d --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HPELPurgeMinTimeTest_2.xml @@ -0,0 +1,13 @@ + + + jsp-2.2 + + + + + + + + + + diff --git a/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HpelDeleteEmptyDirectories.xml b/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HpelDeleteEmptyDirectories.xml new file mode 100755 index 00000000000..8c79c52b470 --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HpelDeleteEmptyDirectories.xml @@ -0,0 +1,14 @@ + + + jsp-2.2 + + + + + + + + + + + diff --git a/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HpelDirChangePurgeMaxTest_1.xml b/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HpelDirChangePurgeMaxTest_1.xml new file mode 100755 index 00000000000..45c04395a5e --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HpelDirChangePurgeMaxTest_1.xml @@ -0,0 +1,13 @@ + + + jsp-2.2 + + + + + + + + + + diff --git a/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HpelDirChangePurgeMaxTest_2.xml b/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HpelDirChangePurgeMaxTest_2.xml new file mode 100755 index 00000000000..f700afe75ae --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HpelDirChangePurgeMaxTest_2.xml @@ -0,0 +1,13 @@ + + + jsp-2.2 + + + + + + + + + + diff --git a/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HpelLogDirectoryChange_1.xml b/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HpelLogDirectoryChange_1.xml new file mode 100755 index 00000000000..98fce4b1e73 --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HpelLogDirectoryChange_1.xml @@ -0,0 +1,11 @@ + + + jsp-2.2 + + + + + + + + diff --git a/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HpelLogDirectoryChange_2.xml b/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HpelLogDirectoryChange_2.xml new file mode 100755 index 00000000000..f86da35d129 --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HpelLogDirectoryChange_2.xml @@ -0,0 +1,11 @@ + + + jsp-2.2 + + + + + + + + diff --git a/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HpelLogElementDelete_1.xml b/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HpelLogElementDelete_1.xml new file mode 100755 index 00000000000..180e0f092d4 --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HpelLogElementDelete_1.xml @@ -0,0 +1,14 @@ + + + jsp-2.2 + + + + + + + + + + + diff --git a/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HpelLogElementDelete_2.xml b/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HpelLogElementDelete_2.xml new file mode 100755 index 00000000000..2925c7ac031 --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HpelLogElementDelete_2.xml @@ -0,0 +1,11 @@ + + + jsp-2.2 + + + + + + + + diff --git a/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HpelTextLogRetention.xml b/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HpelTextLogRetention.xml new file mode 100755 index 00000000000..a39050a34c5 --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-HpelTextLogRetention.xml @@ -0,0 +1,13 @@ + + + jsp-2.2 + + + + + + + + + + diff --git a/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-TraceSpecificationSetToAllTest.xml b/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-TraceSpecificationSetToAllTest.xml new file mode 100755 index 00000000000..b1eb87a21a7 --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/publish/files/server-TraceSpecificationSetToAllTest.xml @@ -0,0 +1,9 @@ + + + + jsp-2.2 + servlet-3.0 + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.logging.hpel_fat/publish/servers/HpelServer/.gitignore b/dev/com.ibm.ws.logging.hpel_fat/publish/servers/HpelServer/.gitignore new file mode 100644 index 00000000000..f3f483d82c0 --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/publish/servers/HpelServer/.gitignore @@ -0,0 +1 @@ +/dropins diff --git a/dev/com.ibm.ws.logging.hpel_fat/publish/servers/HpelServer/bootstrap.properties b/dev/com.ibm.ws.logging.hpel_fat/publish/servers/HpelServer/bootstrap.properties new file mode 100755 index 00000000000..98a6db1b769 --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/publish/servers/HpelServer/bootstrap.properties @@ -0,0 +1,3 @@ +bootstrap.include=../testports.properties +websphere.log.provider=binaryLogging-1.0 +com.ibm.ws.logging.console.log.level=INFO diff --git a/dev/com.ibm.ws.logging.hpel_fat/publish/servers/HpelServer/server.xml b/dev/com.ibm.ws.logging.hpel_fat/publish/servers/HpelServer/server.xml new file mode 100755 index 00000000000..179455eb2d8 --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/publish/servers/HpelServer/server.xml @@ -0,0 +1,9 @@ + + + jsp-2.2 + + + + + + diff --git a/dev/com.ibm.ws.logging.hpel_fat/test-applications/HpelFat/resources/LogCreator.jsp b/dev/com.ibm.ws.logging.hpel_fat/test-applications/HpelFat/resources/LogCreator.jsp new file mode 100755 index 00000000000..fca0089a940 --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/test-applications/HpelFat/resources/LogCreator.jsp @@ -0,0 +1,136 @@ + + +HPEL Function Test JSP + + +<%@page + import="java.util.*, java.io.*, com.ibm.ejs.ras.*, java.security.*" +%> +

+
Date: <%= new java.util.Date() %> +

+ +<% +String actionToPerform = request.getParameter( "ActionParam" ); +//make the default action Logs +if (actionToPerform == null) actionToPerform = "Logs"; + +if (actionToPerform.equals("Help")) { + out.println(""); + out.println(""); + out.println(""); + out.println(""); + out.println("
Parmeters:  
IterationsDefault: 50Will log the message iterations times"); + out.println("
LoggerNameDefault: com.ibm.ws.fat.hpel.tests.Default_HPELTestLoggerWill create a logger with the specificed name"); + out.println("
LevelDefault: ALLWill log messages Only to the specificed level [SEVERE, WARNING, INFO, FINE, FINER, FINEST]"); + out.println("
MessageDefault: Default HPEL MessageWill log the message passed to the JSP
SleepDefault: -1No sleep delay between logging
"); +} else { + String parmStr = request.getParameter("Iterations") ; + int numIterations = (parmStr == null) ? 49 : Integer.parseInt(parmStr) ; + + parmStr = request.getParameter("Message"); + String logMessage = (parmStr == null) ? "Default HPEL Message" : parmStr; + + parmStr = request.getParameter("LoggerName"); + String loggerName = (parmStr == null) ? "com.ibm.ws.fat.hpel.tests.Default_HPELTestLogger" : parmStr; + + parmStr = request.getParameter("Level"); + String level = (parmStr == null) ? "ALL" : parmStr; + + parmStr = request.getParameter("Sleep"); + int secondsToSleep = (parmStr == null) ? -1 : Integer.parseInt(parmStr); + + java.util.logging.Level passedLevel = null; + if (!level.equals("ALL")) { + if (level.toLowerCase().equals("severe")) passedLevel = java.util.logging.Level.SEVERE; + else if (level.toLowerCase().equals("warning")) passedLevel = java.util.logging.Level.WARNING; + else if (level.toLowerCase().equals("info")) passedLevel = java.util.logging.Level.INFO; + else if (level.toLowerCase().equals("fine")) passedLevel = java.util.logging.Level.FINE; + else if (level.toLowerCase().equals("finer")) passedLevel = java.util.logging.Level.FINER; + else if (level.toLowerCase().equals("finest")) passedLevel = java.util.logging.Level.FINEST; + } + + out.println("

Start time of JSP load: " + new java.util.Date() + "

"); + + out.println(""); + out.println(""); + out.println(""); + out.println(""); + out.println(""); + out.println(""); + out.println(""); + out.println(""); + out.println(""); + out.println("
Name Value
******Parms specific to this run******
Iterations " + numIterations + "
LoggerName " + loggerName + "
Level " + level + "
Message " + logMessage + "
Action " + actionToPerform + "
Sleep " + secondsToSleep + " milliseconds
") ; + + java.util.logging.Logger logger = java.util.logging.Logger.getLogger(loggerName); + + out.println("Action to perform: " + actionToPerform); + if (actionToPerform.equals("Logs")) { + out.println("Action performed: Logs"); + if (level.equals("ALL")) { + out.println("Level: ALL"); + for (int j = 0; j < numIterations; j++) { + //only do this once for each iteration + if (secondsToSleep > 0) Thread.sleep(secondsToSleep); + logger.logp(java.util.logging.Level.SEVERE, loggerName, "Method.Severe", logMessage); + logger.logp(java.util.logging.Level.WARNING, loggerName, "Method.Warning", logMessage); + logger.logp(java.util.logging.Level.INFO, loggerName, "Method.Info", logMessage); + } + } else { + out.println("Level: " + passedLevel); + for (int i = 0; i < numIterations; i++) { + //only do this once for each iteration + if (secondsToSleep > 0) Thread.sleep(secondsToSleep); + logger.logp(passedLevel, loggerName, passedLevel.getName(), logMessage); + } + } + } else if (actionToPerform.equals("Trace")) { + out.println("Action performed: Trace"); + if (level.equals("ALL")) { + out.println("Level: ALL"); + for (int j = 0; j < numIterations; j++) { + //only do this once for each iteration + if (secondsToSleep > 0) Thread.sleep(secondsToSleep); + logger.logp(java.util.logging.Level.FINE, loggerName, "Method.Fine", logMessage); + logger.logp(java.util.logging.Level.FINER, loggerName, "Method.Finer", logMessage); + logger.logp(java.util.logging.Level.FINEST, loggerName, "Method.Finest", logMessage); + } + } else { + out.println("Level: " + passedLevel); + for (int i = 0; i < numIterations; i++) { + //only do this once for each iteration + if (secondsToSleep > 0) Thread.sleep(secondsToSleep); + logger.logp(passedLevel, loggerName, passedLevel.getName(), logMessage); + } + } + } else if (actionToPerform.equals("LogsAndTrace")) { + out.println("Action performed: LogsAndTrace"); + if (level.equals("ALL")) { + out.println("Level: ALL"); + for (int j = 0; j < numIterations; j++) { + //only do this once for each iteration + if (secondsToSleep > 0) Thread.sleep(secondsToSleep); + logger.logp(java.util.logging.Level.FINE, loggerName, "Method.Fine", logMessage); + logger.logp(java.util.logging.Level.FINER, loggerName, "Method.Finer", logMessage); + logger.logp(java.util.logging.Level.FINEST, loggerName, "Method.Finest", logMessage); + logger.logp(java.util.logging.Level.SEVERE, loggerName, "Method.Severe", logMessage); + logger.logp(java.util.logging.Level.WARNING, loggerName, "Method.Warning", logMessage); + logger.logp(java.util.logging.Level.INFO, loggerName, "Method.Info", logMessage); + } + } else { + out.println("Level: " + passedLevel); + for (int i = 0; i < numIterations; i++) { + //only do this once for each iteration + if (secondsToSleep > 0) Thread.sleep(secondsToSleep); + logger.logp(passedLevel, loggerName, passedLevel.getName(), logMessage) ; + } + } + } else { + out.println("Action performed: NOTHING"); + } + out.println("

End time of JSP load: " + new java.util.Date() + "

"); +} +%> + + diff --git a/dev/com.ibm.ws.logging.hpel_fat/test-applications/HpelFat/resources/META-INF/permissions.xml b/dev/com.ibm.ws.logging.hpel_fat/test-applications/HpelFat/resources/META-INF/permissions.xml new file mode 100755 index 00000000000..2ec4e2c6204 --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/test-applications/HpelFat/resources/META-INF/permissions.xml @@ -0,0 +1,14 @@ + + + + + java.util.logging.LoggingPermission + control + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.logging.hpel_fat/test-applications/HpelFat/resources/WEB-INF/web.xml b/dev/com.ibm.ws.logging.hpel_fat/test-applications/HpelFat/resources/WEB-INF/web.xml new file mode 100755 index 00000000000..4427dd030b0 --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/test-applications/HpelFat/resources/WEB-INF/web.xml @@ -0,0 +1,22 @@ + + + + + HpelFatWAR + This is a servlet designed to test autoInstall. + + + + WritingCustomLogServlet + WritingCustomLogServlet + Write to custom log ... that's it!. + com.ibm.ws.logging.hpel_fat.WritingCustomLogServlet + + + + + + WritingCustomLogServlet + /* + + diff --git a/dev/com.ibm.ws.logging.hpel_fat/test-applications/HpelFat/src/com/ibm/ws/logging/hpel/handlers/MyCustomHandler.java b/dev/com.ibm.ws.logging.hpel_fat/test-applications/HpelFat/src/com/ibm/ws/logging/hpel/handlers/MyCustomHandler.java new file mode 100755 index 00000000000..3cf7d6d6ac8 --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/test-applications/HpelFat/src/com/ibm/ws/logging/hpel/handlers/MyCustomHandler.java @@ -0,0 +1,11 @@ +package com.ibm.ws.logging.hpel.handlers; + +import java.io.IOException; +import java.util.logging.FileHandler; + +public class MyCustomHandler extends FileHandler { + public MyCustomHandler(String pattern, int limit, int count, boolean append) + throws SecurityException, IOException { + super(pattern, limit, count, append); + } +} \ No newline at end of file diff --git a/dev/com.ibm.ws.logging.hpel_fat/test-applications/HpelFat/src/com/ibm/ws/logging/hpel_fat/WritingCustomLogServlet.java b/dev/com.ibm.ws.logging.hpel_fat/test-applications/HpelFat/src/com/ibm/ws/logging/hpel_fat/WritingCustomLogServlet.java new file mode 100755 index 00000000000..e857d3e1060 --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/test-applications/HpelFat/src/com/ibm/ws/logging/hpel_fat/WritingCustomLogServlet.java @@ -0,0 +1,80 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2014 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.logging.hpel_fat; + +import java.io.IOException; +import java.io.PrintWriter; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.logging.SimpleFormatter; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.ibm.ws.logging.hpel.handlers.MyCustomHandler; + +/** + * This is a servlet to write logs to a custom file + */ +public class WritingCustomLogServlet extends HttpServlet { + private static final long serialVersionUID = 1L; + private final Logger logger = Logger.getLogger(getClass().getPackage() + .getName()); + + @Override + public void init() throws ServletException { + logger.setLevel(Level.ALL); + try { + MyCustomHandler handler = new MyCustomHandler("customlog.log", 50000, 10, true); + handler.setLevel(Level.ALL); + handler.setFormatter(new SimpleFormatter()); + logger.addHandler(handler); + } catch (Exception e) { + logger.severe("FileHanler initilization failed:" + + e.toString()); + e.printStackTrace(); + } + } + + @Override + protected void doGet(HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException { + logger.finest("Entering in to the doGet() method."); + logger.info("doGet method of WritingCustomLogServlet called and now calling the doService"); + doService(request, response); + logger.finest("Exiting from the doGet() method."); + } + + @Override + protected void doPost(HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException { + logger.finest("Entering in to the doPost() method."); + logger.info("doPost method of WritingCustomLogServlet is called and now calling the doService"); + doService(request, response); + logger.finest("Exiting from the doPost() method."); + } + + protected void doService(HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException { + logger.finest("Entering in to the doService() method."); + logger.fine("This is Fine message in doGet()"); + logger.finer("This is Finer message in doGet()"); + logger.config("This is config message in doGet()"); + + PrintWriter pw = response.getWriter(); + pw.println("Servlet successfullly completed"); + + this.logger.finest("Exiting from doService() method."); + } +} diff --git a/dev/com.ibm.ws.logging.hpel_fat/test-applications/LogFat/resources/META-INF/permissions.xml b/dev/com.ibm.ws.logging.hpel_fat/test-applications/LogFat/resources/META-INF/permissions.xml new file mode 100755 index 00000000000..2ec4e2c6204 --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/test-applications/LogFat/resources/META-INF/permissions.xml @@ -0,0 +1,14 @@ + + + + + java.util.logging.LoggingPermission + control + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.logging.hpel_fat/test-applications/LogFat/resources/WEB-INF/web.xml b/dev/com.ibm.ws.logging.hpel_fat/test-applications/LogFat/resources/WEB-INF/web.xml new file mode 100755 index 00000000000..11f8c9b6f4c --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/test-applications/LogFat/resources/WEB-INF/web.xml @@ -0,0 +1,30 @@ + + + + + LRC + LRC servlet + + + LogDecoratorFilter + com.ibm.ws.test.LogDecoratorFilter + + IncludeParameter + userName productId + + + + LogDecoratorFilter + /* + + + + LogServlet + com.ibm.ws.logging.hpel.LRCServlet + + + LogServlet + /* + + + diff --git a/dev/com.ibm.ws.logging.hpel_fat/test-applications/LogFat/src/com/ibm/ws/logging/hpel/LRCServlet.java b/dev/com.ibm.ws.logging.hpel_fat/test-applications/LogFat/src/com/ibm/ws/logging/hpel/LRCServlet.java new file mode 100755 index 00000000000..0824021a132 --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/test-applications/LogFat/src/com/ibm/ws/logging/hpel/LRCServlet.java @@ -0,0 +1,39 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2014 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.logging.hpel; + +import java.io.IOException; +import java.io.PrintWriter; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * + */ +public class LRCServlet extends HttpServlet { + + /** */ + private static final long serialVersionUID = 1L; + + @Override + public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException + { + PrintWriter out = res.getWriter(); + res.setContentType("text/html"); + out.println("LRC Servlet"); + out.println("LRC Servlet"); + System.out.println("LRC Servlet doGet Method stars"); + } +} diff --git a/dev/com.ibm.ws.logging.hpel_fat/test-applications/LogFat/src/com/ibm/ws/test/LogDecoratorFilter.java b/dev/com.ibm.ws.logging.hpel_fat/test-applications/LogFat/src/com/ibm/ws/test/LogDecoratorFilter.java new file mode 100755 index 00000000000..e503d427a0d --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/test-applications/LogFat/src/com/ibm/ws/test/LogDecoratorFilter.java @@ -0,0 +1,145 @@ +/* + * This program may be used, executed, copied, modified and distributed + * without royalty for the purpose of developing, using, marketing, or distributing. + */ + +package com.ibm.ws.test; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.logging.Logger; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; + +import com.ibm.websphere.logging.hpel.LogRecordContext; + +/** + * This servlet filter adds configured request query parameters to the + * LogRecordContext + * + * Sample content to add to web.xml deployment descriptor to configure this + * servlet filter to add the userName and productId request query parameters to + * the LogRecordContext: + * + * + * LogDecoratorFilter + * com.test.LogDecoratorFilter + * + * IncludeParameter + * userName productId + * + * + * + * LogDecoratorFilter + * /* + * + * + */ +public class LogDecoratorFilter implements Filter { + + private static Logger logger = Logger.getLogger("com.ibm.ws.test.LogDecoratorFilter"); + + private ThreadLocalStringExtension[] extensions; + private String[] extensionNames; + + /** + * Default constructor. + */ + public LogDecoratorFilter() {} + + /** + * @see Filter#destroy() + */ + @Override + public void destroy() { + logger.info("LogDecoratorFilter - destroy"); + for (String extensionName : extensionNames) { + LogRecordContext.unregisterExtension(extensionName); + } + } + + /** + * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain) + */ + @Override + public void doFilter(ServletRequest servletRequest, + ServletResponse servletResponse, + FilterChain filterChain) + throws IOException, ServletException { + logger.info("LogDecoratorFilter - doFilter"); + + // set values we want to log + for (int i = 0; i < extensionNames.length; i++) { + String value = servletRequest.getParameter(extensionNames[i]); + extensions[i].setValue(value); + logger.info(extensionNames[i] + " set to: " + value); + } + + // pass the request along the filter chain + filterChain.doFilter(servletRequest, servletResponse); + + // unset the values so they don't leak to other threads + for (int i = 0; i < extensionNames.length; i++) { + extensions[i].setValue(null); + logger.info(extensionNames[i] + " set to: " + null); + } + } + + /** + * @see Filter#init(FilterConfig) + */ + @Override + public void init(FilterConfig filterConfig) throws ServletException { + logger.info("LogDecoratorFilter - init"); + + // get names from deployment descriptor + List names = getIncludeParameters(filterConfig); + + // set up an extension for each name + extensionNames = new String[names.size()]; + extensions = new ThreadLocalStringExtension[names.size()]; + Map extns = new HashMap(); + for (int i = 0; i < names.size(); i++) { + extensionNames[i] = names.get(i); + extensions[i] = new ThreadLocalStringExtension(); + LogRecordContext.registerExtension(extensionNames[i], extensions[i]); + LogRecordContext.getExtensions(extns); + logger.info("LogRecordContextExtensions ::" + extns); + } + logger.info("LogDecoratorFilter - init -Ends"); + } + + private List getIncludeParameters(FilterConfig filterConfig) { + + List names = new ArrayList(); + + { + Enumeration initParameterNames = filterConfig.getInitParameterNames(); + while (initParameterNames.hasMoreElements()) { + String name = initParameterNames.nextElement(); + if (!name.equals("IncludeParameter")) { + logger.info("unrecognized [" + name + "]. Only IncludeParameter accepted"); + } + else { + String combinedValue = filterConfig.getInitParameter(name); + String[] splitValue = combinedValue.split(" "); + for (String value : splitValue) { + logger.info("init parm: " + value); + names.add(value); + } + } + } + } + + return names; + } +} diff --git a/dev/com.ibm.ws.logging.hpel_fat/test-applications/LogFat/src/com/ibm/ws/test/ThreadLocalStringExtension.java b/dev/com.ibm.ws.logging.hpel_fat/test-applications/LogFat/src/com/ibm/ws/test/ThreadLocalStringExtension.java new file mode 100755 index 00000000000..8ba4a6f308d --- /dev/null +++ b/dev/com.ibm.ws.logging.hpel_fat/test-applications/LogFat/src/com/ibm/ws/test/ThreadLocalStringExtension.java @@ -0,0 +1,30 @@ +/* + * This program may be used, executed, copied, modified and distributed + * without royalty for the purpose of developing, using, marketing, or distributing. + */ + +package com.ibm.ws.test; + +import java.util.logging.Logger; + +import com.ibm.websphere.logging.hpel.LogRecordContext; + +public class ThreadLocalStringExtension implements LogRecordContext.Extension { + private static Logger logger = Logger.getLogger("com.ibm.ws.test.ThreadLocalStringExtension"); + + public ThreadLocalStringExtension() {} + + private final ThreadLocal threadLocalString = new ThreadLocal(); + + public void setValue(String string) { + threadLocalString.set(string); + logger.info("setValue - new value: [" + string + "] for thread " + Thread.currentThread().getName()); +// System.out.println("setValue - new value: [" + string + "] for thread " + Thread.currentThread().getName()); + } + + @Override + public String getValue() { + return threadLocalString.get(); + // don't log here or you will get a recursion + } +} diff --git a/dev/com.ibm.ws.logging_fat/.classpath b/dev/com.ibm.ws.logging_fat/.classpath new file mode 100644 index 00000000000..c422489df40 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/dev/com.ibm.ws.logging_fat/.classpath.gradle b/dev/com.ibm.ws.logging_fat/.classpath.gradle new file mode 100644 index 00000000000..c422489df40 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/.classpath.gradle @@ -0,0 +1,7 @@ + + + + + + + diff --git a/dev/com.ibm.ws.logging_fat/.gitignore b/dev/com.ibm.ws.logging_fat/.gitignore new file mode 100644 index 00000000000..647380e0e0c --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/.gitignore @@ -0,0 +1 @@ +dropins diff --git a/dev/com.ibm.ws.logging_fat/.project b/dev/com.ibm.ws.logging_fat/.project new file mode 100755 index 00000000000..52807d17e17 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/.project @@ -0,0 +1,23 @@ + + + com.ibm.ws.logging_fat + + + + + + org.eclipse.jdt.core.javabuilder + + + + + bndtools.core.bndbuilder + + + + + + org.eclipse.jdt.core.javanature + bndtools.core.bndnature + + diff --git a/dev/com.ibm.ws.logging_fat/.settings/org.eclipse.core.resources.prefs b/dev/com.ibm.ws.logging_fat/.settings/org.eclipse.core.resources.prefs new file mode 100755 index 00000000000..25d9425fe34 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,4 @@ +#Ant properties +#Automatically generated by the ant prepare.settings.files task +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/dev/com.ibm.ws.logging_fat/.settings/org.eclipse.jdt.core.prefs b/dev/com.ibm.ws.logging_fat/.settings/org.eclipse.jdt.core.prefs new file mode 100755 index 00000000000..f48ecd6cc60 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,280 @@ +#Ant properties +#Automatically generated by the ant prepare.settings.files task +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.6 +org.eclipse.jdt.core.formatter.align_type_members_on_columns=false +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=0 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=18 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=2 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=2 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=18 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=2 +org.eclipse.jdt.core.formatter.alignment_for_assignment=0 +org.eclipse.jdt.core.formatter.alignment_for_binary_expression=18 +org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=0 +org.eclipse.jdt.core.formatter.alignment_for_enum_constants=16 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=18 +org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=18 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=18 +org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=0 +org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=20 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=4 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +org.eclipse.jdt.core.formatter.blank_lines_before_field=0 +org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 +org.eclipse.jdt.core.formatter.blank_lines_before_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 +org.eclipse.jdt.core.formatter.blank_lines_before_package=0 +org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 +org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 +org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false +org.eclipse.jdt.core.formatter.comment.format_block_comments=true +org.eclipse.jdt.core.formatter.comment.format_header=false +org.eclipse.jdt.core.formatter.comment.format_html=false +org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true +org.eclipse.jdt.core.formatter.comment.format_line_comments=false +org.eclipse.jdt.core.formatter.comment.format_source_code=true +org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true +org.eclipse.jdt.core.formatter.comment.indent_root_tags=true +org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert +org.eclipse.jdt.core.formatter.comment.line_length=180 +org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true +org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true +org.eclipse.jdt.core.formatter.compact_else_if=true +org.eclipse.jdt.core.formatter.continuation_indentation=4 +org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=4 +org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off +org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on +org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false +org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=false +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true +org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_empty_lines=false +org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true +org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true +org.eclipse.jdt.core.formatter.indentation.size=8 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert +org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.join_lines_in_comments=false +org.eclipse.jdt.core.formatter.join_wrapped_lines=false +org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false +org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false +org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false +org.eclipse.jdt.core.formatter.lineSplit=180 +org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=true +org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=true +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 +org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=false +org.eclipse.jdt.core.formatter.tabulation.char=space +org.eclipse.jdt.core.formatter.tabulation.size=4 +org.eclipse.jdt.core.formatter.use_on_off_tags=true +org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false +org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true +org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true diff --git a/dev/com.ibm.ws.logging_fat/.settings/org.eclipse.jdt.ui.prefs b/dev/com.ibm.ws.logging_fat/.settings/org.eclipse.jdt.ui.prefs new file mode 100755 index 00000000000..74d9c72c1f3 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,113 @@ +#Ant properties +#Automatically generated by the ant prepare.settings.files task +cleanup.add_default_serial_version_id=false +cleanup.add_generated_serial_version_id=true +cleanup.add_missing_annotations=true +cleanup.add_missing_deprecated_annotations=true +cleanup.add_missing_methods=false +cleanup.add_missing_nls_tags=false +cleanup.add_missing_override_annotations=true +cleanup.add_missing_override_annotations_interface_methods=true +cleanup.add_serial_version_id=false +cleanup.always_use_blocks=true +cleanup.always_use_parentheses_in_expressions=false +cleanup.always_use_this_for_non_static_field_access=false +cleanup.always_use_this_for_non_static_method_access=false +cleanup.convert_to_enhanced_for_loop=false +cleanup.correct_indentation=true +cleanup.format_source_code=false +cleanup.format_source_code_changes_only=false +cleanup.make_local_variable_final=false +cleanup.make_parameters_final=true +cleanup.make_private_fields_final=false +cleanup.make_type_abstract_if_missing_method=false +cleanup.make_variable_declarations_final=false +cleanup.never_use_blocks=false +cleanup.never_use_parentheses_in_expressions=true +cleanup.organize_imports=false +cleanup.qualify_static_field_accesses_with_declaring_class=false +cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true +cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true +cleanup.qualify_static_member_accesses_with_declaring_class=true +cleanup.qualify_static_method_accesses_with_declaring_class=false +cleanup.remove_private_constructors=true +cleanup.remove_trailing_whitespaces=true +cleanup.remove_trailing_whitespaces_all=true +cleanup.remove_trailing_whitespaces_ignore_empty=false +cleanup.remove_unnecessary_casts=true +cleanup.remove_unnecessary_nls_tags=true +cleanup.remove_unused_imports=true +cleanup.remove_unused_local_variables=false +cleanup.remove_unused_private_fields=true +cleanup.remove_unused_private_members=false +cleanup.remove_unused_private_methods=true +cleanup.remove_unused_private_types=true +cleanup.sort_members=false +cleanup.sort_members_all=false +cleanup.use_blocks=true +cleanup.use_blocks_only_for_return_and_throw=false +cleanup.use_parentheses_in_expressions=true +cleanup.use_this_for_non_static_field_access=false +cleanup.use_this_for_non_static_field_access_only_if_necessary=true +cleanup.use_this_for_non_static_method_access=false +cleanup.use_this_for_non_static_method_access_only_if_necessary=true +eclipse.preferences.version=1 +editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true +org.eclipse.jdt.ui.ignorelowercasenames=true +org.eclipse.jdt.ui.importorder=java;javax;org;com; +org.eclipse.jdt.ui.javadoc=true +org.eclipse.jdt.ui.ondemandthreshold=99 +org.eclipse.jdt.ui.staticondemandthreshold=99 +org.eclipse.jdt.ui.text.custom_code_templates= +sp_cleanup.add_default_serial_version_id=true +sp_cleanup.add_generated_serial_version_id=false +sp_cleanup.add_missing_annotations=true +sp_cleanup.add_missing_deprecated_annotations=true +sp_cleanup.add_missing_methods=false +sp_cleanup.add_missing_nls_tags=false +sp_cleanup.add_missing_override_annotations=true +sp_cleanup.add_missing_override_annotations_interface_methods=true +sp_cleanup.add_serial_version_id=false +sp_cleanup.always_use_blocks=true +sp_cleanup.always_use_parentheses_in_expressions=false +sp_cleanup.always_use_this_for_non_static_field_access=false +sp_cleanup.always_use_this_for_non_static_method_access=false +sp_cleanup.convert_to_enhanced_for_loop=false +sp_cleanup.correct_indentation=false +sp_cleanup.format_source_code=true +sp_cleanup.format_source_code_changes_only=false +sp_cleanup.make_local_variable_final=false +sp_cleanup.make_parameters_final=false +sp_cleanup.make_private_fields_final=true +sp_cleanup.make_type_abstract_if_missing_method=false +sp_cleanup.make_variable_declarations_final=true +sp_cleanup.never_use_blocks=false +sp_cleanup.never_use_parentheses_in_expressions=true +sp_cleanup.on_save_use_additional_actions=true +sp_cleanup.organize_imports=true +sp_cleanup.qualify_static_field_accesses_with_declaring_class=false +sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_with_declaring_class=false +sp_cleanup.qualify_static_method_accesses_with_declaring_class=false +sp_cleanup.remove_private_constructors=true +sp_cleanup.remove_trailing_whitespaces=true +sp_cleanup.remove_trailing_whitespaces_all=true +sp_cleanup.remove_trailing_whitespaces_ignore_empty=false +sp_cleanup.remove_unnecessary_casts=true +sp_cleanup.remove_unnecessary_nls_tags=true +sp_cleanup.remove_unused_imports=true +sp_cleanup.remove_unused_local_variables=false +sp_cleanup.remove_unused_private_fields=true +sp_cleanup.remove_unused_private_members=false +sp_cleanup.remove_unused_private_methods=true +sp_cleanup.remove_unused_private_types=true +sp_cleanup.sort_members=false +sp_cleanup.sort_members_all=false +sp_cleanup.use_blocks=false +sp_cleanup.use_blocks_only_for_return_and_throw=false +sp_cleanup.use_parentheses_in_expressions=false +sp_cleanup.use_this_for_non_static_field_access=false +sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true +sp_cleanup.use_this_for_non_static_method_access=false +sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true diff --git a/dev/com.ibm.ws.logging_fat/bnd.bnd b/dev/com.ibm.ws.logging_fat/bnd.bnd new file mode 100644 index 00000000000..20b28a82bd2 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/bnd.bnd @@ -0,0 +1,28 @@ +-include= ~../cnf/resources/bnd/bundle.props +bVersion=1.0 + +src: \ + fat/src + +-buildpath: \ + ${javac.bootclasspath.java6}, \ + ../build.sharedResources/lib/junit/old/junit.jar;version=file, \ + ../build.sharedResources/lib/ws-junit/ws-junit.jar;version=file, \ + ../build.sharedResources/lib/hamcrest-all.jar;version=file, \ + ../build.sharedResources/lib/jmock/old/jmock-junit4.jar;version=file, \ + ../build.sharedResources/lib/jmock/old/jmock.jar;version=file, \ + fattest.simplicity;version=latest, \ + ../fattest.simplicity/lib/public.api.jar;version=file, \ + ../com.ibm.ws.kernel.boot.archive/lib/org.apache.commons.compress-1.10.jar;version=file, \ + com.ibm.websphere.org.osgi.core.6.0.0;version=latest, \ + com.ibm.websphere.org.osgi.service.cm.1.5.0;version=latest,\ + com.ibm.websphere.org.osgi.service.component.1.3.0;version=latest,\ + com.ibm.wsspi.thirdparty.equinox;version=latest, \ + com.ibm.ws.kernel.boot.core;version=latest,\ + com.ibm.ws.kernel.service;version=latest,\ + com.ibm.ws.kernel.service.location;version=latest,\ + com.ibm.ws.logging.core;version=latest,\ + com.ibm.ws.org.eclipse.equinox.region.1.3.2;version=latest, \ + com.ibm.ws.runtime.update;version=latest, \ + com.ibm.ws.kernel.feature.core;version=latest, \ + com.ibm.ws.kernel.feature;version=latest diff --git a/dev/com.ibm.ws.logging_fat/bnd.bnd.gradle b/dev/com.ibm.ws.logging_fat/bnd.bnd.gradle new file mode 100644 index 00000000000..20b28a82bd2 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/bnd.bnd.gradle @@ -0,0 +1,28 @@ +-include= ~../cnf/resources/bnd/bundle.props +bVersion=1.0 + +src: \ + fat/src + +-buildpath: \ + ${javac.bootclasspath.java6}, \ + ../build.sharedResources/lib/junit/old/junit.jar;version=file, \ + ../build.sharedResources/lib/ws-junit/ws-junit.jar;version=file, \ + ../build.sharedResources/lib/hamcrest-all.jar;version=file, \ + ../build.sharedResources/lib/jmock/old/jmock-junit4.jar;version=file, \ + ../build.sharedResources/lib/jmock/old/jmock.jar;version=file, \ + fattest.simplicity;version=latest, \ + ../fattest.simplicity/lib/public.api.jar;version=file, \ + ../com.ibm.ws.kernel.boot.archive/lib/org.apache.commons.compress-1.10.jar;version=file, \ + com.ibm.websphere.org.osgi.core.6.0.0;version=latest, \ + com.ibm.websphere.org.osgi.service.cm.1.5.0;version=latest,\ + com.ibm.websphere.org.osgi.service.component.1.3.0;version=latest,\ + com.ibm.wsspi.thirdparty.equinox;version=latest, \ + com.ibm.ws.kernel.boot.core;version=latest,\ + com.ibm.ws.kernel.service;version=latest,\ + com.ibm.ws.kernel.service.location;version=latest,\ + com.ibm.ws.logging.core;version=latest,\ + com.ibm.ws.org.eclipse.equinox.region.1.3.2;version=latest, \ + com.ibm.ws.runtime.update;version=latest, \ + com.ibm.ws.kernel.feature.core;version=latest, \ + com.ibm.ws.kernel.feature;version=latest diff --git a/dev/com.ibm.ws.logging_fat/build-test.xml b/dev/com.ibm.ws.logging_fat/build-test.xml new file mode 100755 index 00000000000..365255bee8b --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/build-test.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.logging_fat/build.gradle b/dev/com.ibm.ws.logging_fat/build.gradle new file mode 100644 index 00000000000..e69de29bb2d diff --git a/dev/com.ibm.ws.logging_fat/delivery.sets b/dev/com.ibm.ws.logging_fat/delivery.sets new file mode 100755 index 00000000000..674398425a0 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/delivery.sets @@ -0,0 +1 @@ +SLE diff --git a/dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/AbstractStackTraceFilteringTest.java b/dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/AbstractStackTraceFilteringTest.java new file mode 100755 index 00000000000..b35a9f49f36 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/AbstractStackTraceFilteringTest.java @@ -0,0 +1,105 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.logging.fat; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.BufferedReader; +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.ProtocolException; +import java.net.URL; +import java.util.Arrays; +import java.util.List; + +import componenttest.topology.impl.LibertyServer; +import componenttest.topology.utils.HttpUtils; + +/** + * + */ +public class AbstractStackTraceFilteringTest { + + protected static final String INTERNAL_CLASSES_REGEXP = "at \\[internal classes\\]"; + protected static final String CONSOLE_LOG = "logs/console.log"; + + protected static final int CONN_TIMEOUT = 10; + + protected static LibertyServer server; + + protected static void hitWebPage(String contextRoot, String servletName, boolean failureAllowed) throws MalformedURLException, IOException, ProtocolException { + try { + URL url = new URL("http://" + server.getHostname() + ":" + server.getHttpDefaultPort() + "/" + contextRoot + "/" + servletName); + int expectedResponseCode = failureAllowed ? HttpURLConnection.HTTP_INTERNAL_ERROR : HttpURLConnection.HTTP_OK; + HttpURLConnection con = HttpUtils.getHttpConnection(url, expectedResponseCode, CONN_TIMEOUT); + BufferedReader br = HttpUtils.getConnectionStream(con); + String line = br.readLine(); + // Make sure the server gave us something back + assertNotNull(line); + con.disconnect(); + } catch (IOException e) { + // A message about a 500 code may be fine + if (!failureAllowed) { + throw e; + } + + } + + } + + protected void assertConsoleLogDoesNotContain(String message, String stringToCheckFor) throws Exception { + List lines = server.findStringsInFileInLibertyServerRoot(stringToCheckFor, CONSOLE_LOG); + assertTrue(message + " (found \'" + Arrays.toString(lines.toArray()) + "\'", + lines.isEmpty()); + + } + + protected void assertConsoleLogContains(String message, String stringToCheckFor) throws Exception { + assertFalse(message + " (could not find \'" + stringToCheckFor + "\')", + server.findStringsInFileInLibertyServerRoot(stringToCheckFor, CONSOLE_LOG).isEmpty()); + + } + + protected void assertConsoleLogCountEquals(String message, String stringToCheckFor, int count) throws Exception { + assertEquals(message, count, + server.findStringsInFileInLibertyServerRoot(stringToCheckFor, CONSOLE_LOG).size()); + + } + + protected void assertMessagesLogDoesNotContain(String message, String stringToCheckFor) throws Exception { + assertTrue(message, + server.findStringsInLogs(stringToCheckFor).isEmpty()); + + } + + protected void assertMessagesLogContains(String message, String stringToCheckFor) throws Exception { + assertFalse(message, + server.findStringsInLogs(stringToCheckFor).isEmpty()); + + } + + protected void assertTraceLogDoesNotContain(String message, String stringToCheckFor) throws Exception { + assertTrue(message, + server.findStringsInTrace(stringToCheckFor).isEmpty()); + + } + + protected void assertTraceLogContains(String message, String stringToCheckFor) throws Exception { + assertFalse(message, + server.findStringsInTrace(stringToCheckFor).isEmpty()); + + } +} diff --git a/dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/FATSuite.java b/dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/FATSuite.java new file mode 100755 index 00000000000..6995423fed5 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/FATSuite.java @@ -0,0 +1,30 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2011, 2017 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.logging.fat; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +/** + * + */ +@RunWith(Suite.class) +@SuiteClasses({ StackTraceFilteringForLoggedExceptionParametersTest.class, StackTraceFilteringForLoggedExceptionWithACauseParametersTest.class, + StackTraceFilteringForPrintedExceptionTest.class, StackTraceFilteringForPrintedExceptionWithIBMCodeAtTopTest.class, + StackTraceFilteringForNoClassDefFoundErrorTest.class, StackTraceFilteringForBadlyWrittenThrowableTest.class, + StackTraceFilteringForUserFeatureExceptionTest.class, StackTraceFilteringForIBMFeatureExceptionTest.class, + StackTraceFilteringForSpecificationClassesExceptionTest.class, InvalidTraceSpecificationTest.class, + HealthCenterTest.class, TestHideMessages.class, TestHideMsgDefinedBootstrap.class, IsoDateFormatTest.class }) +public class FATSuite { + +} diff --git a/dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/HealthCenterTest.java b/dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/HealthCenterTest.java new file mode 100755 index 00000000000..250dc8c240b --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/HealthCenterTest.java @@ -0,0 +1,48 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2014 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.logging.fat; + +import java.util.List; + +import org.junit.Assert; +import org.junit.Assume; +import org.junit.BeforeClass; +import org.junit.Test; + +import componenttest.topology.impl.LibertyServer; +import componenttest.topology.impl.LibertyServerFactory; +import componenttest.topology.utils.HttpUtils; + +public class HealthCenterTest { + private static final boolean J9 = System.getProperty("java.vm.name", "unknown").contains("J9"); + private static LibertyServer server; + + @BeforeClass + public static void beforeClass() { + Assume.assumeTrue(J9); + server = LibertyServerFactory.getStartedLibertyServer("com.ibm.ws.logging.healthcenter"); + } + + @Test + public void testHealthCenterInfo() throws Exception { + Assert.assertFalse("Expected healthcenter INFO message", + server.findStringsInLogs("^INFO:.*com\\.ibm\\.java\\.diagnostics\\.healthcenter\\.agent\\.iiop\\.port", + server.getConsoleLogFile()).isEmpty()); + } + + @Test + public void testConsoleLogLevelOff() throws Exception { + HttpUtils.findStringInReadyUrl(server, "/logger-servlet", "Hello world!"); + List messages = server.findStringsInLogs("Hello world!", server.getConsoleLogFile()); + Assert.assertTrue("Did not expect to find servlet Logger message: " + messages, messages.isEmpty()); + } +} diff --git a/dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/InvalidTraceSpecificationTest.java b/dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/InvalidTraceSpecificationTest.java new file mode 100755 index 00000000000..044a2f4f707 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/InvalidTraceSpecificationTest.java @@ -0,0 +1,164 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.logging.fat; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; + +import java.util.List; + +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.ibm.websphere.simplicity.config.Logging; +import com.ibm.websphere.simplicity.config.ServerConfiguration; +import componenttest.topology.impl.LibertyServer; +import componenttest.topology.impl.LibertyServerFactory; + +/** + * + */ +public class InvalidTraceSpecificationTest { + + protected static final String MESSAGE_LOG = "logs/messages.log"; + protected static final String INVALIDTRACEMSG = ""; + protected String invalidTraceSpec1 = "com.ibm.someInvalid.*=all"; + protected String invalidTraceSpec2 = "com.ibm.someMoreInvalid.*=all"; + private final String validTraceSpec1 = "com.ibm.ws.*=all"; + protected static LibertyServer server; + + @BeforeClass + public static void setUp() throws Exception { + server = LibertyServerFactory + .getLibertyServer("com.ibm.ws.logging.tracespec"); + System.out.println("Starting server)"); + server.startServer(); + System.out.println("Stared server)"); + } + + //Check if we have one Warning message with "com.ibm.someInvalid.*=all" + protected void checkOnlyOneInvalidTraceSpecEntryExists() throws Exception { + List lines = server.findStringsInFileInLibertyServerRoot("TRAS0040I", MESSAGE_LOG); + assertEquals("Message TRAS0040I not appeared or appeared more than once ", 1, lines.size()); + assertMessagesLogContains(lines.get(0), invalidTraceSpec1); + } + + protected void checkNoInvalidTraceSpecEntryExists() throws Exception { + List lines = server.findStringsInFileInLibertyServerRoot("TRAS0040I", MESSAGE_LOG); + assertEquals("Message TRAS0040I not appeared or appeared more than once ", 0, lines.size()); + } + + @Test + public void testInvalidTraceSpec() throws Exception { + Logging loggingObj; + ServerConfiguration serverConfig = server.getServerConfiguration(); + loggingObj = serverConfig.getLogging(); + loggingObj.setTraceSpecification(invalidTraceSpec1); + server.setMarkToEndOfLog(); + server.updateServerConfiguration(serverConfig); + server.waitForConfigUpdateInLogUsingMark(null); + + //Test 1: Check if TRAS0040I Message appears for invalid trace spec + checkOnlyOneInvalidTraceSpecEntryExists(); + } + + /* + * This test sets valid trace string now. + */ + @Test + public void testValidTraceSpec() throws Exception { + Logging loggingObj; + ServerConfiguration serverConfig = server.getServerConfiguration(); + loggingObj = serverConfig.getLogging(); + loggingObj.setTraceSpecification(validTraceSpec1); + server.setMarkToEndOfLog(); + server.updateServerConfiguration(serverConfig); + server.waitForConfigUpdateInLogUsingMark(null); + checkNoInvalidTraceSpecEntryExists(); + + } + + /* + * Test 3. + * - Stop Server + * - Update Config with invalid trace spec + * - start server + * - TRAS0040I shouldn't appear during startup. + */ + @Test + public void testInvalidTraceSpecOffline() throws Exception { + Logging loggingObj; + server.stopServer(); + //Offline test + ServerConfiguration serverConfig = server.getServerConfiguration(); + loggingObj = serverConfig.getLogging(); + loggingObj.setTraceSpecification(invalidTraceSpec1); + server.updateServerConfiguration(serverConfig); + //Offline test. + + server.startServer(); + checkNoInvalidTraceSpecEntryExists(); + + String existingTraceString = loggingObj.getTraceSpecification(); + loggingObj.setTraceSpecification(existingTraceString + ":" + validTraceSpec1); + server.setMarkToEndOfLog(); + server.updateServerConfiguration(serverConfig); + server.waitForConfigUpdateInLogUsingMark(null); + checkOnlyOneInvalidTraceSpecEntryExists(); + + } + + /* + * Test 4 + * - Update trace specification with invalidTraceSpec1 and invalidTraceSpec2 + * - Make sure the message TRAS0040I appears for both the invalid strings + */ + @Test + public void testMultipleInvalidTraceSpec() throws Exception { + Logging loggingObj; + + ServerConfiguration serverConfig = server.getServerConfiguration(); + loggingObj = serverConfig.getLogging(); + loggingObj.setTraceSpecification(invalidTraceSpec1 + ":" + invalidTraceSpec2); + server.setMarkToEndOfLog(); + server.updateServerConfiguration(serverConfig); + server.waitForConfigUpdateInLogUsingMark(null); + + List lines = server.findStringsInFileInLibertyServerRoot("TRAS0040I", MESSAGE_LOG); + assertEquals("Expecting multiple invalid trace spec message, but not found ", 1, lines.size()); + assertMessagesLogContains(lines.get(0), invalidTraceSpec1); + assertMessagesLogContains(lines.get(0), invalidTraceSpec2); + } + + protected void assertMessagesLogContains(String message, String stringToCheckFor) throws Exception { + assertFalse(message, + server.findStringsInLogs(stringToCheckFor).isEmpty()); + + } + + @Before + public void setup() throws Exception { + if (server != null && !server.isStarted()) { + server.startServer(); + } + } + + @After + public void tearDown() throws Exception { + if (server != null && server.isStarted()) { + server.stopServer(); + } + } + +} diff --git a/dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/IsoDateFormatTest.java b/dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/IsoDateFormatTest.java new file mode 100644 index 00000000000..9a3a4aa564b --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/IsoDateFormatTest.java @@ -0,0 +1,311 @@ +/* +* IBM Confidential +* +* OCO Source Materials +* +* WLP Copyright IBM Corp. 2017 +* +* The source code for this program is not published or otherwise divested +* of its trade secrets, irrespective of what has been deposited with the +* U.S. Copyright Office. +*/ +package com.ibm.ws.logging.fat; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.ProtocolException; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.ibm.websphere.simplicity.RemoteFile; +import com.ibm.websphere.simplicity.config.Logging; +import com.ibm.websphere.simplicity.config.ServerConfiguration; + +import componenttest.topology.impl.LibertyServer; +import componenttest.topology.impl.LibertyServerFactory; +import componenttest.topology.utils.HttpUtils; + +/** + * + */ +public class IsoDateFormatTest { + private static final String MESSAGE_LOG = "logs/messages.log"; + private static final String TRACE_LOG = "logs/trace.log"; + private static final String TRACE_SPEC = "com.ibm.ws.logging.*=all"; + private static final String SERVER_NAME = "com.ibm.ws.logging.isodateformat"; + private static final String INVALID_ISO_DATE_FORMAT_SERVER = "server-invalidIsoDateFormat.xml"; + private static final String ISO_8601_REGEX_PATTERN = "(\\d{4})\\-(\\d{2})\\-(\\d{2})T(\\d{2})\\:(\\d{2})\\:(\\d{2})\\.(\\d{3})[+-](\\d{4})"; //ISO 8601 Format : yyyy-MM-dd'T'HH:mm:ss.SSSZ + private static final int CONN_TIMEOUT = 10; + + private static LibertyServer server; + + @BeforeClass + public static void initialSetup() throws Exception { + server = LibertyServerFactory.getLibertyServer(SERVER_NAME); + System.out.println("Starting server..."); + server.startServer(); + System.out.println("Started server."); + + // Preserve the original server configuration + server.saveServerConfiguration(); + } + + @Before + public void setUp() throws Exception { + if (server != null && !server.isStarted()) { + // Restore the original server configuration, before starting the server for each test case. + server.restoreServerConfiguration(); + server.startServer(); + } + } + + @After + public void cleanUp() throws Exception { + if (server != null && server.isStarted()) { + server.stopServer(); + } + } + + /* + * This test sets the "isoDateFormat" attribute to true and verifies the ISO-8601 date format in the messages.log file. + */ + @Test + public void testIsoDateFormatInMessagesLog() throws Exception { + // Set isoDateFormat=true and traceSpec=off in server.xml + setServerConfiguration(true, false); + + List lines = server.findStringsInFileInLibertyServerRoot(ISO_8601_REGEX_PATTERN, MESSAGE_LOG); + assertTrue("The date and time was not formatted in ISO-8601 format in messages.log.", lines.size() > 0); + } + + /* + * This test sets the "isoDateFormat" attribute to true and verifies the ISO-8601 date format in the trace.log file. + */ + @Test + public void testIsoDateFormatInTraceLog() throws Exception { + // Set isoDateFormat=true and traceSpec=on in server.xml + setServerConfiguration(true, true); + + List lines = server.findStringsInFileInLibertyServerRoot(ISO_8601_REGEX_PATTERN, TRACE_LOG); + assertTrue("The date and time was not formatted in ISO-8601 format in trace.log.", lines.size() > 0); + } + + /* + * This test sets the "isoDateFormat" attribute to true and verifies the ISO-8601 date format in the FFDC log and summary files. + */ + @Test + public void testIsoDateFormatInFFDC() throws Exception { + // Set isoDateFormat = true and traceSpec=off in server.xml + setServerConfiguration(true, false); + + // Run application to generate FFDC + hitWebPage("ffdc-servlet", "FFDCServlet", true, "?generateFFDC=true"); + + // Get latest FFDC file + ArrayList ffdcFiles = server.listFFDCFiles(SERVER_NAME); + RemoteFile ffdcFile = server.getFFDCLogFile(ffdcFiles.get(ffdcFiles.size() - 1)); //Gets the latest FFDC file. + + List lines = server.findStringsInFileInLibertyServerRoot(ISO_8601_REGEX_PATTERN, "logs/ffdc/" + ffdcFile.getName()); + assertTrue("The date and time was not formatted in ISO-8601 format in FFDC file.", lines.size() > 0); + + // Get latest FFDC Summary file + ArrayList ffdcSummaryFiles = server.listFFDCSummaryFiles(SERVER_NAME); + RemoteFile ffdcSummaryFile = server.getFFDCSummaryFile(ffdcSummaryFiles.get(ffdcSummaryFiles.size() - 1)); //Gets the latest FFDC Summary file. + + lines = server.findStringsInFileInLibertyServerRoot(ISO_8601_REGEX_PATTERN, "logs/ffdc/" + ffdcSummaryFile.getName()); + assertTrue("The date and time was not formatted in ISO-8601 format in FFDC Summary file.", lines.size() > 0); + } + + /* + * This test sets the "isoDateFormat" attribute to an invalid value and verifies if the appropriate warning message is displayed + * and checks that the previously configured date format is applied. + */ + @Test + public void testInvalidIsoDateFormatAttributeValue() throws Exception { + // Set the invalid true value for attribute. e.g. "isoDateFormat=ture" + server.setServerConfigurationFile(INVALID_ISO_DATE_FORMAT_SERVER); + server.waitForConfigUpdateInLogUsingMark(null); + + List lines = server.findStringsInFileInLibertyServerRoot("CWWKG0081E", MESSAGE_LOG); + assertEquals("Error CWWKG0081E did not appear in messages.log", 1, lines.size()); + + lines = server.findStringsInFileInLibertyServerRoot("CWWKG0083W", MESSAGE_LOG); + assertEquals("Error CWWKG0083W did not appear in messages.log", 1, lines.size()); + + // Verify that the ISO-8601 date format is not set, and the previously configured Locale date format is being used. + lines = server.findStringsInFileInLibertyServerRoot(ISO_8601_REGEX_PATTERN, MESSAGE_LOG); + assertFalse("The date and time is being formatted in ISO-8601 format, instead of the default Locale format.", lines.size() > 0); + } + + /* + * This test sets the "isoDateFormat" attribute to true in the bootstrap.properties and verifies the ISO-8601 date format in the FFDC log and summary files. + */ + @Test + public void testIsoDateFormatSetInBootstrapProperties() throws Exception { + // Stop server, if running... + if (server != null && server.isStarted()) { + server.stopServer(); + } + + // Get the bootstrap.properties file and store the original content + RemoteFile bootstrapFile = server.getServerBootstrapPropertiesFile(); + + FileInputStream in = getFileInputStreamForRemoteFile(bootstrapFile); + Properties initialBootstrapProps = loadProperties(in); + + try { + // Update bootstrap.properties file with isoDateFormat = true + Properties newBootstrapProps = new Properties(); + newBootstrapProps.put("com.ibm.ws.logging.isoDateFormat", "true"); + + FileOutputStream out = getFileOutputStreamForRemoteFile(bootstrapFile, true); + writeProperties(newBootstrapProps, out); + + // Start server... + server.startServer(); + + // Check in messages.log file to see if the date and time is formatted in ISO-8601 format + List lines = server.findStringsInFileInLibertyServerRoot(ISO_8601_REGEX_PATTERN, MESSAGE_LOG); + assertTrue("The date and time was not formatted in ISO-8601 format in messages.log.", lines.size() > 0); + } finally { + // Restore the initial contents of bootstrap.properties + FileOutputStream out = getFileOutputStreamForRemoteFile(bootstrapFile, false); + writeProperties(initialBootstrapProps, out); + } + } + + /* + * This test dynamically changes the isoDateFormat attribute to true and false, and verifies if the date and time are formatted accordingly each time. + */ + @Test + public void testDynamicallyUpdatingIsoDateFormatAttribute() throws Exception { + // Verify if the date and time are in Locale format + List lines = server.findStringsInFileInLibertyServerRoot(ISO_8601_REGEX_PATTERN, MESSAGE_LOG); + assertFalse("The date and time is being formatted in ISO-8601 format, instead of the default Locale format.", lines.size() > 0); + + // Set the isoDateFormat=true and traceSpec=off in server.xml + setServerConfiguration(true, false); + + // Verify if the server was successfully updated + lines = server.findStringsInFileInLibertyServerRoot("CWWKG0017I", MESSAGE_LOG); + assertEquals("Message CWWKG0017I not appeared or appeared more than once ", 1, lines.size()); + + // Verify the date and time are in ISO-8601 format + lines = server.findStringsInFileInLibertyServerRoot(ISO_8601_REGEX_PATTERN, MESSAGE_LOG); + assertTrue("The date and time was not formatted in ISO-8601 format in messages.log.", lines.size() > 0); + + // Set the isoDateFormat=false and traceSpec=off in server.xml + setServerConfiguration(false, false); + + // Verify if the server was successfully updated again. + lines = server.findStringsInFileInLibertyServerRoot("CWWKG0017I", MESSAGE_LOG); + assertEquals("Message CWWKG0017I not appeared or appeared more than twice ", 2, lines.size()); + + // Verify if the date and time are in Locale format, by getting the latest server update success message (CWWKG0017I) + // and verifying if the string does not contain the ISO-8601 date format + String latestServerUpdateSuccessMsg = lines.get(1); + assertFalse("The date and time is being formatted in ISO-8601 format, instead of the default Locale format.", latestServerUpdateSuccessMsg.matches(ISO_8601_REGEX_PATTERN)); + } + + private FileInputStream getFileInputStreamForRemoteFile(RemoteFile bootstrapPropFile) throws Exception { + FileInputStream input = null; + try { + input = (FileInputStream) bootstrapPropFile.openForReading(); + } catch (Exception e) { + throw new Exception("Error while getting the FileInputStream for the remote bootstrap properties file."); + } + return input; + } + + private Properties loadProperties(FileInputStream input) throws IOException { + Properties props = new Properties(); + try { + props.load(input); + } catch (IOException e) { + + throw new IOException("Error while loading properties from the remote bootstrap properties file."); + } finally { + try { + input.close(); + } catch (IOException e1) { + throw new IOException("Error while closing the input stream."); + } + } + return props; + } + + private FileOutputStream getFileOutputStreamForRemoteFile(RemoteFile bootstrapPropFile, boolean append) throws Exception { + // Open the remote file for writing with append as false + FileOutputStream output = null; + try { + output = (FileOutputStream) bootstrapPropFile.openForWriting(append); + } catch (Exception e) { + throw new Exception("Error while getting FileOutputStream for the remote bootstrap properties file."); + } + return output; + } + + private void writeProperties(Properties props, FileOutputStream output) throws Exception { + // Write the properties to remote bootstrap properties file + try { + props.store(output, null); + } catch (IOException e) { + throw new Exception("Error while writing to the remote bootstrap properties file."); + } finally { + try { + output.close(); + } catch (IOException e) { + throw new IOException("Error while closing the output stream."); + } + } + } + + private static void setServerConfiguration(boolean useIsoDateFormat, boolean useTraceSpec) throws Exception { + Logging loggingObj; + ServerConfiguration serverConfig = server.getServerConfiguration(); + loggingObj = serverConfig.getLogging(); + if (useTraceSpec) { + loggingObj.setTraceSpecification(TRACE_SPEC); + } + loggingObj.setIsoDateFormat(useIsoDateFormat); + server.setMarkToEndOfLog(); + server.updateServerConfiguration(serverConfig); + server.waitForConfigUpdateInLogUsingMark(null); + } + + private static void hitWebPage(String contextRoot, String servletName, boolean failureAllowed, String params) throws MalformedURLException, IOException, ProtocolException { + try { + String urlStr = "http://" + server.getHostname() + ":" + server.getHttpDefaultPort() + "/" + contextRoot + "/" + servletName; + urlStr = params != null ? urlStr + params : urlStr; + URL url = new URL(urlStr); + int expectedResponseCode = failureAllowed ? HttpURLConnection.HTTP_INTERNAL_ERROR : HttpURLConnection.HTTP_OK; + HttpURLConnection con = HttpUtils.getHttpConnection(url, expectedResponseCode, CONN_TIMEOUT); + BufferedReader br = HttpUtils.getConnectionStream(con); + String line = br.readLine(); + // Make sure the server gave us something back + assertNotNull(line); + con.disconnect(); + } catch (IOException e) { + // A message about a 500 code may be fine + if (!failureAllowed) { + throw e; + } + } + } +} diff --git a/dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/StackTraceFilteringForBadlyWrittenThrowableTest.java b/dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/StackTraceFilteringForBadlyWrittenThrowableTest.java new file mode 100755 index 00000000000..47df688b1be --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/StackTraceFilteringForBadlyWrittenThrowableTest.java @@ -0,0 +1,67 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.logging.fat; + +import org.junit.BeforeClass; +import org.junit.Test; + +import componenttest.topology.impl.LibertyServerFactory; + +public class StackTraceFilteringForBadlyWrittenThrowableTest extends AbstractStackTraceFilteringTest { + + private static final String EXPECTED_EXCEPTION = "BadlyWrittenException"; + + @BeforeClass + public static void setUp() throws Exception { + server = LibertyServerFactory.getLibertyServer("com.ibm.ws.logging.brokenserver"); + + server.startServer(); + + //Make sure the application has come up before proceeding + server.addInstalledAppForValidation("broken-servlet"); + + // Hit the servlet, to drive the error + hitWebPage("broken-servlet", "BrokenWithABadlyWrittenThrowableServlet", true); + + } + + @Test + public void testConsoleDoesNotNPEForPrintedException() throws Exception { + assertConsoleLogContains("The console log did not have our exception in it at all.", + EXPECTED_EXCEPTION); + assertMessagesLogDoesNotContain("The console log had an NPE in it.", "NullPointerException"); + + } + + @Test + public void testMessagesIsNotTrimmedForPrintedException() throws Exception { + assertMessagesLogContains("The messages log did not have our exception in it at all.", + EXPECTED_EXCEPTION); + assertMessagesLogDoesNotContain("The messages log had a trimmed stack trace in it.", INTERNAL_CLASSES_REGEXP); + // We better have a line for the class that threw the exception + assertMessagesLogContains("The console stack didn't show the originating class.", + "at com.ibm.ws.logging.fat.servlet.BrokenWithABadlyWrittenThrowableServlet.doGet"); + // We also want at least one line about javax.servlet + assertMessagesLogContains("The console stack was trimmed too aggressively.", + "at javax.servlet.http.HttpServlet.service"); + assertMessagesLogContains("The console stack was apparently trimmed, but internal WAS classes got left in it", + "at com.ibm.ws.webcontainer"); + + } + + @Test + public void testTraceIsNotTrimmedForPrintedException() throws Exception { + assertTraceLogContains("The trace log did not have our exception in it at all.", + EXPECTED_EXCEPTION); + assertTraceLogDoesNotContain("The trace log had a trimmed stack trace in it.", INTERNAL_CLASSES_REGEXP); + } +} diff --git a/dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/StackTraceFilteringForIBMFeatureExceptionTest.java b/dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/StackTraceFilteringForIBMFeatureExceptionTest.java new file mode 100755 index 00000000000..85785f1a76f --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/StackTraceFilteringForIBMFeatureExceptionTest.java @@ -0,0 +1,78 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.logging.fat; + +import static org.junit.Assert.assertNotNull; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import componenttest.topology.impl.LibertyServerFactory; + +public class StackTraceFilteringForIBMFeatureExceptionTest extends AbstractStackTraceFilteringTest { + + private static final String MAIN_EXCEPTION = "ConfigurationReceivedException"; + private static final String BUNDLE_NAME = "test.configuration.fallalloverthefloor.ibmfeature_1.0.0"; + private static final String FEATURE_NAME = "unconfigurableIbmFeature-1.0"; + + @BeforeClass + public static void setUp() throws Exception { + server = LibertyServerFactory + .getLibertyServer("com.ibm.ws.logging.badconfig.ibm"); + + // install our user feature + server.installUserBundle(BUNDLE_NAME); // NO HYPHENS! NO ".jar" SUFFIX! + server.installUserFeature(FEATURE_NAME); // NO UNDERSCORES! NO ".mf" SUFFIX! + + // Just starting the server should be enough to get exceptions + server.startServer(); + // ... but to be safe, wait until we know the config has been driven + String successMessage = server.waitForStringInLog("The user feature is about to throw an exception."); + assertNotNull("The user feature should have produced a message saying it was active and about to fall all over the floor.", successMessage); + } + + @AfterClass + public static void tearDown() throws Exception { + server.stopServer(); + + server.uninstallUserBundle(BUNDLE_NAME); + server.uninstallFeature(FEATURE_NAME); + } + + @Test + public void testConsoleIsTrimmedForNastyInternalErrorFromIBMFeature() throws Exception { + assertConsoleLogContains("The console log should at the very least have our exception in it.", MAIN_EXCEPTION); + assertConsoleLogCountEquals("The console stack should only have one [internal classes] in it.", + INTERNAL_CLASSES_REGEXP, 1); + // The other methods from the user feature should still be in the stack trace + assertConsoleLogContains("The console log should have frames from the mock-IBM classes in it.", "reallyThrowAnException"); + assertConsoleLogDoesNotContain("The console log should not have more than one frames from the mock-IBM classes in it.", "thinkAboutThrowingAnException"); + + // We should have no SCR stuff, since SCR is calling a 'Liberty' feature + assertConsoleLogDoesNotContain("The SCR classes should not be in the console log", + "at org.apache.felix.scr.impl"); + // Similarly, the Java frames are just calls to Liberty code from SCR code so should be stripped + assertConsoleLogDoesNotContain("The console stack should not have any JVM frames in it.", + "at java."); + + } + + @Test + public void testMessagesIsNotTrimmedForNastyInternalErrorFromIBMFeature() throws Exception { + assertMessagesLogContains("The messages log should have our exception in it.", + MAIN_EXCEPTION); + assertMessagesLogContains("The console stack should have the scr packages we think our stack trace has in it", + "at org.apache.felix.scr.impl"); + assertMessagesLogDoesNotContain("The messages log should not have a trimmed stack trace in it.", INTERNAL_CLASSES_REGEXP); + } +} diff --git a/dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/StackTraceFilteringForLoggedExceptionParametersTest.java b/dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/StackTraceFilteringForLoggedExceptionParametersTest.java new file mode 100755 index 00000000000..a93042f3826 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/StackTraceFilteringForLoggedExceptionParametersTest.java @@ -0,0 +1,72 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.logging.fat; + +import org.junit.BeforeClass; +import org.junit.Test; + +import componenttest.topology.impl.LibertyServerFactory; + +public class StackTraceFilteringForLoggedExceptionParametersTest extends AbstractStackTraceFilteringTest { + + private static final String SPECIAL_BROKEN_EXCEPTION = "SpecialBrokenException"; + + @BeforeClass + public static void setUp() throws Exception { + server = LibertyServerFactory + .getLibertyServer("com.ibm.ws.logging.brokenserver"); + + server.startServer(); + + //Make sure the application has come up before proceeding + server.addInstalledAppForValidation("broken-servlet"); + + // Hit the servlet, to drive the error + hitWebPage("broken-servlet", "BrokenServlet", true); + + } + + @Test + public void testConsoleIsTrimmedForLoggedParameter() throws Exception { + assertConsoleLogContains("The console log did not have our exception in it at all.", + SPECIAL_BROKEN_EXCEPTION); + assertConsoleLogContains("The console stack was not trimmed.", + INTERNAL_CLASSES_REGEXP); + // We better have a line for the class that threw the exception + assertConsoleLogContains("The console stack was trimmed too aggressively and stripped out our servlet.", + "at com.ibm.ws.logging.fat.servlet.BrokenServlet.doGet"); + // We also want at least one line about javax.servlet + assertConsoleLogContains("The console stack was was trimmed too aggressively and stripped out the API we're using", + "at javax.servlet.http.HttpServlet.service"); + + // We don't want to be seeing anything that looks like internal WAS classes in the console + assertConsoleLogDoesNotContain("The console stack was apparently trimmed, but internal WAS classes got left in it", + "at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest"); + } + + @Test + public void testMessagesIsNotTrimmedForLoggedParameter() throws Exception { + assertMessagesLogContains("The messages log did not have our exception in it at all.", + SPECIAL_BROKEN_EXCEPTION); + assertMessagesLogDoesNotContain("The messages log had a trimmed stack trace in it.", INTERNAL_CLASSES_REGEXP); + // We don't want to be seeing anything that looks like internal WAS classes in the console + assertMessagesLogContains("The messages stack was apparently untrimmed, but it didn't have the internal WAS class stacks we expected in it", + "at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest"); + } + + @Test + public void testTraceIsNotTrimmedForLoggedParameter() throws Exception { + assertTraceLogContains("The trace log did not have our exception in it at all.", + SPECIAL_BROKEN_EXCEPTION); + assertTraceLogDoesNotContain("The trace log had a trimmed stack trace in it.", INTERNAL_CLASSES_REGEXP); + } +} diff --git a/dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/StackTraceFilteringForLoggedExceptionWithACauseParametersTest.java b/dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/StackTraceFilteringForLoggedExceptionWithACauseParametersTest.java new file mode 100755 index 00000000000..ca2e339fef1 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/StackTraceFilteringForLoggedExceptionWithACauseParametersTest.java @@ -0,0 +1,67 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.logging.fat; + +import org.junit.BeforeClass; +import org.junit.Test; + +import componenttest.topology.impl.LibertyServerFactory; + +public class StackTraceFilteringForLoggedExceptionWithACauseParametersTest extends AbstractStackTraceFilteringTest { + + private static final String EXCEPTION_WITH_A_CAUSE = "BrokenWithACauseException"; + private static final String CAUSE_EXCEPTION = "ReasonItAllWentWrongException"; + private static final String CAUSED_BY = "Caused by:"; + + @BeforeClass + public static void setUp() throws Exception { + server = LibertyServerFactory + .getLibertyServer("com.ibm.ws.logging.brokenserver"); + + server.startServer(); + + //Make sure the application has come up before proceeding + server.addInstalledAppForValidation("broken-servlet"); + + // Hit the servlet, to drive the error + hitWebPage("broken-servlet", "BrokenWithACauseServlet", true); + + } + + @Test + public void testConsoleIsTrimmedForLoggedParameter() throws Exception { + assertConsoleLogContains("The console log did not have our exception in it at all.", + EXCEPTION_WITH_A_CAUSE); + assertConsoleLogContains("The console stack was not trimmed.", + INTERNAL_CLASSES_REGEXP); + // We better have a line for the class that threw the exception + assertConsoleLogContains("The console stack was trimmed too aggressively and stripped out our servlet.", + "at com.ibm.ws.logging.fat.servlet.BrokenWithACauseServlet.doGet"); + + assertConsoleLogContains("The console log should say 'Caused by'", CAUSED_BY); + assertConsoleLogContains("The console log include the root cause", CAUSE_EXCEPTION); + + } + + @Test + public void testMessagesIsNotTrimmedForLoggedParameter() throws Exception { + assertMessagesLogContains("The messages log did not have our exception in it at all.", + EXCEPTION_WITH_A_CAUSE); + assertMessagesLogDoesNotContain("The messages log had a trimmed stack trace in it.", INTERNAL_CLASSES_REGEXP); + // We don't want to be seeing anything that looks like internal WAS classes in the console + assertMessagesLogContains("The messages stack was apparently untrimmed, but it didn't have the internal WAS class stacks we expected in it", + "at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest"); + assertConsoleLogContains("The console log should say 'Caused by'", CAUSED_BY); + assertConsoleLogContains("The console log include the root cause", CAUSE_EXCEPTION); + } + +} diff --git a/dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/StackTraceFilteringForNoClassDefFoundErrorTest.java b/dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/StackTraceFilteringForNoClassDefFoundErrorTest.java new file mode 100755 index 00000000000..5d81ff416e4 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/StackTraceFilteringForNoClassDefFoundErrorTest.java @@ -0,0 +1,85 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.logging.fat; + +import org.junit.BeforeClass; +import org.junit.Test; + +import componenttest.topology.impl.LibertyServerFactory; + +public class StackTraceFilteringForNoClassDefFoundErrorTest extends AbstractStackTraceFilteringTest { + + private static final String MAIN_EXCEPTION = "NoClassDefFoundError"; + private static final String NESTED_EXCEPTION = "ClassNotFoundException"; + private static final String CAUSED_BY = "Caused by:"; + + @BeforeClass + public static void setUp() throws Exception { + server = LibertyServerFactory + .getLibertyServer("com.ibm.ws.logging.missingfeatureserver"); + + server.startServer(); + + //Make sure the application has come up before proceeding + server.addInstalledAppForValidation("missing-feature-servlet"); + + hitWebPage("missing-feature-servlet", "MissingEntityManagerServlet", true); + } + + @Test + public void testConsoleIsTrimmedForNoClassDefFoundError() throws Exception { + assertConsoleLogContains("The console log did not have our exception in it at all.", + MAIN_EXCEPTION); + assertConsoleLogContains("The console stack was not trimmed.", + INTERNAL_CLASSES_REGEXP); + // We better have a line for the class that threw the exception, but don't make too many assumptions about what class that was + assertConsoleLogContains("The console stack didn't show the originating class.", + "at com.ibm.ws.logging"); + // We only want one line of WAS context + assertConsoleLogCountEquals("The console stack was apparently trimmed, but internal WAS classes got left in it", + "at com.ibm.ws.webcontainer", 1); + + } + + @Test + public void testRedundantCauseIsStrippedOutForNoClassDefFoundError() throws Exception { + assertConsoleLogContains("The console log should always have our exception in it.", + MAIN_EXCEPTION); + assertConsoleLogContains("The console log should have a line saying trimming happened.", INTERNAL_CLASSES_REGEXP); + assertConsoleLogDoesNotContain("The console log should not have anything about \"Caused by\"", + CAUSED_BY); + assertConsoleLogDoesNotContain("The console log should not have our nested exception in it.", + NESTED_EXCEPTION); + } + + @Test + public void testMessagesIsNotTrimmedForNoClassDefFoundError() throws Exception { + assertMessagesLogContains("The messages log should have our exception in it.", + MAIN_EXCEPTION); + assertMessagesLogDoesNotContain("The messages log should not have a trimmed stack trace in it.", INTERNAL_CLASSES_REGEXP); + assertMessagesLogContains("The messages log should have a 'Caused by' line in it.", + CAUSED_BY); + assertMessagesLogContains("The message log should have our nested exception in it.", + NESTED_EXCEPTION); + } + + @Test + public void testTraceIsNotTrimmedForNoClassDefFoundError() throws Exception { + assertTraceLogContains("The trace log should not have our exception in it.", + MAIN_EXCEPTION); + assertTraceLogDoesNotContain("The trace log had a trimmed stack trace in it.", INTERNAL_CLASSES_REGEXP); + assertTraceLogContains("The trace log should have a 'Caused by' line in it.", + CAUSED_BY); + assertTraceLogContains("The trace log should not have our nested exception in it.", + NESTED_EXCEPTION); + } +} diff --git a/dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/StackTraceFilteringForPrintedExceptionTest.java b/dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/StackTraceFilteringForPrintedExceptionTest.java new file mode 100755 index 00000000000..59631ac3bc8 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/StackTraceFilteringForPrintedExceptionTest.java @@ -0,0 +1,77 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.logging.fat; + +import org.junit.BeforeClass; +import org.junit.Test; + +import componenttest.topology.impl.LibertyServerFactory; + +public class StackTraceFilteringForPrintedExceptionTest extends AbstractStackTraceFilteringTest { + + private static final String SPECIAL_PRINTED_EXCEPTION = "SpecialPrintingException"; + + @BeforeClass + public static void setUp() throws Exception { + server = LibertyServerFactory.getLibertyServer("com.ibm.ws.logging.brokenserver"); + + server.startServer(); + + //Make sure the application has come up before proceeding + server.addInstalledAppForValidation("broken-servlet"); + + // Hit the servlet, to drive the error + hitWebPage("broken-servlet", "ExceptionPrintingServlet", false); + + } + + @Test + public void testConsoleIsTrimmedForPrintedException() throws Exception { + assertConsoleLogContains("The console log did not have our exception in it at all.", + SPECIAL_PRINTED_EXCEPTION); + assertConsoleLogContains("The console stack was not trimmed.", + INTERNAL_CLASSES_REGEXP); + // We better have a line for the class that threw the exception + assertConsoleLogContains("The console stack didn't show the originating class.", + "at com.ibm.ws.logging.fat.servlet.ExceptionPrintingServlet.doGet"); + assertConsoleLogContains("The console stack didn't show the inner originating class.", + "ExceptionGeneratingObject.hashCode"); + // We also want at least one line about javax.servlet + assertConsoleLogContains("The console stack was trimmed too aggressively.", + "at javax.servlet.http.HttpServlet.service"); + // We only want one line of internal WAS classes in the console + int traceCount = server.findStringsInFileInLibertyServerRoot(SPECIAL_PRINTED_EXCEPTION, CONSOLE_LOG).size(); + assertConsoleLogCountEquals("The console stack was apparently trimmed, but internal WAS classes got left in it", + "at com.ibm.ws.webcontainer", traceCount); + + // The java.* classes used by the user code should not be trimmed + assertConsoleLogContains("The console stack was trimmed too aggressively of java classes.", + "at java.util.HashMap.put"); + assertConsoleLogContains("The console stack was trimmed too aggressively of java classes.", + "at java.util.HashSet.add"); + + } + + @Test + public void testMessagesIsNotTrimmedForPrintedException() throws Exception { + assertMessagesLogContains("The messages log did not have our exception in it at all.", + SPECIAL_PRINTED_EXCEPTION); + assertMessagesLogDoesNotContain("The messages log had a trimmed stack trace in it.", INTERNAL_CLASSES_REGEXP); + } + + @Test + public void testTraceIsNotTrimmedForPrintedException() throws Exception { + assertTraceLogContains("The trace log did not have our exception in it at all.", + SPECIAL_PRINTED_EXCEPTION); + assertTraceLogDoesNotContain("The trace log had a trimmed stack trace in it.", INTERNAL_CLASSES_REGEXP); + } +} diff --git a/dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/StackTraceFilteringForPrintedExceptionWithIBMCodeAtTopTest.java b/dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/StackTraceFilteringForPrintedExceptionWithIBMCodeAtTopTest.java new file mode 100755 index 00000000000..5a9b218ffdd --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/StackTraceFilteringForPrintedExceptionWithIBMCodeAtTopTest.java @@ -0,0 +1,69 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.logging.fat; + +import org.junit.BeforeClass; +import org.junit.Test; + +import componenttest.topology.impl.LibertyServerFactory; + +public class StackTraceFilteringForPrintedExceptionWithIBMCodeAtTopTest extends AbstractStackTraceFilteringTest { + + private static final String EXPECTED_EXCEPTION = "javax.naming.NamingException"; + + @BeforeClass + public static void setUp() throws Exception { + server = LibertyServerFactory.getLibertyServer("com.ibm.ws.logging.brokenserver"); + + server.startServer(); + + //Make sure the application has come up before proceeding + server.addInstalledAppForValidation("broken-servlet"); + + // Hit the servlet, to drive the error + hitWebPage("broken-servlet", "IBMCodeAtTopExceptionPrintingServlet", false); + + } + + @Test + public void testConsoleIsTrimmedForPrintedExceptionThrownByIBMCode() throws Exception { + assertConsoleLogContains("The console log did not have our exception in it at all.", + EXPECTED_EXCEPTION); + assertConsoleLogContains("The console stack was not trimmed.", + INTERNAL_CLASSES_REGEXP); + // We better have a line for the class that threw the exception + assertConsoleLogContains("The console stack didn't show the originating class.", + "at com.ibm.ws.logging.fat.servlet.IBMCodeAtTopExceptionPrintingServlet.doGet"); + // We also want at least one line about javax.servlet + assertConsoleLogContains("The console stack was trimmed too aggressively.", + "at javax.servlet.http.HttpServlet.service"); + // We only want one line of internal WAS classes in the console + int traceCount = server.findStringsInFileInLibertyServerRoot(EXPECTED_EXCEPTION, CONSOLE_LOG).size(); + assertConsoleLogCountEquals("The console stack was apparently trimmed, but internal WAS classes got left in it", + "at com.ibm.ws.webcontainer", traceCount); + + } + + @Test + public void testMessagesIsNotTrimmedForPrintedExceptionThrownByIBMCode() throws Exception { + assertMessagesLogContains("The messages log did not have our exception in it at all.", + EXPECTED_EXCEPTION); + assertMessagesLogDoesNotContain("The messages log had a trimmed stack trace in it.", INTERNAL_CLASSES_REGEXP); + } + + @Test + public void testTraceIsNotTrimmedForPrintedExceptionThrownByIBMCode() throws Exception { + assertTraceLogContains("The trace log did not have our exception in it at all.", + EXPECTED_EXCEPTION); + assertTraceLogDoesNotContain("The trace log had a trimmed stack trace in it.", INTERNAL_CLASSES_REGEXP); + } +} diff --git a/dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/StackTraceFilteringForSpecificationClassesExceptionTest.java b/dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/StackTraceFilteringForSpecificationClassesExceptionTest.java new file mode 100755 index 00000000000..b96efd952a0 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/StackTraceFilteringForSpecificationClassesExceptionTest.java @@ -0,0 +1,73 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012, 2017 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.logging.fat; + +import org.junit.BeforeClass; +import org.junit.Test; + +import componenttest.topology.impl.LibertyServerFactory; + +/** + * A test which makes sure internal classes exported as spec-type API don't get filtered + * from the top of stack traces, but do get filtered from the middle. + * We want to see exceptions like + * + * java.lang.NullPointerException + * at javax.servlet.http.Cookie.isToken(Cookie.java:384) + * at javax.servlet.http.Cookie.(Cookie.java:124) + * at com.ibm.ws.logging.fat.servlet.SpecUsingServlet.doGet(SpecUsingServlet.java:40) + * at javax.servlet.http.HttpServlet.service(HttpServlet.java:575) + * at javax.servlet.http.HttpServlet.service(HttpServlet.java:668) + * at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1240) + * at [internal classes] + */ +public class StackTraceFilteringForSpecificationClassesExceptionTest extends AbstractStackTraceFilteringTest { + + private static final String MAIN_EXCEPTION = "NullPointerException"; + + @BeforeClass + public static void setUp() throws Exception { + server = LibertyServerFactory.getLibertyServer("com.ibm.ws.logging.brokenserver"); + + server.startServer(); + server.addInstalledAppForValidation("broken-servlet"); + hitWebPage("broken-servlet", "SpecUsingServlet", true); + } + + @Test + public void testConsoleIsTrimmedForUserUseOfSpecificationClass() throws Exception { + assertConsoleLogContains("The console log should at the very least have our exception in it.", MAIN_EXCEPTION); + // How many stack traces we get depends a bit on server internals, so to try and be more robust, + // count how many [ERROR] lines we get and match this + // We don't want to count errors that don't have stack traces, so try and exclude these by also checking + // for message id 'SRVE.*E'. This still isn't totally robust since it won't catch printed Errors + // if the message doesn't include the id 'SRVE.*E' or misspells it, as our current messages do + int errorCount = server.findStringsInFileInLibertyServerRoot("ERROR.*SRVE.*E", CONSOLE_LOG).size(); + int causedByCount = server.findStringsInFileInLibertyServerRoot("Caused by", CONSOLE_LOG).size(); + // Sanity check - we got an [ERROR], right? + assertConsoleLogContains("The console log should have [ERROR] prefix in it", "ERROR"); + + assertConsoleLogCountEquals("The console stack should only have one [internal classes] in it per stack trace.", + INTERNAL_CLASSES_REGEXP, errorCount); + // The javax.servlet methods shouldn't be stripped out, because they're spec used by the app + final int servletFrames = 9; + assertConsoleLogCountEquals("The console log should have several frames from the specification javax.servlet classes", "javax.servlet", servletFrames); + + assertConsoleLogContains("The console log should have the user class in it", "SpecUsingServlet"); + + // We want one line of internal WAS classes in the console + assertConsoleLogCountEquals("There should be exactly one IBM frame per stack trace", + "at com.ibm.ws.webcontainer", errorCount + causedByCount); + + } + +} diff --git a/dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/StackTraceFilteringForUserFeatureExceptionTest.java b/dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/StackTraceFilteringForUserFeatureExceptionTest.java new file mode 100755 index 00000000000..02f2336723f --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/StackTraceFilteringForUserFeatureExceptionTest.java @@ -0,0 +1,80 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2012 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.logging.fat; + +import static org.junit.Assert.assertNotNull; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import componenttest.topology.impl.LibertyServerFactory; + +public class StackTraceFilteringForUserFeatureExceptionTest extends AbstractStackTraceFilteringTest { + + private static final String MAIN_EXCEPTION = "ConfigurationReceivedException"; + private static final String BUNDLE_NAME = "test.configuration.fallalloverthefloor.userfeature_1.0.0"; + private static final String FEATURE_NAME = "unconfigurableUserFeature-1.0"; + + @BeforeClass + public static void setUp() throws Exception { + server = LibertyServerFactory + .getLibertyServer("com.ibm.ws.logging.badconfig.user"); + + // install our user feature + server.installUserBundle(BUNDLE_NAME); // NO HYPHENS! NO ".jar" SUFFIX! + server.installUserFeature(FEATURE_NAME); // NO UNDERSCORES! NO ".mf" SUFFIX! + + // Just starting the server should be enough to get exceptions + server.startServer(); + // ... but to be safe, wait until we know the config has been driven + String successMessage = server.waitForStringInLog("The user feature is about to throw an exception."); + assertNotNull("The user feature should have produced a message saying it was active and about to fall all over the floor.", successMessage); + } + + @AfterClass + public static void tearDown() throws Exception { + server.stopServer(); + + server.uninstallUserBundle(BUNDLE_NAME); + server.uninstallFeature(FEATURE_NAME); + } + + @Test + public void testConsoleIsTrimmedForNastyInternalErrorFromUserFeature() throws Exception { + assertConsoleLogContains("The console log should at the very least have our exception in it.", MAIN_EXCEPTION); + assertConsoleLogCountEquals("The console stack should only have one [internal classes] in it.", + INTERNAL_CLASSES_REGEXP, 1); + // The other methods from the user feature should still be in the stack trace + assertConsoleLogContains("The console log should have frames from the user classes in it.", "thinkAboutThrowingAnException"); + assertConsoleLogContains("The console log should have more than one frames from the user classes in it.", "reallyThrowAnException"); + + // We should have one line of scr stuff, since it's the last internal line before the java + // class packages are called, which count as third-party, and in the IBM->third party->user + // case, the third-party stuff survives + assertConsoleLogCountEquals("The console stack was apparently trimmed, but the SCR classes got left in it", + "at org.apache.felix.scr.impl", 1); + // We want a Java line, but only one + assertConsoleLogCountEquals("The console stack should have one Java lines in it.", + "at java.", 1); + + } + + @Test + public void testMessagesIsNotTrimmedForNastyInternalErrorFromUserFeature() throws Exception { + assertMessagesLogContains("The messages log should have our exception in it.", + MAIN_EXCEPTION); + assertMessagesLogContains("The console stack should have the scr packages we think our stack trace has in it", + "at org.apache.felix.scr.impl"); + assertMessagesLogDoesNotContain("The messages log should not have a trimmed stack trace in it.", INTERNAL_CLASSES_REGEXP); + } +} diff --git a/dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/TestHideMessages.java b/dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/TestHideMessages.java new file mode 100755 index 00000000000..2d21b73134e --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/TestHideMessages.java @@ -0,0 +1,90 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2014 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.logging.fat; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestName; + +import com.ibm.websphere.simplicity.log.Log; +import componenttest.topology.impl.LibertyServer; +import componenttest.topology.impl.LibertyServerFactory; + +/** + * + */ +public class TestHideMessages { + + private static LibertyServer msgServer = LibertyServerFactory.getLibertyServer("com.ibm.ws.logging.hidemessage"); + private static final Class logClass = TestHideMessages.class; + static String TWO_HIDDEDN_MESSAGE_SERVER = "server-twomessageids.xml"; + + static long SMALL_TIMEOUT = 10000; + @Rule + public TestName name = new TestName(); + + @BeforeClass + public static void prepareTest() throws Exception { + msgServer.startServer(); + } + + @Test + // No need to wait for message CWWKZ0058I/TRAS3001I since that happens during server startup. So using findStringsInLogs + public void testHiddenMsgIds() throws Exception { + + assertTrue("Hidden Message CWWKZ0058I should not be seen in messages.log", + msgServer.findStringsInLogs("CWWKZ0058I:", msgServer.getMatchingLogFile("messages.log")).isEmpty()); + assertTrue("Hidden Message CWWKZ0058I should not be seen in console.log", msgServer.findStringsInLogs("CWWKZ0058I:", msgServer.getMatchingLogFile("console.log")).isEmpty()); + assertFalse("Hidden Message CWWKZ0058I should be seen in trace", msgServer.findStringsInTrace("CWWKZ0058I:").isEmpty()); + assertFalse("Info message about redirection to trace file should be logged", + msgServer.findStringsInLogs("TRAS3001I:", msgServer.getMatchingLogFile("messages.log")).isEmpty()); + + } + + @Test + public void testDynamicAddMessageIds() throws Exception { + Log.info(logClass, name.getMethodName(), "Entering test " + name.getMethodName()); + // Need to capture CWWKF0012I messages that are in the logs from initial startup + int initial_messages_size_CWWKF0012I = msgServer.findStringsInLogs("CWWKF0012I:", msgServer.getMatchingLogFile("messages.log")).size(); + int initial_console_size_CWWKF0012I = msgServer.findStringsInLogs("CWWKF0012I:", msgServer.getMatchingLogFile("console.log")).size(); + int initial_trace_size_CWWKF0012I = msgServer.findStringsInTrace("CWWKF0012I:").size(); + + msgServer.setServerConfigurationFile(TWO_HIDDEDN_MESSAGE_SERVER); + + assertTrue("Hidden Message CWWKZ0058I should not be seen in messages.log", + msgServer.findStringsInLogs("CWWKZ0058I:", msgServer.getMatchingLogFile("messages.log")).isEmpty()); + assertTrue("Hidden Message CWWKZ0058I should not be seen in console.log", msgServer.findStringsInLogs("CWWKZ0058I:", msgServer.getMatchingLogFile("console.log")).isEmpty()); + assertFalse("Hidden Message CWWKZ0058I should be seen in trace", msgServer.findStringsInTrace("CWWKZ0058I:").isEmpty()); + + //This will wait for feature update completion message since we are adding a new feature. And CWWKF0012I should be seen before that + msgServer.waitForConfigUpdateInLogUsingMark(null); + assertTrue("Hidden Message CWWKF0012I should not be seen in messages.log", + msgServer.findStringsInLogs("CWWKF0012I:", msgServer.getMatchingLogFile("messages.log")).size() == initial_messages_size_CWWKF0012I); + assertTrue("Hidden Message CWWKF0012I should not be seen in console.log", + msgServer.findStringsInLogs("CWWKF0012I:", msgServer.getMatchingLogFile("console.log")).size() == initial_console_size_CWWKF0012I); + assertTrue("Hidden Message CWWKF0012I should be seen in trace", + msgServer.findStringsInTrace("CWWKF0012I:").size() == (initial_trace_size_CWWKF0012I + 1)); + + Log.info(logClass, name.getMethodName(), "Exiting test " + name.getMethodName()); + } + + @AfterClass + public static void completeTest() throws Exception { + msgServer.stopServer(); + } + +} diff --git a/dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/TestHideMsgDefinedBootstrap.java b/dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/TestHideMsgDefinedBootstrap.java new file mode 100755 index 00000000000..bf7bc50c114 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/fat/src/com/ibm/ws/logging/fat/TestHideMsgDefinedBootstrap.java @@ -0,0 +1,62 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2014 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.logging.fat; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestName; + +import componenttest.topology.impl.LibertyServer; +import componenttest.topology.impl.LibertyServerFactory; + +/** + * + */ +public class TestHideMsgDefinedBootstrap { + + private static LibertyServer msgServer = LibertyServerFactory.getLibertyServer("com.ibm.ws.logging.hidemsg.bootstrap"); + private static final Class logClass = TestHideMsgDefinedBootstrap.class; + + @Rule + public TestName name = new TestName(); + + @BeforeClass + public static void prepareTest() throws Exception { + msgServer.startServer(); + } + + @Test + public void testHiddenMsgIds() throws Exception { + assertTrue("Hidden Message CWWKZ0058I should not be seen in messages.log", + msgServer.findStringsInLogs("CWWKZ0058I:", msgServer.getMatchingLogFile("messages.log")).isEmpty()); + assertTrue("Hidden Message CWWKZ0058I should not be seen in console.log", msgServer.findStringsInLogs("CWWKZ0058I:", msgServer.getMatchingLogFile("console.log")).isEmpty()); + assertFalse("Hidden Message CWWKZ0058I should be seen in trace", msgServer.findStringsInTrace("CWWKZ0058I:").isEmpty()); + } + + @Test + public void testSuppressedIdsInMsgHeader() throws Exception { + assertFalse("Suppressed Message Ids logged in header ", + msgServer.findStringsInLogs("Suppressed message ids:", msgServer.getMatchingLogFile("messages.log")).isEmpty()); + + } + + @AfterClass + public static void completeTest() throws Exception { + msgServer.stopServer(); + } + +} diff --git a/dev/com.ibm.ws.logging_fat/publish/.gitignore b/dev/com.ibm.ws.logging_fat/publish/.gitignore new file mode 100644 index 00000000000..0968b1bceb6 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/publish/.gitignore @@ -0,0 +1 @@ +/bundles diff --git a/dev/com.ibm.ws.logging_fat/publish/features/unconfigurableIbmFeature-1.0.mf b/dev/com.ibm.ws.logging_fat/publish/features/unconfigurableIbmFeature-1.0.mf new file mode 100755 index 00000000000..db84826829b --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/publish/features/unconfigurableIbmFeature-1.0.mf @@ -0,0 +1,7 @@ +Subsystem-ManifestVersion: 1 +IBM-ShortName: unconfigurableIbmFeature-1.0 +Subsystem-SymbolicName: com.ibm.ws.logging.unconfigurableibmfeature-1.0; visibility:=public +Subsystem-Version: 1.0.0 +Subsystem-Content: test.configuration.fallalloverthefloor.ibmfeature; version="[1,1.0.100)", +Subsystem-Type: osgi.subsystem.feature +IBM-Feature-Version: 2 diff --git a/dev/com.ibm.ws.logging_fat/publish/features/unconfigurableUserFeature-1.0.mf b/dev/com.ibm.ws.logging_fat/publish/features/unconfigurableUserFeature-1.0.mf new file mode 100755 index 00000000000..79ee094debd --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/publish/features/unconfigurableUserFeature-1.0.mf @@ -0,0 +1,7 @@ +Subsystem-ManifestVersion: 1 +IBM-ShortName: unconfigurableUserFeature-1.0 +Subsystem-SymbolicName: com.ibm.ws.logging.unconfigurableuserfeature-1.0; visibility:=public +Subsystem-Version: 1.0.0 +Subsystem-Content: test.configuration.fallalloverthefloor.userfeature; version="[1,1.0.100)", +Subsystem-Type: osgi.subsystem.feature +IBM-Feature-Version: 2 diff --git a/dev/com.ibm.ws.logging_fat/publish/files/server-invalidIsoDateFormat.xml b/dev/com.ibm.ws.logging_fat/publish/files/server-invalidIsoDateFormat.xml new file mode 100755 index 00000000000..1df05405bb3 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/publish/files/server-invalidIsoDateFormat.xml @@ -0,0 +1,9 @@ + + + jsp-2.2 + + + + + + diff --git a/dev/com.ibm.ws.logging_fat/publish/files/server-twomessageids.xml b/dev/com.ibm.ws.logging_fat/publish/files/server-twomessageids.xml new file mode 100755 index 00000000000..ce86dd23a23 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/publish/files/server-twomessageids.xml @@ -0,0 +1,11 @@ + + + jsp-2.2 + ssl-1.0 + + + + + + + diff --git a/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.badconfig.ibm/.gitignore b/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.badconfig.ibm/.gitignore new file mode 100644 index 00000000000..2b09f7ba1e1 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.badconfig.ibm/.gitignore @@ -0,0 +1 @@ +/apps diff --git a/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.badconfig.ibm/bootstrap.properties b/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.badconfig.ibm/bootstrap.properties new file mode 100755 index 00000000000..31f32c6fd52 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.badconfig.ibm/bootstrap.properties @@ -0,0 +1 @@ +bootstrap.include=../testports.properties \ No newline at end of file diff --git a/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.badconfig.ibm/server.xml b/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.badconfig.ibm/server.xml new file mode 100755 index 00000000000..da45c5a6553 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.badconfig.ibm/server.xml @@ -0,0 +1,11 @@ + + + + + + + servlet-3.0 + usr:unconfigurableIbmFeature-1.0 + + + diff --git a/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.badconfig.user/.gitignore b/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.badconfig.user/.gitignore new file mode 100644 index 00000000000..2b09f7ba1e1 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.badconfig.user/.gitignore @@ -0,0 +1 @@ +/apps diff --git a/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.badconfig.user/bootstrap.properties b/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.badconfig.user/bootstrap.properties new file mode 100755 index 00000000000..31f32c6fd52 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.badconfig.user/bootstrap.properties @@ -0,0 +1 @@ +bootstrap.include=../testports.properties \ No newline at end of file diff --git a/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.badconfig.user/server.xml b/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.badconfig.user/server.xml new file mode 100755 index 00000000000..b36cf13d721 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.badconfig.user/server.xml @@ -0,0 +1,11 @@ + + + + + + + servlet-3.0 + usr:unconfigurableUserFeature-1.0 + + + diff --git a/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.brokenserver/bootstrap.properties b/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.brokenserver/bootstrap.properties new file mode 100755 index 00000000000..31f32c6fd52 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.brokenserver/bootstrap.properties @@ -0,0 +1 @@ +bootstrap.include=../testports.properties \ No newline at end of file diff --git a/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.brokenserver/server.xml b/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.brokenserver/server.xml new file mode 100755 index 00000000000..413710708a2 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.brokenserver/server.xml @@ -0,0 +1,9 @@ + + + + + + jsp-2.2 + + + diff --git a/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.healthcenter/bootstrap.properties b/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.healthcenter/bootstrap.properties new file mode 100755 index 00000000000..f67f7f4db10 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.healthcenter/bootstrap.properties @@ -0,0 +1,2 @@ +bootstrap.include=../testports.properties +com.ibm.ws.logging.console.log.level=OFF diff --git a/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.healthcenter/jvm.options b/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.healthcenter/jvm.options new file mode 100755 index 00000000000..70bb64f28bb --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.healthcenter/jvm.options @@ -0,0 +1 @@ +-Xhealthcenter \ No newline at end of file diff --git a/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.healthcenter/server.xml b/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.healthcenter/server.xml new file mode 100755 index 00000000000..9a5836e936c --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.healthcenter/server.xml @@ -0,0 +1,7 @@ + + + jsp-2.2 + + + + diff --git a/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.hidemessage/server.xml b/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.hidemessage/server.xml new file mode 100755 index 00000000000..d64a00016be --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.hidemessage/server.xml @@ -0,0 +1,9 @@ + + + jsp-2.2 + + + + + + diff --git a/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.hidemsg.bootstrap/bootstrap.properties b/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.hidemsg.bootstrap/bootstrap.properties new file mode 100755 index 00000000000..d60ff633c37 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.hidemsg.bootstrap/bootstrap.properties @@ -0,0 +1 @@ +com.ibm.ws.logging.hideMessage=CWWKZ0058I \ No newline at end of file diff --git a/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.hidemsg.bootstrap/server.xml b/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.hidemsg.bootstrap/server.xml new file mode 100755 index 00000000000..9a5836e936c --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.hidemsg.bootstrap/server.xml @@ -0,0 +1,7 @@ + + + jsp-2.2 + + + + diff --git a/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.isodateformat/bootstrap.properties b/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.isodateformat/bootstrap.properties new file mode 100755 index 00000000000..4f1ae5a2e10 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.isodateformat/bootstrap.properties @@ -0,0 +1 @@ +bootstrap.include=../testports.properties diff --git a/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.isodateformat/server.xml b/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.isodateformat/server.xml new file mode 100644 index 00000000000..085212527e3 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.isodateformat/server.xml @@ -0,0 +1,8 @@ + + + + + + jsp-2.2 + + diff --git a/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.missingfeatureserver/bootstrap.properties b/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.missingfeatureserver/bootstrap.properties new file mode 100755 index 00000000000..31f32c6fd52 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.missingfeatureserver/bootstrap.properties @@ -0,0 +1 @@ +bootstrap.include=../testports.properties \ No newline at end of file diff --git a/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.missingfeatureserver/server.xml b/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.missingfeatureserver/server.xml new file mode 100755 index 00000000000..413710708a2 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.missingfeatureserver/server.xml @@ -0,0 +1,9 @@ + + + + + + jsp-2.2 + + + diff --git a/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.tracespec/bootstrap.properties b/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.tracespec/bootstrap.properties new file mode 100755 index 00000000000..31f32c6fd52 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.tracespec/bootstrap.properties @@ -0,0 +1 @@ +bootstrap.include=../testports.properties \ No newline at end of file diff --git a/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.tracespec/server.xml b/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.tracespec/server.xml new file mode 100755 index 00000000000..779892ce757 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/publish/servers/com.ibm.ws.logging.tracespec/server.xml @@ -0,0 +1,8 @@ + + + + + + jsp-2.2 + + diff --git a/dev/com.ibm.ws.logging_fat/test-applications/broken-servlet/resources/.gitignore b/dev/com.ibm.ws.logging_fat/test-applications/broken-servlet/resources/.gitignore new file mode 100644 index 00000000000..50d9e9338c7 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/test-applications/broken-servlet/resources/.gitignore @@ -0,0 +1 @@ +/WEB-INF diff --git a/dev/com.ibm.ws.logging_fat/test-applications/broken-servlet/resources/META-INF/MANIFEST.MF b/dev/com.ibm.ws.logging_fat/test-applications/broken-servlet/resources/META-INF/MANIFEST.MF new file mode 100755 index 00000000000..254272e1c07 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/test-applications/broken-servlet/resources/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Class-Path: + diff --git a/dev/com.ibm.ws.logging_fat/test-applications/broken-servlet/src/com/ibm/ws/logging/fat/servlet/BrokenServlet.java b/dev/com.ibm.ws.logging_fat/test-applications/broken-servlet/src/com/ibm/ws/logging/fat/servlet/BrokenServlet.java new file mode 100755 index 00000000000..fbe28197760 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/test-applications/broken-servlet/src/com/ibm/ws/logging/fat/servlet/BrokenServlet.java @@ -0,0 +1,44 @@ +package com.ibm.ws.logging.fat.servlet; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * Servlet which throws an exception. + */ +@WebServlet("/BrokenServlet") +public class BrokenServlet extends HttpServlet { + private static final long serialVersionUID = 1L; + + /** + * @see HttpServlet#HttpServlet() + */ + public BrokenServlet() { + super(); + } + + /** + * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) + */ + @Override + protected void doGet(HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException { + response.setContentType("text/plain"); + + // Whoops, we seem to have a problem! Oh dear, how unexpected! + throw new SpecialBrokenException(); + + } + + static class SpecialBrokenException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + } + +} diff --git a/dev/com.ibm.ws.logging_fat/test-applications/broken-servlet/src/com/ibm/ws/logging/fat/servlet/BrokenWithABadlyWrittenThrowableServlet.java b/dev/com.ibm.ws.logging_fat/test-applications/broken-servlet/src/com/ibm/ws/logging/fat/servlet/BrokenWithABadlyWrittenThrowableServlet.java new file mode 100755 index 00000000000..abdb445489b --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/test-applications/broken-servlet/src/com/ibm/ws/logging/fat/servlet/BrokenWithABadlyWrittenThrowableServlet.java @@ -0,0 +1,50 @@ +package com.ibm.ws.logging.fat.servlet; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * Servlet which throws an exception. The getStackTrace() method on the exception returns null. + */ +@WebServlet("/BrokenWithABadlyWrittenThrowableServlet") +public class BrokenWithABadlyWrittenThrowableServlet extends HttpServlet { + private static final long serialVersionUID = 1L; + + /** + * @see HttpServlet#HttpServlet() + */ + public BrokenWithABadlyWrittenThrowableServlet() { + super(); + } + + /** + * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) + */ + @Override + protected void doGet(HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException { + response.setContentType("text/plain"); + + // Whoops, we seem to have a problem! Oh dear, how unexpected! + throw new BadlyWrittenException(); + + } + + static class BadlyWrittenException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + @Override + public StackTraceElement[] getStackTrace() { + // Can our logging code handle this? + return null; + } + + } + +} diff --git a/dev/com.ibm.ws.logging_fat/test-applications/broken-servlet/src/com/ibm/ws/logging/fat/servlet/BrokenWithACauseServlet.java b/dev/com.ibm.ws.logging_fat/test-applications/broken-servlet/src/com/ibm/ws/logging/fat/servlet/BrokenWithACauseServlet.java new file mode 100755 index 00000000000..c5214b2390d --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/test-applications/broken-servlet/src/com/ibm/ws/logging/fat/servlet/BrokenWithACauseServlet.java @@ -0,0 +1,52 @@ +package com.ibm.ws.logging.fat.servlet; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * Servlet which throws an exception. + */ +@WebServlet("/BrokenWithACauseServlet") +public class BrokenWithACauseServlet extends HttpServlet { + private static final long serialVersionUID = 1L; + + /** + * @see HttpServlet#HttpServlet() + */ + public BrokenWithACauseServlet() { + super(); + } + + /** + * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) + */ + @Override + protected void doGet(HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException { + response.setContentType("text/plain"); + + ReasonItAllWentWrongException reasonItAllWentWrongException = new ReasonItAllWentWrongException(); + throw new BrokenWithACauseException(reasonItAllWentWrongException); + + } + + static class BrokenWithACauseException extends RuntimeException { + public BrokenWithACauseException(ReasonItAllWentWrongException reasonItAllWentWrongException) { + super("arbitrary message", reasonItAllWentWrongException); + } + + private static final long serialVersionUID = 1L; + + } + + static class ReasonItAllWentWrongException extends Exception { + private static final long serialVersionUID = 1L; + + } + +} diff --git a/dev/com.ibm.ws.logging_fat/test-applications/broken-servlet/src/com/ibm/ws/logging/fat/servlet/ExceptionPrintingServlet.java b/dev/com.ibm.ws.logging_fat/test-applications/broken-servlet/src/com/ibm/ws/logging/fat/servlet/ExceptionPrintingServlet.java new file mode 100755 index 00000000000..89c159af369 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/test-applications/broken-servlet/src/com/ibm/ws/logging/fat/servlet/ExceptionPrintingServlet.java @@ -0,0 +1,70 @@ +package com.ibm.ws.logging.fat.servlet; + +import java.io.IOException; +import java.util.HashSet; +import java.util.Set; + +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * Servlet which prints an exception. + */ +@WebServlet("/ExceptionPrintingServlet") +public class ExceptionPrintingServlet extends HttpServlet { + private static final long serialVersionUID = 1L; + + /** + * @see HttpServlet#HttpServlet() + */ + public ExceptionPrintingServlet() { + super(); + } + + /** + * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) + */ + @Override + protected void doGet(HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException { + response.setContentType("text/plain"); + + response.getWriter().println("Well, hello there. This servlet is working."); + + // Generate a few lines of java stack trace + Set set = new HashSet(); + set.add(new ExceptionGeneratingObject(true)); + set.add(new ExceptionGeneratingObject(false)); + + response.getWriter().println("There should be an exception in your logs."); + + } + + static class SpecialPrintingException extends Exception { + + private static final long serialVersionUID = 1L; + + } + + static class ExceptionGeneratingObject { + private final boolean shouldPrintException; + + public ExceptionGeneratingObject(boolean b) { + shouldPrintException = b; + } + + @Override + public int hashCode() { + if (shouldPrintException) { + new SpecialPrintingException().printStackTrace(); + return 1; + } else { + return -1; + } + } + } + +} diff --git a/dev/com.ibm.ws.logging_fat/test-applications/broken-servlet/src/com/ibm/ws/logging/fat/servlet/IBMCodeAtTopExceptionPrintingServlet.java b/dev/com.ibm.ws.logging_fat/test-applications/broken-servlet/src/com/ibm/ws/logging/fat/servlet/IBMCodeAtTopExceptionPrintingServlet.java new file mode 100755 index 00000000000..471e8c361a4 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/test-applications/broken-servlet/src/com/ibm/ws/logging/fat/servlet/IBMCodeAtTopExceptionPrintingServlet.java @@ -0,0 +1,49 @@ +package com.ibm.ws.logging.fat.servlet; + +import java.io.IOException; + +import javax.naming.InitialContext; +import javax.naming.NamingException; +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * Servlet which prints an exception. + */ +@WebServlet("/IBMCodeAtTopExceptionPrintingServlet") +public class IBMCodeAtTopExceptionPrintingServlet extends HttpServlet { + private static final long serialVersionUID = 1L; + + /** + * @see HttpServlet#HttpServlet() + */ + public IBMCodeAtTopExceptionPrintingServlet() { + super(); + } + + /** + * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) + */ + @Override + protected void doGet(HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException { + response.setContentType("text/plain"); + + response.getWriter().println("Howdy! This servlet is working just fine, except for all the bits that are deliberately broken."); + + // In the absence of the jndi feature, this lookup shouldn't go well + try { + InitialContext ctx = new InitialContext(); + ctx.lookup("something/That/Does/Not/Exist"); + } catch (NamingException e) { + // Print the stack trace, and see what happens + e.printStackTrace(); + } + + response.getWriter().println("There should be an exception in your logs."); + + } +} diff --git a/dev/com.ibm.ws.logging_fat/test-applications/broken-servlet/src/com/ibm/ws/logging/fat/servlet/SpecUsingServlet.java b/dev/com.ibm.ws.logging_fat/test-applications/broken-servlet/src/com/ibm/ws/logging/fat/servlet/SpecUsingServlet.java new file mode 100755 index 00000000000..958d533ed6f --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/test-applications/broken-servlet/src/com/ibm/ws/logging/fat/servlet/SpecUsingServlet.java @@ -0,0 +1,65 @@ +package com.ibm.ws.logging.fat.servlet; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * Servlet which prints an exception. + */ +@WebServlet("/SpecUsingServlet") +public class SpecUsingServlet extends HttpServlet { + private static final long serialVersionUID = 1L; + + /** + * @see HttpServlet#HttpServlet() + */ + public SpecUsingServlet() { + super(); + } + + /** + * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) + */ + @Override + protected void doGet(HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException { + response.setContentType("text/plain"); + + response.getWriter().println("This servlet uses specification classes, but you shouldn't see this message."); + // Generate an exception which has a few lines of javax.servlet.* content in it + Cookie cookie = new Cookie(null, null); + response.addCookie(cookie); + + } + + static class SpecialPrintingException extends Exception { + + private static final long serialVersionUID = 1L; + + } + + static class ExceptionGeneratingObject { + private final boolean shouldPrintException; + + public ExceptionGeneratingObject(boolean b) { + shouldPrintException = b; + } + + @Override + public int hashCode() { + if (shouldPrintException) { + new SpecialPrintingException().printStackTrace(); + return 1; + } else { + return -1; + } + } + } + +} diff --git a/dev/com.ibm.ws.logging_fat/test-applications/ffdc-servlet/resources/.gitignore b/dev/com.ibm.ws.logging_fat/test-applications/ffdc-servlet/resources/.gitignore new file mode 100644 index 00000000000..50d9e9338c7 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/test-applications/ffdc-servlet/resources/.gitignore @@ -0,0 +1 @@ +/WEB-INF diff --git a/dev/com.ibm.ws.logging_fat/test-applications/ffdc-servlet/resources/META-INF/MANIFEST.MF b/dev/com.ibm.ws.logging_fat/test-applications/ffdc-servlet/resources/META-INF/MANIFEST.MF new file mode 100755 index 00000000000..254272e1c07 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/test-applications/ffdc-servlet/resources/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Class-Path: + diff --git a/dev/com.ibm.ws.logging_fat/test-applications/ffdc-servlet/src/com/ibm/ws/logging/fat/servlet/FFDCServlet.java b/dev/com.ibm.ws.logging_fat/test-applications/ffdc-servlet/src/com/ibm/ws/logging/fat/servlet/FFDCServlet.java new file mode 100755 index 00000000000..1e27d6d6dda --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/test-applications/ffdc-servlet/src/com/ibm/ws/logging/fat/servlet/FFDCServlet.java @@ -0,0 +1,26 @@ +package com.ibm.ws.logging.fat.servlet; + +import java.io.IOException; +import java.util.logging.Logger; + +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +@WebServlet("/FFDCServlet") +public class FFDCServlet extends HttpServlet { + + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + response.getWriter().println("Test Servlet to generate FFDC"); + + String generateFFDC = request.getParameter("generateFFDC"); + + if ((generateFFDC != null) && (generateFFDC.equalsIgnoreCase("true"))) { + // Divide by zero, to get an ArithmeticException, which will generate an FFDC + int i = 10 / 0; + } + } +} diff --git a/dev/com.ibm.ws.logging_fat/test-applications/logger-servlet/resources/.gitignore b/dev/com.ibm.ws.logging_fat/test-applications/logger-servlet/resources/.gitignore new file mode 100644 index 00000000000..50d9e9338c7 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/test-applications/logger-servlet/resources/.gitignore @@ -0,0 +1 @@ +/WEB-INF diff --git a/dev/com.ibm.ws.logging_fat/test-applications/logger-servlet/resources/META-INF/MANIFEST.MF b/dev/com.ibm.ws.logging_fat/test-applications/logger-servlet/resources/META-INF/MANIFEST.MF new file mode 100755 index 00000000000..254272e1c07 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/test-applications/logger-servlet/resources/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Class-Path: + diff --git a/dev/com.ibm.ws.logging_fat/test-applications/logger-servlet/src/com/ibm/ws/logging/fat/servlet/LoggerServlet.java b/dev/com.ibm.ws.logging_fat/test-applications/logger-servlet/src/com/ibm/ws/logging/fat/servlet/LoggerServlet.java new file mode 100755 index 00000000000..2da44805cc2 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/test-applications/logger-servlet/src/com/ibm/ws/logging/fat/servlet/LoggerServlet.java @@ -0,0 +1,24 @@ +package com.ibm.ws.logging.fat.servlet; + +import java.io.IOException; +import java.util.logging.Logger; + +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +@WebServlet("/*") +@SuppressWarnings("serial") +public class LoggerServlet extends HttpServlet { + private static final Logger logger = Logger.getLogger(LoggerServlet.class.getName()); + + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + response.getWriter().println("Hello world!"); + // Use severe, which is higher than AUDIT, to ensure this message would + // normally show up in console.log if output wasn't disabled. + logger.severe("Hello world!"); + } +} diff --git a/dev/com.ibm.ws.logging_fat/test-applications/missing-feature-servlet/.gitignore b/dev/com.ibm.ws.logging_fat/test-applications/missing-feature-servlet/.gitignore new file mode 100644 index 00000000000..e47e1b33a74 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/test-applications/missing-feature-servlet/.gitignore @@ -0,0 +1 @@ +/resources diff --git a/dev/com.ibm.ws.logging_fat/test-applications/missing-feature-servlet/src/com/ibm/ws/logging/fat/servlet/MissingEntityManagerServlet.java b/dev/com.ibm.ws.logging_fat/test-applications/missing-feature-servlet/src/com/ibm/ws/logging/fat/servlet/MissingEntityManagerServlet.java new file mode 100755 index 00000000000..326e4f7a340 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/test-applications/missing-feature-servlet/src/com/ibm/ws/logging/fat/servlet/MissingEntityManagerServlet.java @@ -0,0 +1,60 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.logging.fat.servlet; + +import java.io.IOException; +import java.util.List; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.Query; +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * A servlet with a dependency on JPA, running in a server with no jpa feature loaded. What could + * possibly go wrong? + */ +@WebServlet("/MissingEntityManagerServlet") +public class MissingEntityManagerServlet extends HttpServlet { + + private static final long serialVersionUID = 1L; + + @PersistenceContext(unitName = "thiswontworkpu") + private EntityManager em; + + /** + * @see HttpServlet#HttpServlet() + */ + public MissingEntityManagerServlet() { + super(); + } + + /** + * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) + */ + @Override + protected void doGet(HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException { + response.getWriter().println("About to try and run a query on the entity manager we don't have."); + String query = "SELECT f FROM ChocolateOrder f"; + Query q = em.createQuery(query); + + List list = q.getResultList(); + response.getWriter().println("How did that work out?" + list); + + } + +} diff --git a/dev/com.ibm.ws.logging_fat/test-bundles/test.configuration.fallalloverthefloor.ibmfeature/bnd.bnd b/dev/com.ibm.ws.logging_fat/test-bundles/test.configuration.fallalloverthefloor.ibmfeature/bnd.bnd new file mode 100755 index 00000000000..4d6d8c13458 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/test-bundles/test.configuration.fallalloverthefloor.ibmfeature/bnd.bnd @@ -0,0 +1,19 @@ +# Simulate a failure in Liberty code by having a user feature which looks like IBM code +Bundle-Vendor: IBM +bVersion=1.0.0 +Bundle-Version: 1.0.0 +Bundle-Name: Exception throwing feature +Bundle-Description: This feature throws an exception +Bundle-SymbolicName: test.configuration.fallalloverthefloor.ibmfeature; singleton:=true + +Private-Package: \ + com.ibm.ws.logging.fat.fallalloverthefloor.ibmfeature + +Include-Resource: \ + OSGI-INF=resources/OSGI-INF + +Service-Component: \ + com.ibm.ws.logging.fat.brokenfeature; \ + implementation:=com.ibm.ws.logging.fat.fallalloverthefloor.ibmfeature.BrokenFeature; \ + configurationAdmin=org.osgi.service.cm.ConfigurationAdmin; \ + properties:="service.vendor=IBM,com.ibm.ws.wim.repository.type=File" diff --git a/dev/com.ibm.ws.logging_fat/test-bundles/test.configuration.fallalloverthefloor.ibmfeature/resources/OSGI-INF/metatype/metatype.xml b/dev/com.ibm.ws.logging_fat/test-bundles/test.configuration.fallalloverthefloor.ibmfeature/resources/OSGI-INF/metatype/metatype.xml new file mode 100755 index 00000000000..e3db91d6ff8 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/test-bundles/test.configuration.fallalloverthefloor.ibmfeature/resources/OSGI-INF/metatype/metatype.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + diff --git a/dev/com.ibm.ws.logging_fat/test-bundles/test.configuration.fallalloverthefloor.ibmfeature/src/com/ibm/ws/logging/fat/fallalloverthefloor/ibmfeature/BrokenFeature.java b/dev/com.ibm.ws.logging_fat/test-bundles/test.configuration.fallalloverthefloor.ibmfeature/src/com/ibm/ws/logging/fat/fallalloverthefloor/ibmfeature/BrokenFeature.java new file mode 100755 index 00000000000..49ed9a932c6 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/test-bundles/test.configuration.fallalloverthefloor.ibmfeature/src/com/ibm/ws/logging/fat/fallalloverthefloor/ibmfeature/BrokenFeature.java @@ -0,0 +1,50 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.logging.fat.fallalloverthefloor.ibmfeature; + +import java.util.Map; + +/** + * + */ +public class BrokenFeature { + + /** + * A method which, after some indirection, throws an exception. + */ + protected void activate(Map properties) throws Exception { + thinkAboutThrowingAnException(); + + } + + /** + * @throws ConfigurationReceivedException + */ + private void thinkAboutThrowingAnException() throws ConfigurationReceivedException { + reallyThrowAnException(); + } + + /** + * @throws ConfigurationReceivedException + */ + private void reallyThrowAnException() throws ConfigurationReceivedException { + System.out.println("The user feature is about to throw an exception."); + throw new ConfigurationReceivedException(); + } + + protected static class ConfigurationReceivedException extends Exception { + + /** */ + private static final long serialVersionUID = 1L; + + } +} diff --git a/dev/com.ibm.ws.logging_fat/test-bundles/test.configuration.fallalloverthefloor.userfeature/bnd.bnd b/dev/com.ibm.ws.logging_fat/test-bundles/test.configuration.fallalloverthefloor.userfeature/bnd.bnd new file mode 100755 index 00000000000..30ab1f2515b --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/test-bundles/test.configuration.fallalloverthefloor.userfeature/bnd.bnd @@ -0,0 +1,18 @@ +# Don't include the IBM properties, this is intended to be a user feature +bVersion=1.0.0 +Bundle-Version: 1.0.0 +Bundle-Name: Exception throwing feature +Bundle-Description: This feature throws an exception +Bundle-SymbolicName: test.configuration.fallalloverthefloor.userfeature; singleton:=true + +Private-Package: \ + com.ibm.ws.logging.fat.fallalloverthefloor.userfeature + +Include-Resource: \ + OSGI-INF=resources/OSGI-INF + +Service-Component: \ + com.ibm.ws.logging.fat.brokenfeature; \ + implementation:=com.ibm.ws.logging.fat.fallalloverthefloor.userfeature.BrokenFeature; \ + configurationAdmin=org.osgi.service.cm.ConfigurationAdmin; \ + properties:="service.vendor=IBM,com.ibm.ws.wim.repository.type=File" diff --git a/dev/com.ibm.ws.logging_fat/test-bundles/test.configuration.fallalloverthefloor.userfeature/resources/OSGI-INF/metatype/metatype.xml b/dev/com.ibm.ws.logging_fat/test-bundles/test.configuration.fallalloverthefloor.userfeature/resources/OSGI-INF/metatype/metatype.xml new file mode 100755 index 00000000000..e3db91d6ff8 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/test-bundles/test.configuration.fallalloverthefloor.userfeature/resources/OSGI-INF/metatype/metatype.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + diff --git a/dev/com.ibm.ws.logging_fat/test-bundles/test.configuration.fallalloverthefloor.userfeature/src/com/ibm/ws/logging/fat/fallalloverthefloor/userfeature/BrokenFeature.java b/dev/com.ibm.ws.logging_fat/test-bundles/test.configuration.fallalloverthefloor.userfeature/src/com/ibm/ws/logging/fat/fallalloverthefloor/userfeature/BrokenFeature.java new file mode 100755 index 00000000000..5f8b2461583 --- /dev/null +++ b/dev/com.ibm.ws.logging_fat/test-bundles/test.configuration.fallalloverthefloor.userfeature/src/com/ibm/ws/logging/fat/fallalloverthefloor/userfeature/BrokenFeature.java @@ -0,0 +1,50 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.logging.fat.fallalloverthefloor.userfeature; + +import java.util.Map; + +/** + * + */ +public class BrokenFeature { + + /** + * A method which, after some indirection, throws an exception. + */ + protected void activate(Map properties) throws Exception { + thinkAboutThrowingAnException(); + + } + + /** + * @throws ConfigurationReceivedException + */ + private void thinkAboutThrowingAnException() throws ConfigurationReceivedException { + reallyThrowAnException(); + } + + /** + * @throws ConfigurationReceivedException + */ + private void reallyThrowAnException() throws ConfigurationReceivedException { + System.out.println("The user feature is about to throw an exception."); + throw new ConfigurationReceivedException(); + } + + protected static class ConfigurationReceivedException extends Exception { + + /** */ + private static final long serialVersionUID = 1L; + + } +} diff --git a/dev/com.ibm.ws.org.codehaus.jackson/.classpath.ant b/dev/com.ibm.ws.org.codehaus.jackson/.classpath.ant deleted file mode 100644 index ba360b1b66d..00000000000 --- a/dev/com.ibm.ws.org.codehaus.jackson/.classpath.ant +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/.classpath b/dev/com.ibm.ws.org.glassfish.json_fat/.classpath new file mode 100644 index 00000000000..c422489df40 --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/.classpath.gradle b/dev/com.ibm.ws.org.glassfish.json_fat/.classpath.gradle new file mode 100644 index 00000000000..c422489df40 --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/.classpath.gradle @@ -0,0 +1,7 @@ + + + + + + + diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/.gitignore b/dev/com.ibm.ws.org.glassfish.json_fat/.gitignore new file mode 100644 index 00000000000..1117ac1f9e9 --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/.gitignore @@ -0,0 +1,2 @@ +junit.jar +/bootstrapping.properties diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/.project b/dev/com.ibm.ws.org.glassfish.json_fat/.project new file mode 100644 index 00000000000..99f4e300645 --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/.project @@ -0,0 +1,23 @@ + + + com.ibm.ws.org.glassfish.json_fat + + + + + + org.eclipse.jdt.core.javabuilder + + + + + bndtools.core.bndbuilder + + + + + + org.eclipse.jdt.core.javanature + bndtools.core.bndnature + + diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/.settings/org.eclipse.core.resources.prefs b/dev/com.ibm.ws.org.glassfish.json_fat/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 00000000000..25d9425fe34 --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,4 @@ +#Ant properties +#Automatically generated by the ant prepare.settings.files task +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/.settings/org.eclipse.jdt.core.prefs b/dev/com.ibm.ws.org.glassfish.json_fat/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000000..f48ecd6cc60 --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,280 @@ +#Ant properties +#Automatically generated by the ant prepare.settings.files task +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.6 +org.eclipse.jdt.core.formatter.align_type_members_on_columns=false +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=0 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=18 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=2 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=2 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=18 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=2 +org.eclipse.jdt.core.formatter.alignment_for_assignment=0 +org.eclipse.jdt.core.formatter.alignment_for_binary_expression=18 +org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=0 +org.eclipse.jdt.core.formatter.alignment_for_enum_constants=16 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=18 +org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=18 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=18 +org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=0 +org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=20 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=4 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +org.eclipse.jdt.core.formatter.blank_lines_before_field=0 +org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 +org.eclipse.jdt.core.formatter.blank_lines_before_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 +org.eclipse.jdt.core.formatter.blank_lines_before_package=0 +org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 +org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 +org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false +org.eclipse.jdt.core.formatter.comment.format_block_comments=true +org.eclipse.jdt.core.formatter.comment.format_header=false +org.eclipse.jdt.core.formatter.comment.format_html=false +org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true +org.eclipse.jdt.core.formatter.comment.format_line_comments=false +org.eclipse.jdt.core.formatter.comment.format_source_code=true +org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true +org.eclipse.jdt.core.formatter.comment.indent_root_tags=true +org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert +org.eclipse.jdt.core.formatter.comment.line_length=180 +org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true +org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true +org.eclipse.jdt.core.formatter.compact_else_if=true +org.eclipse.jdt.core.formatter.continuation_indentation=4 +org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=4 +org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off +org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on +org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false +org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=false +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true +org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_empty_lines=false +org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true +org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true +org.eclipse.jdt.core.formatter.indentation.size=8 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert +org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.join_lines_in_comments=false +org.eclipse.jdt.core.formatter.join_wrapped_lines=false +org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false +org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false +org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false +org.eclipse.jdt.core.formatter.lineSplit=180 +org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=true +org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=true +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 +org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=false +org.eclipse.jdt.core.formatter.tabulation.char=space +org.eclipse.jdt.core.formatter.tabulation.size=4 +org.eclipse.jdt.core.formatter.use_on_off_tags=true +org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false +org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true +org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/.settings/org.eclipse.jdt.ui.prefs b/dev/com.ibm.ws.org.glassfish.json_fat/.settings/org.eclipse.jdt.ui.prefs new file mode 100644 index 00000000000..8607a4626e4 --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,63 @@ +#Ant properties +#Automatically generated by the ant prepare.settings.files task +eclipse.preferences.version=1 +editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true +formatter_settings_version=11 +org.eclipse.jdt.ui.ignorelowercasenames=true +org.eclipse.jdt.ui.importorder=java;javax;org;com; +org.eclipse.jdt.ui.javadoc=true +org.eclipse.jdt.ui.ondemandthreshold=99 +org.eclipse.jdt.ui.staticondemandthreshold=99 +org.eclipse.jdt.ui.text.custom_code_templates= +sp_cleanup.add_default_serial_version_id=true +sp_cleanup.add_generated_serial_version_id=false +sp_cleanup.add_missing_annotations=true +sp_cleanup.add_missing_deprecated_annotations=true +sp_cleanup.add_missing_methods=false +sp_cleanup.add_missing_nls_tags=false +sp_cleanup.add_missing_override_annotations=true +sp_cleanup.add_missing_override_annotations_interface_methods=true +sp_cleanup.add_serial_version_id=false +sp_cleanup.always_use_blocks=true +sp_cleanup.always_use_parentheses_in_expressions=false +sp_cleanup.always_use_this_for_non_static_field_access=false +sp_cleanup.always_use_this_for_non_static_method_access=false +sp_cleanup.convert_to_enhanced_for_loop=false +sp_cleanup.correct_indentation=false +sp_cleanup.format_source_code=true +sp_cleanup.format_source_code_changes_only=false +sp_cleanup.make_local_variable_final=false +sp_cleanup.make_parameters_final=false +sp_cleanup.make_private_fields_final=true +sp_cleanup.make_type_abstract_if_missing_method=false +sp_cleanup.make_variable_declarations_final=true +sp_cleanup.never_use_blocks=false +sp_cleanup.never_use_parentheses_in_expressions=true +sp_cleanup.on_save_use_additional_actions=true +sp_cleanup.organize_imports=true +sp_cleanup.qualify_static_field_accesses_with_declaring_class=false +sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_with_declaring_class=false +sp_cleanup.qualify_static_method_accesses_with_declaring_class=false +sp_cleanup.remove_private_constructors=true +sp_cleanup.remove_trailing_whitespaces=true +sp_cleanup.remove_trailing_whitespaces_all=true +sp_cleanup.remove_trailing_whitespaces_ignore_empty=false +sp_cleanup.remove_unnecessary_casts=true +sp_cleanup.remove_unnecessary_nls_tags=true +sp_cleanup.remove_unused_imports=true +sp_cleanup.remove_unused_local_variables=false +sp_cleanup.remove_unused_private_fields=true +sp_cleanup.remove_unused_private_members=false +sp_cleanup.remove_unused_private_methods=true +sp_cleanup.remove_unused_private_types=true +sp_cleanup.sort_members=false +sp_cleanup.sort_members_all=false +sp_cleanup.use_blocks=false +sp_cleanup.use_blocks_only_for_return_and_throw=false +sp_cleanup.use_parentheses_in_expressions=false +sp_cleanup.use_this_for_non_static_field_access=false +sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true +sp_cleanup.use_this_for_non_static_method_access=false +sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/bnd.bnd b/dev/com.ibm.ws.org.glassfish.json_fat/bnd.bnd new file mode 100644 index 00000000000..9801b86a42e --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/bnd.bnd @@ -0,0 +1,13 @@ +-include= ~../cnf/resources/bnd/bundle.props +bVersion=1.0 + +src: \ + fat/src + +-buildpath: \ + ${javac.bootclasspath.java6}, \ + ../build.sharedResources/lib/junit/old/junit.jar;version=file, \ + com.ibm.ws.componenttest;version=latest, \ + fattest.simplicity;version=latest, \ + ../fattest.simplicity/lib/public.api.jar;version=file, \ + com.ibm.ws.org.glassfish.json.1.0;version=latest diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/bnd.bnd.gradle b/dev/com.ibm.ws.org.glassfish.json_fat/bnd.bnd.gradle new file mode 100644 index 00000000000..9801b86a42e --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/bnd.bnd.gradle @@ -0,0 +1,13 @@ +-include= ~../cnf/resources/bnd/bundle.props +bVersion=1.0 + +src: \ + fat/src + +-buildpath: \ + ${javac.bootclasspath.java6}, \ + ../build.sharedResources/lib/junit/old/junit.jar;version=file, \ + com.ibm.ws.componenttest;version=latest, \ + fattest.simplicity;version=latest, \ + ../fattest.simplicity/lib/public.api.jar;version=file, \ + com.ibm.ws.org.glassfish.json.1.0;version=latest diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/build-test.xml b/dev/com.ibm.ws.org.glassfish.json_fat/build-test.xml new file mode 100644 index 00000000000..28e8733b7e3 --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/build-test.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/build.gradle b/dev/com.ibm.ws.org.glassfish.json_fat/build.gradle new file mode 100644 index 00000000000..e69de29bb2d diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/delivery.sets b/dev/com.ibm.ws.org.glassfish.json_fat/delivery.sets new file mode 100644 index 00000000000..674398425a0 --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/delivery.sets @@ -0,0 +1 @@ +SLE diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/fat/src/com/ibm/ws/org/glassfish/json/fat/FATSuite.java b/dev/com.ibm.ws.org.glassfish.json_fat/fat/src/com/ibm/ws/org/glassfish/json/fat/FATSuite.java new file mode 100644 index 00000000000..1be011b859a --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/fat/src/com/ibm/ws/org/glassfish/json/fat/FATSuite.java @@ -0,0 +1,28 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2014 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.org.glassfish.json.fat; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +import com.ibm.ws.org.glassfish.json.fat.tests.BasicJSONPTest; +import com.ibm.ws.org.glassfish.json.fat.tests.CustomFeatureJSONPTest; +import componenttest.custom.junit.runner.AlwaysPassesTest; + +@RunWith(Suite.class) +@SuiteClasses({ + AlwaysPassesTest.class, + BasicJSONPTest.class, + CustomFeatureJSONPTest.class +}) +public class FATSuite {} diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/fat/src/com/ibm/ws/org/glassfish/json/fat/tests/AbstractTest.java b/dev/com.ibm.ws.org.glassfish.json_fat/fat/src/com/ibm/ws/org/glassfish/json/fat/tests/AbstractTest.java new file mode 100644 index 00000000000..723219190a6 --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/fat/src/com/ibm/ws/org/glassfish/json/fat/tests/AbstractTest.java @@ -0,0 +1,145 @@ +package com.ibm.ws.org.glassfish.json.fat.tests; + +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2014 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ + +import static componenttest.topology.utils.HttpUtils.getHttpConnection; +import static org.junit.Assert.fail; + +import java.io.BufferedReader; +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URL; + +import junit.framework.Assert; + +import org.junit.AfterClass; +import org.junit.ClassRule; +import org.junit.Rule; +import org.junit.rules.TestName; +import org.junit.rules.TestRule; + +import com.ibm.websphere.simplicity.log.Log; +import componenttest.app.FATServlet; +import componenttest.custom.junit.runner.OnlyRunInJava7Rule; +import componenttest.topology.impl.LibertyServer; +import componenttest.topology.utils.HttpUtils; +import componenttest.topology.utils.HttpUtils.HTTPRequestMethod; + +/** + * Abstract test class. This should be extended when adding a new test class, + * so that this shared logic for running the actual tests remains in one place. + * + * To add new test, simply implement @BeforeClass method that gets and starts + * the server needed. + */ +public abstract class AbstractTest { + /** The time in seconds to wait at a URL before giving up. **/ + public static final int CONN_TIMEOUT = 30; + + protected static LibertyServer server; + private static final Class c = AbstractTest.class; + + @ClassRule + public static final TestRule java7Rule = new OnlyRunInJava7Rule(); + + @Rule + public TestName testName = new TestName(); + + public String servlet; + + /** + * Call {@link #runTest} with the configured servlet name and the current + * test method as the "testMethod" query parameter. + */ + protected void runTest() throws Exception { + Assert.assertNotNull(servlet); + runTest(servlet + "?testMethod=" + testName.getMethodName()); + } + + protected void runTest(String servlet, String method) throws Exception { + Assert.assertNotNull(servlet); + String invocationString = servlet + "?testMethod=" + method; + runTest(invocationString); + } + + /** + * Invoke the specified servlet and look for "PASSED" as a response. + */ + protected void runTest(String servlet) throws Exception { + final String method = testName.getMethodName(); + + URL url = new URL("http://" + server.getHostname() + ":" + server.getHttpDefaultPort() + servlet); + Log.info(c, method, "Calling application with URL=" + url.toString()); + HttpURLConnection con = getHttpConnection(url, HttpURLConnection.HTTP_OK, new int[0], CONN_TIMEOUT, HTTPRequestMethod.GET); + + // Check the response from servlet for "PASSED" + String response = getAnyResponse(con); + Log.info(c, method, "Response from " + servlet + ": " + response); + if (!"PASSED".equals(response) && + !response.contains(FATServlet.SUCCESS)) { + fail(servlet + " failed: " + response); + } + } + + /** + * Invoke the specified servlet and wait until the passed in response + * code is returned. + * + * @return the message associated with the response + */ + String runTest(String servlet, int responseCode) throws Exception { + final String method = testName.getMethodName(); + + URL url = new URL("http://" + server.getHostname() + ":" + server.getHttpDefaultPort() + servlet); + Log.info(c, method, "Calling application with URL=" + url.toString()); + HttpURLConnection con = getHttpConnection(url, responseCode, CONN_TIMEOUT); + + // Check the response from servlet for "PASSED" + String response = getAnyResponse(con); + Log.info(c, method, "Response from " + servlet + ": " + response); + + return response; + } + + /** + * This method is used to read the response from either the input stream or + * error stream. + * + * @param con The connection to the HTTP address + * @return The output or error from the webpage + * @throws IOException if neither the input stream nor error stream can be read + */ + public static String getAnyResponse(HttpURLConnection urlConnection) throws IOException { + BufferedReader br; + try { + br = HttpUtils.getConnectionStream(urlConnection); + } catch (IOException ioex) { + br = HttpUtils.getErrorStream(urlConnection); + } + + String response = ""; + String aLine; + + while ((aLine = br.readLine()) != null) { + response = response + aLine; + } + return response; + } + + @AfterClass + public static void tearDown() throws Exception { + if (server != null && server.isStarted()) { + server.stopServer(); + } + } +} diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/fat/src/com/ibm/ws/org/glassfish/json/fat/tests/BasicJSONPTest.java b/dev/com.ibm.ws.org.glassfish.json_fat/fat/src/com/ibm/ws/org/glassfish/json/fat/tests/BasicJSONPTest.java new file mode 100644 index 00000000000..151ff2ec2b4 --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/fat/src/com/ibm/ws/org/glassfish/json/fat/tests/BasicJSONPTest.java @@ -0,0 +1,85 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2014 + * + * The source code for this program is not published or other- + * wise divested of its trade secrets, irrespective of what has + * been deposited with the U.S. Copyright Office. + */ +package com.ibm.ws.org.glassfish.json.fat.tests; + +import org.junit.BeforeClass; +import org.junit.Test; + +import componenttest.topology.impl.LibertyServerFactory; + +public class BasicJSONPTest extends AbstractTest { + + @BeforeClass + public static void setUp() throws Exception { + server = LibertyServerFactory.getLibertyServer("com.ibm.ws.org.glassfish.json.fat.BasicJsonpServer"); + server.addInstalledAppForValidation("JSONPWAR"); + server.addInstalledAppForValidation("customAppJSONPWAR"); + server.addInstalledAppForValidation("customLibJSONPWAR"); + server.startServer("BasicJSONPTest.log"); + } + + /** + * Ensure that JsonObjectBuilder is functioning. + */ + @Test + public void testJsonBuild() throws Exception { + this.servlet = "/JSONPWAR/BuildJSONPServlet"; + runTest(); + } + + /** + * Ensure that JsonReader is functioning. + */ + @Test + public void testJsonRead() throws Exception { + this.servlet = "/JSONPWAR/ReadJSONPServlet"; + runTest(); + } + + /** + * Ensure that JsonWriter is functioning. + */ + @Test + public void testJsonWrite() throws Exception { + this.servlet = "/JSONPWAR/WriteJSONPServlet"; + runTest(); + } + + /** + * Ensure that JsonGenerator is functioning. + */ + @Test + public void testJsonStream() throws Exception { + this.servlet = "/JSONPWAR/StreamJSONPServlet"; + runTest(); + } + + /** + * Test plugging in a custom implementation for JSON processing, + * where the custom implementation is packaged in the application. + */ + @Test + public void testCustomAppJsonProvider() throws Exception { + this.servlet = "/customAppJSONPWAR/CustomJsonProviderServlet"; + runTest(); + } + + /** + * Test plugging in a custom implementation for JSON processing, + * where the custom implementation is packaged in a shared library. + */ + @Test + public void testCustomLibJsonProvider() throws Exception { + this.servlet = "/customLibJSONPWAR/CustomJsonProviderServlet"; + runTest(); + } +} diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/fat/src/com/ibm/ws/org/glassfish/json/fat/tests/CustomFeatureJSONPTest.java b/dev/com.ibm.ws.org.glassfish.json_fat/fat/src/com/ibm/ws/org/glassfish/json/fat/tests/CustomFeatureJSONPTest.java new file mode 100644 index 00000000000..0b53c606e03 --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/fat/src/com/ibm/ws/org/glassfish/json/fat/tests/CustomFeatureJSONPTest.java @@ -0,0 +1,49 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2014 + * + * The source code for this program is not published or other- + * wise divested of its trade secrets, irrespective of what has + * been deposited with the U.S. Copyright Office. + */ +package com.ibm.ws.org.glassfish.json.fat.tests; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import componenttest.topology.impl.LibertyServerFactory; + +public class CustomFeatureJSONPTest extends AbstractTest { + private static final String FEATURE_NAME = "customJsonpProvider-1.0"; + private static final String BUNDLE_NAME = "com.ibm.ws.jsonp.feature.provider.1.0_1.0.0"; + + @BeforeClass + public static void setUp() throws Exception { + server = LibertyServerFactory.getLibertyServer("com.ibm.ws.org.glassfish.json.fat.CustomFeatureJsonpServer"); + server.installUserFeature(FEATURE_NAME); + server.installUserBundle(BUNDLE_NAME); + server.addInstalledAppForValidation("customFeatureJSONPWAR"); + server.startServer("customFeatureJSONPTest.log"); + } + + @AfterClass + public static void afterClass() throws Exception { + server.stopServer(); + server.uninstallUserBundle(BUNDLE_NAME); + server.uninstallUserFeature(FEATURE_NAME); + } + + /** + * Test plugging in a custom implementation for JSON processing, + * where the custom implementation is packaged in a user defined feature. + */ + @Test + public void testCustomFeatureJsonProvider() throws Exception { + this.servlet = "/customFeatureJSONPWAR/CustomJsonProviderServlet"; + runTest(); + } +} diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/publish/.gitignore b/dev/com.ibm.ws.org.glassfish.json_fat/publish/.gitignore new file mode 100644 index 00000000000..0968b1bceb6 --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/publish/.gitignore @@ -0,0 +1 @@ +/bundles diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/publish/features/customJsonpProvider-1.0.mf b/dev/com.ibm.ws.org.glassfish.json_fat/publish/features/customJsonpProvider-1.0.mf new file mode 100644 index 00000000000..34c4cb146bc --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/publish/features/customJsonpProvider-1.0.mf @@ -0,0 +1,10 @@ +Subsystem-ManifestVersion: 1 +IBM-ShortName: customJsonpProvider-1.0 +Subsystem-SymbolicName: com.ibm.ws.jsonp.feature.provider.1.0; visibility:=public +Subsystem-Version: 1.0.0 +Subsystem-Content: com.ibm.websphere.appserver.classloading-1.0; type="osgi.subsystem.feature", + com.ibm.ws.jsonp.feature.provider.1.0; version="[1,1.0.100)" +IBM-API-Package: com.ibm.ws.jsonp.feature.provider; type="api" +Subsystem-Type: osgi.subsystem.feature +IBM-Feature-Version: 2 + diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/publish/servers/com.ibm.ws.org.glassfish.json.fat.BasicJsonpServer/.gitignore b/dev/com.ibm.ws.org.glassfish.json_fat/publish/servers/com.ibm.ws.org.glassfish.json.fat.BasicJsonpServer/.gitignore new file mode 100644 index 00000000000..a443afd9743 --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/publish/servers/com.ibm.ws.org.glassfish.json.fat.BasicJsonpServer/.gitignore @@ -0,0 +1,4 @@ +/JSONPProviderLib +/apps +/dropins +/lib diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/publish/servers/com.ibm.ws.org.glassfish.json.fat.BasicJsonpServer/bootstrap.properties b/dev/com.ibm.ws.org.glassfish.json_fat/publish/servers/com.ibm.ws.org.glassfish.json.fat.BasicJsonpServer/bootstrap.properties new file mode 100644 index 00000000000..af984ccafa5 --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/publish/servers/com.ibm.ws.org.glassfish.json.fat.BasicJsonpServer/bootstrap.properties @@ -0,0 +1,2 @@ +bootstrap.include=../testports.properties +com.ibm.ws.logging.trace.specification=*=info diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/publish/servers/com.ibm.ws.org.glassfish.json.fat.BasicJsonpServer/build.properties b/dev/com.ibm.ws.org.glassfish.json_fat/publish/servers/com.ibm.ws.org.glassfish.json.fat.BasicJsonpServer/build.properties new file mode 100644 index 00000000000..ae211a3c3cc --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/publish/servers/com.ibm.ws.org.glassfish.json.fat.BasicJsonpServer/build.properties @@ -0,0 +1 @@ +include.JSONPProviderLib=true \ No newline at end of file diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/publish/servers/com.ibm.ws.org.glassfish.json.fat.BasicJsonpServer/server.xml b/dev/com.ibm.ws.org.glassfish.json_fat/publish/servers/com.ibm.ws.org.glassfish.json.fat.BasicJsonpServer/server.xml new file mode 100644 index 00000000000..1de1369c8e5 --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/publish/servers/com.ibm.ws.org.glassfish.json.fat.BasicJsonpServer/server.xml @@ -0,0 +1,17 @@ + + + + + servlet-3.0 + jsonp-1.0 + + + + + + + + + + + diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/publish/servers/com.ibm.ws.org.glassfish.json.fat.CustomFeatureJsonpServer/.gitignore b/dev/com.ibm.ws.org.glassfish.json_fat/publish/servers/com.ibm.ws.org.glassfish.json.fat.CustomFeatureJsonpServer/.gitignore new file mode 100644 index 00000000000..26548bf9b65 --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/publish/servers/com.ibm.ws.org.glassfish.json.fat.CustomFeatureJsonpServer/.gitignore @@ -0,0 +1,2 @@ +/dropins +/lib diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/publish/servers/com.ibm.ws.org.glassfish.json.fat.CustomFeatureJsonpServer/bootstrap.properties b/dev/com.ibm.ws.org.glassfish.json_fat/publish/servers/com.ibm.ws.org.glassfish.json.fat.CustomFeatureJsonpServer/bootstrap.properties new file mode 100644 index 00000000000..af984ccafa5 --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/publish/servers/com.ibm.ws.org.glassfish.json.fat.CustomFeatureJsonpServer/bootstrap.properties @@ -0,0 +1,2 @@ +bootstrap.include=../testports.properties +com.ibm.ws.logging.trace.specification=*=info diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/publish/servers/com.ibm.ws.org.glassfish.json.fat.CustomFeatureJsonpServer/server.xml b/dev/com.ibm.ws.org.glassfish.json_fat/publish/servers/com.ibm.ws.org.glassfish.json.fat.CustomFeatureJsonpServer/server.xml new file mode 100644 index 00000000000..9d1ab7f343a --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/publish/servers/com.ibm.ws.org.glassfish.json.fat.CustomFeatureJsonpServer/server.xml @@ -0,0 +1,10 @@ + + + + + servlet-3.0 + jsonp-1.0 + usr:customJsonpProvider-1.0 + + + diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/JSONPWAR.war/package.properties b/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/JSONPWAR.war/package.properties new file mode 100644 index 00000000000..3ee53ab9e54 --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/JSONPWAR.war/package.properties @@ -0,0 +1,2 @@ +server.pattern=com.ibm.ws.org.glassfish.json.fat.BasicJsonpServer +lib.componenttest=true diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/JSONPWAR.war/resources/META-INF/permissions.xml b/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/JSONPWAR.war/resources/META-INF/permissions.xml new file mode 100644 index 00000000000..28acc02da03 --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/JSONPWAR.war/resources/META-INF/permissions.xml @@ -0,0 +1,20 @@ + + + + + java.lang.RuntimePermission + getenv.* + + + + java.io.FilePermission + ALL FILES + read,write + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/JSONPWAR.war/resources/WEB-INF/json_read_test_data.js b/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/JSONPWAR.war/resources/WEB-INF/json_read_test_data.js new file mode 100644 index 00000000000..7d566461a52 --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/JSONPWAR.war/resources/WEB-INF/json_read_test_data.js @@ -0,0 +1,6 @@ +{ "firstName": "Steve", "lastName": "Watson", "age": 45, + "phoneNumber": [ + { "type": "office", "number": "507-253-1234" }, + { "type": "cell", "number": "507-253-4321" } + ] +} \ No newline at end of file diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/JSONPWAR.war/src/com/ibm/ws/jsonp/fat/AbstractJSONPServlet.java b/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/JSONPWAR.war/src/com/ibm/ws/jsonp/fat/AbstractJSONPServlet.java new file mode 100644 index 00000000000..f0ad4205609 --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/JSONPWAR.war/src/com/ibm/ws/jsonp/fat/AbstractJSONPServlet.java @@ -0,0 +1,138 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2014 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jsonp.fat; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.util.HashMap; + +import javax.json.Json; +import javax.json.JsonObject; +import javax.json.stream.JsonParser; +import javax.json.stream.JsonParser.Event; +import javax.json.stream.JsonParserFactory; + +import junit.framework.Assert; + +import componenttest.app.FATServlet; + +@SuppressWarnings("serial") +public abstract class AbstractJSONPServlet extends FATServlet { + private String jsonData = ""; + + protected JsonParser getJsonParser(String fileLocation) { + FileInputStream fis = createFileInputStream(fileLocation); + JsonParserFactory jsonParserFactory = Json.createParserFactory(new HashMap()); + JsonParser parser = jsonParserFactory.createParser(fis); + return parser; + } + + protected JsonParser getJsonParser(JsonObject value) { + JsonParserFactory jsonParserFactory = Json.createParserFactory(new HashMap()); + JsonParser parser = jsonParserFactory.createParser(value); + return parser; + } + + protected void parseJson(JsonParser parser) { + + Boolean startObjectOrArray = false; + Boolean endObjectOrArray = false; + while (parser.hasNext()) { + Event event = parser.next(); + + if (endObjectOrArray && (event.equals(Event.START_ARRAY) || event.equals(Event.START_OBJECT))) { + logJsonElement(","); + } + endObjectOrArray = false; + + switch (event) { + case START_ARRAY: + startObjectOrArray = true; + logJsonElement("["); + break; + case END_ARRAY: + endObjectOrArray = true; + logJsonElement("]"); + break; + case START_OBJECT: + startObjectOrArray = true; + logJsonElement("{"); + break; + case END_OBJECT: + endObjectOrArray = true; + logJsonElement("}"); + break; + case VALUE_NUMBER: + if (parser.isIntegralNumber()) { + logJsonElement(Integer.toString(parser.getInt())); + } else { + logJsonElement(Long.toString(parser.getLong())); + } + break; + case VALUE_FALSE: + logJsonElement("FALSE"); + break; + case VALUE_NULL: + logJsonElement("NULL"); + break; + case VALUE_TRUE: + logJsonElement("TRUE"); + break; + case KEY_NAME: + if (!startObjectOrArray) { + logJsonElement(","); + } + startObjectOrArray = false; + + logJsonElement("\"" + parser.getString() + "\":"); + break; + case VALUE_STRING: + logJsonElement("\"" + parser.getString() + "\""); + break; + } + } + //System.out.println("DEBUG: " + jsonData); + } + + private void logJsonElement(String element) { + System.out.println(element); + jsonData = jsonData + element; + } + + protected void checkJsonData() { + String expectedString = "{\"firstName\":\"Steve\",\"lastName\":\"Watson\",\"age\":45,\"phoneNumber\":[{\"type\":\"office\",\"number\":\"507-253-1234\"},{\"type\":\"cell\",\"number\":\"507-253-4321\"}]}"; + Assert.assertTrue("DEBUG: EXPECTED <" + expectedString + "> FOUND <" + jsonData + ">", expectedString.equals(jsonData)); + } + + protected FileOutputStream createFileOutputStream(String fileLocation) { + FileOutputStream fos = null; + try { + fos = new FileOutputStream(fileLocation); + } catch (FileNotFoundException e) { + e.printStackTrace(); + Assert.fail("AbstractJSONPServlet threw an unexpected FileNotFoundException."); + } + return fos; + } + + protected FileInputStream createFileInputStream(String fileLocation) { + FileInputStream fis = null; + try { + fis = new FileInputStream(fileLocation); + } catch (FileNotFoundException e) { + e.printStackTrace(); + Assert.fail("AbstractJSONPServlet threw an unexpected FileNotFoundException."); + } + return fis; + } +} \ No newline at end of file diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/JSONPWAR.war/src/com/ibm/ws/jsonp/fat/BuildJSONPServlet.java b/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/JSONPWAR.war/src/com/ibm/ws/jsonp/fat/BuildJSONPServlet.java new file mode 100644 index 00000000000..f0a134d7d58 --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/JSONPWAR.war/src/com/ibm/ws/jsonp/fat/BuildJSONPServlet.java @@ -0,0 +1,41 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2014 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jsonp.fat; + +import javax.json.Json; +import javax.json.JsonObject; +import javax.json.stream.JsonParser; +import javax.servlet.annotation.WebServlet; + +@WebServlet("/BuildJSONPServlet") +@SuppressWarnings("serial") +public class BuildJSONPServlet extends AbstractJSONPServlet { + + public void testJsonBuild() { + JsonObject value = buildJsonObject(); + JsonParser parser = getJsonParser(value); + parseJson(parser); + checkJsonData(); + } + + private JsonObject buildJsonObject() { + JsonObject value = Json.createObjectBuilder() + .add("firstName", "Steve") + .add("lastName", "Watson") + .add("age", 45) + .add("phoneNumber", Json.createArrayBuilder() + .add(Json.createObjectBuilder().add("type", "office").add("number", "507-253-1234")) + .add(Json.createObjectBuilder().add("type", "cell").add("number", "507-253-4321"))) + .build(); + return value; + } +} \ No newline at end of file diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/JSONPWAR.war/src/com/ibm/ws/jsonp/fat/ReadJSONPServlet.java b/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/JSONPWAR.war/src/com/ibm/ws/jsonp/fat/ReadJSONPServlet.java new file mode 100644 index 00000000000..98daf7189b6 --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/JSONPWAR.war/src/com/ibm/ws/jsonp/fat/ReadJSONPServlet.java @@ -0,0 +1,41 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2014 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jsonp.fat; + +import java.io.InputStream; + +import javax.json.Json; +import javax.json.JsonObject; +import javax.json.JsonReader; +import javax.json.stream.JsonParser; +import javax.servlet.ServletContext; +import javax.servlet.annotation.WebServlet; + +@WebServlet("/ReadJSONPServlet") +@SuppressWarnings("serial") +public class ReadJSONPServlet extends AbstractJSONPServlet { + + public void testJsonRead() { + JsonObject jsonData = readJsonFile("/WEB-INF/json_read_test_data.js"); + JsonParser parser = getJsonParser(jsonData); + parseJson(parser); + checkJsonData(); + } + + private JsonObject readJsonFile(String fileLocation) { + ServletContext context = getServletContext(); + InputStream is = context.getResourceAsStream(fileLocation); + JsonReader reader = Json.createReader(is); + JsonObject value = reader.readObject(); + return value; + } +} \ No newline at end of file diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/JSONPWAR.war/src/com/ibm/ws/jsonp/fat/StreamJSONPServlet.java b/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/JSONPWAR.war/src/com/ibm/ws/jsonp/fat/StreamJSONPServlet.java new file mode 100644 index 00000000000..6bbd7f6a6b7 --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/JSONPWAR.war/src/com/ibm/ws/jsonp/fat/StreamJSONPServlet.java @@ -0,0 +1,59 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2014 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jsonp.fat; + +import java.io.FileOutputStream; +import java.util.HashMap; +import java.util.Map; + +import javax.json.Json; +import javax.json.stream.JsonGenerator; +import javax.json.stream.JsonGeneratorFactory; +import javax.json.stream.JsonParser; +import javax.servlet.annotation.WebServlet; + +@WebServlet("/StreamJSONPServlet") +@SuppressWarnings("serial") +public class StreamJSONPServlet extends AbstractJSONPServlet { + + public void testJsonStream() { + String outputDir = System.getenv("X_LOG_DIR") + "/json_stream_test_data.js"; + generateJSON(outputDir); + JsonParser parser = getJsonParser(outputDir); + parseJson(parser); + checkJsonData(); + } + + private void generateJSON(String fileLocation) { + FileOutputStream os = createFileOutputStream(fileLocation); + Map props = new HashMap(); + props.put(JsonGenerator.PRETTY_PRINTING, new Object()); + JsonGeneratorFactory factory = Json.createGeneratorFactory(props); + JsonGenerator generator = factory.createGenerator(os); + generator.writeStartObject() + .write("firstName", "Steve") + .write("lastName", "Watson") + .write("age", 45) + .writeStartArray("phoneNumber") + .writeStartObject() + .write("type", "office") + .write("number", "507-253-1234") + .writeEnd() + .writeStartObject() + .write("type", "cell") + .write("number", "507-253-4321") + .writeEnd() + .writeEnd() + .writeEnd(); + generator.close(); + } +} \ No newline at end of file diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/JSONPWAR.war/src/com/ibm/ws/jsonp/fat/WriteJSONPServlet.java b/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/JSONPWAR.war/src/com/ibm/ws/jsonp/fat/WriteJSONPServlet.java new file mode 100644 index 00000000000..081424f3cc8 --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/JSONPWAR.war/src/com/ibm/ws/jsonp/fat/WriteJSONPServlet.java @@ -0,0 +1,54 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2014 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jsonp.fat; + +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.InputStream; + +import javax.json.Json; +import javax.json.JsonObject; +import javax.json.JsonReader; +import javax.json.JsonWriter; +import javax.json.stream.JsonParser; +import javax.servlet.annotation.WebServlet; + +@WebServlet("/WriteJSONPServlet") +@SuppressWarnings("serial") +public class WriteJSONPServlet extends AbstractJSONPServlet { + + public void testJsonWrite() { + InputStream originalInputStream = getServletContext().getResourceAsStream("/WEB-INF/json_read_test_data.js"); + JsonObject originalJsonData = readJsonFile(originalInputStream); + + String outputDir = System.getenv("X_LOG_DIR") + "/json_write_test_data.js"; + writeJsonFile(outputDir, originalJsonData); + FileInputStream newInputStream = createFileInputStream(outputDir); + JsonObject newJsonData = readJsonFile(newInputStream); + JsonParser parser = getJsonParser(newJsonData); + parseJson(parser); + checkJsonData(); + } + + private void writeJsonFile(String fileLocation, JsonObject value) { + FileOutputStream os = createFileOutputStream(fileLocation); + JsonWriter writer = Json.createWriter(os); + writer.writeObject(value); + writer.close(); + } + + private JsonObject readJsonFile(InputStream is) { + JsonReader reader = Json.createReader(is); + JsonObject value = reader.readObject(); + return value; + } +} \ No newline at end of file diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customAppJSONPProvider.jar/resources/META-INF/permissions.xml b/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customAppJSONPProvider.jar/resources/META-INF/permissions.xml new file mode 100644 index 00000000000..28acc02da03 --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customAppJSONPProvider.jar/resources/META-INF/permissions.xml @@ -0,0 +1,20 @@ + + + + + java.lang.RuntimePermission + getenv.* + + + + java.io.FilePermission + ALL FILES + read,write + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customAppJSONPProvider.jar/resources/META-INF/services/javax.json.spi.JsonProvider b/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customAppJSONPProvider.jar/resources/META-INF/services/javax.json.spi.JsonProvider new file mode 100644 index 00000000000..34dbcb5cfc5 --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customAppJSONPProvider.jar/resources/META-INF/services/javax.json.spi.JsonProvider @@ -0,0 +1 @@ +com.ibm.ws.jsonp.app.provider.JsonProviderImpl \ No newline at end of file diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customAppJSONPProvider.jar/src/com/ibm/ws/jsonp/app/provider/JsonParserImpl.java b/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customAppJSONPProvider.jar/src/com/ibm/ws/jsonp/app/provider/JsonParserImpl.java new file mode 100644 index 00000000000..08605d06014 --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customAppJSONPProvider.jar/src/com/ibm/ws/jsonp/app/provider/JsonParserImpl.java @@ -0,0 +1,65 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2014 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jsonp.app.provider; + +import java.math.BigDecimal; + +import javax.json.stream.JsonLocation; + +/** + * + */ +public class JsonParserImpl implements javax.json.stream.JsonParser { + + @Override + public void close() {} + + @Override + public BigDecimal getBigDecimal() { + return null; + } + + @Override + public int getInt() { + return 0; + } + + @Override + public JsonLocation getLocation() { + return null; + } + + @Override + public long getLong() { + return 0; + } + + @Override + public String getString() { + return "Custom JSONP implementation loaded from an application library"; + } + + @Override + public boolean hasNext() { + return false; + } + + @Override + public boolean isIntegralNumber() { + return false; + } + + @Override + public Event next() { + return null; + } +} diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customAppJSONPProvider.jar/src/com/ibm/ws/jsonp/app/provider/JsonProviderImpl.java b/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customAppJSONPProvider.jar/src/com/ibm/ws/jsonp/app/provider/JsonProviderImpl.java new file mode 100644 index 00000000000..3c122636eb7 --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customAppJSONPProvider.jar/src/com/ibm/ws/jsonp/app/provider/JsonProviderImpl.java @@ -0,0 +1,97 @@ +package com.ibm.ws.jsonp.app.provider; + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; +import java.util.Map; + +import javax.json.JsonArrayBuilder; +import javax.json.JsonBuilderFactory; +import javax.json.JsonObjectBuilder; +import javax.json.JsonReader; +import javax.json.JsonReaderFactory; +import javax.json.JsonWriter; +import javax.json.JsonWriterFactory; +import javax.json.spi.JsonProvider; +import javax.json.stream.JsonGenerator; +import javax.json.stream.JsonGeneratorFactory; +import javax.json.stream.JsonParser; +import javax.json.stream.JsonParserFactory; + +public class JsonProviderImpl extends JsonProvider { + @Override + public JsonParser createParser(Reader reader) { + return null; + } + + @Override + public JsonParser createParser(InputStream in) { + return new JsonParserImpl(); + } + + @Override + public JsonParserFactory createParserFactory(Map config) { + return null; + } + + @Override + public JsonGenerator createGenerator(Writer writer) { + return null; + } + + @Override + public JsonGenerator createGenerator(OutputStream out) { + return null; + } + + @Override + public JsonGeneratorFactory createGeneratorFactory(Map config) { + return null; + } + + @Override + public JsonReader createReader(Reader reader) { + return null; + } + + @Override + public JsonReader createReader(InputStream in) { + return null; + } + + @Override + public JsonWriter createWriter(Writer writer) { + return null; + } + + @Override + public JsonWriter createWriter(OutputStream out) { + return null; + } + + @Override + public JsonWriterFactory createWriterFactory(Map config) { + return null; + } + + @Override + public JsonReaderFactory createReaderFactory(Map config) { + return null; + } + + @Override + public JsonObjectBuilder createObjectBuilder() { + return null; + } + + @Override + public JsonArrayBuilder createArrayBuilder() { + return null; + } + + @Override + public JsonBuilderFactory createBuilderFactory(Map config) { + return null; + } +} diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customAppJSONPWAR.war/package.properties b/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customAppJSONPWAR.war/package.properties new file mode 100644 index 00000000000..109d9f3a7d9 --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customAppJSONPWAR.war/package.properties @@ -0,0 +1,3 @@ +server.pattern=com.ibm.ws.org.glassfish.json.fat.BasicJsonpServer +lib.pattern=customAppJSONPProvider.jar +lib.componenttest=true diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customAppJSONPWAR.war/resources/META-INF/permissions.xml b/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customAppJSONPWAR.war/resources/META-INF/permissions.xml new file mode 100644 index 00000000000..28acc02da03 --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customAppJSONPWAR.war/resources/META-INF/permissions.xml @@ -0,0 +1,20 @@ + + + + + java.lang.RuntimePermission + getenv.* + + + + java.io.FilePermission + ALL FILES + read,write + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customAppJSONPWAR.war/src/com/ibm/ws/jsonp/fat/CustomAppJSONPServlet.java b/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customAppJSONPWAR.war/src/com/ibm/ws/jsonp/fat/CustomAppJSONPServlet.java new file mode 100644 index 00000000000..cf771f427e5 --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customAppJSONPWAR.war/src/com/ibm/ws/jsonp/fat/CustomAppJSONPServlet.java @@ -0,0 +1,42 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2014 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jsonp.fat; + +import java.io.InputStream; + +import javax.json.spi.JsonProvider; +import javax.json.stream.JsonParser; +import javax.servlet.annotation.WebServlet; + +import junit.framework.Assert; + +import componenttest.app.FATServlet; + +@WebServlet("/CustomJsonProviderServlet") +@SuppressWarnings("serial") +public class CustomAppJSONPServlet extends FATServlet { + public void testCustomAppJsonProvider() { + // Verify the custom JSON Provider class is being used. + JsonProvider dummyProvider = JsonProvider.provider(); + String providerName = dummyProvider.getClass().getName(); + String expectedString1 = "com.ibm.ws.jsonp.app.provider.JsonProviderImpl"; + Assert.assertTrue("DEBUG: EXPECTED <" + expectedString1 + "> FOUND <" + providerName + ">", expectedString1.equals(providerName)); + + // Verify the custom implemented JsonParser class gets loaded and used. + InputStream dummyInputStream = null; + JsonParser dummyParser = dummyProvider.createParser(dummyInputStream); + String parserString = dummyParser.getString(); + String expectedString2 = "Custom JSONP implementation loaded from an application library"; + Assert.assertTrue("DEBUG: EXPECTED <" + expectedString2 + "> FOUND <" + parserString + ">", expectedString2.equals(parserString)); + + } +} \ No newline at end of file diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customFeatureJSONPWAR.war/package.properties b/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customFeatureJSONPWAR.war/package.properties new file mode 100644 index 00000000000..92fd83b503d --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customFeatureJSONPWAR.war/package.properties @@ -0,0 +1,2 @@ +server.pattern=com.ibm.ws.org.glassfish.json.fat.CustomFeatureJsonpServer +lib.componenttest=true diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customFeatureJSONPWAR.war/resources/META-INF/permissions.xml b/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customFeatureJSONPWAR.war/resources/META-INF/permissions.xml new file mode 100644 index 00000000000..28acc02da03 --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customFeatureJSONPWAR.war/resources/META-INF/permissions.xml @@ -0,0 +1,20 @@ + + + + + java.lang.RuntimePermission + getenv.* + + + + java.io.FilePermission + ALL FILES + read,write + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customFeatureJSONPWAR.war/src/com/ibm/ws/jsonp/fat/CustomFeatureJSONPServlet.java b/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customFeatureJSONPWAR.war/src/com/ibm/ws/jsonp/fat/CustomFeatureJSONPServlet.java new file mode 100644 index 00000000000..6424974169c --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customFeatureJSONPWAR.war/src/com/ibm/ws/jsonp/fat/CustomFeatureJSONPServlet.java @@ -0,0 +1,42 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2014 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jsonp.fat; + +import java.io.InputStream; + +import javax.json.spi.JsonProvider; +import javax.json.stream.JsonParser; +import javax.servlet.annotation.WebServlet; + +import junit.framework.Assert; + +import componenttest.app.FATServlet; + +@WebServlet("/CustomJsonProviderServlet") +@SuppressWarnings("serial") +public class CustomFeatureJSONPServlet extends FATServlet { + public void testCustomFeatureJsonProvider() { + // Verify the custom JSON Provider class is being used. + JsonProvider dummyProvider = JsonProvider.provider(); + String providerName = dummyProvider.getClass().getName(); + String expectedString1 = "com.ibm.ws.jsonp.feature.provider.JsonProviderImpl"; + Assert.assertTrue("DEBUG: EXPECTED <" + expectedString1 + "> FOUND <" + providerName + ">", expectedString1.equals(providerName)); + + // Verify the custom implemented JsonParser class gets loaded and used. + InputStream dummyInputStream = null; + JsonParser dummyParser = dummyProvider.createParser(dummyInputStream); + String parserString = dummyParser.getString(); + String expectedString2 = "Custom JSONP implementation loaded from a user defined feature"; + Assert.assertTrue("DEBUG: EXPECTED <" + expectedString2 + "> FOUND <" + parserString + ">", expectedString2.equals(parserString)); + + } +} \ No newline at end of file diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customLibJSONPProvider.jar/resources/META-INF/permissions.xml b/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customLibJSONPProvider.jar/resources/META-INF/permissions.xml new file mode 100644 index 00000000000..28acc02da03 --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customLibJSONPProvider.jar/resources/META-INF/permissions.xml @@ -0,0 +1,20 @@ + + + + + java.lang.RuntimePermission + getenv.* + + + + java.io.FilePermission + ALL FILES + read,write + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customLibJSONPProvider.jar/resources/META-INF/services/javax.json.spi.JsonProvider b/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customLibJSONPProvider.jar/resources/META-INF/services/javax.json.spi.JsonProvider new file mode 100644 index 00000000000..6f90d7810ce --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customLibJSONPProvider.jar/resources/META-INF/services/javax.json.spi.JsonProvider @@ -0,0 +1 @@ +com.ibm.ws.jsonp.lib.provider.JsonProviderImpl \ No newline at end of file diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customLibJSONPProvider.jar/src/com/ibm/ws/jsonp/lib/provider/JsonParserImpl.java b/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customLibJSONPProvider.jar/src/com/ibm/ws/jsonp/lib/provider/JsonParserImpl.java new file mode 100644 index 00000000000..54ce647847d --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customLibJSONPProvider.jar/src/com/ibm/ws/jsonp/lib/provider/JsonParserImpl.java @@ -0,0 +1,65 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2014 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jsonp.lib.provider; + +import java.math.BigDecimal; + +import javax.json.stream.JsonLocation; + +/** + * + */ +public class JsonParserImpl implements javax.json.stream.JsonParser { + + @Override + public void close() {} + + @Override + public BigDecimal getBigDecimal() { + return null; + } + + @Override + public int getInt() { + return 0; + } + + @Override + public JsonLocation getLocation() { + return null; + } + + @Override + public long getLong() { + return 0; + } + + @Override + public String getString() { + return "Custom JSONP implementation loaded from a shared library"; + } + + @Override + public boolean hasNext() { + return false; + } + + @Override + public boolean isIntegralNumber() { + return false; + } + + @Override + public Event next() { + return null; + } +} diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customLibJSONPProvider.jar/src/com/ibm/ws/jsonp/lib/provider/JsonProviderImpl.java b/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customLibJSONPProvider.jar/src/com/ibm/ws/jsonp/lib/provider/JsonProviderImpl.java new file mode 100644 index 00000000000..672ff871cc8 --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customLibJSONPProvider.jar/src/com/ibm/ws/jsonp/lib/provider/JsonProviderImpl.java @@ -0,0 +1,97 @@ +package com.ibm.ws.jsonp.lib.provider; + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; +import java.util.Map; + +import javax.json.JsonArrayBuilder; +import javax.json.JsonBuilderFactory; +import javax.json.JsonObjectBuilder; +import javax.json.JsonReader; +import javax.json.JsonReaderFactory; +import javax.json.JsonWriter; +import javax.json.JsonWriterFactory; +import javax.json.spi.JsonProvider; +import javax.json.stream.JsonGenerator; +import javax.json.stream.JsonGeneratorFactory; +import javax.json.stream.JsonParser; +import javax.json.stream.JsonParserFactory; + +public class JsonProviderImpl extends JsonProvider { + @Override + public JsonParser createParser(Reader reader) { + return null; + } + + @Override + public JsonParser createParser(InputStream in) { + return new JsonParserImpl(); + } + + @Override + public JsonParserFactory createParserFactory(Map config) { + return null; + } + + @Override + public JsonGenerator createGenerator(Writer writer) { + return null; + } + + @Override + public JsonGenerator createGenerator(OutputStream out) { + return null; + } + + @Override + public JsonGeneratorFactory createGeneratorFactory(Map config) { + return null; + } + + @Override + public JsonReader createReader(Reader reader) { + return null; + } + + @Override + public JsonReader createReader(InputStream in) { + return null; + } + + @Override + public JsonWriter createWriter(Writer writer) { + return null; + } + + @Override + public JsonWriter createWriter(OutputStream out) { + return null; + } + + @Override + public JsonWriterFactory createWriterFactory(Map config) { + return null; + } + + @Override + public JsonReaderFactory createReaderFactory(Map config) { + return null; + } + + @Override + public JsonObjectBuilder createObjectBuilder() { + return null; + } + + @Override + public JsonArrayBuilder createArrayBuilder() { + return null; + } + + @Override + public JsonBuilderFactory createBuilderFactory(Map config) { + return null; + } +} diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customLibJSONPWAR.war/package.properties b/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customLibJSONPWAR.war/package.properties new file mode 100644 index 00000000000..4678d3b93f7 --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customLibJSONPWAR.war/package.properties @@ -0,0 +1,3 @@ +server.pattern=com.ibm.ws.org.glassfish.json.fat.BasicJsonpServer +app.dir=apps +lib.componenttest=true diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customLibJSONPWAR.war/resources/META-INF/permissions.xml b/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customLibJSONPWAR.war/resources/META-INF/permissions.xml new file mode 100644 index 00000000000..28acc02da03 --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customLibJSONPWAR.war/resources/META-INF/permissions.xml @@ -0,0 +1,20 @@ + + + + + java.lang.RuntimePermission + getenv.* + + + + java.io.FilePermission + ALL FILES + read,write + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customLibJSONPWAR.war/src/com/ibm/ws/jsonp/fat/CustomLibJSONPServlet.java b/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customLibJSONPWAR.war/src/com/ibm/ws/jsonp/fat/CustomLibJSONPServlet.java new file mode 100644 index 00000000000..5322b03e301 --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/test-applications/customLibJSONPWAR.war/src/com/ibm/ws/jsonp/fat/CustomLibJSONPServlet.java @@ -0,0 +1,42 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2014 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jsonp.fat; + +import java.io.InputStream; + +import javax.json.spi.JsonProvider; +import javax.json.stream.JsonParser; +import javax.servlet.annotation.WebServlet; + +import junit.framework.Assert; + +import componenttest.app.FATServlet; + +@WebServlet("/CustomJsonProviderServlet") +@SuppressWarnings("serial") +public class CustomLibJSONPServlet extends FATServlet { + public void testCustomLibJsonProvider() { + // Verify the custom JSON Provider class is being used. + JsonProvider dummyProvider = JsonProvider.provider(); + String providerName = dummyProvider.getClass().getName(); + String expectedString1 = "com.ibm.ws.jsonp.lib.provider.JsonProviderImpl"; + Assert.assertTrue("DEBUG: EXPECTED <" + expectedString1 + "> FOUND <" + providerName + ">", expectedString1.equals(providerName)); + + // Verify the custom implemented JsonParser class gets loaded and used. + InputStream dummyInputStream = null; + JsonParser dummyParser = dummyProvider.createParser(dummyInputStream); + String parserString = dummyParser.getString(); + String expectedString2 = "Custom JSONP implementation loaded from a shared library"; + Assert.assertTrue("DEBUG: EXPECTED <" + expectedString2 + "> FOUND <" + parserString + ">", expectedString2.equals(parserString)); + + } +} \ No newline at end of file diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/test-bundles/custom.jsonp/bnd.bnd b/dev/com.ibm.ws.org.glassfish.json_fat/test-bundles/custom.jsonp/bnd.bnd new file mode 100644 index 00000000000..ab64fc7816b --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/test-bundles/custom.jsonp/bnd.bnd @@ -0,0 +1,25 @@ +-include=~../../../cnf/resources/bnd/bundle.props + +bVersion=1.0.0 + + +Bundle-SymbolicName: com.ibm.ws.jsonp.feature.provider.1.0 + +# Provide these as resources to applications. +app-resources= \ + META-INF/services/javax.json.spi.JsonProvider + +Export-Package: \ + com.ibm.ws.jsonp.feature.provider.* + +# The file system path is relative to the location of this bnd.bnd file. +Include-Resource: \ + META-INF/services=resources/META-INF/services + +Service-Component: \ + com.ibm.ws.jsonp.feature.provide_${bVersion}.ResourceProvider; \ + implementation:=com.ibm.wsspi.classloading.ResourceProvider; \ + provide:=com.ibm.wsspi.classloading.ResourceProvider; \ + configuration-policy:=ignore; \ + properties:= "resources=${app-resources}" + \ No newline at end of file diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/test-bundles/custom.jsonp/resources/META-INF/services/javax.json.spi.JsonProvider b/dev/com.ibm.ws.org.glassfish.json_fat/test-bundles/custom.jsonp/resources/META-INF/services/javax.json.spi.JsonProvider new file mode 100644 index 00000000000..cfe62ac4c41 --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/test-bundles/custom.jsonp/resources/META-INF/services/javax.json.spi.JsonProvider @@ -0,0 +1 @@ +com.ibm.ws.jsonp.feature.provider.JsonProviderImpl \ No newline at end of file diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/test-bundles/custom.jsonp/src/com/ibm/ws/jsonp/feature/provider/JsonParserImpl.java b/dev/com.ibm.ws.org.glassfish.json_fat/test-bundles/custom.jsonp/src/com/ibm/ws/jsonp/feature/provider/JsonParserImpl.java new file mode 100644 index 00000000000..11e32120c14 --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/test-bundles/custom.jsonp/src/com/ibm/ws/jsonp/feature/provider/JsonParserImpl.java @@ -0,0 +1,65 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2014 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.jsonp.feature.provider; + +import java.math.BigDecimal; + +import javax.json.stream.JsonLocation; + +/** + * + */ +public class JsonParserImpl implements javax.json.stream.JsonParser { + + @Override + public void close() {} + + @Override + public BigDecimal getBigDecimal() { + return null; + } + + @Override + public int getInt() { + return 0; + } + + @Override + public JsonLocation getLocation() { + return null; + } + + @Override + public long getLong() { + return 0; + } + + @Override + public String getString() { + return "Custom JSONP implementation loaded from a user defined feature"; + } + + @Override + public boolean hasNext() { + return false; + } + + @Override + public boolean isIntegralNumber() { + return false; + } + + @Override + public Event next() { + return null; + } +} diff --git a/dev/com.ibm.ws.org.glassfish.json_fat/test-bundles/custom.jsonp/src/com/ibm/ws/jsonp/feature/provider/JsonProviderImpl.java b/dev/com.ibm.ws.org.glassfish.json_fat/test-bundles/custom.jsonp/src/com/ibm/ws/jsonp/feature/provider/JsonProviderImpl.java new file mode 100644 index 00000000000..69e4a1d86ec --- /dev/null +++ b/dev/com.ibm.ws.org.glassfish.json_fat/test-bundles/custom.jsonp/src/com/ibm/ws/jsonp/feature/provider/JsonProviderImpl.java @@ -0,0 +1,97 @@ +package com.ibm.ws.jsonp.feature.provider; + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; +import java.util.Map; + +import javax.json.JsonArrayBuilder; +import javax.json.JsonBuilderFactory; +import javax.json.JsonObjectBuilder; +import javax.json.JsonReader; +import javax.json.JsonReaderFactory; +import javax.json.JsonWriter; +import javax.json.JsonWriterFactory; +import javax.json.spi.JsonProvider; +import javax.json.stream.JsonGenerator; +import javax.json.stream.JsonGeneratorFactory; +import javax.json.stream.JsonParser; +import javax.json.stream.JsonParserFactory; + +public class JsonProviderImpl extends JsonProvider { + @Override + public JsonParser createParser(Reader reader) { + return null; + } + + @Override + public JsonParser createParser(InputStream in) { + return new JsonParserImpl(); + } + + @Override + public JsonParserFactory createParserFactory(Map config) { + return null; + } + + @Override + public JsonGenerator createGenerator(Writer writer) { + return null; + } + + @Override + public JsonGenerator createGenerator(OutputStream out) { + return null; + } + + @Override + public JsonGeneratorFactory createGeneratorFactory(Map config) { + return null; + } + + @Override + public JsonReader createReader(Reader reader) { + return null; + } + + @Override + public JsonReader createReader(InputStream in) { + return null; + } + + @Override + public JsonWriter createWriter(Writer writer) { + return null; + } + + @Override + public JsonWriter createWriter(OutputStream out) { + return null; + } + + @Override + public JsonWriterFactory createWriterFactory(Map config) { + return null; + } + + @Override + public JsonReaderFactory createReaderFactory(Map config) { + return null; + } + + @Override + public JsonObjectBuilder createObjectBuilder() { + return null; + } + + @Override + public JsonArrayBuilder createArrayBuilder() { + return null; + } + + @Override + public JsonBuilderFactory createBuilderFactory(Map config) { + return null; + } +} diff --git a/dev/com.ibm.ws.org.osgi.service.resolver/.classpath.ant b/dev/com.ibm.ws.org.osgi.service.resolver/.classpath.ant deleted file mode 100644 index 6e48000f881..00000000000 --- a/dev/com.ibm.ws.org.osgi.service.resolver/.classpath.ant +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/dev/com.ibm.ws.product.utility_bvt/bnd.bnd b/dev/com.ibm.ws.product.utility_bvt/bnd.bnd index df45604f272..27abb02cc16 100755 --- a/dev/com.ibm.ws.product.utility_bvt/bnd.bnd +++ b/dev/com.ibm.ws.product.utility_bvt/bnd.bnd @@ -13,4 +13,4 @@ src: \ ../build.sharedResources/lib/hamcrest-all.jar;version=file, \ ../build.sharedResources/lib/jmock/old/jmock-junit4.jar;version=file, \ ../build.sharedResources/lib/jmock/old/jmock.jar;version=file, \ - com.ibm.ws.threading;version=latest + com.ibm.ws.product.utility;version=latest diff --git a/dev/com.ibm.ws.product.utility_bvt/bnd.bnd.gradle b/dev/com.ibm.ws.product.utility_bvt/bnd.bnd.gradle index df45604f272..27abb02cc16 100755 --- a/dev/com.ibm.ws.product.utility_bvt/bnd.bnd.gradle +++ b/dev/com.ibm.ws.product.utility_bvt/bnd.bnd.gradle @@ -13,4 +13,4 @@ src: \ ../build.sharedResources/lib/hamcrest-all.jar;version=file, \ ../build.sharedResources/lib/jmock/old/jmock-junit4.jar;version=file, \ ../build.sharedResources/lib/jmock/old/jmock.jar;version=file, \ - com.ibm.ws.threading;version=latest + com.ibm.ws.product.utility;version=latest diff --git a/dev/com.ibm.ws.product.utility_fat/.classpath b/dev/com.ibm.ws.product.utility_fat/.classpath new file mode 100644 index 00000000000..c422489df40 --- /dev/null +++ b/dev/com.ibm.ws.product.utility_fat/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/dev/com.ibm.ws.product.utility_fat/.classpath.gradle b/dev/com.ibm.ws.product.utility_fat/.classpath.gradle new file mode 100644 index 00000000000..c422489df40 --- /dev/null +++ b/dev/com.ibm.ws.product.utility_fat/.classpath.gradle @@ -0,0 +1,7 @@ + + + + + + + diff --git a/dev/com.ibm.ws.product.utility_fat/.gitignore b/dev/com.ibm.ws.product.utility_fat/.gitignore new file mode 100644 index 00000000000..106ad11d242 --- /dev/null +++ b/dev/com.ibm.ws.product.utility_fat/.gitignore @@ -0,0 +1,5 @@ +bundles +dist +/*.log* +/coverage.ec +/lib diff --git a/dev/com.ibm.ws.product.utility_fat/.project b/dev/com.ibm.ws.product.utility_fat/.project new file mode 100755 index 00000000000..f421c24b889 --- /dev/null +++ b/dev/com.ibm.ws.product.utility_fat/.project @@ -0,0 +1,23 @@ + + + com.ibm.ws.product.utility_fat + + + + + + org.eclipse.jdt.core.javabuilder + + + + + bndtools.core.bndbuilder + + + + + + org.eclipse.jdt.core.javanature + bndtools.core.bndnature + + diff --git a/dev/com.ibm.ws.product.utility_fat/.settings/org.eclipse.core.resources.prefs b/dev/com.ibm.ws.product.utility_fat/.settings/org.eclipse.core.resources.prefs new file mode 100755 index 00000000000..25d9425fe34 --- /dev/null +++ b/dev/com.ibm.ws.product.utility_fat/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,4 @@ +#Ant properties +#Automatically generated by the ant prepare.settings.files task +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/dev/com.ibm.ws.product.utility_fat/.settings/org.eclipse.jdt.core.prefs b/dev/com.ibm.ws.product.utility_fat/.settings/org.eclipse.jdt.core.prefs new file mode 100755 index 00000000000..845c3083c7d --- /dev/null +++ b/dev/com.ibm.ws.product.utility_fat/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,286 @@ +#Ant properties +#Automatically generated by the ant prepare.settings.files task +org.eclipse.jdt.core.codeComplete.argumentPrefixes= +org.eclipse.jdt.core.codeComplete.argumentSuffixes= +org.eclipse.jdt.core.codeComplete.fieldPrefixes= +org.eclipse.jdt.core.codeComplete.fieldSuffixes= +org.eclipse.jdt.core.codeComplete.localPrefixes= +org.eclipse.jdt.core.codeComplete.localSuffixes= +org.eclipse.jdt.core.codeComplete.staticFieldPrefixes= +org.eclipse.jdt.core.codeComplete.staticFieldSuffixes= +org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes= +org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes= +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.6 +org.eclipse.jdt.core.formatter.align_type_members_on_columns=false +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=0 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=18 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=2 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=2 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=18 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=2 +org.eclipse.jdt.core.formatter.alignment_for_assignment=0 +org.eclipse.jdt.core.formatter.alignment_for_binary_expression=18 +org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=0 +org.eclipse.jdt.core.formatter.alignment_for_enum_constants=16 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=18 +org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=18 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=18 +org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=0 +org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=20 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=4 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +org.eclipse.jdt.core.formatter.blank_lines_before_field=0 +org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 +org.eclipse.jdt.core.formatter.blank_lines_before_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 +org.eclipse.jdt.core.formatter.blank_lines_before_package=0 +org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 +org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 +org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false +org.eclipse.jdt.core.formatter.comment.format_block_comments=true +org.eclipse.jdt.core.formatter.comment.format_header=false +org.eclipse.jdt.core.formatter.comment.format_html=false +org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true +org.eclipse.jdt.core.formatter.comment.format_line_comments=false +org.eclipse.jdt.core.formatter.comment.format_source_code=true +org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true +org.eclipse.jdt.core.formatter.comment.indent_root_tags=true +org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert +org.eclipse.jdt.core.formatter.comment.line_length=180 +org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true +org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true +org.eclipse.jdt.core.formatter.compact_else_if=true +org.eclipse.jdt.core.formatter.continuation_indentation=4 +org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=4 +org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off +org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on +org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false +org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=false +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true +org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_empty_lines=false +org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true +org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true +org.eclipse.jdt.core.formatter.indentation.size=8 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert +org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.join_lines_in_comments=false +org.eclipse.jdt.core.formatter.join_wrapped_lines=false +org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false +org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false +org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false +org.eclipse.jdt.core.formatter.lineSplit=180 +org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=true +org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=true +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 +org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=false +org.eclipse.jdt.core.formatter.tabulation.char=space +org.eclipse.jdt.core.formatter.tabulation.size=4 +org.eclipse.jdt.core.formatter.use_on_off_tags=true +org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false +org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true +org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true diff --git a/dev/com.ibm.ws.product.utility_fat/.settings/org.eclipse.jdt.ui.prefs b/dev/com.ibm.ws.product.utility_fat/.settings/org.eclipse.jdt.ui.prefs new file mode 100755 index 00000000000..c874b581698 --- /dev/null +++ b/dev/com.ibm.ws.product.utility_fat/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,117 @@ +#Ant properties +#Automatically generated by the ant prepare.settings.files task +cleanup.add_default_serial_version_id=false +cleanup.add_generated_serial_version_id=true +cleanup.add_missing_annotations=true +cleanup.add_missing_deprecated_annotations=true +cleanup.add_missing_methods=false +cleanup.add_missing_nls_tags=false +cleanup.add_missing_override_annotations=true +cleanup.add_missing_override_annotations_interface_methods=true +cleanup.add_serial_version_id=false +cleanup.always_use_blocks=true +cleanup.always_use_parentheses_in_expressions=false +cleanup.always_use_this_for_non_static_field_access=false +cleanup.always_use_this_for_non_static_method_access=false +cleanup.convert_to_enhanced_for_loop=false +cleanup.correct_indentation=true +cleanup.format_source_code=false +cleanup.format_source_code_changes_only=false +cleanup.make_local_variable_final=false +cleanup.make_parameters_final=true +cleanup.make_private_fields_final=false +cleanup.make_type_abstract_if_missing_method=false +cleanup.make_variable_declarations_final=false +cleanup.never_use_blocks=false +cleanup.never_use_parentheses_in_expressions=true +cleanup.organize_imports=false +cleanup.qualify_static_field_accesses_with_declaring_class=false +cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true +cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true +cleanup.qualify_static_member_accesses_with_declaring_class=true +cleanup.qualify_static_method_accesses_with_declaring_class=false +cleanup.remove_private_constructors=true +cleanup.remove_trailing_whitespaces=true +cleanup.remove_trailing_whitespaces_all=true +cleanup.remove_trailing_whitespaces_ignore_empty=false +cleanup.remove_unnecessary_casts=true +cleanup.remove_unnecessary_nls_tags=true +cleanup.remove_unused_imports=true +cleanup.remove_unused_local_variables=false +cleanup.remove_unused_private_fields=true +cleanup.remove_unused_private_members=false +cleanup.remove_unused_private_methods=true +cleanup.remove_unused_private_types=true +cleanup.sort_members=false +cleanup.sort_members_all=false +cleanup.use_blocks=true +cleanup.use_blocks_only_for_return_and_throw=false +cleanup.use_parentheses_in_expressions=true +cleanup.use_this_for_non_static_field_access=false +cleanup.use_this_for_non_static_field_access_only_if_necessary=true +cleanup.use_this_for_non_static_method_access=false +cleanup.use_this_for_non_static_method_access_only_if_necessary=true +eclipse.preferences.version=1 +editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true +org.eclipse.jdt.ui.exception.name=e +org.eclipse.jdt.ui.gettersetter.use.is=false +org.eclipse.jdt.ui.ignorelowercasenames=true +org.eclipse.jdt.ui.importorder=java;javax;org;com; +org.eclipse.jdt.ui.javadoc=true +org.eclipse.jdt.ui.keywordthis=false +org.eclipse.jdt.ui.ondemandthreshold=99 +org.eclipse.jdt.ui.overrideannotation=true +org.eclipse.jdt.ui.staticondemandthreshold=99 +org.eclipse.jdt.ui.text.custom_code_templates= +sp_cleanup.add_default_serial_version_id=true +sp_cleanup.add_generated_serial_version_id=false +sp_cleanup.add_missing_annotations=true +sp_cleanup.add_missing_deprecated_annotations=true +sp_cleanup.add_missing_methods=false +sp_cleanup.add_missing_nls_tags=false +sp_cleanup.add_missing_override_annotations=true +sp_cleanup.add_missing_override_annotations_interface_methods=true +sp_cleanup.add_serial_version_id=false +sp_cleanup.always_use_blocks=true +sp_cleanup.always_use_parentheses_in_expressions=false +sp_cleanup.always_use_this_for_non_static_field_access=false +sp_cleanup.always_use_this_for_non_static_method_access=false +sp_cleanup.convert_to_enhanced_for_loop=false +sp_cleanup.correct_indentation=false +sp_cleanup.format_source_code=true +sp_cleanup.format_source_code_changes_only=false +sp_cleanup.make_local_variable_final=false +sp_cleanup.make_parameters_final=false +sp_cleanup.make_private_fields_final=true +sp_cleanup.make_type_abstract_if_missing_method=false +sp_cleanup.make_variable_declarations_final=true +sp_cleanup.never_use_blocks=false +sp_cleanup.never_use_parentheses_in_expressions=true +sp_cleanup.on_save_use_additional_actions=true +sp_cleanup.organize_imports=true +sp_cleanup.qualify_static_field_accesses_with_declaring_class=false +sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_with_declaring_class=false +sp_cleanup.qualify_static_method_accesses_with_declaring_class=false +sp_cleanup.remove_private_constructors=true +sp_cleanup.remove_trailing_whitespaces=true +sp_cleanup.remove_trailing_whitespaces_all=true +sp_cleanup.remove_trailing_whitespaces_ignore_empty=false +sp_cleanup.remove_unnecessary_casts=true +sp_cleanup.remove_unnecessary_nls_tags=true +sp_cleanup.remove_unused_imports=true +sp_cleanup.remove_unused_local_variables=false +sp_cleanup.remove_unused_private_fields=true +sp_cleanup.remove_unused_private_members=false +sp_cleanup.remove_unused_private_methods=true +sp_cleanup.remove_unused_private_types=true +sp_cleanup.sort_members=false +sp_cleanup.sort_members_all=false +sp_cleanup.use_blocks=false +sp_cleanup.use_blocks_only_for_return_and_throw=false +sp_cleanup.use_parentheses_in_expressions=false +sp_cleanup.use_this_for_non_static_field_access=false +sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true +sp_cleanup.use_this_for_non_static_method_access=false +sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true diff --git a/dev/com.ibm.ws.product.utility_fat/bnd.bnd b/dev/com.ibm.ws.product.utility_fat/bnd.bnd new file mode 100644 index 00000000000..20b28a82bd2 --- /dev/null +++ b/dev/com.ibm.ws.product.utility_fat/bnd.bnd @@ -0,0 +1,28 @@ +-include= ~../cnf/resources/bnd/bundle.props +bVersion=1.0 + +src: \ + fat/src + +-buildpath: \ + ${javac.bootclasspath.java6}, \ + ../build.sharedResources/lib/junit/old/junit.jar;version=file, \ + ../build.sharedResources/lib/ws-junit/ws-junit.jar;version=file, \ + ../build.sharedResources/lib/hamcrest-all.jar;version=file, \ + ../build.sharedResources/lib/jmock/old/jmock-junit4.jar;version=file, \ + ../build.sharedResources/lib/jmock/old/jmock.jar;version=file, \ + fattest.simplicity;version=latest, \ + ../fattest.simplicity/lib/public.api.jar;version=file, \ + ../com.ibm.ws.kernel.boot.archive/lib/org.apache.commons.compress-1.10.jar;version=file, \ + com.ibm.websphere.org.osgi.core.6.0.0;version=latest, \ + com.ibm.websphere.org.osgi.service.cm.1.5.0;version=latest,\ + com.ibm.websphere.org.osgi.service.component.1.3.0;version=latest,\ + com.ibm.wsspi.thirdparty.equinox;version=latest, \ + com.ibm.ws.kernel.boot.core;version=latest,\ + com.ibm.ws.kernel.service;version=latest,\ + com.ibm.ws.kernel.service.location;version=latest,\ + com.ibm.ws.logging.core;version=latest,\ + com.ibm.ws.org.eclipse.equinox.region.1.3.2;version=latest, \ + com.ibm.ws.runtime.update;version=latest, \ + com.ibm.ws.kernel.feature.core;version=latest, \ + com.ibm.ws.kernel.feature;version=latest diff --git a/dev/com.ibm.ws.product.utility_fat/bnd.bnd.gradle b/dev/com.ibm.ws.product.utility_fat/bnd.bnd.gradle new file mode 100644 index 00000000000..20b28a82bd2 --- /dev/null +++ b/dev/com.ibm.ws.product.utility_fat/bnd.bnd.gradle @@ -0,0 +1,28 @@ +-include= ~../cnf/resources/bnd/bundle.props +bVersion=1.0 + +src: \ + fat/src + +-buildpath: \ + ${javac.bootclasspath.java6}, \ + ../build.sharedResources/lib/junit/old/junit.jar;version=file, \ + ../build.sharedResources/lib/ws-junit/ws-junit.jar;version=file, \ + ../build.sharedResources/lib/hamcrest-all.jar;version=file, \ + ../build.sharedResources/lib/jmock/old/jmock-junit4.jar;version=file, \ + ../build.sharedResources/lib/jmock/old/jmock.jar;version=file, \ + fattest.simplicity;version=latest, \ + ../fattest.simplicity/lib/public.api.jar;version=file, \ + ../com.ibm.ws.kernel.boot.archive/lib/org.apache.commons.compress-1.10.jar;version=file, \ + com.ibm.websphere.org.osgi.core.6.0.0;version=latest, \ + com.ibm.websphere.org.osgi.service.cm.1.5.0;version=latest,\ + com.ibm.websphere.org.osgi.service.component.1.3.0;version=latest,\ + com.ibm.wsspi.thirdparty.equinox;version=latest, \ + com.ibm.ws.kernel.boot.core;version=latest,\ + com.ibm.ws.kernel.service;version=latest,\ + com.ibm.ws.kernel.service.location;version=latest,\ + com.ibm.ws.logging.core;version=latest,\ + com.ibm.ws.org.eclipse.equinox.region.1.3.2;version=latest, \ + com.ibm.ws.runtime.update;version=latest, \ + com.ibm.ws.kernel.feature.core;version=latest, \ + com.ibm.ws.kernel.feature;version=latest diff --git a/dev/com.ibm.ws.product.utility_fat/build-test.xml b/dev/com.ibm.ws.product.utility_fat/build-test.xml new file mode 100755 index 00000000000..adf0e26c1ad --- /dev/null +++ b/dev/com.ibm.ws.product.utility_fat/build-test.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/dev/com.ibm.ws.product.utility_fat/build.gradle b/dev/com.ibm.ws.product.utility_fat/build.gradle new file mode 100644 index 00000000000..e69de29bb2d diff --git a/dev/com.ibm.ws.product.utility_fat/delivery.sets b/dev/com.ibm.ws.product.utility_fat/delivery.sets new file mode 100755 index 00000000000..674398425a0 --- /dev/null +++ b/dev/com.ibm.ws.product.utility_fat/delivery.sets @@ -0,0 +1 @@ +SLE diff --git a/dev/com.ibm.ws.product.utility_fat/fat/src/com/ibm/ws/product/utility/fat/FATSuite.java b/dev/com.ibm.ws.product.utility_fat/fat/src/com/ibm/ws/product/utility/fat/FATSuite.java new file mode 100755 index 00000000000..92b28c8f443 --- /dev/null +++ b/dev/com.ibm.ws.product.utility_fat/fat/src/com/ibm/ws/product/utility/fat/FATSuite.java @@ -0,0 +1,30 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.product.utility.fat; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +@RunWith(Suite.class) +@SuiteClasses({ + ProductUtilToolTest.class, + ProductInfoToolTest.class, + ProductInfoValidateTest.class, + ProductInfoLicenseFileTest.class +}) +/** + * Purpose: This suite collects and runs all known good test suites. + */ +public class FATSuite { + +} diff --git a/dev/com.ibm.ws.product.utility_fat/fat/src/com/ibm/ws/product/utility/fat/ProductInfoLicenseFileTest.java b/dev/com.ibm.ws.product.utility_fat/fat/src/com/ibm/ws/product/utility/fat/ProductInfoLicenseFileTest.java new file mode 100755 index 00000000000..2adea07dac0 --- /dev/null +++ b/dev/com.ibm.ws.product.utility_fat/fat/src/com/ibm/ws/product/utility/fat/ProductInfoLicenseFileTest.java @@ -0,0 +1,205 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2015 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.product.utility.fat; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.util.Collection; +import java.util.HashSet; +import java.util.Locale; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestName; + +import com.ibm.websphere.simplicity.ProgramOutput; +import com.ibm.websphere.simplicity.log.Log; +import componenttest.topology.impl.LibertyServer; +import componenttest.topology.impl.LibertyServerFactory; + +/** + * This class tests that license information and license agreement gets generated properly + */ +public class ProductInfoLicenseFileTest { + + public static final Class c = ProductInfoLicenseFileTest.class; + public static LibertyServer server = LibertyServerFactory.getLibertyServer("com.ibm.ws.kernel.feature.fat.info.tool"); + public static String javaExc; + public static String installRoot; + public static final Collection filesToTidy = new HashSet(); + + @Rule + public final TestName method = new TestName(); + + @BeforeClass + public static void before() throws Exception { + setupEnv(LibertyServerFactory.getLibertyServer("com.ibm.ws.kernel.feature.fat.info.tool")); + } + + @AfterClass + public static void after() throws Exception { + server.deleteDirectoryFromLibertyInstallRoot("lafiles"); + } + + /** + * Setup the environment. + * + * @param svr The server instance. + * + * @throws Exception + */ + public static void setupEnv(LibertyServer svr) throws Exception { + final String METHOD_NAME = "setup"; + server = svr; + installRoot = server.getInstallRoot(); + javaExc = System.getProperty("java.home") + "/bin/java"; + Log.entering(c, METHOD_NAME); + Log.info(c, METHOD_NAME, "java: " + javaExc); + Log.info(c, METHOD_NAME, "installRoot: " + installRoot); + + // Create a directory to store the output files. + File toolsOutputDir = new File(installRoot + "/tool.output.dir"); + toolsOutputDir.mkdir(); + } + + /** + * Tests that the license information gets generated properly + * + * @throws Exception + */ + @Test + public void testLicenseInformation() throws Exception { + Log.entering(c, method.getMethodName()); + + if (!verifyLicenseFilesExists()) { + Log.info(c, method.getMethodName(), "The lafiles directory does not exist in installdir. Skipping."); + return; + } + + testLicenseInfoContents(installRoot + "/bin/productInfo", new String[] { "viewLicenseInfo" }, installRoot); + Log.exiting(c, method.getMethodName()); + } + + /** + * Tests that the agreement information gets generated properly + * + * @throws Exception + */ + @Test + public void testLicenseAgreement() throws Exception { + Log.entering(c, method.getMethodName()); + + if (!verifyLicenseFilesExists()) { + Log.info(c, method.getMethodName(), "The lafiles directory does not exist in installdir. Skipping."); + return; + } + testLicenseAgreementContents(installRoot + "/bin/productInfo", new String[] { "viewLicenseAgreement" }, installRoot); + Log.exiting(c, method.getMethodName()); + } + + /** + * Tests the command productInfo produces license information correctly + * + * @param cmd The command to execute. + * @param parms The parameters for the command. + * @param workDir The working directory where the command is to be issued. + * + * @throws Exception + */ + public void testLicenseInfoContents(String cmd, String[] parms, String workDir) throws Exception { + Log.entering(c, method.getMethodName()); + + if (!verifyLicenseFilesExists()) { + Log.info(c, method.getMethodName(), "The lafiles directory does not exist in installdir. Skipping."); + return; + } + + ProgramOutput po = server.getMachine().execute(cmd, parms, workDir); + logInfo(po); + assertEquals("License information should be generated", po.getReturnCode(), 0); + + Locale locale = Locale.getDefault(); + String lang = locale.getLanguage(); + Log.info(ProductInfoLicenseFileTest.class, "localelanguage", lang); + + assertTrue("FAIL: License information doesnt exist:", new File(installRoot + "/lafiles/" + "LI_" + lang).exists()); + assertEquals("License locale is not en or not LI:", "LI_" + lang, new File(installRoot + "/lafiles/" + "LI_" + lang).getName()); + Log.exiting(c, method.getMethodName()); + } + + /** + * Tests the command productInfo produces license agreement correctly + * + * @param cmd The command to execute. + * @param parms The parameters for the command. + * @param workDir The working directory where the command is to be issued. + * + * @throws Exception + */ + public void testLicenseAgreementContents(String cmd, String[] parms, String workDir) throws Exception { + Log.entering(c, method.getMethodName()); + + if (!verifyLicenseFilesExists()) { + Log.info(c, method.getMethodName(), "The lafiles directory does not exist in installdir. Skipping."); + return; + } + + ProgramOutput po = server.getMachine().execute(cmd, parms, workDir); + logInfo(po); + assertEquals("License agreement should be generated", po.getReturnCode(), 0); + + Locale locale = Locale.getDefault(); + String lang = locale.getLanguage(); + Log.info(ProductInfoLicenseFileTest.class, "localelanguage", lang); + + assertTrue("FAIL: License agreement doesnt exist:", new File(installRoot + "/lafiles/" + "LA_" + lang).exists()); + assertEquals("License locale is not en or not LA:", "LA_" + lang, new File(installRoot + "/lafiles/" + "LA_" + lang).getName()); + Log.exiting(c, method.getMethodName()); + } + + /** + * Prints an extended debug output. + * + * @param po The programOutput + * @param fileName + * @throws Exception + */ + public void logInfo(ProgramOutput po) throws Exception { + String methodName = "logInfo"; + Log.info(c, methodName, "Return Code: " + po.getReturnCode() + ". STDOUT: " + po.getStdout()); + + if (po.getReturnCode() != 0) { + Log.info(c, methodName, "STDERR: " + po.getStderr()); + } + } + + private boolean verifyLicenseFilesExists() { + boolean licenseFileExists = false; + File folder = new File(installRoot + "/lafiles/"); + + if (folder.exists()) { + for (File fileEntry : folder.listFiles()) { + if (fileEntry.exists() && !(fileEntry.getName().startsWith("com.ibm"))) { + licenseFileExists = true; + } else { + licenseFileExists = false; + } + Log.info(ProductInfoLicenseFileTest.class, method.getMethodName(), fileEntry.getName() + "status:" + licenseFileExists); + } + } + return licenseFileExists; + } +} diff --git a/dev/com.ibm.ws.product.utility_fat/fat/src/com/ibm/ws/product/utility/fat/ProductInfoToolTest.java b/dev/com.ibm.ws.product.utility_fat/fat/src/com/ibm/ws/product/utility/fat/ProductInfoToolTest.java new file mode 100755 index 00000000000..c268fe9c82c --- /dev/null +++ b/dev/com.ibm.ws.product.utility_fat/fat/src/com/ibm/ws/product/utility/fat/ProductInfoToolTest.java @@ -0,0 +1,126 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.product.utility.fat; + +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.util.Properties; + +import org.junit.BeforeClass; +import org.junit.Test; + +import com.ibm.websphere.simplicity.ProgramOutput; +import com.ibm.websphere.simplicity.log.Log; +import componenttest.topology.impl.LibertyServerFactory; + +public class ProductInfoToolTest extends ProductToolTestCommon { + + @BeforeClass + public static void beforeClassSetup() throws Exception { + setupEnv(LibertyServerFactory.getLibertyServer("com.ibm.ws.kernel.feature.fat.info.tool")); + setupProductExtensions(SETUP_ALL_PROD_EXTS); + + } + + /** + * Test that productInfo version will display information for all installed products. + * This includes core, product extensions in default usr location and other installed product extensions. + * + * @throws Exception + */ + @Test + public void testProdInfoToolPrintProductVersionForAllProductsInstalled() throws Exception { + testPrintProductVersionForAllProductsInstalled(installRoot + "/bin/productInfo", new String[] { "version" }, installRoot); + } + + /** + * Test that productInfo featureInfo will display a list of all installed features. + * This includes core, product extensions in default usr location and other installed product extensions. + * + * @throws Exception + */ + @Test + public void testProdInfoToolPrintFeatureInfoForAllProductsInstalled() throws Exception { + testPrintFeatureInfoForAllProductsInstalled(installRoot + "/bin/productInfo", new String[] { "featureInfo" }, installRoot); + } + + /** + * Test that productInfo version will display ifix information for all installed products. + * This includes core, product extensions in default usr location and other installed product extensions. + * + * @throws Exception + */ + @Test + public void testProdInfoToolPrintProductVersionIfixesForAllProductsInstalled() throws Exception { + testPrintProductVersionIfixesForAllProductsInstalled(installRoot + "/bin/productInfo", new String[] { "version", "--ifixes" }, installRoot); + } + + /** + * + * Tests the command that lists the installed features for all products installed + * does not have duplicates in the list. + * + * @throws Exception + */ + @Test + public void testPrintFeatureInfoForAllProductsInstalledNoDuplicates() throws Exception { + final String METHOD_NAME = "testPrintFeatureInfoForAllProductsInstalledNoDuplicates"; + Log.entering(c, METHOD_NAME); + String cmd = installRoot + "/bin/productInfo"; + String[] parms = new String[] { "featureInfo" }; + + ProgramOutput po = server.getMachine().execute(cmd, parms, installRoot); + logInfo(po); + String stdout = po.getStdout(); + assertTrue("The output should contain only one copy of the usr product feature: usertest-1.0 [1.0.0].", + stdout.indexOf("usertest [1.0.0]") == stdout.lastIndexOf("usertest [1.0.0]")); + assertTrue("The output should contain only one copy of the product feature: prodtest-1.0 [1.0.0].", + stdout.indexOf("prodtest-1.0 [1.0.0]") == stdout.lastIndexOf("prodtest-1.0 [1.0.0]")); + assertTrue("The output should contain only one copy of the core features: check servlet-3.0 [1.0.0].", + stdout.indexOf("servlet-3.0 [1.0.0]") == stdout.lastIndexOf("servlet-3.0 [1.0.0]")); + + Log.exiting(c, METHOD_NAME); + } + + @Test + /** + * This test validates that the productInfo script functions correctly when the CDPATH environment variable + * is present. + * + * @throws Exception + */ + public void testProdInfoToolWithCDPATH() throws Exception { + final String METHOD_NAME = "testProdInfoToolWithCDPATH"; + Log.entering(c, METHOD_NAME); + + // issuing the command from the Liberty install root while supplying the bin directory as + // part of the command itself causes the productInfo script to cd to the bin directory, which + // is where we noticed problems when CDPATH is set + String executionDir = server.getInstallRoot(); + String command = "bin" + File.separator + "productInfo"; + + String[] parms = new String[1]; + parms[0] = "version"; + + Properties envVars = new Properties(); + envVars.put("CDPATH", "."); + + ProgramOutput po = server.getMachine().execute(command, parms, executionDir, envVars); + Log.info(c, METHOD_NAME, "stdout = " + po.getStdout()); + Log.info(c, METHOD_NAME, "stderr = " + po.getStderr()); + + assertTrue("productInfo does not contain the correct output", po.getStdout().contains("Product name")); + + Log.exiting(c, METHOD_NAME); + } +} \ No newline at end of file diff --git a/dev/com.ibm.ws.product.utility_fat/fat/src/com/ibm/ws/product/utility/fat/ProductInfoValidateTest.java b/dev/com.ibm.ws.product.utility_fat/fat/src/com/ibm/ws/product/utility/fat/ProductInfoValidateTest.java new file mode 100755 index 00000000000..293023ead7c --- /dev/null +++ b/dev/com.ibm.ws.product.utility_fat/fat/src/com/ibm/ws/product/utility/fat/ProductInfoValidateTest.java @@ -0,0 +1,67 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.product.utility.fat; + +import static org.junit.Assert.assertTrue; + +import org.junit.BeforeClass; +import org.junit.Test; + +import com.ibm.websphere.simplicity.ProgramOutput; +import com.ibm.websphere.simplicity.log.Log; +import componenttest.topology.impl.LibertyServer; +import componenttest.topology.impl.LibertyServerFactory; + +/** + * + */ +public class ProductInfoValidateTest { + + public static Class c = ProductInfoValidateTest.class; + //don't really need a server for this test, but need to get the install paths + public static LibertyServer server = LibertyServerFactory.getLibertyServer("com.ibm.ws.product.utility.test.validate.server"); + + private static String installRoot; + + @BeforeClass + public static void setup() throws Exception { + final String METHOD_NAME = "setup"; + installRoot = server.getInstallRoot(); + Log.entering(c, METHOD_NAME); + Log.info(c, METHOD_NAME, "installRoot: " + installRoot); + } + + /** + * Tests that we can run the productInfo validate command without exception. + * Does not verify the output of the command, only that there were no exceptions + * during the run of the command. + * + * @throws Exception + */ + @Test + public void testProductInfoValidate() throws Exception { + final String METHOD_NAME = "testProductInfoValidate"; + Log.entering(c, METHOD_NAME); + String cmd = installRoot + "/bin/productInfo"; + String[] parms = new String[] { "validate" }; + + ProgramOutput po = server.getMachine().execute(cmd, parms, installRoot); + Log.info(c, METHOD_NAME, "productInfo validate stdout: "); + Log.info(c, METHOD_NAME, po.getStdout()); + Log.info(c, METHOD_NAME, "productInfo validate stderr: "); + Log.info(c, METHOD_NAME, po.getStderr()); + assertTrue("The productInfo validate command returned an error code, see autoFVT/results/output.txt log for detailed output", po.getReturnCode() == 0); + + Log.exiting(c, METHOD_NAME); + } + +} diff --git a/dev/com.ibm.ws.product.utility_fat/fat/src/com/ibm/ws/product/utility/fat/ProductToolTestCommon.java b/dev/com.ibm.ws.product.utility_fat/fat/src/com/ibm/ws/product/utility/fat/ProductToolTestCommon.java new file mode 100755 index 00000000000..729cef8cb77 --- /dev/null +++ b/dev/com.ibm.ws.product.utility_fat/fat/src/com/ibm/ws/product/utility/fat/ProductToolTestCommon.java @@ -0,0 +1,265 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * WLP Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.product.utility.fat; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.util.Collection; +import java.util.HashSet; + +import org.junit.AfterClass; + +import com.ibm.websphere.simplicity.ProgramOutput; +import com.ibm.websphere.simplicity.log.Log; +import componenttest.topology.impl.LibertyServer; + +/** + * + */ +public abstract class ProductToolTestCommon { + public static final Class c = ProductToolTestCommon.class; + public static LibertyServer server; + public static String javaExc; + public static String installRoot; + + // ETC product extension related variables. + public static final String PRODUCT_FEATURE_PATH = "producttest/lib/features/"; + public static final String PRODUCT_VERSIONS_PATH = "producttest/lib/versions/"; + public static final String PRODUCT_BUNDLE_PATH = "producttest/lib/"; + public static final String PRODUCT_EXTENSIONS_PATH = "etc/extensions/"; + public static final String PRODUCT_FEATURE_PROPERTIES_FILE = "testproduct.properties"; + public static final String PRODUCT_VERSIONS_PROPERTIES_FILE = "producttest.properties"; + public static final String PRODUCT_FEATURE_PRODTEST_MF = "prodtest-1.0.mf"; + public static final String PRODUCT_FEATURE_PRODTEST_JAR = "com.ibm.ws.prodtest.internal_1.0.jar"; + public static final String PRODUCT_EXT_NAME = "testproduct"; + + // USR product extension related properties: + public static final String USR_PRODUCT_BUNDLE_PATH = "usr/extension/lib/"; + public static final String USR_PRODUCT_FEATURE_PATH = "usr/extension/lib/features/"; + public static final String USR_PRODUCT_VERSIONS_PATH = "usr/extension/lib/versions/"; + public static final String USR_PRODUCT_FEATURE_NAME = "usertest.with.versions.props.file"; + public static final String USR_PRODUCT_FEATURE_MF = "user.ext.version.info.mf"; + public static final String USR_PRODUCT_BUNDLE_JAR = "userProdExt_1.0.0.jar"; + public static final String USR_PRODUCT_VERSIONS_PROPERTIES_FILE = "user.ext.version.info.properties"; + + // Product pre-set return codes as set in: + // com.ibm.ws.kernel.feature.internal.cmdline.ReturnCode, + // com.ibm.ws.kernel.feature.internal.generator.FeatureListOptions. + public static final int PRODUCT_EXT_NOT_FOUND = 26; + public static final int PRODUCT_EXT_NOT_DEFINED = 27; + public static final int PRODUCT_EXT_NO_FEATURES_FOUND = 28; + + // Other variables. + public static final String CORE_PRODUCT_NAME = "core"; + public static final String USR_PRODUCT_NAME = "usr"; + public static final int SETUP_PROD_EXT = 1; + public static final int SETUP_USR_PROD_EXT = 2; + public static final int SETUP_ALL_PROD_EXTS = 3; + public static final Collection filesToTidy = new HashSet(); + + /** + * Setup the environment. + * + * @param svr The server instance. + * + * @throws Exception + */ + public static void setupEnv(LibertyServer svr) throws Exception { + final String METHOD_NAME = "setup"; + server = svr; + installRoot = server.getInstallRoot(); + javaExc = System.getProperty("java.home") + "/bin/java"; + Log.entering(c, METHOD_NAME); + Log.info(c, METHOD_NAME, "java: " + javaExc); + Log.info(c, METHOD_NAME, "installRoot: " + installRoot); + + // Create a directory to store the output files. + File toolsOutputDir = new File(installRoot + "/tool.output.dir"); + toolsOutputDir.mkdir(); + } + + /** + * Setup product extensions. + * + * @param setupOption The option that determines what preset product extension will be installed. + * + * @throws Exception + */ + public static void setupProductExtensions(int setupOption) throws Exception { + final String METHOD_NAME = "setupProductExtensions"; + Log.exiting(c, METHOD_NAME); + boolean setupAll = false; + switch (setupOption) { + case SETUP_ALL_PROD_EXTS: + setupAll = true; + case SETUP_PROD_EXT: + // Copy the product's feature manifest. + server.copyFileToLibertyInstallRoot(PRODUCT_FEATURE_PATH, "productFeatures/" + PRODUCT_FEATURE_PRODTEST_MF); + assertTrue("product feature: " + PRODUCT_FEATURE_PRODTEST_MF + " should have been copied to: " + PRODUCT_FEATURE_PATH, + server.fileExistsInLibertyInstallRoot(PRODUCT_FEATURE_PATH + PRODUCT_FEATURE_PRODTEST_MF)); + // Copy the product's bundle jar. + server.copyFileToLibertyInstallRoot(PRODUCT_BUNDLE_PATH, "productBundles/" + PRODUCT_FEATURE_PRODTEST_JAR); + assertTrue("product bundle: " + PRODUCT_FEATURE_PRODTEST_JAR + " should have been copied to: " + PRODUCT_BUNDLE_PATH, + server.fileExistsInLibertyInstallRoot(PRODUCT_BUNDLE_PATH + PRODUCT_FEATURE_PRODTEST_JAR)); + // Copy the product's extension properties file. + server.copyFileToLibertyInstallRoot(PRODUCT_EXTENSIONS_PATH, "productProperties/" + PRODUCT_FEATURE_PROPERTIES_FILE); + assertTrue("product extension props file: " + PRODUCT_FEATURE_PROPERTIES_FILE + " should have been copied to: " + PRODUCT_EXTENSIONS_PATH, + server.fileExistsInLibertyInstallRoot(PRODUCT_EXTENSIONS_PATH + PRODUCT_FEATURE_PROPERTIES_FILE)); + // Copy the product's version properties file. + server.copyFileToLibertyInstallRoot(PRODUCT_VERSIONS_PATH, "productVersionProperties/" + PRODUCT_VERSIONS_PROPERTIES_FILE); + assertTrue("product version props file: " + PRODUCT_VERSIONS_PROPERTIES_FILE + " should have been copied to: " + PRODUCT_VERSIONS_PATH, + server.fileExistsInLibertyInstallRoot(PRODUCT_VERSIONS_PATH + PRODUCT_VERSIONS_PROPERTIES_FILE)); + + Log.info(c, METHOD_NAME, "Product extension: " + PRODUCT_EXT_NAME + " has been installed."); + if (!setupAll) { + break; + } + case SETUP_USR_PROD_EXT: + // install a (usr) product extension. + ProgramOutput po = server.installFeature(null, USR_PRODUCT_FEATURE_NAME); + String stdout = po.getStdout(); + if (!stdout.contains("CWWKF1000I")) { + assertEquals("The feature: " + USR_PRODUCT_FEATURE_NAME + " should have been installed. stdout:\r\n" + po.getStdout() + "\r\n" + po.getStderr(), 0, + po.getReturnCode()); + } + assertTrue("The " + USR_PRODUCT_FEATURE_MF + " feature manifest should exist.", + server.fileExistsInLibertyInstallRoot(USR_PRODUCT_FEATURE_PATH + USR_PRODUCT_FEATURE_MF)); + assertTrue("The " + USR_PRODUCT_BUNDLE_JAR + " bundle should exist.", server.fileExistsInLibertyInstallRoot(USR_PRODUCT_BUNDLE_PATH + USR_PRODUCT_BUNDLE_JAR)); + assertTrue("The " + USR_PRODUCT_VERSIONS_PROPERTIES_FILE + " bundle should exist.", + server.fileExistsInLibertyInstallRoot(USR_PRODUCT_VERSIONS_PATH + USR_PRODUCT_VERSIONS_PROPERTIES_FILE)); + + Log.info(c, METHOD_NAME, "Product extension: " + USR_PRODUCT_FEATURE_NAME + " has been installed in usr"); + + break; + default: + throw new Exception("Invalid setupOption: " + setupOption); + + } + + Log.exiting(c, METHOD_NAME); + } + + /** + * Cleans up the installation from any files that may have been left around. + * + * @throws Exception + */ + @AfterClass + public static void AfterClassCleanup() throws Exception { + final String METHOD_NAME = "cleanup"; + + Log.entering(c, METHOD_NAME); + + if (server.isStarted()) + server.stopServer(); + + server.deleteDirectoryFromLibertyInstallRoot("usr/extension/"); + server.deleteDirectoryFromLibertyInstallRoot("producttest"); + server.deleteDirectoryFromLibertyInstallRoot("etc/extensions"); + server.deleteDirectoryFromLibertyInstallRoot("tool.output.dir"); + + for (String filePath : filesToTidy) { + server.deleteFileFromLibertyInstallRoot(filePath); + } + filesToTidy.clear(); + + Log.exiting(c, METHOD_NAME); + } + + /** + * Tests the command to print product information such as product name and version. + * + * @param cmd The command to execute. + * @param parms The parameters for the command. + * @param workDir The working directory where the command is to be issued. + * + * @throws Exception + */ + public void testPrintProductVersionForAllProductsInstalled(String cmd, String[] parms, String workDir) throws Exception { + final String METHOD_NAME = "testPrintProductVersionForAllProductsInstalled"; + Log.entering(c, METHOD_NAME); + + ProgramOutput po = server.getMachine().execute(cmd, parms, workDir); + logInfo(po); + String stdout = po.getStdout(); + assertTrue("The output should contain usr product name: XYZ User Product.", stdout.contains("XYZ User Product")); + assertTrue("The output should contain usr product version: 1.0.0.", stdout.contains("1.0.0")); + assertTrue("The output should contain product name: ACMEProductTest.", stdout.contains("ACMEProductTest")); + assertTrue("The output should contain product version: 9.8.8.9.", stdout.contains("9.8.8.9")); + Log.exiting(c, METHOD_NAME); + } + + /** + * Tests the command to print product information such as product name and version. + * + * @param cmd The command to execute. + * @param parms The parameters for the command. + * @param workDir The working directory where the command is to be issued. + * + * @throws Exception + */ + public void testPrintProductVersionIfixesForAllProductsInstalled(String cmd, String[] parms, String workDir) throws Exception { + final String METHOD_NAME = "testPrintProductVersionForAllProductsInstalled"; + Log.entering(c, METHOD_NAME); + + ProgramOutput po = server.getMachine().execute(cmd, parms, workDir); + logInfo(po); + String stdout = po.getStdout(); + assertTrue("The output should contain usr product name: XYZ User Product.", stdout.contains("XYZ User Product")); + assertTrue("The output should contain usr product version: 1.0.0.", stdout.contains("1.0.0")); + assertTrue("The output should contain product name: ACMEProductTest.", stdout.contains("ACMEProductTest")); + assertTrue("The output should contain product version: 9.8.8.9.", stdout.contains("9.8.8.9")); + Log.exiting(c, METHOD_NAME); + } + + /** + * Tests the command that list the installed features for all products installed. + * + * @param cmd The command to execute. + * @param parms The parameters for the command. + * @param workDir The working directory where the command is to be issued. + * + * @throws Exception + */ + public void testPrintFeatureInfoForAllProductsInstalled(String cmd, String[] parms, String workDir) throws Exception { + final String METHOD_NAME = "testPrintFeatureInfoForAllProductsInstalled"; + Log.entering(c, METHOD_NAME); + + ProgramOutput po = server.getMachine().execute(cmd, parms, workDir); + logInfo(po); + String stdout = po.getStdout(); + assertTrue("The output should contain usr product feature heading: Product Extension: usr.", stdout.contains("Product Extension: usr")); + assertTrue("The output should contain usr product feature: user.ext.version.info [1.0.0].", stdout.contains("user.ext.version.info [1.0.0]")); + assertTrue("The output should contain product feature heading: Product Extension: testproduct.", stdout.contains("Product Extension: testproduct")); + assertTrue("The output should contain product feature: prodtest-1.0 [1.0.0].", stdout.contains("prodtest-1.0 [1.0.0]")); + + Log.exiting(c, METHOD_NAME); + } + + /** + * Prints an extended debug output. + * + * @param po The programOutput + * @param fileName + * @throws Exception + */ + public void logInfo(ProgramOutput po) throws Exception { + String methodName = "logInfo"; + Log.info(c, methodName, "Return Code: " + po.getReturnCode() + ". STDOUT: " + po.getStdout()); + + if (po.getReturnCode() != 0) { + Log.info(c, methodName, "STDERR: " + po.getStderr()); + } + } +} diff --git a/dev/com.ibm.ws.product.utility_fat/fat/src/com/ibm/ws/product/utility/fat/ProductUtilToolTest.java b/dev/com.ibm.ws.product.utility_fat/fat/src/com/ibm/ws/product/utility/fat/ProductUtilToolTest.java new file mode 100755 index 00000000000..f84806da31b --- /dev/null +++ b/dev/com.ibm.ws.product.utility_fat/fat/src/com/ibm/ws/product/utility/fat/ProductUtilToolTest.java @@ -0,0 +1,53 @@ +/* + * IBM Confidential + * + * OCO Source Materials + * + * Copyright IBM Corp. 2013 + * + * The source code for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + */ +package com.ibm.ws.product.utility.fat; + +import org.junit.BeforeClass; +import org.junit.Test; + +import componenttest.topology.impl.LibertyServerFactory; + +public class ProductUtilToolTest extends ProductToolTestCommon { + + @BeforeClass + public static void beforeClassSetup() throws Exception { + setupEnv(LibertyServerFactory.getLibertyServer("com.ibm.ws.kernel.feature.fat.util.tool")); + setupProductExtensions(SETUP_ALL_PROD_EXTS); + + } + + /** + * Test that ws-productutil.jar version will display information for all installed products. + * This includes core, product extensions in default usr location and other installed product extensions. + * + * @throws Exception + */ + @Test + public void testProdUtilToolPrintProductVersionForAllProductsInstalled() throws Exception { + testPrintProductVersionForAllProductsInstalled(javaExc, + new String[] { "-jar", installRoot + "/bin/tools/ws-productutil.jar", "version" }, + installRoot); + } + + /** + * Test that ws-productutil.jar featureInfo will display a list of all installed features. + * This includes core, product extensions in default usr location and other installed product extensions. + * + * @throws Exception + */ + @Test + public void testProdUtilToolPrintFeatureInfoForAllProductsInstalled() throws Exception { + testPrintFeatureInfoForAllProductsInstalled(javaExc, + new String[] { "-jar", installRoot + "/bin/tools/ws-productutil.jar", "featureInfo" }, + installRoot); + } +} \ No newline at end of file diff --git a/dev/com.ibm.ws.product.utility_fat/publish/features/usertest.esa b/dev/com.ibm.ws.product.utility_fat/publish/features/usertest.esa new file mode 100755 index 0000000000000000000000000000000000000000..05653fcc822406eb3b1cb98c23feee077dbd4ceb GIT binary patch literal 1542 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 M?`LoLpFHsY09s;51poj5 literal 0 HcmV?d00001 diff --git a/dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/LA_el b/dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/LA_el new file mode 100755 index 0000000000000000000000000000000000000000..bfaab3fb744ad10524010f1c805b26378bef397c GIT binary patch literal 75934 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 literal 0 HcmV?d00001 diff --git a/dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/LA_fr b/dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/LA_fr new file mode 100755 index 0000000000000000000000000000000000000000..120b31ca869289e3a077ff52e33879c0c94ae13e GIT binary patch literal 88336 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 literal 0 HcmV?d00001 diff --git a/dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/LA_in b/dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/LA_in new file mode 100755 index 0000000000000000000000000000000000000000..ad7a5b2e495139c7becccf14f46c766eb6ccd44a GIT binary patch literal 63082 zcmeI5S(8=Cm8Ijk&H6ut@dRZBQYuwLtDZolfMm$93@DlUEy)ov8jvMZ{rKwk?|iJ- z?tac47^KcNE5jm)dj|JCtiAU3;hg(_{_E`I`;*rve?Ix<aP#DglLsfaPOi7#rziK{eR|YB-E7z1KKaLY zNAI^Q&X=ohT^xIG@~3v>UX$}dcZ{~~wrjs=Ke_us`*e4?`}E}D$ycqP8}0YK*7l|L z`HPdUTO0InsU5lAj$ChjpEe14*?!-Se%*es+x4Z-lJ{1-{y{sMKF->eUp1|`{{AAx zS!)aJ)b!TU%AG~Z2krNr_F3Kk)UJ8hTKls7aP)l9k#-(7TlSyu7m|P3&OK{4(l=_qW8w^n`6B2u=S1ZCC&SI-yZ()B9i{0X&@GUnb8z`?~j##Yg&khFa&zx z&07oF3%z_Mj%9#giC%6tyIx?}MVd?Ox+F*b@d4JJ` zzr*25Kem4D0^gr4oOZM2qaRwvdC`8zNI}V^W)CvikL};jOO_(noi4eDqxAF5$xjQz zlcU})ZTxuhbjecvb>Fo!WWBfT%&X-*?Qrz8j5*>e2NayM5fEgAEhc9qwVtI4*U%N1je#ybxuP0ZNj^~bHHx9y7W zS_`k*kAFW|r1-hXcG|8$M$RM2>x*9g+^%`P^!!u1>Q%d{w=D6)709aGSRAXJF87fA zu@ZK>+$?^-+5S=c|H=}1k1no#(C$GyEUR8f{ianJ$i|&#C;$HL&eL{XY%}|Amd~DT z`94|Iff_jcpzi6?7HNmYl9_XN| zqpdY+(Ga`CfA~v%ziVwgZM}ipF{U{3{2hv(T%ZR{=YGK$_x9D`TpJ=4t*O)46Y=-7 z>56svNj!kO#ML@B&?DHYy0#*OR>6kR{g)H|U2Df4H#x2~uf1&l|El%&vgz}-og+rR zUyk6NYwb>ZAR1tTb*w#Wt>K}>A@@;R(<5y?ZD;UM#X!mV-C}PUCX7)077K_4Y>xdz z4BUv8^i**pCs45)bMV8{1@%a0)Pf0Q6EU1mKXL_VSuCez5LnrIA&^?YGM{#U#WBExlMY`OVVL(*;#TKYZXBZHuMfELTRa=k2QRnmo^z zqn}^g@3@QzAzR?Dm(7;{(f%houq<(mzeNWebGrE5_;6=0KX#bvpkPNF{88{l|C7QVJ?mNw& zw@=7n?_swa?R>GDQQ&=Ni@X(MV!QM@Z#@%XT!(LWWq+7~Ud)p+1J{EsGI6ZY_x-e; zhaKoG=MVL>t}9+FF=4h(EA-E3TuBc81-6``$nXXS%_+bD!4KpeifC-X!I(f=s`ncp1XcpGCt>z z@zTdx-6&LEGhony?`j-E))G6ju2=)K9Lr(5Q8nAOuPJFAbdZ<6Z@t}Wy%x75yMr9j zg7ieQdCtm$d}akw(IrA*Ub7c1(8l4o1AA0v&)T)dgc33q=`&Di@tcJm&YM(Z%Zyai zY@8!a6|;5jbU`!OM&IET+9NJ*w7)-WUKDhWcmJjxVbrm2R`u?{m=Bv|V1{`*a}*vT zT8)=tM7hn(P9h$A^LsM^Y2uNEwf7VFuH@f1-8BO(p$;%BA7rnG7luE!#kJBqjQ zEUj5Pj1?%-(AzlvAESh(Irw-1GD+!mAc;}>yImMu$ReQVw)t?ukCyKme$ z_Uk;+d20!FaSla$=!ae=auYt~7?m(J3K_t$0@2|3&iWkIA{QjvF_xzVDs=oe$}ux~ z@z3WA|7dMn&e-H$>lrDmV~TzH5fr^6Z|Z=majWVmixL$w6BTq_K`*bDXq;Iyxt$99 z)x{NJdSq1WgO+9}nJ~7r)l>ncdtzBnNBdN&WBWaql$TChkNAp_t8*t@G)75V0b$TTttu}cP~FEk!GhYY+;XUJbb^5`^{=-gNN0iJOTSN2Z%1< zfveZ6qe!@3r^RbePX6s;uKV%AABXHVj&q1KxXRYG+qa8FK?R(GmQ@+dS{8<>v3eiH zE`5ZS)tuR>o=b~wI~Lqm1%MZ3CtkJR&W2=mrborAc14ZjQg!MvyxQl*eGF$tphxZ% zfm+KR`uPNByXUbJ_#skdUC#d4>bL&W9F55*WEOOK+*+vWarX1*nX>11?_p1+!DI0r zeP+Ca44kvlK?8iw>=K;Nv$9N46-HVcWu)>P@l)B>NO8PLC5he1Q}8OS!D{?=E~>wR zzlo_U?TTXXWfOUmqn`8T$ny-qCc;~3g{a`K<;r`ET?9_%8U;x%Fr z&tUDu)_$HmJt>cfC&vrO4R8`RYnVDo)!BO z*>jI%+P>PO^$)RQRrOReA{8F$KM@tM9L%4pG7+JzxSH`Bddj7+Amat@L4I>EbJ@(C z6T7V7SEgTMP>w5p**_nyb^BRxuBSIR9jP<_eLBs5_jc!RyhElNnFu6+x&5=$b&u^Z z2Zr{^^tL>DZp}GZrliUYx_$rLqG?N(Lf2oLl+1JVZ6uaG6U2>j(5wDWHT1*6D(j4Y zi0{Gxhbkh_Vx^N@X01HRm721zGtrjVrl;NW0?ILS+Z;JHKSK@(u0b>mO^%5^W1ZVa zA3KJK5h6NP#IHt?tq>_h12&$qO;$Ct7%4r6jouzB@Yzx&1r`d1{Clq3j-;Vx?)w$HUz%O^+O zYw}fIjs>z$fWDlG>pjqqu?~&6W@&out!&}O_nRG!?9A`67y4ndG&z~5e%SukuRkpn zqc+7)L?YQCx$pIb_i{9G)3?F7vA_L&=GyBE>+c@t6Psd-$V^31)#Pk9bE!I-DbYzC z=lGfL9c{ku761R(ejE!R8D3`=1#YT2MeTj9RsE?RK8;<^T7THy@w#|891G&#YSX&m zRntM=_rB)n=s>Nx-Nx5{QkG0Q`+TgoF3hC^MIX+;A;@$?@+i$Dw(W!`L9ssK;YJ ztb$}%4HoG+7~8TA6c&fuLCM-0V^ypLX_-pw?UctpZ!PThf8;|G{8P3sjif|LaMy8ZYh2!Lb+;IkqcTkh-sSe)2kG=tsM z$I&8d@?h4rk+NZL&tCRkQ`lWLq=KUd_Rpq0>I~$eS9Eu;_@UgoZ5!-DkqFUakZa908xmz-}2o#XcfSAFpSw z6O}!RMy4rW{nHZFXRRl&_4J|=nSJQ)Dr;G^Q39Ah9%H;urijJp@tb9Cgt)YIyniIt{!u?jP^z5hXtVRwin{6IIpF}?~L6jzo6#B>K%;YvI zM*3&GLm%1K2y&d~#FE&k@DU`C(>TiWTjJ?jJ95}kT08y86Z8xE7z;gae=9XTXjh_z zJ+8eJuNIu)QFhv)2}fjB>@?b&#Q6G7knO>goaMltJ>*tD(!|1Es?7KWSjy910!+F5jTGy4UUQ0fFpGZIs zP(~~kf6v^)Rb#}k3RYY*G9|XHY*6{;pO<{|W$TCCuNhf9T6!l^@3#BQE!Zk`<&5UT zzUcD;qcf|maYx7+58yz#u>`yqj)Eh|bs6c!URa3=g0qRw!_oyQ*!1w##Q>FS=`Hi= z>zRvQx~-j%uNE!Adf8h4Z`G)~{0#44BWsnu?(9dxhxO~ZVf2Z}#3PO|<%?t$WhKWV zgOPB!H)C_uy*$^~7Znv-PnA{7^>r4OCsQO256jbAaTjllR+;6R`QP)&+GL{C(x;1+ zG9&o;$*&v!tbt)XqI*}~$}=U7qgegmuh?z$;QnfVD?5$6NbF(9U~4|x_qJO*tx{O& zy+j?GT?t}}_@z%GJW)YhV>?jzK0Hl3w8y;TE|1a+UP)i*I7gs$7QBi@Xc4PpmAMig z5s?)Tjxt{D`-sP4Usg?a+i*q*Qv2)y_81YfyOqie%(sIgIG40{&&G0vd66jf{#o_4q!CNT#&n@k%S!5&xiF{ z?z~+MBYGbrq_IV{N#4Wm=B&dS9%t9%yhe5DJd%}&Gupd)5Glkl~ zyY|s249eZ?Yr56+4ClfP5106d)j-ypi|aE>sTauXj@IT{yRVkfxEQX`gl&S*t?C0S zS)Y<+Qs=*HZQ)C#;=EN*RT8v{Pmnu%L6893=}V$2&xBG5^`nS4OY5#5Iit_tJX=Sv z^Kp9@7hC6d-8aWuRcUB6zh?<;`nj@W?9xa3mPPC_wWugH^H7`e*(*RcmEf*DdaHgy(P zpTSq-6BV-`W}EbtMW2_z0aEdQ#Sd2m7ml#893H&Wv?c3c0pCGH{yg-&P}NYeedOzB z3#{a^=lYo!Ek~smL}UMte+s6M1!kQQkq>2(SQ!jFZC(zm&TQJ-SHz>?dSw?quxRD` z*>e?dV=ckVDNodlJFmfA(A!_XX77aG3#=z6 z(=IW-mPlkdcM}~7gItfd!9Q0LxAcPrQ?H9X-{7VEvtGx=r5>||)Kt6I4$uxB$(zvp zd*`?$9}En=(8OVT2D zv6h-uj2=O>Ls6!Ot){Y`GcK1hmH)f1+}{@#mS zu{}KP-&|#1#v53Fw6x+1=$6IFskDK8l!F@l?Gmd*S)ZNH+Gl6Vw8+hNC5%>;npos) zy_5Ccas{X{{{XF)#WtD2o0S*S+))Pmu!F*pCM-%i#uhx(Pq$LN+3rWkYodUUrv&@u1L z3Wref>-kT!3KNN|#y#X=*yFq*cx{Jc{0xTB0qv7H4)q8su?bw^dKNOQWBgEt+LG8> zl3jOmUOf)&deMl?xFV?kB|VQ-v7hk)nlr|Le|O;+KKW(M3NuTQCxOT&{g{HdNG(*~ zGr)VtuP*P-_j?C?4|#p-0dH^TJ0EU0I~=-;@0mDnKlfVxmK9BiL9K1C@$LO86-E&2Kqk&iRK6&4}PxSb1{K&x7+&Npdmt#vKzt@8Hc+>or zK3^}kS90aXBG}_ryPh_&3h%j(efw{Q;63>HZVle0f3MBxaYwv?{Cul`@2!t^^-g`f zsINc*y?O`VNWu?y=G!{@e)GK_`c3=sTW``vzE7aO{eq)G53PTwP18?o)O%8|Ytho_&$X5<+~b)m>E6VP%rphEnjrsA5h^f4TWde; z3&O^4ETISNvgt@j&@nIpXjT5Xqjp%(Tql%Mbi2v z7<~FwyYh>6wy>dhD?Vt6?{wiiYpCV)Tv-_Fi0NC6m-|m>*jp>#wJ~agt;Js$qWYfg ziw@|D9(Y&8l@_xdkl^o!^RhQKy4u-)8|`ECm2YPIls%$fcwX(kUhDw^(YHLa3;Uy- zV&(6H`1j4`@``o}pNChkE)jFLX?(kB?)S#@-<5K{pu?=ry=IbRHL-IjJ`csP-_%0v z7|XQ&u>GyvtTWLw(U)9+m*J7{bNN;+`Asx|9{<8Ka-_UGvUJ_gH?#O%Gvha5?Ycga z#Pjgi*wZ%eAMWwced)PoRY%0H`K{+kZ0xttoSyt^llk&g<>`qB?aVHYztYa7UX&;O zZmn<|ECWkYD_p(!tB)*4szh7WB*Z3nP+O7b^ZjR_1MkBK>tjl5>~qhf=J!!U>*LEu zX~XvhiAK>xyIYybIv_ECJ^AJ(A|&~s|2`zEx;yV$F5Qt+Od2QE&UV~Z>*2BFIPwG* zqD5?KJ^^VTS8eJc+94|A^FAj z`WCqG=GuKx$O*h)7%)r*!L*wnV+RqU(LUaz%Q6rKa8gDbJk$I(zi5dAb z*PvXkl`(F1zU^_7{Z;#Wdv=UDJ=&!2c~v=f}xkJ-`T@_0z+Bql0TD%=|j<;SN0KDQdo}-h{_k*f(c9Z#_Fhv^5)8 z_tJ}Yd0+X)Ik}4O>lZzvD{V7h2e-viykq9(l!w_B=ek^tV$K|IW(E-JFq_NVQ_a%q zm8_X?{&j2Hnfyr2tW&KIAGX=(vBL=b^J3eq+|0B2v$gSX$>00fEBn1P*gKqnRJG!Z z1zp7%kBNNaSYO2oeOu_XZznx| z6g77ZrZ`#zX`}v%tTwIBj87IRE0SexrLYN0`d+o_59{kKtQlm1sO)s4#gXfgu_93~ z5Z`zTMB};fGyQGj2I<%p(PM`72;{20QOZR=e$-meJY_JS9{abfVS$ltz(=18u+Z#L zR(ZG%4eIZ*7WW&o?C^NpB<$aY>9>0ozg=#UR`zmkwMQwqK!-d>l(vhN`*k;bf>qFL zzQdI=u;I$o;h4@GI`Uju(5~LcWTYTsWa7Ux`S@|49c#iP&m>M~ei}XP(*?xi%qvyz zAJ&e0%{W;t;8S^g_bR=aUPgt#dCm{ZaDU+-en(r6nxV)0Kv3$fYNNOjuW^U#Z;8{? z6~}m@x25)lx2yxmC*+$ghSBEWul5nVYRKl>mVCaSx+sXik3JJ*_ACwbQN{4M{#aEH zQqc-4&-N+9(k@TM^X&szitAvP@|3$AI38(gFC|%kyF90dwqkDd%C;wp8}J6t?IH!) zYyHN;%G}tjp7At}=q=poyK%W*>D@0;y2zx~1@Tj5{88?0G{q|8wc9#sEh<=i0Gl2Y zN%cl5{K=hJAzIg%#a!DQvCRmDlk624wb{zEg+X);uYb7jf-oY3x*UG2OjGtO4aX~# zA=SgYM?bA&yRxDjd@M879u9I-?dJ#r`e*LgCDK1>nY@wwUe>d^BJ=ban4MBq5M~?f zx|Xw;D%`%G4-R{E=KNkJ?ykt|>q^cbt?vvVx`@d!JMBUqT9JV{&uTK3vMqg;^I@gf zMSpY67CP5@%(em%US&mRbx?l&ls?8*)NAmJ++(()_7LOx7WCFrCRl_!v1{et&)O4! z*IFw#+EMN@hcM$YSMQlO7_YRh>hBDGW8rxX*UA^4%xBak5qtJd8gxWT=Jv+Ex1?k? z4-b+>#0>4Z0~1`ym5%7B8erj){?lr+Moo`$P>pO>*vL|t!jIZk!i#R+Yh*E1Te)6x0M zb_C91Zb;S%&Oo4fmU|p!)n~DS+>ABGh%lCkJ?u+llIQA~B>H2|Fh|(`U{%*gQXe?k+uob~m~YPXL=vr$Q`Y?IIrnP9I(Q>h&N8)KjwzE z&=kzY&R~N3vg3Iz31=&t(&pIDY>hEu3PHWL*b{9W&yQmPvm83ZQ2i&6-_PIn7986s zdG(}Yh+>mbMxzBuMMCThes|3c$qag>uhc*leOf#FmbkIPDvMx8B!N}(Z8h7NN1|dG z-U5Zb&M%N>XcJ6sMFJkfiuMFnj99Mc9B4uBXl*QkEm}n~$9qNrt@PN}c8sljTb{KF zsN~K(ck^u3%3lXL);(~f#!KrS|I(z!uHUtmqrIcqZ406w*d|hg8=`B=0{9Q~F>}NJ z##Vfa{&)_}#S6JTf2VG)`mC27+sYJ3t$v`g-aA;C8uWoC^&z9(Yj@CdX0Q7go+G2M zF3-UiW=iLyn5iZ9*YSS2T?w-%%dMl%don+W1-TwCQ1xWIfmQPNhzhPWM)tiQKpgVh z%9GqBO0oZkdSjGICZjE6Pwhq|jBm3*SGCiBAjc|M_N}V7>d2}V!6{x`*NwdgM>ZhZ ztYn|Jp2TAzowG8d-`_ZUzq0j~JRpLo$7_lDk)yOUQB7W8lxv>JJSb?yT4Q}>Tx3Rr z)@7)V(IxSOb&A!)I(p9UEkx$>gEb{PK5w_<+co8lrd#yCzhRSy?M{4fOikJE9AGa9 zJ0w_>z0)L^_Z?;R9A42={57s}vlEQn0qmi1f1)eL?4Foc!Oz;d?^o@5*2wR-t6k6T zSD#&_ckP?~dG0iGRhgCM8;g{jKW~4z>%pB*{OxX!>>IN!_M5P43=JN%A2dML+ZQX_ zYJH=fV|M^`W9_G6Hw5?np~?OAvhx8;Wlh|6kjuNiUe@Wc5B;$^KJJxsCEc}tR=jE5 zoiMzyeZSnlyV&{bw?WeS?RGyhV|Uvw+jIWwra5+ry!am5)wk~XU5s1T{_33uv~jET zWBYeopR~!3sCdx+VqcE?Jduavzi;+pkIq-^dOq)$Yr8Kbz1!}MhV+W2V|yIK?_B9_ zxa`V3UMudymp7Uh=o75#L-s?X$yd#j?Dyo`sG>_oX?_!A?~5QC$!Q6R!Pj|fiQjy7 zFAg3NFW8sk?8|gVB6qq^>vGfjtM>0^+iih`@4c&|BMF+{X?M{Q_djUu)UG5@2DXU0 zv!)N{d;akohyQ)ym3eM>U1QyC*TIF zm#A%=7pgN>d-PjRN>;5`SzxSXsjaA@$hBrFXDh~I8KIi3xQ@{?BSGv5Zfw7=MCnJo zS&3%-hdWazGCK2(8LZYlZf8L0+_&Bz``&s+?{cda_;;=8^SIgbTFd7z+yB36zJJ+9 z4{w)hf>937HBDXZ=vJ&)^*9I05l0%-K;cPXR-2NhU~ zA6Rt!>+2h)7wMa`?F1%T`154nFXiNNOERi`xJfE4j8U2+V zjzbU(qE_Qv*xxgA<0mE*xw_qZ#DK41K)#>k#bj8;Zrp$1RD`+C0gHb3HF zFxc~CB3-W7=7z8=OlT!Gn7%o^)d=$4&KqY#N9k5c5%;5d<(k?cg$3gfQzu;Z^zOwYwuM<%5_n(o=Ui3Vz zvch89@gIKp`+DJ8>u;-)2&ZE2)S_fmrMF5l!`880KQgtMy)drttlsd?v(`76NFQ=M zH3m#YPcjx+jl9e{IF-*K)+2(#A0oSQWh%sy+Ux+c8)=Mj>(g<)p;=X%jGUggYQ_IE z-_Iv@M!sxzQG0B^E7GI8qbaRkd7d`9-qj^_S~xry8l(3RI%T|ykF}n13z!E}$9gKULp(8G^YkKGd+!{U z4teO8Oty;|=elv^w$iO)pO%aeeD)y~fujJByQ??aClbJHUyXp~UqYoyydSnd(t>(? zIL0t%*k>fK29xz&DI*SpV(u!BU?aE%d+@*9Y8zJ%6E>-QnLp2HC9MZaIHSZ z{^NJ6&>LEjNw;<}BYW*9msQ}4o(DZTM>gKJN;I3Qm)G{aes~W?teO#z8CPmQw6-pX z;W>td#AS~0b)&X*?x4?f?&cLeS>K04;!iw69V*k3Ym+09Zl0e>EUhc_pdtR$ z(j!`6PFI@io%)5B<1$ar*uQBrAc>ush3)^W^+yH)Uw4~6#6LAe&4|p^SdF1YRE-|- zFwdg!Ubuem6n09xeKxWh+L|*eosALvMKzTe+SNMO(Oc!W!@Qwg@F}xfwYtxp>#S=P zw%@AGT5peCkZ{gZ=3>r_ad+63m)rci8or-*FD;cf_Al?nwvL0quap$xn4A8XJo&#p);r_ zhUF~27bz8c?>#F3P^Ij#F8L$K=;Nio_n0U$_9BbfJ$)Txrw>657P-FYQ#BSI89neJ zErb1J!_-c@pVm0WKJYo54VNL|rN(ZFr(K-abJNWW&+#-qal+l>tkk7p&LMRLc&oXe zL(fkgil8wD`&p*7JTUmD)=}TSXcn|qKugwrz%v{HXUe(eNX8u0zsSJ|gk6F8n@luj zlgfVLnd}VDTOk~(z{Yy^Z=?JBjNnSsQEPP*k-iIX7ssZ4H8-Ol)}Y$l!e4qBQJH+d zZwAZSh&h2{VriBi9-vkjYoG1)DtK8hN2mNxHrLZ0sZ75+Kg#B`$-S=1rPAsdbRW)Y z<&k*avTI*KeZEvskJ@$ccB&%xpFC{$!|>Ej8BY@rcri0vYi`_CQ}pa3m%M5=CKAXm z%ufSgIigj_x5Vr#88%?5h0uewvo zIzQ1r*`U;}&-YIkxEJS9lO$uF(Ua@h!BN{(L6K&zBj3L|MB~1;D9Ng4d#zorb2c-h z#e>wR$3#xNpEo`vZv5Y~zJEU>lSG1JnVO9_WWzbWtsiK``K4HMtgIuS_#qyt$jU09 z4=-j`rT2fuI&B_$V?2_8I^+P2wQ6{HPN)!Y)>^?6nIT>8(KQxQi4+UCyJ@a`v|1k# z=)zGkqMzvXn25((S`zu#kKM-|tl|m@btml7pY3I!oslK=9++IqCubigGf}`8ASf$O z2S1GD9A{_FgHap$7h~&7Y(zZRR$2PHZoInBQzCq8u1DsSgJn#v&AKg^1=HY?|EX&{ z*0bNpg7omDE$g0q<99HN<$3Db z6(DrZt}1M=t|I^H;*I_Yt#W6+i}m{Ah4bY%b_o|_DRM>LuRxDVJs%|><~_dAKAL2# zg6+rFGme`3S+`J#`Tj`6hzmV)e09$FPv5bgK+I*|8@m~u{bp7AP5Z|i-gsv^sPhr~~|oT(t>gZ`N( zcaU&An7ZHYGDo9rzmn9C)iN5mGWpZ2*YA3%mOWQUN`}F5^BhBJ1?|Mh^Y|4ldUQOZ zrLhT^bA~>WXTF|!NTP)};`g|IR&mT(EJN$5&}0%uH_oP}QprkXY)bnwCp{R8^*OnR zzQBuIPc-*qS$JGInd^2YLfbl@+K-~vdZdq8`m@$5e%X~DE9QP!Vh*&!Hdc>vo1d_9 z%_^F=WAn^?R1Bhx9BpN(#FbrYg@3Nz`d+XHy(c^M%wp`zwUra#0`@hrZ?0O({Xr;C zpVz#j^$fpbb?1eVv2Ud+l(g6PraZ}k;1e4ht_l0LUN2D!TfEPVWwFPWe`H6WHNpNf zLcqL!<4GQiO=WCft+#WvN)?^VeJ7U9Ms^Guw(sI znii(y^j&dGBaeA(4|YXi$P> zse80Cv0-Fk<@ssvvM*kxP3sAe+2@GgwO*Wq>g&&~v2R&Dj9b2y53n4^7!tYRQTKPtJw}2!<3%I0Y4pCeHKnq zIrZ_Q9YtMgqIs`jqS9PJ#8}rE)A%U}T4$Hh#_L?uBi(W6zE#K>IT-=;Sdx>oYgn0$ zX_#FMmKE6_&(mY;*|hkz?1!diy)|OT=&qb@|5zNG&Dzd8wtG%KYZ%*=31E}N$H#kh zMx9R#$zS24-5QB#tc66(9w0eLKw}top6x(-kZ>q>JvsT$#be>(9%<(-iXXS$^a$Kt zZwI;D*44nIGnJgH_`BcktE|Mh2`+;9#LdHZGVgnqlhH;pf4Bx2sp-jdtjm4ullO%> zEagb6a@X4Cui7>FWjfiX}0y!9-8_3U*ux7gbe{~{G0h=2C8NN@@x z)VgKmS200*_<5{ou|dVq%*z$ce_o>bX1l*bRfbRE zo%hv&Ua`b_>{@jl%4>H9Uf74v@*kM9rp=p^wex%w@5d+TVni~xML$Ml?i`OAJY zG({azgm;mQeKQ#&9-8NJw@gL{#48BE7w|nRi1I4noGG?`NrsxOJtxy~bU60?+oditbi&7q?b?pBk;=@7WT6`<^m!#)JsK zujMza8o4c8Y5MoMRL>_#3`b3C<6JE|EFZzi@5H@A~J z4`Wf>_t}n~kg)dX9zsJ^y>dVDXyN1wbopV4-CY?YQ5<~Ak!H4W9)vb&onBlU(l%E2 zH5;kz4qG61C+>>xh@SPl82!s8RO)s07{xXInClps68+YdDs8i##=NANn4XAw*lb_? zaOWsNAN%-)j802%H0NUBjC`;|zVXB7D77HDniz$78GG+WV==m%#E$M_5c&rFv?ls( z|3>SVs08zT2ULABufxqAa|a-wK|A)rBJRMjwuTF6f%CLURVTNv-|fMZ-o(4(9p?NW zw7am3eCqnp1oY>t&fk1A0iF*aU=&;;0CZ_6)T_8FOfTrGwSHa zzx)5=d8#Z2LU^kv@-k*RZMfV2eC6HdQR;GjoXaDsK}@l4EDoly8u%QUbDdXv_E_gp z*&GD(?iZMz7<4tMe+GSi3yzr{B)DtI44cZFIaoCBIiUDVrT~fazRP_*j(Sihaeo+w zeFJ&68RUQzRs%*q_?Ds`uYHf!e7o-Kc^JLqGVXcOdVbvcV>DM|LzysV3b)KRd9~Px ztOXatQgBRo5}Ok3SDTHh9x0u-Sg7~QTzy?x-nC_`iJjy0xc)8bzZFT|DSzhRWrrs%^KHRW@L|v8I)|CYpySq4A1wwgTvZ1*?Qy= zP)amV8xdKFbK2tw{6f95HG@uVk0h5jWFhkvlh6|JI7dNMw~@4$S&S=*QjhUBuA;2D zmH4ENryY4*cCbq7kL}kl5k2=V(~?EjEpG2u++{_05U(W-Rk9LF9RMO5y= z%GiSHS2^L;lFjh~NZYqMK;A(XXI@4OnK8A=fA7DsF5L2up8oIsH``f9z6ksD>y|`q zjcUWSL1bUm?2F(+{1|aWEi6HFFs?NpbG7ln*nt>y<%BD(`#*G#4Hd?d)fguu3hEBH zWsLD()*hR(BurQH19+y^XXP3+F(YwyJ>E~%HrF7@9(^m0X|YiDLC-S_dKM3IRc2Za z^}+S2tCeHxS@lo5Kc{5GJ|K+WBC+3@L%vEj!;Z*FB~NX@)#OoP!&%$dy0SlL;}f2; z9^@~p*F;jkK75>S_eF3&H)NH?49MTYXGEfz%{@}o^_eqDuAINMpx2MuZWk&K*=$#p zg#_-Fs=E2S*&pp3D8TUCm$IMy(iP=Q@M&gpjYSxu<`l3Zg4Ooa8H%ECA!WCHFZ(F0hU=@!U z0U|>?vm5;R(r$KEGM1yp$c!rZ9I@Be<}=^)l{ywhVrG8U46ut)iq*h7nZh0Gwo!8R zI6^m&cDGqK>oJ8gH7_Q_uXwInt})RziV72Yw!e4o$5GyTZ(g;b<@>y(ZXhxvX4$xp z)q*R_viJt8gRbz(R*%e?&N9$H+HSMRa2_Hob!ypYMnjwpiDwBJwy3FV5ENxq)lQWXK8zjaQg}zwy?{ zrdkP~;%#(B8?G7|g6t-b#dEL-h)1&Ec#Q5jj(YakU8R1$e1{(P)Vf%TtLXy?;C7Jw ztbN|HSI<|GHTFFe>t2Uuv+RYdnQPLv^D0OPR*58Jw7N*OVE<@CE9+k5u;{nuX`>T9 zFz$$0qBpD0v(#%wo~57tT=}px200)I|Is6@ip4_Sc{^qn9Alu*VSPj)hnS;vY5{E| zs^E7c-ZdC7kk;pS=$D+dNo&p%RkhdSu8+@AwzaJy6Pj1upjRpnYJbOT)_wR7?84sK z>{m^y#MPaq?YI_HR^9JkSpSI#!EyVHgR--*V4}2b{wqZ zvk#ed2G^hiUvj^`sJ?1Wk(`ryK>ie)ebf_WHMf!2+lrmD)*py@*82Rcts?$&`$x^; z-1y`6_oKyIvd-0|!q6hrm$%zzpZdx8oOAdYjDT69q@TUrl7VX?!y1F=vYt7j9qL4U zWc(0y@laxmSe+}4(T8x5yd@uJ2V_6`k+as%ARt3YhMwDd&#aA%%le`e*BEN)?RDx1Cr8NRY3rIugjd{`j5+;d#(Tdzs}D-t3NN!UY>nk|6V)0 zIQ#nSyR)bD{p+(QXa92ctd8>Oc^$h}*F39#@7BMc)%UOK{FB#5AJjcB&c3XFpPYSF zf1aKF=d=Gb{ywN9FUP3Y&fcx-e_DTUjd2+-b1?FqF)Fh&V~=oI*Pov~Eb93G-q{Cd z_s@P(*I(4<%d~8&;&)ljj9@P2y*m>Q3>+E*jeR~??!@7o}jtXUW$2`|++3Qcg8*3^{D>bukTQEzy3b1?-yf)PtHDhJv)>-(!;vyPH}R6_EG&g zf5ipooE17g8Fa%H95ZStXSVZkEmT11dChoP*W4X+!CB_HUB?+siXGv8jfm`iR(Erj ze=q9a<@oo;oJy6mhx0tBdmoN7_s0y-n7Q})Kt|5@LCt#W>>mc7$l}_d#^p}6uumc5VM)%yJ(1y-99oJ< z>|Tw(FU`F%;qJ0HxhxC;y67k9hMa%uOk6+!zoKhLfYRd}_VWUV@-}_+P$z0rfd)TO`r8nQN z>$vh>UEz`V*W)^Nt;V@1D&H>}9u~K=uc6_G<2*Jb8eJ5nTmuDo6yDL6x~GpdU5v0q zUB*FrTI{2m^>K}Vr)E`CXiYwloAx9I^Ev3CEN2A#*=s9!chLDk#egpg`@deqhIqp} zHOsdnQk|duzG4cIix@&A;@dkl7xCp;#gA(vhWw$%dtQHD)c0@CzNv4Y)mdiv?A1Nj z#?hCr@A{`2IT6os=7{%f+(kqqHeNgXANBXiCM_KQyv{zYd7oBf{C(Z=vOZlK_kB@k zne&S}P9#mF^$O=*$J8f7Lcgs$;OUURZ|cmyznYOb9gA4}ZJi;iBBSQ_>pJ??xQ?Sn zcce;e|E}&r-yaPRyLNVC#B?MnrQg=M7ezf%Wu`yWak7GIH72_Iu8!XvBgh5kzO6rK z>{{6<5{3_Arq?saJ7u>Y*O7N#-3wiehb*7hnB*9Td^hFDO?%+FJ$-*(qk)_67k6!c z@4Pw^8(QW<$RoMXwYu~7H9A%*SIFr}@&AvnkAbJ~`px(k$$P)rhbL(GyzWP)$N?Sk zKl#|#LsD2OcRpQF`E|*ivA?Rbv7BdhC;EOq?s!)EU@WA@5oOj{8$2RyVj;5DYm_vZ z;Ace(mVq50NjPIX=S5%N)-jGCgKcU!8(%_JPlm)83yP56i&wNgDew5Qu3&!T^oK$5 zq4wfY(z)#&cgMZ(73qS7%iI)s;J4TfvmozhXP?$zHSx`mq}CcNfdggn$20!?Y~1lx z{g1xBI{W$H=Zm`Lk3|8R;0T<8zM?)eG3q>*HVwymtJ;$OCq-8zkEKPI(9PAK4T@f# z{qs>?@nXEXeS>k$_m!j^^ill@I=`*^o(?->6f8kHw5Lx872gdiv;=gkW@E>Z-=Pj> z&pSLDFVu1}3YwX#3^ZvBz<#(O1LmPM&{=-ov z5(N9ZI`Z!D8YT3yW|{pEO5!W{sCL8r+Id?VNEEGdCDoW10%y?373dE6zc=PoTUzam z)WkG-y_EgNJL}0s-{PU?bYOF|-O^iByb1Jcl=Fdrv9K4;yAW}<;}>`GLSAf zJ2p$_7oUz1&F9n?^FVuJ*_VSl=F{J>RnDV5Ed6Eu5v89NZP21-$>fqh;pJQf-Fg`J zfd+|T+AAEIj|JI`H_Rzr+6=LiGvRHl86xhNL-`OpIRCPv8f+xJhA@O<}s^?kqlY9vr%PhMri z*#48E2Wdmim&FrTI4&`R&o}CSY}W5^nY_d}uP(@Gp@=Iz62#Ho$&HOQ`j7R+^Xiv~ zTWCfrgA(RQ-p2jr9I@`ZMOXB`jDgM{WW?K{#kkV=#fV}lu~}{GdlvY9S(4eJKRJ|s zth|DJSdOt5S{YxywCAsCX5s-cBk=^f@Y8CHfbEANDIGGeWS2>(@C0rP7I;rrQ? z)BbWG)~&%iHfHsSB)BiAg~iMs^W-&dUDVk4`eD_T`Z-w-c1%@8hMZ^;`{~GF1n4dT zd@E(I6(6uY#s^=Kupa6tdS$pa+fy=7ifrQtJ!|LSPX_{lutq`$^ArQXmzbE*&>>Z{S(JU5;I~eQ)nU5r#q^Y zjs08tB&*Orkg)t;B|q59OO_r~ zVlN#6#A)5d>$t?)YnI(^kQ^@Mjk%Kb?%Syp&UqldKrTSmAjRH2>#QkAG+^E(HCj;f_u1g@ zVtB(beStTipZykaK1glNi>Dr17FIM@*~Uj}V6@Kp{fr|T#AlJnoFgDre4+CiG^XJRDvrkwaUv7+Vu`H=T%|40sHEJL=8 z*0y5@4T)>VYb4;>efzSPLvo1I%XTa)i))gWz)QF0BDYKEoCW~xo z2br~5Bq=&>-Ot(Y=dG+EkkNq?$E-OKW-E%=MTxI>Ee}#a^{2%pyz2w|GG^_|oCi-q zqIMk3mC1pTH&#Obfe}4oOv#z_tB}naqasVYg=p#1ngv~8o6riy9BXvahmgN~5v@}w?Rhl@Oz zRr%p1%en?$iLvI9!OT?M+>H&ey2NL_9;!fvxh~YBjZk!2q^Wb2AZ=DVn5lC^uq|UI zekwmKBP*~!Ib)}QF?$)$)zb5lbg(tqEL2CIX1Z7u*YD#gv~!lL(np_U=UR15E^^&1!XIO-CTX(!eHT}+DH&;8usr(dccv>1KhS?LD^96Ogl^-BoX0Z!T zMx~!HpB-7G&@?bod;lwn_Tko%f|7F{w1))D{`7S|@x?$WJ;FPV;gmU0=kd#&<-sf4 zvPv>@*Cvqj)>*Z(%qi8`q1~OH3tX|Uc060%lZ-Utd*l%4)u;pYb`to1-Qz?zV(9Z% zR~ak8G;XI;idvVil!uN7Z&xx9-tgGAzY3KM@a*1cjC z?9&jvXAjed*3x>XX4DSRi&zPMy25cNcdRdU09^o4jr)R~P-aG(7`#PIs&99d98$Yw zDX!)*)3Xr|j2z33`&DpcEdyezJtVk0y*puxHZ*smF5)x6c^(gL&(GR>^Iv@EP-GWXTF z`&s4hsndU3mQVf!6^GJH^#L9zX|7VHT{poE*(B$ZD{N7-?n5|d;`QAcA(*`E5_FG= z4j;R!AC-Qg;%Q|apcNW8uZ)enl5Fm9HT2dvj_u4b;l|mAb;o}j^$b?^pho>}_+#Yb zjN7y3n#&sXm=;{WS@vPg@y#$!S!XisnOkjTZT-ij4~nB_B4c+C@Dj3L(27swti(?; zDtu#|U#)fVv#R5MEZJk5bPci&^1No+w-PHIEXb-LxVdc=T?v_kwpCzDL_PdaTZqN) z>4`g1KkLuinaQ%I)sv)-k+A@uJq5&BW{*|bTM(M_iPID*cO_61Z z6JW&bxoFoIh^1$@E;1$iu!>)zYw{cK!porutRg#Fu>WwyT9Gv`Ey~9QnNG4?o%;Yy&hJJ$wp^cUo9K8YmDup@0s&u z#1c2Ca87HntGh@xQ4{=udLx(;HWLpf6PtS1m=+vlS@t$WXYhLIYoHi%dNXe$&bedE z9NS)TdTdxAvX$aFBVpIP{^u^5wNK#Tj?Jzi5fZQBC?gW-uw6cho~+E6fqGT=7V^$QbrP$?S7H&tEv5*7(edMMF+OFv8qb2g8XRo@?^vI!*quh_w=xlRD znz40PB#2j{3mG)yFMH{G{E6R^5^LF;>vOCKIAys3A%9%2`k(7Uu`!TB>sxEfYL--tROiSlG8HrYre(f z^{LRVr;!_*`-V1FhUZ@}FoHURHe}VA!P~~e_@sJ=8~l!Fi|xf8kb@pSTW{|!@@~$t zO4Odxm2GDU$_p!<&ssS%rx7q?V4I!W=n+?4VWsy0W!w)xV9HvaTe(Kti}!=+lD-*B-Wqjo`b4ONMw_e`6ov{%r-sB2+CiiI9r#(h{ZaWu| z@TO24Z(!7xMUJk0XU|KJ5BNzf)AzW8s5Q^1@gcOdbza-H6UDw7M#V?WDy>De+&Q*O z7so+j#t?~-r?Gq+HP9MY;BD+%fhIoZ9y|t{!ZO8aY@RDl`=DbHA(1uXLXA7x*HL}D z21H&zjOW9HRU(}1`$@F8fWV=&xyOy@Rpw*lLG#SPJ{enmUF>Z)>uwcy0j0_1AXHc zsV>_}@B(JipV!iAd)$h^ahgkQ4WG0de0m=Xe2S4^ zDLQ;mGPzy<>kAx#m#n;iZcwCOno}MAZUk(TbCHBhjy({+sDITb-F$t&=V_E)dcX9A zF8l7z04-cg4HATByk%c1=R}3>X*w?GMctD9sf=$9l4?d7h`87U-}ibu`at&=xt71o zolcCnD&JT4wYRfXJW?$MSCP)41&S)$mOymJ6Qw_h)>g(R?kC518%?|86nU6`T(z3e z?zC~_OD3t+9rLp}&r;9Y694M=O5ti&->6|#(y_Ta8}VhNgqLYwL|GzfD$byew69U8 zvHfpeW&LPmD`q!79cnoh!o>+6feW9*u+9yX(4Ks?qI7TIH$1->pI%g!=WN3HfPrL zFIB_;tzEpt?ip9!RNGd~$&Y)VZA%@rJ#B4G%Q349_V(!6uNsXVTD-ZcyHdT1y!Ci5 zp)KHWJovd)UW?ZCg0;*#dpwITDXXh)}HK>-Adoa<= zpE)=iS)HJk)VQQ>Y)X-kLktu5C5oZzKC%P(n`bw+Sn z`N0P(df;I)=G3QIR{#$hL4UK89sBEz+l8vjok=D8^9 zg1!i!h+_WF7w0eej@0NNu{_?vsY$9pi*n=!_n*wij&i(2XyFY|LBtT&LPQpT%6*q@fI`HOD- z3hW`i;agC-FK427BCgpH*PFwqN4cgTkVbI7PB~b?JnXB{ew3&N!zKm4mjE<0gPlBPyXS7U%2QGpNsmP<_yqEXQlE{aZ>p2|w;S9iO2K=uAepNir^iWV)w|Z2 zyY!r1v%7=hHQFH=GP7k5o1@9pn%g;^ClheDdT@ogwL{nE z4)v@pimVxhpw~an}Gdru=i=<=W59y3QKO-}fSaf6;=!5J96Ctb2Y!n%(vX;|g*-B3d-BFYU`! z`L$&x5~BN$iZT!mN@gAEt(SFXxfA}f=$xN=W`~1(0V;Z3134iPFf92kauFN;Sm!>i z<8Sh8wV9Ik3i}^s1BXc0yHnN}riFlH>+CWS=IY+o*lG5PE%cLDv=}ORpRCq2rEj2| zqI*%qeGkaas=#;ywd!eK+h{I06^&q@SeF)UgjoA6ULdBBvF}w`a|Nu1!8ALlvt4cJ zLh6Z4*dqU18JV*f@46cZ@89n!K6Cez(a5f-2ar!J5t@)V{F;AoL^*K0cN#E4a60Is zq!VY{Lx8Vi5!ext_JjK0Dvzg>q2;ZvAfpG-*EO2>biKv|`;48g<_FuLIsFCn0h)Qm zDV-#;EvvumWIb&U|9|!sscqTOdAlrWum0uPzV-n6N!L8_`F7pMlYHl=AM@;8o<)4W z&iORm!+UsMGSBAb3E({SmvQo(UFPwr=7&!c=Q^Gvyf@$BlYF6@C;oEhAsx^twLBYm zeug#j;K{^3+u0|Mb2ZO1elTQlt3LDWV=NjTF2?^nw_CnE!;{kcxz6zR(YTMN8$*-N zQNKE6TNL$7e(+`UZo;v-0{mY!_@A{w=K3VC0Tt}8?E=mJFLps-kX+ABTr#ZvD zy5*VQobx%+Xe-Z?mgntfOd}^a&J)3rnD<5Qw+F^By3bhu?{&4$vBr+>)X~fFy{`}F z@WNB7dH%SRp*=olHnp5*qC>~slE~5yiea+ zSyo&R?b`8q$v!q19Vd$9GEvZ-~R`>pp ze0BoM)`a{yGq4>%!YVU{Jr6AYTvgSfCNSX^bCDq z2>Jq_KCHj|4+>(hoZm)%tNi2Fp!LUP8N5dUT6jwX-1jr;<3GF;1N8MB75sZhv+o%I z*Yj2fu7S=|h_vQUKVc3r84N|^(0e|-0pE>`_fSXA2DkAay$?i~_57O}^Tx`fkO1!> zFrFngo^FZ-+x%29@b~$nrH6TF*#37j4l#q&qv(TDrcF?1(M~>0O$fbws}xL z_p94^$d8%HjluIF?L?HOehV?QE&iQ(^PL;&JY3})ae^2*zrjOW`DF0WQ4cw^KKAD5 zdFQ;Sv1>V>@rk#utdUVm-p*D+JJuQ7!t+4EC6yhwdBXyj4}Bda^9n(B^~sXa;IO(6bwhg7$TA9sWNqYA^4>h{Ap1&J;G46a`|5AS{ zN1s)3S{w7)EaS3^2Wg$|2H5%B*RvxtmK{AmdDogwc$aGtje3+`r+bQK4WzG3eL3%B zNOzi%dOg7^wO2WowwB#S++*(c3HD?5ep2>u^FX^29W+*E~mS+jIGAx0e&2dPRp``7rEt^ zw!Jo%-=56+!gn&(VV}!6!i{`OOIB*mOICJESh>P#E{0dkznw?h?(@n>_IT69pl3pt z|CFu6Yk1(EUS|-i(!EVD4$kacVpsh3jv48%1f#fuQQeUvCc#J66&M#h^?fLGW77Lu zTJYS3IcA%|II*$qfc_d(MHB1ilke*~t0merYf(fLcT~eI^fN1aAZGs!f-W@?xrl_^ zt>>_E>gpA?>gtDms!$xw-l*$(Z-y2F;xi6^q2qs!|J~or9B`MlLBAu3*t|RT94UJ( z)0F}f)IF%XFZr8;_p2hvVIOYx=vbL+1lWcY5DP>&ZN_)LbQXJ2k~>CYcMaj5QPbrm zdd{79=FD!N$O~MEZ5sEqHDbAI_>CDsD$pN0?lI;JA~b&>TN<_q^=1S`q#2%Y)~_Qnyc*?l+j z3K;Zx26~VWcE{cJT$ktPSmDkab}i(2@QzOgg#496R<^Sr2y9{{rT2ErTgU4gb*^_G zwZ8Zy!ZE(Ttaw(t5ulK{eA1d4#Dnw9Q_p%FzTnSs+De>#wg^USnuyfoJw(d<_Kas0 z<15eW-+gcF6%x2Y6Ie76fY}=rv)7BYmf%YwYF3`KE5`9Y@~v3OwsepU(n@si`+{Z7 zBlL(o;vT$)LT1A2BJ18Qghb;5OW(yu7y;`vAHgc;ef{+5wN|Cg)m#1=dbH5~eMG!A z^3uDpG~WjkPkd7H`eGbq)jGJp^bp3@51?gV#%Pc6sRfq5r)*uirahy8+HOD7{;+&; zAeP9lJD-mgm*}-6Bia@-ucv9%q6-5M#N*ZyaE42yHh_ zT&pdxnmzBOa9*x|SvJZYp=y4{_q+AW0K5qQ+1iETC=bW1tUJxWI74=Sn))WpfiqS-_eV}7&r;u7^|K$0wOJYns zKRIi-j4vl=LuY2C=ywloy1tigEJX=v&+byhE7Sqj>iY%MID9j{_$MuROQ@Tl`f98u zmz*<|LvPQ$+cYmF8b1+XPiG;_Y`q7~&x=w#1#b+}OOO4BV_td;FN|;GdZI*7oIVF~ z44yDI+?p4;e=1mjR7E9Z{_piIsQvkffyNRLF-OPBK$rg zfoXX*bjMk^Smqp9jur}Lv8RH#Mb^%>_^Q7NswC7{Sm8bR0GxMvx>&%kOK(Att@j^NtjY&|1JnSU(&Z$ThFT*a-bfT&D zg=~_wZAm*eOm?Qnv(FT%VmleX(alVlf61r%ckJY7K`f+>9{8&-h5~DEj+>d=*F)!4 z@6kcm_0bi23q^j$>)bQJcO)S4aEDfeRUj8=u+~1@TM-K5%@69H_1<>A=jm0>ZI^`k ziE3mcbR~j?zpY#XS-J)fev^IBXh42Nt@F`$U}`w@Y+&aM-S#@{O)&b)6F$obaNcK(czkIB-1fi zoWP=@+htZLABVY1>&fWI4vecu$K(Rp@v@bH#}4el&+D$eG8_%yY3cP}jx``o0Cl~*O%Q>!Ro}laW1JP-T+ zYdQJ;3A6#_(Fr;{A5yqe$E8S(w=7*hVvQfI@g8#450Nw)gM#G_7gidv3h#qkc3N<~ z`yM>bZVEggE6&^jFKY^sAR0iHa6EgdZ$$dIJRLkwMj4ziwiy zQCBYe<05PKu+0dGp2-cL)jeC)2*-oq>)(iQPRf$a|2l@doWPe)@8J z2BC?Oe*5`qtKeb86ZcidaGvtnx$cN4HdHFRZlLtRc* zJ8OxvN|2H1toaRVH+p|s`vSulLptY(6L#Np}cwKNHNG2`mX^XgItYDIJfSGWMJ$VEh<@t#-nkoH3uA3XtkjFI@&rM+$+H5G2=f>NGUJ?KDf`69x3iSSOS3mCUr>aZd@`IKWwH0Z+{$?7nh6HbE|>ZRjIrWyCh4DOOKx<0)aC*)CVNkLw%j zRFAAXN+sT8Jm!p+H`Bbd5Up0L;QG_Z&zyNOQ{toiff4?qT3PZ93E*egK7QpfbK30d z@fXGMuC>)D!F1Q>3;}w@4zS2xpc)}#+14l2qq)e%=OT#%9Sh^}bMGIIBGM5%=e7Ba zm0cQ81dqXK*LS+_fW87r5jcjIubhaLj(a2_gKjr_) z`+i$Tkxj-7r_h7#YdfJyDVb@>N8*7RKj!`JrCDp!n#{Y`-i=<&!ko*it`=GB&aeG3 zQA<98%4i4~d>_=nj$B7!?0yRF{3Pe+b>)ZJ`wVQDqE|DD=uGGPO zBx^>WTvln!xw&%J?zBxPHOsS~Zik&3F}<10fDU6*Y9l#m)?LizJN9&U1D(wAAlYc= z93TlCAboR)wvpv-#bl?!fs7TIizj~TDzFi{Z3K>jcXK7w7?ZK(7u=ugFtOblZ(ZNP z2Q#^!W-BHh(*l|%i-DIQs^h`6UMm(I_N-`XGj7I}O31eaIb57~g;+TcG$)K1=eLsIS@71e*?^|Xt@CPr*JW=($=2HKlGpKN< z_(qbQq4F&@-F|yDS-?B<8AVgaYD=8sjc8ZbpzlN@N_HexPxv%5f$g(5ActV`vNk@Q zg&>XFyLYmQKI7^|S*?rS^P<^$x? zIzd}v6ex;@W4T*8LsBox^V$-kVW`nQ)8P|$-^BjaMx+*PttAG9sRY(GK;J@XJsNzh zeHqDI)|q+zo{ser3r>yFab%sFY`t^uZE%3N4V8545AkE0H`Xz{Hj&TH<P?t#QH_D(Z;z^E`YO8&1uTpe(wd zE%{Vz?i|7^&C1jQH5?K$>O%z`6zo?HIHwJC{|y?DGsii)^egQY9k^H6oVa}}5?W(? zsypqGZ;8*$B^|w|6Tj@-!a2<;@yL1ii!197>UugG$ZZ`hITk+(LK-pIBL*GJrOuC8 zyE5!ptLLE*Y~heXArHd3iMs+&=RR-=0s&MsqxUd{;eE(+o&=rL5fci0Hk)rE6qjVKXpK93(U?u?B~$`}Lm z#m}!7_4LV+0$n+^oXq*MyalU**2gs_l{B9j!7=GBQ#ra8k#k56jUsuD&9fP)eBN;G zW4w4QR%TAsH3DNSJ8>KdwR=}vf6R8{?*Ol2H_V3Y(Yw#AyC^=L2@8fVvN+N1{o&n6 zUH|m?azuI9l+`=&?f4h-z`GQ3 zoe>$tw%4dkmlEKC6 z$jrbmug%7Ink$GHf5XqLGR%fJlhsc?Yb}XfpqNpfIX!Aj#AB7Vxxu0Awyp6h{H8|v za@f*k$^1=oI=B=)@xo+)S{WLIOYG;WzgWWC@Wb>tjp=w@V)5~(A8V0aJ@j)!ksb(w zyhq4)~$UwEM3n5 zjj(*BYHdp-rj|4v z+6i;cC=`2^3iF|?cftWS5DZ^uT}n4n!GbbEZ*}x;c%6{Ige;jyN%ayzuJ3JQM%salnPSpTlTMygN3? z0zHa;M09Hj=nf*Txnw7tkq>ReUygCwcK%;qAply5M_3`E7v&`~oXTgkN+q3$#u#W@ z>dh44I-bW2aEm3FhZx;Omgt{5;$he}@uyc1@DWiXyU&vuEWH%^z?QCmIpRJ?y*sKP3=*? zdlfm{{go&0KnG}~<;ZQvkoE~JLEP^?2RsvP&?D87y@%O9coU2LzI2UP|GR44?izRS z1uJszk3B~C!&lJEVT~*;xduw{=C1Fs7>7hwi{&WMkn<1=t%=9~;d`kubBpxB50l#XtX8`L?z*En($=Q=Ns-+TNRrXU-x zzBVx%2Wu z?9Cnzbl$9^u@pNt%f7BQNo>{d?8r8fOnCpUJxL95e=H%aMJ@*;VhkJv2>hf*R&iMvd?-1M}@< z_2&5KYANlYVoNqsmnJMG7Q!q@mTQ%3aw|MuL?Mb`Z~d+W;|fQS!=c@0^eug21!Mxu zCWX@DdK8F-b&&I6W64>J2lxp2VGz~WyX2lLy7R->86Ry~J*rowG9$(kxe^`WhI_5= z?Q>!q$}1IZuI{y8b62j!hTS=?-9V9YkfYQHP`;hB9b$QVpHg%@z2%D`L+c21&3w!R z#bl1GH|01|(7HQ<-yK@LRaCQHCZ3tqI9G6qXWlMl_PFjq%3OziGLPeQk4S3767A>X zF$Z*NYZo<&8pjS|&v5AcjPOx?wo~2MgUv3jA?wD?o8JFkU3sVGW6vs<$K08x{rORy zkHth{ZAIE9a!i)MHBflUvf48E)K8?~esU{3V43fb!9s25!~>*Au%Y zY#{P-Zt|C9MWt*#i+^OVEIL=a_$J#{%kd)}H85umFyvs2_5+~Qp5 zjwoN?*@ z9sR`a-XwC_w_V$C`Ub=pGEUY!#9q4t!H;?0mR4-^LBs1T-H2hBT%%q z4e#97HnRuODzG64l-98UqznDBeD9JVahQk?gOm|JS4w>k~wanKO&VG8Md%q7s@(+_gcU|syIAB z%C6#NbBB>yL@6-B($6_!ZTe~Pz)a>;NQDkB6;!-H@9iEiv@_n)COh`suH8;N;fSaE z!0Sg9D|kB4{rc=1LHd0Zx9b@1#^8BCJijP7X6(KwDx~bmSP|Z%TF?BbB!!IdnSS!q z)v1BjnHFLv&wRRFM{m|SKl8Mwe&*E0xQBmvzSF&`7kJYa-{GELkzBmy$+yY))GS8* zs5)8m^Sz?gwcb8=kGb+DnubcO4 zw~gGZ(a3(_nA{(v!vj03;Hkg<3W+!I(0dJrnjcd++Qr3>p`I>sc1teN*LoTKC?h5M)_`qhs?K+aW?P!PQ?$AE0ngC6zh==HJ#$juaIblM{B<4w$h@&{J6P}zonVan zocYdZXhCyLBb~ab{DBcA{7xLl%qz57Y+sxE;51zjtdb1e$KWz9PCt7k7#V zWQattn0Ve&@=O0Ytm5DU3qP-Mh(2i4-@rNhTrb>s^~;|RYF7JR-D`j%YUcAABV92* ziF#x^Rz*m3e=fWyUOrdZb3NG{rC!Clw&VF{H7>mCaa^Uge<=Gw z9%gIw;gl1xA~=2As*ZDOc7)cjY2W#>Cp&Bt4W@=Q!$%HXJE0RR{Um5bY$%; zW0Tr8b3$LbJpR63bUm%9WOiLg?@Pko?DF}4`sdBp_{e+9Zx%IbKimb;k&$>C?-a4H z`S_sM;_qC&XP@84I=PqVYTsEz#5(7?Ha7A@T4Bc?R?(0WzLB`+eipT9?6RYZe+M^> zi^%1J*ZLP3iK~ZWA?4no3D;to2h=VEjw1@*UwcZ2uT zOXNK9L-Urd#~Eoa$I=r(FV-6wcdp{`@vkdtk~@kgTQahrNbNPh??5?s{sCXk15RNv zT))1GJc|y-T3<@4J=T%hH=rD^OFsf{4kz}`@RIejlaj;Z<4BTgpn$x{*h^l3e?o6R zV`=@1hj8H9jn`o0CG#{|V-Dm1f87~5NBM@tL9e#l_)1+au1pnVzHKslovw{NAGZa1-? zYKO6q82l0$nd1=akQ{gP9B4LkXUu)6y;pA(`9-Ze{k)|2n@MtOzR~lK!L5BNC8)eY zv;K;PefDh7k1SlDhQ_{!&t?#GY|IiOFXY1<-nqn8yZ539?|(#oSI15LVc&y(UYf&W zxDLcv`x02jt_(9ou7S=O zLb{^7e~3te{Eqn#@r!%XZ-o0FDjv*LYitSWK+}3IhUXh3hLcM07o8+b8d zrgiH@(N0|CDQ)JhaLp)Nd$~TUGvotsOkHa(vGv zCbM5#;VYf#xvMae@9r9v0~$&FFr&Aa0%eRtJ(!)6o>4;R?0B7htE7fr(Wp`Ee4uw{ z^2jKdiZ){d+B;{ne{8lGtlNw$J#nuWHI7M!Ic6UbljH)t1c{9~S`IkdPq)Aap=mug z-iNg01X}1Y@e7IO!^lg%n_V8jgp40V>@V* z>74qlsPrC63G}oN_fFwL>+*6$#pNE47o+p+Z=2EuOqC0F%+VdAAIF32##p0cJ;W&X z0fI`=$`+SOdfnwl2dBB7k;z@-nE`aB?}OJPfz)n?>v0#Q=^p|^)@x-TL1&|&N~}tY z&YXBW`(!5lyvv2xgWajg@ZMhYjl=RJW|_D2Isdo)99~;uMsJ+ zAR>U>biQF##$UV2+L-8vzW?&%C+eL-OgvS-Ksq={loTg;s-C?B_aP9+jI>;d*Tm9u zo|TI~4M~dhhmm=S`N)v5&^BvT${JfHqEMw<$2%K($T{e8Ca6poLKMAO<7}Zd){O3M z7441k9NCJ~#GveqLq2rm96u`#d{3d+5XQDe{OE#6?hu;wmx6n;|NILIDRD01j~y;- z+WZ=uqn;Kksi}hJe|f0Y5!Sa`v1_2$`28iPIbc>gXX&fshb2ww67)#?=x%Snuk~%# zEVrc}E5ar&Yv!3A=mp#Gkhh~390P@-v97+b5NikKLBHjSO*v8zaT61 zhhw_CpGbzxjD*-CNTn}{V}9mdj)QI@l{f{@{TnUDW>-UJXI#zrodY($K{c`>CZnmD zBXx*|x>uWDZ9|b~kUHOHE%|+ksvLuQ=8j%Cw$>&(k}A$BRpglc@IDs`+O)W~39=+s zF{tJfCHAd>dAJuj9ohjMa^^>p(D1zYYrEDXZjSq6>y9POYR&!4v2=Q`=-8d-*lj9j zXx8iKMXv=0IBU zP(DXe`{TLCX5RG&Rk4Ssf7Sdq@{O?= zo$+(@<`~t;v5sis6uu1wGb-TQhw*Ce9veaVUC`AdXmrKAdov_%vMZC{ps^S8a_q09 zCgOdZ_v^R_fGzTk-Ix5o_2y3A33^fI7~}q{PaoI++wX7X$_HZ??4A0T{i3|(l6ibb z>%Z2g?YFbut}{JX-p9(jKN<7(cyp@X813{sTF+mNceg0z^Y?#8Yo5%sexoRo%Ntg& z_IB1h_aJw{;hVgJRjs|*8(1?J)V|qUSJBMR>o0fO6GQj6hL*7@Eewr3s?TU={nk@< z7k^k<$opg068v+&b#=>rus!Jec-WR!CtdJ=F)Z2r+`MfTi{dQr7j9eqWE@A*Sl#tH z!~1@b3$nX)_7C;#TK%g%vRC|r`pesMIgd}ZCEcGeU99+Jo&B(oiS;CMNj^QRV^8a^ zd&$;s&E_n)`@H^tFp$yTwiqdc6h@4__~3q6&@5{V^F9z}*hZpsA<441YS}*p<+oxE zM}uIw^Qm{+_v4e*boQfc`}H(c4rpg;i?u@8o@YF3~_qI;;Lr zJWA)*eQY2~pXPm@jeB&s`%t`cDoZVtrX{?ig~O-s(bsvc-||{Nq$n*|n`(&C86zi$ zqjZ4&i}yLmpU$IsO$*!R(=X_|{H)KPAEO`ezft-O@7QB7Swo|gpe*HRnDYG1lFU4^ z`?&a4Mds7u$kF&&@p=4Ii3U0ZmE9gIhoMn}4+nZ}Awl%s}6 zFUMoUbG9j_y0)wY2rpS((G(?lw}+v0X_<4N@u{yc+}cd7{7$x^x~qQDr^*cIx4ej_ zPubxG>FXHVO;iB{`^v~Q&B zyZNTV)eSlN>3DBK*H=kMFwe5|o@6ckykiBgeNn2py~4XC^~`RMpMPezNUp#XqYTxS zC^xgDLMlML97`W$&3#gM0@+_f1I#hc$aCjLpDwxS;VgJq$9!sL`p+t1UK9BcQ-5FU z9YabB)vJfMzP?KIQSpY}#X@`fw7)erEZT78mZ$2K20lSIA+<>w*toCNBdq81-YV%U znFFKdQ(*ENUi&-z*P|O!QL2q3BFzlf;z(_zGt$j}IwL(1FS3b0>xrcK-$W!8*%;~P z&pY_1Dt_AIpL_X<>PXb+-vg|v_wtG-=xNs4qvogI(3AY><1DwThxL(F{O<0Jc6cT`iAqPhlb+qDd5uYui*wDC`ZR~utk#XI#e z{GI$nivI_$wfsy+BwPBdDsnaBzcF%y`PaT*6%h^qw)$4sK$p@Ahw||tJ+i)LwbGy} zGLK>mSC|IE`=Es7=&etxKV-|)$u=H*g{~aBX;)rt8LYBUIJkC> zKG^gb=C@eKg=_N-^{rxqK@CWPSl%79jD3Sxc;!ZLC875I#FETRS`2<=8xnQ!Q7h?{ z!rVsr$)~zz=u|6B6#a+KP;Fml=?2Ou+%&axq7nmUG3XPss^KUm~LZF{3?4B_<)z_exqHl^3xZarzb~x zx9uCbhiUpK|9#j{`*wPfSG=E}d6e#A%0G^^C;oJEls?+`<9bjYdfUa^-Ncr%DsqWg z>A;@z3*fYs+{ealNr4h~@oKXF^YL|SVWVXYYuW5Ou+}Q=^QfL>>k};PRgtjYg?{Q= zuyvl11=umzE|0DL0=D|rfX+0vgKw(?`;?~bw8SO1`HX<>1n#}?^=#xAdU10Su&SMh48&+b`W)lcY&;aB+Qz3lvb;xF!@>7OnTb83 z+mX!s8odyGuy%EqPtV5}#Kl)0O~JxRJlwm^l{U2-OO40Io3Oj0m-?NJxlD90LtM>q z1AnuWsi_h7?52~e#Ihsq246Pj6G_MgCQ98G9bn~@aHEzmrG(8^B2}`dW@GQ~QBk(}=Tz#ReUb*ItG`@{-ELk}Y z3W>~sqOKf@*UCDp3heHl$^G5?@s7sv@=lCC(6FLGwHJOT=wU7{NlJB>XW}s{CvM!> zr8&6`h?Ha z?kuAYqlICB?;DNJ+3Qnm_!`#Z?X2(X zZhmd!`ozwD)jQaBrJDFfmFx^@EElu@h#rFYO2hyzAPZEFDbcOs3flpjznrlQzHMXl zwRP`mZ!vkOT}!1{{OZ#t_dLM=K4+qqpE6H;!h8D0EXH#^%R!W38Drf9ZIExOWQ)A| zw9QKvEn<%9C&PBD&B%>w$+1pF)8X!&{m2zv+3|~Z650=JMIR=T;3s~!kSX8V&FU^L zf`eu@*eke4%;Xrzk2H7m>H5i9eom@AH~q*+eJsy>M0Y2+=8g4oU6eSS$$d^=08*U-UVW$-5lhAlzk&B$ZtrW| z&eDI!(9asBdH|jeGagauES$j+%5NIHA)nqmy1J+%mKUkAxCu1w4neOA3#t-O4p*(? z{I0Gew}Z8zj`g5+_dl$&(x6&;Su!>ZJ@-nsb*6Ra77))qW8&T@%`F@-m8fSq3bxgz zm2J;=X6VGwifokQDcScJXPFCbBP5H6o~HK<*S(htV&AJcvBA6pQwm_m+qknPe3 zn}&-1sB+4#ZF!$A%lmmWk+jvb`CR8)!V$?>^4?sAP^ExwiPxE_u7|h{5-73VJo>0p z^*i-?KGzFgVCWw=7Sw%DVwvhLk(K3aci^2aZLFWnF{dYzqO*Q68VK7jtAWsLH)92z zgK-P2pS!bG^rqWfi({BSE*4gcE@T^YddRhMqBws@gu`1glO)j)Z>+zPsW z5TY3Cio4GVr}8b)pEo4c&k+;tiB7toB|}z8X%3o5MRwWX=i@4I3WdUn90ob_=`jn^ zH>{x=!Jm39WYg#DwR-2S33!9FQQ54D*jSR|GM3*{?~*HVc9df@spCp!F{hZf+|UQ> zW1}tfC;(MZJ5Tja%v9?jJsMG+PC|MZJG&#I0$9D^jzRomM&@Rgf-v=Yg4qfWA95aux z_w-l~*ye6S>^Zl$hHF{yOcNY6)HNfn4zDM6!-d$|2R!Q&WCD4Q`;2GuRlpOJOdEfz zeu-6;KFM^+a%ls)k0p1|`_~^EJ2MWtVvSluGr$DCr`E=XIa}u^u~wK1oSDW2d#!fj zom&Qn+7A_LuNz07OB~{=LU{{+iHVy~B~+^7XY8%HYpzsr5G$b-Os?Lyq&ON5YOTsF zR(L5TU8+TyqbZN5F;(jPVGoH4rHeHLn9aUF9p71y_%67vW}=pQ8RJLcmu)Sh$7FId zOD3QKhZP5(UTlB=8qif_0yQ1fCKU^fT=n-|c|`ZS8txdIvn^-pJdl#B+VLsi_f1zW zY{`_eA2zgJu*K3kC`nRl!1tQXbvOKKpu6GQc|;aM0SlXI3%b$^xJQB!=C|{$ z#wKv*l_d(8yV8u`Ya149Ii6m}HI1h`-ZGURP(gE+C-cj?k8^#pa@?b5cGvP#;8hs6 zau}q^?tQrN{JsTSa@-w7wF0{$@;RD18n2xU!{pJeV~@1k$`fjwF3ho#Cff?<$yG<= zXRpcdxU19VR;J{#4X1amwR@#nu-DX&Qc2&D+lV%*@pO5W!ha| zW(-hs10-P!7p|}?g~0a?_AQX`Q}>!xOVxIStNy6;!<(epKBF#uafH|pK^i{CzAA{N zdO=;Qe1{wo>sFnF3gRbY^hk31h}8aE|E-n!AZ5z!4!N+M3Xk5`_)G5G$R07L&JGJ# z4kPsO#d`uy#5vLbcduSJ;F&pvmtZ+g%EG9#JcccC@q zBosOud{+46(lRVZHsh=As^$ugbmdS})M`7bJz7=d%EH!4_U1XGxv$yIJamA;ckC^Fq92=lP^zOlN*D)yHe_fl8T31Q4*WsxlB0T}->bKtE~|dgS7Wy1?%vO?&KO;Wj7b~~eLoz3zB9+# z^2TT?PHR26YP@We!B@WQFXVy%K%x#Ai9V)3^G;%Nb6(%4)0|&SI5X8 z(40WtLk(H{flvZiLdrmi3`a*Y*CDndyb^S;e(=lO?Y9=+<*G-BNo@3_^u!*BH!kFP zMi+ngUG?;c*^h3X-Wdh-QG>fjz#(e%4RtP&{9mpbDqwOz?Kxx+HQNd9A6XfdDUhGB zK4X*ur#xW~jDp%G035xXMiU{G~HKeLUH8gPCpWWorRXo(N3> z;gjG~D|jx*i(JnWL_Pc`$M5;{{X~Z0DmU+DX&a7SV#a2iTgVgafk+f=EF#sF%)#$hjOj8nn-+4sDNMlK8 zq$`ouPq-C~AfCagTdgkqt>Ytj8&rV6YtL8~*B33x;PY@D!`gOvORRuzy1;-_^quRB z-J{7fxsu-8dvD((?Jv|pgQIj!^FvMVU+)zG6Tv-Os*q#eh5mSVTJT zhIC@>B!jgxVNZfyEx4)vM7#^uz>1!+95LEHu)3I?LMy~mq0cO_`I+%^nAX8}!ZcPJ zud`|z73vy_DOQ2~Lxxd5DHD}aIn{5Z3Imw6qk(VSnz&fxnJ@(xy%4@p1HH%#b`Rqn zp57>jd-(0sQ9v!e%4ATZa@_eqodSJ#NQBG@iJe8|tQ>Yy8@3z@R#wolshFB6TC1GO znYyG*thrMmF-{h-raWAdc{3p^L-RELvn$p%d~2*YBWH4jdrUNHr$()H zbtg`y_c_Gwxz9ifP*v9zU5SAF?l4`s9bBo9E*+-7q3uCDmSpbD{mV|QWn*Toms!|E zLZ#Dv-i@fN+Es$FfO7UDCNd7%N%5+p@veu}cY-!kJv6)v$25r}JVlL(>ToRp)t)yx z01sweFu9-}BP@lOkHK_|=2kv!A9=D=@pfa-a&rMXH;Z@xQwTODuyo4tw9)TN^YF8Z zQ=~yEz-NlJ(iKmTP{S`m&NviaG<-trWo1p`O<)`5mrPX(-j-J~p^eEMYvskBBYKmX ztxTtXZr2K?pY~5Z^Sq5^(8qjt!A^}eteHJ16$_c1RLPU5L1vnE1o#l8Z?MnQ$yIPv zxhwJ4vF#sYTYhr*A+9`pB-OJcYbMw+H~NoF@H)a-#FgN__W2dw)YP3O1CjXxg?=FU zTuN_=19A(!;DyLjYj5(1V zuf=oXIQwHQldGX#Q9=bbn?Z?$%aavTIEl1+^nymz4OODuX$Uuxj`D7I@%;2Lo{Rn} zOGcD#PQRHrJ0VqX*#}ynabfNZ(bP)a3?6N(%FsU7!DEqE68eNMJ zEj(Y0P9$4EMi%7k?Ri8Z?mMcla=HspfDV|=)I3h1^GY@Y^PG1!*Q^oPM)zDXfOpR4 z9t9@iRYqg<&EZix-k(U;vQ>RxY;m7ZLUBR;+|_)E%w*o`V%9$B)Z9iyWvH{bG}D?m z&QKv{fQQsNzgqYjuA<`Hjg7DL8}ZQ7zptFa{0ru+P&W}+)yslQ!Pss4K)cCWL1S39 zOewz(#sjhsDl1=zgfLoqzp3t(x05q$)h_DRu*E*wiS`KZJeb=3PgMbrH3O zDjC*~dvsPDwtw?3$>d#ZkBlwi$mB%)$Ah(dK}U23)XPdQQYJ}fH@%tA=m=8l5#I3W z%y|8zjjY9AT3UW0wXjX&bWjA5HDp{)yX9z6-)feRZ+;Qy%oggWmtX()Lc za(U4Pa5DIWcFSvv{RGVCYDHeE^!iPW$-Dkc6`8q>mMY+{&yoDs*JVw-^vv$Ne2bOJ z8oUu?8(a_y2BF|--aT9T=WG)ixe=hsiyQyDCmG}o<+`nb>55w4F1O}WyU!Sbz7T#aSSwacM5_=7TS-9ttKYkEf=*7kaY7JY)IluFLW6P;gKn^1!|~A(uDWH; zyHRbi%8E<^i;QSRO8MY(d~8n8;0a(u>uo&zSbe%2%dm>D_2-N)7iy0y1Pv3Ue0<`-S|X*#gtY%qV%K06a7(o zk>em)^Ltxon?C$Xj^|p8H4n}o>WVd7g@)b58Q1S@e26t2r@ZuAwY}w@K_+t@Thla8 zxLwO9VPahMt%_K_AlsJdLan%qMXPmUPW!a&?XwRunR?|E_y-R8w6JYclUCEhv#^+{ zmAS7`Q`f_+Mp#~Cx(71)Y~nphRDsoYs60-us-b6xQolhwVI!n-?M5e2Uin#$k6z}<+xvp+H3lmFVEa70Glf(4^bhv z`Cl;~t-&5B>!_~aImI@mYJ&^(ggr=OTUU6w2FWtrL&doqp&CA%JNh3q4O z_UXuA{j_O4u^@;k&|fGgBY+#!Q$OWWFx=mlm`{7sKB4ZB=I8-gx9Gq6`M<)m9E9b_7-9mOr(QWfWl4ENz|1aJKkZa+b6 zhdkECX^77e|423~6;rJ&3~W3nkN%*_R?t!u@0&2STl76qMOC^6Cpj=eP&Yy99-gcbzESmdN7(%Ou@>B_OmcZrwN34m=)Vb^Hc`FJ`o3&8(?Qr~neq}sT7inTIdo|AkB$(1V5nyLB;aO!hxfjF5)T0O4YaXQ3l<>OYP_aqP3 z_rsQ2^+HdS&9t6x_Q86v8X6ghpM<2lyQ@~Y_6&Kn#J{LSA!5AS_yh63u-=ks0$Q0S znhBDuu@JZOECl8=4s$dsrIEqfI&2m6{5l>vB)=NexqDd7)aaRMQo0 zRqNrI6Ld0l0k}b1oj!ofAifAfq||2pFJ%QHS*pV|Y(1dw5_9RNlGWMz2zDCY@BmN9 z;;ioB?(q?!uT&|d8_8#Wd5!}dgS`$MsY#B z0FSJ3MhE&|D+|#A?lj5Kd7jKu>-V@10Jy!?u=%q>&D!13g4D1yqjkGf?(W&*9x9XrEU7R zlRQ1Sec`kW;Hh&lHg>70aLd{CnMvW4)r>jRXIopW&1= z>reYFgSb6RChu{YOS%?XXR#JjYY@}#rLZ!I{*A1!w|;=;T7eec*cF3!LLfFo)_!2m z_v?JNa(Q}U@KLV!fwJH%qFvQXoGx3@pcQanwXl0WS4mGy-k9&|dy{(zCnoD#aqr5j zd|vzjp9Xu)bT)#OSD(JqyrJ`>8xC`S87JjW#22=qx_4E3j`OkGwrWnOygglCM$UC= zo+T$8AnC{ZSGM=oV^RrHD$@ya9zkYFrE;v+Ui#g!;UUxi!;HUVL5Q4uQwc}B>d{5% zj+{^5s=uyjy2j`^3)mBPSCwx49aDHUxjh$3p^erGQJ1dn0v+*FjNqfSp1UlK zEPE;6nX{5Bugt~4ICneTd%~8b(W{0u4R3hFQ-7pTWerr*Id*LOA3qISif%G${qU}^ z{c;W;Re$U&HEh)Fls2F@YU;4S4qm<8?VwNYf3EwQ8Cs~Xsss3N>EFV5cYC9>wsAo#L(J3!Q?~vRgjmUbF(Y2r@gF| zh;e>`8_64#&LsXRTllmb!*A71fd+yd5G#|l4(WxK+)VRwK{bwuf(5W6m zjRY3wg2uDh!ebsFc$XC3J=NMC!T$*5{;+yMTCJ|#ryNa!o>O%l-bC=UR%m)>quX#K z$Vc5x>od3+?RLHi2$)F(?HS4)PghJSHdmWF`+B*Wy}{h-SH*pSjJdNeWj?`ee^q?r zMki>Pf0mrz-@Hiu-nYoID_S zTTTso2V?@&f`}Y73E6wnJJNo*R8NwpP^S)luAUNnJlwrMfw_a9Z+?e$N-BLeS_Zt3 zF7*tyQ!k%OBm}#rYg*q6pAYV_SLM0OOSxkF^2p=6qddp`U24?fK9+U@MEWoP*1M<(j;yp0xpW>$yFS2Wo8dTWA(nt6i*%_>$i6?;@(Ew z(&+K+lqqxDqulX`n=8H2cfBklxZ4poR#x#{hq%>|>p*N%E+4n&qBZ&nc1YAig6n@h&9Tc>?H*SI@8UC0(@%?Q z^kMJ0l6%sEcaiB+M^j5OnbP^KQMN!T^V-QotxP(ch%LD$Rl21sL*j>$W)jdRJ!wA5 z{#R^{cw)R~D-*$(#jYmRHav@1Ts))9*vCqz9FXg2lnd$!eWNCah6lpUL266w32n$` za972?d>${K;x<&iLoLbKF;_$d_kZn3HDI4$HDE~w^;6N<-FV?mbr^dGepDHQ<0>2$mP_t2y9++4lQ9 z-}}>Z?zvaC*NtHkN#{K0d47MszrW9O&VT*qvFV{^A?a_8&)=Q?;Bp~3dAXQAUAwSS zNLEWfum67XdkOzBW+W*jr0qUh9B&?L`G~vrx6g7YEhO8s<;M8@&GJ`l z^#0n|6@GqJDOLITVtq8Mu;jKuf8<}X)bZ4rl;>F)TE}cvDB7$Sl8@)c(y`WLsgN8fH)pqJziKnCFPyXy z)#@68vI@3#ucp+ zuYrp%){)cL*2MA`D^I7tUAeikzk#-Q43K`k@bE% z`3qYU%tEv5;o!yUrsxv~?cve#T`RDT=ncw|S?s z&m_7pIh=gk{(r#MM5FHIz@>Q%(;Fj&OHwgXEau?Iq*sSn{=?lUGbKKQ-RpFiCLbsQtcK$Ckdkbs~*8y0qfB+4F0t>|W*O z%7vBjtA*tB;#2d`D_eE{=X^rpW0xM8fA4B(LF?S9$XjP|e9!nk()!IsaXnaui^t|9ubI&9sd^=rH=Dw2S!2d2Jn+?{$NAMez^f$}vuF+G=Z&^HYYrTE_NDDqkf~F2$ zTs4aJT(8fWmP+sArPq#J(Ok#pis`|t;QsM2_UQCT?ObEB#+5HzCrYs52aC-Ry`BhT z4yPlvuO)qrTD6drXQmoYFAXOHjX$#|is{{@>Ke~}=jw%(`D^_4vkwp3EN9YnL%!^U zCqWQ1KN)6BribmWYX#h#TE1P!>Uqv*zhIWcGa%?d;uwmu^XCf*UQ>8|&d~Bq2C;FB zdN@7+kUFZTG-# zF(tpr$^<$;-T0&oW|?7x8+*hNdBgA=yLBbG2U}C<|7Zq!|j$0BUA1^Za+O&J~o|{!0xS5 z!Db^i47W2Lepj{!a)owgh+2%1C0+xQP*F@joiEo%ZMBIs>NU%Gd`41+n@$~b9nXy~ z!t>;x=$3{uq+;4{>mHqc&YqEf8>$r-EvBYK*XO3kwm^3>S6+8aWaR=K@Q!w(Ed8oK z={3RN%HC$2#bs8jPHn_&T-jWt9=U-c=p#z_+~|F#QK%`)?`uvq+%GtCo(PDFGvSl{ zURHL@I9V&ClhbhFh{@(eR_~M^xk&t@GMGqB|4Gt3Yftd(oyutNVPvhxO>)@rU|Al< zwdw0>cGih>W$i{0FWv(oaEgVZ)vT{Se33P>oFH#zQ)aD*SWItU#yYZ3GOoI|Y2yxB zlVRD*Pka^TNp2{Wh zVop1f0`ufK>TAAJQ3Z(i5^aphR*C^>R*4l`y}Z{C!dlRe43&wvAK}UFtUcBhk!$Rm zk*?cAJw4@155*U_i4}@lUd)2fx$X;Rg=G8&brU{Z(L#vT^$enFY@s8koyr~S%;Q$tR3(1Pv@%p%w+NKitmea-gw@@&>h*PR z?Y`WTM{E^Jw`UKh_{BdgVRdh}`UAZKW;^aLoO)kf`2-f%*OU~Rt*J)LW8iA2d7^D) zy?Da&dxr#{=W;z*xqV%p4mubmzCm)W3MPt+cu}(4ky;^X)WMvx%XcbI&4Y@uV6DG1 zbqjA*=m?eT&(D(U(AVr>5c*1xtDngI_0Oak?b9i zpo-PGK;A>vc`8*^v8pd6|BnBkY9OQgSs@be*(6KZcAm2=9S_e}ewN4=cifjh90&3~ zoe~Z@wYbyiBgn1jMZRMH6_R5uq%^hI*QEB_XOTOrqkRb;Vte+4A>XqA*PrEi)-mLn zEcbL0nDJzKYPlFlLJR&Xw)ajV|G3vXS(_PTWRYJ{z<6?^(nshv05j>&TP4YcDdY#Yv-7Fe!eQ-hVur5+BN^p&8!^5+0U9$00rj|ChyG zCqh}xIVPUukR;m(X~%aGTzfbV(e+S1hQBGC$~!E3)I=swtS4d5>#eK zeLVN9&6&k_7NK|qvhY}8_44zvI%M{d(ybMzGd>5V4%M5pz5GdbMdY2OZ+(GI3fb#! zHu8k=4adZC#yG$5gx2uOTrZdv9=@cyr;vWIm6ze})s;tRk28)%MafQVMY+3A%W|g- zq`DSspL~s1u3xxh^ri*tFt7)4GCg2?s4oN^jv}84+t@uH$m_KmTdIhB)-26lt9`IY z^~@f~?l=^JTs}eC#>48?W_{KAu0*(4>C=B-xHeKFiWbwiL+2x}8&!^H4VmH`87{1> zmd@Bus+hC&LGuInH|EdUq-+1lkZYZ53|#ap{N7nRdwuM?EZ*PBSGxxEF5bh|WFvajNd4n*;NY zU7Ekf3hHzUi+N1twTq4Ac|319yP~~kFNy~~&abKmsmM~Q_BWyC($#8vcT!%}Ie@dy zOu%*V^`M>6TGUQ5O`rbr*<;iAkSuN^zsdAy=*{ySe(2Qlo!J5FL5NaSwue5NYQ+BO z&`L3V({SSXE>EH_^l>0T%4js|s+V^|TGQ)Cr#pKozT*gwJ6c*Ct*L{qeaoTdyBnSS zNBeb4^Z4RX8k!u3vY>8hK(k`Aa@nEM345xP&QwRkeknA8q-WOON|9!^FW4#P@r?oN zqv!Dn9 zThin6^zqB}_b%bbqu0+$6+YG%{?YbSJ0ndNs~!zvf6MU{r7RvL8}~0?4Ex)i`*DW9 zuqV)qt9T9HnT;M9SkNgQ#zjdtS?&JR|{elBJN30t3DVFDAw*Hc_VS3`rnbv zeJcL;p0#zr{7$R}va%L(87useHeEcH~^+X#3P0HV-yDN8Zh%Gy`-> zMxx%4YEkRTb64lDfrLIglcjDY)jzd`BHV+jXwS0Il4tckKk}k`quW`Joo)+GRtVFBY^>F^@ zJv)vWCqK3`X8)7(UfH=+%Z#oYr(Ne1^Zu(_3tT}i(OWrUK#=p( zDJ`rJIVdvVL-2HFoy|Q>&|7THlswKhGAB`cN4YGGvhLloD&>T+!js2w8siBW&%fZ{ z;WOVX9dJPohi>U)fcZR1LAqbVhO#jz-f_F=Wo7@LIUUiCE@3_j)~e*apaA?jKTdUs z6qV{Gd-IIJ=FxtwI&otp)Z-I3nr5BUC|KaaHF}WjlWc~w*nM_tL*umTjK`FveSL{t zQq3xl$SG#}c-2iiV{NpMy>T|+$dzKq6!jcb#PR6K^NQh}^Gx!~j^o2AJJ8zqET;6; zw6=a%B=LQr{M__tqqVD-MIB5mO{Tx!nw%y^f)1Zwd!Ab1gi!~*aN}~vgKJk<72VTm zbqVX~4?Jf_<#i#iNTl&N6i^z@3rFwnag4}{Mr2E_Uw(Rz7%#lpqpzJEqb>yeaTVIL z>&I2^Cz-6Kkp%r$(Gbz#p8G-4(Jm#Uei!L@es_P&OU@t}>wl*LO2Hygq4QKqo(ANU zM~88G>7<=@+nzmJXFlQ0=Sxah&)^C^glPZJ^(r4omDw4e z?oQvn>}L+;0hq0Gj^g4o>*U4QzbchN^1{E~ETb#;t??8Sly+u2LYPJ%fpWW}A;hpc zmhJJ=@yQCx{Ic;Bjz69K`DM?Y$T305SbDsK^h6Jo38h}yJ-PJ3)(iGtK<^&tQ=t;b zYs+&0$u%3{T>kkd@;*G`SFsPeHXA3xTN_`v{*3LM=PNxq_;2+#EK3l<;>t_u8p`y8rmBcxQniDtL z)*DVn2i%u9fq2X2&>0n07|vyh#I5~}lho=%eElqB5vXgm1Hs>0LdrDVlZ}5bY>3Z8Q z#&<4Eu4%0bU4Bld*X)Yz2NI_^B2P6@UbA=~(JS0o9b~)?w%@Gby(*-Y_2Ii&Iy3b? znFdE%1M5VNkt)u3Dkqj5b$b@Du3DAYEX&kb^UBuAclm#^!f9dO8TZ-9bmaF{r!dEz z%Cq65!wdCM^MG7|Cav7x{8cyunuJr%1I^)eT~92UK}n(Z$)>Ixo$lYlR&*Lm>!~)P zf0i`gPpJ`fohNm+5hQ$8IchnOjhVx{QTZX`t9H^$Z`}3Lk>(*Xw7U>npR5RXyUW0l zi!V}+CClV`#CNRUvN(|c@O+CMfbEsR6|%1UD7cLC`tFjC!tRMeaYT?}x@|j6aPwJd zs1)R7C#lux@+U#YQ00?q#0m)OYYv1QLscfylsw`NMlYED@B{JYBw@bN?O==O8`a!VCUg{i5*=W$M{1p_691ZjuZ(?$=RUf{0-)k1lfo-s#*ogyjhGFXsNp9$YdSI}EHQy_3hc{_XEpJ<< z&uK5N3MU$=2p;93m9&m~&|o3v!PUdyES2|Bei^!+ z1UC;e2hwo8_1UQl{~MjX+V0@@x5v=`T%E&0dTG-+k*A{jp!GYgUI@tBzE=@QOeab5 zTtJs=Dau0D5UUZ;MoiQRPVlX`I#PolPA~YoRBQ zJL%%%^e%zkVFQWi9Di*uXpf$&lXfaca#JK4XzsBdG8W_SEG#Xm8;qxg8uG<&7T{^^?;Z@7_e`1`0L}kgo?qsdMHGl2X@b-Be|1;|$lb0d8x562a zsm7Yo&Iu-Xn=*g(%sTx!_-Za#e|?&>vST&78{R|B&V@~@vqrQn274Gc>z57CQ)9%K zooMnpqFcvM?z>spy;yLQ^|4s8YZkBSzau^N!xhE-9E$c3;Nkri`+|?#JAv#YbC$8! z**;;CoP(V#`3$~2;q>NLgSz}RW&Ofh*6V;Y??=N$Cyw&_(QqK?XSH!AMKjEVN4mev z8KIMh%+$FP#69Fi1!5JU-B&)br$p7}wFEL?q_BT5oG6>x5MK5+SFN6=Gw|Ke`Bp{E zd!=B?djzXE-tl#xKJ-!WQ@5NhoM%L~4>v;(B>&0Kd zeTXdwD$16}HzsRzw8sooP#$(Oxrwg zQk{<4?Tu*pBeEg($s{31Rc6ihdmKnz(#T5h-ujh>u?3F?-C70>;t!O|YOzvzEj*0uGG61JygT3Oc)@a+e-FD~u_C~Hc1=6S2oSLzh(*I~y(NpT zw(oh3l4>f~zdWATSza@6fPYxY^QCks!WiD2cVAGJ=b?>_I^hnol2W{+s@rJaY)AK zJnoJiY~|2L6SiByyX|^E;*pKjHMFm$ADR!!zClec-Z2z116&$?ZW)z!zfk)a1qKNTLxliFT0ydk9dWa0QB z#-RI1AFFyj<==IpK6Pq28Jwli=>m6PiVRNlo7Telec|q{@Jw9IN#D`zDj9zsRivo)PX@fqPPdm484-4pY_;Ts8bM%@1+ z0qjLFc(R6%8EV>>2aRGn)Am>BTzbC)PO59?XLzGh`_AGYU+>aU*3qk@?{bSBeb$aL ziC$NA>)E>Y=crtD9)?quNG{OW?g?p6Ryn-K-7v4cQvtoa%{f?xV%?4F;mf@?i&p~` zZSD4z`hs4GK*&n(CE`hmCLW1hLq~#!@)i>#1|Ia%)gkkR6FYv_dL#kG;M_9+cAJFu zrA0VV6{KF6_B%N{lVAPSuzFStP^=sz`qW-J7B=A#pYTa_q~`d@o&kpXJa2Jctpjd6 z2gpg(_GyP|;KX|y*)t5vqI5n=U3>LvW8{q8aJXW(P94hqwbP5(p+-UvNKswrE2)e5 zzuDUnpK!qHajm#QJ`?$e4sDoJ?8Jv+L*8z7y8dCeobyF^D)r-TTd&zOOlaurgl26{ z9Z%OAy7HNBt<2aiTW7xH7O&HPyPx%vE$fV-WXi0_8?0hI_Ei~M3)FcAgJ0vDhi#8{ z@%@k?%RVDYmP@~B@2E~rzaQ#Oe?m2L9%-Q>v~SFGdT%Ofe=hDJ#C?Gu2Q5fn$V6F( zQ;M9)mKD1^77~Ybh3{fzy|SJ@-mIHAF5(*2&wYa-e_ zKFcjbb}fl^V$Hqd(Fb@($tvzJ`&%VW+rf+O+q7d7=^{s}uCXh{jx4)M_{W&F`g714 zca*)a?`VkLjdALR_U2^7zM@GV0KIA?>;JYM;@jHs(mNIBStHp4NII_f&MUAm?f*+F zPIvFP8TnTh9penTRwjZ^S03nj6!C{FvDo^O#d;*S*Y@_5{~b5)O!v^KrDMfchRFr~ z?n=<~&R%|gb?md#3-}1)wZC1=*(~Pcog88_QjTw+utKj+mA(`H^b+~@_5$Cxbc@mn zqe6Pao_utRojL!u@XPj&1D%-oEndFc%U60|vo8_99KQCe?-cWu;@5WW744)O-}Wtr z@BF@E_ufES_N`yuXu985f}gkNj)qbC>hWLNv#%Q!?4@Cu4@MNdS)J~7{Pfad&_jr( z_z9P?s*m`-V>haM>wz5*UlomX?>LaJK-uo!lyqvxTgSrp1(mPF{RFh$`4vi5it*o{ q|9i_rA5Xq+?~gqZ-hmyl->@Ldq3u-BH|&eUkK0fB*zxN=Jp12=URVzR literal 0 HcmV?d00001 diff --git a/dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/LA_lt b/dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/LA_lt new file mode 100755 index 0000000000000000000000000000000000000000..4108a4badcc7568993d235dfc5f1115fbe96f94c GIT binary patch literal 54246 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 literal 0 HcmV?d00001 diff --git a/dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/LA_pl b/dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/LA_pl new file mode 100755 index 0000000000000000000000000000000000000000..3152ccb3a35c68431887844e734cbcbe274a5a48 GIT binary patch literal 64574 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 MQ_egjhVlRZ4bQ{m7ytkO literal 0 HcmV?d00001 diff --git a/dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/LA_pt b/dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/LA_pt new file mode 100755 index 0000000000000000000000000000000000000000..3fccbeffa8cddbf1c3464ac649b4078936741456 GIT binary patch literal 60484 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

rcq;-t zNW{yYiP7!7(+Q?3sn~`<1Qi{HO z1AD@iGOnCVyq;8@Wc5pb`|#!Lsc}h$iWQj`<7KWO;USy{gI)aw>*LIGj<{{S{qnU4 zhTHtU9Zl4BZ2%Q=ZW{OkK)I-TV<5>v8OwqGD6mf ziO#!ce#(hcF*75UUPhkd^X!*(3$RKbu-~Dxh?&2s@7&)!-rO7OFsEnzcjXHft*nR% z?nqw#|8u2=xy&AN{_D0271dUBmN{@t(HFz>hH zO@!Ol^IJZzSF8CAl=O7FuJR5=-!pi#-j(^z(e>(?aq@1wynFM|IC)!V-l2)Cc*ZyU z(fcR$i8uT)it_V*(f_ECkLz>pr=@QqMC;?F4?cfhZ5|97-#@d)7o|UMIwU%IYv1kq zWNZ87&51Xcw!FPiJ+IaOc?%}*_q$#8yj3msTQ5?LTA|bDH6s1;HpYG@V&1dK8!V9m z3t|JVqcv~c#ACoAfUO^hH%llXHB^t8IAZC0&B-Yfk zyxa0#ed4W@A1~I7^vHx~wGVe-o6qY1BUbL$XQP+5U*1~0atL{m0lU)%t>_gtU>x67 zxz$WG`=(KF2m)mLL>-dxHc(}pTW<9s>TVXp@D1;lMIIzsTlD`uGGd{|gmxb-gqD|y z^q+@^i@EiDq@-3n%=NMe{H6E6W!@%?Zfh=wr+Am?N983@v(+6u`bJmY^$ap*E%x;~ zY9XFs^)MVb3I~r_Vjc+#`-WKGwF)z=dBe;wbBWpMa!lg=murg^9xnDH7RXlExa;>d zzOm*Q*RE&U%Z$2H#^inYxy>vrkS>tl3- z3apC8k(F^$iBQ+>V_76?W)p+$YdJ9$ao(AWCcIahcLsxN-%0GdbQxQp^A>O44-87~ zEaStjFx#h96Wpx(!6xq+*E;Jy%^cz`l7&;T7r9P6d{iTlO}Cu2FXu6GGP8LTwoKmS zy~N}&Bgc0bGY;3xez)pwV^4dx{T?i~(7*Wd{puAf?aNQFxZjA3|61}lqog82f4uhb znbpD&=qaD1X35*k!#4kZmJfRN^|bDB9`8EDlltu3x>q7DuKUyfjhb_?QfIH@F6^ti zKF%gG4rig50l60J{D*nED><&v(c8R_HqUEcFEWqo`kpKsXOv=y>s_;d-S>P@J&q?zuuClFssVG-(`7B;d40#(J=RpSTbA|b$cfFe z@AB>uSJRtVyJ+6$x~Mqh`9j_*=#H-^GM!t~QiC{IZZdWYvy>C5XrO!1+ zBaW4uefyB`Dcr_NBEE8c-e@CA*%irCP_f9oBc|qucbAxja{?RdvU;eWJ5Igo?412R z?7FO~AF*>F!V@X3KYE&nSwA}f_|iVLDeHpt-q&fx6ZBYF{P8>Of>%)E?i@JaZgweX zkF}94Yo=V&=Z~s|Qgba&ZS#IbEh;L}-t~WC5?zs|(KYS?k1P^DBPS~sA{mdmhZUWB z>_)ijp`e8QC(nY7<7Bl1mB5`LD}3)j(`tSC!dEjfE_P5Z-(`XFz9GQz;WS4KZREsSPd-)-i;SGd+b ziST}RmMB$LP>7_yIW$&@1m~e3qrR+YlK1I%WTjD8IOrl&k8xwHj$S8LVD>P8d`Zsa zoS-YNvxkXE5FL(+Y-qkdd4OllbM6$3%m|i7o8!Bgjo_O+#m62p`2x1eo-w~0?|kcN z1MRPdha)&UwjvC?@fL8HlsF(#PL8ax>@OqIqR;S-c|0*YY6t?TR(N;)mG83hK z3L5uWbN}uOHYC5Xx(`ngZ(4S}XOHxa27D8*%N*p}uPPF?UcLi`tW}$DMLFDC-Z?tY z_t-M_G_UsPo_^j&skX>7FT^EMinn$45vlBq$;-&;EGE|yu#guRh))^A_-?`q#DNd7J_7F)VwPFx^6b8@1B z|Fb)4ZIo|=4o)M$yT-@kC2x@L$KF5#r;Ol~`Mnv98SK%h@e|QDSNXIF`ncEkeVw<9ry9xSm{P%BRVyUpL&cj_nF(Nb;xy@Qy?AQq@Jc1a}sQU zwC*>jDkFlT`?!jO7iP`DWZTQ90jQaNd^7uy-?*}WCXA2i7tbIo`1NNpJ5Mf}F;abS zCDlh(h4!Hl%^a0;aO1i}qKTRc_THcSIMw}qp#>daZF5ELQCqd&*y3iS$Jl_wsTjgT4K5qb1Pt?!!>xBY|2Ys>vss^;Cxu~klcVfDnz ztRHgOuRZF6e#U2x+>>J2WTh__+Xbm@iO#$rEhp8qPv)fId$V?)ZYSn)A_Y(AcP$w1 zk{`EzvSRa&=zw*5jw5sOgej4nzXzdQoe8qeC1)g0+po3GC?$F0u#|i|TN|_)sYEQf z%(tzWCwewdPHRhB-Ek`8ZebJYJv)r=w(=+25Qj)`xUPtHIb*>-lYi^;xbDji0Vg}$ z_uy)F&-d-5@Vz@G`75W_mn-Z+j61aK>Dku5Xv&#`>`Tyg{(GbD9k`#9Qw03|$m}t@ z=l5C3&Q1z8>0O|Aj&9axceUC1VZVd(BkU71=AHWYS^Zq^V6c1W&JJ?ruSGf%`$T_! z69q&B7H60KevLqnu@QS5e?4-qr~i5+eSfj++B_KE!R%YN#~so;i!PoQ=#w;F^$ZGH zuotr)lXDjSg-y=h@NJ|RTOK-n;f@mb@iz?ZUAYeT%KJOjI_%(kxZ5u7wDoBU{wD4_ zWg9(~{@HWN=>a?m%08}tH%bm$iaU1YusUAP$T`jM&e8QV>(Ue7>$i^=MDrIx*&mCX zAJ%*Y4-#3v`@lN0SA27hF?C1JogOX>2$P!)%&dp!Ma&YezST(A>JIW*vW>OFPi2qf z8T0j)WsYkccEPuYxMKqoPwvvQ~hHF zmN^@8GJAIQ=4p)|4pNSJhbi?S7AB)IGYR9(8Ylnv=~*+bnay?Jab9Egwfe;hd}b|x ze3_>=sqD&z_c4FW*!FhgQ;w7-zez!SVD-G5~s5 zO}4gVA2X!-$HMe7+6^uF$Ev3I(^{8XailkpVO2y=))_wU)pi4IWMS%YaK(&7#EJ}j zh%KC{bo>&x)&}$#Jnx^`cFlc$j5?!2R;-4_s8+kKac*D*`)JXQr*7QQmmj?Yd2*c@B8p6oheUu2^VHY2L23a}KqAtb;NeBh1n?T@Jgv`qI5i=$<`uDGRpjhTDd~|Ff9#5V;m6(qr^nX|Yi1ol z|AAWS!RK!(ZLH)PGH1}K*s&s4-L;j$7;XGpN<<~`6=q!TU+38bW)ZCS`A!d3oicY} zl=WR)L+kYl^~j<~Ml2DvDC<|DEq_b4HswO-KY8WF2dSQ)&zgFRbo z+#d>ByWcg-QD59Bzi~PtRRnjz%IC$nykYi6N+JPHgnx*0>;n?vZ!|HA@t5x$%Wk#b z_1+^ZcR~B;bJ`hsnQOzjW?^~d*YJ5W((Ofd;|Ub;7p&Ko&wNbX#=mMNhllC$7HlF{ zvew{=KT+`;*w%gGP#8^2QC*Xld znUOOi6M06Tx~5LmAF0NC11Fr4;DnM_XNeMK4uGwnSKVn<3Nm!m7^7= z6^Bw;4b6T=xJsCci7KJOIg%*)MA@>pbL-4j3PH}5sy;?wRWyZ?9|?1JjB z=e#2&#RSxkHuAUWKH#x(cL?|*f&ID&Te55d<5dGjMuD#u5jvzY7x7|w2UDO zz|(6x&9ZHy8y_Ok80CB(t4_Stu{}pKXcq@$im&QltgeopiOBlpI0_nd+@XhT!u8ZP zS@G^#ioBR-@3K4Bx$@DOH2e8ejE{M8Ymf7*PyPOWSxZ#UZ-q#m$$B;1g16XF(sx7^ zQHg!ltG;9sJeRdotG=L2RAXt`foeBz6imgDS$THn8ZXJ<$}xL@G0o1294cY%mEW6H zFV|n+hm7Hb8Ob6R+q7g{8ztj&u%RT|SxKJ)lM$9Y#F!NY*Xn+~k@GB!WoEJ37ExAZ z=be8@Y+AQj7qq9$U$2H*iVT@*DBOvzlm$4wq#t-Lv;PX`-NnoO=ChIUNA^yHp$SpekvYn}9Z4ovu4WSNrzdCMR{hK@ z$+RF4zK5w{pmC1Mor#8yvX*AQ#{4BMZARbEs$VdW{TV!q6}3Px@x{X*}& zx8PPxja~pxL_gz0dhA7hNC=6oipV*-41M8Fr;I*dP_a_BXg59^(l z=y9)FFsJ3*Se<7$dxx&RGZIgZ*mLm7ELW=CH?bmdl|kF^bjz3_@U?kVy z39UProNc?!BUtwE++NJ08wl{}3Q!4l!vxN98y8ls=6xlS&9;>^G4<|IRv`|Z0b_2( z=vnPWcaTf;VCjx~|2{&a*;d+ZUo7}!g`6?2BZFqveDpFqN%}YPiiN}S=1#2FduENp zS>|#5#=ky&ys&;&!?!*=f0pk|wAW}sef9&gGDke1MRQH#TkT;9*1Nb4M%GV~q`u_I zBbk)lCnE&Ao>Xq{Z}8bTCos#&F0L~;8vaa9;CeHa>wuzF_Cj{NW@SRICsMy(u+p-S z1z6k78ngXaf1nfZ#D{UjC`i}K#1*>B#5s?4(JX&`_t+i;vg^{3;tb{@Z({>l&ef=n zJ^msFnjDv`WD2q;9LZlW<~Kb5QEA8i8rr<9|2X5riaYP3^V*eqikr;KIB-htk0+8R zu?B67dn(-IqpM3_#G@INmW=hgx z68p6D9^whMX-0Uo_#y0Q-c>^GCId4UBlCY>ce&?+=gdOUf)+B%ddy__>{N=k{WS{g zyT8t~UX2a05;B^};#=lIZ~|zQ-O-X&T|W~!{APs#5BJ;Vl1Zqf!IHI}OhV*3A9Yp| zWJPx(4XtxBozL0#Y0sX=^zfG_VHiC;F;=BtEfxFcHA?1M3Y4&HVJo&J(%7>O(oOU>_|Q0`g6{6+h5_W-v3u|{G&kY4yrEBY2lWN*t7Eyj#U zCn~Und4YN2+Ah}g=9yp-{Lg1AxDr2_U6T`IIsFF;N1d=zKgVmdg9frkv+dVQY}_u{ zvg$bIr!`As+qBG_f-B(?@EyEZd4x@oah`dFO&dSh8Lq`n`#BE%(81>f+pBm2tIWGi zTAXzwWHRPKVV;QQE^C{%hx^7~)b%-njR$-IcRPQ8Ly1oO(0U?y;(hj8NBit2?rtl< z@ofj9ol`KGzc(lP*SXpsY8$W2o@nO6gQJ97NzNNlBocl2XwK?H$Xv_d5xf=F?YPBe zX4PakcLKl+nreGuqF0|iiRW4WJ}ImWSzcD9 zV3s^5?p1rN zlv$!x9(J4~iO^1Fu{g(cTe=4t&ok7ukM9HTF$KCNKFEKYj8YD{?+r1O}Tm zjGwOU(w>SBEw(#)-uvsE&TCuzT=`?uwQahR__6YV^;jxk?9;5|TBWS$yiH4T50S_j zB6Qvt(?%H#4_|$GW@|h}Hso(OjP@Mk+T8l5>X)~#$?yFaAu`ss0 z)bk?A-?rx@R5VE(f{mvOQd!~Ue3Z3PGO#uFh&+1D-R{1_*883uKi-AFw2?_9@dxG4Q6tuD9B@FvwQB=Tg|t-M~uKM zNvpY*a9N#TDLH*U6UP14cD;JUH5jr-%6>7sBCuFmbQMM1B(up~+5rm%TlkJRvl5xL zP}^}$M1=Ds!MrL0)1^l}u&)Z+q83b8S8D5ZWq_n}Wzc9nUF?3NtfH07tw^$7UBqt5 zq1Z__SI)6_e4*X>nLN(ZgvACmiuVy|#CZ3F4UvER`y${8Pq1IJ)jP;LzhZ7ovK|83 z8K-^3S_mh9oYUB+*-r+bch-RV4yx8UX85cnM&8PEvCa>`#<&+Y##s10XTV2$%2Tk1 z`2h*-@z7kYz5C(Lzlr^qx+huWZ)JD1O|;6wv1PDsjk5TBL3VbS?2-EKVOil&t2;{# zKHCVXiLTK?el{msPcU1<)2`4kuSRpN>uB5qO7d2IT7%cIf=|^cdmdi3pE(|EjF!*1 z=rQg_GUB){iC3eYUgcXDaDIOg_a!D++jV9!GHW7d-USgg$)m3Jz$)`RHLT*e%v2fA ztkbJ&SkLI($1Qv}M$?u#a(AL3D;P$z?1gMbP|wg9SB>-RHhu4}PQ!tCmFUepyLT3_ z1(Kqnv9NFT1pDXBJAXeC;rK@!5e3=|SzRma$hlSHK3_&2YoUh=^7y;g`a7C}4lIqt zYwjdUM;^->uSmh#tk#kX=tFiCZ_acpQYE>js>ZKr-yqaqRq&YjYgWc%0)ilK082 z`TIlh+ZOW#q`Z2i-YMIj0$-qu(+;46Dpmf{Z+O(x3_gK_EUitSi+osj&r-F0*L;rl z_i7vw&uEbX8G7f2tFxrW8wdnXc$j<9Ke05QvdFi#ms!MBkeYlzuJj3HrL|rHH(MFZ z;B#wiIIjx9@bVI4jm5=AbxS9WmuZPu%KSdPP@op<4n_B~H(bB^%S z9naeHEOOpdKfgnpH__i*zP(!i=N-n}cYQ&}z2%vHpY=bk`yVXt6y|ww^uE6PpY{E5 zJ<)x=>h8qc-1|F6jEn@lxB1F2g72c|ZyN9|?>?Nyni-J={Q4T-Upa{$M&cgr)6_`SOM0ho=??-^`Odr3CXO<6t%ScAhWw_wACQ zv*F0aiHh-zl3LTpShK66*qD7x-^6je1HZUB^tKpcj&^6^7$c3I$x4hj=E?SuJcZTB zG}PMcrLm$q{(Z~yPjz9Pk^S%jx`gkNQOI%cmW|;(dmQn1^=v=qMvcyiRPf|%oBrT_ zxtgBk9nY;T))=(U=sU-So!wyJ&%!K<&-KA77=r-%8*@<@Ppr@Pv$H{*f=Nge2PfDUhSPtna|Pdxb8IPi%CcO z>ycbYWQ;cN^9*aty)EX5XLp4Tp^~v@L~M5~VjU|I*I+WQ+1kr*u$#{l%9}w2IN|2THvUCnIL4>z!`-tETmM9dtYlzG@It&%G3MM;=KA~Xb#16r zu9gdv7#COLH$j$pfrRgEU5rFO4f0zHQ;W6^u~1c%p{hh+@_Va~*row=CIJ!R5!* z*87+vF~&20pcZ>}MzYQ@zMW$rOV2SfKSAEUI@T-nsYmGRW@&l2_F^@1YoAo^NQ&;g zDyp5dJ-^R;x>>6jy<#86WMXvdB_xHL+3jhq&^$Al@k#OT7r(%dS=Y@zCN&t>%;ZE2 z*^XM}T3v7C>REfpJP1q7wPJJE7A;^Zb9mnf4<9j4O6ALQOpN-luFg1OByBiaYCnE| zE{?!G`v^!dYsKhe1srL%GKMc$vC96U_!A+GvabBh)~P%7gH~9?Id;Gzo;4sYxk~NBo|Vt#?_;&j%3EH$w(JmgBtJdFr9SL<|G6wiKl{=9oBGBm zcXi?IP<$~LAByA4VhZH&?r>zZRxr!It%b?W#^j+ouO-6UBN}6M=5zb%#Ev%j^OtaM z_HM@$YcK)WAxdFDxr*3yZ2{kg&ACdO_Gv#;1x82ib(cCb6>~jUX5X6=?q)Jr^0X*G#&cs=L+^(_yv%dLXbroykJO0L)YfEM$Gj4l|-LdhUxAMkXpokSq z*$Gd(nwTqi&DkRnOe;A+6!3FBCmC1FuAV*Ff4ul1GnDoGL`=a)Fl*-K+TSSI&Ua__ zGTSoW8rNBp6-S-mQ{%m7#_|t(t>?y!4wkIOsSid}VB--L;X-Oc<~A^USKjakUZd4K zBiPPrjLE}M)pMuwMoP^DBQr9UE;CAc*Nd_!*_GA!W!LD)3>*Bk?J{4Ws>3Ga%0Br! zYh>1jnS3kW_$Is2f_Nwvq|Z@r-%mjtSd)Riyt9AHRAkM}C(S^-QQEuBO?cwjat*oh zMe7Ex`>w0Yw}ii1dkehhsiQmOG6$MpQ+aFxbXCiu?)!IWp ztvz@#4p|xP^*)g3OhrEAR7cLwcFpOWaa@(*6yp{Nov&d(bT+byt^HBdw!j1L)-(K| ztZTcA^#P-OnuvRoKhM{5DRJ~(TRkI^A%|H^o~32jh?K>CT?I|(8T*hPD@I@ zx2p6B0OuCn;@YAKcTumA=ljT_RNXD@R4iD<9bZ;u{k7b6^;*9%=t2#v7t27Yv#iCWuvtv&&bv>u%X@s zC%zpsI|g$F=(-*wI?_1nw_XPWA|9O6Yt|bR^K$!n(T(guw!Ezl=3wxXoRepT7}1!b zCHAB`*w4EET!!hK^sx4Zephq!_v;-6zpoklhxHrhrHJU??*6T2?#$$Qqj&EHldu0T Dis}f- literal 0 HcmV?d00001 diff --git a/dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/LA_tr b/dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/LA_tr new file mode 100755 index 0000000000000000000000000000000000000000..c80dafb18df068e43f68a2464fea5912758b663d GIT binary patch literal 62848 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 F{x1YhK_dVF literal 0 HcmV?d00001 diff --git a/dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/LA_zh_TW b/dev/com.ibm.ws.product.utility_fat/publish/files/lafiles/LA_zh_TW new file mode 100755 index 0000000000000000000000000000000000000000..9f95d22b82e3739697598d01900dfe8bab3ad2ba GIT binary patch literal 17838 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