From 9be6e994ba0a0c92f77948d3d1e1b63a6d2f38f6 Mon Sep 17 00:00:00 2001 From: Andrew Rouse Date: Wed, 13 Nov 2024 15:28:04 +0000 Subject: [PATCH 01/67] CDI: Update to Weld 6 CR1 --- .../check_this_in_if_it_changes/pom.xml | 6 +- dev/cnf/oss_dependencies.maven | 6 +- .../cdi-4.1/io.openliberty.cdi-4.1.feature | 4 +- dev/io.openliberty.cdi.4.1.thirdparty/bnd.bnd | 4 +- dev/io.openliberty.org.jboss.weld6/bnd.bnd | 2 +- .../build.gradle | 4 +- .../check-me-in-if-i-change.bnd | 183 +++++++++--------- 7 files changed, 104 insertions(+), 105 deletions(-) diff --git a/dev/cnf/dependabot/check_this_in_if_it_changes/pom.xml b/dev/cnf/dependabot/check_this_in_if_it_changes/pom.xml index 224651e778a..ed1afa3fdb3 100644 --- a/dev/cnf/dependabot/check_this_in_if_it_changes/pom.xml +++ b/dev/cnf/dependabot/check_this_in_if_it_changes/pom.xml @@ -3944,7 +3944,7 @@ org.jboss.weld.environment weld-environment-common - 6.0.0.Beta1 + 6.0.0.CR1 org.jboss.weld.se @@ -3964,7 +3964,7 @@ org.jboss.weld.se weld-se-core - 6.0.0.Beta1 + 6.0.0.CR1 org.jboss.weld @@ -3989,7 +3989,7 @@ org.jboss.weld weld-osgi-bundle - 6.0.0.Beta1 + 6.0.0.CR1 org.jetbrains.kotlin diff --git a/dev/cnf/oss_dependencies.maven b/dev/cnf/oss_dependencies.maven index e87f33ab480..dbf2cf840c6 100644 --- a/dev/cnf/oss_dependencies.maven +++ b/dev/cnf/oss_dependencies.maven @@ -784,16 +784,16 @@ org.jboss.shrinkwrap:shrinkwrap-api:1.2.3 org.jboss.shrinkwrap:shrinkwrap-impl-base:1.2.3 org.jboss.shrinkwrap:shrinkwrap-spi:1.2.3 org.jboss.weld.environment:weld-environment-common:5.1.1.SP2 -org.jboss.weld.environment:weld-environment-common:6.0.0.Beta1 +org.jboss.weld.environment:weld-environment-common:6.0.0.CR1 org.jboss.weld.se:weld-se-core:3.1.9.Final org.jboss.weld.se:weld-se-core:4.0.3.Final org.jboss.weld.se:weld-se-core:5.1.1.SP2 -org.jboss.weld.se:weld-se-core:6.0.0.Beta1 +org.jboss.weld.se:weld-se-core:6.0.0.CR1 org.jboss.weld:weld-osgi-bundle:2.4.8.Final org.jboss.weld:weld-osgi-bundle:3.1.9.Final org.jboss.weld:weld-osgi-bundle:4.0.3.Final org.jboss.weld:weld-osgi-bundle:5.1.1.SP2 -org.jboss.weld:weld-osgi-bundle:6.0.0.Beta1 +org.jboss.weld:weld-osgi-bundle:6.0.0.CR1 org.jetbrains.kotlin:kotlin-stdlib-common:1.9.0 org.jetbrains.kotlin:kotlin-stdlib:1.9.0 org.jetbrains:annotations:13.0 diff --git a/dev/com.ibm.websphere.appserver.features/visibility/public/cdi-4.1/io.openliberty.cdi-4.1.feature b/dev/com.ibm.websphere.appserver.features/visibility/public/cdi-4.1/io.openliberty.cdi-4.1.feature index 0e83135366d..8de091c5ac4 100644 --- a/dev/com.ibm.websphere.appserver.features/visibility/public/cdi-4.1/io.openliberty.cdi-4.1.feature +++ b/dev/com.ibm.websphere.appserver.features/visibility/public/cdi-4.1/io.openliberty.cdi-4.1.feature @@ -55,7 +55,7 @@ Subsystem-Name: Jakarta Contexts and Dependency Injection 4.1 io.openliberty.org.jboss.weld6.se, \ com.ibm.ws.org.jboss.jdeparser.1.0.0, \ com.ibm.ws.managedobject, \ - io.openliberty.org.jboss.logging35, \ + io.openliberty.org.jboss.logging36, \ io.openliberty.org.jboss.classfilewriter.1.3, \ com.ibm.ws.cdi.weld.jakarta, \ com.ibm.ws.cdi.internal.jakarta, \ @@ -64,7 +64,7 @@ Subsystem-Name: Jakarta Contexts and Dependency Injection 4.1 com.ibm.ws.cdi.interfaces.jakarta, \ io.openliberty.cdi.4.0.internal.interfaces, \ io.openliberty.cdi.spi; location:="dev/spi/ibm/,lib/" --jars=io.openliberty.cdi.4.1.thirdparty; location:="dev/api/third-party/,lib/"; mavenCoordinates="org.jboss.weld:weld-osgi-bundle:6.0.0.Beta1" +-jars=io.openliberty.cdi.4.1.thirdparty; location:="dev/api/third-party/,lib/"; mavenCoordinates="org.jboss.weld:weld-osgi-bundle:6.0.0.CR1" -files=dev/api/ibm/schema/ibm-managed-bean-bnd_1_0.xsd, \ dev/api/ibm/schema/ibm-managed-bean-bnd_1_1.xsd, \ dev/spi/ibm/javadoc/io.openliberty.cdi.spi_1.1-javadoc.zip diff --git a/dev/io.openliberty.cdi.4.1.thirdparty/bnd.bnd b/dev/io.openliberty.cdi.4.1.thirdparty/bnd.bnd index 143f1fef9c1..e864adbd74b 100644 --- a/dev/io.openliberty.cdi.4.1.thirdparty/bnd.bnd +++ b/dev/io.openliberty.cdi.4.1.thirdparty/bnd.bnd @@ -20,8 +20,8 @@ Bundle-SymbolicName: io.openliberty.cdi.4.1.thirdparty Bundle-Description: WebSphere CDI 4.1 Weld Third Party API Export-Package:\ - org.jboss.weld.context;version=6.0.0.Beta1, \ - org.jboss.weld.context.*;version=6.0.0.Beta1 + org.jboss.weld.context;version=6.0.0.CR1, \ + org.jboss.weld.context.*;version=6.0.0.CR1 Import-Package:* diff --git a/dev/io.openliberty.org.jboss.weld6/bnd.bnd b/dev/io.openliberty.org.jboss.weld6/bnd.bnd index e832585a99d..b534ee5c70b 100644 --- a/dev/io.openliberty.org.jboss.weld6/bnd.bnd +++ b/dev/io.openliberty.org.jboss.weld6/bnd.bnd @@ -32,4 +32,4 @@ instrument.disabled: true ../build.sharedResources/lib/junit/old/junit.jar;version=file, \ com.ibm.ws.junit.extensions;version=latest,\ io.openliberty.jakarta.cdi.4.1;version=latest,\ - io.openliberty.org.jboss.logging35;version=latest + io.openliberty.org.jboss.logging36;version=latest diff --git a/dev/io.openliberty.org.jboss.weld6/build.gradle b/dev/io.openliberty.org.jboss.weld6/build.gradle index 47faddfaf14..8c299799470 100644 --- a/dev/io.openliberty.org.jboss.weld6/build.gradle +++ b/dev/io.openliberty.org.jboss.weld6/build.gradle @@ -11,7 +11,7 @@ import java.util.List; import java.util.stream.Collectors; ////// Update me when updating weld //// -def weldVersion = "6.0.0.Beta1" //// +def weldVersion = "6.0.0.CR1" //// //////////////////////////////////////// def unzippDir = "${buildDir}/unzip" @@ -35,9 +35,7 @@ def additionalExports = """\ """ def additionalImports = """\ - javax.security.auth,\\\\ jakarta.xml.ws;version="[4.0,5)",\\\\ - jakarta.servlet.descriptor,\\\\ """ // Key is a property, value is an addition. diff --git a/dev/io.openliberty.org.jboss.weld6/check-me-in-if-i-change.bnd b/dev/io.openliberty.org.jboss.weld6/check-me-in-if-i-change.bnd index 0ca8d36fa26..4e268128099 100644 --- a/dev/io.openliberty.org.jboss.weld6/check-me-in-if-i-change.bnd +++ b/dev/io.openliberty.org.jboss.weld6/check-me-in-if-i-change.bnd @@ -51,99 +51,98 @@ Service-Component: \ # Automatically filled in by build.gradle Export-Package: \ - org.jboss.weldx.transaction;version="6.0.0.Beta1",\ - org.jboss.weld.bean.proxy.util;version="6.0.0.Beta1",\ - org.jboss.weld.annotated.enhanced;version="6.0.0.Beta1",\ - org.jboss.weld.executor;version="6.0.0.Beta1",\ - org.jboss.weld.metadata;version="6.0.0.Beta1",\ - org.jboss.weld.resolution;version="6.0.0.Beta1",\ - org.jboss.weld.resources;version="6.0.0.Beta1",\ - org.jboss.weld.util.collections;version="6.0.0.Beta1",\ - org.jboss.weld.bootstrap.api;version="6.0.0.Beta1";uses:="jakarta.enterprise.inject.spi,org.jboss.weld.bootstrap.spi,org.jboss.weld.manager.api",\ - org.jboss.weld.bootstrap.api.helpers;version="6.0.0.Beta1";uses:="org.jboss.weld.bootstrap.api,org.jboss.weld.bootstrap.spi,org.jboss.weld.manager.api",\ - org.jboss.weld.construction.api;version="6.0.0.Beta1";uses:="jakarta.enterprise.context.spi,jakarta.enterprise.inject.spi",\ - org.jboss.weld.context.api;version="6.0.0.Beta1";uses:="jakarta.enterprise.context.spi",\ - org.jboss.weld.ejb.api;version="6.0.0.Beta1",\ - org.jboss.weld.manager.api;version="6.0.0.Beta1";uses:="jakarta.enterprise.context.spi,jakarta.enterprise.inject,jakarta.enterprise.inject.spi,jakarta.enterprise.inject.spi.el,org.jboss.weld.bootstrap.api,org.jboss.weld.construction.api,org.jboss.weld.context,org.jboss.weld.ejb.spi,org.jboss.weld.serialization.spi",\ - org.jboss.weld.servlet.api;version="6.0.0.Beta1";uses:="jakarta.servlet,jakarta.servlet.http",\ - org.jboss.weld.servlet.api.helpers;version="6.0.0.Beta1";uses:="jakarta.servlet,jakarta.servlet.http,org.jboss.weld.servlet.api",\ - org.jboss.weld.bootstrap.spi;version="6.0.0.Beta1";uses:="jakarta.enterprise.inject.spi,org.jboss.weld.bootstrap.api,org.jboss.weld.ejb.spi",\ - org.jboss.weld.bootstrap.spi.helpers;version="6.0.0.Beta1";uses:="org.jboss.weld.bootstrap.api,org.jboss.weld.bootstrap.spi,org.jboss.weld.ejb.spi",\ - org.jboss.weld.configuration.spi;version="6.0.0.Beta1";uses:="org.jboss.weld.bootstrap.api",\ - org.jboss.weld.configuration.spi.helpers;version="6.0.0.Beta1";uses:="org.jboss.weld.configuration.spi",\ - org.jboss.weld.ejb.spi;version="6.0.0.Beta1";uses:="jakarta.enterprise.inject.spi,org.jboss.weld.bootstrap.api,org.jboss.weld.ejb.api",\ - org.jboss.weld.ejb.spi.helpers;version="6.0.0.Beta1";uses:="org.jboss.weld.ejb.api,org.jboss.weld.ejb.spi",\ - org.jboss.weld.injection.spi;version="6.0.0.Beta1";uses:="jakarta.enterprise.inject.spi,jakarta.persistence,org.jboss.weld.bootstrap.api",\ - org.jboss.weld.injection.spi.helpers;version="6.0.0.Beta1";uses:="jakarta.annotation,jakarta.enterprise.inject.spi,jakarta.persistence,javax.naming,org.jboss.weld.bootstrap.api,org.jboss.weld.injection.spi",\ - org.jboss.weld.interceptor.spi.metadata;version="6.0.0.Beta1";uses:="jakarta.enterprise.context.spi,org.jboss.weld.interceptor.proxy,org.jboss.weld.interceptor.spi.model,org.jboss.weld.manager",\ - org.jboss.weld.interceptor.spi.model;version="6.0.0.Beta1";uses:="jakarta.enterprise.inject.spi,org.jboss.weld.interceptor.spi.metadata",\ - org.jboss.weld.resources.spi;version="6.0.0.Beta1";uses:="org.jboss.weld.bootstrap.api",\ - org.jboss.weld.resources.spi.helpers;version="6.0.0.Beta1";uses:="org.jboss.weld.resources.spi",\ - org.jboss.weld.security.spi;version="6.0.0.Beta1";uses:="org.jboss.weld.bootstrap.api",\ - org.jboss.weld.serialization.spi;version="6.0.0.Beta1";uses:="jakarta.enterprise.context.spi,org.jboss.weld.bootstrap.api,org.jboss.weld.serialization.spi.helpers",\ - org.jboss.weld.serialization.spi.helpers;version="6.0.0.Beta1";uses:="jakarta.enterprise.context.spi,org.jboss.weld.context.api",\ - org.jboss.weld.servlet.spi;version="6.0.0.Beta1";uses:="jakarta.servlet.http,org.jboss.weld.bootstrap.api",\ - org.jboss.weld.servlet.spi.helpers;version="6.0.0.Beta1";uses:="jakarta.servlet.http,org.jboss.weld.servlet.spi",\ - org.jboss.weld.transaction.spi;version="6.0.0.Beta1";uses:="jakarta.transaction,org.jboss.weld.bootstrap.api",\ - org.jboss.weld.bootstrap.event;version="6.0.0.Beta1";uses:="jakarta.enterprise.context.spi,jakarta.enterprise.inject,jakarta.enterprise.inject.spi,jakarta.enterprise.inject.spi.configurator,jakarta.enterprise.util,jakarta.interceptor",\ - org.jboss.weld.context;version="6.0.0.Beta1";uses:="jakarta.enterprise.context,jakarta.enterprise.context.spi,org.jboss.weld.context.api",\ - org.jboss.weld.context.activator;version="6.0.0.Beta1";uses:="jakarta.enterprise.util,jakarta.interceptor",\ - org.jboss.weld.context.bound;version="6.0.0.Beta1";uses:="jakarta.enterprise.util,jakarta.inject,org.jboss.weld.context",\ - org.jboss.weld.context.ejb;version="6.0.0.Beta1";uses:="jakarta.enterprise.util,jakarta.inject,jakarta.interceptor,org.jboss.weld.context",\ - org.jboss.weld.context.http;version="6.0.0.Beta1";uses:="jakarta.enterprise.util,jakarta.inject,jakarta.servlet.http,org.jboss.weld.context",\ - org.jboss.weld.context.unbound;version="6.0.0.Beta1";uses:="jakarta.enterprise.util,jakarta.inject",\ - org.jboss.weld.events;version="6.0.0.Beta1";uses:="jakarta.enterprise.event,jakarta.enterprise.util",\ - org.jboss.weld.inject;version="6.0.0.Beta1";uses:="jakarta.enterprise.inject,jakarta.enterprise.inject.spi,jakarta.enterprise.util",\ - org.jboss.weld.interceptor;version="6.0.0.Beta1";uses:="jakarta.interceptor",\ - org.jboss.weld.proxy;version="6.0.0.Beta1";uses:="jakarta.enterprise.inject.spi",\ - org.jboss.weld.lite.extension.translator;version="6.0.0.Beta1";uses:="jakarta.annotation,jakarta.enterprise.event,jakarta.enterprise.inject.build.compatible.spi,jakarta.enterprise.inject.spi,jakarta.enterprise.lang.model,jakarta.enterprise.lang.model.declarations",\ - org.jboss.weld.lite.extension.translator.logging;version="6.0.0.Beta1";uses:="org.jboss.logging,org.jboss.weld.exceptions",\ - org.jboss.weld.lite.extension.translator.util;version="6.0.0.Beta1",\ - org.jboss.weld.lite.extension.translator.util.reflection;version="6.0.0.Beta1",\ - org.jboss.weld.module.ejb;version="6.0.0.Beta1";uses:="jakarta.enterprise.context.spi,jakarta.interceptor,org.jboss.weld.bean,org.jboss.weld.bean.proxy,org.jboss.weld.context.ejb,org.jboss.weld.manager,org.jboss.weld.module",\ - org.jboss.weld.module.ejb.context;version="6.0.0.Beta1";uses:="jakarta.interceptor,org.jboss.weld.context.ejb,org.jboss.weld.contexts",\ - org.jboss.weld.module.ejb.context.beanstore;version="6.0.0.Beta1";uses:="jakarta.interceptor,org.jboss.weld.contexts.beanstore",\ - org.jboss.weld.module.jsf;version="6.0.0.Beta1";uses:="jakarta.faces.application,jakarta.faces.context,org.jboss.weld.bootstrap.api,org.jboss.weld.module,org.jboss.weld.resources.spi,org.jboss.weld.util",\ - org.jboss.weld.module.jsf.servlet;version="6.0.0.Beta1";uses:="jakarta.servlet",\ - org.jboss.weld.module.jta;version="6.0.0.Beta1";uses:="org.jboss.weld.module",\ - org.jboss.weld.module.web;version="6.0.0.Beta1";uses:="jakarta.enterprise.context.spi,jakarta.enterprise.inject.spi,jakarta.servlet,jakarta.servlet.http,org.jboss.weld.bean.builtin,org.jboss.weld.manager,org.jboss.weld.module",\ - org.jboss.weld.module.web.context.beanstore.http;version="6.0.0.Beta1";uses:="jakarta.servlet.http,org.jboss.weld.bootstrap.api,org.jboss.weld.context.api,org.jboss.weld.contexts.beanstore,org.jboss.weld.serialization.spi",\ - org.jboss.weld.module.web.context.http;version="6.0.0.Beta1";uses:="jakarta.enterprise.context,jakarta.servlet.http,org.jboss.weld.bootstrap.api,org.jboss.weld.context.http,org.jboss.weld.contexts,org.jboss.weld.contexts.beanstore",\ - org.jboss.weld.module.web.el;version="6.0.0.Beta1";uses:="jakarta.el,org.jboss.weld.manager,org.jboss.weld.module.web.util.el",\ - org.jboss.weld.module.web.logging;version="6.0.0.Beta1";uses:="org.jboss.logging,org.jboss.weld.exceptions,org.jboss.weld.logging,org.jboss.weld.module.web.servlet",\ - org.jboss.weld.module.web.servlet;version="6.0.0.Beta1";uses:="jakarta.servlet,jakarta.servlet.http,org.jboss.weld.bootstrap.api,org.jboss.weld.context.http,org.jboss.weld.manager,org.jboss.weld.resources.spi,org.jboss.weld.servlet.api.helpers,org.jboss.weld.servlet.spi,org.jboss.weld.util",\ - org.jboss.weld.module.web.util.el;version="6.0.0.Beta1";uses:="jakarta.el",\ - org.jboss.weld.module.web.util.servlet;version="6.0.0.Beta1";uses:="jakarta.servlet,org.jboss.weld.manager,org.jboss.weld.servlet.spi",\ - org.jboss.weld;version="6.0.0.Beta1";uses:="jakarta.enterprise.inject,jakarta.enterprise.inject.spi,jakarta.enterprise.util,org.jboss.weld.bean.builtin,org.jboss.weld.bootstrap,org.jboss.weld.bootstrap.api,org.jboss.weld.bootstrap.spi,org.jboss.weld.inject,org.jboss.weld.manager",\ - org.jboss.weld.bean;version="6.0.0.Beta1";uses:="jakarta.enterprise.context.spi,jakarta.enterprise.inject.spi,jakarta.interceptor,org.jboss.weld.bootstrap,org.jboss.weld.bootstrap.api,org.jboss.weld.ejb.spi,org.jboss.weld.interceptor.spi.metadata,org.jboss.weld.interceptor.spi.model,org.jboss.weld.manager,org.jboss.weld.serialization.spi",\ - org.jboss.weld.bean.builtin;version="6.0.0.Beta1";uses:="jakarta.enterprise.context,jakarta.enterprise.context.control,jakarta.enterprise.context.spi,jakarta.enterprise.event,jakarta.enterprise.inject,jakarta.enterprise.inject.spi,jakarta.enterprise.util,org.jboss.weld.bean,org.jboss.weld.bean.proxy,org.jboss.weld.bootstrap,org.jboss.weld.bootstrap.api,org.jboss.weld.bootstrap.spi,org.jboss.weld.construction.api,org.jboss.weld.contexts,org.jboss.weld.ejb.spi,org.jboss.weld.inject,org.jboss.weld.injection,org.jboss.weld.manager,org.jboss.weld.manager.api,org.jboss.weld.serialization.spi,org.jboss.weld.util",\ - org.jboss.weld.bean.proxy;version="6.0.0.Beta1";uses:="jakarta.enterprise.context.spi,jakarta.enterprise.inject.spi,org.jboss.classfilewriter,org.jboss.classfilewriter.code,org.jboss.weld.bootstrap.api,org.jboss.weld.bootstrap.api.helpers,org.jboss.weld.config,org.jboss.weld.contexts.cache,org.jboss.weld.exceptions,org.jboss.weld.interceptor.proxy,org.jboss.weld.interceptor.spi.model,org.jboss.weld.interceptor.util.proxy,org.jboss.weld.manager,org.jboss.weld.proxy,org.jboss.weld.serialization.spi,org.jboss.weld.serialization.spi.helpers",\ - org.jboss.weld.bootstrap;version="6.0.0.Beta1";uses:="jakarta.enterprise.context.spi,jakarta.enterprise.inject.spi,org.jboss.weld.bean,org.jboss.weld.bean.builtin,org.jboss.weld.bootstrap.api,org.jboss.weld.bootstrap.api.helpers,org.jboss.weld.bootstrap.spi,org.jboss.weld.event,org.jboss.weld.exceptions,org.jboss.weld.logging,org.jboss.weld.manager,org.jboss.weld.manager.api,org.jboss.weld.module,org.jboss.weld.resources.spi",\ - org.jboss.weld.config;version="6.0.0.Beta1";uses:="org.jboss.weld.bootstrap.api,org.jboss.weld.bootstrap.spi",\ - org.jboss.weld.contexts;version="6.0.0.Beta1";uses:="jakarta.enterprise.context,jakarta.enterprise.context.spi,org.jboss.weld.bootstrap.api,org.jboss.weld.construction.api,org.jboss.weld.context,org.jboss.weld.context.api,org.jboss.weld.contexts.beanstore,org.jboss.weld.contexts.conversation,org.jboss.weld.injection.spi,org.jboss.weld.interceptor.proxy,org.jboss.weld.serialization.spi,org.jboss.weld.serialization.spi.helpers",\ - org.jboss.weld.contexts.activator;version="6.0.0.Beta1";uses:="jakarta.annotation,jakarta.enterprise.context.control,jakarta.enterprise.inject,jakarta.inject,jakarta.interceptor,org.jboss.weld.context,org.jboss.weld.context.activator,org.jboss.weld.context.unbound,org.jboss.weld.event,org.jboss.weld.manager",\ - org.jboss.weld.contexts.beanstore;version="6.0.0.Beta1";uses:="org.jboss.weld.context.api,org.jboss.weld.serialization.spi",\ - org.jboss.weld.contexts.bound;version="6.0.0.Beta1";uses:="org.jboss.weld.bootstrap.api,org.jboss.weld.context.bound,org.jboss.weld.contexts,org.jboss.weld.contexts.beanstore",\ - org.jboss.weld.contexts.cache;version="6.0.0.Beta1",\ - org.jboss.weld.contexts.conversation;version="6.0.0.Beta1";uses:="jakarta.inject,org.jboss.weld.context,org.jboss.weld.manager",\ - org.jboss.weld.contexts.unbound;version="6.0.0.Beta1";uses:="jakarta.enterprise.context,jakarta.enterprise.context.spi,org.jboss.weld.context,org.jboss.weld.context.api,org.jboss.weld.contexts,org.jboss.weld.serialization.spi",\ - org.jboss.weld.event;thread-context=true;version="6.0.0.Beta1";uses:="jakarta.enterprise.context.spi,jakarta.enterprise.event,jakarta.enterprise.inject.spi,jakarta.enterprise.util,org.jboss.weld.bean,org.jboss.weld.bean.builtin,org.jboss.weld.bootstrap.api,org.jboss.weld.events,org.jboss.weld.injection,org.jboss.weld.manager,org.jboss.weld.module,org.jboss.weld.util",\ - org.jboss.weld.exceptions;version="6.0.0.Beta1";uses:="jakarta.enterprise.inject,jakarta.enterprise.inject.spi",\ - org.jboss.weld.injection;version="6.0.0.Beta1";uses:="jakarta.enterprise.context.spi,jakarta.enterprise.inject.spi,jakarta.enterprise.inject.spi.configurator,org.jboss.weld.bootstrap.api,org.jboss.weld.injection.spi,org.jboss.weld.manager",\ - org.jboss.weld.interceptor.proxy;version="6.0.0.Beta1";uses:="jakarta.enterprise.context.spi,jakarta.enterprise.inject.spi,jakarta.interceptor,org.jboss.weld.bean.proxy,org.jboss.weld.interceptor,org.jboss.weld.interceptor.spi.metadata,org.jboss.weld.interceptor.spi.model,org.jboss.weld.manager,org.jboss.weld.util",\ - org.jboss.weld.interceptor.util.proxy;version="6.0.0.Beta1";uses:="org.jboss.weld.bean.proxy",\ - org.jboss.weld.logging;version="6.0.0.Beta1";uses:="jakarta.enterprise.context.spi,jakarta.enterprise.inject.spi,javax.naming,org.jboss.logging,org.jboss.weld.contexts,org.jboss.weld.exceptions",\ - org.jboss.weld.manager;version="6.0.0.Beta1";uses:="jakarta.el,jakarta.enterprise.context.spi,jakarta.enterprise.event,jakarta.enterprise.inject,jakarta.enterprise.inject.spi,jakarta.enterprise.inject.spi.configurator,org.jboss.weld.bean,org.jboss.weld.bean.proxy,org.jboss.weld.bootstrap.api,org.jboss.weld.bootstrap.spi,org.jboss.weld.construction.api,org.jboss.weld.contexts,org.jboss.weld.ejb.spi,org.jboss.weld.event,org.jboss.weld.events,org.jboss.weld.inject,org.jboss.weld.interceptor.spi.model,org.jboss.weld.manager.api,org.jboss.weld.serialization.spi",\ - org.jboss.weld.module;version="6.0.0.Beta1";uses:="jakarta.el,jakarta.enterprise.context.spi,jakarta.enterprise.inject.spi,org.jboss.weld.bean,org.jboss.weld.bean.builtin,org.jboss.weld.bootstrap,org.jboss.weld.bootstrap.api,org.jboss.weld.bootstrap.spi,org.jboss.weld.ejb.spi,org.jboss.weld.event,org.jboss.weld.manager",\ - org.jboss.weld.security;version="6.0.0.Beta1";uses:="org.jboss.weld.security.spi",\ - org.jboss.weld.util;version="6.0.0.Beta1";uses:="jakarta.el,jakarta.enterprise.context.spi,jakarta.enterprise.event,jakarta.enterprise.inject,jakarta.enterprise.inject.spi,jakarta.enterprise.inject.spi.el,jakarta.enterprise.util,jakarta.interceptor,org.jboss.weld.bean,org.jboss.weld.bootstrap,org.jboss.weld.bootstrap.api,org.jboss.weld.bootstrap.spi,org.jboss.weld.exceptions,org.jboss.weld.inject,org.jboss.weld.injection,org.jboss.weld.interceptor.spi.model,org.jboss.weld.manager,org.jboss.weld.resources.spi,org.jboss.weld.serialization.spi",\ - org.jboss.weld.xml;version="6.0.0.Beta1";uses:="org.jboss.weld.bootstrap.spi,org.xml.sax,org.xml.sax.helpers" + org.jboss.weldx.transaction;version="6.0.0.CR1",\ + org.jboss.weld.bean.proxy.util;version="6.0.0.CR1",\ + org.jboss.weld.annotated.enhanced;version="6.0.0.CR1",\ + org.jboss.weld.executor;version="6.0.0.CR1",\ + org.jboss.weld.metadata;version="6.0.0.CR1",\ + org.jboss.weld.resolution;version="6.0.0.CR1",\ + org.jboss.weld.resources;version="6.0.0.CR1",\ + org.jboss.weld.util.collections;version="6.0.0.CR1",\ + org.jboss.weld.bootstrap.api;version="6.0.0.CR1";uses:="jakarta.enterprise.inject.spi,org.jboss.weld.bootstrap.spi,org.jboss.weld.manager.api",\ + org.jboss.weld.bootstrap.api.helpers;version="6.0.0.CR1";uses:="org.jboss.weld.bootstrap.api,org.jboss.weld.bootstrap.spi,org.jboss.weld.manager.api",\ + org.jboss.weld.construction.api;version="6.0.0.CR1";uses:="jakarta.enterprise.context.spi,jakarta.enterprise.inject.spi",\ + org.jboss.weld.context.api;version="6.0.0.CR1";uses:="jakarta.enterprise.context.spi",\ + org.jboss.weld.ejb.api;version="6.0.0.CR1",\ + org.jboss.weld.manager.api;version="6.0.0.CR1";uses:="jakarta.enterprise.context.spi,jakarta.enterprise.inject,jakarta.enterprise.inject.spi,jakarta.enterprise.inject.spi.el,org.jboss.weld.bootstrap.api,org.jboss.weld.construction.api,org.jboss.weld.context,org.jboss.weld.ejb.spi,org.jboss.weld.serialization.spi",\ + org.jboss.weld.servlet.api;version="6.0.0.CR1";uses:="jakarta.servlet,jakarta.servlet.http",\ + org.jboss.weld.servlet.api.helpers;version="6.0.0.CR1";uses:="jakarta.servlet,jakarta.servlet.http,org.jboss.weld.servlet.api",\ + org.jboss.weld.bootstrap.spi;version="6.0.0.CR1";uses:="jakarta.enterprise.inject.spi,org.jboss.weld.bootstrap.api,org.jboss.weld.ejb.spi",\ + org.jboss.weld.bootstrap.spi.helpers;version="6.0.0.CR1";uses:="org.jboss.weld.bootstrap.api,org.jboss.weld.bootstrap.spi,org.jboss.weld.ejb.spi",\ + org.jboss.weld.configuration.spi;version="6.0.0.CR1";uses:="org.jboss.weld.bootstrap.api",\ + org.jboss.weld.configuration.spi.helpers;version="6.0.0.CR1";uses:="org.jboss.weld.configuration.spi",\ + org.jboss.weld.ejb.spi;version="6.0.0.CR1";uses:="jakarta.enterprise.inject.spi,org.jboss.weld.bootstrap.api,org.jboss.weld.ejb.api",\ + org.jboss.weld.ejb.spi.helpers;version="6.0.0.CR1";uses:="org.jboss.weld.ejb.api,org.jboss.weld.ejb.spi",\ + org.jboss.weld.injection.spi;version="6.0.0.CR1";uses:="jakarta.enterprise.inject.spi,jakarta.persistence,org.jboss.weld.bootstrap.api",\ + org.jboss.weld.injection.spi.helpers;version="6.0.0.CR1";uses:="jakarta.annotation,jakarta.enterprise.inject.spi,jakarta.persistence,javax.naming,org.jboss.weld.bootstrap.api,org.jboss.weld.injection.spi",\ + org.jboss.weld.interceptor.spi.metadata;version="6.0.0.CR1";uses:="jakarta.enterprise.context.spi,org.jboss.weld.interceptor.proxy,org.jboss.weld.interceptor.spi.model,org.jboss.weld.manager",\ + org.jboss.weld.interceptor.spi.model;version="6.0.0.CR1";uses:="jakarta.enterprise.inject.spi,org.jboss.weld.interceptor.spi.metadata",\ + org.jboss.weld.resources.spi;version="6.0.0.CR1";uses:="org.jboss.weld.bootstrap.api",\ + org.jboss.weld.resources.spi.helpers;version="6.0.0.CR1";uses:="org.jboss.weld.resources.spi",\ + org.jboss.weld.security.spi;version="6.0.0.CR1";uses:="org.jboss.weld.bootstrap.api",\ + org.jboss.weld.serialization.spi;version="6.0.0.CR1";uses:="jakarta.enterprise.context.spi,org.jboss.weld.bootstrap.api,org.jboss.weld.serialization.spi.helpers",\ + org.jboss.weld.serialization.spi.helpers;version="6.0.0.CR1";uses:="jakarta.enterprise.context.spi,org.jboss.weld.context.api",\ + org.jboss.weld.servlet.spi;version="6.0.0.CR1";uses:="jakarta.servlet.http,org.jboss.weld.bootstrap.api",\ + org.jboss.weld.servlet.spi.helpers;version="6.0.0.CR1";uses:="jakarta.servlet.http,org.jboss.weld.servlet.spi",\ + org.jboss.weld.transaction.spi;version="6.0.0.CR1";uses:="jakarta.transaction,org.jboss.weld.bootstrap.api",\ + org.jboss.weld.bootstrap.event;version="6.0.0.CR1";uses:="jakarta.enterprise.context.spi,jakarta.enterprise.inject,jakarta.enterprise.inject.spi,jakarta.enterprise.inject.spi.configurator,jakarta.enterprise.invoke,jakarta.enterprise.util,jakarta.interceptor",\ + org.jboss.weld.context;version="6.0.0.CR1";uses:="jakarta.enterprise.context,jakarta.enterprise.context.spi,org.jboss.weld.context.api",\ + org.jboss.weld.context.activator;version="6.0.0.CR1";uses:="jakarta.enterprise.util,jakarta.interceptor",\ + org.jboss.weld.context.bound;version="6.0.0.CR1";uses:="jakarta.enterprise.util,jakarta.inject,org.jboss.weld.context",\ + org.jboss.weld.context.ejb;version="6.0.0.CR1";uses:="jakarta.enterprise.util,jakarta.inject,jakarta.interceptor,org.jboss.weld.context",\ + org.jboss.weld.context.http;version="6.0.0.CR1";uses:="jakarta.enterprise.util,jakarta.inject,jakarta.servlet.http,org.jboss.weld.context",\ + org.jboss.weld.context.unbound;version="6.0.0.CR1";uses:="jakarta.enterprise.util,jakarta.inject",\ + org.jboss.weld.events;version="6.0.0.CR1";uses:="jakarta.enterprise.event,jakarta.enterprise.util",\ + org.jboss.weld.inject;version="6.0.0.CR1";uses:="jakarta.enterprise.inject,jakarta.enterprise.inject.spi,jakarta.enterprise.util",\ + org.jboss.weld.interceptor;version="6.0.0.CR1";uses:="jakarta.interceptor",\ + org.jboss.weld.proxy;version="6.0.0.CR1";uses:="jakarta.enterprise.inject.spi",\ + org.jboss.weld.lite.extension.translator;version="6.0.0.CR1";uses:="jakarta.annotation,jakarta.enterprise.event,jakarta.enterprise.inject.build.compatible.spi,jakarta.enterprise.inject.spi,jakarta.enterprise.lang.model,jakarta.enterprise.lang.model.declarations",\ + org.jboss.weld.lite.extension.translator.logging;version="6.0.0.CR1";uses:="org.jboss.logging,org.jboss.weld.exceptions",\ + org.jboss.weld.lite.extension.translator.util;version="6.0.0.CR1",\ + org.jboss.weld.lite.extension.translator.util.reflection;version="6.0.0.CR1",\ + org.jboss.weld.module.ejb;version="6.0.0.CR1";uses:="jakarta.enterprise.context.spi,jakarta.interceptor,org.jboss.weld.bean,org.jboss.weld.bean.proxy,org.jboss.weld.context.ejb,org.jboss.weld.manager,org.jboss.weld.module",\ + org.jboss.weld.module.ejb.context;version="6.0.0.CR1";uses:="jakarta.interceptor,org.jboss.weld.context.ejb,org.jboss.weld.contexts",\ + org.jboss.weld.module.ejb.context.beanstore;version="6.0.0.CR1";uses:="jakarta.interceptor,org.jboss.weld.contexts.beanstore",\ + org.jboss.weld.module.jsf;version="6.0.0.CR1";uses:="jakarta.faces.application,jakarta.faces.context,org.jboss.weld.bootstrap.api,org.jboss.weld.module,org.jboss.weld.resources.spi,org.jboss.weld.util",\ + org.jboss.weld.module.jsf.servlet;version="6.0.0.CR1";uses:="jakarta.servlet",\ + org.jboss.weld.module.jta;version="6.0.0.CR1";uses:="org.jboss.weld.module",\ + org.jboss.weld.module.web;version="6.0.0.CR1";uses:="jakarta.enterprise.context.spi,jakarta.enterprise.inject.spi,jakarta.servlet,jakarta.servlet.http,org.jboss.weld.bean.builtin,org.jboss.weld.manager,org.jboss.weld.module",\ + org.jboss.weld.module.web.context.beanstore.http;version="6.0.0.CR1";uses:="jakarta.servlet.http,org.jboss.weld.bootstrap.api,org.jboss.weld.context.api,org.jboss.weld.contexts.beanstore,org.jboss.weld.serialization.spi",\ + org.jboss.weld.module.web.context.http;version="6.0.0.CR1";uses:="jakarta.enterprise.context,jakarta.servlet.http,org.jboss.weld.bootstrap.api,org.jboss.weld.context.http,org.jboss.weld.contexts,org.jboss.weld.contexts.beanstore",\ + org.jboss.weld.module.web.el;version="6.0.0.CR1";uses:="jakarta.el,org.jboss.weld.manager,org.jboss.weld.module.web.util.el",\ + org.jboss.weld.module.web.logging;version="6.0.0.CR1";uses:="org.jboss.logging,org.jboss.weld.exceptions,org.jboss.weld.logging,org.jboss.weld.module.web.servlet",\ + org.jboss.weld.module.web.servlet;version="6.0.0.CR1";uses:="jakarta.servlet,jakarta.servlet.http,org.jboss.weld.bootstrap.api,org.jboss.weld.context.http,org.jboss.weld.manager,org.jboss.weld.resources.spi,org.jboss.weld.servlet.api.helpers,org.jboss.weld.servlet.spi,org.jboss.weld.util",\ + org.jboss.weld.module.web.util.el;version="6.0.0.CR1";uses:="jakarta.el",\ + org.jboss.weld.module.web.util.servlet;version="6.0.0.CR1";uses:="jakarta.servlet,org.jboss.weld.manager,org.jboss.weld.servlet.spi",\ + org.jboss.weld;version="6.0.0.CR1";uses:="jakarta.enterprise.inject,jakarta.enterprise.inject.spi,jakarta.enterprise.util,org.jboss.weld.bean.builtin,org.jboss.weld.bootstrap,org.jboss.weld.bootstrap.api,org.jboss.weld.bootstrap.spi,org.jboss.weld.inject,org.jboss.weld.manager",\ + org.jboss.weld.bean;version="6.0.0.CR1";uses:="jakarta.enterprise.context.spi,jakarta.enterprise.inject.spi,jakarta.interceptor,org.jboss.weld.bootstrap,org.jboss.weld.bootstrap.api,org.jboss.weld.ejb.spi,org.jboss.weld.interceptor.spi.metadata,org.jboss.weld.interceptor.spi.model,org.jboss.weld.manager,org.jboss.weld.serialization.spi",\ + org.jboss.weld.bean.builtin;version="6.0.0.CR1";uses:="jakarta.enterprise.context,jakarta.enterprise.context.control,jakarta.enterprise.context.spi,jakarta.enterprise.event,jakarta.enterprise.inject,jakarta.enterprise.inject.spi,jakarta.enterprise.util,org.jboss.weld.bean,org.jboss.weld.bean.proxy,org.jboss.weld.bootstrap,org.jboss.weld.bootstrap.api,org.jboss.weld.bootstrap.spi,org.jboss.weld.construction.api,org.jboss.weld.contexts,org.jboss.weld.ejb.spi,org.jboss.weld.inject,org.jboss.weld.injection,org.jboss.weld.manager,org.jboss.weld.manager.api,org.jboss.weld.serialization.spi,org.jboss.weld.util",\ + org.jboss.weld.bean.proxy;version="6.0.0.CR1";uses:="jakarta.enterprise.context.spi,jakarta.enterprise.inject.spi,org.jboss.classfilewriter,org.jboss.classfilewriter.code,org.jboss.weld.bootstrap.api,org.jboss.weld.bootstrap.api.helpers,org.jboss.weld.config,org.jboss.weld.contexts.cache,org.jboss.weld.exceptions,org.jboss.weld.interceptor.proxy,org.jboss.weld.interceptor.spi.model,org.jboss.weld.interceptor.util.proxy,org.jboss.weld.manager,org.jboss.weld.proxy,org.jboss.weld.serialization.spi,org.jboss.weld.serialization.spi.helpers",\ + org.jboss.weld.bootstrap;version="6.0.0.CR1";uses:="jakarta.enterprise.context.spi,jakarta.enterprise.inject.spi,org.jboss.weld.bean,org.jboss.weld.bean.builtin,org.jboss.weld.bootstrap.api,org.jboss.weld.bootstrap.api.helpers,org.jboss.weld.bootstrap.spi,org.jboss.weld.event,org.jboss.weld.exceptions,org.jboss.weld.logging,org.jboss.weld.manager,org.jboss.weld.manager.api,org.jboss.weld.module,org.jboss.weld.resources.spi",\ + org.jboss.weld.config;version="6.0.0.CR1";uses:="org.jboss.weld.bootstrap.api,org.jboss.weld.bootstrap.spi",\ + org.jboss.weld.contexts;version="6.0.0.CR1";uses:="jakarta.enterprise.context,jakarta.enterprise.context.spi,org.jboss.weld.bootstrap.api,org.jboss.weld.construction.api,org.jboss.weld.context,org.jboss.weld.context.api,org.jboss.weld.contexts.beanstore,org.jboss.weld.contexts.conversation,org.jboss.weld.injection.spi,org.jboss.weld.interceptor.proxy,org.jboss.weld.serialization.spi,org.jboss.weld.serialization.spi.helpers",\ + org.jboss.weld.contexts.activator;version="6.0.0.CR1";uses:="jakarta.annotation,jakarta.enterprise.context.control,jakarta.enterprise.inject,jakarta.inject,jakarta.interceptor,org.jboss.weld.context,org.jboss.weld.context.activator,org.jboss.weld.context.unbound,org.jboss.weld.event,org.jboss.weld.manager",\ + org.jboss.weld.contexts.beanstore;version="6.0.0.CR1";uses:="org.jboss.weld.context.api,org.jboss.weld.serialization.spi",\ + org.jboss.weld.contexts.bound;version="6.0.0.CR1";uses:="org.jboss.weld.bootstrap.api,org.jboss.weld.context.bound,org.jboss.weld.contexts,org.jboss.weld.contexts.beanstore",\ + org.jboss.weld.contexts.cache;version="6.0.0.CR1",\ + org.jboss.weld.contexts.conversation;version="6.0.0.CR1";uses:="jakarta.inject,org.jboss.weld.context,org.jboss.weld.manager",\ + org.jboss.weld.contexts.unbound;version="6.0.0.CR1";uses:="jakarta.enterprise.context,jakarta.enterprise.context.spi,org.jboss.weld.context,org.jboss.weld.context.api,org.jboss.weld.contexts,org.jboss.weld.serialization.spi",\ + org.jboss.weld.event;thread-context=true;version="6.0.0.CR1";uses:="jakarta.enterprise.context.spi,jakarta.enterprise.event,jakarta.enterprise.inject.spi,jakarta.enterprise.util,org.jboss.weld.bean,org.jboss.weld.bean.builtin,org.jboss.weld.bootstrap.api,org.jboss.weld.events,org.jboss.weld.injection,org.jboss.weld.manager,org.jboss.weld.module,org.jboss.weld.util",\ + org.jboss.weld.exceptions;version="6.0.0.CR1";uses:="jakarta.enterprise.inject,jakarta.enterprise.inject.spi",\ + org.jboss.weld.injection;version="6.0.0.CR1";uses:="jakarta.enterprise.context.spi,jakarta.enterprise.inject.spi,jakarta.enterprise.inject.spi.configurator,org.jboss.weld.bootstrap.api,org.jboss.weld.injection.spi,org.jboss.weld.manager",\ + org.jboss.weld.interceptor.proxy;version="6.0.0.CR1";uses:="jakarta.enterprise.context.spi,jakarta.enterprise.inject.spi,jakarta.interceptor,org.jboss.weld.bean.proxy,org.jboss.weld.interceptor,org.jboss.weld.interceptor.spi.metadata,org.jboss.weld.interceptor.spi.model,org.jboss.weld.manager,org.jboss.weld.util",\ + org.jboss.weld.interceptor.util.proxy;version="6.0.0.CR1";uses:="org.jboss.weld.bean.proxy",\ + org.jboss.weld.logging;version="6.0.0.CR1";uses:="jakarta.enterprise.context.spi,jakarta.enterprise.inject.spi,javax.naming,org.jboss.logging,org.jboss.weld.contexts,org.jboss.weld.exceptions",\ + org.jboss.weld.manager;version="6.0.0.CR1";uses:="jakarta.el,jakarta.enterprise.context.spi,jakarta.enterprise.event,jakarta.enterprise.inject,jakarta.enterprise.inject.spi,jakarta.enterprise.inject.spi.configurator,org.jboss.weld.bean,org.jboss.weld.bean.proxy,org.jboss.weld.bootstrap.api,org.jboss.weld.bootstrap.spi,org.jboss.weld.construction.api,org.jboss.weld.contexts,org.jboss.weld.ejb.spi,org.jboss.weld.event,org.jboss.weld.events,org.jboss.weld.inject,org.jboss.weld.interceptor.spi.model,org.jboss.weld.manager.api,org.jboss.weld.serialization.spi",\ + org.jboss.weld.module;version="6.0.0.CR1";uses:="jakarta.el,jakarta.enterprise.context.spi,jakarta.enterprise.inject.spi,org.jboss.weld.bean,org.jboss.weld.bean.builtin,org.jboss.weld.bootstrap,org.jboss.weld.bootstrap.api,org.jboss.weld.bootstrap.spi,org.jboss.weld.ejb.spi,org.jboss.weld.event,org.jboss.weld.manager",\ + org.jboss.weld.security;version="6.0.0.CR1";uses:="org.jboss.weld.security.spi",\ + org.jboss.weld.util;version="6.0.0.CR1";uses:="jakarta.el,jakarta.enterprise.context.spi,jakarta.enterprise.event,jakarta.enterprise.inject,jakarta.enterprise.inject.spi,jakarta.enterprise.inject.spi.el,jakarta.enterprise.util,jakarta.interceptor,org.jboss.weld.bean,org.jboss.weld.bootstrap,org.jboss.weld.bootstrap.api,org.jboss.weld.bootstrap.spi,org.jboss.weld.exceptions,org.jboss.weld.inject,org.jboss.weld.injection,org.jboss.weld.interceptor.spi.model,org.jboss.weld.manager,org.jboss.weld.resources.spi,org.jboss.weld.serialization.spi",\ + org.jboss.weld.util.reflection;version="6.0.0.CR1";uses:="jakarta.enterprise.inject.spi,org.jboss.weld.ejb.spi,org.jboss.weld.resources.spi",\ + org.jboss.weld.xml;version="6.0.0.CR1";uses:="org.jboss.weld.bootstrap.spi,org.xml.sax,org.xml.sax.helpers" # Automatically filled in by build.gradle Import-Package: \ - javax.security.auth,\ jakarta.xml.ws;version="[4.0,5)",\ - jakarta.servlet.descriptor,\ jakarta.annotation,\ jakarta.ejb;resolution:=optional,\ jakarta.el;resolution:=optional,\ @@ -185,10 +184,9 @@ Import-Package: \ org.jboss.classfilewriter;version="[1.3,2)",\ org.jboss.classfilewriter.code;version="[1.3,2)",\ org.jboss.classfilewriter.util;version="[1.3,2)",\ - org.jboss.logging;version="[3.5,4)",\ + org.jboss.logging;version="[3.6,4)",\ org.jboss.weld.bootstrap.api;version="[6.0,7)",\ org.jboss.weld.bootstrap.api.helpers;version="[6.0,7)",\ - org.jboss.weld.bootstrap.event;version="[6.0,7)",\ org.jboss.weld.bootstrap.spi;version="[6.0,7)",\ org.jboss.weld.bootstrap.spi.helpers;version="[6.0,7)",\ org.jboss.weld.configuration.spi;version="[6.0,7)",\ @@ -222,6 +220,7 @@ Import-Package: \ org.jboss.weld.module.jsf;version="[6.0,7)",\ org.jboss.weld.module.web.el;version="[6.0,7)",\ org.jboss.weld.module.web.logging;version="[6.0,7)",\ + org.jboss.weld.module.web.servlet;version="[6.0,7)",\ org.jboss.weld.module.web.util.el;version="[6.0,7)",\ org.jboss.weld.module.web.util.servlet;version="[6.0,7)",\ org.jboss.weld.proxy;version="[6.0,7)",\ @@ -237,4 +236,6 @@ Import-Package: \ org.jboss.weld.transaction.spi;version="[6.0,7)",\ org.xml.sax,\ org.xml.sax.helpers,\ + jakarta.servlet.descriptor;resolution:=optional,\ + javax.security.auth;resolution:=optional,\ org.jboss.logging.annotations;resolution:=optional From ec93fef419c5b2bb92755a9b746be755a98d0367 Mon Sep 17 00:00:00 2001 From: Wendy Raschke Date: Thu, 14 Nov 2024 11:58:39 -0600 Subject: [PATCH 02/67] Additional properties needed to complete checklist --- .ci-orchestrator/checks.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.ci-orchestrator/checks.yml b/.ci-orchestrator/checks.yml index b3cadb908b9..a4a3cbceded 100644 --- a/.ci-orchestrator/checks.yml +++ b/.ci-orchestrator/checks.yml @@ -41,13 +41,18 @@ steps: properties: isBvtCodeChanged: ${PR Changes:is.bvt.code.changed} isFatCodeChanged: ${PR Changes:is.fat.code.changed} + isFeatureFilesChanged: ${PR Changes:is.feature.files.changed} isInfraCodeChanged: ${PR Changes:is.infra.code.changed} + isMsgsFilesChanged: ${PR Changes:is.msgs.files.changed} + isNlsFilesChanged: ${PR Changes:is.nls.files.changed} isProductCodeChanged: ${PR Changes:is.product.code.changed} isTestInfraCodeChanged: ${PR Changes:is.test.infra.code.changed} isUnittestCodeChanged: ${PR Changes:is.unittest.code.changed} bvtFilesCount: ${PR Changes:bvt.files.count} fatFilesCount: ${PR Changes:fat.files.count} infraFilesCount: ${PR Changes:infra.files.count} + msgsFiles: ${PR Changes:msgs.files} + nlsFiles: ${PR Changes:nls.files} productFilesCount: ${PR Changes:product.files.count} testInfraFilesCount: ${PR Changes:test.infra.files.count} unittestFilesCount: ${PR Changes:unittest.files.count} From e3cc9a2c265adf8b88d42b25bd82719383eaac04 Mon Sep 17 00:00:00 2001 From: Wendy Raschke Date: Thu, 14 Nov 2024 12:12:00 -0600 Subject: [PATCH 03/67] Temporary commit to test with messages changes --- .../jbatch/container/internal/resources/JBatchMessages.nlsprops | 2 ++ .../resources/l10n/io.openliberty.xmlWS-4.0.properties | 2 ++ .../com/ibm/wsspi/rest/config/resources/CWWKOMessages.nlsprops | 2 ++ 3 files changed, 6 insertions(+) diff --git a/dev/com.ibm.jbatch.container/resources/com/ibm/jbatch/container/internal/resources/JBatchMessages.nlsprops b/dev/com.ibm.jbatch.container/resources/com/ibm/jbatch/container/internal/resources/JBatchMessages.nlsprops index da3e373661c..aeba5d63ab3 100644 --- a/dev/com.ibm.jbatch.container/resources/com/ibm/jbatch/container/internal/resources/JBatchMessages.nlsprops +++ b/dev/com.ibm.jbatch.container/resources/com/ibm/jbatch/container/internal/resources/JBatchMessages.nlsprops @@ -36,6 +36,8 @@ # 0001 - 0100: com.ibm.jbatch.container # +# Test commit only; not for merging + stopping.job.at.shutdown=CWWKY0001I: Issuing stop for job execution {0} because the batch component is deactivating. stopping.job.at.shutdown.explanation=This message is for informational purposes only. stopping.job.at.shutdown.useraction=No action is required. diff --git a/dev/com.ibm.websphere.appserver.features/visibility/public/xmlWS-4.0/resources/l10n/io.openliberty.xmlWS-4.0.properties b/dev/com.ibm.websphere.appserver.features/visibility/public/xmlWS-4.0/resources/l10n/io.openliberty.xmlWS-4.0.properties index 390c091c87b..ad6c3db49ce 100644 --- a/dev/com.ibm.websphere.appserver.features/visibility/public/xmlWS-4.0/resources/l10n/io.openliberty.xmlWS-4.0.properties +++ b/dev/com.ibm.websphere.appserver.features/visibility/public/xmlWS-4.0/resources/l10n/io.openliberty.xmlWS-4.0.properties @@ -16,6 +16,8 @@ #NLS_MESSAGEFORMAT_NONE # +# Test commit only; not for merging + description=This feature enables support for Jakarta XML Web Services 4.0. These web \ services and clients communicate using XML. Annotations can be used to simplify the development \ of service clients and endpoints. diff --git a/dev/com.ibm.websphere.rest.handler/resources/com/ibm/wsspi/rest/config/resources/CWWKOMessages.nlsprops b/dev/com.ibm.websphere.rest.handler/resources/com/ibm/wsspi/rest/config/resources/CWWKOMessages.nlsprops index ca05d338df8..90e620c84e7 100644 --- a/dev/com.ibm.websphere.rest.handler/resources/com/ibm/wsspi/rest/config/resources/CWWKOMessages.nlsprops +++ b/dev/com.ibm.websphere.rest.handler/resources/com/ibm/wsspi/rest/config/resources/CWWKOMessages.nlsprops @@ -26,6 +26,8 @@ # All messages must use the range CWWKO1500 to CWWKO1529 +# Test commit only; not for merging + CWWKO1500_NOT_FOUND=CWWKO1500E: No configured instances of the {0} element were found in the server configuration. CWWKO1500_NOT_FOUND.explanation=The requested configuration element was not found in the server.xml file. CWWKO1500_NOT_FOUND.useraction=Verify that the configuration element exists in the server.xml file and that it is correctly spelled with matching case. From a7c817aee328c1e88ede9d5aa1f5fd9a20393940 Mon Sep 17 00:00:00 2001 From: Wendy Raschke Date: Thu, 14 Nov 2024 12:16:54 -0600 Subject: [PATCH 04/67] Temporary commit to test with feature file --- .../visibility/public/xmlWS-4.0/io.openliberty.xmlWS-4.0.feature | 1 + 1 file changed, 1 insertion(+) diff --git a/dev/com.ibm.websphere.appserver.features/visibility/public/xmlWS-4.0/io.openliberty.xmlWS-4.0.feature b/dev/com.ibm.websphere.appserver.features/visibility/public/xmlWS-4.0/io.openliberty.xmlWS-4.0.feature index b14f6ab620e..95dd433cfce 100644 --- a/dev/com.ibm.websphere.appserver.features/visibility/public/xmlWS-4.0/io.openliberty.xmlWS-4.0.feature +++ b/dev/com.ibm.websphere.appserver.features/visibility/public/xmlWS-4.0/io.openliberty.xmlWS-4.0.feature @@ -1,3 +1,4 @@ +# Test commit only; not for merging -include= ~${workspace}/cnf/resources/bnd/feature.props symbolicName=io.openliberty.xmlWS-4.0 visibility=public From 6f45996e9fbc5f2aca738fefc2ad965923eec7ad Mon Sep 17 00:00:00 2001 From: Joe Chacko <143064+joe-chacko@users.noreply.github.com> Date: Mon, 28 Oct 2024 11:56:26 +0000 Subject: [PATCH 05/67] docs: describe how to use ApplicationPrereq --- .../lifecycle/ApplicationPrereq.java | 122 ++++++++++++++++-- 1 file changed, 114 insertions(+), 8 deletions(-) diff --git a/dev/com.ibm.ws.app.manager.lifecycle/src/com/ibm/wsspi/application/lifecycle/ApplicationPrereq.java b/dev/com.ibm.ws.app.manager.lifecycle/src/com/ibm/wsspi/application/lifecycle/ApplicationPrereq.java index cdbad0249b0..a2b0a626417 100644 --- a/dev/com.ibm.ws.app.manager.lifecycle/src/com/ibm/wsspi/application/lifecycle/ApplicationPrereq.java +++ b/dev/com.ibm.ws.app.manager.lifecycle/src/com/ibm/wsspi/application/lifecycle/ApplicationPrereq.java @@ -1,10 +1,10 @@ /******************************************************************************* - * Copyright (c) 2020 IBM Corporation and others. + * Copyright (c) 2020,2024 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * * Contributors: @@ -13,12 +13,118 @@ package com.ibm.wsspi.application.lifecycle; /** - * This a marker interface for Service components that must be present before wsspi.applications are started. - * - * Implementors must also provide a config element in their defaultInstances.xml as follows: - * {@code - * - * } + * A marker interface for service components indicating + * they must be present before applications are started. + *

+ * Liberty's processing of configuration and metatype will discover + * these declarations and wait for the configured services before + * allowing applications to start. + *

+ * + * Every implementor must observe the following conventions: + *
    + *
  1. Edit the {@code bnd.bnd} for the bundle to instruct bnd appropriately: + *
      + *
    • Process the class for declarative services annotations: + *
      + * -dsannotations: com.acme.Widget
      + *         
      + *
    • + *
    • Add the metatype and default instances to the bundle: + *
      + * Include-Resource: OSGI-INF=resources/OSGI-INF
      + *         
      + *
    • + *
    • Declare the default instances (if required — see below): + *
      + * IBM-Default-Config: OSGI-INF/wlp/defaultInstances.xml
      + *         
      + *
    • + *
    • Add the app manager lifecycle bundle to the build path: + *
      + * -buildpath: com.ibm.ws.app.manager.lifecycle;version=latest
      + *         
      + *
    • + *
    + *
  2. + *
  3. The implementation must declare itself as a declarative services (DS) component. + *
      + *
    • The component declaration must provide {@link ApplicationPrereq} as a service.
      + * + * If this is not done, the configured component instance will never be discovered, and applications will not start up. + * + *
    • + *
    • The component declaration must require configuration.
    • + *
    + * e.g.: + *
    + * package com.acme;
    + * {@code @Component}(
    + *         service = ApplicationPrereq.class,
    + *         configurationPolicy = REQUIRE,
    + *         configurationPid = "com.acme.Widget",
    + *         property = "service.vendor=Acme")
    + * public class Widget implements ApplicationPrereq {…}
    + *     
    + * + * Note: Components can be declared in the Java source or in the {@code bnd.bnd} file.
    + * Verify the component xml in the generated bundle, + * e.g. {@code OSGI-INF/com.acme.Widget.xml} + *
    + *
  4. + *
  5. + * The implementing bundle must provide an {@code OCD} and a {@code Designate} + * for the configuration in an XML file in {@code resources/OSGI-INF/metatype/}, + * usually {@code metatype.xml}. + *
      + *
    • the OCD must declare its objectClass to be {@link ApplicationPrereq}
      + * e.g. + *
      + * {@code }
      + * ⋮
      + * {@code }
      + *         
      + * + * Declaring the objectClass correctly allows every configuration of this OCD to be discovered. + * Application containers will start only after the configured component instances become available. + * + *
    • + *
    • + * Either the Designate must use a factoryPid instead of a pid, + *
      + * {@code }
      + *   {@code }
      + * {@code }
      + *         
      + *       
      + *       
    • + * Or the OCD must contain a required AD without a default value: + *
      + * {@code }
      + *   {@code }
      + * {@code }
      + *         
      + * + * If the delegate uses a pid and the OCD has no required non-default AD, + * Liberty's configuration processing may not be invoked for this OCD, + * and the counting of application prereqs may fail. + * This can be very difficult to debug! + * + *
    • + * + * + *
    • The configuration may be user-specified in the server.xml or provided in the bundle's default instances: + *
      + * {@code }
      + *   {@code }
      + * {@code }
      + *     
      + *
    • + * */ public interface ApplicationPrereq { } From e2de6f1cca5483a65d9f15ff3f08166b8f972ba8 Mon Sep 17 00:00:00 2001 From: Neil Richards <7203556+ngmr@users.noreply.github.com> Date: Thu, 14 Nov 2024 20:26:34 +0000 Subject: [PATCH 06/67] docs: avoid javadoc syntax for license coment --- .../ibm/wsspi/application/lifecycle/ApplicationPrereq.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dev/com.ibm.ws.app.manager.lifecycle/src/com/ibm/wsspi/application/lifecycle/ApplicationPrereq.java b/dev/com.ibm.ws.app.manager.lifecycle/src/com/ibm/wsspi/application/lifecycle/ApplicationPrereq.java index a2b0a626417..1a7d0383ac7 100644 --- a/dev/com.ibm.ws.app.manager.lifecycle/src/com/ibm/wsspi/application/lifecycle/ApplicationPrereq.java +++ b/dev/com.ibm.ws.app.manager.lifecycle/src/com/ibm/wsspi/application/lifecycle/ApplicationPrereq.java @@ -1,4 +1,4 @@ -/******************************************************************************* +/* ============================================================================= * Copyright (c) 2020,2024 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -9,7 +9,8 @@ * * Contributors: * IBM Corporation - initial API and implementation - *******************************************************************************/ + * ============================================================================= + */ package com.ibm.wsspi.application.lifecycle; /** From bf086c85f719db6dedf6b8d3df10f85bc11ddcfe Mon Sep 17 00:00:00 2001 From: Joe Chacko <143064+joe-chacko@users.noreply.github.com> Date: Wed, 13 Nov 2024 14:36:07 +0000 Subject: [PATCH 07/67] refactor: encapsulate recovery manager class --- .../src/com/ibm/tx/jta/impl/RecoveryManager.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dev/com.ibm.tx.jta/src/com/ibm/tx/jta/impl/RecoveryManager.java b/dev/com.ibm.tx.jta/src/com/ibm/tx/jta/impl/RecoveryManager.java index d6832184078..72e4a2dc8c7 100644 --- a/dev/com.ibm.tx.jta/src/com/ibm/tx/jta/impl/RecoveryManager.java +++ b/dev/com.ibm.tx.jta/src/com/ibm/tx/jta/impl/RecoveryManager.java @@ -88,8 +88,8 @@ public class RecoveryManager implements Runnable { protected final RecoveryAgent _agent; protected RecoveryLog _tranLog; // 169107 - protected RecoveryLog _xaLog; // 169107 - protected final RecoveryLog _recoverXaLog; //@MD18134A + private RecoveryLog _xaLog; // 169107 + private final RecoveryLog _recoverXaLog; //@MD18134A protected SharedServerLeaseLog _leaseLog; protected String _recoveryGroup; From 0735241c808656078c61610ccb772aebd92ae3e0 Mon Sep 17 00:00:00 2001 From: Joe Chacko <143064+joe-chacko@users.noreply.github.com> Date: Wed, 13 Nov 2024 14:36:15 +0000 Subject: [PATCH 08/67] refactor: encapsulate recovery manager class --- dev/com.ibm.tx.jta/src/com/ibm/tx/jta/impl/RecoveryManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/com.ibm.tx.jta/src/com/ibm/tx/jta/impl/RecoveryManager.java b/dev/com.ibm.tx.jta/src/com/ibm/tx/jta/impl/RecoveryManager.java index d6832184078..97fa24f106b 100644 --- a/dev/com.ibm.tx.jta/src/com/ibm/tx/jta/impl/RecoveryManager.java +++ b/dev/com.ibm.tx.jta/src/com/ibm/tx/jta/impl/RecoveryManager.java @@ -97,7 +97,7 @@ public class RecoveryManager implements Runnable { protected boolean _peerTranLogEverOpened = false; protected boolean _peerXaLogEverOpened = false; - protected PartnerLogTable _recoveryPartnerLogTable; + private PartnerLogTable _recoveryPartnerLogTable; protected byte[] _ourApplId; protected int _ourEpoch; From 596f4a279871118e29990e4d4346298083907b36 Mon Sep 17 00:00:00 2001 From: Joe Chacko <143064+joe-chacko@users.noreply.github.com> Date: Wed, 13 Nov 2024 14:37:54 +0000 Subject: [PATCH 09/67] refactor: encapsulate recovery manager class --- .../src/com/ibm/tx/jta/impl/RecoveryManager.java | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/dev/com.ibm.tx.jta/src/com/ibm/tx/jta/impl/RecoveryManager.java b/dev/com.ibm.tx.jta/src/com/ibm/tx/jta/impl/RecoveryManager.java index d6832184078..6fad620228f 100644 --- a/dev/com.ibm.tx.jta/src/com/ibm/tx/jta/impl/RecoveryManager.java +++ b/dev/com.ibm.tx.jta/src/com/ibm/tx/jta/impl/RecoveryManager.java @@ -129,16 +129,10 @@ public class RecoveryManager implements Runnable { // The following relate to the service data recoverable unit in the transaction log // This is reserved and holds the servername, applid and epoch. // - protected RecoverableUnit _tranlogServiceData; - protected RecoverableUnitSection _tranlogServerSection; - protected RecoverableUnitSection _tranlogApplIdSection; - protected RecoverableUnitSection _tranlogEpochSection; - - protected String _classPath; // current classpath for recovery - // These are static as they are only initialized from the "server's" own log - // We use our own classpaths and not from other servers in case we recover - // for a filesystem that does not match our own. - protected static String _loggedClassPath; // classpath read from the log at startup + private RecoverableUnit _tranlogServiceData; + private RecoverableUnitSection _tranlogServerSection; + private RecoverableUnitSection _tranlogApplIdSection; + private RecoverableUnitSection _tranlogEpochSection; // Server States logged for serviceability public static final int STARTING = 1; From 194ace95e4e5086ca2528efd1a66c10b0d8f2da4 Mon Sep 17 00:00:00 2001 From: Joe Chacko <143064+joe-chacko@users.noreply.github.com> Date: Wed, 13 Nov 2024 14:38:10 +0000 Subject: [PATCH 10/67] refactor: encapsulate recovery manager class --- dev/com.ibm.tx.jta/src/com/ibm/tx/jta/impl/RecoveryManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/com.ibm.tx.jta/src/com/ibm/tx/jta/impl/RecoveryManager.java b/dev/com.ibm.tx.jta/src/com/ibm/tx/jta/impl/RecoveryManager.java index d6832184078..77f9ce98634 100644 --- a/dev/com.ibm.tx.jta/src/com/ibm/tx/jta/impl/RecoveryManager.java +++ b/dev/com.ibm.tx.jta/src/com/ibm/tx/jta/impl/RecoveryManager.java @@ -155,7 +155,7 @@ public class RecoveryManager implements Runnable { /** * This set contains a list of all recovering transactions. */ - protected Set _recoveringTransactions; + private final Set _recoveringTransactions; protected final Object _recoveryMonitor = new Object(); From 6f6897038504c7cee4e2ab4a9f633d1b238f8d26 Mon Sep 17 00:00:00 2001 From: Joe Chacko <143064+joe-chacko@users.noreply.github.com> Date: Wed, 13 Nov 2024 14:38:20 +0000 Subject: [PATCH 11/67] refactor: encapsulate recovery manager class --- dev/com.ibm.tx.jta/src/com/ibm/tx/jta/impl/RecoveryManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/com.ibm.tx.jta/src/com/ibm/tx/jta/impl/RecoveryManager.java b/dev/com.ibm.tx.jta/src/com/ibm/tx/jta/impl/RecoveryManager.java index d6832184078..f0cb9104a31 100644 --- a/dev/com.ibm.tx.jta/src/com/ibm/tx/jta/impl/RecoveryManager.java +++ b/dev/com.ibm.tx.jta/src/com/ibm/tx/jta/impl/RecoveryManager.java @@ -157,7 +157,7 @@ public class RecoveryManager implements Runnable { */ protected Set _recoveringTransactions; - protected final Object _recoveryMonitor = new Object(); + private final Object _recoveryMonitor = new Object(); protected boolean _cleanRemoteShutdown; From c9585f8b8f0be5c91575c233fc16d0d7a600841e Mon Sep 17 00:00:00 2001 From: Wendy Raschke Date: Fri, 15 Nov 2024 19:11:09 -0600 Subject: [PATCH 12/67] Building pipelines need the additional properties, too --- .ci-orchestrator/pb.yml | 5 +++++ .ci-orchestrator/pbRTCBuild.yml | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/.ci-orchestrator/pb.yml b/.ci-orchestrator/pb.yml index 14dba40cdc7..0c867ce130c 100644 --- a/.ci-orchestrator/pb.yml +++ b/.ci-orchestrator/pb.yml @@ -149,13 +149,18 @@ steps: githubPRNumber: ${github_pr_number} isBvtCodeChanged: ${PR Changes:is.bvt.code.changed} isFatCodeChanged: ${PR Changes:is.fat.code.changed} + isFeatureFilesChanged: ${PR Changes:is.feature.files.changed} isInfraCodeChanged: ${PR Changes:is.infra.code.changed} + isMsgsFilesChanged: ${PR Changes:is.msgs.files.changed} + isNlsFilesChanged: ${PR Changes:is.nls.files.changed} isProductCodeChanged: ${PR Changes:is.product.code.changed} isTestInfraCodeChanged: ${PR Changes:is.test.infra.code.changed} isUnittestCodeChanged: ${PR Changes:is.unittest.code.changed} bvtFilesCount: ${PR Changes:bvt.files.count} fatFilesCount: ${PR Changes:fat.files.count} infraFilesCount: ${PR Changes:infra.files.count} + msgsFiles: ${PR Changes:msgs.files} + nlsFiles: ${PR Changes:nls.files} productFilesCount: ${PR Changes:product.files.count} testInfraFilesCount: ${PR Changes:test.infra.files.count} unittestFilesCount: ${PR Changes:unittest.files.count} diff --git a/.ci-orchestrator/pbRTCBuild.yml b/.ci-orchestrator/pbRTCBuild.yml index 3dad515faf3..9c2bf8454b7 100644 --- a/.ci-orchestrator/pbRTCBuild.yml +++ b/.ci-orchestrator/pbRTCBuild.yml @@ -78,13 +78,18 @@ steps: githubPRNumber: ${github_pr_number} isBvtCodeChanged: ${PR Changes:is.bvt.code.changed} isFatCodeChanged: ${PR Changes:is.fat.code.changed} + isFeatureFilesChanged: ${PR Changes:is.feature.files.changed} isInfraCodeChanged: ${PR Changes:is.infra.code.changed} + isMsgsFilesChanged: ${PR Changes:is.msgs.files.changed} + isNlsFilesChanged: ${PR Changes:is.nls.files.changed} isProductCodeChanged: ${PR Changes:is.product.code.changed} isTestInfraCodeChanged: ${PR Changes:is.test.infra.code.changed} isUnittestCodeChanged: ${PR Changes:is.unittest.code.changed} bvtFilesCount: ${PR Changes:bvt.files.count} fatFilesCount: ${PR Changes:fat.files.count} infraFilesCount: ${PR Changes:infra.files.count} + msgsFiles: ${PR Changes:msgs.files} + nlsFiles: ${PR Changes:nls.files} productFilesCount: ${PR Changes:product.files.count} testInfraFilesCount: ${PR Changes:test.infra.files.count} unittestFilesCount: ${PR Changes:unittest.files.count} From 1f68e797eeae7377b07739bb12ba301c50a1f021 Mon Sep 17 00:00:00 2001 From: yasmin-aumeeruddy Date: Mon, 18 Nov 2024 10:35:35 +0000 Subject: [PATCH 13/67] Update JakartaEEAction strings --- .../src/componenttest/rules/repeater/JakartaEE10Action.java | 2 +- .../src/componenttest/rules/repeater/JakartaEE11Action.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dev/fattest.simplicity/src/componenttest/rules/repeater/JakartaEE10Action.java b/dev/fattest.simplicity/src/componenttest/rules/repeater/JakartaEE10Action.java index eb934b940fb..c41de4045a3 100644 --- a/dev/fattest.simplicity/src/componenttest/rules/repeater/JakartaEE10Action.java +++ b/dev/fattest.simplicity/src/componenttest/rules/repeater/JakartaEE10Action.java @@ -120,7 +120,7 @@ public JakartaEE10Action() { @Override public String toString() { - return "JakartaEE10 FAT repeat action"; + return "JakartaEE10 FAT repeat action (" + getID() + ")"; } // diff --git a/dev/fattest.simplicity/src/componenttest/rules/repeater/JakartaEE11Action.java b/dev/fattest.simplicity/src/componenttest/rules/repeater/JakartaEE11Action.java index 70b3e3c5797..60e06cb61ba 100644 --- a/dev/fattest.simplicity/src/componenttest/rules/repeater/JakartaEE11Action.java +++ b/dev/fattest.simplicity/src/componenttest/rules/repeater/JakartaEE11Action.java @@ -150,7 +150,7 @@ protected JakartaEE11Action() { @Override public String toString() { - return "JakartaEE11 FAT repeat action"; + return "JakartaEE11 FAT repeat action (" + getID() + ")"; } // From 0ffad0a014d991330af8cbce9540ce76ee300e99 Mon Sep 17 00:00:00 2001 From: Neil Richards <7203556+ngmr@users.noreply.github.com> Date: Fri, 15 Nov 2024 13:44:16 +0000 Subject: [PATCH 14/67] refactor: convert ControlMessageType to enum --- .../sib/mfp/control/ControlMessageType.java | 406 ++++++++---------- 1 file changed, 184 insertions(+), 222 deletions(-) diff --git a/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/control/ControlMessageType.java b/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/control/ControlMessageType.java index 84e33c66aee..dfc6ce9c843 100644 --- a/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/control/ControlMessageType.java +++ b/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/control/ControlMessageType.java @@ -1,239 +1,201 @@ -/******************************************************************************* - * Copyright (c) 2012 IBM Corporation and others. +/* ============================================================================= + * Copyright (c) 2012,2024 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * * Contributors: * IBM Corporation - initial API and implementation - *******************************************************************************/ + * ============================================================================= + */ package com.ibm.ws.sib.mfp.control; -import com.ibm.ws.sib.mfp.*; -import com.ibm.ws.sib.utils.ras.SibTr; +import static com.ibm.websphere.ras.TraceComponent.isAnyTracingEnabled; +import static com.ibm.ws.sib.mfp.MfpConstants.MSG_BUNDLE; +import static com.ibm.ws.sib.mfp.MfpConstants.MSG_GROUP; +import static com.ibm.ws.sib.utils.ras.SibTr.debug; +import static com.ibm.ws.sib.utils.ras.SibTr.register; +import static java.util.Collections.unmodifiableMap; + +import java.util.HashMap; +import java.util.Map; +import java.util.function.Function; + import com.ibm.websphere.ras.TraceComponent; +import com.ibm.ws.sib.mfp.IntAble; /** * ControlMessageType is a type-safe enumeration which indicates the type of a * Control Message. */ -public final class ControlMessageType implements IntAble { - - private static TraceComponent tc = SibTr.register(ControlMessageType.class, MfpConstants.MSG_GROUP, MfpConstants.MSG_BUNDLE); - - /** Integer value of the Control Message Types */ - public final static int UNKNOWN_INT = 0; - public final static int ACKEXPECTED_INT = 1; - public final static int SILENCE_INT = 2; - public final static int ACK_INT = 3; - public final static int NACK_INT = 4; - public final static int PREVALUE_INT = 5; - public final static int ACCEPT_INT = 6; - public final static int REJECT_INT = 7; - public final static int DECISION_INT = 8; - public final static int REQUEST_INT = 9; - public final static int REQUESTACK_INT = 10; - public final static int REQUESTHIGHESTGENERATEDTICK_INT = 11; - public final static int HIGHESTGENERATEDTICK_INT = 12; - public final static int RESETREQUESTACK_INT = 13; - public final static int RESETREQUESTACKACK_INT = 14; - public final static int BROWSEGET_INT = 15; - public final static int BROWSEEND_INT = 16; - public final static int BROWSESTATUS_INT = 17; - public final static int COMPLETED_INT = 18; - public final static int DECISIONEXPECTED_INT = 19; - public final static int CREATESTREAM_INT = 20; - public final static int AREYOUFLUSHED_INT = 21; - public final static int FLUSHED_INT = 22; - public final static int NOTFLUSHED_INT = 23; - public final static int REQUESTFLUSH_INT = 24; - public final static int REQUESTCARDINALITYINFO_INT = 25; - public final static int CARDINALITYINFO_INT = 26; - public final static int CREATEDURABLE_INT = 27; - public final static int DELETEDURABLE_INT = 28; - public final static int DURABLECONFIRM_INT = 29; - - - /** Constant denoting an indeterminate DDD Message */ - public final static ControlMessageType UNKNOWN = new ControlMessageType("UNKNOWN" ,(byte)UNKNOWN_INT ); - - /** Constant denoting an Ack Expected Messge */ - public final static ControlMessageType ACKEXPECTED = new ControlMessageType("ACKEXPECTED" ,(byte)ACKEXPECTED_INT ); - - /** Constant denoting a Silence Message */ - public final static ControlMessageType SILENCE = new ControlMessageType("SILENCE" ,(byte)SILENCE_INT ); - - /** Constant denoting an Ack Message */ - public final static ControlMessageType ACK = new ControlMessageType("ACK" ,(byte)ACK_INT ); - - /** Constant denoting a Nack Message */ - public final static ControlMessageType NACK = new ControlMessageType("NACK" ,(byte)NACK_INT ); - - /** Constant denoting a Prevalue Message */ - public final static ControlMessageType PREVALUE = new ControlMessageType("PREVALUE" ,(byte)PREVALUE_INT ); - - /** Constant denoting an Accept Message */ - public final static ControlMessageType ACCEPT = new ControlMessageType("ACCEPT" ,(byte)ACCEPT_INT ); - - /** Constant denoting a Reject Message */ - public final static ControlMessageType REJECT = new ControlMessageType("REJECT" ,(byte)REJECT_INT ); - - /** Constant denoting a Decision Message */ - public final static ControlMessageType DECISION = new ControlMessageType("DECISION" ,(byte)DECISION_INT ); - - /** Constant denoting a Request Message */ - public final static ControlMessageType REQUEST = new ControlMessageType("REQUEST ",(byte)REQUEST_INT ); - - /** Constant denoting a RequestAck Message */ - public final static ControlMessageType REQUESTACK = new ControlMessageType("REQUESTACK ",(byte)REQUESTACK_INT ); - - /** Constant denoting a RequestHighestGeneratedTick Message */ - public final static ControlMessageType REQUESTHIGHESTGENERATEDTICK = new ControlMessageType("REQUESTHIGHESTGENERATEDTICK",(byte)REQUESTHIGHESTGENERATEDTICK_INT ); - - /** Constant denoting a HighestGeneratedTick Message */ - public final static ControlMessageType HIGHESTGENERATEDTICK = new ControlMessageType("HIGHESTGENERATEDTICK ",(byte)HIGHESTGENERATEDTICK_INT ); - - /** Constant denoting a RequestRequestAck Message */ - public final static ControlMessageType RESETREQUESTACK = new ControlMessageType("RESETREQUESTACK ",(byte)RESETREQUESTACK_INT ); - - /** Constant denoting a RequestRequestAckAck Message */ - public final static ControlMessageType RESETREQUESTACKACK = new ControlMessageType("RESETREQUESTACKACK ",(byte)RESETREQUESTACKACK_INT ); - - /** Constant denoting a BrowseGet Message */ - public final static ControlMessageType BROWSEGET = new ControlMessageType("BROWSEGET ",(byte)BROWSEGET_INT ); - - /** Constant denoting a BrowseEnd Message */ - public final static ControlMessageType BROWSEEND = new ControlMessageType("BROWSEEND ",(byte)BROWSEEND_INT ); - - /** Constant denoting a BrowseStatus Message */ - public final static ControlMessageType BROWSESTATUS = new ControlMessageType("BROWSESTATUS ",(byte)BROWSESTATUS_INT ); - - /** Constant denoting a Completed Message */ - public final static ControlMessageType COMPLETED = new ControlMessageType("COMPLETED ",(byte)COMPLETED_INT ); - - /** Constant denoting a DecisionExpected Message */ - public final static ControlMessageType DECISIONEXPECTED = new ControlMessageType("DECISIONEXPECTED ",(byte)DECISIONEXPECTED_INT ); - - /** Constant denoting a CreateStream Message */ - public final static ControlMessageType CREATESTREAM = new ControlMessageType("CREATESTREAM ",(byte)CREATESTREAM_INT ); - - /** Constant denoting an AreYouFlushed Message */ - public final static ControlMessageType AREYOUFLUSHED = new ControlMessageType("AREYOUFLUSHED ",(byte)AREYOUFLUSHED_INT ); - - /** Constant denoting a Flushed Message */ - public final static ControlMessageType FLUSHED = new ControlMessageType("FLUSHED ",(byte)FLUSHED_INT ); - - /** Constant denoting a NotFlushed Message */ - public final static ControlMessageType NOTFLUSHED = new ControlMessageType("NOTFLUSHED ",(byte)NOTFLUSHED_INT ); - - /** Constant denoting a RequestFlushed Message */ - public final static ControlMessageType REQUESTFLUSH = new ControlMessageType("REQUESTFLUSH ",(byte)REQUESTFLUSH_INT ); - - /** Constant denoting a RequestCardinalityInfo Message */ - public final static ControlMessageType REQUESTCARDINALITYINFO = new ControlMessageType("REQUESTCARDINALITYINFO ",(byte)REQUESTCARDINALITYINFO_INT ); - - /** Constant denoting a CardinalityInfo Message */ - public final static ControlMessageType CARDINALITYINFO = new ControlMessageType("CARDINALITYINFO ",(byte)CARDINALITYINFO_INT ); - - /** Constant denoting a CreateDurable Message */ - public final static ControlMessageType CREATEDURABLE = new ControlMessageType("CREATEDURABLE ",(byte)CREATEDURABLE_INT ); - - /** Constant denoting a DeleteDurable Message */ - public final static ControlMessageType DELETEDURABLE = new ControlMessageType("DELETEDURABLE ",(byte)DELETEDURABLE_INT ); - - /** Constant denoting a DurableConfirm Message */ - public final static ControlMessageType DURABLECONFIRM = new ControlMessageType("DURABLECONFIRM ",(byte)DURABLECONFIRM_INT ); - - /* Array of defined ControlMessageTypes - needed by getControlMessageType */ - private final static ControlMessageType[] set = {UNKNOWN - ,ACKEXPECTED - ,SILENCE - ,ACK - ,NACK - ,PREVALUE - ,ACCEPT - ,REJECT - ,DECISION - ,REQUEST - ,REQUESTACK - ,REQUESTHIGHESTGENERATEDTICK - ,HIGHESTGENERATEDTICK - ,RESETREQUESTACK - ,RESETREQUESTACKACK - ,BROWSEGET - ,BROWSEEND - ,BROWSESTATUS - ,COMPLETED - ,DECISIONEXPECTED - ,CREATESTREAM - ,AREYOUFLUSHED - ,FLUSHED - ,NOTFLUSHED - ,REQUESTFLUSH - ,REQUESTCARDINALITYINFO - ,CARDINALITYINFO - ,CREATEDURABLE - ,DELETEDURABLE - ,DURABLECONFIRM - }; - - private String name; - private Byte value; - private int intValue; - - /* Private constructor - ensures the 'constants' defined here are the total set. */ - private ControlMessageType(String aName, byte aValue) { - name = aName; - value = Byte.valueOf(aValue); - intValue = (int)aValue; - } - - /** - * Returns the corresponding ControlMessageType for a given integer. - * This method should NOT be called by any code outside the MFP component. - * It is only public so that it can be accessed by sub-packages. - * - * @param aValue The integer for which an ControlMessageType is required. - * - * @return The corresponding ControlMessageType - */ - public final static ControlMessageType getControlMessageType(Byte aValue) { - if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(tc,"Value = " + aValue); - return set[aValue.intValue()]; - } - - /** - * Returns the Byte representation of the ControlMessageType. - * This method should NOT be called by any code outside the MFP component. - * It is only public so that it can be accessed by sub-packages. - * - * @return The Byte representation of the instance. - */ - public final Byte toByte() { - return value; - } - - /** - * Returns the integer representation of the ControlMessageType. - * This method should NOT be called by any code outside the MFP component. - * It is only public so that it can be accessed by sub-packages. - * - * @return The int representation of the instance. - */ - public final int toInt() { - return intValue; - } - - /** - * Returns the name of the ControlMessageType. - * - * @return The name of the instance. - */ - public final String toString() { - return name; - } - +public enum ControlMessageType implements IntAble { + /** Constant denoting an indeterminate DDD Message */ + UNKNOWN(0, false), + /** Constant denoting an Ack Expected Messge */ + ACKEXPECTED(1, false), + /** Constant denoting a Silence Message */ + SILENCE(2, false), + /** Constant denoting an Ack Message */ + ACK(3, false), + /** Constant denoting a Nack Message */ + NACK(4, false), + /** Constant denoting a Prevalue Message */ + PREVALUE(5, false), + /** Constant denoting an Accept Message */ + ACCEPT(6, false), + /** Constant denoting a Reject Message */ + REJECT(7, false), + /** Constant denoting a Decision Message */ + DECISION(8, false), + /** Constant denoting a Request Message */ + REQUEST(9), + /** Constant denoting a RequestAck Message */ + REQUESTACK(10), + /** Constant denoting a RequestHighestGeneratedTick Message */ + REQUESTHIGHESTGENERATEDTICK(11), + /** Constant denoting a HighestGeneratedTick Message */ + HIGHESTGENERATEDTICK(12), + /** Constant denoting a RequestRequestAck Message */ + RESETREQUESTACK(13), + /** Constant denoting a RequestRequestAckAck Message */ + RESETREQUESTACKACK(14), + /** Constant denoting a BrowseGet Message */ + BROWSEGET(15), + /** Constant denoting a BrowseEnd Message */ + BROWSEEND(16), + /** Constant denoting a BrowseStatus Message */ + BROWSESTATUS(17), + /** Constant denoting a Completed Message */ + COMPLETED(18), + /** Constant denoting a DecisionExpected Message */ + DECISIONEXPECTED(19), + /** Constant denoting a CreateStream Message */ + CREATESTREAM(20), + /** Constant denoting an AreYouFlushed Message */ + AREYOUFLUSHED(21), + /** Constant denoting a Flushed Message */ + FLUSHED(22), + /** Constant denoting a NotFlushed Message */ + NOTFLUSHED(23), + /** Constant denoting a RequestFlushed Message */ + REQUESTFLUSH(24), + /** Constant denoting a RequestCardinalityInfo Message */ + REQUESTCARDINALITYINFO(25), + /** Constant denoting a CardinalityInfo Message */ + CARDINALITYINFO(26), + /** Constant denoting a CreateDurable Message */ + CREATEDURABLE(27), + /** Constant denoting a DeleteDurable Message */ + DELETEDURABLE(28), + /** Constant denoting a DurableConfirm Message */ + DURABLECONFIRM(29), + ; + + private static final TraceComponent tc = register(ControlMessageType.class, MSG_GROUP, MSG_BUNDLE); + + private static String format(String name) { return String.format("%-27s", name); } + + /** Integer value of the Control Message Types */ + public static final int UNKNOWN_INT = UNKNOWN.toInt(); + public static final int ACKEXPECTED_INT = ACKEXPECTED.toInt(); + public static final int SILENCE_INT = SILENCE.toInt(); + public static final int ACK_INT = ACK.toInt(); + public static final int NACK_INT = NACK.toInt(); + public static final int PREVALUE_INT = PREVALUE.toInt(); + public static final int ACCEPT_INT = ACCEPT.toInt(); + public static final int REJECT_INT = REJECT.toInt(); + public static final int DECISION_INT = DECISION.toInt(); + public static final int REQUEST_INT = REQUEST.toInt(); + public static final int REQUESTACK_INT = REQUESTACK.toInt(); + public static final int REQUESTHIGHESTGENERATEDTICK_INT = REQUESTHIGHESTGENERATEDTICK.toInt(); + public static final int HIGHESTGENERATEDTICK_INT = HIGHESTGENERATEDTICK.toInt(); + public static final int RESETREQUESTACK_INT = RESETREQUESTACK.toInt(); + public static final int RESETREQUESTACKACK_INT = RESETREQUESTACKACK.toInt(); + public static final int BROWSEGET_INT = BROWSEGET.toInt(); + public static final int BROWSEEND_INT = BROWSEEND.toInt(); + public static final int BROWSESTATUS_INT = BROWSESTATUS.toInt(); + public static final int COMPLETED_INT = COMPLETED.toInt(); + public static final int DECISIONEXPECTED_INT = DECISIONEXPECTED.toInt(); + public static final int CREATESTREAM_INT = CREATESTREAM.toInt(); + public static final int AREYOUFLUSHED_INT = AREYOUFLUSHED.toInt(); + public static final int FLUSHED_INT = FLUSHED.toInt(); + public static final int NOTFLUSHED_INT = NOTFLUSHED.toInt(); + public static final int REQUESTFLUSH_INT = REQUESTFLUSH.toInt(); + public static final int REQUESTCARDINALITYINFO_INT = REQUESTCARDINALITYINFO.toInt(); + public static final int CARDINALITYINFO_INT = CARDINALITYINFO.toInt(); + public static final int CREATEDURABLE_INT = CREATEDURABLE.toInt(); + public static final int DELETEDURABLE_INT = DELETEDURABLE.toInt(); + public static final int DURABLECONFIRM_INT = DURABLECONFIRM.toInt(); + + private static final Map types; + + static { + Map map = new HashMap<>(); + for (ControlMessageType type: values()) map.put(type.toInt(), type); + types = unmodifiableMap(map); + } + + private final Function nameFormatter; + private final Byte value; + private final int intValue; + + private ControlMessageType(int aValue) { + this(aValue, true); + } + + private ControlMessageType(int aValue, boolean customFormatted) { + nameFormatter = customFormatted ? ControlMessageType::format : s -> s; + value = Byte.valueOf((byte)aValue); + intValue = aValue; + } + + + /** + * Returns the corresponding ControlMessageType for a given integer. + * This method should NOT be called by any code outside the MFP component. + * It is only public so that it can be accessed by sub-packages. + * + * @param aValue The integer for which an ControlMessageType is required. + * + * @return The corresponding ControlMessageType + */ + public static final ControlMessageType getControlMessageType(Byte aValue) { + if (isAnyTracingEnabled() && tc.isDebugEnabled()) debug(tc,"Value = " + aValue); + return types.get(aValue.intValue()); + } + + /** + * Returns the Byte representation of the ControlMessageType. + * This method should NOT be called by any code outside the MFP component. + * It is only public so that it can be accessed by sub-packages. + * + * @return The Byte representation of the instance. + */ + public final Byte toByte() { + return value; + } + + /** + * Returns the integer representation of the ControlMessageType. + * This method should NOT be called by any code outside the MFP component. + * It is only public so that it can be accessed by sub-packages. + * + * @return The int representation of the instance. + */ + public final int toInt() { + return intValue; + } + + /** + * Returns the name of the ControlMessageType. + * + * @return The name of the instance. + */ + @Override + public final String toString() { + return nameFormatter.apply(name()); + } } From 9bab06fb6333e4d1b802b6b741a1f1d70f139d84 Mon Sep 17 00:00:00 2001 From: Neil Richards <7203556+ngmr@users.noreply.github.com> Date: Fri, 15 Nov 2024 19:51:25 +0000 Subject: [PATCH 15/67] refactor: convert SubscriptionMessageType to enum --- .../mfp/control/SubscriptionMessageType.java | 167 +++++++++--------- 1 file changed, 79 insertions(+), 88 deletions(-) diff --git a/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/control/SubscriptionMessageType.java b/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/control/SubscriptionMessageType.java index 456c84a6059..c2b64376546 100644 --- a/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/control/SubscriptionMessageType.java +++ b/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/control/SubscriptionMessageType.java @@ -1,105 +1,96 @@ -/******************************************************************************* - * Copyright (c) 2012 IBM Corporation and others. +/* ============================================================================= + * Copyright (c) 2012,2024 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * * Contributors: * IBM Corporation - initial API and implementation - *******************************************************************************/ + * ============================================================================= + */ package com.ibm.ws.sib.mfp.control; -import com.ibm.ws.sib.mfp.*; -import com.ibm.ws.sib.utils.ras.SibTr; +import static com.ibm.websphere.ras.TraceComponent.isAnyTracingEnabled; +import static com.ibm.ws.sib.mfp.MfpConstants.MSG_BUNDLE; +import static com.ibm.ws.sib.mfp.MfpConstants.MSG_GROUP; +import static com.ibm.ws.sib.utils.ras.SibTr.debug; +import static com.ibm.ws.sib.utils.ras.SibTr.register; +import static java.util.Collections.unmodifiableMap; + +import java.util.HashMap; +import java.util.Map; + import com.ibm.websphere.ras.TraceComponent; +import com.ibm.ws.sib.mfp.IntAble; /** * SubscriptionMessageType is a type-safe enumeration which indicates the type of a * Subscription Propagation message. */ -public final class SubscriptionMessageType implements IntAble { - - private static TraceComponent tc = SibTr.register(SubscriptionMessageType.class, MfpConstants.MSG_GROUP, MfpConstants.MSG_BUNDLE); - - /** Integer value of the Subscription Message Types */ - public final static int UNKNOWN_INT = 0; - public final static int RESET_INT = 1; - public final static int CREATE_INT = 2; - public final static int DELETE_INT = 3; - public final static int REQUEST_INT = 4; - public final static int REPLY_INT = 5; - - /** Constant denoting an indeterminate Subscription Propagation Message */ - public final static SubscriptionMessageType UNKNOWN = new SubscriptionMessageType("UNKNOWN" ,UNKNOWN_INT ); - - /** Constant denoting a Reset Message */ - public final static SubscriptionMessageType RESET = new SubscriptionMessageType("RESET" ,RESET_INT ); - - /** Constant denoting a Create Message */ - public final static SubscriptionMessageType CREATE = new SubscriptionMessageType("CREATE" ,CREATE_INT ); - - /** Constant denoting a Delete Message */ - public final static SubscriptionMessageType DELETE = new SubscriptionMessageType("DELETE" ,DELETE_INT ); - - /** Constant denoting a Request Message */ - public final static SubscriptionMessageType REQUEST = new SubscriptionMessageType("REQUEST" ,REQUEST_INT ); - - /** Constant denoting a Reply Message */ - public final static SubscriptionMessageType REPLY = new SubscriptionMessageType("REPLY" ,REPLY_INT ); - - /* Array of defined SubscriptionMessageTypes - needed by getSubscriptionMessageType */ - private final static SubscriptionMessageType[] set = {UNKNOWN - ,RESET - ,CREATE - ,DELETE - ,REQUEST - ,REPLY - }; - - private String name; - private int value; - - /* Private constructor - ensures the 'constants' defined here are the total set. */ - private SubscriptionMessageType(String aName, int aValue) { - name = aName; - value = aValue; - } - - /** - * Returns the corresponding SubscriptionMessageType for a given integer. - * This method should NOT be called by any code outside the MFP component. - * It is only public so that it can be accessed by sub-packages. - * - * @param aValue The integer for which an SubscriptionMessageType is required. - * - * @return The corresponding SubscriptionMessageType - */ - public final static SubscriptionMessageType getSubscriptionMessageType(int aValue) { - if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(tc,"Value = " + aValue); - return set[aValue]; - } - - /** - * Returns the integer representation of the SubscriptionMessageType. - * This method should NOT be called by any code outside the MFP component. - * It is only public so that it can be accessed by sub-packages. - * - * @return The int representation of the instance. - */ - public final int toInt() { - return value; - } - - /** - * Returns the name of the SubscriptionMessageType. - * - * @return The name of the instance. - */ - public final String toString() { - return name; - } - +public enum SubscriptionMessageType implements IntAble { + /** Constant denoting an indeterminate Subscription Propagation Message */ + UNKNOWN(0), + /** Constant denoting a Reset Message */ + RESET(1), + /** Constant denoting a Create Message */ + CREATE(2), + /** Constant denoting a Delete Message */ + DELETE(3), + /** Constant denoting a Request Message */ + REQUEST(4), + /** Constant denoting a Reply Message */ + REPLY(5), + ; + + private static final TraceComponent tc = register(SubscriptionMessageType.class, MSG_GROUP, MSG_BUNDLE); + + /** Integer value of the Subscription Message Types */ + public static final int UNKNOWN_INT = UNKNOWN.toInt(); + public static final int RESET_INT = RESET.toInt(); + public static final int CREATE_INT = CREATE.toInt(); + public static final int DELETE_INT = DELETE.toInt(); + public static final int REQUEST_INT = REQUEST.toInt(); + public static final int REPLY_INT = REPLY.toInt(); + + private static final Map types; + + static { + Map map = new HashMap<>(); + for (SubscriptionMessageType type: values()) map.put(type.toInt(), type); + types = unmodifiableMap(map); + } + + private final int value; + + private SubscriptionMessageType(int aValue) { + value = aValue; + } + + /** + * Returns the corresponding SubscriptionMessageType for a given integer. + * This method should NOT be called by any code outside the MFP component. + * It is only public so that it can be accessed by sub-packages. + * + * @param aValue The integer for which an SubscriptionMessageType is required. + * + * @return The corresponding SubscriptionMessageType + */ + public static final SubscriptionMessageType getSubscriptionMessageType(int aValue) { + if (isAnyTracingEnabled() && tc.isDebugEnabled()) debug(tc,"Value = " + aValue); + return types.get(aValue); + } + + /** + * Returns the integer representation of the SubscriptionMessageType. + * This method should NOT be called by any code outside the MFP component. + * It is only public so that it can be accessed by sub-packages. + * + * @return The int representation of the instance. + */ + public final int toInt() { + return value; + } } From 1b1330d183730061f8b5ea48114c4c18c517309b Mon Sep 17 00:00:00 2001 From: Neil Richards <7203556+ngmr@users.noreply.github.com> Date: Mon, 18 Nov 2024 12:41:02 +0000 Subject: [PATCH 16/67] fix: use SubscriptionMessageType enum in switch --- .../mfp/control/SubscriptionMessageType.java | 8 -- .../sib/mfp/impl/SubscriptionMessageImpl.java | 11 +- .../proxyhandler/NeighbourProxyListener.java | 105 +++++++----------- 3 files changed, 46 insertions(+), 78 deletions(-) diff --git a/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/control/SubscriptionMessageType.java b/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/control/SubscriptionMessageType.java index c2b64376546..c3706bd2dbe 100644 --- a/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/control/SubscriptionMessageType.java +++ b/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/control/SubscriptionMessageType.java @@ -47,14 +47,6 @@ public enum SubscriptionMessageType implements IntAble { private static final TraceComponent tc = register(SubscriptionMessageType.class, MSG_GROUP, MSG_BUNDLE); - /** Integer value of the Subscription Message Types */ - public static final int UNKNOWN_INT = UNKNOWN.toInt(); - public static final int RESET_INT = RESET.toInt(); - public static final int CREATE_INT = CREATE.toInt(); - public static final int DELETE_INT = DELETE.toInt(); - public static final int REQUEST_INT = REQUEST.toInt(); - public static final int REPLY_INT = REPLY.toInt(); - private static final Map types; static { diff --git a/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/impl/SubscriptionMessageImpl.java b/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/impl/SubscriptionMessageImpl.java index cdb608d8923..e55fcca00c6 100644 --- a/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/impl/SubscriptionMessageImpl.java +++ b/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/impl/SubscriptionMessageImpl.java @@ -1,15 +1,16 @@ -/******************************************************************************* - * Copyright (c) 2012 IBM Corporation and others. +/* ============================================================================= + * Copyright (c) 2012,2024 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * * Contributors: * IBM Corporation - initial API and implementation - *******************************************************************************/ + * ============================================================================= + */ package com.ibm.ws.sib.mfp.impl; import java.util.ArrayList; @@ -80,7 +81,7 @@ public class SubscriptionMessageImpl extends JsMessageImpl implements Subscripti setProducerType(ProducerType.MP); /* Default all the fields */ - setSubtype(SubscriptionMessageType.UNKNOWN_INT); + setSubtype(SubscriptionMessageType.UNKNOWN.toInt()); setTopics(null); setTopicSpaces(null); setTopicSpaceMappings(null); diff --git a/dev/com.ibm.ws.messaging.runtime/src/com/ibm/ws/sib/processor/proxyhandler/NeighbourProxyListener.java b/dev/com.ibm.ws.messaging.runtime/src/com/ibm/ws/sib/processor/proxyhandler/NeighbourProxyListener.java index d7f496838fa..c7ca885286b 100644 --- a/dev/com.ibm.ws.messaging.runtime/src/com/ibm/ws/sib/processor/proxyhandler/NeighbourProxyListener.java +++ b/dev/com.ibm.ws.messaging.runtime/src/com/ibm/ws/sib/processor/proxyhandler/NeighbourProxyListener.java @@ -1,5 +1,5 @@ -/******************************************************************************* - * Copyright (c) 2012 IBM Corporation and others. +/* ============================================================================= + * Copyright (c) 2012,2024 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at @@ -9,7 +9,8 @@ * * Contributors: * IBM Corporation - initial API and implementation - *******************************************************************************/ + * ============================================================================= + */ package com.ibm.ws.sib.processor.proxyhandler; import java.util.ArrayList; @@ -198,43 +199,28 @@ public void consumeMessages(LockedMessageEnumeration messages) throws Exception // Get a transaction to operate under transaction = iProxyHandler.getTransactionManager().createLocalTransaction(true); - switch (subMessage.getSubscriptionMessageType().toInt()) - { - case SubscriptionMessageType.CREATE_INT : - + switch (subMessage.getSubscriptionMessageType()) { + case CREATE: // Create a new Proxy subscription handleCreateProxySubscription(subMessage, (Transaction) transaction); - break; - - case SubscriptionMessageType.DELETE_INT : - + case DELETE: // Delete a proxy subscription handleDeleteProxySubscription(subMessage, (Transaction) transaction); - break; - - case SubscriptionMessageType.RESET_INT : - + case RESET: // Reset the subscription state. handleResetState(subMessage, (Transaction) transaction, false); - break; - - case SubscriptionMessageType.REQUEST_INT : - + case REQUEST: // Reset the subscription state. handleResetState(subMessage, (Transaction) transaction, true); - break; - - case SubscriptionMessageType.REPLY_INT : - + case REPLY: // Reset the subscription state. handleResetState(subMessage, (Transaction) transaction, false); - break; - default : + default : // Log Message break; } @@ -317,50 +303,39 @@ void handleRollback(SubscriptionMessage subMessage, } Transaction msTran = iProxyHandler.getMessageProcessor().resolveAndEnlistMsgStoreTransaction(transaction); - - switch (subMessage.getSubscriptionMessageType().toInt()) - { - case SubscriptionMessageType.CREATE_INT : - + switch (subMessage.getSubscriptionMessageType()) { + case CREATE: // Remove any created Proxy subscriptions - iProxyHandler.remoteUnsubscribeEvent(iAddTopicSpaces, - iAddTopics, - subMessage.getBus(), - msTran, - false); - + iProxyHandler.remoteUnsubscribeEvent(iAddTopicSpaces, + iAddTopics, + subMessage.getBus(), + msTran, + false); break; - - case SubscriptionMessageType.DELETE_INT : - - // Create any removed Proxy subscriptions - iProxyHandler.remoteSubscribeEvent(iDeleteTopicSpaces, - iDeleteTopics, - subMessage.getBus(), - msTran, - false); - + case DELETE: + // Create any removed Proxy subscriptions + iProxyHandler.remoteSubscribeEvent(iDeleteTopicSpaces, + iDeleteTopics, + subMessage.getBus(), + msTran, + false); break; - - case SubscriptionMessageType.RESET_INT : - - // Remove any created Proxy subscriptions - iProxyHandler.remoteUnsubscribeEvent(iAddTopicSpaces, - iAddTopics, - subMessage.getBus(), - msTran, - false); - - // Create any removed Proxy subscriptions - iProxyHandler.remoteSubscribeEvent(iDeleteTopicSpaces, - iDeleteTopics, - subMessage.getBus(), - msTran, - false); - + case RESET: + // Remove any created Proxy subscriptions + iProxyHandler.remoteUnsubscribeEvent(iAddTopicSpaces, + iAddTopics, + subMessage.getBus(), + msTran, + false); + + // Create any removed Proxy subscriptions + iProxyHandler.remoteSubscribeEvent(iDeleteTopicSpaces, + iDeleteTopics, + subMessage.getBus(), + msTran, + false); break; - - default : + default : // Log Message break; } From 977084c2da62f9306efc70e2e907f5b7fb0eb441 Mon Sep 17 00:00:00 2001 From: Neil Richards <7203556+ngmr@users.noreply.github.com> Date: Mon, 18 Nov 2024 12:30:08 +0000 Subject: [PATCH 17/67] fix: use ControlMessageType enum in switch --- .../sib/mfp/control/ControlMessageType.java | 36 +------ .../mfp/impl/ControlMessageFactoryImpl.java | 99 +++++++------------ 2 files changed, 39 insertions(+), 96 deletions(-) diff --git a/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/control/ControlMessageType.java b/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/control/ControlMessageType.java index dfc6ce9c843..165934a011d 100644 --- a/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/control/ControlMessageType.java +++ b/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/control/ControlMessageType.java @@ -98,38 +98,6 @@ public enum ControlMessageType implements IntAble { private static String format(String name) { return String.format("%-27s", name); } - /** Integer value of the Control Message Types */ - public static final int UNKNOWN_INT = UNKNOWN.toInt(); - public static final int ACKEXPECTED_INT = ACKEXPECTED.toInt(); - public static final int SILENCE_INT = SILENCE.toInt(); - public static final int ACK_INT = ACK.toInt(); - public static final int NACK_INT = NACK.toInt(); - public static final int PREVALUE_INT = PREVALUE.toInt(); - public static final int ACCEPT_INT = ACCEPT.toInt(); - public static final int REJECT_INT = REJECT.toInt(); - public static final int DECISION_INT = DECISION.toInt(); - public static final int REQUEST_INT = REQUEST.toInt(); - public static final int REQUESTACK_INT = REQUESTACK.toInt(); - public static final int REQUESTHIGHESTGENERATEDTICK_INT = REQUESTHIGHESTGENERATEDTICK.toInt(); - public static final int HIGHESTGENERATEDTICK_INT = HIGHESTGENERATEDTICK.toInt(); - public static final int RESETREQUESTACK_INT = RESETREQUESTACK.toInt(); - public static final int RESETREQUESTACKACK_INT = RESETREQUESTACKACK.toInt(); - public static final int BROWSEGET_INT = BROWSEGET.toInt(); - public static final int BROWSEEND_INT = BROWSEEND.toInt(); - public static final int BROWSESTATUS_INT = BROWSESTATUS.toInt(); - public static final int COMPLETED_INT = COMPLETED.toInt(); - public static final int DECISIONEXPECTED_INT = DECISIONEXPECTED.toInt(); - public static final int CREATESTREAM_INT = CREATESTREAM.toInt(); - public static final int AREYOUFLUSHED_INT = AREYOUFLUSHED.toInt(); - public static final int FLUSHED_INT = FLUSHED.toInt(); - public static final int NOTFLUSHED_INT = NOTFLUSHED.toInt(); - public static final int REQUESTFLUSH_INT = REQUESTFLUSH.toInt(); - public static final int REQUESTCARDINALITYINFO_INT = REQUESTCARDINALITYINFO.toInt(); - public static final int CARDINALITYINFO_INT = CARDINALITYINFO.toInt(); - public static final int CREATEDURABLE_INT = CREATEDURABLE.toInt(); - public static final int DELETEDURABLE_INT = DELETEDURABLE.toInt(); - public static final int DURABLECONFIRM_INT = DURABLECONFIRM.toInt(); - private static final Map types; static { @@ -167,6 +135,10 @@ public static final ControlMessageType getControlMessageType(Byte aValue) { return types.get(aValue.intValue()); } + public static final ControlMessageType getControlMessageType(int aValue) { + return types.get(aValue); + } + /** * Returns the Byte representation of the ControlMessageType. * This method should NOT be called by any code outside the MFP component. diff --git a/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/impl/ControlMessageFactoryImpl.java b/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/impl/ControlMessageFactoryImpl.java index f478a7b0280..becf38f72e0 100644 --- a/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/impl/ControlMessageFactoryImpl.java +++ b/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/impl/ControlMessageFactoryImpl.java @@ -1,15 +1,16 @@ -/******************************************************************************* - * Copyright (c) 2012 IBM Corporation and others. +/* ============================================================================= + * Copyright (c) 2012,2024 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * * Contributors: * IBM Corporation - initial API and implementation - *******************************************************************************/ + * ============================================================================= + */ package com.ibm.ws.sib.mfp.impl; import java.util.List; @@ -819,124 +820,94 @@ private final ControlMessage makeInboundControlMessage(JsMsgObject jmo, int mess ControlMessage controlMessage = null; /* Create an instance of the appropriate message subclass */ - switch (messageType) { - - case ControlMessageType.ACKEXPECTED_INT: + switch (ControlMessageType.getControlMessageType(messageType)) { + case ACKEXPECTED: controlMessage = new ControlAckExpectedImpl(jmo); break; - - case ControlMessageType.SILENCE_INT: + case SILENCE: controlMessage = new ControlSilenceImpl(jmo); break; - - case ControlMessageType.ACK_INT: + case ACK: controlMessage = new ControlAckImpl(jmo); break; - - case ControlMessageType.NACK_INT: + case NACK: controlMessage = new ControlNackImpl(jmo); break; - - case ControlMessageType.PREVALUE_INT: + case PREVALUE: controlMessage = new ControlPrevalueImpl(jmo); break; - - case ControlMessageType.ACCEPT_INT: + case ACCEPT: controlMessage = new ControlAcceptImpl(jmo); break; - - case ControlMessageType.REJECT_INT: + case REJECT: controlMessage = new ControlRejectImpl(jmo); break; - - case ControlMessageType.DECISION_INT: + case DECISION: controlMessage = new ControlDecisionImpl(jmo); break; - - case ControlMessageType.REQUEST_INT: + case REQUEST: controlMessage = new ControlRequestImpl(jmo); break; - - case ControlMessageType.REQUESTACK_INT: + case REQUESTACK: controlMessage = new ControlRequestAckImpl(jmo); break; - - case ControlMessageType.REQUESTHIGHESTGENERATEDTICK_INT: + case REQUESTHIGHESTGENERATEDTICK: controlMessage = new ControlRequestHighestGeneratedTickImpl(jmo); break; - - case ControlMessageType.HIGHESTGENERATEDTICK_INT: + case HIGHESTGENERATEDTICK: controlMessage = new ControlHighestGeneratedTickImpl(jmo); break; - - case ControlMessageType.RESETREQUESTACK_INT: + case RESETREQUESTACK: controlMessage = new ControlResetRequestAckImpl(jmo); break; - - case ControlMessageType.RESETREQUESTACKACK_INT: + case RESETREQUESTACKACK: controlMessage = new ControlResetRequestAckAckImpl(jmo); break; - - case ControlMessageType.BROWSEGET_INT: + case BROWSEGET: controlMessage = new ControlBrowseGetImpl(jmo); break; - - case ControlMessageType.BROWSEEND_INT: + case BROWSEEND: controlMessage = new ControlBrowseEndImpl(jmo); break; - - case ControlMessageType.BROWSESTATUS_INT: + case BROWSESTATUS: controlMessage = new ControlBrowseStatusImpl(jmo); break; - - case ControlMessageType.COMPLETED_INT: + case COMPLETED: controlMessage = new ControlCompletedImpl(jmo); break; - - case ControlMessageType.DECISIONEXPECTED_INT: + case DECISIONEXPECTED: controlMessage = new ControlDecisionExpectedImpl(jmo); break; - - case ControlMessageType.CREATESTREAM_INT: + case CREATESTREAM: controlMessage = new ControlCreateStreamImpl(jmo); break; - - case ControlMessageType.AREYOUFLUSHED_INT: + case AREYOUFLUSHED: controlMessage = new ControlAreYouFlushedImpl(jmo); break; - - case ControlMessageType.FLUSHED_INT: + case FLUSHED: controlMessage = new ControlFlushedImpl(jmo); break; - - case ControlMessageType.NOTFLUSHED_INT: + case NOTFLUSHED: controlMessage = new ControlNotFlushedImpl(jmo); break; - - case ControlMessageType.REQUESTFLUSH_INT: + case REQUESTFLUSH: controlMessage = new ControlRequestFlushImpl(jmo); break; - - case ControlMessageType.REQUESTCARDINALITYINFO_INT: + case REQUESTCARDINALITYINFO: controlMessage = new ControlRequestCardinalityInfoImpl(jmo); break; - - case ControlMessageType.CARDINALITYINFO_INT: + case CARDINALITYINFO: controlMessage = new ControlCardinalityInfoImpl(jmo); break; - - case ControlMessageType.CREATEDURABLE_INT: + case CREATEDURABLE: controlMessage = new ControlCreateDurableImpl(jmo); break; - - case ControlMessageType.DELETEDURABLE_INT: + case DELETEDURABLE: controlMessage = new ControlDeleteDurableImpl(jmo); break; - - case ControlMessageType.DURABLECONFIRM_INT: + case DURABLECONFIRM: controlMessage = new ControlDurableConfirmImpl(jmo); break; - default: /* This shouldn't happen at the moment but will provide some support */ /* for new types being added by future releases & arriving at an old */ From f14a34cb7d86479e75b6ffcb2c44d89ef2aa7962 Mon Sep 17 00:00:00 2001 From: Neil Richards <7203556+ngmr@users.noreply.github.com> Date: Fri, 15 Nov 2024 20:34:43 +0000 Subject: [PATCH 18/67] refactor: convert TrmMessageType to enum --- .../ibm/ws/sib/mfp/trm/TrmMessageType.java | 119 +++++++++--------- 1 file changed, 59 insertions(+), 60 deletions(-) diff --git a/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/trm/TrmMessageType.java b/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/trm/TrmMessageType.java index 5035f4d9e3c..091acc72430 100644 --- a/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/trm/TrmMessageType.java +++ b/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/trm/TrmMessageType.java @@ -1,86 +1,85 @@ -/******************************************************************************* - * Copyright (c) 2012 IBM Corporation and others. +/* ============================================================================= + * Copyright (c) 2012,2024 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * * Contributors: * IBM Corporation - initial API and implementation - *******************************************************************************/ + * ============================================================================= + */ package com.ibm.ws.sib.mfp.trm; -import com.ibm.ws.sib.mfp.*; -import com.ibm.ws.sib.utils.ras.SibTr; +import static com.ibm.websphere.ras.TraceComponent.isAnyTracingEnabled; +import static com.ibm.ws.sib.mfp.MfpConstants.MSG_BUNDLE; +import static com.ibm.ws.sib.mfp.MfpConstants.MSG_GROUP; +import static com.ibm.ws.sib.utils.ras.SibTr.debug; +import static com.ibm.ws.sib.utils.ras.SibTr.register; +import static java.util.Collections.unmodifiableMap; + +import java.util.HashMap; +import java.util.Map; + import com.ibm.websphere.ras.TraceComponent; +import com.ibm.ws.sib.mfp.IntAble; /** * TrmMessageType is a type-safe enumeration which indicates the type of a TRM * message. */ -public final class TrmMessageType implements IntAble { - - private static TraceComponent tc = SibTr.register(TrmMessageType.class, MfpConstants.MSG_GROUP, MfpConstants.MSG_BUNDLE); - - /** Integer value of the Trm Message Types */ - public final static int UNKNOWN_INT = 0; - public final static int ROUTE_DATA_INT = 1; - - /** Constant denoting an indeterminate TRM Message */ - public final static TrmMessageType UNKNOWN = new TrmMessageType("UNKNOWN" ,UNKNOWN_INT ); +public enum TrmMessageType implements IntAble { + /** Constant denoting an indeterminate TRM Message */ + UNKNOWN(0), + /** Constant denoting a Route data Message */ + ROUTE_DATA(1), + ; - /** Constant denoting a Route data Message */ - public final static TrmMessageType ROUTE_DATA = new TrmMessageType("ROUTE_DATA" ,ROUTE_DATA_INT ); + private static final TraceComponent tc = register(TrmMessageType.class, MSG_GROUP, MSG_BUNDLE); - /* Array of defined TrmMessageTypes - needed by getTrmMessageType */ - private final static TrmMessageType[] set = {UNKNOWN - ,ROUTE_DATA - }; + /** Integer value of the Trm Message Types */ + public static final int UNKNOWN_INT = UNKNOWN.toInt(); + public static final int ROUTE_DATA_INT = ROUTE_DATA.toInt(); - private String name; - private int value; + private static final Map types; - /* Private constructor - ensures the 'constants' defined here are the total set. */ - private TrmMessageType(String aName, int aValue) { - name = aName; - value = aValue; - } + static { + Map map = new HashMap<>(); + for (TrmMessageType type: values()) map.put(type.toInt(), type); + types = unmodifiableMap(map); + } - /** - * Returns the corresponding TrmMessageType for a given integer. - * This method should NOT be called by any code outside the MFP component. - * It is only public so that it can be accessed by sub-packages. - * - * @param aValue The integer for which an TrmMessageType is required. - * - * @return The corresponding TrmMessageType - */ - public final static TrmMessageType getTrmMessageType(int aValue) { - if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(tc,"Value = " + aValue); - return set[aValue]; - } + private final int value; - /** - * Returns the integer representation of the TrmMessageType. - * This method should NOT be called by any code outside the MFP component. - * It is only public so that it can be accessed by sub-packages. - * - * @return The int representation of the instance. - */ - public final int toInt() { - return value; - } + private TrmMessageType(int aValue) { + value = aValue; + } - /** - * Returns the name of the TrmMessageType. - * - * @return The name of the instance. - */ - public final String toString() { - return name; - } + /** + * Returns the corresponding TrmMessageType for a given integer. + * This method should NOT be called by any code outside the MFP component. + * It is only public so that it can be accessed by sub-packages. + * + * @param aValue The integer for which an TrmMessageType is required. + * + * @return The corresponding TrmMessageType + */ + public static final TrmMessageType getTrmMessageType(int aValue) { + if (isAnyTracingEnabled() && tc.isDebugEnabled()) debug(tc,"Value = " + aValue); + return types.get(aValue); + } + /** + * Returns the integer representation of the TrmMessageType. + * This method should NOT be called by any code outside the MFP component. + * It is only public so that it can be accessed by sub-packages. + * + * @return The int representation of the instance. + */ + public final int toInt() { + return value; + } } From 6de3c89ac196fa39ccf92deabecd9b6996d14673 Mon Sep 17 00:00:00 2001 From: Neil Richards <7203556+ngmr@users.noreply.github.com> Date: Mon, 18 Nov 2024 12:51:04 +0000 Subject: [PATCH 19/67] fix: use TrmMessageType enum in switch --- .../sib/mfp/impl/TrmMessageFactoryImpl.java | 20 ++++++++++--------- .../ibm/ws/sib/mfp/impl/TrmRouteDataImpl.java | 11 +++++----- .../ibm/ws/sib/mfp/trm/TrmMessageType.java | 4 ---- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/impl/TrmMessageFactoryImpl.java b/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/impl/TrmMessageFactoryImpl.java index c82723d570a..317bebf4650 100644 --- a/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/impl/TrmMessageFactoryImpl.java +++ b/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/impl/TrmMessageFactoryImpl.java @@ -1,21 +1,25 @@ -/******************************************************************************* - * Copyright (c) 2012 IBM Corporation and others. +/* ============================================================================= + * Copyright (c) 2012,2024 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * * Contributors: * IBM Corporation - initial API and implementation - *******************************************************************************/ + * ============================================================================= + */ package com.ibm.ws.sib.mfp.impl; import com.ibm.ws.sib.mfp.*; import com.ibm.ws.sib.mfp.schema.TrmFirstContactAccess; import com.ibm.ws.sib.mfp.trm.*; import com.ibm.ws.sib.utils.ras.SibTr; + +import static com.ibm.ws.sib.mfp.trm.TrmMessageType.getTrmMessageType; + import com.ibm.websphere.ras.TraceComponent; /** @@ -392,13 +396,11 @@ final TrmMessage createInboundTrmMessage(JsMsgObject jmo, int messageType) { TrmMessage trmMessage = null; /* Create an instance of the appropriate message subclass */ - switch (messageType) { - - case TrmMessageType.ROUTE_DATA_INT: + switch (getTrmMessageType(messageType)) { + case ROUTE_DATA: trmMessage = new TrmRouteDataImpl(jmo); break; - - default: + default: trmMessage = new TrmMessageImpl(jmo); } diff --git a/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/impl/TrmRouteDataImpl.java b/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/impl/TrmRouteDataImpl.java index 56ddfa7c669..f6df48eab72 100644 --- a/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/impl/TrmRouteDataImpl.java +++ b/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/impl/TrmRouteDataImpl.java @@ -1,15 +1,16 @@ -/******************************************************************************* - * Copyright (c) 2012 IBM Corporation and others. +/* ============================================================================= + * Copyright (c) 2012,2024 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * * Contributors: * IBM Corporation - initial API and implementation - *******************************************************************************/ + * ============================================================================= + */ package com.ibm.ws.sib.mfp.impl; import java.util.List; @@ -56,7 +57,7 @@ final class TrmRouteDataImpl extends TrmMessageImpl implements TrmRouteData { TrmRouteDataImpl(int flag) throws MessageDecodeFailedException { super(flag); if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(tc, ""); - setSubtype(TrmMessageType.ROUTE_DATA_INT); + setSubtype(TrmMessageType.ROUTE_DATA.toInt()); } diff --git a/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/trm/TrmMessageType.java b/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/trm/TrmMessageType.java index 091acc72430..d2103ff9d6b 100644 --- a/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/trm/TrmMessageType.java +++ b/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/trm/TrmMessageType.java @@ -40,10 +40,6 @@ public enum TrmMessageType implements IntAble { private static final TraceComponent tc = register(TrmMessageType.class, MSG_GROUP, MSG_BUNDLE); - /** Integer value of the Trm Message Types */ - public static final int UNKNOWN_INT = UNKNOWN.toInt(); - public static final int ROUTE_DATA_INT = ROUTE_DATA.toInt(); - private static final Map types; static { From e40ec380b9d316db6a0cc687c9600f3f58fcce3f Mon Sep 17 00:00:00 2001 From: Nathan Rauh Date: Tue, 12 Nov 2024 16:37:34 -0600 Subject: [PATCH 20/67] Issue #28595 IllegalArgumentException and message for empty list of entities --- .../resources/CWWKDMessages.nlsprops | 8 +++ .../data/internal/persistence/QueryInfo.java | 39 +++++++++-- .../internal/persistence/RepositoryImpl.java | 16 ++++- .../jakarta/data/web/DataTestServlet.java | 2 - .../errpaths/web/DataErrPathsTestServlet.java | 69 +++++++++++++++++++ .../jakarta/data/errpaths/web/Voters.java | 5 ++ 6 files changed, 131 insertions(+), 8 deletions(-) diff --git a/dev/io.openliberty.data.internal.persistence/resources/io/openliberty/data/internal/persistence/resources/CWWKDMessages.nlsprops b/dev/io.openliberty.data.internal.persistence/resources/io/openliberty/data/internal/persistence/resources/CWWKDMessages.nlsprops index 8dbac31d740..c9b4c29a173 100644 --- a/dev/io.openliberty.data.internal.persistence/resources/io/openliberty/data/internal/persistence/resources/CWWKDMessages.nlsprops +++ b/dev/io.openliberty.data.internal.persistence/resources/io/openliberty/data/internal/persistence/resources/CWWKDMessages.nlsprops @@ -908,3 +908,11 @@ CWWKD1090.orderby.conflict.explanation=The OrderBy annotation is not compatible with the OrderBy keyword. CWWKD1090.orderby.conflict.useraction=Use only the OrderBy annotation or the \ OrderBy keyword. + +CWWKD1092.lifecycle.arg.empty=CWWKD1092E: The {0} method of the {1} repository \ + does not accept an empty {2} parameter. The parameter value must contain at \ + least one entity. +CWWKD1092.lifecycle.arg.empty.explanation=Insert, Update, Save, and Delete methods + require at least one entity. +CWWKD1092.lifecycle.arg.empty.useraction=Ensure that the array, List, or Stream \ + that is supplied to the method contains at least one entity. \ No newline at end of file diff --git a/dev/io.openliberty.data.internal.persistence/src/io/openliberty/data/internal/persistence/QueryInfo.java b/dev/io.openliberty.data.internal.persistence/src/io/openliberty/data/internal/persistence/QueryInfo.java index e2be4a18121..332d07f5ff7 100644 --- a/dev/io.openliberty.data.internal.persistence/src/io/openliberty/data/internal/persistence/QueryInfo.java +++ b/dev/io.openliberty.data.internal.persistence/src/io/openliberty/data/internal/persistence/QueryInfo.java @@ -1163,6 +1163,14 @@ Object findAndUpdate(Object arg, EntityManager em) throws Exception { results.add(findAndUpdateOne(arg, em)); } } + + if (results.isEmpty()) + throw exc(IllegalArgumentException.class, + "CWWKD1092.lifecycle.arg.empty", + method.getName(), + repositoryInterface.getName(), + method.getGenericParameterTypes()[0].getTypeName()); + em.flush(); Class returnType = method.getReturnType(); @@ -3501,11 +3509,12 @@ Object insert(Object arg, EntityManager em) throws Exception { ArrayList results; boolean hasSingularEntityParam = false; + int entityCount = 0; if (entityParamType.isArray()) { int length = Array.getLength(arg); results = resultVoid ? null : new ArrayList<>(length); - for (int i = 0; i < length; i++) { - Object entity = toEntity(Array.get(arg, i)); + for (; entityCount < length; entityCount++) { + Object entity = toEntity(Array.get(arg, entityCount)); em.persist(entity); if (results != null) results.add(entity); @@ -3519,6 +3528,7 @@ Object insert(Object arg, EntityManager em) throws Exception { if (arg instanceof Iterable) { results = resultVoid ? null : new ArrayList<>(); for (Object e : ((Iterable) arg)) { + entityCount++; Object entity = toEntity(e); em.persist(entity); if (results != null) @@ -3526,6 +3536,7 @@ Object insert(Object arg, EntityManager em) throws Exception { } em.flush(); } else { + entityCount = 1; hasSingularEntityParam = true; results = resultVoid ? null : new ArrayList<>(1); Object entity = toEntity(arg); @@ -3536,6 +3547,13 @@ Object insert(Object arg, EntityManager em) throws Exception { } } + if (entityCount == 0) + throw exc(IllegalArgumentException.class, + "CWWKD1092.lifecycle.arg.empty", + method.getName(), + repositoryInterface.getName(), + method.getGenericParameterTypes()[0].getTypeName()); + Class returnType = method.getReturnType(); Object returnValue; if (resultVoid) { @@ -3998,11 +4016,12 @@ Object save(Object arg, EntityManager em) throws Exception { List results; boolean hasSingularEntityParam = false; + int entityCount = 0; if (entityParamType.isArray()) { results = new ArrayList<>(); int length = Array.getLength(arg); - for (int i = 0; i < length; i++) - results.add(em.merge(toEntity(Array.get(arg, i)))); + for (; entityCount < length; entityCount++) + results.add(em.merge(toEntity(Array.get(arg, entityCount)))); em.flush(); } else { arg = arg instanceof Stream // @@ -4011,10 +4030,13 @@ Object save(Object arg, EntityManager em) throws Exception { if (Iterable.class.isAssignableFrom(entityParamType)) { results = new ArrayList<>(); - for (Object e : ((Iterable) arg)) + for (Object e : ((Iterable) arg)) { + entityCount++; results.add(em.merge(toEntity(e))); + } em.flush(); } else { + entityCount = 1; hasSingularEntityParam = true; results = resultVoid ? null : new ArrayList<>(1); Object entity = em.merge(toEntity(arg)); @@ -4024,6 +4046,13 @@ Object save(Object arg, EntityManager em) throws Exception { } } + if (entityCount == 0) + throw exc(IllegalArgumentException.class, + "CWWKD1092.lifecycle.arg.empty", + method.getName(), + repositoryInterface.getName(), + method.getGenericParameterTypes()[0].getTypeName()); + Class returnType = method.getReturnType(); Object returnValue; if (resultVoid) { diff --git a/dev/io.openliberty.data.internal.persistence/src/io/openliberty/data/internal/persistence/RepositoryImpl.java b/dev/io.openliberty.data.internal.persistence/src/io/openliberty/data/internal/persistence/RepositoryImpl.java index b41f05a0491..c19b9d585af 100644 --- a/dev/io.openliberty.data.internal.persistence/src/io/openliberty/data/internal/persistence/RepositoryImpl.java +++ b/dev/io.openliberty.data.internal.persistence/src/io/openliberty/data/internal/persistence/RepositoryImpl.java @@ -847,7 +847,7 @@ else if (DoubleStream.class.equals(multiType)) queryInfo.returnArrayType.isInstance(firstNonNullResult) || queryInfo.returnArrayType.isPrimitive() && Util.isWrapperClassFor(queryInfo.returnArrayType, - firstNonNullResult.getClass())) { + firstNonNullResult.getClass())) { returnValue = Array.newInstance(queryInfo.returnArrayType, size); int i = 0; for (Object result : results) @@ -972,6 +972,13 @@ else if (DoubleStream.class.equals(multiType)) updateCount = queryInfo.remove(arg, em); } + if (numExpected == 0) + throw exc(IllegalArgumentException.class, + "CWWKD1091.lifecycle.arg.empty", + method.getName(), + repositoryInterface.getName(), + method.getGenericParameterTypes()[0].getTypeName()); + if (updateCount < numExpected) if (numExpected == 1) throw exc(OptimisticLockingFailureException.class, @@ -1016,6 +1023,13 @@ else if (DoubleStream.class.equals(multiType)) updateCount = queryInfo.update(arg, em); } + if (numExpected == 0) + throw exc(IllegalArgumentException.class, + "CWWKD1092.lifecycle.arg.empty", + method.getName(), + repositoryInterface.getName(), + method.getGenericParameterTypes()[0].getTypeName()); + if (updateCount < numExpected) if (numExpected == 1) throw exc(OptimisticLockingFailureException.class, diff --git a/dev/io.openliberty.data.internal_fat/test-applications/DataTestApp/src/test/jakarta/data/web/DataTestServlet.java b/dev/io.openliberty.data.internal_fat/test-applications/DataTestApp/src/test/jakarta/data/web/DataTestServlet.java index e55fb5407b5..402484a6cc1 100644 --- a/dev/io.openliberty.data.internal_fat/test-applications/DataTestApp/src/test/jakarta/data/web/DataTestServlet.java +++ b/dev/io.openliberty.data.internal_fat/test-applications/DataTestApp/src/test/jakarta/data/web/DataTestServlet.java @@ -5940,8 +5940,6 @@ public void testUpdateWithEntityParameter() { assertEquals(3, persons.updateSome(ulysses, ursula, uriah)); - assertEquals(0, persons.updateSome()); - assertEquals(4, people.deleteBySSN_IdBetween(0L, 999999999L)); } diff --git a/dev/io.openliberty.data.internal_fat_errorpaths/test-applications/DataErrPathsTestApp/src/test/jakarta/data/errpaths/web/DataErrPathsTestServlet.java b/dev/io.openliberty.data.internal_fat_errorpaths/test-applications/DataErrPathsTestApp/src/test/jakarta/data/errpaths/web/DataErrPathsTestServlet.java index 3aaa01f56f9..a418454e180 100644 --- a/dev/io.openliberty.data.internal_fat_errorpaths/test-applications/DataErrPathsTestApp/src/test/jakarta/data/errpaths/web/DataErrPathsTestServlet.java +++ b/dev/io.openliberty.data.internal_fat_errorpaths/test-applications/DataErrPathsTestApp/src/test/jakarta/data/errpaths/web/DataErrPathsTestServlet.java @@ -19,6 +19,7 @@ import java.util.List; import java.util.Optional; import java.util.concurrent.CompletionException; +import java.util.stream.Stream; import jakarta.annotation.Resource; import jakarta.annotation.sql.DataSourceDefinition; @@ -177,6 +178,74 @@ public void testDuplicateNamedParam() { } } + /** + * Verify IllegalArgumentException is raised if you attempt to delete an + * empty list of entities. + */ + @Test + public void testEmptyDelete() { + try { + voters.deleteAll(List.of()); + fail("Deleted an empty list of entities."); + } catch (IllegalArgumentException x) { + if (x.getMessage() == null || + !x.getMessage().startsWith("CWWKD1092E:") || + !x.getMessage().contains("deleteAll")) + throw x; + } + } + + /** + * Verify IllegalArgumentException is raised if you attempt to delete an + * empty array of entities. + */ + @Test + public void testEmptyInsert() { + try { + voters.register(new Voter[] {}); + fail("Inserted an empty array of entities."); + } catch (IllegalArgumentException x) { + if (x.getMessage() == null || + !x.getMessage().startsWith("CWWKD1092E:") || + !x.getMessage().contains("register")) + throw x; + } + } + + /** + * Verify IllegalArgumentException is raised if you attempt to save an + * empty list of entities. + */ + @Test + public void testEmptySave() { + try { + List saved = voters.saveAll(List.of()); + fail("Saved an empty list of entities. Result: " + saved); + } catch (IllegalArgumentException x) { + if (x.getMessage() == null || + !x.getMessage().startsWith("CWWKD1092E:") || + !x.getMessage().contains("saveAll")) + throw x; + } + } + + /** + * Verify IllegalArgumentException is raised if you attempt to update an + * empty stream of entities. + */ + @Test + public void testEmptyUpdate() { + try { + List updated = voters.changeAll(Stream.of()); + fail("Updated an empty stream of entities. Result: " + updated); + } catch (IllegalArgumentException x) { + if (x.getMessage() == null || + !x.getMessage().startsWith("CWWKD1092E:") || + !x.getMessage().contains("changeAll")) + throw x; + } + } + /** * Verify an error is raised for a repository method that has extra Param * annotations that do not correspond to any named parameters in the query. diff --git a/dev/io.openliberty.data.internal_fat_errorpaths/test-applications/DataErrPathsTestApp/src/test/jakarta/data/errpaths/web/Voters.java b/dev/io.openliberty.data.internal_fat_errorpaths/test-applications/DataErrPathsTestApp/src/test/jakarta/data/errpaths/web/Voters.java index 9e656840e5e..b25c4e0bd93 100644 --- a/dev/io.openliberty.data.internal_fat_errorpaths/test-applications/DataErrPathsTestApp/src/test/jakarta/data/errpaths/web/Voters.java +++ b/dev/io.openliberty.data.internal_fat_errorpaths/test-applications/DataErrPathsTestApp/src/test/jakarta/data/errpaths/web/Voters.java @@ -14,6 +14,7 @@ import java.time.Month; import java.util.List; +import java.util.stream.Stream; import jakarta.data.Sort; import jakarta.data.repository.BasicRepository; @@ -22,6 +23,7 @@ import jakarta.data.repository.Param; import jakarta.data.repository.Query; import jakarta.data.repository.Repository; +import jakarta.data.repository.Update; /** * Repository with a valid entity. @@ -60,6 +62,9 @@ List bornOn(@Param("year") int yearBorn, @Param("month") int monthNum, // duplicate parameter name @Param("day") int dayBorn); + @Update + List changeAll(Stream v); + /** * This invalid method has a conflict between its OrderBy annotation and * method name keyword. From fc2ee30e5df6ac2887fc3258be9ac3cb6f4d872c Mon Sep 17 00:00:00 2001 From: Nathan Rauh Date: Tue, 12 Nov 2024 16:53:47 -0600 Subject: [PATCH 21/67] Issue #28595 messages for getAttributeName --- .../resources/CWWKDMessages.nlsprops | 29 +++++++++-- .../data/internal/persistence/QueryInfo.java | 50 ++++++++++++------- .../data/internal/persistence/Util.java | 38 ++++++++++++++ .../test/jakarta/data/jpa/DataJPATest.java | 4 +- 4 files changed, 98 insertions(+), 23 deletions(-) diff --git a/dev/io.openliberty.data.internal.persistence/resources/io/openliberty/data/internal/persistence/resources/CWWKDMessages.nlsprops b/dev/io.openliberty.data.internal.persistence/resources/io/openliberty/data/internal/persistence/resources/CWWKDMessages.nlsprops index c9b4c29a173..b368720c1c9 100644 --- a/dev/io.openliberty.data.internal.persistence/resources/io/openliberty/data/internal/persistence/resources/CWWKDMessages.nlsprops +++ b/dev/io.openliberty.data.internal.persistence/resources/io/openliberty/data/internal/persistence/resources/CWWKDMessages.nlsprops @@ -125,9 +125,9 @@ CWWKD1009.lifecycle.param.err.explanation=Lifecycle methods must have a single \ CWWKD1009.lifecycle.param.err.useraction=Update the repository method to have a \ single parameter that is an entity or an array of List of the entity. -CWWKD1010.unknown.entity.prop=CWWKD1010E: The {0} method of the {1} repository \ - interface expects an entity property named {2} that is not found on the \ - {3} entity class. Valid property names for the entity are: {4}. +CWWKD1010.unknown.entity.prop=CWWKD1010E: An entity property named {0} is \ + not found on the {1} entity class for the {2} method of the {3} repository \ + interface. Valid property names for the entity are: {4}. CWWKD1010.unknown.entity.prop.explanation=The repository method is attempting \ to use an entity property that does not exist. CWWKD1010.unknown.entity.prop.useraction=Update the repository method to match \ @@ -909,10 +909,31 @@ CWWKD1090.orderby.conflict.explanation=The OrderBy annotation is not compatible CWWKD1090.orderby.conflict.useraction=Use only the OrderBy annotation or the \ OrderBy keyword. +CWWKD1091.method.name.parse.err=CWWKD1091E: An entity property named {0} is \ + not found on the {1} entity class for the {2} method of the {3} repository \ + interface. Confirm that the repository method either has a name that conforms \ + to the Query by Method Name pattern or is annotated with one of: {4}. \ + Valid property names for the entity are: {5}. +CWWKD1091.method.name.parse.err.explanation=The repository method name was parsed \ + according to the Query by Method Name pattern because the repository method \ + does not have a Jakarta Data annotation that indicates the type of operation. +CWWKD1091.method.name.parse.err.useraction=Correct the repository method name \ + or annotate the repository method to indicate a Jakarta Data operation such as \ + Query, Find, or Save. + CWWKD1092.lifecycle.arg.empty=CWWKD1092E: The {0} method of the {1} repository \ does not accept an empty {2} parameter. The parameter value must contain at \ least one entity. CWWKD1092.lifecycle.arg.empty.explanation=Insert, Update, Save, and Delete methods require at least one entity. CWWKD1092.lifecycle.arg.empty.useraction=Ensure that the array, List, or Stream \ - that is supplied to the method contains at least one entity. \ No newline at end of file + that is supplied to the method contains at least one entity. + +CWWKD1093.fn.not.applicable=CWWKD1093E: The {0} function cannot be evaluated \ + for the {1} entity that is used by the {2} method of the {3} repository \ + interface. The entity does not have a property that is annotated with {4} \ + or from which {0} can be inferred. +CWWKD1093.fn.not.applicable.explanation=The function cannot be used on the entity \ + because the entity lacks an ID or version property. +CWWKD1093.fn.not.applicable.useraction=Do not use the function in query language \ + or parameters for the repository method. diff --git a/dev/io.openliberty.data.internal.persistence/src/io/openliberty/data/internal/persistence/QueryInfo.java b/dev/io.openliberty.data.internal.persistence/src/io/openliberty/data/internal/persistence/QueryInfo.java index 332d07f5ff7..cf33d7abc11 100644 --- a/dev/io.openliberty.data.internal.persistence/src/io/openliberty/data/internal/persistence/QueryInfo.java +++ b/dev/io.openliberty.data.internal.persistence/src/io/openliberty/data/internal/persistence/QueryInfo.java @@ -2464,15 +2464,23 @@ String getAttributeName(String name, boolean failIfNotFound) { // id(this) attributeName = entityInfo.attributeNames.get(By.ID); if (attributeName == null && failIfNotFound) - throw new MappingException("Entity class " + entityInfo.getType().getName() + - " does not have a property named " + name + - " or which is designated as the @Id."); // TODO NLS + throw exc(UnsupportedOperationException.class, + "CWWKD1093.fn.not.applicable", + name, + entityInfo.getType().getName(), + method.getName(), + repositoryInterface.getName(), + "@Id"); } else if (len == 13 && name.regionMatches(true, 0, "version", 0, 7)) { // version(this) if (entityInfo.versionAttributeName == null && failIfNotFound) - throw new MappingException("Entity class " + entityInfo.getType().getName() + - " does not have a property named " + name + - " or which is designated as the @Version."); // TODO NLS + throw exc(UnsupportedOperationException.class, + "CWWKD1093.fn.not.applicable", + name, + entityInfo.getType().getName(), + method.getName(), + repositoryInterface.getName(), + "@Version"); else attributeName = entityInfo.versionAttributeName; } else { @@ -2487,10 +2495,10 @@ String getAttributeName(String name, boolean failIfNotFound) { else throw exc(MappingException.class, "CWWKD1010.unknown.entity.prop", - method.getName(), - repositoryInterface.getName(), name, entityInfo.getType().getName(), + method.getName(), + repositoryInterface.getName(), entityInfo.attributeTypes.keySet()); } else { String lowerName = name.toLowerCase(); @@ -2512,15 +2520,23 @@ String getAttributeName(String name, boolean failIfNotFound) { lowerName = lowerName.replace("_", ""); attributeName = entityInfo.attributeNames.get(lowerName); if (attributeName == null && failIfNotFound) { - // TODO If attempting to parse Query by Method Name without a By keyword, then the message - // should also include the possibility that repository method is missing an annotation. - throw exc(MappingException.class, - "CWWKD1010.unknown.entity.prop", - method.getName(), - repositoryInterface.getName(), - name, - entityInfo.getType().getName(), - entityInfo.attributeTypes.keySet()); + if (Util.hasOperationAnno(method)) + throw exc(MappingException.class, + "CWWKD1010.unknown.entity.prop", + name, + entityInfo.getType().getName(), + method.getName(), + repositoryInterface.getName(), + entityInfo.attributeTypes.keySet()); + else + throw exc(MappingException.class, + "CWWKD1091.method.name.parse.err", + name, + entityInfo.getType().getName(), + method.getName(), + repositoryInterface.getName(), + Util.OP_ANNOS, + entityInfo.attributeTypes.keySet()); } } } diff --git a/dev/io.openliberty.data.internal.persistence/src/io/openliberty/data/internal/persistence/Util.java b/dev/io.openliberty.data.internal.persistence/src/io/openliberty/data/internal/persistence/Util.java index 55a7b56b194..b052a9a1c2c 100644 --- a/dev/io.openliberty.data.internal.persistence/src/io/openliberty/data/internal/persistence/Util.java +++ b/dev/io.openliberty.data.internal.persistence/src/io/openliberty/data/internal/persistence/Util.java @@ -9,6 +9,8 @@ *******************************************************************************/ package io.openliberty.data.internal.persistence; +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.math.BigDecimal; import java.math.BigInteger; @@ -27,6 +29,12 @@ import jakarta.data.Order; import jakarta.data.Sort; import jakarta.data.page.PageRequest; +import jakarta.data.repository.Delete; +import jakarta.data.repository.Find; +import jakarta.data.repository.Insert; +import jakarta.data.repository.Query; +import jakarta.data.repository.Save; +import jakarta.data.repository.Update; /** * A location for helper methods that do not require any state. @@ -44,6 +52,11 @@ public class Util { Set.of(long.class, int.class, short.class, byte.class, double.class, float.class); + /** + * List of Jakarta Data operation annotations for use in NLS messages. + */ + static final String OP_ANNOS = "Delete, Find, Insert, Query, Save, Update"; + /** * Return types for deleteBy that distinguish delete-only from find-and-delete. */ @@ -120,6 +133,31 @@ public static boolean cannotBeEntity(Class c) { Modifier.isAbstract(modifiers); } + /** + * Identifies whether a method is annotated with a Jakarta Data annotation + * that performs and operation, such as Query, Find, or Save. This method is + * for use by error reporting only, so it does not need to be very efficient. + * + * @param method repository method. + * @return if the repository method has an annotation indicating an operation. + */ + @Trivial + static final boolean hasOperationAnno(Method method) { + Set> operationAnnos = // + Set.of(Delete.class, + Insert.class, + Find.class, + Query.class, + Save.class, + Update.class); + + for (Annotation anno : method.getAnnotations()) + if (operationAnnos.contains(anno.annotationType())) + return true; + + return false; + } + /** * Indicates if the specified class is a wrapper for the primitive class. * diff --git a/dev/io.openliberty.data.internal_fat_jpa/fat/src/test/jakarta/data/jpa/DataJPATest.java b/dev/io.openliberty.data.internal_fat_jpa/fat/src/test/jakarta/data/jpa/DataJPATest.java index 64496236569..860443566a4 100644 --- a/dev/io.openliberty.data.internal_fat_jpa/fat/src/test/jakarta/data/jpa/DataJPATest.java +++ b/dev/io.openliberty.data.internal_fat_jpa/fat/src/test/jakarta/data/jpa/DataJPATest.java @@ -42,7 +42,6 @@ public class DataJPATest extends FATServletClient { */ static final String[] EXPECTED_ERROR_MESSAGES = // new String[] { - "CWWKD1010E.*countBySurgePriceGreaterThanEqual", "CWWKD1026E.*allSorted", "CWWKD1046E.*publicDebtAsByte", "CWWKD1046E.*publicDebtAsDouble", @@ -55,7 +54,8 @@ public class DataJPATest extends FATServletClient { "CWWKD1046E.*numFullTimeWorkersAsShort", "CWWKD1054E.*findByIsControlTrueAndNumericValueBetween", "CWWKD1075E.*Apartment2", - "CWWKD1075E.*Apartment3" + "CWWKD1075E.*Apartment3", + "CWWKD1091E.*countBySurgePriceGreaterThanEqual" }; @ClassRule From 6ad05c4df54d35cd0cebab44aa3db597a50b4fb7 Mon Sep 17 00:00:00 2001 From: Nathan Rauh Date: Mon, 18 Nov 2024 08:39:56 -0600 Subject: [PATCH 22/67] Correction to code that was using the wrong message id --- .../openliberty/data/internal/persistence/RepositoryImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/io.openliberty.data.internal.persistence/src/io/openliberty/data/internal/persistence/RepositoryImpl.java b/dev/io.openliberty.data.internal.persistence/src/io/openliberty/data/internal/persistence/RepositoryImpl.java index c19b9d585af..304a3820fda 100644 --- a/dev/io.openliberty.data.internal.persistence/src/io/openliberty/data/internal/persistence/RepositoryImpl.java +++ b/dev/io.openliberty.data.internal.persistence/src/io/openliberty/data/internal/persistence/RepositoryImpl.java @@ -974,7 +974,7 @@ else if (DoubleStream.class.equals(multiType)) if (numExpected == 0) throw exc(IllegalArgumentException.class, - "CWWKD1091.lifecycle.arg.empty", + "CWWKD1092.lifecycle.arg.empty", method.getName(), repositoryInterface.getName(), method.getGenericParameterTypes()[0].getTypeName()); From 162f18e7beaade57ffe4aba48fde76a2de4e0388 Mon Sep 17 00:00:00 2001 From: Benson Lam Date: Mon, 18 Nov 2024 10:56:05 -0500 Subject: [PATCH 23/67] swidtags for OL25 --- ...rty-24.0.0.swidtag => ibm.com_Open_Liberty-25.0.0.swidtag} | 2 +- dev/build.image/publish/ibm.com_Open_Liberty_release.swidtag | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) rename dev/build.image/publish/{ibm.com_Open_Liberty-24.0.0.swidtag => ibm.com_Open_Liberty-25.0.0.swidtag} (90%) diff --git a/dev/build.image/publish/ibm.com_Open_Liberty-24.0.0.swidtag b/dev/build.image/publish/ibm.com_Open_Liberty-25.0.0.swidtag similarity index 90% rename from dev/build.image/publish/ibm.com_Open_Liberty-24.0.0.swidtag rename to dev/build.image/publish/ibm.com_Open_Liberty-25.0.0.swidtag index 3e87e0f8eb2..42d450c50d3 100644 --- a/dev/build.image/publish/ibm.com_Open_Liberty-24.0.0.swidtag +++ b/dev/build.image/publish/ibm.com_Open_Liberty-25.0.0.swidtag @@ -1,5 +1,5 @@ - + diff --git a/dev/build.image/publish/ibm.com_Open_Liberty_release.swidtag b/dev/build.image/publish/ibm.com_Open_Liberty_release.swidtag index 89990892b76..5c64a8145b6 100644 --- a/dev/build.image/publish/ibm.com_Open_Liberty_release.swidtag +++ b/dev/build.image/publish/ibm.com_Open_Liberty_release.swidtag @@ -1,8 +1,8 @@ - + - + From ce6b1be202bb0b6c617eb26805307685ee783edb Mon Sep 17 00:00:00 2001 From: Thomas Watson Date: Fri, 15 Nov 2024 14:28:50 -0600 Subject: [PATCH 24/67] Add overlay for Equinox PR 698 --- .../internal/loader/EquinoxClassLoader.java | 87 ++++ .../internal/loader/ModuleClassLoader.java | 449 ++++++++++++++++++ 2 files changed, 536 insertions(+) create mode 100644 dev/org.eclipse.osgi/src/org/eclipse/osgi/internal/loader/EquinoxClassLoader.java create mode 100644 dev/org.eclipse.osgi/src/org/eclipse/osgi/internal/loader/ModuleClassLoader.java diff --git a/dev/org.eclipse.osgi/src/org/eclipse/osgi/internal/loader/EquinoxClassLoader.java b/dev/org.eclipse.osgi/src/org/eclipse/osgi/internal/loader/EquinoxClassLoader.java new file mode 100644 index 00000000000..0b01cd33937 --- /dev/null +++ b/dev/org.eclipse.osgi/src/org/eclipse/osgi/internal/loader/EquinoxClassLoader.java @@ -0,0 +1,87 @@ +/******************************************************************************* + * Copyright (c) 2005, 2016 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.osgi.internal.loader; + +import org.eclipse.osgi.internal.debug.Debug; +import org.eclipse.osgi.internal.framework.EquinoxConfiguration; +import org.eclipse.osgi.internal.loader.classpath.ClasspathManager; +import org.eclipse.osgi.storage.BundleInfo.Generation; + +public class EquinoxClassLoader extends ModuleClassLoader { + protected static final boolean EQUINOX_REGISTERED_AS_PARALLEL; + static { + boolean registered; + try { + registered = ClassLoader.registerAsParallelCapable(); + } catch (Throwable t) { + registered = false; + } + EQUINOX_REGISTERED_AS_PARALLEL = registered; + } + private final EquinoxConfiguration configuration; + private final Debug debug; + private final BundleLoader delegate; + private final Generation generation; + // TODO Note that PDE has internal dependency on this field type/name (bug 267238) + private final ClasspathManager manager; + private final boolean isRegisteredAsParallel; + + /** + * Constructs a new DefaultClassLoader. + * @param parent the parent classloader + * @param configuration the equinox configuration + * @param delegate the delegate for this classloader + * @param generation the generation for this class loader + */ + public EquinoxClassLoader(ClassLoader parent, EquinoxConfiguration configuration, BundleLoader delegate, Generation generation) { + super(parent); + this.configuration = configuration; + this.debug = configuration.getDebug(); + this.delegate = delegate; + this.generation = generation; + this.manager = new ClasspathManager(generation, this); + this.isRegisteredAsParallel = (ModuleClassLoader.REGISTERED_AS_PARALLEL && EQUINOX_REGISTERED_AS_PARALLEL) || this.configuration.PARALLEL_CAPABLE; + } + + @Override + protected final Generation getGeneration() { + return this.generation; + } + + @Override + public final ClasspathManager getClasspathManager() { + return manager; + } + + @Override + public final boolean isRegisteredAsParallel() { + return isRegisteredAsParallel; + } + + @Override + public final BundleLoader getBundleLoader() { + return delegate; + } + + @Override + protected final Debug getDebug() { + return debug; + } + + @Override + protected final EquinoxConfiguration getConfiguration() { + return configuration; + } +} diff --git a/dev/org.eclipse.osgi/src/org/eclipse/osgi/internal/loader/ModuleClassLoader.java b/dev/org.eclipse.osgi/src/org/eclipse/osgi/internal/loader/ModuleClassLoader.java new file mode 100644 index 00000000000..ede519ad212 --- /dev/null +++ b/dev/org.eclipse.osgi/src/org/eclipse/osgi/internal/loader/ModuleClassLoader.java @@ -0,0 +1,449 @@ +/******************************************************************************* + * Copyright (c) 2005, 2016 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.osgi.internal.loader; + +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.security.AllPermission; +import java.security.CodeSource; +import java.security.PermissionCollection; +import java.security.ProtectionDomain; +import java.security.cert.Certificate; +import java.util.Collection; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.eclipse.osgi.container.ModuleRevision; +import org.eclipse.osgi.internal.debug.Debug; +import org.eclipse.osgi.internal.framework.EquinoxConfiguration; +import org.eclipse.osgi.internal.loader.classpath.ClasspathEntry; +import org.eclipse.osgi.internal.loader.classpath.ClasspathManager; +import org.eclipse.osgi.signedcontent.SignedContent; +import org.eclipse.osgi.signedcontent.SignerInfo; +import org.eclipse.osgi.storage.BundleInfo.Generation; +import org.eclipse.osgi.storage.bundlefile.BundleFile; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleReference; + +public abstract class ModuleClassLoader extends ClassLoader implements BundleReference { + public static class GenerationProtectionDomain extends ProtectionDomain implements BundleReference { + private final Generation generation; + + public GenerationProtectionDomain(CodeSource codesource, PermissionCollection permissions, Generation generation) { + super(codesource, permissions); + this.generation = generation; + } + + @Override + public Bundle getBundle() { + return generation.getRevision().getBundle(); + } + } + + /** + * A PermissionCollection for AllPermissions; shared across all ProtectionDomains when security is disabled + */ + protected static final PermissionCollection ALLPERMISSIONS; + protected static final boolean REGISTERED_AS_PARALLEL; + static { + boolean registered; + try { + registered = ClassLoader.registerAsParallelCapable(); + } catch (Throwable t) { + registered = false; + } + REGISTERED_AS_PARALLEL = registered; + } + + static { + AllPermission allPerm = new AllPermission(); + ALLPERMISSIONS = allPerm.newPermissionCollection(); + if (ALLPERMISSIONS != null) + ALLPERMISSIONS.add(allPerm); + } + + /** + * Holds the result of a defining a class. + * + */ + public static class DefineClassResult { + /** + * The class object that either got defined or was found as previously loaded. + */ + public final Class clazz; + /** + * Set to true if the class object got defined; set to false if the class + * did not get defined correctly or the class was found as a previously loaded + * class. + */ + public final boolean defined; + + public DefineClassResult(Class clazz, boolean defined) { + this.clazz = clazz; + this.defined = defined; + } + } + + private final Map classNameLocks = new HashMap<>(5); + private final Object pkgLock = new Object(); + + /** + * Constructs a new ModuleClassLoader. + * @param parent the parent classloader + */ + public ModuleClassLoader(ClassLoader parent) { + super(parent); + } + + /** + * Returns the generation of the host revision associated with this class loader + * @return the generation for this class loader + */ + protected abstract Generation getGeneration(); + + /** + * Returns the Debug object for the Framework instance + * @return the Debug object for the Framework instance + */ + protected abstract Debug getDebug(); + + /** + * Returns the classpath manager for this class loader + * @return the classpath manager for this class loader + */ + public abstract ClasspathManager getClasspathManager(); + + /** + * Returns the configuration for the Framework instance + * @return the configuration for the Framework instance + */ + protected abstract EquinoxConfiguration getConfiguration(); + + /** + * Returns the bundle loader for this class loader + * @return the bundle loader for this class loader + */ + public abstract BundleLoader getBundleLoader(); + + /** + * Returns true if this class loader implementation has been + * registered with the JVM as a parallel class loader. + * This requires Java 7 or later. + * @return true if this class loader implementation has been + * registered with the JVM as a parallel class loader; otherwise + * false is returned. + */ + public abstract boolean isRegisteredAsParallel(); + + /** + * Loads a class for the bundle. First delegate.findClass(name) is called. + * The delegate will query the system class loader, bundle imports, bundle + * local classes, bundle hosts and fragments. The delegate will call + * BundleClassLoader.findLocalClass(name) to find a class local to this + * bundle. + * @param name the name of the class to load. + * @param resolve indicates whether to resolve the loaded class or not. + * @return The Class object. + * @throws ClassNotFoundException if the class is not found. + */ + @Override + protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { + // Just ask the delegate. This could result in findLocalClass(name) being + // called. + Class clazz = getBundleLoader().findClass(name); + // resolve the class if asked to. + if (resolve) { + resolveClass(clazz); + } + return (clazz); + } + + // preparing for Java 9 + protected Class findClass(String moduleName, String name) { + try { + return findLocalClass(name); + } catch (ClassNotFoundException e) { + return null; + } + } + + @Override + protected Class findClass(String name) throws ClassNotFoundException { + return findLocalClass(name); + } + + /** + * Gets a resource for the bundle. First delegate.findResource(name) is + * called. The delegate will query the system class loader, bundle imports, + * bundle local resources, bundle hosts and fragments. The delegate will + * call BundleClassLoader.findLocalResource(name) to find a resource local + * to this bundle. + * @param name The resource path to get. + * @return The URL of the resource or null if it does not exist. + */ + @Override + public URL getResource(String name) { + if (getDebug().DEBUG_LOADER) { + Debug.println("ModuleClassLoader[" + getBundleLoader() + "].getResource(" + name + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } + + URL url = getBundleLoader().findResource(name); + if (url != null) + return (url); + + if (getDebug().DEBUG_LOADER) { + Debug.println("ModuleClassLoader[" + getBundleLoader() + "].getResource(" + name + ") failed."); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } + + return (null); + } + + // preparing for Java 9 + protected URL findResource(String moduleName, String name) { + return findLocalResource(name); + } + + @Override + protected URL findResource(String name) { + return findLocalResource(name); + } + + /** + * Gets resources for the bundle. First delegate.findResources(name) is + * called. The delegate will query the system class loader, bundle imports, + * bundle local resources, bundle hosts and fragments. The delegate will + * call BundleClassLoader.findLocalResources(name) to find a resource local + * to this bundle. + * @param name The resource path to get. + * @return The Enumeration of the resource URLs. + */ + @Override + public Enumeration getResources(String name) throws IOException { + if (getDebug().DEBUG_LOADER) { + Debug.println("ModuleClassLoader[" + getBundleLoader() + "].getResources(" + name + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } + Enumeration result = getBundleLoader().findResources(name); + if (getDebug().DEBUG_LOADER) { + if (result == null || !result.hasMoreElements()) { + Debug.println("ModuleClassLoader[" + getBundleLoader() + "].getResources(" + name + ") failed."); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } + } + return result; + } + + @Override + protected Enumeration findResources(String name) throws IOException { + return findLocalResources(name); + } + + /** + * Finds a library for this bundle. Simply calls + * manager.findLibrary(libname) to find the library. + * @param libname The library to find. + * @return The absolution path to the library or null if not found + */ + @Override + protected String findLibrary(String libname) { + // let the manager find the library for us + return getClasspathManager().findLibrary(libname); + } + + public ClasspathEntry createClassPathEntry(BundleFile bundlefile, Generation entryGeneration) { + return new ClasspathEntry(bundlefile, createProtectionDomain(bundlefile, entryGeneration), entryGeneration); + } + + public DefineClassResult defineClass(String name, byte[] classbytes, ClasspathEntry classpathEntry) { + // Note that we must check findLoadedClass again here since no locks are held between + // calling findLoadedClass the first time and defineClass. + // This is to allow weavers to get called while holding no locks. + // See ClasspathManager.findLocalClass(String) + boolean defined = false; + Class result = null; + if (isRegisteredAsParallel()) { + // lock by class name in this case + boolean initialLock = lockClassName(name); + try { + result = findLoadedClass(name); + if (result == null) { + result = defineClass(name, classbytes, 0, classbytes.length, classpathEntry.getDomain()); + defined = true; + } + } finally { + if (initialLock) { + unlockClassName(name); + } + } + } else { + // lock by class loader instance in this case + synchronized (this) { + result = findLoadedClass(name); + if (result == null) { + result = defineClass(name, classbytes, 0, classbytes.length, classpathEntry.getDomain()); + defined = true; + } + } + } + return new DefineClassResult(result, defined); + } + + public Class publicFindLoaded(String classname) { + if (isRegisteredAsParallel()) { + return findLoadedClass(classname); + } + synchronized (this) { + return findLoadedClass(classname); + } + } + + public Package publicGetPackage(String pkgname) { + synchronized (pkgLock) { + return getPackage(pkgname); + } + } + + public Package publicDefinePackage(String name, String specTitle, String specVersion, String specVendor, String implTitle, String implVersion, String implVendor, URL sealBase) { + synchronized (pkgLock) { + Package pkg = getPackage(name); + return pkg != null ? pkg : definePackage(name, specTitle, specVersion, specVendor, implTitle, implVersion, implVendor, sealBase); + } + } + + public URL findLocalResource(String resource) { + return getClasspathManager().findLocalResource(resource); + } + + public Enumeration findLocalResources(String resource) { + return getClasspathManager().findLocalResources(resource); + } + + public Class findLocalClass(String classname) throws ClassNotFoundException { + return getClasspathManager().findLocalClass(classname); + } + + /** + * Creates a ProtectionDomain which uses specified BundleFile and the permissions of the baseDomain + * @param bundlefile The source bundlefile the domain is for. + * @param domainGeneration the source generation for the domain + * @return a ProtectionDomain which uses specified BundleFile and the permissions of the baseDomain + */ + @SuppressWarnings("deprecation") + protected ProtectionDomain createProtectionDomain(BundleFile bundlefile, Generation domainGeneration) { + // create a protection domain which knows about the codesource for this classpath entry (bug 89904) + ProtectionDomain baseDomain = domainGeneration.getDomain(); + try { + // use the permissions supplied by the domain passed in from the framework + PermissionCollection permissions; + if (baseDomain != null) { + permissions = baseDomain.getPermissions(); + } else { + // no domain specified. Better use a collection that has all permissions + // this is done just incase someone sets the security manager later + permissions = ALLPERMISSIONS; + } + Certificate[] certs = null; + if (getConfiguration().CLASS_CERTIFICATE) { + Bundle b = getBundle(); + SignedContent signedContent = b == null ? null : b.adapt(SignedContent.class); + if (signedContent != null && signedContent.isSigned()) { + SignerInfo[] signers = signedContent.getSignerInfos(); + if (signers.length > 0) { + certs = signers[0].getCertificateChain(); + } + } + } + File file = bundlefile.getBaseFile(); + // Bug 477787: file will be null when the osgi.framework configuration property contains an invalid value. + return new GenerationProtectionDomain(file == null ? null : new CodeSource(file.toURL(), certs), permissions, getGeneration()); + //return new ProtectionDomain(new CodeSource(bundlefile.getBaseFile().toURL(), certs), permissions); + } catch (MalformedURLException e) { + // Failed to create our own domain; just return the baseDomain + return baseDomain; + } + } + + @Override + public Bundle getBundle() { + return getGeneration().getRevision().getBundle(); + } + + public List findEntries(String path, String filePattern, int options) { + return getClasspathManager().findEntries(path, filePattern, options); + } + + public Collection listResources(String path, String filePattern, int options) { + return getBundleLoader().listResources(path, filePattern, options); + } + + public Collection listLocalResources(String path, String filePattern, int options) { + return getClasspathManager().listLocalResources(path, filePattern, options); + } + + @Override + public String toString() { + Bundle b = getBundle(); + StringBuilder result = new StringBuilder(super.toString()); + if (b == null) + return result.toString(); + return result.append('[').append(b.getSymbolicName()).append(':').append(b.getVersion()).append("(id=").append(b.getBundleId()).append(")]").toString(); //$NON-NLS-1$//$NON-NLS-2$ + } + + public void loadFragments(Collection fragments) { + getClasspathManager().loadFragments(fragments); + } + + private boolean lockClassName(String classname) { + synchronized (classNameLocks) { + Object lockingThread = classNameLocks.get(classname); + Thread current = Thread.currentThread(); + if (lockingThread == current) + return false; + boolean previousInterruption = Thread.interrupted(); + try { + while (true) { + if (lockingThread == null) { + classNameLocks.put(classname, current); + return true; + } + + classNameLocks.wait(); + lockingThread = classNameLocks.get(classname); + } + } catch (InterruptedException e) { + previousInterruption = true; + // must not throw LinkageError or ClassNotFoundException here because that will cause all threads + // to fail to load the class (see bug 490902) + throw new Error("Interrupted while waiting for classname lock: " + classname, e); //$NON-NLS-1$ + } finally { + if (previousInterruption) { + current.interrupt(); + } + } + } + } + + private void unlockClassName(String classname) { + synchronized (classNameLocks) { + classNameLocks.remove(classname); + classNameLocks.notifyAll(); + } + } + + public void close() { + getClasspathManager().close(); + } +} From 07d3f0353f3a47227bdbc9451fc7d96ed8f77876 Mon Sep 17 00:00:00 2001 From: Thomas Watson Date: Fri, 15 Nov 2024 14:33:45 -0600 Subject: [PATCH 25/67] Applying Equinox PR 698 to Liberty Get loader-classname lock for calls to findLoadedClass There is a concern that the initial call to findLoadedClass by Equinox is not protected by the same loader-classname lock as the later calls to findLoadedClass/defineClass are. There are concerns that the unprotected findLoadedClass call could catch the JVM in an invalid state if there is another thread in the middle of defining the class. This change replaces the clunky way of doing loader-classname locks with a more efficient strategy. This way we can use this lock around the initial call to findLoadedClass without too much concern over the performance impact. This change also removes some of the old code that still supported Java 6. It is always assumed we now can register the class loaders as parallel capable. --- .../internal/container/KeyBasedLockStore.java | 71 ++++++ .../internal/loader/EquinoxClassLoader.java | 29 +-- .../internal/loader/ModuleClassLoader.java | 212 ++++++++---------- 3 files changed, 180 insertions(+), 132 deletions(-) create mode 100644 dev/org.eclipse.osgi/src/org/eclipse/osgi/internal/container/KeyBasedLockStore.java diff --git a/dev/org.eclipse.osgi/src/org/eclipse/osgi/internal/container/KeyBasedLockStore.java b/dev/org.eclipse.osgi/src/org/eclipse/osgi/internal/container/KeyBasedLockStore.java new file mode 100644 index 00000000000..e4b5e9d3828 --- /dev/null +++ b/dev/org.eclipse.osgi/src/org/eclipse/osgi/internal/container/KeyBasedLockStore.java @@ -0,0 +1,71 @@ +/******************************************************************************* + * Copyright (c) 2022, 2024 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.osgi.internal.container; + +import java.lang.ref.ReferenceQueue; +import java.lang.ref.WeakReference; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Function; + +public final class KeyBasedLockStore { + + final ReferenceQueue refQueue = new ReferenceQueue<>(); + private final ConcurrentHashMap lockMap = new ConcurrentHashMap<>(); + private final Function lockCreator; + + public KeyBasedLockStore(Function lockCreator) { + this.lockCreator = lockCreator; + } + + private final class LockWeakRef extends WeakReference { + final Key key; + + public LockWeakRef(Lock referent, Key keyValue) { + super(referent, refQueue); + key = keyValue; + } + } + + public final Lock getLock(Key key) { + poll(); + LockWeakRef lockRef = lockMap.get(key); + Lock lock = lockRef != null ? lockRef.get() : null; + if (lock != null) { + return lock; + } + + lock = lockCreator.apply(key); + + while (true) { + LockWeakRef retVal = lockMap.putIfAbsent(key, new LockWeakRef(lock, key)); + if (retVal == null) { + return lock; + } + + Lock retLock = retVal.get(); + if (retLock != null) { + return retLock; + } + lockMap.remove(key, retVal); + } + } + + @SuppressWarnings("unchecked") + private final void poll() { + LockWeakRef lockRef; + while ((lockRef = (LockWeakRef) refQueue.poll()) != null) { + lockMap.remove(lockRef.key, lockRef); + } + } +} diff --git a/dev/org.eclipse.osgi/src/org/eclipse/osgi/internal/loader/EquinoxClassLoader.java b/dev/org.eclipse.osgi/src/org/eclipse/osgi/internal/loader/EquinoxClassLoader.java index 0b01cd33937..b4480a3a4dc 100644 --- a/dev/org.eclipse.osgi/src/org/eclipse/osgi/internal/loader/EquinoxClassLoader.java +++ b/dev/org.eclipse.osgi/src/org/eclipse/osgi/internal/loader/EquinoxClassLoader.java @@ -20,39 +20,35 @@ import org.eclipse.osgi.storage.BundleInfo.Generation; public class EquinoxClassLoader extends ModuleClassLoader { - protected static final boolean EQUINOX_REGISTERED_AS_PARALLEL; static { - boolean registered; - try { - registered = ClassLoader.registerAsParallelCapable(); - } catch (Throwable t) { - registered = false; + if (!ClassLoader.registerAsParallelCapable()) { + throw new IllegalStateException("Failed to register as parallel capabable."); //$NON-NLS-1$ } - EQUINOX_REGISTERED_AS_PARALLEL = registered; } private final EquinoxConfiguration configuration; private final Debug debug; private final BundleLoader delegate; private final Generation generation; - // TODO Note that PDE has internal dependency on this field type/name (bug 267238) + // TODO Note that PDE has internal dependency on this field type/name (bug + // 267238) private final ClasspathManager manager; - private final boolean isRegisteredAsParallel; /** * Constructs a new DefaultClassLoader. - * @param parent the parent classloader + * + * @param parent the parent classloader * @param configuration the equinox configuration - * @param delegate the delegate for this classloader - * @param generation the generation for this class loader + * @param delegate the delegate for this classloader + * @param generation the generation for this class loader */ - public EquinoxClassLoader(ClassLoader parent, EquinoxConfiguration configuration, BundleLoader delegate, Generation generation) { + public EquinoxClassLoader(ClassLoader parent, EquinoxConfiguration configuration, BundleLoader delegate, + Generation generation) { super(parent); this.configuration = configuration; this.debug = configuration.getDebug(); this.delegate = delegate; this.generation = generation; this.manager = new ClasspathManager(generation, this); - this.isRegisteredAsParallel = (ModuleClassLoader.REGISTERED_AS_PARALLEL && EQUINOX_REGISTERED_AS_PARALLEL) || this.configuration.PARALLEL_CAPABLE; } @Override @@ -65,11 +61,6 @@ public final ClasspathManager getClasspathManager() { return manager; } - @Override - public final boolean isRegisteredAsParallel() { - return isRegisteredAsParallel; - } - @Override public final BundleLoader getBundleLoader() { return delegate; diff --git a/dev/org.eclipse.osgi/src/org/eclipse/osgi/internal/loader/ModuleClassLoader.java b/dev/org.eclipse.osgi/src/org/eclipse/osgi/internal/loader/ModuleClassLoader.java index ede519ad212..cd65014eb3e 100644 --- a/dev/org.eclipse.osgi/src/org/eclipse/osgi/internal/loader/ModuleClassLoader.java +++ b/dev/org.eclipse.osgi/src/org/eclipse/osgi/internal/loader/ModuleClassLoader.java @@ -25,10 +25,10 @@ import java.security.cert.Certificate; import java.util.Collection; import java.util.Enumeration; -import java.util.HashMap; import java.util.List; -import java.util.Map; +import java.util.function.Function; import org.eclipse.osgi.container.ModuleRevision; +import org.eclipse.osgi.internal.container.KeyBasedLockStore; import org.eclipse.osgi.internal.debug.Debug; import org.eclipse.osgi.internal.framework.EquinoxConfiguration; import org.eclipse.osgi.internal.loader.classpath.ClasspathEntry; @@ -44,7 +44,8 @@ public abstract class ModuleClassLoader extends ClassLoader implements BundleRef public static class GenerationProtectionDomain extends ProtectionDomain implements BundleReference { private final Generation generation; - public GenerationProtectionDomain(CodeSource codesource, PermissionCollection permissions, Generation generation) { + public GenerationProtectionDomain(CodeSource codesource, PermissionCollection permissions, + Generation generation) { super(codesource, permissions); this.generation = generation; } @@ -56,18 +57,14 @@ public Bundle getBundle() { } /** - * A PermissionCollection for AllPermissions; shared across all ProtectionDomains when security is disabled + * A PermissionCollection for AllPermissions; shared across all + * ProtectionDomains when security is disabled */ protected static final PermissionCollection ALLPERMISSIONS; - protected static final boolean REGISTERED_AS_PARALLEL; static { - boolean registered; - try { - registered = ClassLoader.registerAsParallelCapable(); - } catch (Throwable t) { - registered = false; + if (!ClassLoader.registerAsParallelCapable()) { + throw new IllegalStateException("Failed to register as parallel capabable."); //$NON-NLS-1$ } - REGISTERED_AS_PARALLEL = registered; } static { @@ -79,7 +76,6 @@ public Bundle getBundle() { /** * Holds the result of a defining a class. - * */ public static class DefineClassResult { /** @@ -87,8 +83,8 @@ public static class DefineClassResult { */ public final Class clazz; /** - * Set to true if the class object got defined; set to false if the class - * did not get defined correctly or the class was found as a previously loaded + * Set to true if the class object got defined; set to false if the class did + * not get defined correctly or the class was found as a previously loaded * class. */ public final boolean defined; @@ -99,11 +95,31 @@ public DefineClassResult(Class clazz, boolean defined) { } } - private final Map classNameLocks = new HashMap<>(5); + private static final class ClassNameLock { + static final Function SUPPLIER = new Function() { + public ClassNameLock apply(String className) { + return new ClassNameLock(className); + } + }; + final String name; + + ClassNameLock(String name) { + this.name = name; + } + + @Override + public String toString() { + return "ClassNameLock: " + name; //$NON-NLS-1$ + } + } + + private final KeyBasedLockStore classNameLocks = new KeyBasedLockStore<>( + ClassNameLock.SUPPLIER); private final Object pkgLock = new Object(); /** * Constructs a new ModuleClassLoader. + * * @param parent the parent classloader */ public ModuleClassLoader(ClassLoader parent) { @@ -112,51 +128,58 @@ public ModuleClassLoader(ClassLoader parent) { /** * Returns the generation of the host revision associated with this class loader + * * @return the generation for this class loader */ protected abstract Generation getGeneration(); /** * Returns the Debug object for the Framework instance + * * @return the Debug object for the Framework instance */ protected abstract Debug getDebug(); /** * Returns the classpath manager for this class loader + * * @return the classpath manager for this class loader */ public abstract ClasspathManager getClasspathManager(); /** * Returns the configuration for the Framework instance + * * @return the configuration for the Framework instance */ protected abstract EquinoxConfiguration getConfiguration(); /** * Returns the bundle loader for this class loader + * * @return the bundle loader for this class loader */ public abstract BundleLoader getBundleLoader(); /** - * Returns true if this class loader implementation has been - * registered with the JVM as a parallel class loader. - * This requires Java 7 or later. - * @return true if this class loader implementation has been - * registered with the JVM as a parallel class loader; otherwise - * false is returned. + * Returns true if this class loader implementation has been registered with the + * JVM as a parallel class loader. This requires Java 7 or later. This always + * returns true now that Java 8 is required. + * + * @return true if this class loader implementation has been registered with the + * JVM as a parallel class loader; otherwise false is returned. */ - public abstract boolean isRegisteredAsParallel(); + public boolean isRegisteredAsParallel() { + return true; + } /** - * Loads a class for the bundle. First delegate.findClass(name) is called. - * The delegate will query the system class loader, bundle imports, bundle - * local classes, bundle hosts and fragments. The delegate will call - * BundleClassLoader.findLocalClass(name) to find a class local to this - * bundle. - * @param name the name of the class to load. + * Loads a class for the bundle. First delegate.findClass(name) is called. The + * delegate will query the system class loader, bundle imports, bundle local + * classes, bundle hosts and fragments. The delegate will call + * BundleClassLoader.findLocalClass(name) to find a class local to this bundle. + * + * @param name the name of the class to load. * @param resolve indicates whether to resolve the loaded class or not. * @return The Class object. * @throws ClassNotFoundException if the class is not found. @@ -188,11 +211,12 @@ protected Class findClass(String name) throws ClassNotFoundException { } /** - * Gets a resource for the bundle. First delegate.findResource(name) is - * called. The delegate will query the system class loader, bundle imports, - * bundle local resources, bundle hosts and fragments. The delegate will - * call BundleClassLoader.findLocalResource(name) to find a resource local - * to this bundle. + * Gets a resource for the bundle. First delegate.findResource(name) is called. + * The delegate will query the system class loader, bundle imports, bundle local + * resources, bundle hosts and fragments. The delegate will call + * BundleClassLoader.findLocalResource(name) to find a resource local to this + * bundle. + * * @param name The resource path to get. * @return The URL of the resource or null if it does not exist. */ @@ -224,11 +248,12 @@ protected URL findResource(String name) { } /** - * Gets resources for the bundle. First delegate.findResources(name) is - * called. The delegate will query the system class loader, bundle imports, - * bundle local resources, bundle hosts and fragments. The delegate will - * call BundleClassLoader.findLocalResources(name) to find a resource local - * to this bundle. + * Gets resources for the bundle. First delegate.findResources(name) is called. + * The delegate will query the system class loader, bundle imports, bundle local + * resources, bundle hosts and fragments. The delegate will call + * BundleClassLoader.findLocalResources(name) to find a resource local to this + * bundle. + * * @param name The resource path to get. * @return The Enumeration of the resource URLs. */ @@ -252,8 +277,9 @@ protected Enumeration findResources(String name) throws IOException { } /** - * Finds a library for this bundle. Simply calls - * manager.findLibrary(libname) to find the library. + * Finds a library for this bundle. Simply calls manager.findLibrary(libname) to + * find the library. + * * @param libname The library to find. * @return The absolution path to the library or null if not found */ @@ -268,44 +294,25 @@ public ClasspathEntry createClassPathEntry(BundleFile bundlefile, Generation ent } public DefineClassResult defineClass(String name, byte[] classbytes, ClasspathEntry classpathEntry) { - // Note that we must check findLoadedClass again here since no locks are held between + // Note that we must check findLoadedClass again here since no locks are held + // between // calling findLoadedClass the first time and defineClass. // This is to allow weavers to get called while holding no locks. // See ClasspathManager.findLocalClass(String) boolean defined = false; Class result = null; - if (isRegisteredAsParallel()) { - // lock by class name in this case - boolean initialLock = lockClassName(name); - try { - result = findLoadedClass(name); - if (result == null) { - result = defineClass(name, classbytes, 0, classbytes.length, classpathEntry.getDomain()); - defined = true; - } - } finally { - if (initialLock) { - unlockClassName(name); - } - } - } else { - // lock by class loader instance in this case - synchronized (this) { - result = findLoadedClass(name); - if (result == null) { - result = defineClass(name, classbytes, 0, classbytes.length, classpathEntry.getDomain()); - defined = true; - } + synchronized (getClassLoadingLock(name)) { + result = findLoadedClass(name); + if (result == null) { + result = defineClass(name, classbytes, 0, classbytes.length, classpathEntry.getDomain()); + defined = true; } } return new DefineClassResult(result, defined); } public Class publicFindLoaded(String classname) { - if (isRegisteredAsParallel()) { - return findLoadedClass(classname); - } - synchronized (this) { + synchronized (getClassLoadingLock(classname)) { return findLoadedClass(classname); } } @@ -316,10 +323,13 @@ public Package publicGetPackage(String pkgname) { } } - public Package publicDefinePackage(String name, String specTitle, String specVersion, String specVendor, String implTitle, String implVersion, String implVendor, URL sealBase) { + public Package publicDefinePackage(String name, String specTitle, String specVersion, String specVendor, + String implTitle, String implVersion, String implVendor, URL sealBase) { synchronized (pkgLock) { Package pkg = getPackage(name); - return pkg != null ? pkg : definePackage(name, specTitle, specVersion, specVendor, implTitle, implVersion, implVendor, sealBase); + return pkg != null ? pkg + : definePackage(name, specTitle, specVersion, specVendor, implTitle, implVersion, implVendor, + sealBase); } } @@ -336,14 +346,18 @@ public Class findLocalClass(String classname) throws ClassNotFoundException { } /** - * Creates a ProtectionDomain which uses specified BundleFile and the permissions of the baseDomain - * @param bundlefile The source bundlefile the domain is for. + * Creates a ProtectionDomain which uses specified BundleFile and the + * permissions of the baseDomain + * + * @param bundlefile The source bundlefile the domain is for. * @param domainGeneration the source generation for the domain - * @return a ProtectionDomain which uses specified BundleFile and the permissions of the baseDomain + * @return a ProtectionDomain which uses specified BundleFile and the + * permissions of the baseDomain */ @SuppressWarnings("deprecation") protected ProtectionDomain createProtectionDomain(BundleFile bundlefile, Generation domainGeneration) { - // create a protection domain which knows about the codesource for this classpath entry (bug 89904) + // create a protection domain which knows about the codesource for this + // classpath entry (bug 89904) ProtectionDomain baseDomain = domainGeneration.getDomain(); try { // use the permissions supplied by the domain passed in from the framework @@ -351,7 +365,7 @@ protected ProtectionDomain createProtectionDomain(BundleFile bundlefile, Generat if (baseDomain != null) { permissions = baseDomain.getPermissions(); } else { - // no domain specified. Better use a collection that has all permissions + // no domain specified. Better use a collection that has all permissions // this is done just incase someone sets the security manager later permissions = ALLPERMISSIONS; } @@ -367,9 +381,12 @@ protected ProtectionDomain createProtectionDomain(BundleFile bundlefile, Generat } } File file = bundlefile.getBaseFile(); - // Bug 477787: file will be null when the osgi.framework configuration property contains an invalid value. - return new GenerationProtectionDomain(file == null ? null : new CodeSource(file.toURL(), certs), permissions, getGeneration()); - //return new ProtectionDomain(new CodeSource(bundlefile.getBaseFile().toURL(), certs), permissions); + // Bug 477787: file will be null when the osgi.framework configuration property + // contains an invalid value. + return new GenerationProtectionDomain(file == null ? null : new CodeSource(file.toURL(), certs), + permissions, getGeneration()); + // return new ProtectionDomain(new CodeSource(bundlefile.getBaseFile().toURL(), + // certs), permissions); } catch (MalformedURLException e) { // Failed to create our own domain; just return the baseDomain return baseDomain; @@ -399,48 +416,17 @@ public String toString() { StringBuilder result = new StringBuilder(super.toString()); if (b == null) return result.toString(); - return result.append('[').append(b.getSymbolicName()).append(':').append(b.getVersion()).append("(id=").append(b.getBundleId()).append(")]").toString(); //$NON-NLS-1$//$NON-NLS-2$ + return result.append('[').append(b.getSymbolicName()).append(':').append(b.getVersion()).append("(id=") //$NON-NLS-1$ + .append(b.getBundleId()).append(")]").toString(); //$NON-NLS-1$ } public void loadFragments(Collection fragments) { getClasspathManager().loadFragments(fragments); } - private boolean lockClassName(String classname) { - synchronized (classNameLocks) { - Object lockingThread = classNameLocks.get(classname); - Thread current = Thread.currentThread(); - if (lockingThread == current) - return false; - boolean previousInterruption = Thread.interrupted(); - try { - while (true) { - if (lockingThread == null) { - classNameLocks.put(classname, current); - return true; - } - - classNameLocks.wait(); - lockingThread = classNameLocks.get(classname); - } - } catch (InterruptedException e) { - previousInterruption = true; - // must not throw LinkageError or ClassNotFoundException here because that will cause all threads - // to fail to load the class (see bug 490902) - throw new Error("Interrupted while waiting for classname lock: " + classname, e); //$NON-NLS-1$ - } finally { - if (previousInterruption) { - current.interrupt(); - } - } - } - } - - private void unlockClassName(String classname) { - synchronized (classNameLocks) { - classNameLocks.remove(classname); - classNameLocks.notifyAll(); - } + @Override + public Object getClassLoadingLock(String classname) { + return classNameLocks.getLock(classname); } public void close() { From 80f34780d8c20e714f1558dea194dd56967d0894 Mon Sep 17 00:00:00 2001 From: Wendy Raschke Date: Mon, 18 Nov 2024 12:20:20 -0600 Subject: [PATCH 26/67] Undo temporary, fake product code chanfges for simulation --- .../jbatch/container/internal/resources/JBatchMessages.nlsprops | 2 -- .../public/xmlWS-4.0/io.openliberty.xmlWS-4.0.feature | 1 - .../resources/l10n/io.openliberty.xmlWS-4.0.properties | 2 -- .../com/ibm/wsspi/rest/config/resources/CWWKOMessages.nlsprops | 2 -- 4 files changed, 7 deletions(-) diff --git a/dev/com.ibm.jbatch.container/resources/com/ibm/jbatch/container/internal/resources/JBatchMessages.nlsprops b/dev/com.ibm.jbatch.container/resources/com/ibm/jbatch/container/internal/resources/JBatchMessages.nlsprops index aeba5d63ab3..da3e373661c 100644 --- a/dev/com.ibm.jbatch.container/resources/com/ibm/jbatch/container/internal/resources/JBatchMessages.nlsprops +++ b/dev/com.ibm.jbatch.container/resources/com/ibm/jbatch/container/internal/resources/JBatchMessages.nlsprops @@ -36,8 +36,6 @@ # 0001 - 0100: com.ibm.jbatch.container # -# Test commit only; not for merging - stopping.job.at.shutdown=CWWKY0001I: Issuing stop for job execution {0} because the batch component is deactivating. stopping.job.at.shutdown.explanation=This message is for informational purposes only. stopping.job.at.shutdown.useraction=No action is required. diff --git a/dev/com.ibm.websphere.appserver.features/visibility/public/xmlWS-4.0/io.openliberty.xmlWS-4.0.feature b/dev/com.ibm.websphere.appserver.features/visibility/public/xmlWS-4.0/io.openliberty.xmlWS-4.0.feature index 95dd433cfce..b14f6ab620e 100644 --- a/dev/com.ibm.websphere.appserver.features/visibility/public/xmlWS-4.0/io.openliberty.xmlWS-4.0.feature +++ b/dev/com.ibm.websphere.appserver.features/visibility/public/xmlWS-4.0/io.openliberty.xmlWS-4.0.feature @@ -1,4 +1,3 @@ -# Test commit only; not for merging -include= ~${workspace}/cnf/resources/bnd/feature.props symbolicName=io.openliberty.xmlWS-4.0 visibility=public diff --git a/dev/com.ibm.websphere.appserver.features/visibility/public/xmlWS-4.0/resources/l10n/io.openliberty.xmlWS-4.0.properties b/dev/com.ibm.websphere.appserver.features/visibility/public/xmlWS-4.0/resources/l10n/io.openliberty.xmlWS-4.0.properties index ad6c3db49ce..390c091c87b 100644 --- a/dev/com.ibm.websphere.appserver.features/visibility/public/xmlWS-4.0/resources/l10n/io.openliberty.xmlWS-4.0.properties +++ b/dev/com.ibm.websphere.appserver.features/visibility/public/xmlWS-4.0/resources/l10n/io.openliberty.xmlWS-4.0.properties @@ -16,8 +16,6 @@ #NLS_MESSAGEFORMAT_NONE # -# Test commit only; not for merging - description=This feature enables support for Jakarta XML Web Services 4.0. These web \ services and clients communicate using XML. Annotations can be used to simplify the development \ of service clients and endpoints. diff --git a/dev/com.ibm.websphere.rest.handler/resources/com/ibm/wsspi/rest/config/resources/CWWKOMessages.nlsprops b/dev/com.ibm.websphere.rest.handler/resources/com/ibm/wsspi/rest/config/resources/CWWKOMessages.nlsprops index 90e620c84e7..ca05d338df8 100644 --- a/dev/com.ibm.websphere.rest.handler/resources/com/ibm/wsspi/rest/config/resources/CWWKOMessages.nlsprops +++ b/dev/com.ibm.websphere.rest.handler/resources/com/ibm/wsspi/rest/config/resources/CWWKOMessages.nlsprops @@ -26,8 +26,6 @@ # All messages must use the range CWWKO1500 to CWWKO1529 -# Test commit only; not for merging - CWWKO1500_NOT_FOUND=CWWKO1500E: No configured instances of the {0} element were found in the server configuration. CWWKO1500_NOT_FOUND.explanation=The requested configuration element was not found in the server.xml file. CWWKO1500_NOT_FOUND.useraction=Verify that the configuration element exists in the server.xml file and that it is correctly spelled with matching case. From e08b955c9eb6de37952ce17fb2322fb89b76106a Mon Sep 17 00:00:00 2001 From: David Chan Date: Mon, 18 Nov 2024 15:41:52 -0500 Subject: [PATCH 27/67] Set intervals to 1 second like the rest of the FAT --- .../publish/resources/META-INF/microprofile-config.properties | 2 +- .../publish/servers/ContainerJustServer/jvm.options | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dev/io.openliberty.http.monitor_fat/publish/resources/META-INF/microprofile-config.properties b/dev/io.openliberty.http.monitor_fat/publish/resources/META-INF/microprofile-config.properties index 12f1f142cfb..b7fc1502df7 100644 --- a/dev/io.openliberty.http.monitor_fat/publish/resources/META-INF/microprofile-config.properties +++ b/dev/io.openliberty.http.monitor_fat/publish/resources/META-INF/microprofile-config.properties @@ -2,4 +2,4 @@ otel.metrics.exporter=otlp otel.sdk.disabled=false otel.traces.exporter=none otel.logs.exporter=none -otel.metric.export.interval=200 \ No newline at end of file +otel.metric.export.interval=1000 \ No newline at end of file diff --git a/dev/io.openliberty.http.monitor_fat/publish/servers/ContainerJustServer/jvm.options b/dev/io.openliberty.http.monitor_fat/publish/servers/ContainerJustServer/jvm.options index c2be5c22952..9cdd659ae36 100644 --- a/dev/io.openliberty.http.monitor_fat/publish/servers/ContainerJustServer/jvm.options +++ b/dev/io.openliberty.http.monitor_fat/publish/servers/ContainerJustServer/jvm.options @@ -2,4 +2,4 @@ -Dotel.traces.exporter=none -Dotel.logs.exporter=none -Dotel.sdk.disabled=false --Dotel.metric.export.interval=500 \ No newline at end of file +-Dotel.metric.export.interval=1000 \ No newline at end of file From b12cfcfc244443cf8d289a9e4e1b83d51d253e8b Mon Sep 17 00:00:00 2001 From: Nathan Rauh Date: Mon, 18 Nov 2024 15:36:47 -0600 Subject: [PATCH 28/67] Issue #27352 NLS messages for new Jakarta Concurrency function --- .../cdi/resources/CWWKCMessages.nlsprops | 32 +++++- .../internal/cdi/ConcurrencyExtension.java | 98 +++++++++++++++---- .../cdi/ConcurrencyExtensionMetadata.java | 37 +++++-- .../cdi/interceptor/ScheduleCronTrigger.java | 10 +- .../processor/AppDefinedResourceFactory.java | 6 ++ .../qualified/QualifiedResourceFactory.java | 8 ++ 6 files changed, 160 insertions(+), 31 deletions(-) diff --git a/dev/io.openliberty.concurrent.internal.cdi/resources/io/openliberty/concurrent/internal/cdi/resources/CWWKCMessages.nlsprops b/dev/io.openliberty.concurrent.internal.cdi/resources/io/openliberty/concurrent/internal/cdi/resources/CWWKCMessages.nlsprops index 577da15a041..20b4c3913f0 100644 --- a/dev/io.openliberty.concurrent.internal.cdi/resources/io/openliberty/concurrent/internal/cdi/resources/CWWKCMessages.nlsprops +++ b/dev/io.openliberty.concurrent.internal.cdi/resources/io/openliberty/concurrent/internal/cdi/resources/CWWKCMessages.nlsprops @@ -1,5 +1,5 @@ ############################################################################### -# Copyright (c) 2022,2023 IBM Corporation and others. +# Copyright (c) 2022,2024 IBM Corporation and others. # All rights reserved. This program and the accompanying materials # are made available under the terms of the Eclipse Public License 2.0 # which accompanies this distribution, and is available at @@ -24,5 +24,33 @@ # which do NOT contain replacement variables are NOT processed by the MessageFormat class # (single quote must be coded as one single quote '). -# All messages must use the range CWWCK1410 to CWWCK1499 +# All messages must use the range CWWKC1410 to CWWKC1499 +CWWKC1410.schedule.lacks.seconds=CWWKC1410E: The Schedule, {0}, specifies an \ + empty value for the seconds at which to run. You must specify a non-empty value. \ + Alternatively, omit the seconds from the Schedule and rely on the default \ + behavior of scheduling the task to run at the second at the start of the minute. +CWWKC1410.schedule.lacks.seconds.explanation=The empty array value indicates that \ + the field must be disregarded when computing scheduled times. The seconds field \ + cannot accept an empty value because it is the most granular unit and cannot be \ + disregarded. +CWWKC1410.schedule.lacks.seconds.useraction=Modify the seconds field of the \ + Schedule annotation to specify a non-empty value, or omit the seconds field \ + from the Schedule. + +CWWKC1411.qualified.res.err=CWWKC1411E: An error occurred creating a {0} bean \ + for the {1} annotation or {2} deployment descriptor element with the \ + {3} name and {4} qualifiers that is defined in the {5} application artifact. \ + The error is: {5} +CWWKC1411.qualified.res.err.explanation=An error occurred when creating the \ + resource or attempting to register it as a bean. +CWWKC1411.qualified.res.err.useraction=Ensure that the resource is configured \ + correctly. + +CWWKC1412.qualifier.conflict=CWWKC1412E: The {0} application artifact includes \ + multiple {1} resource definitions that have the {2} qualifiers. The names of \ + the conflicting {1} resource definitions are: {3}. +CWWKC1412.qualifier.conflict.explanation=Qualifiers must uniquely identify a \ + resource type. +CWWKC1412.qualifier.conflict.useraction=Each resource definition of the same \ + type must have different qualifiers or must not have any qualifiers. diff --git a/dev/io.openliberty.concurrent.internal.cdi/src/io/openliberty/concurrent/internal/cdi/ConcurrencyExtension.java b/dev/io.openliberty.concurrent.internal.cdi/src/io/openliberty/concurrent/internal/cdi/ConcurrencyExtension.java index 6fa5842b720..b0c8079bac2 100644 --- a/dev/io.openliberty.concurrent.internal.cdi/src/io/openliberty/concurrent/internal/cdi/ConcurrencyExtension.java +++ b/dev/io.openliberty.concurrent.internal.cdi/src/io/openliberty/concurrent/internal/cdi/ConcurrencyExtension.java @@ -12,6 +12,8 @@ *******************************************************************************/ package io.openliberty.concurrent.internal.cdi; +import java.io.PrintWriter; +import java.io.StringWriter; import java.lang.annotation.Annotation; import java.util.ArrayList; import java.util.Collections; @@ -24,8 +26,14 @@ import org.osgi.framework.ServiceReference; import com.ibm.websphere.csi.J2EEName; +import com.ibm.websphere.ras.Tr; +import com.ibm.websphere.ras.TraceComponent; +import com.ibm.websphere.ras.annotation.Trivial; import com.ibm.ws.cdi.CDIServiceUtils; +import com.ibm.ws.runtime.metadata.ApplicationMetaData; import com.ibm.ws.runtime.metadata.ComponentMetaData; +import com.ibm.ws.runtime.metadata.MetaData; +import com.ibm.ws.runtime.metadata.ModuleMetaData; import com.ibm.ws.threadContext.ComponentMetaDataAccessorImpl; import io.openliberty.concurrent.internal.cdi.interceptor.AsyncInterceptor; @@ -33,9 +41,13 @@ import io.openliberty.concurrent.internal.qualified.QualifiedResourceFactory; import jakarta.enterprise.concurrent.Asynchronous; import jakarta.enterprise.concurrent.ContextService; +import jakarta.enterprise.concurrent.ContextServiceDefinition; +import jakarta.enterprise.concurrent.ManagedExecutorDefinition; import jakarta.enterprise.concurrent.ManagedExecutorService; +import jakarta.enterprise.concurrent.ManagedScheduledExecutorDefinition; import jakarta.enterprise.concurrent.ManagedScheduledExecutorService; import jakarta.enterprise.concurrent.ManagedThreadFactory; +import jakarta.enterprise.concurrent.ManagedThreadFactoryDefinition; import jakarta.enterprise.event.Observes; import jakarta.enterprise.inject.Default; import jakarta.enterprise.inject.Instance; @@ -51,6 +63,8 @@ * CDI Extension for Jakarta Concurrency 3.1+ in Jakarta EE 11+, which corresponds to CDI 4.1+ */ public class ConcurrencyExtension implements Extension { + private static final TraceComponent tc = Tr.register(ConcurrencyExtension.class); + private static final Annotation[] DEFAULT_QUALIFIER_ARRAY = new Annotation[] { Default.Literal.INSTANCE }; private static final Set DEFAULT_QUALIFIER_SET = Set.of(Default.Literal.INSTANCE); @@ -149,11 +163,14 @@ private void addBeans(AfterBeanDiscovery event, List, Qualified try { event.addBean(new ContextServiceBean(factory)); } catch (Throwable x) { - // TODO NLS - System.out.println(" E Unable to create a bean for the " + - factory + " ContextServiceDefinition with the " + factory.getQualifiers() + " qualifiers" + - " due to the following error: "); - x.printStackTrace(); + Tr.error(tc, "CWWKC1411.qualified.res.err", + ContextService.class.getSimpleName(), + ContextServiceDefinition.class.getSimpleName(), + "context-service", + factory.getName(), + factory.getQualifiers(), + toArtifactName(factory.getDeclaringMetadata()), + toStackTrace(x)); } } @@ -164,11 +181,14 @@ private void addBeans(AfterBeanDiscovery event, List, Qualified try { event.addBean(new ManagedExecutorBean(factory)); } catch (Throwable x) { - // TODO NLS - System.out.println(" E Unable to create a bean for the " + - factory + " ManagedExecutorDefinition with the " + factory.getQualifiers() + " qualifiers" + - " due to the following error: "); - x.printStackTrace(); + Tr.error(tc, "CWWKC1411.qualified.res.err", + ManagedExecutorService.class.getSimpleName(), + ManagedExecutorDefinition.class.getSimpleName(), + "managed-executor", + factory.getName(), + factory.getQualifiers(), + toArtifactName(factory.getDeclaringMetadata()), + toStackTrace(x)); } } @@ -179,11 +199,14 @@ private void addBeans(AfterBeanDiscovery event, List, Qualified try { event.addBean(new ManagedScheduledExecutorBean(factory)); } catch (Throwable x) { - // TODO NLS - System.out.println(" E Unable to create a bean for the " + - factory + " ManagedScheduledExecutorDefinition with the " + factory.getQualifiers() + " qualifiers" + - " due to the following error: "); - x.printStackTrace(); + Tr.error(tc, "CWWKC1411.qualified.res.err", + ManagedScheduledExecutorService.class.getSimpleName(), + ManagedScheduledExecutorDefinition.class.getSimpleName(), + "managed-scheduled-executor", + factory.getName(), + factory.getQualifiers(), + toArtifactName(factory.getDeclaringMetadata()), + toStackTrace(x)); } } @@ -194,11 +217,14 @@ private void addBeans(AfterBeanDiscovery event, List, Qualified try { event.addBean(new ManagedThreadFactoryBean(factory, extSvc)); } catch (Throwable x) { - // TODO NLS - System.out.println(" E Unable to create a bean for the " + - factory + " ManagedThreadFactoryDefinition with the " + factory.getQualifiers() + " qualifiers" + - " due to the following error: "); - x.printStackTrace(); + Tr.error(tc, "CWWKC1411.qualified.res.err", + ManagedThreadFactory.class.getSimpleName(), + ManagedThreadFactoryDefinition.class.getSimpleName(), + "managed-thread-factory", + factory.getName(), + factory.getQualifiers(), + toArtifactName(factory.getDeclaringMetadata()), + toStackTrace(x)); } } } @@ -223,4 +249,36 @@ public void afterDeploymentValidation(@Observes AfterDeploymentValidation event, qualifierSetsPerMTF = null; } } + + /** + * Utility method to obtain the JEE name for a MetaData instance if possible, + * and otherwise the name. + * + * @param metadata ComponentMetaData, ModuleMetaData, or ApplicationMetaData. + * @return the artifact name, preferably as a JEE name string. + */ + @Trivial + private static String toArtifactName(MetaData metadata) { + if (metadata instanceof ComponentMetaData) + return ((ComponentMetaData) metadata).getJ2EEName().toString(); + else if (metadata instanceof ModuleMetaData) + return ((ModuleMetaData) metadata).getJ2EEName().toString(); + else if (metadata instanceof ApplicationMetaData) + return ((ApplicationMetaData) metadata).getJ2EEName().toString(); + else + return metadata.getName(); + } + + /** + * Utility method that converts an exception to a stack trace string. + * + * @param x exception. + * @return stack trace string. + */ + @Trivial + private static String toStackTrace(Throwable x) { + StringWriter s = new StringWriter(); + x.printStackTrace(new PrintWriter(s)); + return s.toString(); + } } \ No newline at end of file diff --git a/dev/io.openliberty.concurrent.internal.cdi/src/io/openliberty/concurrent/internal/cdi/ConcurrencyExtensionMetadata.java b/dev/io.openliberty.concurrent.internal.cdi/src/io/openliberty/concurrent/internal/cdi/ConcurrencyExtensionMetadata.java index 99d75a561f1..07f408356e8 100644 --- a/dev/io.openliberty.concurrent.internal.cdi/src/io/openliberty/concurrent/internal/cdi/ConcurrencyExtensionMetadata.java +++ b/dev/io.openliberty.concurrent.internal.cdi/src/io/openliberty/concurrent/internal/cdi/ConcurrencyExtensionMetadata.java @@ -28,6 +28,8 @@ import org.osgi.service.component.annotations.ReferencePolicy; import org.osgi.service.component.annotations.ReferencePolicyOption; +import com.ibm.websphere.ras.Tr; +import com.ibm.websphere.ras.TraceComponent; import com.ibm.ws.cdi.extension.CDIExtensionMetadataInternal; import com.ibm.ws.container.service.metadata.extended.DeferredMetaDataFactory; import com.ibm.ws.javaee.version.JavaEEVersion; @@ -45,6 +47,8 @@ @Component(configurationPolicy = ConfigurationPolicy.IGNORE, service = { CDIExtensionMetadata.class, QualifiedResourceFactories.class }) public class ConcurrencyExtensionMetadata implements CDIExtensionMetadata, CDIExtensionMetadataInternal, QualifiedResourceFactories { + private static final TraceComponent tc = Tr.register(ConcurrencyExtensionMetadata.class); + private static final Set> beanClasses = Set.of(ContextService.class, ManagedExecutorService.class, ManagedScheduledExecutorService.class, @@ -121,20 +125,37 @@ public class ConcurrencyExtensionMetadata implements CDIExtensionMetadata, CDIEx * @param resourceFactory the resource factory */ @Override - public void add(String jeeName, QualifiedResourceFactory.Type resourceType, - List qualifierNames, QualifiedResourceFactory resourceFactory) { + public void add(String jeeName, + QualifiedResourceFactory.Type resourceType, + List qualifierNames, + QualifiedResourceFactory resourceFactory) { List, QualifiedResourceFactory>> list = resourceFactories.get(jeeName); if (list == null) { list = List.of(new HashMap<>(), new HashMap<>(), new HashMap<>(), new HashMap<>()); resourceFactories.put(jeeName, list); } - Map, QualifiedResourceFactory> qualifiersToResourceFactory = list.get(resourceType.ordinal()); - QualifiedResourceFactory conflict = qualifiersToResourceFactory.put(qualifierNames, resourceFactory); - - if (conflict != null) - throw new IllegalStateException("The " + jeeName + " application artifact defines multiple " + // - resourceType + " resources with the " + qualifierNames + " qualifiers."); // TODO NLS and Tr.error + Map, QualifiedResourceFactory> qualifiersToResourceFactory = // + list.get(resourceType.ordinal()); + QualifiedResourceFactory conflict = // + qualifiersToResourceFactory.put(qualifierNames, resourceFactory); + + if (conflict != null) { + Set names = Set.of(resourceFactory.getName(), conflict.getName()); + + Tr.error(tc, "CWWKC1412.qualifier.conflict", + jeeName, + resourceType, + resourceFactory.getQualifiers(), + names); + + throw new IllegalStateException(Tr // + .formatMessage(tc, "CWWKC1412.qualifier.conflict", + jeeName, + resourceType, + resourceFactory.getQualifiers(), + names)); + } } @Override diff --git a/dev/io.openliberty.concurrent.internal.cdi/src/io/openliberty/concurrent/internal/cdi/interceptor/ScheduleCronTrigger.java b/dev/io.openliberty.concurrent.internal.cdi/src/io/openliberty/concurrent/internal/cdi/interceptor/ScheduleCronTrigger.java index 90f15057d04..612259d6832 100644 --- a/dev/io.openliberty.concurrent.internal.cdi/src/io/openliberty/concurrent/internal/cdi/interceptor/ScheduleCronTrigger.java +++ b/dev/io.openliberty.concurrent.internal.cdi/src/io/openliberty/concurrent/internal/cdi/interceptor/ScheduleCronTrigger.java @@ -17,6 +17,8 @@ import java.time.ZoneId; import java.time.ZonedDateTime; +import com.ibm.websphere.ras.Tr; +import com.ibm.websphere.ras.TraceComponent; import com.ibm.websphere.ras.annotation.Trivial; import jakarta.enterprise.concurrent.CronTrigger; @@ -27,6 +29,7 @@ * so that multiple triggers can compute from the same time. */ class ScheduleCronTrigger extends CronTrigger { + private static final TraceComponent tc = Tr.register(ScheduleCronTrigger.class); private static final Month[] ALL_MONTHS = Month.values(); @@ -105,7 +108,12 @@ static ScheduleCronTrigger create(Schedule schedule) { int[] seconds = schedule.seconds(); if (seconds.length == 0) - throw new IllegalArgumentException("seconds: {}"); // TODO NLS The seconds field cannot be ignored because no other units of Schedule are more granular. + // The seconds field cannot be ignored because no other + // units of Schedule are more granular. + throw new IllegalArgumentException(Tr // + .formatMessage(tc, + "CWWKC1410.schedule.lacks.seconds", + schedule)); trigger.months(months) // .daysOfMonth(daysOfMonth) // diff --git a/dev/io.openliberty.concurrent.internal/src/io/openliberty/concurrent/internal/processor/AppDefinedResourceFactory.java b/dev/io.openliberty.concurrent.internal/src/io/openliberty/concurrent/internal/processor/AppDefinedResourceFactory.java index c90b8805ecc..386cf0c214d 100644 --- a/dev/io.openliberty.concurrent.internal/src/io/openliberty/concurrent/internal/processor/AppDefinedResourceFactory.java +++ b/dev/io.openliberty.concurrent.internal/src/io/openliberty/concurrent/internal/processor/AppDefinedResourceFactory.java @@ -307,6 +307,12 @@ public MetaData getDeclaringMetadata() { return declaringMetadata; } + @Override + @Trivial + public String getName() { + return jndiName; + } + /** * Returns text showing an example of a valid qualifier with the specified * class name. diff --git a/dev/io.openliberty.concurrent.internal/src/io/openliberty/concurrent/internal/qualified/QualifiedResourceFactory.java b/dev/io.openliberty.concurrent.internal/src/io/openliberty/concurrent/internal/qualified/QualifiedResourceFactory.java index e30657e759b..7c5e94eb6d3 100644 --- a/dev/io.openliberty.concurrent.internal/src/io/openliberty/concurrent/internal/qualified/QualifiedResourceFactory.java +++ b/dev/io.openliberty.concurrent.internal/src/io/openliberty/concurrent/internal/qualified/QualifiedResourceFactory.java @@ -47,6 +47,14 @@ enum Type { */ MetaData getDeclaringMetadata(); + /** + * Returns the name of the resource definition, which is typically a + * JNDI name in java:comp, java:module, java:app, or java:global + * + * @return the name. + */ + String getName(); + /** * Returns instances of the qualifier annotations for this resource factory. * From b6939b3f51b3cef359c446ccaa631a036fc0fa66 Mon Sep 17 00:00:00 2001 From: Neil Richards <7203556+ngmr@users.noreply.github.com> Date: Tue, 19 Nov 2024 10:40:27 +0000 Subject: [PATCH 29/67] refactor: convert TrmFirstContactMessageType to enum --- .../mfp/trm/TrmFirstContactMessageType.java | 194 ++++++++---------- 1 file changed, 86 insertions(+), 108 deletions(-) diff --git a/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/trm/TrmFirstContactMessageType.java b/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/trm/TrmFirstContactMessageType.java index 0773a89109a..6d3c8af7e35 100644 --- a/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/trm/TrmFirstContactMessageType.java +++ b/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/trm/TrmFirstContactMessageType.java @@ -1,125 +1,103 @@ -/******************************************************************************* - * Copyright (c) 2012 IBM Corporation and others. +/* ============================================================================= + * Copyright (c) 2012,2024 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * * Contributors: * IBM Corporation - initial API and implementation - *******************************************************************************/ + * ============================================================================= + */ + package com.ibm.ws.sib.mfp.trm; -import com.ibm.ws.sib.mfp.*; -import com.ibm.ws.sib.utils.ras.SibTr; +import static com.ibm.websphere.ras.TraceComponent.isAnyTracingEnabled; +import static com.ibm.ws.sib.mfp.MfpConstants.MSG_BUNDLE; +import static com.ibm.ws.sib.mfp.MfpConstants.MSG_GROUP; +import static com.ibm.ws.sib.utils.ras.SibTr.debug; +import static com.ibm.ws.sib.utils.ras.SibTr.register; +import static java.util.Collections.unmodifiableMap; + +import java.util.HashMap; +import java.util.Map; + import com.ibm.websphere.ras.TraceComponent; +import com.ibm.ws.sib.mfp.IntAble; /** * TrmFirstContactMessageType is a type-safe enumeration which indicates the * type of a TRM First Contact message. */ -public final class TrmFirstContactMessageType implements IntAble { - - private static TraceComponent tc = SibTr.register(TrmFirstContactMessageType.class, MfpConstants.MSG_GROUP, MfpConstants.MSG_BUNDLE); - - /** Constant denoting a Client Bootstrap Request */ - public final static TrmFirstContactMessageType CLIENT_BOOTSTRAP_REQUEST = new TrmFirstContactMessageType("CLIENT_BOOTSTRAP_REQUEST" ,0); - - /** Constant denoting a Client Bootstrap Reply */ - public final static TrmFirstContactMessageType CLIENT_BOOTSTRAP_REPLY = new TrmFirstContactMessageType("CLIENT_BOOTSTRAP_REPLY" ,1); - - /** Constant denoting a Client Attach Request */ - public final static TrmFirstContactMessageType CLIENT_ATTACH_REQUEST = new TrmFirstContactMessageType("CLIENT_ATTACH_REQUEST" ,2); - - /** Constant denoting a Client Attach Request 2 */ - public final static TrmFirstContactMessageType CLIENT_ATTACH_REQUEST2 = new TrmFirstContactMessageType("CLIENT_ATTACH_REQUEST2" ,3); - - /** Constant denoting a Client Attach Reply */ - public final static TrmFirstContactMessageType CLIENT_ATTACH_REPLY = new TrmFirstContactMessageType("CLIENT_ATTACH_REPLY" ,4); - - /** Constant denoting a ME Bootstrap Request */ - public final static TrmFirstContactMessageType ME_CONNECT_REQUEST = new TrmFirstContactMessageType("ME_CONNECT_REQUEST" ,5); - - /** Constant denoting a ME Bootstrap Reply */ - public final static TrmFirstContactMessageType ME_CONNECT_REPLY = new TrmFirstContactMessageType("ME_CONNECT_REPLY" ,6); - - /** Constant denoting a ME Link Request */ - public final static TrmFirstContactMessageType ME_LINK_REQUEST = new TrmFirstContactMessageType("ME_LINK_REQUEST" ,7); - - /** Constant denoting a ME Link Reply */ - public final static TrmFirstContactMessageType ME_LINK_REPLY = new TrmFirstContactMessageType("ME_LINK_REPLY" ,8); - - /** Constant denoting a ME Bridge Request */ - public final static TrmFirstContactMessageType ME_BRIDGE_REQUEST = new TrmFirstContactMessageType("ME_BRIDGE_REQUEST" ,9); - - /** Constant denoting a ME Bridge Reply */ - public final static TrmFirstContactMessageType ME_BRIDGE_REPLY = new TrmFirstContactMessageType("ME_BRIDGE_REPLY" ,10); - - /** Constant denoting a ME Bridge Bootstrap Request */ - public final static TrmFirstContactMessageType ME_BRIDGE_BOOTSTRAP_REQUEST = new TrmFirstContactMessageType("ME_BRIDGE_BOOTSTRAP_REQUEST", 11); - - /** Constant denoting a ME Bridge Bootstrap Reply */ - public final static TrmFirstContactMessageType ME_BRIDGE_BOOTSTRAP_REPLY = new TrmFirstContactMessageType("ME_BRIDGE_BOOTSTRAP_REPLY", 12); - - /* Array of defined TrmFirstContactMessageTypes - needed by getTrmFirstContactMessageType */ - private final static TrmFirstContactMessageType[] set = {CLIENT_BOOTSTRAP_REQUEST - ,CLIENT_BOOTSTRAP_REPLY - ,CLIENT_ATTACH_REQUEST - ,CLIENT_ATTACH_REQUEST2 - ,CLIENT_ATTACH_REPLY - ,ME_CONNECT_REQUEST - ,ME_CONNECT_REPLY - ,ME_LINK_REQUEST - ,ME_LINK_REPLY - ,ME_BRIDGE_REQUEST - ,ME_BRIDGE_REPLY - ,ME_BRIDGE_BOOTSTRAP_REQUEST - ,ME_BRIDGE_BOOTSTRAP_REPLY - }; - - private String name; - private int value; - - /* Private constructor - ensures the 'constants' defined here are the total set. */ - private TrmFirstContactMessageType(String aName, int aValue) { - name = aName; - value = aValue; - } - - /** - * Returns the corresponding TrmFirstContactMessageType for a given integer. - * This method should NOT be called by any code outside the MFP component. - * It is only public so that it can be accessed by sub-packages. - * - * @param aValue The integer for which an TrmFirstContactMessageType is required. - * - * @return The corresponding TrmFirstContactMessageType - */ - public final static TrmFirstContactMessageType getTrmFirstContactMessageType(int aValue) { - if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(tc,"Value = " + aValue); - return set[aValue]; - } - - /** - * Returns the integer representation of the TrmFirstContactMessageType. - * This method should NOT be called by any code outside the MFP component. - * It is only public so that it can be accessed by sub-packages. - * - * @return The int representation of the instance. - */ - public final int toInt() { - return value; - } - - /** - * Returns the name of the TrmFirstContactMessageType. - * - * @return The name of the instance. - */ - public final String toString() { - return name; - } - +public enum TrmFirstContactMessageType implements IntAble { + /** Constant denoting a Client Bootstrap Request */ + CLIENT_BOOTSTRAP_REQUEST(0), + /** Constant denoting a Client Bootstrap Reply */ + CLIENT_BOOTSTRAP_REPLY(1), + /** Constant denoting a Client Attach Request */ + CLIENT_ATTACH_REQUEST(2), + /** Constant denoting a Client Attach Request 2 */ + CLIENT_ATTACH_REQUEST2(3), + /** Constant denoting a Client Attach Reply */ + CLIENT_ATTACH_REPLY(4), + /** Constant denoting a ME Bootstrap Request */ + ME_CONNECT_REQUEST(5), + /** Constant denoting a ME Bootstrap Reply */ + ME_CONNECT_REPLY(6), + /** Constant denoting a ME Link Request */ + ME_LINK_REQUEST(7), + /** Constant denoting a ME Link Reply */ + ME_LINK_REPLY(8), + /** Constant denoting a ME Bridge Request */ + ME_BRIDGE_REQUEST(9), + /** Constant denoting a ME Bridge Reply */ + ME_BRIDGE_REPLY(10), + /** Constant denoting a ME Bridge Bootstrap Request */ + ME_BRIDGE_BOOTSTRAP_REQUEST(11), + /** Constant denoting a ME Bridge Bootstrap Reply */ + ME_BRIDGE_BOOTSTRAP_REPLY(12), + ; + + private static final TraceComponent tc = register(TrmFirstContactMessageType.class, MSG_GROUP, MSG_BUNDLE); + + private static final Map types; + + static { + Map map = new HashMap<>(); + for (TrmFirstContactMessageType type: values()) map.put(type.toInt(), type); + types = unmodifiableMap(map); + } + + private final int value; + + private TrmFirstContactMessageType(int aValue) { + value = aValue; + } + + /** + * Returns the corresponding TrmFirstContactMessageType for a given integer. + * This method should NOT be called by any code outside the MFP component. + * It is only public so that it can be accessed by sub-packages. + * + * @param aValue The integer for which an TrmFirstContactMessageType is required. + * + * @return The corresponding TrmFirstContactMessageType + */ + public static final TrmFirstContactMessageType getTrmFirstContactMessageType(int aValue) { + if (isAnyTracingEnabled() && tc.isDebugEnabled()) debug(tc,"Value = " + aValue); + return types.get(aValue); + } + + /** + * Returns the integer representation of the TrmFirstContactMessageType. + * This method should NOT be called by any code outside the MFP component. + * It is only public so that it can be accessed by sub-packages. + * + * @return The int representation of the instance. + */ + public final int toInt() { + return value; + } } From a1d17631d509160a2b7831834ed141fb78dc1165 Mon Sep 17 00:00:00 2001 From: Neil Richards <7203556+ngmr@users.noreply.github.com> Date: Tue, 19 Nov 2024 10:45:28 +0000 Subject: [PATCH 30/67] refactor: convert JmsBodyType to enum --- .../src/com/ibm/ws/sib/mfp/JmsBodyType.java | 264 +++++++++--------- 1 file changed, 128 insertions(+), 136 deletions(-) diff --git a/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/JmsBodyType.java b/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/JmsBodyType.java index 7d39f533b55..9a862483436 100644 --- a/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/JmsBodyType.java +++ b/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/JmsBodyType.java @@ -1,152 +1,144 @@ -/******************************************************************************* - * Copyright (c) 2012 IBM Corporation and others. +/* ============================================================================= + * Copyright (c) 2012,2024 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * * Contributors: * IBM Corporation - initial API and implementation - *******************************************************************************/ + * ============================================================================= + */ package com.ibm.ws.sib.mfp; -import com.ibm.websphere.sib.SIApiConstants; -import com.ibm.ws.sib.utils.ras.SibTr; +import static com.ibm.websphere.ras.TraceComponent.isAnyTracingEnabled; +import static com.ibm.websphere.sib.SIApiConstants.JMS_FORMAT; +import static com.ibm.websphere.sib.SIApiConstants.JMS_FORMAT_BYTES; +import static com.ibm.websphere.sib.SIApiConstants.JMS_FORMAT_MAP; +import static com.ibm.websphere.sib.SIApiConstants.JMS_FORMAT_OBJECT; +import static com.ibm.websphere.sib.SIApiConstants.JMS_FORMAT_STREAM; +import static com.ibm.websphere.sib.SIApiConstants.JMS_FORMAT_TEXT; +import static com.ibm.ws.sib.mfp.MfpConstants.MSG_BUNDLE; +import static com.ibm.ws.sib.mfp.MfpConstants.MSG_GROUP; +import static com.ibm.ws.sib.utils.ras.SibTr.debug; +import static com.ibm.ws.sib.utils.ras.SibTr.entry; +import static com.ibm.ws.sib.utils.ras.SibTr.exit; +import static com.ibm.ws.sib.utils.ras.SibTr.register; +import static java.util.Collections.unmodifiableMap; + +import java.util.HashMap; +import java.util.Map; + import com.ibm.websphere.ras.TraceComponent; /** * JmsBodyType is a type-safe enumeration for JmsBody types. */ -public final class JmsBodyType implements IntAble { - - private static TraceComponent tc = SibTr.register(JmsBodyType.class, MfpConstants.MSG_GROUP, MfpConstants.MSG_BUNDLE); - - /** Integer value of the NULL JMsBodyType */ - public final static int NULL_INT = 0; - /** Integer value of the BYTES JMsBodyType */ - public final static int BYTES_INT = 1; - /** Integer value of the MAP JMsBodyType */ - public final static int MAP_INT = 2; - /** Integer value of the OBJECT JMsBodyType */ - public final static int OBJECT_INT = 3; - /** Integer value of the STREAM JMsBodyType */ - public final static int STREAM_INT = 4; - /** Integer value of the TEXT JMsBodyType */ - public final static int TEXT_INT = 5; - - - - /** Constant denoting a null-bodied JMS Message */ - public final static JmsBodyType NULL = new JmsBodyType("NULL" ,(byte)NULL_INT); - - /** Constant denoting JmsBody Type of Bytes */ - public final static JmsBodyType BYTES = new JmsBodyType("BYTES" ,(byte)BYTES_INT); - - /** Constant denoting JmsBody Type of Map */ - public final static JmsBodyType MAP = new JmsBodyType("MAP" ,(byte)MAP_INT); - - /** Constant denoting JmsBody Type of Object */ - public final static JmsBodyType OBJECT = new JmsBodyType("OBJECT",(byte)OBJECT_INT); - - /** Constant denoting JmsBody Type of Stream */ - public final static JmsBodyType STREAM = new JmsBodyType("STREAM",(byte)STREAM_INT); - - /** Constant denoting JmsBody Type of Text */ - public final static JmsBodyType TEXT = new JmsBodyType("TEXT" ,(byte)TEXT_INT); - - /* Array of defined JmsBodyTypes - needed by getJmsBodyType */ - private final static JmsBodyType[] set = {NULL - ,BYTES - ,MAP - ,OBJECT - ,STREAM - ,TEXT - }; - - private String name; - private Byte value; - private int intValue; - - /* Private constructor - ensures the 'constants' define here are the total set. */ - private JmsBodyType(String aName, byte aValue) { - name = aName; - value = new Byte(aValue); - intValue = (int)aValue; - } - - /** - * Return the appropriate JMSBodyType for a specific format string - * - * @param format A String corresponding to the SDO format of a JMS Message - * - * @return JmsBodyType The JmsBodyType singleton which maps to the given format string - */ - public static JmsBodyType getBodyType(String format) { - if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.entry(tc, "getBodyType"); - - JmsBodyType result = null; - if (format.equals(SIApiConstants.JMS_FORMAT_BYTES)) - result = BYTES; - else if (format.equals(SIApiConstants.JMS_FORMAT_TEXT)) - result = TEXT; - else if (format.equals(SIApiConstants.JMS_FORMAT_OBJECT)) - result = OBJECT; - else if (format.equals(SIApiConstants.JMS_FORMAT_STREAM)) - result = STREAM; - else if (format.equals(SIApiConstants.JMS_FORMAT_MAP)) - result = MAP; - else if (format.equals(SIApiConstants.JMS_FORMAT)) - result = NULL; - - if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.exit(tc, "getBodyType"); - return result; - } - - /** - * Returns the corresponding JmsBodyType for a given Byte. - * This method should NOT be called by any code outside the TEXT component. - * It is only public so that it can be accessed by sub-packages. - * - * @param aValue The Byte for which an JmsBodyType is required. - * - * @return The corresponding JmsBodyType - */ - public final static JmsBodyType getJmsBodyType(Byte aValue) { - if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(tc,"Value = " + aValue); - return set[aValue.intValue()]; - } - - /** - * Returns the Byte representation of the JmsBodyType. - * This method should NOT be called by any code outside the MFP component. - * It is only public so that it can be accessed by sub-packages. - * - * @return The Byte representation of the instance. - */ - public final Byte toByte() { - return value; - } - - /** - * Returns the integer representation of the JmsBodyType. - * This method should NOT be called by any code outside the SIBus. - * It is only public so that it can be accessed by SIBus components. - * - * @return The int representation of the instance. - */ - public final int toInt() { - return intValue; - } - - /** - * Returns the name of the JmsBodyType. - * - * @return The name of the instance. - */ - public final String toString() { - return name; - } - +public enum JmsBodyType implements IntAble { + /** Constant denoting a null-bodied JMS Message */ + NULL(0, JMS_FORMAT), + /** Constant denoting JmsBody Type of Bytes */ + BYTES(1, JMS_FORMAT_BYTES), + /** Constant denoting JmsBody Type of Map */ + MAP(2, JMS_FORMAT_MAP), + /** Constant denoting JmsBody Type of Object */ + OBJECT(3, JMS_FORMAT_OBJECT), + /** Constant denoting JmsBody Type of Stream */ + STREAM(4, JMS_FORMAT_STREAM), + /** Constant denoting JmsBody Type of Text */ + TEXT(5, JMS_FORMAT_TEXT), + ; + + private static final TraceComponent tc = register(JmsBodyType.class, MSG_GROUP, MSG_BUNDLE); + + /** Integer value of the NULL JMsBodyType */ + public static final int NULL_INT = NULL.toInt(); + /** Integer value of the BYTES JMsBodyType */ + public static final int BYTES_INT = BYTES.toInt(); + /** Integer value of the MAP JMsBodyType */ + public static final int MAP_INT = MAP.toInt(); + /** Integer value of the OBJECT JMsBodyType */ + public static final int OBJECT_INT = OBJECT.toInt(); + /** Integer value of the STREAM JMsBodyType */ + public static final int STREAM_INT = STREAM.toInt(); + /** Integer value of the TEXT JMsBodyType */ + public static final int TEXT_INT = TEXT.toInt(); + + private static final Map types; + private static final Map typesByFormat; + + static { + Map map = new HashMap<>(); + Map formatMap = new HashMap<>(); + for (JmsBodyType type: values()) { + map.put(type.toInt(), type); + formatMap.put(type.format, type); + } + types = unmodifiableMap(map); + typesByFormat = unmodifiableMap(formatMap); + } + + private final String format; + private final Byte value; + private final int intValue; + + private JmsBodyType(int aValue, String sdoFormat) { + format = sdoFormat; + value = Byte.valueOf((byte)aValue); + intValue = aValue; + } + + /** + * Return the appropriate JMSBodyType for a specific format string + * + * @param format A String corresponding to the SDO format of a JMS Message + * + * @return JmsBodyType The JmsBodyType singleton which maps to the given format string + */ + public static JmsBodyType getBodyType(String format) { + if (isAnyTracingEnabled() && tc.isEntryEnabled()) entry(tc, "getBodyType"); + + JmsBodyType result = typesByFormat.get(format); + + if (isAnyTracingEnabled() && tc.isEntryEnabled()) exit(tc, "getBodyType", result); + return result; + } + + /** + * Returns the corresponding JmsBodyType for a given Byte. + * This method should NOT be called by any code outside the TEXT component. + * It is only public so that it can be accessed by sub-packages. + * + * @param aValue The Byte for which an JmsBodyType is required. + * + * @return The corresponding JmsBodyType + */ + public static final JmsBodyType getJmsBodyType(Byte aValue) { + if (isAnyTracingEnabled() && tc.isDebugEnabled()) debug(tc,"Value = " + aValue); + return types.get(aValue.intValue()); + } + + /** + * Returns the Byte representation of the JmsBodyType. + * This method should NOT be called by any code outside the MFP component. + * It is only public so that it can be accessed by sub-packages. + * + * @return The Byte representation of the instance. + */ + public final Byte toByte() { + return value; + } + + /** + * Returns the integer representation of the JmsBodyType. + * This method should NOT be called by any code outside the SIBus. + * It is only public so that it can be accessed by SIBus components. + * + * @return The int representation of the instance. + */ + public final int toInt() { + return intValue; + } } From a6e3ac7012395f6da9aa192f9c029a0f411072e4 Mon Sep 17 00:00:00 2001 From: Neil Richards <7203556+ngmr@users.noreply.github.com> Date: Mon, 18 Nov 2024 11:02:58 +0000 Subject: [PATCH 31/67] fix: use JmsBodyType enum in switch statements --- .../src/com/ibm/ws/sib/mfp/JmsBodyType.java | 33 +++-- .../sib/mfp/impl/JsJmsMessageFactoryImpl.java | 24 ++-- .../ibm/ws/sib/mfp/impl/JsJmsMessageImpl.java | 16 ++- .../ws/sib/api/jms/impl/JmsMessageImpl.java | 123 +++++++++--------- 4 files changed, 103 insertions(+), 93 deletions(-) diff --git a/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/JmsBodyType.java b/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/JmsBodyType.java index 9a862483436..3f262df9548 100644 --- a/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/JmsBodyType.java +++ b/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/JmsBodyType.java @@ -53,18 +53,13 @@ public enum JmsBodyType implements IntAble { private static final TraceComponent tc = register(JmsBodyType.class, MSG_GROUP, MSG_BUNDLE); - /** Integer value of the NULL JMsBodyType */ - public static final int NULL_INT = NULL.toInt(); - /** Integer value of the BYTES JMsBodyType */ - public static final int BYTES_INT = BYTES.toInt(); - /** Integer value of the MAP JMsBodyType */ - public static final int MAP_INT = MAP.toInt(); - /** Integer value of the OBJECT JMsBodyType */ - public static final int OBJECT_INT = OBJECT.toInt(); - /** Integer value of the STREAM JMsBodyType */ - public static final int STREAM_INT = STREAM.toInt(); - /** Integer value of the TEXT JMsBodyType */ - public static final int TEXT_INT = TEXT.toInt(); + // TODO remove constants once all dependencies addressed + public static final int NULL_INT = 0; + public static final int BYTES_INT = 1; + public static final int MAP_INT = 2; + public static final int OBJECT_INT = 3; + public static final int STREAM_INT = 4; + public static final int TEXT_INT = 5; private static final Map types; private static final Map typesByFormat; @@ -120,6 +115,20 @@ public static final JmsBodyType getJmsBodyType(Byte aValue) { return types.get(aValue.intValue()); } + /** + * Returns the corresponding JmsBodyType for a given integer. + * This method should NOT be called by any code outside the TEXT component. + * It is only public so that it can be accessed by sub-packages. + * + * @param aValue The integer for which an JmsBodyType is required. + * + * @return The corresponding JmsBodyType + */ + public static final JmsBodyType getJmsBodyType(int aValue) { + if (isAnyTracingEnabled() && tc.isDebugEnabled()) debug(tc,"Value = " + aValue); + return types.get(aValue); + } + /** * Returns the Byte representation of the JmsBodyType. * This method should NOT be called by any code outside the MFP component. diff --git a/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/impl/JsJmsMessageFactoryImpl.java b/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/impl/JsJmsMessageFactoryImpl.java index 977fcfa3755..3fccd7eb53e 100644 --- a/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/impl/JsJmsMessageFactoryImpl.java +++ b/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/impl/JsJmsMessageFactoryImpl.java @@ -1,19 +1,23 @@ -/******************************************************************************* - * Copyright (c) 2012 IBM Corporation and others. +/* ============================================================================= + * Copyright (c) 2012,2024 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * * Contributors: * IBM Corporation - initial API and implementation - *******************************************************************************/ + * ============================================================================= + */ package com.ibm.ws.sib.mfp.impl; import com.ibm.ws.sib.mfp.*; import com.ibm.ws.sib.utils.ras.SibTr; + +import static com.ibm.ws.sib.mfp.JmsBodyType.getJmsBodyType; + import com.ibm.websphere.ras.TraceComponent; /** @@ -185,25 +189,25 @@ final JsJmsMessage createInboundJmsMessage(JsMsgObject jmo, int messageType) { JsJmsMessage jmsMessage = null; - switch (messageType) { + switch (getJmsBodyType(messageType)) { - case JmsBodyType.BYTES_INT: + case BYTES: jmsMessage = new JsJmsBytesMessageImpl(jmo); break; - case JmsBodyType.MAP_INT: + case MAP: jmsMessage = new JsJmsMapMessageImpl(jmo); break; - case JmsBodyType.OBJECT_INT: + case OBJECT: jmsMessage = new JsJmsObjectMessageImpl(jmo); break; - case JmsBodyType.STREAM_INT: + case STREAM: jmsMessage = new JsJmsStreamMessageImpl(jmo); break; - case JmsBodyType.TEXT_INT: + case TEXT: jmsMessage = new JsJmsTextMessageImpl(jmo); break; diff --git a/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/impl/JsJmsMessageImpl.java b/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/impl/JsJmsMessageImpl.java index a0d106bd178..d040620ed9b 100644 --- a/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/impl/JsJmsMessageImpl.java +++ b/dev/com.ibm.ws.messaging.common/src/com/ibm/ws/sib/mfp/impl/JsJmsMessageImpl.java @@ -1,17 +1,20 @@ -/******************************************************************************* - * Copyright (c) 2012, 2014 IBM Corporation and others. +/* ============================================================================= + * Copyright (c) 2012,2024 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * * Contributors: * IBM Corporation - initial API and implementation - *******************************************************************************/ + * ============================================================================= + */ package com.ibm.ws.sib.mfp.impl; +import static com.ibm.ws.sib.mfp.JmsBodyType.getJmsBodyType; + import java.util.HashSet; import java.util.List; import java.util.Set; @@ -110,7 +113,7 @@ class JsJmsMessageImpl extends JsApiMessageImpl implements JsJmsMessage { /* Set the JMS message fields */ setJsMessageType(MessageType.JMS); - setSubtype(JmsBodyType.NULL_INT); + setSubtype(JmsBodyType.NULL.toInt()); /* Set some of the JMS specific header values unless flagged not to */ /* For an Inbound MQ message the fields will be set by the */ @@ -319,8 +322,7 @@ public JsMessage getSent(boolean copy) throws MessageCopyFailedException { @Override public final JmsBodyType getBodyType() { /* Get the subtype and get the corresponding JmsBodyType to return */ - int bType = getSubtype(); - return JmsBodyType.getJmsBodyType(Byte.valueOf((byte) bType)); + return getJmsBodyType(getSubtype()); } /* ************************************************************************* */ diff --git a/dev/com.ibm.ws.messaging.jms.2.0/src/com/ibm/ws/sib/api/jms/impl/JmsMessageImpl.java b/dev/com.ibm.ws.messaging.jms.2.0/src/com/ibm/ws/sib/api/jms/impl/JmsMessageImpl.java index 26a112244a9..07a2dff3a4a 100644 --- a/dev/com.ibm.ws.messaging.jms.2.0/src/com/ibm/ws/sib/api/jms/impl/JmsMessageImpl.java +++ b/dev/com.ibm.ws.messaging.jms.2.0/src/com/ibm/ws/sib/api/jms/impl/JmsMessageImpl.java @@ -1,15 +1,16 @@ -/******************************************************************************* - * Copyright (c) 2012, 2015, 2020 IBM Corporation and others. +/* ============================================================================= + * Copyright (c) 2012,2024 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * * Contributors: * IBM Corporation - initial API and implementation - *******************************************************************************/ + * ============================================================================= + */ package com.ibm.ws.sib.api.jms.impl; import java.io.IOException; @@ -1987,34 +1988,29 @@ static Message inboundJmsInstance(JsJmsMessage newMsg, JmsSessionImpl newSess, M if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(tc, "body type: " + bt); - int bodyTypeInt = -2; // This is not one of the JmsBodyType constants. - if (bt != null) { - bodyTypeInt = bt.toInt(); - } - - switch (bodyTypeInt) { + switch (bt) { - case JmsBodyType.NULL_INT: + case NULL: jmsMsg = new JmsMessageImpl(newMsg, newSess); break; - case JmsBodyType.TEXT_INT: + case TEXT: jmsMsg = new JmsTextMessageImpl((JsJmsTextMessage) newMsg, newSess); break; - case JmsBodyType.MAP_INT: + case MAP: jmsMsg = new JmsMapMessageImpl((JsJmsMapMessage) newMsg, newSess); break; - case JmsBodyType.OBJECT_INT: + case OBJECT: jmsMsg = new JmsObjectMessageImpl((JsJmsObjectMessage) newMsg, newSess); break; - case JmsBodyType.BYTES_INT: + case BYTES: jmsMsg = new JmsBytesMessageImpl((JsJmsBytesMessage) newMsg, newSess); break; - case JmsBodyType.STREAM_INT: + case STREAM: jmsMsg = new JmsStreamMessageImpl((JsJmsStreamMessage) newMsg, newSess); break; @@ -2736,63 +2732,60 @@ public T getBody(Class paramClass) throws JMSException, MessageFormatExce T returnObj = null; try { - int bodyType = msg.getBodyType().toInt(); - Object _messageObject = null; - switch (bodyType) { - case JmsBodyType.TEXT_INT: - try { + final Object _messageObject; + switch (msg.getBodyType()) { + case TEXT: + try { _messageObject = ((JsJmsTextMessage) msg).getText(); - } catch (UnsupportedEncodingException exp) { + } catch (UnsupportedEncodingException exp) { throw getJMSException(paramClass, exp); - } - break; + } + break; - case JmsBodyType.OBJECT_INT: - try { + case OBJECT: + try { _messageObject = ((JsJmsObjectMessage) msg).getRealObject(); - //As per spec: if the message is an ObjectMessage and object deserialization fails + //As per spec: if the message is an ObjectMessage and object deserialization fails //then throw MessageFormatException. if (_messageObject != null && !Serializable.class.isAssignableFrom(paramClass)) { - throw getMessageFormatException(paramClass); + throw getMessageFormatException(paramClass); } - } catch (ClassNotFoundException cnfe) { + } catch (ClassNotFoundException cnfe) { throw getJMSException(paramClass, cnfe); - } catch (IOException ioe) { + } catch (IOException ioe) { throw getJMSException(paramClass, ioe); - } - break; + } + break; - case JmsBodyType.MAP_INT: - try { + case MAP: + try { _messageObject = getMapMessage(); - //As per spec: If the message is a MapMessage then this parameter must be set to java.util.Map.class (or java.lang.Object.class). + //As per spec: If the message is a MapMessage then this parameter must be set to java.util.Map.class (or java.lang.Object.class). //then throw MessageFormatException. if (_messageObject != null && !paramClass.isAssignableFrom(Map.class)) { - throw getMessageFormatException(paramClass); + throw getMessageFormatException(paramClass); } - } catch (UnsupportedEncodingException uee) { + } catch (UnsupportedEncodingException uee) { throw getJMSException(paramClass, uee); - } - break; + } + break; - case JmsBodyType.BYTES_INT: - byte[] byteMsg = ((JsJmsBytesMessage) msg).getBytes(); - _messageObject = (byteMsg != null && byteMsg.length > 0) ? byteMsg : null; + case BYTES: + byte[] byteMsg = ((JsJmsBytesMessage) msg).getBytes(); + _messageObject = (byteMsg != null && byteMsg.length > 0) ? byteMsg : null; - if (_messageObject != null && !paramClass.isAssignableFrom(byte[].class)) { + if (_messageObject != null && !paramClass.isAssignableFrom(byte[].class)) { throw getMessageFormatException(paramClass); - } - break; - - case JmsBodyType.STREAM_INT: - throw getMessageFormatException(paramClass); - - case JmsBodyType.NULL_INT: - _messageObject = null; - break; + } + break; + case STREAM: + throw getMessageFormatException(paramClass); + default: + _messageObject = null; + break; } if (_messageObject != null) { if (paramClass.isAssignableFrom(_messageObject.getClass())) { @@ -2894,35 +2887,37 @@ public boolean isBodyAssignableTo(Class paramClass) throws JMSException, Message if (paramClass == null) return false; try { - // get the body type - int bodyType = msg.getBodyType().toInt(); - - if (bodyType == JmsBodyType.TEXT_INT) { + switch(msg.getBodyType()) { + case TEXT: decision = String.class.isAssignableFrom(paramClass); - } else if (bodyType == JmsBodyType.OBJECT_INT) { + break; + case OBJECT: decision = Serializable.class.isAssignableFrom(paramClass); // try if the object can be deserialized, if not then return false if (decision) { try { Object object = ((JsJmsObjectMessage) msg).getRealObject(); - decision = (paramClass.isAssignableFrom(object.getClass())); + decision = paramClass.isAssignableFrom(object.getClass()); } catch (IOException jmse) { return false; } catch (ClassNotFoundException e) { return false; } } - } else if (bodyType == JmsBodyType.MAP_INT) { + break; + case MAP: decision = Map.class.isAssignableFrom(paramClass); - } else if (bodyType == JmsBodyType.BYTES_INT) { + break; + case BYTES: decision = byte[].class.isAssignableFrom(paramClass); - } else if (bodyType == JmsBodyType.STREAM_INT) { - decision = false; - } else if (bodyType == JmsBodyType.NULL_INT) { // return false if message does not have a body + break; + case STREAM: + case NULL: + default: // return false if message does not have a body decision = false; + break; } - } finally { if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.exit(tc, "isBodyAssignableTo", new Object[] { decision }); From bc34dcae91fc3554b0c9733a7cacc8e44b07116c Mon Sep 17 00:00:00 2001 From: Luke Saker <29537386+sakerl@users.noreply.github.com> Date: Fri, 15 Nov 2024 11:12:11 +0000 Subject: [PATCH 32/67] Add description for persistent delayed message tests --- .../src/deliverydelay/web/DeliveryDelayServlet.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/dev/com.ibm.ws.messaging.open_jms20deliverydelay_fat/test-applications/DeliveryDelay/src/deliverydelay/web/DeliveryDelayServlet.java b/dev/com.ibm.ws.messaging.open_jms20deliverydelay_fat/test-applications/DeliveryDelay/src/deliverydelay/web/DeliveryDelayServlet.java index 0796d12b554..bdae0893e8e 100644 --- a/dev/com.ibm.ws.messaging.open_jms20deliverydelay_fat/test-applications/DeliveryDelay/src/deliverydelay/web/DeliveryDelayServlet.java +++ b/dev/com.ibm.ws.messaging.open_jms20deliverydelay_fat/test-applications/DeliveryDelay/src/deliverydelay/web/DeliveryDelayServlet.java @@ -1260,6 +1260,12 @@ public void testGetDeliveryDelayTopic_Tcp( } } + + // Tests for delayed message persistence over server restart. + // These tests are each in two parts; a sender part that sends 2 messages, and a receiver part that attempts to receive the messages. + // The methods are driven from the Test class, which calls the sender method, restarts the server, and then calls the receiver method. + + // new tests for simplified API public void testPersistentMessage( @@ -1464,6 +1470,11 @@ public void testPersistentMessageReceiveTopic_Tcp( } } + + + + + public void testTimeToLiveWithDeliveryDelay( HttpServletRequest request, HttpServletResponse response) throws Exception { From 47abcbc9e43dfda3ce2fa9958f226402cebcd1a3 Mon Sep 17 00:00:00 2001 From: Luke Saker <29537386+sakerl@users.noreply.github.com> Date: Fri, 15 Nov 2024 11:14:44 +0000 Subject: [PATCH 33/67] Remove unused variables from Simplified API tests --- .../src/deliverydelay/web/DeliveryDelayServlet.java | 8 -------- 1 file changed, 8 deletions(-) diff --git a/dev/com.ibm.ws.messaging.open_jms20deliverydelay_fat/test-applications/DeliveryDelay/src/deliverydelay/web/DeliveryDelayServlet.java b/dev/com.ibm.ws.messaging.open_jms20deliverydelay_fat/test-applications/DeliveryDelay/src/deliverydelay/web/DeliveryDelayServlet.java index bdae0893e8e..6086631cf74 100644 --- a/dev/com.ibm.ws.messaging.open_jms20deliverydelay_fat/test-applications/DeliveryDelay/src/deliverydelay/web/DeliveryDelayServlet.java +++ b/dev/com.ibm.ws.messaging.open_jms20deliverydelay_fat/test-applications/DeliveryDelay/src/deliverydelay/web/DeliveryDelayServlet.java @@ -1271,8 +1271,6 @@ public void testGetDeliveryDelayTopic_Tcp( public void testPersistentMessage( HttpServletRequest request, HttpServletResponse response) throws Exception { - boolean testFailed = false; - JMSContext jmsContext = jmsQCFBindings.createContext(); JMSConsumer jmsConsumer = jmsContext.createConsumer(jmsQueue); JMSProducer jmsProducer = jmsContext.createProducer(); @@ -1323,8 +1321,6 @@ public void testPersistentMessageReceive( public void testPersistentMessage_Tcp( HttpServletRequest request, HttpServletResponse response) throws Exception { - boolean testFailed = false; - JMSContext jmsContext = jmsQCFTCP.createContext(); JMSConsumer jmsConsumer = jmsContext.createConsumer(jmsQueue); JMSProducer jmsProducer = jmsContext.createProducer(); @@ -1373,8 +1369,6 @@ public void testPersistentMessageReceive_Tcp( public void testPersistentMessageTopic( HttpServletRequest request, HttpServletResponse response) throws Exception { - boolean testFailed = false; - JMSContext jmsContext = jmsTCFBindings.createContext(); JMSConsumer jmsConsumer1 = jmsContext.createDurableConsumer(jmsTopic, "durPersMsg1"); JMSConsumer jmsConsumer2 = jmsContext.createDurableConsumer(jmsTopic1, "durPersMsg2"); @@ -1423,8 +1417,6 @@ public void testPersistentMessageReceiveTopic( public void testPersistentMessageTopic_Tcp( HttpServletRequest request, HttpServletResponse response) throws Exception { - boolean testFailed = false; - JMSContext jmsContext = jmsTCFTCP.createContext(); JMSConsumer jmsConsumer1 = jmsContext.createDurableConsumer(jmsTopic, "durPersMsgTcp1"); JMSConsumer jmsConsumer2 = jmsContext.createDurableConsumer(jmsTopic1, "durPersMsgTcp2"); From 0740574f529d17a386728f6e024fc77d06383cca Mon Sep 17 00:00:00 2001 From: Luke Saker <29537386+sakerl@users.noreply.github.com> Date: Fri, 15 Nov 2024 11:33:56 +0000 Subject: [PATCH 34/67] Bring classic and simplified API tests together --- .../web/DeliveryDelayServlet.java | 514 +++++++++--------- 1 file changed, 257 insertions(+), 257 deletions(-) diff --git a/dev/com.ibm.ws.messaging.open_jms20deliverydelay_fat/test-applications/DeliveryDelay/src/deliverydelay/web/DeliveryDelayServlet.java b/dev/com.ibm.ws.messaging.open_jms20deliverydelay_fat/test-applications/DeliveryDelay/src/deliverydelay/web/DeliveryDelayServlet.java index 6086631cf74..cbd0f6fe6fd 100644 --- a/dev/com.ibm.ws.messaging.open_jms20deliverydelay_fat/test-applications/DeliveryDelay/src/deliverydelay/web/DeliveryDelayServlet.java +++ b/dev/com.ibm.ws.messaging.open_jms20deliverydelay_fat/test-applications/DeliveryDelay/src/deliverydelay/web/DeliveryDelayServlet.java @@ -1462,9 +1462,264 @@ public void testPersistentMessageReceiveTopic_Tcp( } } + + // Old tests for classic API - - + public void testPersistentMessageClassicApi( + HttpServletRequest request, HttpServletResponse response) throws Exception { + + QueueConnection con = jmsQCFBindings.createQueueConnection(); + con.start(); + + QueueSession sessionSender = con.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); + + QueueSender producer1 = sessionSender.createSender(jmsQueue); + emptyQueue(jmsQCFBindings, jmsQueue); + + QueueSender producer2 = sessionSender.createSender(jmsQueue1); + emptyQueue(jmsQCFBindings, jmsQueue1); + + producer1.setDeliveryMode(DeliveryMode.PERSISTENT); + producer1.setDeliveryDelay(1000); + TextMessage msg1 = sessionSender.createTextMessage("testPersistentMessage_PersistentMsgClassicApi"); + producer1.send(msg1); + + producer2.setDeliveryDelay(1000); + producer2.setDeliveryMode(DeliveryMode.NON_PERSISTENT); + TextMessage msg2 = sessionSender.createTextMessage("testPersistentMessage_NonPersistentMsgClassicApi"); + producer2.send(msg2); + + sessionSender.close(); + con.close(); + } + + public void testPersistentMessageReceiveClassicApi( + HttpServletRequest request, HttpServletResponse response) throws Exception { + + boolean testFailed = false; + + QueueConnection con = jmsQCFBindings.createQueueConnection(); + con.start(); + + QueueSession sessionSender = con.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); + + QueueReceiver jmsConsumer1 = sessionSender.createReceiver(jmsQueue); + QueueReceiver jmsConsumer2 = sessionSender.createReceiver(jmsQueue); + + QueueSender producer = sessionSender.createSender(jmsQueue1); + + TextMessage msg1 = (TextMessage) jmsConsumer1.receive(30000); + TextMessage msg2 = (TextMessage) jmsConsumer2.receive(30000); + + if ( ((msg1 == null) || + (msg1.getText() == null) || + !msg1.getText().equals("testPersistentMessage_PersistentMsgClassicApi")) || + (msg2 != null) ) { + testFailed = true; + } + + sessionSender.close(); + con.close(); + + if ( testFailed ) { + throw new Exception("testPersistentMessageReceiveClassicApi failed"); + } + } + + public void testPersistentMessageClassicApi_Tcp( + HttpServletRequest request, HttpServletResponse response) throws Exception { + + QueueConnection con = jmsQCFTCP.createQueueConnection(); + con.start(); + + QueueSession sessionSender = con.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); + + QueueSender producer1 = sessionSender.createSender(jmsQueue); + emptyQueue(jmsQCFBindings, jmsQueue); + + QueueSender producer2 = sessionSender.createSender(jmsQueue1); + emptyQueue(jmsQCFBindings, jmsQueue1); + + producer1.setDeliveryMode(DeliveryMode.PERSISTENT); + producer1.setDeliveryDelay(1000); + TextMessage msg1 = sessionSender.createTextMessage("testPersistentMessage_PersistentMsgClassicApi"); + producer1.send(msg1); + + producer2.setDeliveryDelay(1000); + producer2.setDeliveryMode(DeliveryMode.NON_PERSISTENT); + TextMessage msg2 = sessionSender.createTextMessage("testPersistentMessage_NonPersistentMsgClassicApi"); + producer2.send(msg2); + + sessionSender.close(); + con.close(); + } + + public void testPersistentMessageReceiveClassicApi_Tcp( + HttpServletRequest request, HttpServletResponse response) throws Exception { + + boolean testFailed = false; + + QueueConnection con = jmsQCFTCP.createQueueConnection(); + con.start(); + + QueueSession sessionSender = con.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); + + MessageConsumer jmsConsumer1 = sessionSender.createConsumer(jmsQueue); + MessageConsumer jmsConsumer2 = sessionSender.createConsumer(jmsQueue); + + QueueSender producer = sessionSender.createSender(jmsQueue1); + + TextMessage msg1 = (TextMessage) jmsConsumer1.receive(30000); + TextMessage msg2 = (TextMessage) jmsConsumer2.receive(30000); + + if ( ((msg1 == null) || + (msg1.getText() == null) || + !msg1.getText().equals("testPersistentMessage_PersistentMsgClassicApi")) || + (msg2 != null) ) { + testFailed = true; + } + + sessionSender.close(); + con.close(); + + if ( testFailed ) { + throw new Exception("testPersistentMessageReceiveClassicApi failed"); + } + } + + public void testPersistentMessageTopicClassicApi( + HttpServletRequest request, HttpServletResponse response) throws Exception { + + TopicConnection con = jmsTCFBindings.createTopicConnection(); + con.start(); + + TopicSession sessionSender = con.createTopicSession(false, Session.AUTO_ACKNOWLEDGE); + + TopicSubscriber jmsConsumer1 = sessionSender.createDurableSubscriber(jmsTopic, "durPersMsgCA1"); + TopicSubscriber jmsConsumer2 = sessionSender.createDurableSubscriber(jmsTopic1, "durPersMsgCA2"); + + TopicPublisher jmsProducer1 = sessionSender.createPublisher(jmsTopic); + TopicPublisher jmsProducer2 = sessionSender.createPublisher(jmsTopic1); + + jmsProducer1.setDeliveryMode(DeliveryMode.PERSISTENT); + jmsProducer1.setDeliveryDelay(1000); + TextMessage msg1 = sessionSender.createTextMessage("testPersistentMessage_PersistentMsgTopicClassicApi"); + jmsProducer1.send(msg1); + + jmsProducer2.setDeliveryDelay(1000); + jmsProducer2.setDeliveryMode(DeliveryMode.NON_PERSISTENT); + TextMessage msg2 = sessionSender.createTextMessage("testPersistentMessage_NonPersistentMsgTopicClassicApi"); + jmsProducer2.send(msg2); + + con.close(); + } + + public void testPersistentMessageReceiveTopicClassicApi( + HttpServletRequest request, HttpServletResponse response) throws Exception { + + boolean testFailed = false; + + TopicConnection con = jmsTCFBindings.createTopicConnection(); + con.start(); + + TopicSession sessionSender = con.createTopicSession(false, Session.AUTO_ACKNOWLEDGE); + + TopicSubscriber jmsConsumer1 = sessionSender.createDurableSubscriber(jmsTopic, "durPersMsgCA1"); + TopicSubscriber jmsConsumer2 = sessionSender.createDurableSubscriber(jmsTopic1, "durPersMsgCA2"); + + TopicPublisher jmsProducer = sessionSender.createPublisher(jmsTopic); + + TextMessage msg1 = (TextMessage) jmsConsumer1.receive(30000); + TextMessage msg2 = (TextMessage) jmsConsumer2.receive(30000); + + if ( ((msg1 == null) || + (msg1.getText() == null) || + !msg1.getText().equals("testPersistentMessage_PersistentMsgTopicClassicApi")) || + (msg2 != null) ) { + testFailed = true; + } + + jmsConsumer1.close(); + jmsConsumer2.close(); + + sessionSender.unsubscribe("durPersMsgCA1"); + sessionSender.unsubscribe("durPersMsgCA2"); + sessionSender.close(); + + con.close(); + + if ( testFailed ) { + throw new Exception("testPersistentMessageReceiveTopicClassicApi failed"); + } + } + + public void testPersistentMessageTopicClassicApi_Tcp( + HttpServletRequest request, HttpServletResponse response) throws Exception { + + boolean testFailed = false; + + TopicConnection con = jmsTCFTCP.createTopicConnection(); + con.start(); + + TopicSession sessionSender = con.createTopicSession(false, Session.AUTO_ACKNOWLEDGE); + + TopicSubscriber jmsConsumer1 = sessionSender.createDurableSubscriber(jmsTopic, "durPersMsgCATcp1"); + TopicSubscriber jmsConsumer2 = sessionSender.createDurableSubscriber(jmsTopic1, "durPersMsgCATcp2"); + + TopicPublisher jmsProducer1 = sessionSender.createPublisher(jmsTopic); + TopicPublisher jmsProducer2 = sessionSender.createPublisher(jmsTopic1); + + jmsProducer1.setDeliveryMode(DeliveryMode.PERSISTENT); + jmsProducer1.setDeliveryDelay(1000); + TextMessage msg1 = sessionSender.createTextMessage("testPersistentMessage_PersistentMsgTopicClassicApiTcp"); + jmsProducer1.send(msg1); + + jmsProducer2.setDeliveryDelay(1000); + jmsProducer2.setDeliveryMode(DeliveryMode.NON_PERSISTENT); + TextMessage msg2 = sessionSender.createTextMessage("testPersistentMessage_NonPersistentMsgTopicClassicApiTcp"); + jmsProducer2.send(msg2); + + con.close(); + } + + public void testPersistentMessageReceiveTopicClassicApi_Tcp( + HttpServletRequest request, HttpServletResponse response) throws Exception { + + boolean testFailed = false; + + TopicConnection con = jmsTCFTCP.createTopicConnection(); + con.start(); + + TopicSession sessionSender = con.createTopicSession(false, Session.AUTO_ACKNOWLEDGE); + + TopicSubscriber jmsConsumer1 = sessionSender.createDurableSubscriber(jmsTopic, "durPersMsgCATcp1"); + TopicSubscriber jmsConsumer2 = sessionSender.createDurableSubscriber(jmsTopic1, "durPersMsgCATcp2"); + + TopicPublisher jmsProducer = sessionSender.createPublisher(jmsTopic); + + TextMessage msg1 = (TextMessage) jmsConsumer1.receive(30000); + TextMessage msg2 = (TextMessage) jmsConsumer2.receive(30000); + + if ( ((msg1 == null) || + (msg1.getText() == null) || + !msg1.getText().equals("testPersistentMessage_PersistentMsgTopicClassicApiTcp")) || + (msg2 != null) ) { + testFailed = true; + } + + jmsConsumer1.close(); + jmsConsumer2.close(); + + sessionSender.unsubscribe("durPersMsgCATcp1"); + sessionSender.unsubscribe("durPersMsgCATcp2"); + sessionSender.close(); + + con.close(); + + if ( testFailed ) { + throw new Exception("testPersistentMessageStoreReceiveTopicClassicApi_Tcp failed"); + } + } public void testTimeToLiveWithDeliveryDelay( @@ -3700,261 +3955,6 @@ public void testGetDeliveryDelayClassicApiTopic_Tcp( } } - public void testPersistentMessageClassicApi( - HttpServletRequest request, HttpServletResponse response) throws Exception { - - QueueConnection con = jmsQCFBindings.createQueueConnection(); - con.start(); - - QueueSession sessionSender = con.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); - - QueueSender producer1 = sessionSender.createSender(jmsQueue); - emptyQueue(jmsQCFBindings, jmsQueue); - - QueueSender producer2 = sessionSender.createSender(jmsQueue1); - emptyQueue(jmsQCFBindings, jmsQueue1); - - producer1.setDeliveryMode(DeliveryMode.PERSISTENT); - producer1.setDeliveryDelay(1000); - TextMessage msg1 = sessionSender.createTextMessage("testPersistentMessage_PersistentMsgClassicApi"); - producer1.send(msg1); - - producer2.setDeliveryDelay(1000); - producer2.setDeliveryMode(DeliveryMode.NON_PERSISTENT); - TextMessage msg2 = sessionSender.createTextMessage("testPersistentMessage_NonPersistentMsgClassicApi"); - producer2.send(msg2); - - sessionSender.close(); - con.close(); - } - - public void testPersistentMessageReceiveClassicApi( - HttpServletRequest request, HttpServletResponse response) throws Exception { - - boolean testFailed = false; - - QueueConnection con = jmsQCFBindings.createQueueConnection(); - con.start(); - - QueueSession sessionSender = con.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); - - QueueReceiver jmsConsumer1 = sessionSender.createReceiver(jmsQueue); - QueueReceiver jmsConsumer2 = sessionSender.createReceiver(jmsQueue); - - QueueSender producer = sessionSender.createSender(jmsQueue1); - - TextMessage msg1 = (TextMessage) jmsConsumer1.receive(30000); - TextMessage msg2 = (TextMessage) jmsConsumer2.receive(30000); - - if ( ((msg1 == null) || - (msg1.getText() == null) || - !msg1.getText().equals("testPersistentMessage_PersistentMsgClassicApi")) || - (msg2 != null) ) { - testFailed = true; - } - - sessionSender.close(); - con.close(); - - if ( testFailed ) { - throw new Exception("testPersistentMessageReceiveClassicApi failed"); - } - } - - public void testPersistentMessageClassicApi_Tcp( - HttpServletRequest request, HttpServletResponse response) throws Exception { - - QueueConnection con = jmsQCFTCP.createQueueConnection(); - con.start(); - - QueueSession sessionSender = con.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); - - QueueSender producer1 = sessionSender.createSender(jmsQueue); - emptyQueue(jmsQCFBindings, jmsQueue); - - QueueSender producer2 = sessionSender.createSender(jmsQueue1); - emptyQueue(jmsQCFBindings, jmsQueue1); - - producer1.setDeliveryMode(DeliveryMode.PERSISTENT); - producer1.setDeliveryDelay(1000); - TextMessage msg1 = sessionSender.createTextMessage("testPersistentMessage_PersistentMsgClassicApi"); - producer1.send(msg1); - - producer2.setDeliveryDelay(1000); - producer2.setDeliveryMode(DeliveryMode.NON_PERSISTENT); - TextMessage msg2 = sessionSender.createTextMessage("testPersistentMessage_NonPersistentMsgClassicApi"); - producer2.send(msg2); - - sessionSender.close(); - con.close(); - } - - public void testPersistentMessageReceiveClassicApi_Tcp( - HttpServletRequest request, HttpServletResponse response) throws Exception { - - boolean testFailed = false; - - QueueConnection con = jmsQCFTCP.createQueueConnection(); - con.start(); - - QueueSession sessionSender = con.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); - - MessageConsumer jmsConsumer1 = sessionSender.createConsumer(jmsQueue); - MessageConsumer jmsConsumer2 = sessionSender.createConsumer(jmsQueue); - - QueueSender producer = sessionSender.createSender(jmsQueue1); - - TextMessage msg1 = (TextMessage) jmsConsumer1.receive(30000); - TextMessage msg2 = (TextMessage) jmsConsumer2.receive(30000); - - if ( ((msg1 == null) || - (msg1.getText() == null) || - !msg1.getText().equals("testPersistentMessage_PersistentMsgClassicApi")) || - (msg2 != null) ) { - testFailed = true; - } - - sessionSender.close(); - con.close(); - - if ( testFailed ) { - throw new Exception("testPersistentMessageReceiveClassicApi failed"); - } - } - - public void testPersistentMessageTopicClassicApi( - HttpServletRequest request, HttpServletResponse response) throws Exception { - - TopicConnection con = jmsTCFBindings.createTopicConnection(); - con.start(); - - TopicSession sessionSender = con.createTopicSession(false, Session.AUTO_ACKNOWLEDGE); - - TopicSubscriber jmsConsumer1 = sessionSender.createDurableSubscriber(jmsTopic, "durPersMsgCA1"); - TopicSubscriber jmsConsumer2 = sessionSender.createDurableSubscriber(jmsTopic1, "durPersMsgCA2"); - - TopicPublisher jmsProducer1 = sessionSender.createPublisher(jmsTopic); - TopicPublisher jmsProducer2 = sessionSender.createPublisher(jmsTopic1); - - jmsProducer1.setDeliveryMode(DeliveryMode.PERSISTENT); - jmsProducer1.setDeliveryDelay(1000); - TextMessage msg1 = sessionSender.createTextMessage("testPersistentMessage_PersistentMsgTopicClassicApi"); - jmsProducer1.send(msg1); - - jmsProducer2.setDeliveryDelay(1000); - jmsProducer2.setDeliveryMode(DeliveryMode.NON_PERSISTENT); - TextMessage msg2 = sessionSender.createTextMessage("testPersistentMessage_NonPersistentMsgTopicClassicApi"); - jmsProducer2.send(msg2); - - con.close(); - } - - public void testPersistentMessageReceiveTopicClassicApi( - HttpServletRequest request, HttpServletResponse response) throws Exception { - - boolean testFailed = false; - - TopicConnection con = jmsTCFBindings.createTopicConnection(); - con.start(); - - TopicSession sessionSender = con.createTopicSession(false, Session.AUTO_ACKNOWLEDGE); - - TopicSubscriber jmsConsumer1 = sessionSender.createDurableSubscriber(jmsTopic, "durPersMsgCA1"); - TopicSubscriber jmsConsumer2 = sessionSender.createDurableSubscriber(jmsTopic1, "durPersMsgCA2"); - - TopicPublisher jmsProducer = sessionSender.createPublisher(jmsTopic); - - TextMessage msg1 = (TextMessage) jmsConsumer1.receive(30000); - TextMessage msg2 = (TextMessage) jmsConsumer2.receive(30000); - - if ( ((msg1 == null) || - (msg1.getText() == null) || - !msg1.getText().equals("testPersistentMessage_PersistentMsgTopicClassicApi")) || - (msg2 != null) ) { - testFailed = true; - } - - jmsConsumer1.close(); - jmsConsumer2.close(); - - sessionSender.unsubscribe("durPersMsgCA1"); - sessionSender.unsubscribe("durPersMsgCA2"); - sessionSender.close(); - - con.close(); - - if ( testFailed ) { - throw new Exception("testPersistentMessageReceiveTopicClassicApi failed"); - } - } - - public void testPersistentMessageTopicClassicApi_Tcp( - HttpServletRequest request, HttpServletResponse response) throws Exception { - - boolean testFailed = false; - - TopicConnection con = jmsTCFTCP.createTopicConnection(); - con.start(); - - TopicSession sessionSender = con.createTopicSession(false, Session.AUTO_ACKNOWLEDGE); - - TopicSubscriber jmsConsumer1 = sessionSender.createDurableSubscriber(jmsTopic, "durPersMsgCATcp1"); - TopicSubscriber jmsConsumer2 = sessionSender.createDurableSubscriber(jmsTopic1, "durPersMsgCATcp2"); - - TopicPublisher jmsProducer1 = sessionSender.createPublisher(jmsTopic); - TopicPublisher jmsProducer2 = sessionSender.createPublisher(jmsTopic1); - - jmsProducer1.setDeliveryMode(DeliveryMode.PERSISTENT); - jmsProducer1.setDeliveryDelay(1000); - TextMessage msg1 = sessionSender.createTextMessage("testPersistentMessage_PersistentMsgTopicClassicApiTcp"); - jmsProducer1.send(msg1); - - jmsProducer2.setDeliveryDelay(1000); - jmsProducer2.setDeliveryMode(DeliveryMode.NON_PERSISTENT); - TextMessage msg2 = sessionSender.createTextMessage("testPersistentMessage_NonPersistentMsgTopicClassicApiTcp"); - jmsProducer2.send(msg2); - - con.close(); - } - - public void testPersistentMessageReceiveTopicClassicApi_Tcp( - HttpServletRequest request, HttpServletResponse response) throws Exception { - - boolean testFailed = false; - - TopicConnection con = jmsTCFTCP.createTopicConnection(); - con.start(); - - TopicSession sessionSender = con.createTopicSession(false, Session.AUTO_ACKNOWLEDGE); - - TopicSubscriber jmsConsumer1 = sessionSender.createDurableSubscriber(jmsTopic, "durPersMsgCATcp1"); - TopicSubscriber jmsConsumer2 = sessionSender.createDurableSubscriber(jmsTopic1, "durPersMsgCATcp2"); - - TopicPublisher jmsProducer = sessionSender.createPublisher(jmsTopic); - - TextMessage msg1 = (TextMessage) jmsConsumer1.receive(30000); - TextMessage msg2 = (TextMessage) jmsConsumer2.receive(30000); - - if ( ((msg1 == null) || - (msg1.getText() == null) || - !msg1.getText().equals("testPersistentMessage_PersistentMsgTopicClassicApiTcp")) || - (msg2 != null) ) { - testFailed = true; - } - - jmsConsumer1.close(); - jmsConsumer2.close(); - - sessionSender.unsubscribe("durPersMsgCATcp1"); - sessionSender.unsubscribe("durPersMsgCATcp2"); - sessionSender.close(); - - con.close(); - - if ( testFailed ) { - throw new Exception("testPersistentMessageStoreReceiveTopicClassicApi_Tcp failed"); - } - } public void testJSAD_Send_Message_P2PTest( HttpServletRequest request, HttpServletResponse response) throws Exception { From 31602124d37375224830685e511af8a6beaf87a9 Mon Sep 17 00:00:00 2001 From: Luke Saker <29537386+sakerl@users.noreply.github.com> Date: Tue, 19 Nov 2024 11:54:25 +0000 Subject: [PATCH 35/67] Add new simplied API persistent message send method --- .../web/DeliveryDelayServlet.java | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/dev/com.ibm.ws.messaging.open_jms20deliverydelay_fat/test-applications/DeliveryDelay/src/deliverydelay/web/DeliveryDelayServlet.java b/dev/com.ibm.ws.messaging.open_jms20deliverydelay_fat/test-applications/DeliveryDelay/src/deliverydelay/web/DeliveryDelayServlet.java index cbd0f6fe6fd..abb8775aa9b 100644 --- a/dev/com.ibm.ws.messaging.open_jms20deliverydelay_fat/test-applications/DeliveryDelay/src/deliverydelay/web/DeliveryDelayServlet.java +++ b/dev/com.ibm.ws.messaging.open_jms20deliverydelay_fat/test-applications/DeliveryDelay/src/deliverydelay/web/DeliveryDelayServlet.java @@ -1267,6 +1267,51 @@ public void testGetDeliveryDelayTopic_Tcp( // new tests for simplified API + + // New consolidated simplified API persistent test sender method + private void testPersistentMessageSimplifiedAPI_send(ConnectionFactory cf, + Destination persistentMessageDestination, + Destination nonpersistentMessageDestination, + String identifier) + throws Exception { + + boolean pubSub = persistentMessageDestination instanceof Topic; + JMSConsumer jmsConsumer1 = null, jmsConsumer2 = null; + + try (JMSContext jmsContext = cf.createContext()) { + + JMSProducer jmsProducer = jmsContext.createProducer(); + + // If we are sending messages to Topic destinations then there needs to be subscriptions to receive the messages + if (pubSub) { + jmsConsumer1 = jmsContext.createDurableConsumer((Topic) persistentMessageDestination, "durPersMsg1_" + identifier); + jmsConsumer2 = jmsContext.createDurableConsumer((Topic) nonpersistentMessageDestination, "durPersMsg2_" + identifier); + } + else { + // empty the message queue before sending the new messages. + // This is replicating previous behaviour, but will probably need to be removed if we re-work the tests to run concurrently. + emptyQueue(cf, (Queue)persistentMessageDestination); + emptyQueue(cf, (Queue)nonpersistentMessageDestination); + } + + // Send the messages + jmsProducer.setDeliveryDelay(defaultTestDeliveryDelay).setDeliveryMode(DeliveryMode.PERSISTENT) + .send(persistentMessageDestination, "PersistentMessage_" + identifier); + + jmsProducer.setDeliveryDelay(defaultTestDeliveryDelay).setDeliveryMode(DeliveryMode.NON_PERSISTENT) + .send(nonpersistentMessageDestination, "NonPersistentMessage_" + identifier); + + // If we're running in the pub/sub domain then close the subscribers (the subscriptions will remain open + if (pubSub) { + jmsConsumer1.close(); + jmsConsumer2.close(); + } + + } + + return; + } + public void testPersistentMessage( HttpServletRequest request, HttpServletResponse response) throws Exception { From 6b0a669e6624bcc43226d70e07d3cad6d670549e Mon Sep 17 00:00:00 2001 From: Paul Nicolucci Date: Tue, 12 Nov 2024 14:53:12 -0500 Subject: [PATCH 36/67] Don't skip Pages 4.0 test for Jakarta EE11 --- .../src/com/ibm/ws/jsp23/fat/tests/JSP23JSP22ServerTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/com.ibm.ws.jsp.2.3_fat/fat/src/com/ibm/ws/jsp23/fat/tests/JSP23JSP22ServerTest.java b/dev/com.ibm.ws.jsp.2.3_fat/fat/src/com/ibm/ws/jsp23/fat/tests/JSP23JSP22ServerTest.java index e3f7af144cb..8bbbb7bb80e 100644 --- a/dev/com.ibm.ws.jsp.2.3_fat/fat/src/com/ibm/ws/jsp23/fat/tests/JSP23JSP22ServerTest.java +++ b/dev/com.ibm.ws.jsp.2.3_fat/fat/src/com/ibm/ws/jsp23/fat/tests/JSP23JSP22ServerTest.java @@ -215,7 +215,7 @@ public void testJsp31to23FeatureChange() throws Exception { * @throws Exception */ @Test - @SkipForRepeat({ SkipForRepeat.NO_MODIFICATION, SkipForRepeat.EE9_OR_LATER_FEATURES }) + @SkipForRepeat({ SkipForRepeat.NO_MODIFICATION, SkipForRepeat.EE9_FEATURES, SkipForRepeat.EE10_FEATURES }) public void testJsp40to31FeatureChange() throws Exception { WebConversation wc = new WebConversation(); wc.setExceptionsThrownOnErrorStatus(false); From 0ecbe7b8f6bda815476be3c9250ebdd29b885576 Mon Sep 17 00:00:00 2001 From: Paul Nicolucci Date: Tue, 12 Nov 2024 14:53:49 -0500 Subject: [PATCH 37/67] Format and rename tests --- .../com/ibm/ws/jsp23/fat/tests/JSP23JSP22ServerTest.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/dev/com.ibm.ws.jsp.2.3_fat/fat/src/com/ibm/ws/jsp23/fat/tests/JSP23JSP22ServerTest.java b/dev/com.ibm.ws.jsp.2.3_fat/fat/src/com/ibm/ws/jsp23/fat/tests/JSP23JSP22ServerTest.java index 8bbbb7bb80e..8b6f4a282d4 100644 --- a/dev/com.ibm.ws.jsp.2.3_fat/fat/src/com/ibm/ws/jsp23/fat/tests/JSP23JSP22ServerTest.java +++ b/dev/com.ibm.ws.jsp.2.3_fat/fat/src/com/ibm/ws/jsp23/fat/tests/JSP23JSP22ServerTest.java @@ -88,10 +88,9 @@ public static void testCleanup() throws Exception { * * @throws Exception */ - @Test @SkipForRepeat({ SkipForRepeat.EE9_OR_LATER_FEATURES }) - public void testJsp23to22FeatureChange() throws Exception { + public void testJsp23toJsp22FeatureChange() throws Exception { WebConversation wc = new WebConversation(); wc.setExceptionsThrownOnErrorStatus(false); @@ -132,7 +131,7 @@ public void testJsp23to22FeatureChange() throws Exception { */ @Test @SkipForRepeat({ SkipForRepeat.NO_MODIFICATION, SkipForRepeat.EE10_OR_LATER_FEATURES }) - public void testJsp30to23FeatureChange() throws Exception { + public void testPages30toJsp23FeatureChange() throws Exception { WebConversation wc = new WebConversation(); wc.setExceptionsThrownOnErrorStatus(false); @@ -174,7 +173,7 @@ public void testJsp30to23FeatureChange() throws Exception { */ @Test @SkipForRepeat({ SkipForRepeat.NO_MODIFICATION, SkipForRepeat.EE9_FEATURES, SkipForRepeat.EE11_OR_LATER_FEATURES }) - public void testJsp31to23FeatureChange() throws Exception { + public void testPages31toJsp23FeatureChange() throws Exception { WebConversation wc = new WebConversation(); wc.setExceptionsThrownOnErrorStatus(false); @@ -216,7 +215,7 @@ public void testJsp31to23FeatureChange() throws Exception { */ @Test @SkipForRepeat({ SkipForRepeat.NO_MODIFICATION, SkipForRepeat.EE9_FEATURES, SkipForRepeat.EE10_FEATURES }) - public void testJsp40to31FeatureChange() throws Exception { + public void testPages40toJsp31FeatureChange() throws Exception { WebConversation wc = new WebConversation(); wc.setExceptionsThrownOnErrorStatus(false); From 52e14352dbc0e5e73d4b4196c15d76b1fa0a68ba Mon Sep 17 00:00:00 2001 From: Smitha Subbarao Date: Mon, 28 Oct 2024 18:47:49 -0500 Subject: [PATCH 38/67] Create new DynamicConfigRule for batch JDBC test --- .../junit/DynamicConfigRuleCheckpoint.java | 213 ++++++++++++++++++ .../fat/junit/JdbcConfigTestCheckpoint.java | 93 +++----- 2 files changed, 245 insertions(+), 61 deletions(-) create mode 100644 dev/com.ibm.ws.jbatch.open_fat/fat/src/batch/fat/junit/DynamicConfigRuleCheckpoint.java diff --git a/dev/com.ibm.ws.jbatch.open_fat/fat/src/batch/fat/junit/DynamicConfigRuleCheckpoint.java b/dev/com.ibm.ws.jbatch.open_fat/fat/src/batch/fat/junit/DynamicConfigRuleCheckpoint.java new file mode 100644 index 00000000000..d5c2b7c1ca8 --- /dev/null +++ b/dev/com.ibm.ws.jbatch.open_fat/fat/src/batch/fat/junit/DynamicConfigRuleCheckpoint.java @@ -0,0 +1,213 @@ +/******************************************************************************* + * Copyright (c) 2014, 2020 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package batch.fat.junit; + +import static org.junit.Assert.assertNotNull; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Callable; + +import org.junit.rules.TestRule; +import org.junit.runner.Description; +import org.junit.runner.RunWith; +import org.junit.runners.model.Statement; + +import com.ibm.websphere.simplicity.log.Log; +import batch.fat.util.BatchFATHelper; +import componenttest.annotation.CheckpointTest; +import com.ibm.websphere.simplicity.log.Log; +import com.ibm.ws.jbatch.test.FatUtils; + +import componenttest.custom.junit.runner.FATRunner; +import componenttest.topology.impl.LibertyServer; + +/** + * The DynamicConfigRuleCheckpoint takes a list of server.xml file names and runs the + * test(s) multiple times, once for each server.xml file. The server.xml updates + * are applied dynamically (i.e the server is not restarted). + * + */ +@RunWith(FATRunner.class) +public class DynamicConfigRuleCheckpoint implements TestRule { + + public static void log(String method, String msg) { + Log.info(DynamicConfigRuleCheckpoint.class, method, msg); + } + + /** + * A function that does setup of a {@code LibertyServer}. + * + * @param + */ + @FunctionalInterface + public static interface ServerSetup { + /** + * Setup the server + * @return the checkpointed server + * @throws T + */ + public LibertyServer call() throws T; + } + + /** + * A function that does some action. + * + * @param + */ + @FunctionalInterface + public static interface Action { + /** + * Perform some action + */ + public void call() throws T; + } + + private ServerSetup initialSetup; + + private Action finalTearDown; + + private Action beforeEach; + + private LibertyServer server; + + /** + * The list of server.xml config files to run the tests against. + */ + private final List serverXmlFileNames = new ArrayList(); + + /** + * Sets the mandatory function that does server setup for the normal and checkpoint mode for the test + * + * @param + * @param serverSetup + * @return + */ + public DynamicConfigRuleCheckpoint setInitialSetup(ServerSetup initialSetup) { + this.initialSetup = initialSetup; + return this; + } + + /** + * @param finalTearDown Executed after iterating thru ALL server xmls. + * + * @return this + */ + public DynamicConfigRuleCheckpoint setFinalTearDown(Action finalTearDown) { + this.finalTearDown = finalTearDown; + return this; + } + + /** + * @param beforeEach Executed before each iteration of the server.xmls + * + * @return this + */ + public DynamicConfigRuleCheckpoint setBeforeEach(Action beforeEach) { + this.beforeEach = beforeEach; + return this; + } + + /** + * @param serverXmlFileName Add a server.xml file to the list + * + * @return this + */ + public DynamicConfigRuleCheckpoint addServerXml(String serverXmlFileName) { + this.serverXmlFileNames.add(serverXmlFileName); + return this; + } + + /** + * {@inheritDoc} + */ + @Override + public Statement apply(Statement base, Description desc) { + return new DynamicConfigStatement(base); + } + + /** + * Statement class - performs the before/after operations around a + * call to the base Statement's evaulate() method (which runs the test). + */ + protected class DynamicConfigStatement extends Statement { + + /** + * A reference to the Statement that this Statement wraps around. + */ + private final Statement base; + + /** + * CTOR. + * + * @param base The Statement that this Statement wraps around. + */ + public DynamicConfigStatement(Statement base) { + this.base = base; + } + + /** + * This method is called by the test runner in order to execute the test. + * + * Before/After logic is embedded here around a call to base.evaluate(), + * which processes the Statement chain (for any other @Rules that have been + * applied) until at last the test method is executed. + * + */ + @Override + public void evaluate() throws Throwable { + assertNotNull("initialSetup must not be null.", initialSetup); + assertNotNull("beforeEach must not be null.", beforeEach); + assertNotNull("finalTearDown must not be null.", finalTearDown); + log("evaluate", "running initial setup"); + + server = initialSetup.call(); + + try { + iterateServerXmls(); + + } finally { + finalTearDown.call(); + } + } + + /** + * Iterate thru all server.xml and run the suite of tests against each. + */ + protected void iterateServerXmls() throws Throwable { + + server.setMarkToEndOfLog(); + for (String serverXmlFileName : serverXmlFileNames) { + + log("evaluate", "setting server.xml to " + serverXmlFileName); + + server.setServerConfigurationFile(serverXmlFileName); + server.checkpointRestore(); + + beforeEach.call(); + + try { + base.evaluate(); + } finally { + // TODO: if a test fails will I be able to run the other configs + // and still report the test failure? + } + + server.stopServer(); + } + } + + } + +} + diff --git a/dev/com.ibm.ws.jbatch.open_fat/fat/src/batch/fat/junit/JdbcConfigTestCheckpoint.java b/dev/com.ibm.ws.jbatch.open_fat/fat/src/batch/fat/junit/JdbcConfigTestCheckpoint.java index 5028a5afd9c..71fb8209605 100644 --- a/dev/com.ibm.ws.jbatch.open_fat/fat/src/batch/fat/junit/JdbcConfigTestCheckpoint.java +++ b/dev/com.ibm.ws.jbatch.open_fat/fat/src/batch/fat/junit/JdbcConfigTestCheckpoint.java @@ -8,14 +8,13 @@ import org.junit.runner.RunWith; import com.ibm.websphere.simplicity.log.Log; - -import batch.fat.util.BatchFATHelper; -import componenttest.annotation.CheckpointTest; - import com.ibm.ws.jbatch.test.BatchAppUtils; import com.ibm.ws.jbatch.test.FatUtils; +import batch.fat.util.BatchFATHelper; +import componenttest.annotation.CheckpointTest; import componenttest.custom.junit.runner.FATRunner; +import componenttest.topology.impl.LibertyServer; import componenttest.topology.impl.LibertyServerFactory; import io.openliberty.checkpoint.spi.CheckpointPhase; @@ -28,39 +27,6 @@ @CheckpointTest public class JdbcConfigTestCheckpoint extends BatchFATHelper { - /** - * Used with DynamicConfigRule. - */ - public static Callable initialSetup = new Callable() { - @Override - public Void call() throws Exception { - setup(); - return null; - } - }; - - /** - * Used with DynamicConfigRule. - */ - public static Callable finalTearDown = new Callable() { - @Override - public Void call() throws Exception { - tearDown(); - return null; - } - }; - - /** - * Used with DynamicConfigRule. Called after each iteration. - */ - public static Callable afterEach = new Callable() { - @Override - public Void call() throws Exception { - afterEach(); - return null; - } - }; - /** * This ClassRule will run all the tests in this class multiple times, against * all the given server.xml configuration files. @@ -69,12 +35,18 @@ public Void call() throws Exception { * tests (against all configurations) have run. */ @ClassRule - public static DynamicConfigRule dynamicConfigRule = new DynamicConfigRule().setServer(server).setInitialSetup(initialSetup).setFinalTearDown(finalTearDown).setAfterEach(afterEach).addServerXml("JDBCPersistenceCheckpoint/jdbc.config.myschema1.server.xml").addServerXml("JDBCPersistenceCheckpoint/jdbc.config.myschema2.server.xml").addServerXml("JDBCPersistenceCheckpoint/jdbc.config.myschema1.tp1.server.xml").addServerXml("JDBCPersistenceCheckpoint/jdbc.config.myschema1.tp2.server.xml"); - + public static DynamicConfigRuleCheckpoint dynamicConfigRuleCheckpoint = new DynamicConfigRuleCheckpoint() // + .setInitialSetup(JdbcConfigTestCheckpoint::setup) // + .setBeforeEach(JdbcConfigTestCheckpoint::beforeEach) // + .setFinalTearDown(JdbcConfigTestCheckpoint::tearDown) // + .addServerXml("JDBCPersistenceCheckpoint/jdbc.config.myschema1.server.xml") // + .addServerXml("JDBCPersistenceCheckpoint/jdbc.config.myschema2.server.xml") // + .addServerXml("JDBCPersistenceCheckpoint/jdbc.config.myschema1.tp1.server.xml") // + .addServerXml("JDBCPersistenceCheckpoint/jdbc.config.myschema1.tp2.server.xml"); /** * Start the server and setup the DB. */ - public static void setup() throws Exception { + public static LibertyServer setup() throws Exception { log("setup", "start server and execute DDLs"); @@ -88,23 +60,9 @@ public static void setup() throws Exception { // Start server server.setServerConfigurationFile("JDBCPersistenceCheckpoint/jdbc.config.myschema1.server.xml"); - server.setCheckpoint(CheckpointPhase.AFTER_APP_START, true, null); - server.startServer("JdbcConfig.log"); - - // Apply config and restore - server.waitForStringInLog("CWWKF0011I", 20000); - FatUtils.waitForSmarterPlanet(server); - - // Setup chunk test data - executeSql("jdbc/batch", getChunkInTableSql()); - executeSql("jdbc/batch", getChunkOutTableSql("APP.OUT4")); - - executeSql("jdbc/myds", getChunkInTableSql()); - executeSql("jdbc/myds", getChunkOutTableSql("APP.OUT1")); - executeSql("jdbc/myds", getChunkOutTableSql("APP.OUT2")); - - executeSql("jdbc/mydsNonTran", getChunkInTableSql()); - executeSql("jdbc/mydsNonTran", getChunkOutTableSql("APP.OUT3")); + server.setCheckpoint(CheckpointPhase.AFTER_APP_START, false, null); + server.startServer("JdbcConfigTestCheckpoint.log"); + return server; } /** @@ -118,11 +76,24 @@ public static void tearDown() throws Exception { } /** - * Clear out the OUT4 table used by the chunk tests. + * Do a Checkpoint restore and setup chunk test data. */ - public static void afterEach() throws Exception { - log("afterEach", ""); - executeSql(DFLT_PERSISTENCE_JNDI, "DELETE FROM APP.OUT4;"); + public static void beforeEach() throws Exception { + log("beforeEach", ""); + // Apply config and restore + server.waitForStringInLog("CWWKF0011I", 20000); + FatUtils.waitForSmarterPlanet(server); + + // Setup chunk test data + executeSql("jdbc/batch", getChunkInTableSql()); + executeSql("jdbc/batch", getChunkOutTableSql("APP.OUT4")); + + executeSql("jdbc/myds", getChunkInTableSql()); + executeSql("jdbc/myds", getChunkOutTableSql("APP.OUT1")); + executeSql("jdbc/myds", getChunkOutTableSql("APP.OUT2")); + + executeSql("jdbc/mydsNonTran", getChunkInTableSql()); + executeSql("jdbc/mydsNonTran", getChunkOutTableSql("APP.OUT3")); } /** From 839dc4168c02db79fbb34d89f08bb50f491a654d Mon Sep 17 00:00:00 2001 From: jonhawkes Date: Tue, 19 Nov 2024 15:59:23 +0000 Subject: [PATCH 39/67] Revert "Identify database product on connection retry" --- .../recoverylog/custom/jdbc/impl/DBUtils.java | 42 -- .../jdbc/impl/SQLMultiScopeRecoveryLog.java | 427 ++++++++++-------- .../jdbc/impl/SQLSharedServerLeaseLog.java | 104 +++-- .../servers/jakartaee8/bootstrap.properties | 2 +- .../publish/servers/jakartaee8/server.xml | 4 +- .../internal/monitor_fat/BaseTestClass.java | 12 +- .../ConnectionPoolMetricsTest.java | 2 +- 7 files changed, 326 insertions(+), 267 deletions(-) delete mode 100644 dev/com.ibm.rls.jdbc/src/com/ibm/ws/recoverylog/custom/jdbc/impl/DBUtils.java diff --git a/dev/com.ibm.rls.jdbc/src/com/ibm/ws/recoverylog/custom/jdbc/impl/DBUtils.java b/dev/com.ibm.rls.jdbc/src/com/ibm/ws/recoverylog/custom/jdbc/impl/DBUtils.java deleted file mode 100644 index a5ff7872169..00000000000 --- a/dev/com.ibm.rls.jdbc/src/com/ibm/ws/recoverylog/custom/jdbc/impl/DBUtils.java +++ /dev/null @@ -1,42 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2024 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License 2.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - *******************************************************************************/ -package com.ibm.ws.recoverylog.custom.jdbc.impl; - -import java.sql.Connection; -import java.sql.SQLException; - -public class DBUtils { - public enum DBProduct { - DB2, - Derby, - Oracle, - Postgresql, - Sqlserver, - Unknown, - } - - public static DBProduct identifyDB(Connection conn) throws SQLException { - final String dbName = conn.getMetaData().getDatabaseProductName().toLowerCase(); - - if (dbName.contains("db2")) { - return DBProduct.DB2; - } else if (dbName.contains("derby")) { - return DBProduct.Derby; - } else if (dbName.contains("oracle")) { - return DBProduct.Oracle; - } else if (dbName.contains("postgresql")) { - return DBProduct.Postgresql; - } else if (dbName.contains("microsoft sql")) { - return DBProduct.Sqlserver; - } else { - return DBProduct.Unknown; - } - } -} diff --git a/dev/com.ibm.rls.jdbc/src/com/ibm/ws/recoverylog/custom/jdbc/impl/SQLMultiScopeRecoveryLog.java b/dev/com.ibm.rls.jdbc/src/com/ibm/ws/recoverylog/custom/jdbc/impl/SQLMultiScopeRecoveryLog.java index 6433e625478..244eb4c3116 100644 --- a/dev/com.ibm.rls.jdbc/src/com/ibm/ws/recoverylog/custom/jdbc/impl/SQLMultiScopeRecoveryLog.java +++ b/dev/com.ibm.rls.jdbc/src/com/ibm/ws/recoverylog/custom/jdbc/impl/SQLMultiScopeRecoveryLog.java @@ -18,6 +18,7 @@ import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; import java.sql.Connection; +import java.sql.DatabaseMetaData; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; @@ -44,7 +45,6 @@ import com.ibm.websphere.ras.TraceComponent; import com.ibm.ws.ffdc.FFDCFilter; import com.ibm.ws.ffdc.annotation.FFDCIgnore; -import com.ibm.ws.recoverylog.custom.jdbc.impl.DBUtils.DBProduct; import com.ibm.ws.recoverylog.spi.Configuration; import com.ibm.ws.recoverylog.spi.CustomLogProperties; import com.ibm.ws.recoverylog.spi.DistributedRecoveryLog; @@ -144,7 +144,12 @@ public class SQLMultiScopeRecoveryLog implements LogCursorCallback, MultiScopeLo /** * Which RDBMS are we working against? */ - private DBProduct dbProduct; + volatile private boolean _isDerby; + volatile private boolean _isOracle; + volatile private boolean _isPostgreSQL; + volatile private boolean _isDB2; + volatile private boolean _isSQLServer; + volatile private boolean _isNonStandard; private boolean isolationFailureReported; @@ -848,15 +853,32 @@ private Connection getFirstConnection() throws InternalLogException, SQLExceptio if (tc.isDebugEnabled()) Tr.debug(tc, "Got connection: " + conn); - - dbProduct = DBUtils.identifyDB(conn); - - if (DBProduct.Unknown == dbProduct && !SQLRetry.isLogRetriesEnabled()) { + DatabaseMetaData mdata = conn.getMetaData(); + String dbName = mdata.getDatabaseProductName(); + if (tc.isDebugEnabled()) + Tr.debug(tc, "Working with database: " + dbName); + if (dbName.toLowerCase().contains("oracle")) { + _isOracle = true; + } else if (dbName.toLowerCase().contains("db2")) { + _isDB2 = true; + } else if (dbName.toLowerCase().contains("postgresql")) { + _isPostgreSQL = true; + } else if (dbName.toLowerCase().contains("microsoft sql")) { + _isSQLServer = true; + } else if (dbName.toLowerCase().contains("derby")) { + _isDerby = true; + } else { + _isNonStandard = true; // We're not working with the standard set of databases. The "default" behaviour is not to retry for such non-standard, untested databases, // even if the exception is a SQLTransientException. But if the logRetriesEnabled flag has been explicitly set, then we will retry SQL // operations on all databases. - _sqlTransientErrorHandlingEnabled = false; + if (!SQLRetry.isLogRetriesEnabled()) + _sqlTransientErrorHandlingEnabled = false; } + + String dbVersion = mdata.getDatabaseProductVersion(); + if (tc.isDebugEnabled()) + Tr.debug(tc, "You are now connected to " + dbName + ", version " + dbVersion); } if (tc.isEntryEnabled()) Tr.exit(tc, "getFirstConnection", conn); @@ -891,9 +913,8 @@ public Connection getConnection() throws Exception { Tr.debug(tc, "Set the logRetriesEnabled flag to false"); // If _logRetriesEnabled has been reset (config change) and if the database is non-standard, then we will // no longer retry SQLExceptions - if (SQLRetry.isLogRetriesEnabled() && (dbProduct == null || DBProduct.Unknown == dbProduct)) + if (SQLRetry.isLogRetriesEnabled() && _isNonStandard) _sqlTransientErrorHandlingEnabled = false; - SQLRetry.setLogRetriesEnabled(false); } @@ -947,17 +968,6 @@ public Connection getConnection() throws Exception { } } - if (dbProduct == null) { - dbProduct = DBUtils.identifyDB(conn); - - if (DBProduct.Unknown == dbProduct && !SQLRetry.isLogRetriesEnabled()) { - // We're not working with the standard set of databases. The "default" behaviour is not to retry for such non-standard, untested databases, - // even if the exception is a SQLTransientException. But if the logRetriesEnabled flag has been explicitly set, then we will retry SQL - // operations on all databases. - _sqlTransientErrorHandlingEnabled = false; - } - } - if (tc.isEntryEnabled()) Tr.exit(tc, "getConnection", conn); return conn; @@ -980,14 +990,20 @@ private void recover(Connection conn) throws SQLException, RecoverableUnitSectio if (tc.isEntryEnabled()) Tr.entry(tc, "recover", conn); - String queryString = "SELECT RU_ID, RUSECTION_ID, RUSECTION_DATA_INDEX, DATA" + - " FROM " + _recoveryTableName + _logIdentifierString + _recoveryTableNameSuffix + - " WHERE SERVER_NAME='" + _serverName + - "' AND SERVICE_ID=" + _recoveryAgent.clientIdentifier(); - if (tc.isDebugEnabled()) - Tr.debug(tc, "Retrieve all rows from table using - " + queryString); + Statement recoveryStmt = null; + ResultSet recoveryRS = null; + + try { + recoveryStmt = conn.createStatement(); + String queryString = "SELECT RU_ID, RUSECTION_ID, RUSECTION_DATA_INDEX, DATA" + + " FROM " + _recoveryTableName + _logIdentifierString + _recoveryTableNameSuffix + + " WHERE SERVER_NAME='" + _serverName + + "' AND SERVICE_ID=" + _recoveryAgent.clientIdentifier(); + if (tc.isDebugEnabled()) + Tr.debug(tc, "Retrieve all rows from table using - " + queryString); + + recoveryRS = recoveryStmt.executeQuery(queryString); - try (Statement recoveryStmt = conn.createStatement(); ResultSet recoveryRS = recoveryStmt.executeQuery(queryString)) { while (recoveryRS.next()) { final long ruId = recoveryRS.getLong(1); if (ruId != -1) { @@ -1018,6 +1034,11 @@ private void recover(Connection conn) throws SQLException, RecoverableUnitSectio } else if (tc.isDebugEnabled()) Tr.debug(tc, "Bypass locking row with id: " + ruId); } + } finally { + if (recoveryRS != null && !recoveryRS.isClosed()) + recoveryRS.close(); + if (recoveryStmt != null && !recoveryStmt.isClosed()) + recoveryStmt.close(); } if (tc.isEntryEnabled()) @@ -2463,17 +2484,21 @@ private boolean assertLogOwnershipAtRuntime(Connection conn) throws SQLException if (tc.isEntryEnabled()) Tr.entry(tc, "assertLogOwnershipAtRuntime", new java.lang.Object[] { conn, this }); + Statement lockingStmt = null; + ResultSet lockingRS = null; boolean lockSuccess = false; - final String queryString = "SELECT SERVER_NAME" + - " FROM " + _recoveryTableName + _logIdentifierString + _recoveryTableNameSuffix + - (DBProduct.Sqlserver == dbProduct ? " WITH (ROWLOCK, UPDLOCK, HOLDLOCK)" : "") + - " WHERE RU_ID=-1" + - (DBProduct.Sqlserver == dbProduct ? "" : " FOR UPDATE"); - if (tc.isDebugEnabled()) - Tr.debug(tc, "Attempt to select the HA LOCKING ROW for UPDATE using - " + queryString); + try { + lockingStmt = conn.createStatement(); + String queryString = "SELECT SERVER_NAME" + + " FROM " + _recoveryTableName + _logIdentifierString + _recoveryTableNameSuffix + + (_isSQLServer ? " WITH (ROWLOCK, UPDLOCK, HOLDLOCK)" : "") + + " WHERE RU_ID=-1" + + (_isSQLServer ? "" : " FOR UPDATE"); + if (tc.isDebugEnabled()) + Tr.debug(tc, "Attempt to select the HA LOCKING ROW for UPDATE using - " + queryString); + lockingRS = lockingStmt.executeQuery(queryString); - try (Statement lockingStmt = conn.createStatement(); ResultSet lockingRS = lockingStmt.executeQuery(queryString)) { if (lockingRS.next()) { // We found the HA Lock row String storedServerName = lockingRS.getString(1); @@ -2493,7 +2518,7 @@ private boolean assertLogOwnershipAtRuntime(Connection conn) throws SQLException if (tc.isDebugEnabled()) Tr.debug(tc, "Not the home server, failurescope is " + _failureScope); // Instantiate a PeerLostLogOwnershipException which is less "noisy" than its parent InternalLogException - final PeerLostLogOwnershipException ple = new PeerLostLogOwnershipException("Another server (" + storedServerName + ") has locked the HA lock row", null); + PeerLostLogOwnershipException ple = new PeerLostLogOwnershipException("Another server (" + storedServerName + ") has locked the HA lock row", null); markFailed(ple, false, true); // second parameter "false" as we do not wish to fire out error messages if (tc.isEntryEnabled()) Tr.exit(tc, "assertLogOwnershipAtRuntime", ple); @@ -2502,7 +2527,7 @@ private boolean assertLogOwnershipAtRuntime(Connection conn) throws SQLException Tr.audit(tc, "WTRN0100E: " + "Another server (" + storedServerName + ") owns the log cannot force SQL RecoveryLog " + _logName + " for server " + _serverName); - final InternalLogException ile = new InternalLogException("Another server (" + storedServerName + ") has locked the HA lock row", null); + InternalLogException ile = new InternalLogException("Another server (" + storedServerName + ") has locked the HA lock row", null); markFailed(ile); if (tc.isEntryEnabled()) Tr.exit(tc, "assertLogOwnershipAtRuntime", ile); @@ -2513,7 +2538,7 @@ private boolean assertLogOwnershipAtRuntime(Connection conn) throws SQLException // We didn't find the HA Lock row in the table, mark the log as failed if (tc.isDebugEnabled()) Tr.debug(tc, "Could not find HA Lock row"); - final InternalLogException ile = new InternalLogException("Could not find the HA lock row", null); + InternalLogException ile = new InternalLogException("Could not find the HA lock row", null); Tr.audit(tc, "WTRN0100E: " + "Could not find HA lock row when forcing SQL RecoveryLog " + _logName + " for server " + _serverName); markFailed(ile); @@ -2521,6 +2546,11 @@ private boolean assertLogOwnershipAtRuntime(Connection conn) throws SQLException Tr.exit(tc, "assertLogOwnershipAtRuntime", ile); throw ile; } + } finally { + if (lockingRS != null && !lockingRS.isClosed()) + lockingRS.close(); + if (lockingStmt != null && !lockingStmt.isClosed()) + lockingStmt.close(); } if (tc.isEntryEnabled()) @@ -2541,32 +2571,22 @@ private boolean isTableDeleted(SQLException sqlex) { Tr.debug(tc, "SQL State: {0}", sqlState); Tr.debug(tc, "Error code: {0}", sqlErrorCode); } - - switch (dbProduct) { - case DB2: - if (sqlErrorCode == -204) - noTable = true; - break; - case Derby: - if ("42X05".equals(sqlState)) - noTable = true; - break; - case Oracle: - if (sqlErrorCode == 942) - noTable = true; - break; - case Postgresql: - if (sqlMessage.contains("relation") && sqlMessage.contains("does not exist")) - noTable = true; - break; - case Sqlserver: - if (sqlErrorCode == 208) - noTable = true; - break; - default: - break; + if (_isDB2) { + if (sqlErrorCode == -204) + noTable = true; + } else if (_isOracle) { + if (sqlErrorCode == 942) + noTable = true; + } else if (_isPostgreSQL) { + if (sqlMessage.contains("relation") && sqlMessage.contains("does not exist")) + noTable = true; + } else if (_isSQLServer) { + if (sqlErrorCode == 208) + noTable = true; + } else if (_isDerby) { + if ("42X05".equals(sqlState)) + noTable = true; } - if (tc.isEntryEnabled()) Tr.exit(tc, "isTableDeleted", noTable); return noTable; @@ -2596,6 +2616,7 @@ private void assertLogOwnershipAtOpenWithLatching(Connection conn) throws SQLExc Statement readForUpdateStmt = null; Statement updateStmt = null; + PreparedStatement specStatement = null; ResultSet readForUpdateRS = null; boolean lockingRecordExists = false; @@ -2674,7 +2695,7 @@ private void assertLogOwnershipAtOpenWithLatching(Connection conn) throws SQLExc // we create the table... and here (if is already exists without the locking row) short serviceId = (short) 1; String fullTableName = _recoveryTableName + _logIdentifierString + _recoveryTableNameSuffix; - insertLockingRow(conn, fullTableName, serviceId, _reservedConnectionActiveSectionIDUnset); + insertLockingRow(conn, specStatement, fullTableName, serviceId, _reservedConnectionActiveSectionIDUnset); } } finally { @@ -2694,6 +2715,11 @@ private void assertLogOwnershipAtOpenWithLatching(Connection conn) throws SQLExc updateStmt.close(); } catch (Exception e) { } + if (specStatement != null) + try { + specStatement.close(); + } catch (Exception e) { + } } if (tc.isEntryEnabled()) @@ -2715,6 +2741,7 @@ private void assertLogOwnershipAtOpenPeerLocking(Connection conn) throws SQLExce Statement readForUpdateStmt = null; ResultSet readForUpdateRS = null; Statement updateStmt = null; + PreparedStatement specStatement = null; try { readForUpdateStmt = conn.createStatement(); @@ -2781,14 +2808,14 @@ private void assertLogOwnershipAtOpenPeerLocking(Connection conn) throws SQLExce short serviceId = (short) 1; String fullTableName = _recoveryTableName + _logIdentifierString + _recoveryTableNameSuffix; long fir1 = System.currentTimeMillis(); - insertLockingRow(conn, fullTableName, serviceId, fir1); + insertLockingRow(conn, specStatement, fullTableName, serviceId, fir1); } else { // Handle peer server cases if (ConfigurationProviderManager.getConfigurationProvider().peerRecoveryPrecedence()) { short serviceId = (short) 1; String fullTableName = _recoveryTableName + _logIdentifierString + _recoveryTableNameSuffix; long fir1 = System.currentTimeMillis(); - insertLockingRow(conn, fullTableName, serviceId, fir1); + insertLockingRow(conn, specStatement, fullTableName, serviceId, fir1); } else { // In this case instantiate a PeerLostLogOwnershipException which is less "noisy" than its parent InternalLogException PeerLostLogOwnershipException ple = new PeerLostLogOwnershipException("No lock row but this is peer recovery", null); @@ -2816,6 +2843,11 @@ private void assertLogOwnershipAtOpenPeerLocking(Connection conn) throws SQLExce updateStmt.close(); } catch (Exception e) { } + if (specStatement != null) + try { + specStatement.close(); + } catch (Exception e) { + } } if (tc.isEntryEnabled()) @@ -2838,92 +2870,86 @@ private void createDBTable(Connection conn, String logIdentifierString) throws S Tr.entry(tc, "createDBTable", new java.lang.Object[] { conn, this }); Statement createTableStmt = null; + PreparedStatement specStatement = null; boolean success = false; try { createTableStmt = conn.createStatement(); String fullTableName = _recoveryTableName + logIdentifierString + _recoveryTableNameSuffix; + if (_isOracle) { - switch (dbProduct) { - case Oracle: - String oracleTableString = genericTableCreatePreString + fullTableName + oracleTablePostString; - if (tc.isDebugEnabled()) - Tr.debug(tc, "Create Oracle Table using: " + oracleTableString); + String oracleTableString = genericTableCreatePreString + fullTableName + oracleTablePostString; + if (tc.isDebugEnabled()) + Tr.debug(tc, "Create Oracle Table using: " + oracleTableString); - String oracleIndexString = indexPreString + _recoveryIndexName + logIdentifierString + _recoveryTableNameSuffix + - " ON " + fullTableName + indexPostString; + String oracleIndexString = indexPreString + _recoveryIndexName + logIdentifierString + _recoveryTableNameSuffix + + " ON " + fullTableName + indexPostString; - if (tc.isDebugEnabled()) - Tr.debug(tc, "Create Oracle Index using: " + oracleIndexString); - // Create the Oracle table - createTableStmt.executeUpdate(oracleTableString); - // Create index on the new table - createTableStmt.executeUpdate(oracleIndexString); - break; - case DB2: - String db2TableString = genericTableCreatePreString + fullTableName + db2TablePostString; - String dbName = ConfigurationProviderManager.getConfigurationProvider().getTransactionLogDBName(); - if (!dbName.isEmpty()) { - db2TableString = db2TableString + " IN DATABASE " + dbName; - } - if (tc.isDebugEnabled()) - Tr.debug(tc, "Create DB2 Table using: " + db2TableString); + if (tc.isDebugEnabled()) + Tr.debug(tc, "Create Oracle Index using: " + oracleIndexString); + // Create the Oracle table + createTableStmt.executeUpdate(oracleTableString); + // Create index on the new table + createTableStmt.executeUpdate(oracleIndexString); + } else if (_isDB2) { + String db2TableString = genericTableCreatePreString + fullTableName + db2TablePostString; + String dbName = ConfigurationProviderManager.getConfigurationProvider().getTransactionLogDBName(); + if (!dbName.isEmpty()) { + db2TableString = db2TableString + " IN DATABASE " + dbName; + } + if (tc.isDebugEnabled()) + Tr.debug(tc, "Create DB2 Table using: " + db2TableString); - String db2IndexString = indexPreString + _recoveryIndexName + logIdentifierString + _recoveryTableNameSuffix + - " ON " + fullTableName + indexPostString; - if (tc.isDebugEnabled()) - Tr.debug(tc, "Create DB2 Index using: " + db2IndexString); - // Create the DB2 table - createTableStmt.executeUpdate(db2TableString); - // Create index on the new table - createTableStmt.executeUpdate(db2IndexString); - break; - case Postgresql: - String postgreSQLTableString = genericTableCreatePreString + fullTableName + postgreSQLTablePostString; - if (tc.isDebugEnabled()) - Tr.debug(tc, "Create PostgreSQL table using: " + postgreSQLTableString); + String db2IndexString = indexPreString + _recoveryIndexName + logIdentifierString + _recoveryTableNameSuffix + + " ON " + fullTableName + indexPostString; + if (tc.isDebugEnabled()) + Tr.debug(tc, "Create DB2 Index using: " + db2IndexString); + // Create the DB2 table + createTableStmt.executeUpdate(db2TableString); + // Create index on the new table + createTableStmt.executeUpdate(db2IndexString); + } else if (_isPostgreSQL) { + String postgreSQLTableString = genericTableCreatePreString + fullTableName + postgreSQLTablePostString; + if (tc.isDebugEnabled()) + Tr.debug(tc, "Create PostgreSQL table using: " + postgreSQLTableString); - String postgreSQLIndexString = indexPreString + _recoveryIndexName + logIdentifierString + _recoveryTableNameSuffix + - " ON " + fullTableName + postgreSQLIndexPostString; - if (tc.isDebugEnabled()) - Tr.debug(tc, "Create PostgreSQL index using: " + postgreSQLIndexString); - conn.rollback(); - // Create the PostgreSQL table - createTableStmt.execute(postgreSQLTableString); - // Create index on the new table - createTableStmt.execute(postgreSQLIndexString); - break; - case Sqlserver: - String sqlServerTableString = genericTableCreatePreString + fullTableName + sqlServerTablePostString; - if (tc.isDebugEnabled()) - Tr.debug(tc, "Create SQL Server table using: " + sqlServerTableString); + String postgreSQLIndexString = indexPreString + _recoveryIndexName + logIdentifierString + _recoveryTableNameSuffix + + " ON " + fullTableName + postgreSQLIndexPostString; + if (tc.isDebugEnabled()) + Tr.debug(tc, "Create PostgreSQL index using: " + postgreSQLIndexString); + conn.rollback(); + // Create the PostgreSQL table + createTableStmt.execute(postgreSQLTableString); + // Create index on the new table + createTableStmt.execute(postgreSQLIndexString); + } else if (_isSQLServer) { + String sqlServerTableString = genericTableCreatePreString + fullTableName + sqlServerTablePostString; + if (tc.isDebugEnabled()) + Tr.debug(tc, "Create SQL Server table using: " + sqlServerTableString); - String sqlServerIndexString = indexPreString + _recoveryIndexName + logIdentifierString + _recoveryTableNameSuffix + - " ON " + fullTableName + indexPostString; + String sqlServerIndexString = indexPreString + _recoveryIndexName + logIdentifierString + _recoveryTableNameSuffix + + " ON " + fullTableName + indexPostString; - if (tc.isDebugEnabled()) - Tr.debug(tc, "Create SQL Server index using: " + sqlServerIndexString); - conn.rollback(); - // Create the SQL Server table - createTableStmt.execute(sqlServerTableString); - // Create index on the new table - createTableStmt.execute(sqlServerIndexString); - break; - case Derby: - case Unknown: - String genericTableString = genericTableCreatePreString + fullTableName + genericTablePostString; - if (tc.isDebugEnabled()) - Tr.debug(tc, "Create Generic Table using: " + genericTableString); + if (tc.isDebugEnabled()) + Tr.debug(tc, "Create SQL Server index using: " + sqlServerIndexString); + conn.rollback(); + // Create the SQL Server table + createTableStmt.execute(sqlServerTableString); + // Create index on the new table + createTableStmt.execute(sqlServerIndexString); + } else { + String genericTableString = genericTableCreatePreString + fullTableName + genericTablePostString; + if (tc.isDebugEnabled()) + Tr.debug(tc, "Create Generic Table using: " + genericTableString); - String genericIndexString = indexPreString + _recoveryIndexName + logIdentifierString + _recoveryTableNameSuffix + - " ON " + fullTableName + indexPostString; - if (tc.isDebugEnabled()) - Tr.debug(tc, "Create Generic Index using: " + genericIndexString); - // Create the DB2 table - createTableStmt.executeUpdate(genericTableString); - // Create index on the new table - createTableStmt.executeUpdate(genericIndexString); - break; + String genericIndexString = indexPreString + _recoveryIndexName + logIdentifierString + _recoveryTableNameSuffix + + " ON " + fullTableName + indexPostString; + if (tc.isDebugEnabled()) + Tr.debug(tc, "Create Generic Index using: " + genericIndexString); + // Create the DB2 table + createTableStmt.executeUpdate(genericTableString); + // Create index on the new table + createTableStmt.executeUpdate(genericIndexString); } // Insert the HA Locking row @@ -2933,7 +2959,7 @@ private void createDBTable(Connection conn, String logIdentifierString) throws S fir1 = System.currentTimeMillis(); } - insertLockingRow(conn, fullTableName, serviceId, fir1); + insertLockingRow(conn, specStatement, fullTableName, serviceId, fir1); conn.commit(); // the table and index creation may not be transactional but the INSERT of the locking row IS - commit success = true; @@ -2942,6 +2968,9 @@ private void createDBTable(Connection conn, String logIdentifierString) throws S if (createTableStmt != null && !createTableStmt.isClosed()) { createTableStmt.close(); } + if (specStatement != null && !specStatement.isClosed()) { + specStatement.close(); + } if (!success) conn.rollback(); // should not be needed really } @@ -2954,38 +2983,37 @@ private void createDBTable(Connection conn, String logIdentifierString) throws S * Insert the control, or HA Locking, row containing metadata into the recovery log table * * @param conn + * @param specStatement * @param fullTableName * @param serviceId * @param sectionId * @throws SQLException */ - private void insertLockingRow(Connection conn, String fullTableName, short serviceId, long sectionId) throws SQLException { + private void insertLockingRow(Connection conn, PreparedStatement specStatement, String fullTableName, short serviceId, long sectionId) throws SQLException { if (tc.isEntryEnabled()) - Tr.entry(tc, "insertLockingRow", conn, fullTableName, serviceId, sectionId, this); - + Tr.entry(tc, "insertLockingRow", new java.lang.Object[] { conn, specStatement, fullTableName, serviceId, sectionId, this }); String insertString = "INSERT INTO " + fullTableName + " (SERVER_NAME, SERVICE_ID, RU_ID, RUSECTION_ID, RUSECTION_DATA_INDEX, DATA)" + " VALUES (?,?,?,?,?,?)"; if (tc.isDebugEnabled()) Tr.debug(tc, "Insert LOCKING row using - " + insertString); - - int ret; - try (PreparedStatement specStatement = conn.prepareStatement(insertString)) { - specStatement.setString(1, _currentProcessServerName); - specStatement.setShort(2, serviceId); - specStatement.setLong(3, -1); // NOTE RU_ID SET TO -1 - specStatement.setLong(4, sectionId); - specStatement.setShort(5, (short) 1); - byte buf[] = new byte[2]; - specStatement.setBytes(6, buf); - ret = specStatement.executeUpdate(); - } - + specStatement = conn.prepareStatement(insertString); + specStatement.setString(1, _currentProcessServerName); + specStatement.setShort(2, serviceId); + specStatement.setLong(3, -1); // NOTE RU_ID SET TO -1 + specStatement.setLong(4, sectionId); + specStatement.setShort(5, (short) 1); + byte buf[] = new byte[2]; + specStatement.setBytes(6, buf); + int ret = specStatement.executeUpdate(); if (tc.isDebugEnabled()) Tr.debug(tc, "Have inserted HA LOCKING ROW with return: " + ret); if (tc.isEntryEnabled()) Tr.exit(tc, "insertLockingRow"); + + if (tc.isDebugEnabled()) + Tr.debug(tc, "Have inserted HA Lock row with return: " + ret); } //------------------------------------------------------------------------------ @@ -3003,16 +3031,21 @@ private boolean dropDBTable(Connection conn, String logIdentifierString) throws if (tc.isEntryEnabled()) Tr.entry(tc, "dropDBTable", new java.lang.Object[] { conn, logIdentifierString, this }); + Statement dropTableStmt = null; + Statement lockingStmt = null; + ResultSet lockingRS = null; boolean dropSuccess = false; - String queryString = "SELECT SERVER_NAME" + - " FROM " + _recoveryTableName + logIdentifierString + _recoveryTableNameSuffix + - (DBProduct.Sqlserver == dbProduct ? " WITH (ROWLOCK, UPDLOCK, HOLDLOCK)" : "") + - " WHERE RU_ID=-1" + - (DBProduct.Sqlserver == dbProduct ? "" : " FOR UPDATE"); - if (tc.isDebugEnabled()) - Tr.debug(tc, "Attempt to select the HA LOCKING ROW using - " + queryString); + try { + lockingStmt = conn.createStatement(); + String queryString = "SELECT SERVER_NAME" + + " FROM " + _recoveryTableName + logIdentifierString + _recoveryTableNameSuffix + + (_isSQLServer ? " WITH (ROWLOCK, UPDLOCK, HOLDLOCK)" : "") + + " WHERE RU_ID=-1" + + (_isSQLServer ? "" : " FOR UPDATE"); + if (tc.isDebugEnabled()) + Tr.debug(tc, "Attempt to select the HA LOCKING ROW using - " + queryString); + lockingRS = lockingStmt.executeQuery(queryString); - try (Statement lockingStmt = conn.createStatement(); ResultSet lockingRS = lockingStmt.executeQuery(queryString)) { if (lockingRS.next()) { // We found the HA Lock row String storedServerName = lockingRS.getString(1); @@ -3030,11 +3063,13 @@ private boolean dropDBTable(Connection conn, String logIdentifierString) throws Tr.audit(tc, "WTRN0107W: " + "Could not find the lock row, so cannot delete SQL RecoveryLog " + _logName + " for server " + _serverName); } - } - - // Proceed if we found the locking row and this server is the owner - if (dropSuccess) { - try (Statement dropTableStmt = conn.createStatement()) { + if (lockingRS != null && !lockingRS.isClosed()) + lockingRS.close(); + if (lockingStmt != null && !lockingStmt.isClosed()) + lockingStmt.close(); + // Proceed if we found the locking row and this server is the owner + if (dropSuccess) { + dropTableStmt = conn.createStatement(); String fullTableName = _recoveryTableName + logIdentifierString + _recoveryTableNameSuffix; @@ -3045,6 +3080,14 @@ private boolean dropDBTable(Connection conn, String logIdentifierString) throws // Drop the table dropTableStmt.executeUpdate(dropTableString); } + } finally { + if (dropTableStmt != null && !dropTableStmt.isClosed()) { + dropTableStmt.close(); + } + if (lockingRS != null && !lockingRS.isClosed()) + lockingRS.close(); + if (lockingStmt != null && !lockingStmt.isClosed()) + lockingStmt.close(); } if (tc.isEntryEnabled()) @@ -3636,8 +3679,7 @@ public void provideServiceability() { public int prepareConnectionForBatch(Connection conn) throws SQLException { conn.setAutoCommit(false); int initialIsolation = Connection.TRANSACTION_REPEATABLE_READ; - - if (DBProduct.DB2 == dbProduct) { + if (_isDB2) { try { initialIsolation = conn.getTransactionIsolation(); if (Connection.TRANSACTION_REPEATABLE_READ != initialIsolation && Connection.TRANSACTION_SERIALIZABLE != initialIsolation) { @@ -3663,7 +3705,7 @@ public int prepareConnectionForBatch(Connection conn) throws SQLException { // closes the connection and resets the isolation level if required @Override public void closeConnectionAfterBatch(Connection conn, int initialIsolation) throws SQLException { - if (DBProduct.DB2 == dbProduct) { + if (_isDB2) { if (Connection.TRANSACTION_REPEATABLE_READ != initialIsolation && Connection.TRANSACTION_SERIALIZABLE != initialIsolation) try { conn.setTransactionIsolation(initialIsolation); @@ -3686,9 +3728,9 @@ private ResultSet readHADBLock(Statement lockingStmt, String logIdentifierString // Use RDBMS SELECT FOR UPDATE to lock table for recovery String queryString = "SELECT SERVER_NAME, RUSECTION_ID" + " FROM " + _recoveryTableName + logIdentifierString + _recoveryTableNameSuffix + - (DBProduct.Sqlserver == dbProduct ? " WITH (ROWLOCK, UPDLOCK, HOLDLOCK)" : "") + + (_isSQLServer ? " WITH (ROWLOCK, UPDLOCK, HOLDLOCK)" : "") + " WHERE RU_ID=-1" + - (DBProduct.Sqlserver == dbProduct ? "" : " FOR UPDATE"); + (_isSQLServer ? "" : " FOR UPDATE"); if (tc.isDebugEnabled()) Tr.debug(tc, "Attempt to select the HA LOCKING ROW for UPDATE - " + queryString); return lockingStmt.executeQuery(queryString); @@ -4236,15 +4278,20 @@ public void internalHeartBeat(Connection conn) throws SQLException { if (tc.isEntryEnabled()) Tr.entry(tc, "internalHeartBeat", new Object[] { conn }); - String queryString = "SELECT RUSECTION_ID" + - " FROM " + _recoveryTableName + "PARTNER_LOG" + _recoveryTableNameSuffix + - (DBProduct.Sqlserver == dbProduct ? " WITH (ROWLOCK, UPDLOCK, HOLDLOCK)" : "") + - " WHERE RU_ID=-1" + - (DBProduct.Sqlserver == dbProduct ? "" : " FOR UPDATE"); - if (tc.isDebugEnabled()) - Tr.debug(tc, "Attempt to select the HA LOCKING ROW for UPDATE using - " + queryString); + Statement lockingStmt = null; + ResultSet lockingRS = null; + + try { + lockingStmt = conn.createStatement(); + String queryString = "SELECT RUSECTION_ID" + + " FROM " + _recoveryTableName + "PARTNER_LOG" + _recoveryTableNameSuffix + + (_isSQLServer ? " WITH (ROWLOCK, UPDLOCK, HOLDLOCK)" : "") + + " WHERE RU_ID=-1" + + (_isSQLServer ? "" : " FOR UPDATE"); + if (tc.isDebugEnabled()) + Tr.debug(tc, "Attempt to select the HA LOCKING ROW for UPDATE using - " + queryString); + lockingRS = lockingStmt.executeQuery(queryString); - try (Statement lockingStmt = conn.createStatement(); ResultSet lockingRS = lockingStmt.executeQuery(queryString)) { if (lockingRS.next()) { // We found the HA Lock row long storedTimestamp = lockingRS.getLong(1); @@ -4268,8 +4315,12 @@ public void internalHeartBeat(Connection conn) throws SQLException { if (tc.isDebugEnabled()) Tr.debug(tc, "Could not find HA Lock row, unable to update timestamp"); } + } finally { + if (lockingRS != null && !lockingRS.isClosed()) + lockingRS.close(); + if (lockingStmt != null && !lockingStmt.isClosed()) + lockingStmt.close(); } - if (tc.isEntryEnabled()) Tr.exit(tc, "internalHeartBeat"); } @@ -4444,9 +4495,9 @@ boolean internalClaimRecoveryLogs(Connection conn, boolean isHomeServer) throws // First we process the control record in the partner_log String queryString = "SELECT SERVER_NAME, RUSECTION_ID" + " FROM " + _recoveryTableName + "PARTNER_LOG" + _recoveryTableNameSuffix + - (DBProduct.Sqlserver == dbProduct ? " WITH (ROWLOCK, UPDLOCK, HOLDLOCK)" : "") + + (_isSQLServer ? " WITH (ROWLOCK, UPDLOCK, HOLDLOCK)" : "") + " WHERE RU_ID=-1" + - (DBProduct.Sqlserver == dbProduct ? "" : " FOR UPDATE"); + (_isSQLServer ? "" : " FOR UPDATE"); if (tc.isDebugEnabled()) Tr.debug(tc, "Attempt to select the HA LOCKING ROW for UPDATE using - " + queryString); @@ -4552,9 +4603,9 @@ boolean internalClaimRecoveryLogs(Connection conn, boolean isHomeServer) throws isClaimed = false; queryString = "SELECT SERVER_NAME" + " FROM " + _recoveryTableName + "TRAN_LOG" + _recoveryTableNameSuffix + - (DBProduct.Sqlserver == dbProduct ? " WITH (ROWLOCK, UPDLOCK, HOLDLOCK)" : "") + + (_isSQLServer ? " WITH (ROWLOCK, UPDLOCK, HOLDLOCK)" : "") + " WHERE RU_ID=-1" + - (DBProduct.Sqlserver == dbProduct ? "" : " FOR UPDATE"); + (_isSQLServer ? "" : " FOR UPDATE"); if (tc.isDebugEnabled()) Tr.debug(tc, "Attempt to select the HA LOCKING ROW for UPDATE using - " + queryString); @@ -4838,7 +4889,7 @@ public void retryCode(Connection conn) throws SQLException, Exception { if (_serverStopping) { Tr.debug(tc, "Server is stopping will not claim logs"); } else { - prepareConnectionForBatch(conn); + int initialIsolation = prepareConnectionForBatch(conn); assertDBTableExists(conn, "PARTNER_LOG"); assertDBTableExists(conn, "TRAN_LOG"); diff --git a/dev/com.ibm.rls.jdbc/src/com/ibm/ws/recoverylog/custom/jdbc/impl/SQLSharedServerLeaseLog.java b/dev/com.ibm.rls.jdbc/src/com/ibm/ws/recoverylog/custom/jdbc/impl/SQLSharedServerLeaseLog.java index e2f63b66af6..0d06412e3d6 100644 --- a/dev/com.ibm.rls.jdbc/src/com/ibm/ws/recoverylog/custom/jdbc/impl/SQLSharedServerLeaseLog.java +++ b/dev/com.ibm.rls.jdbc/src/com/ibm/ws/recoverylog/custom/jdbc/impl/SQLSharedServerLeaseLog.java @@ -18,6 +18,7 @@ import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; import java.sql.Connection; +import java.sql.DatabaseMetaData; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; @@ -36,7 +37,6 @@ import com.ibm.websphere.ras.TraceComponent; import com.ibm.ws.ffdc.FFDCFilter; import com.ibm.ws.ffdc.annotation.FFDCIgnore; -import com.ibm.ws.recoverylog.custom.jdbc.impl.DBUtils.DBProduct; import com.ibm.ws.recoverylog.spi.CustomLogProperties; import com.ibm.ws.recoverylog.spi.InternalLogException; import com.ibm.ws.recoverylog.spi.LeaseInfo; @@ -67,10 +67,18 @@ public class SQLSharedServerLeaseLog extends LeaseLogImpl implements SharedServe */ private final CustomLogProperties _customLogProperties; + /** + * Flag whether the database type has ever been determined + */ + boolean _determineDBType; /** * Which RDBMS are we working against? */ - private DBProduct dbProduct; + volatile private boolean _isOracle; + volatile private boolean _isPostgreSQL; + volatile private boolean _isSQLServer; + volatile private boolean _isDB2; + volatile private boolean _isNonStandard; volatile private boolean _leaseTableExists; private boolean _sqlTransientErrorHandlingEnabled = true; @@ -312,10 +320,10 @@ private void getPeerLeasesFromTable(final PeerLeaseTable peerLeaseTable, String if (!_noLockOnLeaseScans) { queryString = "SELECT SERVER_IDENTITY, LEASE_TIME" + " FROM " + _leaseTableName + - (DBProduct.Sqlserver == dbProduct ? " WITH (ROWLOCK, UPDLOCK, HOLDLOCK)" : "") + + (_isSQLServer ? " WITH (ROWLOCK, UPDLOCK, HOLDLOCK)" : "") + " WHERE RECOVERY_GROUP = '" + recoveryGroup + "' AND SERVER_IDENTITY != '" + _localRecoveryIdentity + "'" + - ((DBProduct.Sqlserver == dbProduct) ? "" : " FOR UPDATE") + - ((DBProduct.Postgresql == dbProduct || DBProduct.Sqlserver == dbProduct) ? "" : " OF LEASE_TIME"); + ((_isSQLServer) ? "" : " FOR UPDATE") + + ((_isPostgreSQL || _isSQLServer) ? "" : " OF LEASE_TIME"); if (tc.isDebugEnabled()) Tr.debug(tc, "Attempt to select the row for UPDATE using - " + queryString); } else { @@ -575,10 +583,10 @@ private boolean queryLeaseTable(String recoveryIdentity, Connection conn, boolea try { String queryString = "SELECT LEASE_TIME, LEASE_OWNER" + " FROM " + _leaseTableName + - (DBProduct.Sqlserver == dbProduct ? " WITH (ROWLOCK, UPDLOCK, HOLDLOCK)" : "") + + (_isSQLServer ? " WITH (ROWLOCK, UPDLOCK, HOLDLOCK)" : "") + " WHERE SERVER_IDENTITY='" + recoveryIdentity + "'" + - ((DBProduct.Sqlserver == dbProduct) ? "" : " FOR UPDATE") + - ((DBProduct.Postgresql == dbProduct || DBProduct.Sqlserver == dbProduct) ? "" : " OF LEASE_TIME"); + ((_isSQLServer) ? "" : " FOR UPDATE") + + ((_isPostgreSQL || _isSQLServer) ? "" : " OF LEASE_TIME"); if (tc.isDebugEnabled()) Tr.debug(tc, "Attempt to select the row for UPDATE using - " + queryString); _updatelockingRS = _lockingStmt.executeQuery(queryString); @@ -850,7 +858,7 @@ public Connection getConnection() throws Exception { Tr.debug(tc, "Set the logRetriesEnabled flag to false"); // If _logRetriesEnabled has been reset (config change) and if the database is non-standard, then we will // no longer retry SQLExceptions - if (_logRetriesEnabled && (dbProduct == null || DBProduct.Unknown == dbProduct)) + if (_logRetriesEnabled && _isNonStandard) _sqlTransientErrorHandlingEnabled = false; _logRetriesEnabled = false; SQLRetry.setLogRetriesEnabled(false); @@ -907,15 +915,48 @@ public Connection getConnection() throws Exception { } } - if (conn != null && null == dbProduct) { - dbProduct = DBUtils.identifyDB(conn); - - if (dbProduct == DBProduct.Unknown && !_logRetriesEnabled) { + if (conn != null && !_determineDBType) { + if (tc.isDebugEnabled()) + Tr.debug(tc, "Got connection: " + conn); + DatabaseMetaData mdata = conn.getMetaData(); + if (tc.isDebugEnabled()) + Tr.debug(tc, "Got metadata: " + mdata); + String dbName = mdata.getDatabaseProductName(); + if (dbName.toLowerCase().contains("oracle")) { + _isOracle = true; + if (tc.isDebugEnabled()) + Tr.debug(tc, "This is an Oracle Database"); + } else if (dbName.toLowerCase().contains("postgresql")) { + // we are PostgreSQL + _isPostgreSQL = true; + if (tc.isDebugEnabled()) + Tr.debug(tc, "This is a PostgreSQL Database"); + } else if (dbName.toLowerCase().contains("db2")) { + _isDB2 = true; + if (tc.isDebugEnabled()) + Tr.debug(tc, "This is a DB2 Database"); + } else if (dbName.toLowerCase().contains("microsoft sql")) { + // we are MS SQL Server + _isSQLServer = true; + int tranIsolation = mdata.getDefaultTransactionIsolation(); + if (tc.isDebugEnabled()) + Tr.debug(tc, "This is a Microsoft SQL Server Database with default isolation - " + tranIsolation); + } else if (dbName.toLowerCase().contains("derby")) { + if (tc.isDebugEnabled()) + Tr.debug(tc, "This is a Derby Database"); + } else { + _isNonStandard = true; // We're not working with a member of the standard set of databases. The "default" behaviour is not to retry for such non-standard, untested databases, // even if the exception is a SQLTransientException. But if the logRetriesEnabled flag has been explicitly set, then we will retry SQL // operations on all databases. - _sqlTransientErrorHandlingEnabled = false; + if (!_logRetriesEnabled) + _sqlTransientErrorHandlingEnabled = false; } + + String dbVersion = mdata.getDatabaseProductVersion(); + if (tc.isDebugEnabled()) + Tr.debug(tc, "You are now connected to " + dbName + ", version " + dbVersion); + _determineDBType = true; } if (tc.isEntryEnabled()) @@ -938,15 +979,19 @@ private void createLeaseTable(Connection conn) throws SQLException { if (tc.isEntryEnabled()) Tr.entry(tc, "createLeaseTable", conn, this); - try (Statement createTableStmt = conn.createStatement()) { - if (DBProduct.Oracle == dbProduct) { + Statement createTableStmt = null; + + try { + createTableStmt = conn.createStatement(); + + if (_isOracle) { String oracleTableString = oracleTablePreString + _leaseTableName + oracleTablePostString; if (tc.isDebugEnabled()) Tr.debug(tc, "Create Oracle Table using: " + oracleTableString); createTableStmt.executeUpdate(oracleTableString); // Do not manually create an index as ORACLE automatically sets up an index because of the "UNIQUE" constraint on // the SERVER_IDENTITY column - } else if (DBProduct.Postgresql == dbProduct) { + } else if (_isPostgreSQL) { String postgreSQLTableString = postgreSQLTablePreString + _leaseTableName + postgreSQLTablePostString; if (tc.isDebugEnabled()) Tr.debug(tc, "Create PostgreSQL Table using: " + postgreSQLTableString); @@ -962,7 +1007,7 @@ private void createLeaseTable(Connection conn) throws SQLException { } else { String genericTableString = genericTablePreString + _leaseTableName + genericTablePostString; - if (DBProduct.DB2 == dbProduct) { + if (_isDB2) { String dbName = ConfigurationProviderManager.getConfigurationProvider().getTransactionLogDBName(); if (!dbName.isEmpty()) { genericTableString = genericTableString + " IN DATABASE " + dbName; @@ -980,6 +1025,11 @@ private void createLeaseTable(Connection conn) throws SQLException { // Create index on the new table createTableStmt.execute(genericIndexString); } + + } finally { + if (createTableStmt != null && !createTableStmt.isClosed()) { + createTableStmt.close(); + } } if (tc.isEntryEnabled()) @@ -1252,9 +1302,9 @@ private int deleteLeaseFromTable(String recoveryIdentity, Connection conn) throw _deleteStmt = conn.createStatement(); final String queryString = "SELECT LEASE_OWNER FROM " + _leaseTableName - + (DBProduct.Sqlserver == dbProduct ? " WITH (ROWLOCK, UPDLOCK, HOLDLOCK)" : "") + + (_isSQLServer ? " WITH (ROWLOCK, UPDLOCK, HOLDLOCK)" : "") + " WHERE SERVER_IDENTITY='" + recoveryIdentity + "'" - + ((DBProduct.Sqlserver == dbProduct) ? "" : " FOR UPDATE"); + + ((_isSQLServer) ? "" : " FOR UPDATE"); if (tc.isDebugEnabled()) Tr.debug(tc, "Locking lease for delete: {0}", queryString); @@ -1269,7 +1319,7 @@ private int deleteLeaseFromTable(String recoveryIdentity, Connection conn) throw // Check we're still the lease owner if (leaseOwner.startsWith(_localRecoveryIdentity + ",")) { final String deleteString = "DELETE FROM " + _leaseTableName + - (DBProduct.Sqlserver == dbProduct ? " WITH (ROWLOCK, UPDLOCK, HOLDLOCK)" : "") + (_isSQLServer ? " WITH (ROWLOCK, UPDLOCK, HOLDLOCK)" : "") + " WHERE SERVER_IDENTITY='" + recoveryIdentity + "'"; if (tc.isDebugEnabled()) @@ -1475,10 +1525,10 @@ private boolean claimPeerLeaseFromTable(String recoveryIdentityToRecover, String try { String queryString = "SELECT LEASE_TIME" + " FROM " + _leaseTableName + - (DBProduct.Sqlserver == dbProduct ? " WITH (ROWLOCK, UPDLOCK, HOLDLOCK)" : "") + + (_isSQLServer ? " WITH (ROWLOCK, UPDLOCK, HOLDLOCK)" : "") + " WHERE SERVER_IDENTITY='" + recoveryIdentityToRecover + "'" + - ((DBProduct.Sqlserver == dbProduct) ? "" : " FOR UPDATE") + - ((DBProduct.Postgresql == dbProduct || DBProduct.Sqlserver == dbProduct) ? "" : " OF LEASE_TIME"); + ((_isSQLServer) ? "" : " FOR UPDATE") + + ((_isPostgreSQL || _isSQLServer) ? "" : " OF LEASE_TIME"); if (tc.isDebugEnabled()) Tr.debug(tc, "Attempt to select the row for UPDATE using - " + queryString); @@ -1811,7 +1861,7 @@ public int prepareConnectionForBatch(Connection conn) throws SQLException { Tr.entry(tc, "prepareConnectionForBatch", conn); conn.setAutoCommit(false); int initialIsolation = Connection.TRANSACTION_REPEATABLE_READ; - if (DBProduct.DB2 == dbProduct) { + if (_isDB2) { try { initialIsolation = conn.getTransactionIsolation(); if (Connection.TRANSACTION_REPEATABLE_READ != initialIsolation && Connection.TRANSACTION_SERIALIZABLE != initialIsolation) { @@ -1830,7 +1880,7 @@ public int prepareConnectionForBatch(Connection conn) throws SQLException { // returning RR will prevent closeConnectionAfterBatch resetting isolation level initialIsolation = Connection.TRANSACTION_REPEATABLE_READ; } - } else if (DBProduct.Sqlserver == dbProduct) { + } else if (_isSQLServer) { // SQL Server is predisposed to deadlock on lower isolation levels. The SERIALIZABLE isolation level should mean that deadlocks are // considerably less likely but could lead to poorer performance. Poorer performance wrt lease access is hopefully a price worth paying // to avoid (unexpected) deadlocks. @@ -1869,7 +1919,7 @@ public void closeConnectionAfterBatch(Connection conn, int initialIsolation) thr if (tc.isEntryEnabled()) Tr.entry(tc, "closeConnectionAfterBatch", conn, initialIsolation); if (conn != null && !conn.isClosed()) { - if (DBProduct.DB2 == dbProduct) { + if (_isDB2) { if (Connection.TRANSACTION_REPEATABLE_READ != initialIsolation && Connection.TRANSACTION_SERIALIZABLE != initialIsolation) try { conn.setTransactionIsolation(initialIsolation); diff --git a/dev/com.ibm.ws.kernel.feature.resolver_fat/publish/servers/jakartaee8/bootstrap.properties b/dev/com.ibm.ws.kernel.feature.resolver_fat/publish/servers/jakartaee8/bootstrap.properties index 79059d111e2..035182ebc1f 100644 --- a/dev/com.ibm.ws.kernel.feature.resolver_fat/publish/servers/jakartaee8/bootstrap.properties +++ b/dev/com.ibm.ws.kernel.feature.resolver_fat/publish/servers/jakartaee8/bootstrap.properties @@ -4,7 +4,7 @@ # are made available under the terms of the Eclipse Public License 2.0 # which accompanies this distribution, and is available at # http://www.eclipse.org/legal/epl-2.0/ -# +# # SPDX-License-Identifier: EPL-2.0 # # Contributors: diff --git a/dev/com.ibm.ws.kernel.feature.resolver_fat/publish/servers/jakartaee8/server.xml b/dev/com.ibm.ws.kernel.feature.resolver_fat/publish/servers/jakartaee8/server.xml index 101dcc2ccff..dd40f7eefa6 100644 --- a/dev/com.ibm.ws.kernel.feature.resolver_fat/publish/servers/jakartaee8/server.xml +++ b/dev/com.ibm.ws.kernel.feature.resolver_fat/publish/servers/jakartaee8/server.xml @@ -6,7 +6,7 @@ http://www.eclipse.org/legal/epl-2.0/ SPDX-License-Identifier: EPL-2.0 - + Contributors: IBM Corporation - initial API and implementation --> @@ -20,4 +20,4 @@ - + \ No newline at end of file diff --git a/dev/io.openliberty.microprofile.telemetry.internal.monitor_fat/fat/src/io/openliberty/microprofile/telemetry/internal/monitor_fat/BaseTestClass.java b/dev/io.openliberty.microprofile.telemetry.internal.monitor_fat/fat/src/io/openliberty/microprofile/telemetry/internal/monitor_fat/BaseTestClass.java index bb47d3a0c18..f6828649d1b 100644 --- a/dev/io.openliberty.microprofile.telemetry.internal.monitor_fat/fat/src/io/openliberty/microprofile/telemetry/internal/monitor_fat/BaseTestClass.java +++ b/dev/io.openliberty.microprofile.telemetry.internal.monitor_fat/fat/src/io/openliberty/microprofile/telemetry/internal/monitor_fat/BaseTestClass.java @@ -105,9 +105,9 @@ protected void checkStrings(String metricsText, String[] expectedString) { * @param expectedString String array of expected strings */ protected void matchStringsWithRetries(Supplier metricsOutput, String[] expectedString) throws InterruptedException { - matchStringsWithRetries(metricsOutput, expectedString, 5); + matchStringsWithRetries(metricsOutput, expectedString, 5); } - + /** * Waits one second before checking the condition. Will wait 1 second for every retry amount. * @@ -126,16 +126,16 @@ protected void matchStringsWithRetries(Supplier metricsOutput, String[] Log.info(c, "assertTrueRetryWithTimeout", String.format("It took %d retries and %d seconds of waiting to be succesful)", x, (x + 1))); return; } - + } Assert.fail(String.format("Failed to find all expected strings. The /metrics output is:\n%s", metricsString)); - + } private static BiFunction doMatching = (metricsText, expectedString) -> { - + for (String m : expectedString) { try (Scanner sc = new Scanner(metricsText)) { boolean isFound = false; @@ -197,5 +197,5 @@ protected String requestHttpServlet(String servletPath, LibertyServer server, St con.disconnect(); } - } + } } diff --git a/dev/io.openliberty.microprofile.telemetry.internal.monitor_fat/fat/src/io/openliberty/microprofile/telemetry/internal/monitor_fat/ConnectionPoolMetricsTest.java b/dev/io.openliberty.microprofile.telemetry.internal.monitor_fat/fat/src/io/openliberty/microprofile/telemetry/internal/monitor_fat/ConnectionPoolMetricsTest.java index 0494d531ac9..3cba1b6c60a 100644 --- a/dev/io.openliberty.microprofile.telemetry.internal.monitor_fat/fat/src/io/openliberty/microprofile/telemetry/internal/monitor_fat/ConnectionPoolMetricsTest.java +++ b/dev/io.openliberty.microprofile.telemetry.internal.monitor_fat/fat/src/io/openliberty/microprofile/telemetry/internal/monitor_fat/ConnectionPoolMetricsTest.java @@ -96,7 +96,7 @@ public void connectionPoolTest() throws Exception { Log.info(c, testName, "------- connectionpool metrics should be available ------"); // Allow time for the collector to receive and expose metrics - matchStringsWithRetries(() -> getContainerCollectorMetrics(container), + matchStringsWithRetries(() -> getContainerCollectorMetrics(container), new String[] { "io_openliberty_connection_pool_handle_count\\{instance=\"[a-zA-Z0-9-]*\",io_openliberty_datasource_name=\"jdbc/exampleDS1\",job=\"unknown_service\"\\}.*", "io_openliberty_connection_pool_connection_free\\{instance=\"[a-zA-Z0-9-]*\",io_openliberty_datasource_name=\"jdbc/exampleDS1\",job=\"unknown_service\"\\}.*", "io_openliberty_connection_pool_connection_destroyed_total\\{instance=\"[a-zA-Z0-9-]*\",io_openliberty_datasource_name=\"jdbc/exampleDS1\",job=\"unknown_service\"\\}.*", From 690c1d3db8e21ce819849677bb603b9dc4182c22 Mon Sep 17 00:00:00 2001 From: Jon Hawkes Date: Wed, 13 Nov 2024 14:29:37 +0000 Subject: [PATCH 40/67] fix: add utility class for RDBMS identification --- .../recoverylog/custom/jdbc/impl/DBUtils.java | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 dev/com.ibm.rls.jdbc/src/com/ibm/ws/recoverylog/custom/jdbc/impl/DBUtils.java diff --git a/dev/com.ibm.rls.jdbc/src/com/ibm/ws/recoverylog/custom/jdbc/impl/DBUtils.java b/dev/com.ibm.rls.jdbc/src/com/ibm/ws/recoverylog/custom/jdbc/impl/DBUtils.java new file mode 100644 index 00000000000..4519da303c7 --- /dev/null +++ b/dev/com.ibm.rls.jdbc/src/com/ibm/ws/recoverylog/custom/jdbc/impl/DBUtils.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2024 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package com.ibm.ws.recoverylog.custom.jdbc.impl; + +import java.sql.Connection; +import java.sql.SQLException; + +public class DBUtils { + public enum DBProduct { + DB2, + Derby, + Oracle, + Postgresql, + Sqlserver, + Unknown, + } + + public static DBProduct identifyDB(Connection conn) throws SQLException { + final String dbName = conn.getMetaData().getDatabaseProductName().toLowerCase(); + + if (dbName.contains("db2")) { + return DBProduct.DB2; + } else if (dbName.contains("derby")) { + return DBProduct.Derby; + } else if (dbName.contains("oracle")) { + return DBProduct.Oracle; + } else if (dbName.contains("postgresql")) { + return DBProduct.Postgresql; + } else if (dbName.contains("microsoft sql")) { + return DBProduct.Sqlserver; + } else { + return DBProduct.Unknown; + } + } +} \ No newline at end of file From def4bbb84fe3de1c40f8132c0c7cd98545e349e8 Mon Sep 17 00:00:00 2001 From: Jon Hawkes Date: Wed, 13 Nov 2024 15:05:25 +0000 Subject: [PATCH 41/67] fix: update DB logs to use new DBUtils --- .../jdbc/impl/SQLMultiScopeRecoveryLog.java | 119 +++++++++--------- .../jdbc/impl/SQLSharedServerLeaseLog.java | 93 ++++---------- 2 files changed, 82 insertions(+), 130 deletions(-) diff --git a/dev/com.ibm.rls.jdbc/src/com/ibm/ws/recoverylog/custom/jdbc/impl/SQLMultiScopeRecoveryLog.java b/dev/com.ibm.rls.jdbc/src/com/ibm/ws/recoverylog/custom/jdbc/impl/SQLMultiScopeRecoveryLog.java index 244eb4c3116..3093d6cc1a6 100644 --- a/dev/com.ibm.rls.jdbc/src/com/ibm/ws/recoverylog/custom/jdbc/impl/SQLMultiScopeRecoveryLog.java +++ b/dev/com.ibm.rls.jdbc/src/com/ibm/ws/recoverylog/custom/jdbc/impl/SQLMultiScopeRecoveryLog.java @@ -18,7 +18,6 @@ import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; import java.sql.Connection; -import java.sql.DatabaseMetaData; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; @@ -45,6 +44,7 @@ import com.ibm.websphere.ras.TraceComponent; import com.ibm.ws.ffdc.FFDCFilter; import com.ibm.ws.ffdc.annotation.FFDCIgnore; +import com.ibm.ws.recoverylog.custom.jdbc.impl.DBUtils.DBProduct; import com.ibm.ws.recoverylog.spi.Configuration; import com.ibm.ws.recoverylog.spi.CustomLogProperties; import com.ibm.ws.recoverylog.spi.DistributedRecoveryLog; @@ -144,12 +144,7 @@ public class SQLMultiScopeRecoveryLog implements LogCursorCallback, MultiScopeLo /** * Which RDBMS are we working against? */ - volatile private boolean _isDerby; - volatile private boolean _isOracle; - volatile private boolean _isPostgreSQL; - volatile private boolean _isDB2; - volatile private boolean _isSQLServer; - volatile private boolean _isNonStandard; + private DBProduct dbProduct; private boolean isolationFailureReported; @@ -853,32 +848,15 @@ private Connection getFirstConnection() throws InternalLogException, SQLExceptio if (tc.isDebugEnabled()) Tr.debug(tc, "Got connection: " + conn); - DatabaseMetaData mdata = conn.getMetaData(); - String dbName = mdata.getDatabaseProductName(); - if (tc.isDebugEnabled()) - Tr.debug(tc, "Working with database: " + dbName); - if (dbName.toLowerCase().contains("oracle")) { - _isOracle = true; - } else if (dbName.toLowerCase().contains("db2")) { - _isDB2 = true; - } else if (dbName.toLowerCase().contains("postgresql")) { - _isPostgreSQL = true; - } else if (dbName.toLowerCase().contains("microsoft sql")) { - _isSQLServer = true; - } else if (dbName.toLowerCase().contains("derby")) { - _isDerby = true; - } else { - _isNonStandard = true; + + dbProduct = DBUtils.identifyDB(conn); + + if (DBProduct.Unknown == dbProduct && !SQLRetry.isLogRetriesEnabled()) { // We're not working with the standard set of databases. The "default" behaviour is not to retry for such non-standard, untested databases, // even if the exception is a SQLTransientException. But if the logRetriesEnabled flag has been explicitly set, then we will retry SQL // operations on all databases. - if (!SQLRetry.isLogRetriesEnabled()) - _sqlTransientErrorHandlingEnabled = false; + _sqlTransientErrorHandlingEnabled = false; } - - String dbVersion = mdata.getDatabaseProductVersion(); - if (tc.isDebugEnabled()) - Tr.debug(tc, "You are now connected to " + dbName + ", version " + dbVersion); } if (tc.isEntryEnabled()) Tr.exit(tc, "getFirstConnection", conn); @@ -913,8 +891,9 @@ public Connection getConnection() throws Exception { Tr.debug(tc, "Set the logRetriesEnabled flag to false"); // If _logRetriesEnabled has been reset (config change) and if the database is non-standard, then we will // no longer retry SQLExceptions - if (SQLRetry.isLogRetriesEnabled() && _isNonStandard) + if (SQLRetry.isLogRetriesEnabled() && (dbProduct == null || DBProduct.Unknown == dbProduct)) _sqlTransientErrorHandlingEnabled = false; + SQLRetry.setLogRetriesEnabled(false); } @@ -968,6 +947,10 @@ public Connection getConnection() throws Exception { } } + if (dbProduct == null) { + dbProduct = DBUtils.identifyDB(conn); + } + if (tc.isEntryEnabled()) Tr.exit(tc, "getConnection", conn); return conn; @@ -2492,9 +2475,9 @@ private boolean assertLogOwnershipAtRuntime(Connection conn) throws SQLException lockingStmt = conn.createStatement(); String queryString = "SELECT SERVER_NAME" + " FROM " + _recoveryTableName + _logIdentifierString + _recoveryTableNameSuffix + - (_isSQLServer ? " WITH (ROWLOCK, UPDLOCK, HOLDLOCK)" : "") + + (DBProduct.Sqlserver == dbProduct ? " WITH (ROWLOCK, UPDLOCK, HOLDLOCK)" : "") + " WHERE RU_ID=-1" + - (_isSQLServer ? "" : " FOR UPDATE"); + (DBProduct.Sqlserver == dbProduct ? "" : " FOR UPDATE"); if (tc.isDebugEnabled()) Tr.debug(tc, "Attempt to select the HA LOCKING ROW for UPDATE using - " + queryString); lockingRS = lockingStmt.executeQuery(queryString); @@ -2571,21 +2554,30 @@ private boolean isTableDeleted(SQLException sqlex) { Tr.debug(tc, "SQL State: {0}", sqlState); Tr.debug(tc, "Error code: {0}", sqlErrorCode); } - if (_isDB2) { - if (sqlErrorCode == -204) - noTable = true; - } else if (_isOracle) { - if (sqlErrorCode == 942) - noTable = true; - } else if (_isPostgreSQL) { - if (sqlMessage.contains("relation") && sqlMessage.contains("does not exist")) - noTable = true; - } else if (_isSQLServer) { - if (sqlErrorCode == 208) - noTable = true; - } else if (_isDerby) { - if ("42X05".equals(sqlState)) - noTable = true; + + switch (dbProduct) { + case DB2: + if (sqlErrorCode == -204) + noTable = true; + break; + case Derby: + if ("42X05".equals(sqlState)) + noTable = true; + break; + case Oracle: + if (sqlErrorCode == 942) + noTable = true; + break; + case Postgresql: + if (sqlMessage.contains("relation") && sqlMessage.contains("does not exist")) + noTable = true; + break; + case Sqlserver: + if (sqlErrorCode == 208) + noTable = true; + break; + default: + break; } if (tc.isEntryEnabled()) Tr.exit(tc, "isTableDeleted", noTable); @@ -2876,7 +2868,7 @@ private void createDBTable(Connection conn, String logIdentifierString) throws S try { createTableStmt = conn.createStatement(); String fullTableName = _recoveryTableName + logIdentifierString + _recoveryTableNameSuffix; - if (_isOracle) { + if (DBProduct.Oracle == dbProduct) { String oracleTableString = genericTableCreatePreString + fullTableName + oracleTablePostString; if (tc.isDebugEnabled()) @@ -2891,7 +2883,7 @@ private void createDBTable(Connection conn, String logIdentifierString) throws S createTableStmt.executeUpdate(oracleTableString); // Create index on the new table createTableStmt.executeUpdate(oracleIndexString); - } else if (_isDB2) { + } else if (DBProduct.DB2 == dbProduct) { String db2TableString = genericTableCreatePreString + fullTableName + db2TablePostString; String dbName = ConfigurationProviderManager.getConfigurationProvider().getTransactionLogDBName(); if (!dbName.isEmpty()) { @@ -2908,7 +2900,7 @@ private void createDBTable(Connection conn, String logIdentifierString) throws S createTableStmt.executeUpdate(db2TableString); // Create index on the new table createTableStmt.executeUpdate(db2IndexString); - } else if (_isPostgreSQL) { + } else if (DBProduct.Postgresql == dbProduct) { String postgreSQLTableString = genericTableCreatePreString + fullTableName + postgreSQLTablePostString; if (tc.isDebugEnabled()) Tr.debug(tc, "Create PostgreSQL table using: " + postgreSQLTableString); @@ -2922,7 +2914,7 @@ private void createDBTable(Connection conn, String logIdentifierString) throws S createTableStmt.execute(postgreSQLTableString); // Create index on the new table createTableStmt.execute(postgreSQLIndexString); - } else if (_isSQLServer) { + } else if (DBProduct.Sqlserver == dbProduct) { String sqlServerTableString = genericTableCreatePreString + fullTableName + sqlServerTablePostString; if (tc.isDebugEnabled()) Tr.debug(tc, "Create SQL Server table using: " + sqlServerTableString); @@ -3039,9 +3031,9 @@ private boolean dropDBTable(Connection conn, String logIdentifierString) throws lockingStmt = conn.createStatement(); String queryString = "SELECT SERVER_NAME" + " FROM " + _recoveryTableName + logIdentifierString + _recoveryTableNameSuffix + - (_isSQLServer ? " WITH (ROWLOCK, UPDLOCK, HOLDLOCK)" : "") + + (DBProduct.Sqlserver == dbProduct ? " WITH (ROWLOCK, UPDLOCK, HOLDLOCK)" : "") + " WHERE RU_ID=-1" + - (_isSQLServer ? "" : " FOR UPDATE"); + (DBProduct.Sqlserver == dbProduct ? "" : " FOR UPDATE"); if (tc.isDebugEnabled()) Tr.debug(tc, "Attempt to select the HA LOCKING ROW using - " + queryString); lockingRS = lockingStmt.executeQuery(queryString); @@ -3679,7 +3671,8 @@ public void provideServiceability() { public int prepareConnectionForBatch(Connection conn) throws SQLException { conn.setAutoCommit(false); int initialIsolation = Connection.TRANSACTION_REPEATABLE_READ; - if (_isDB2) { + + if (DBProduct.DB2 == dbProduct) { try { initialIsolation = conn.getTransactionIsolation(); if (Connection.TRANSACTION_REPEATABLE_READ != initialIsolation && Connection.TRANSACTION_SERIALIZABLE != initialIsolation) { @@ -3705,7 +3698,7 @@ public int prepareConnectionForBatch(Connection conn) throws SQLException { // closes the connection and resets the isolation level if required @Override public void closeConnectionAfterBatch(Connection conn, int initialIsolation) throws SQLException { - if (_isDB2) { + if (DBProduct.DB2 == dbProduct) { if (Connection.TRANSACTION_REPEATABLE_READ != initialIsolation && Connection.TRANSACTION_SERIALIZABLE != initialIsolation) try { conn.setTransactionIsolation(initialIsolation); @@ -3728,9 +3721,9 @@ private ResultSet readHADBLock(Statement lockingStmt, String logIdentifierString // Use RDBMS SELECT FOR UPDATE to lock table for recovery String queryString = "SELECT SERVER_NAME, RUSECTION_ID" + " FROM " + _recoveryTableName + logIdentifierString + _recoveryTableNameSuffix + - (_isSQLServer ? " WITH (ROWLOCK, UPDLOCK, HOLDLOCK)" : "") + + (DBProduct.Sqlserver == dbProduct ? " WITH (ROWLOCK, UPDLOCK, HOLDLOCK)" : "") + " WHERE RU_ID=-1" + - (_isSQLServer ? "" : " FOR UPDATE"); + (DBProduct.Sqlserver == dbProduct ? "" : " FOR UPDATE"); if (tc.isDebugEnabled()) Tr.debug(tc, "Attempt to select the HA LOCKING ROW for UPDATE - " + queryString); return lockingStmt.executeQuery(queryString); @@ -4285,9 +4278,9 @@ public void internalHeartBeat(Connection conn) throws SQLException { lockingStmt = conn.createStatement(); String queryString = "SELECT RUSECTION_ID" + " FROM " + _recoveryTableName + "PARTNER_LOG" + _recoveryTableNameSuffix + - (_isSQLServer ? " WITH (ROWLOCK, UPDLOCK, HOLDLOCK)" : "") + + (DBProduct.Sqlserver == dbProduct ? " WITH (ROWLOCK, UPDLOCK, HOLDLOCK)" : "") + " WHERE RU_ID=-1" + - (_isSQLServer ? "" : " FOR UPDATE"); + (DBProduct.Sqlserver == dbProduct ? "" : " FOR UPDATE"); if (tc.isDebugEnabled()) Tr.debug(tc, "Attempt to select the HA LOCKING ROW for UPDATE using - " + queryString); lockingRS = lockingStmt.executeQuery(queryString); @@ -4495,9 +4488,9 @@ boolean internalClaimRecoveryLogs(Connection conn, boolean isHomeServer) throws // First we process the control record in the partner_log String queryString = "SELECT SERVER_NAME, RUSECTION_ID" + " FROM " + _recoveryTableName + "PARTNER_LOG" + _recoveryTableNameSuffix + - (_isSQLServer ? " WITH (ROWLOCK, UPDLOCK, HOLDLOCK)" : "") + + (DBProduct.Sqlserver == dbProduct ? " WITH (ROWLOCK, UPDLOCK, HOLDLOCK)" : "") + " WHERE RU_ID=-1" + - (_isSQLServer ? "" : " FOR UPDATE"); + (DBProduct.Sqlserver == dbProduct ? "" : " FOR UPDATE"); if (tc.isDebugEnabled()) Tr.debug(tc, "Attempt to select the HA LOCKING ROW for UPDATE using - " + queryString); @@ -4603,9 +4596,9 @@ boolean internalClaimRecoveryLogs(Connection conn, boolean isHomeServer) throws isClaimed = false; queryString = "SELECT SERVER_NAME" + " FROM " + _recoveryTableName + "TRAN_LOG" + _recoveryTableNameSuffix + - (_isSQLServer ? " WITH (ROWLOCK, UPDLOCK, HOLDLOCK)" : "") + + (DBProduct.Sqlserver == dbProduct ? " WITH (ROWLOCK, UPDLOCK, HOLDLOCK)" : "") + " WHERE RU_ID=-1" + - (_isSQLServer ? "" : " FOR UPDATE"); + (DBProduct.Sqlserver == dbProduct ? "" : " FOR UPDATE"); if (tc.isDebugEnabled()) Tr.debug(tc, "Attempt to select the HA LOCKING ROW for UPDATE using - " + queryString); diff --git a/dev/com.ibm.rls.jdbc/src/com/ibm/ws/recoverylog/custom/jdbc/impl/SQLSharedServerLeaseLog.java b/dev/com.ibm.rls.jdbc/src/com/ibm/ws/recoverylog/custom/jdbc/impl/SQLSharedServerLeaseLog.java index 0d06412e3d6..50ede1840bc 100644 --- a/dev/com.ibm.rls.jdbc/src/com/ibm/ws/recoverylog/custom/jdbc/impl/SQLSharedServerLeaseLog.java +++ b/dev/com.ibm.rls.jdbc/src/com/ibm/ws/recoverylog/custom/jdbc/impl/SQLSharedServerLeaseLog.java @@ -18,7 +18,6 @@ import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; import java.sql.Connection; -import java.sql.DatabaseMetaData; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; @@ -37,6 +36,7 @@ import com.ibm.websphere.ras.TraceComponent; import com.ibm.ws.ffdc.FFDCFilter; import com.ibm.ws.ffdc.annotation.FFDCIgnore; +import com.ibm.ws.recoverylog.custom.jdbc.impl.DBUtils.DBProduct; import com.ibm.ws.recoverylog.spi.CustomLogProperties; import com.ibm.ws.recoverylog.spi.InternalLogException; import com.ibm.ws.recoverylog.spi.LeaseInfo; @@ -67,18 +67,10 @@ public class SQLSharedServerLeaseLog extends LeaseLogImpl implements SharedServe */ private final CustomLogProperties _customLogProperties; - /** - * Flag whether the database type has ever been determined - */ - boolean _determineDBType; /** * Which RDBMS are we working against? */ - volatile private boolean _isOracle; - volatile private boolean _isPostgreSQL; - volatile private boolean _isSQLServer; - volatile private boolean _isDB2; - volatile private boolean _isNonStandard; + private DBProduct dbProduct; volatile private boolean _leaseTableExists; private boolean _sqlTransientErrorHandlingEnabled = true; @@ -320,10 +312,10 @@ private void getPeerLeasesFromTable(final PeerLeaseTable peerLeaseTable, String if (!_noLockOnLeaseScans) { queryString = "SELECT SERVER_IDENTITY, LEASE_TIME" + " FROM " + _leaseTableName + - (_isSQLServer ? " WITH (ROWLOCK, UPDLOCK, HOLDLOCK)" : "") + + (DBProduct.Sqlserver == dbProduct ? " WITH (ROWLOCK, UPDLOCK, HOLDLOCK)" : "") + " WHERE RECOVERY_GROUP = '" + recoveryGroup + "' AND SERVER_IDENTITY != '" + _localRecoveryIdentity + "'" + - ((_isSQLServer) ? "" : " FOR UPDATE") + - ((_isPostgreSQL || _isSQLServer) ? "" : " OF LEASE_TIME"); + ((DBProduct.Sqlserver == dbProduct) ? "" : " FOR UPDATE") + + ((DBProduct.Postgresql == dbProduct || DBProduct.Sqlserver == dbProduct) ? "" : " OF LEASE_TIME"); if (tc.isDebugEnabled()) Tr.debug(tc, "Attempt to select the row for UPDATE using - " + queryString); } else { @@ -583,10 +575,10 @@ private boolean queryLeaseTable(String recoveryIdentity, Connection conn, boolea try { String queryString = "SELECT LEASE_TIME, LEASE_OWNER" + " FROM " + _leaseTableName + - (_isSQLServer ? " WITH (ROWLOCK, UPDLOCK, HOLDLOCK)" : "") + + (DBProduct.Sqlserver == dbProduct ? " WITH (ROWLOCK, UPDLOCK, HOLDLOCK)" : "") + " WHERE SERVER_IDENTITY='" + recoveryIdentity + "'" + - ((_isSQLServer) ? "" : " FOR UPDATE") + - ((_isPostgreSQL || _isSQLServer) ? "" : " OF LEASE_TIME"); + ((DBProduct.Sqlserver == dbProduct) ? "" : " FOR UPDATE") + + ((DBProduct.Postgresql == dbProduct || DBProduct.Sqlserver == dbProduct) ? "" : " OF LEASE_TIME"); if (tc.isDebugEnabled()) Tr.debug(tc, "Attempt to select the row for UPDATE using - " + queryString); _updatelockingRS = _lockingStmt.executeQuery(queryString); @@ -858,7 +850,7 @@ public Connection getConnection() throws Exception { Tr.debug(tc, "Set the logRetriesEnabled flag to false"); // If _logRetriesEnabled has been reset (config change) and if the database is non-standard, then we will // no longer retry SQLExceptions - if (_logRetriesEnabled && _isNonStandard) + if (_logRetriesEnabled && (dbProduct == null || DBProduct.Unknown == dbProduct)) _sqlTransientErrorHandlingEnabled = false; _logRetriesEnabled = false; SQLRetry.setLogRetriesEnabled(false); @@ -915,48 +907,15 @@ public Connection getConnection() throws Exception { } } - if (conn != null && !_determineDBType) { - if (tc.isDebugEnabled()) - Tr.debug(tc, "Got connection: " + conn); - DatabaseMetaData mdata = conn.getMetaData(); - if (tc.isDebugEnabled()) - Tr.debug(tc, "Got metadata: " + mdata); - String dbName = mdata.getDatabaseProductName(); - if (dbName.toLowerCase().contains("oracle")) { - _isOracle = true; - if (tc.isDebugEnabled()) - Tr.debug(tc, "This is an Oracle Database"); - } else if (dbName.toLowerCase().contains("postgresql")) { - // we are PostgreSQL - _isPostgreSQL = true; - if (tc.isDebugEnabled()) - Tr.debug(tc, "This is a PostgreSQL Database"); - } else if (dbName.toLowerCase().contains("db2")) { - _isDB2 = true; - if (tc.isDebugEnabled()) - Tr.debug(tc, "This is a DB2 Database"); - } else if (dbName.toLowerCase().contains("microsoft sql")) { - // we are MS SQL Server - _isSQLServer = true; - int tranIsolation = mdata.getDefaultTransactionIsolation(); - if (tc.isDebugEnabled()) - Tr.debug(tc, "This is a Microsoft SQL Server Database with default isolation - " + tranIsolation); - } else if (dbName.toLowerCase().contains("derby")) { - if (tc.isDebugEnabled()) - Tr.debug(tc, "This is a Derby Database"); - } else { - _isNonStandard = true; + if (conn != null && null == dbProduct) { + dbProduct = DBUtils.identifyDB(conn); + + if (dbProduct == DBProduct.Unknown && !_logRetriesEnabled) { // We're not working with a member of the standard set of databases. The "default" behaviour is not to retry for such non-standard, untested databases, // even if the exception is a SQLTransientException. But if the logRetriesEnabled flag has been explicitly set, then we will retry SQL // operations on all databases. - if (!_logRetriesEnabled) - _sqlTransientErrorHandlingEnabled = false; + _sqlTransientErrorHandlingEnabled = false; } - - String dbVersion = mdata.getDatabaseProductVersion(); - if (tc.isDebugEnabled()) - Tr.debug(tc, "You are now connected to " + dbName + ", version " + dbVersion); - _determineDBType = true; } if (tc.isEntryEnabled()) @@ -984,14 +943,14 @@ private void createLeaseTable(Connection conn) throws SQLException { try { createTableStmt = conn.createStatement(); - if (_isOracle) { + if (DBProduct.Oracle == dbProduct) { String oracleTableString = oracleTablePreString + _leaseTableName + oracleTablePostString; if (tc.isDebugEnabled()) Tr.debug(tc, "Create Oracle Table using: " + oracleTableString); createTableStmt.executeUpdate(oracleTableString); // Do not manually create an index as ORACLE automatically sets up an index because of the "UNIQUE" constraint on // the SERVER_IDENTITY column - } else if (_isPostgreSQL) { + } else if (DBProduct.Postgresql == dbProduct) { String postgreSQLTableString = postgreSQLTablePreString + _leaseTableName + postgreSQLTablePostString; if (tc.isDebugEnabled()) Tr.debug(tc, "Create PostgreSQL Table using: " + postgreSQLTableString); @@ -1007,7 +966,7 @@ private void createLeaseTable(Connection conn) throws SQLException { } else { String genericTableString = genericTablePreString + _leaseTableName + genericTablePostString; - if (_isDB2) { + if (DBProduct.DB2 == dbProduct) { String dbName = ConfigurationProviderManager.getConfigurationProvider().getTransactionLogDBName(); if (!dbName.isEmpty()) { genericTableString = genericTableString + " IN DATABASE " + dbName; @@ -1302,9 +1261,9 @@ private int deleteLeaseFromTable(String recoveryIdentity, Connection conn) throw _deleteStmt = conn.createStatement(); final String queryString = "SELECT LEASE_OWNER FROM " + _leaseTableName - + (_isSQLServer ? " WITH (ROWLOCK, UPDLOCK, HOLDLOCK)" : "") + + (DBProduct.Sqlserver == dbProduct ? " WITH (ROWLOCK, UPDLOCK, HOLDLOCK)" : "") + " WHERE SERVER_IDENTITY='" + recoveryIdentity + "'" - + ((_isSQLServer) ? "" : " FOR UPDATE"); + + ((DBProduct.Sqlserver == dbProduct) ? "" : " FOR UPDATE"); if (tc.isDebugEnabled()) Tr.debug(tc, "Locking lease for delete: {0}", queryString); @@ -1319,7 +1278,7 @@ private int deleteLeaseFromTable(String recoveryIdentity, Connection conn) throw // Check we're still the lease owner if (leaseOwner.startsWith(_localRecoveryIdentity + ",")) { final String deleteString = "DELETE FROM " + _leaseTableName + - (_isSQLServer ? " WITH (ROWLOCK, UPDLOCK, HOLDLOCK)" : "") + (DBProduct.Sqlserver == dbProduct ? " WITH (ROWLOCK, UPDLOCK, HOLDLOCK)" : "") + " WHERE SERVER_IDENTITY='" + recoveryIdentity + "'"; if (tc.isDebugEnabled()) @@ -1525,10 +1484,10 @@ private boolean claimPeerLeaseFromTable(String recoveryIdentityToRecover, String try { String queryString = "SELECT LEASE_TIME" + " FROM " + _leaseTableName + - (_isSQLServer ? " WITH (ROWLOCK, UPDLOCK, HOLDLOCK)" : "") + + (DBProduct.Sqlserver == dbProduct ? " WITH (ROWLOCK, UPDLOCK, HOLDLOCK)" : "") + " WHERE SERVER_IDENTITY='" + recoveryIdentityToRecover + "'" + - ((_isSQLServer) ? "" : " FOR UPDATE") + - ((_isPostgreSQL || _isSQLServer) ? "" : " OF LEASE_TIME"); + ((DBProduct.Sqlserver == dbProduct) ? "" : " FOR UPDATE") + + ((DBProduct.Postgresql == dbProduct || DBProduct.Sqlserver == dbProduct) ? "" : " OF LEASE_TIME"); if (tc.isDebugEnabled()) Tr.debug(tc, "Attempt to select the row for UPDATE using - " + queryString); @@ -1861,7 +1820,7 @@ public int prepareConnectionForBatch(Connection conn) throws SQLException { Tr.entry(tc, "prepareConnectionForBatch", conn); conn.setAutoCommit(false); int initialIsolation = Connection.TRANSACTION_REPEATABLE_READ; - if (_isDB2) { + if (DBProduct.DB2 == dbProduct) { try { initialIsolation = conn.getTransactionIsolation(); if (Connection.TRANSACTION_REPEATABLE_READ != initialIsolation && Connection.TRANSACTION_SERIALIZABLE != initialIsolation) { @@ -1880,7 +1839,7 @@ public int prepareConnectionForBatch(Connection conn) throws SQLException { // returning RR will prevent closeConnectionAfterBatch resetting isolation level initialIsolation = Connection.TRANSACTION_REPEATABLE_READ; } - } else if (_isSQLServer) { + } else if (DBProduct.Sqlserver == dbProduct) { // SQL Server is predisposed to deadlock on lower isolation levels. The SERIALIZABLE isolation level should mean that deadlocks are // considerably less likely but could lead to poorer performance. Poorer performance wrt lease access is hopefully a price worth paying // to avoid (unexpected) deadlocks. @@ -1919,7 +1878,7 @@ public void closeConnectionAfterBatch(Connection conn, int initialIsolation) thr if (tc.isEntryEnabled()) Tr.entry(tc, "closeConnectionAfterBatch", conn, initialIsolation); if (conn != null && !conn.isClosed()) { - if (_isDB2) { + if (DBProduct.DB2 == dbProduct) { if (Connection.TRANSACTION_REPEATABLE_READ != initialIsolation && Connection.TRANSACTION_SERIALIZABLE != initialIsolation) try { conn.setTransactionIsolation(initialIsolation); From c6b9d7b13d1704f9035c856216fa7a97a54d28e6 Mon Sep 17 00:00:00 2001 From: Jon Hawkes Date: Wed, 13 Nov 2024 15:11:00 +0000 Subject: [PATCH 42/67] fix: tidy up log classes --- .../jdbc/impl/SQLMultiScopeRecoveryLog.java | 328 ++++++++---------- .../jdbc/impl/SQLSharedServerLeaseLog.java | 11 +- 2 files changed, 143 insertions(+), 196 deletions(-) diff --git a/dev/com.ibm.rls.jdbc/src/com/ibm/ws/recoverylog/custom/jdbc/impl/SQLMultiScopeRecoveryLog.java b/dev/com.ibm.rls.jdbc/src/com/ibm/ws/recoverylog/custom/jdbc/impl/SQLMultiScopeRecoveryLog.java index 3093d6cc1a6..6433e625478 100644 --- a/dev/com.ibm.rls.jdbc/src/com/ibm/ws/recoverylog/custom/jdbc/impl/SQLMultiScopeRecoveryLog.java +++ b/dev/com.ibm.rls.jdbc/src/com/ibm/ws/recoverylog/custom/jdbc/impl/SQLMultiScopeRecoveryLog.java @@ -949,6 +949,13 @@ public Connection getConnection() throws Exception { if (dbProduct == null) { dbProduct = DBUtils.identifyDB(conn); + + if (DBProduct.Unknown == dbProduct && !SQLRetry.isLogRetriesEnabled()) { + // We're not working with the standard set of databases. The "default" behaviour is not to retry for such non-standard, untested databases, + // even if the exception is a SQLTransientException. But if the logRetriesEnabled flag has been explicitly set, then we will retry SQL + // operations on all databases. + _sqlTransientErrorHandlingEnabled = false; + } } if (tc.isEntryEnabled()) @@ -973,20 +980,14 @@ private void recover(Connection conn) throws SQLException, RecoverableUnitSectio if (tc.isEntryEnabled()) Tr.entry(tc, "recover", conn); - Statement recoveryStmt = null; - ResultSet recoveryRS = null; - - try { - recoveryStmt = conn.createStatement(); - String queryString = "SELECT RU_ID, RUSECTION_ID, RUSECTION_DATA_INDEX, DATA" + - " FROM " + _recoveryTableName + _logIdentifierString + _recoveryTableNameSuffix + - " WHERE SERVER_NAME='" + _serverName + - "' AND SERVICE_ID=" + _recoveryAgent.clientIdentifier(); - if (tc.isDebugEnabled()) - Tr.debug(tc, "Retrieve all rows from table using - " + queryString); - - recoveryRS = recoveryStmt.executeQuery(queryString); + String queryString = "SELECT RU_ID, RUSECTION_ID, RUSECTION_DATA_INDEX, DATA" + + " FROM " + _recoveryTableName + _logIdentifierString + _recoveryTableNameSuffix + + " WHERE SERVER_NAME='" + _serverName + + "' AND SERVICE_ID=" + _recoveryAgent.clientIdentifier(); + if (tc.isDebugEnabled()) + Tr.debug(tc, "Retrieve all rows from table using - " + queryString); + try (Statement recoveryStmt = conn.createStatement(); ResultSet recoveryRS = recoveryStmt.executeQuery(queryString)) { while (recoveryRS.next()) { final long ruId = recoveryRS.getLong(1); if (ruId != -1) { @@ -1017,11 +1018,6 @@ private void recover(Connection conn) throws SQLException, RecoverableUnitSectio } else if (tc.isDebugEnabled()) Tr.debug(tc, "Bypass locking row with id: " + ruId); } - } finally { - if (recoveryRS != null && !recoveryRS.isClosed()) - recoveryRS.close(); - if (recoveryStmt != null && !recoveryStmt.isClosed()) - recoveryStmt.close(); } if (tc.isEntryEnabled()) @@ -2467,21 +2463,17 @@ private boolean assertLogOwnershipAtRuntime(Connection conn) throws SQLException if (tc.isEntryEnabled()) Tr.entry(tc, "assertLogOwnershipAtRuntime", new java.lang.Object[] { conn, this }); - Statement lockingStmt = null; - ResultSet lockingRS = null; boolean lockSuccess = false; - try { - lockingStmt = conn.createStatement(); - String queryString = "SELECT SERVER_NAME" + - " FROM " + _recoveryTableName + _logIdentifierString + _recoveryTableNameSuffix + - (DBProduct.Sqlserver == dbProduct ? " WITH (ROWLOCK, UPDLOCK, HOLDLOCK)" : "") + - " WHERE RU_ID=-1" + - (DBProduct.Sqlserver == dbProduct ? "" : " FOR UPDATE"); - if (tc.isDebugEnabled()) - Tr.debug(tc, "Attempt to select the HA LOCKING ROW for UPDATE using - " + queryString); - lockingRS = lockingStmt.executeQuery(queryString); + final String queryString = "SELECT SERVER_NAME" + + " FROM " + _recoveryTableName + _logIdentifierString + _recoveryTableNameSuffix + + (DBProduct.Sqlserver == dbProduct ? " WITH (ROWLOCK, UPDLOCK, HOLDLOCK)" : "") + + " WHERE RU_ID=-1" + + (DBProduct.Sqlserver == dbProduct ? "" : " FOR UPDATE"); + if (tc.isDebugEnabled()) + Tr.debug(tc, "Attempt to select the HA LOCKING ROW for UPDATE using - " + queryString); + try (Statement lockingStmt = conn.createStatement(); ResultSet lockingRS = lockingStmt.executeQuery(queryString)) { if (lockingRS.next()) { // We found the HA Lock row String storedServerName = lockingRS.getString(1); @@ -2501,7 +2493,7 @@ private boolean assertLogOwnershipAtRuntime(Connection conn) throws SQLException if (tc.isDebugEnabled()) Tr.debug(tc, "Not the home server, failurescope is " + _failureScope); // Instantiate a PeerLostLogOwnershipException which is less "noisy" than its parent InternalLogException - PeerLostLogOwnershipException ple = new PeerLostLogOwnershipException("Another server (" + storedServerName + ") has locked the HA lock row", null); + final PeerLostLogOwnershipException ple = new PeerLostLogOwnershipException("Another server (" + storedServerName + ") has locked the HA lock row", null); markFailed(ple, false, true); // second parameter "false" as we do not wish to fire out error messages if (tc.isEntryEnabled()) Tr.exit(tc, "assertLogOwnershipAtRuntime", ple); @@ -2510,7 +2502,7 @@ private boolean assertLogOwnershipAtRuntime(Connection conn) throws SQLException Tr.audit(tc, "WTRN0100E: " + "Another server (" + storedServerName + ") owns the log cannot force SQL RecoveryLog " + _logName + " for server " + _serverName); - InternalLogException ile = new InternalLogException("Another server (" + storedServerName + ") has locked the HA lock row", null); + final InternalLogException ile = new InternalLogException("Another server (" + storedServerName + ") has locked the HA lock row", null); markFailed(ile); if (tc.isEntryEnabled()) Tr.exit(tc, "assertLogOwnershipAtRuntime", ile); @@ -2521,7 +2513,7 @@ private boolean assertLogOwnershipAtRuntime(Connection conn) throws SQLException // We didn't find the HA Lock row in the table, mark the log as failed if (tc.isDebugEnabled()) Tr.debug(tc, "Could not find HA Lock row"); - InternalLogException ile = new InternalLogException("Could not find the HA lock row", null); + final InternalLogException ile = new InternalLogException("Could not find the HA lock row", null); Tr.audit(tc, "WTRN0100E: " + "Could not find HA lock row when forcing SQL RecoveryLog " + _logName + " for server " + _serverName); markFailed(ile); @@ -2529,11 +2521,6 @@ private boolean assertLogOwnershipAtRuntime(Connection conn) throws SQLException Tr.exit(tc, "assertLogOwnershipAtRuntime", ile); throw ile; } - } finally { - if (lockingRS != null && !lockingRS.isClosed()) - lockingRS.close(); - if (lockingStmt != null && !lockingStmt.isClosed()) - lockingStmt.close(); } if (tc.isEntryEnabled()) @@ -2579,6 +2566,7 @@ private boolean isTableDeleted(SQLException sqlex) { default: break; } + if (tc.isEntryEnabled()) Tr.exit(tc, "isTableDeleted", noTable); return noTable; @@ -2608,7 +2596,6 @@ private void assertLogOwnershipAtOpenWithLatching(Connection conn) throws SQLExc Statement readForUpdateStmt = null; Statement updateStmt = null; - PreparedStatement specStatement = null; ResultSet readForUpdateRS = null; boolean lockingRecordExists = false; @@ -2687,7 +2674,7 @@ private void assertLogOwnershipAtOpenWithLatching(Connection conn) throws SQLExc // we create the table... and here (if is already exists without the locking row) short serviceId = (short) 1; String fullTableName = _recoveryTableName + _logIdentifierString + _recoveryTableNameSuffix; - insertLockingRow(conn, specStatement, fullTableName, serviceId, _reservedConnectionActiveSectionIDUnset); + insertLockingRow(conn, fullTableName, serviceId, _reservedConnectionActiveSectionIDUnset); } } finally { @@ -2707,11 +2694,6 @@ private void assertLogOwnershipAtOpenWithLatching(Connection conn) throws SQLExc updateStmt.close(); } catch (Exception e) { } - if (specStatement != null) - try { - specStatement.close(); - } catch (Exception e) { - } } if (tc.isEntryEnabled()) @@ -2733,7 +2715,6 @@ private void assertLogOwnershipAtOpenPeerLocking(Connection conn) throws SQLExce Statement readForUpdateStmt = null; ResultSet readForUpdateRS = null; Statement updateStmt = null; - PreparedStatement specStatement = null; try { readForUpdateStmt = conn.createStatement(); @@ -2800,14 +2781,14 @@ private void assertLogOwnershipAtOpenPeerLocking(Connection conn) throws SQLExce short serviceId = (short) 1; String fullTableName = _recoveryTableName + _logIdentifierString + _recoveryTableNameSuffix; long fir1 = System.currentTimeMillis(); - insertLockingRow(conn, specStatement, fullTableName, serviceId, fir1); + insertLockingRow(conn, fullTableName, serviceId, fir1); } else { // Handle peer server cases if (ConfigurationProviderManager.getConfigurationProvider().peerRecoveryPrecedence()) { short serviceId = (short) 1; String fullTableName = _recoveryTableName + _logIdentifierString + _recoveryTableNameSuffix; long fir1 = System.currentTimeMillis(); - insertLockingRow(conn, specStatement, fullTableName, serviceId, fir1); + insertLockingRow(conn, fullTableName, serviceId, fir1); } else { // In this case instantiate a PeerLostLogOwnershipException which is less "noisy" than its parent InternalLogException PeerLostLogOwnershipException ple = new PeerLostLogOwnershipException("No lock row but this is peer recovery", null); @@ -2835,11 +2816,6 @@ private void assertLogOwnershipAtOpenPeerLocking(Connection conn) throws SQLExce updateStmt.close(); } catch (Exception e) { } - if (specStatement != null) - try { - specStatement.close(); - } catch (Exception e) { - } } if (tc.isEntryEnabled()) @@ -2862,86 +2838,92 @@ private void createDBTable(Connection conn, String logIdentifierString) throws S Tr.entry(tc, "createDBTable", new java.lang.Object[] { conn, this }); Statement createTableStmt = null; - PreparedStatement specStatement = null; boolean success = false; try { createTableStmt = conn.createStatement(); String fullTableName = _recoveryTableName + logIdentifierString + _recoveryTableNameSuffix; - if (DBProduct.Oracle == dbProduct) { - String oracleTableString = genericTableCreatePreString + fullTableName + oracleTablePostString; - if (tc.isDebugEnabled()) - Tr.debug(tc, "Create Oracle Table using: " + oracleTableString); + switch (dbProduct) { + case Oracle: + String oracleTableString = genericTableCreatePreString + fullTableName + oracleTablePostString; + if (tc.isDebugEnabled()) + Tr.debug(tc, "Create Oracle Table using: " + oracleTableString); - String oracleIndexString = indexPreString + _recoveryIndexName + logIdentifierString + _recoveryTableNameSuffix + - " ON " + fullTableName + indexPostString; + String oracleIndexString = indexPreString + _recoveryIndexName + logIdentifierString + _recoveryTableNameSuffix + + " ON " + fullTableName + indexPostString; - if (tc.isDebugEnabled()) - Tr.debug(tc, "Create Oracle Index using: " + oracleIndexString); - // Create the Oracle table - createTableStmt.executeUpdate(oracleTableString); - // Create index on the new table - createTableStmt.executeUpdate(oracleIndexString); - } else if (DBProduct.DB2 == dbProduct) { - String db2TableString = genericTableCreatePreString + fullTableName + db2TablePostString; - String dbName = ConfigurationProviderManager.getConfigurationProvider().getTransactionLogDBName(); - if (!dbName.isEmpty()) { - db2TableString = db2TableString + " IN DATABASE " + dbName; - } - if (tc.isDebugEnabled()) - Tr.debug(tc, "Create DB2 Table using: " + db2TableString); + if (tc.isDebugEnabled()) + Tr.debug(tc, "Create Oracle Index using: " + oracleIndexString); + // Create the Oracle table + createTableStmt.executeUpdate(oracleTableString); + // Create index on the new table + createTableStmt.executeUpdate(oracleIndexString); + break; + case DB2: + String db2TableString = genericTableCreatePreString + fullTableName + db2TablePostString; + String dbName = ConfigurationProviderManager.getConfigurationProvider().getTransactionLogDBName(); + if (!dbName.isEmpty()) { + db2TableString = db2TableString + " IN DATABASE " + dbName; + } + if (tc.isDebugEnabled()) + Tr.debug(tc, "Create DB2 Table using: " + db2TableString); - String db2IndexString = indexPreString + _recoveryIndexName + logIdentifierString + _recoveryTableNameSuffix + - " ON " + fullTableName + indexPostString; - if (tc.isDebugEnabled()) - Tr.debug(tc, "Create DB2 Index using: " + db2IndexString); - // Create the DB2 table - createTableStmt.executeUpdate(db2TableString); - // Create index on the new table - createTableStmt.executeUpdate(db2IndexString); - } else if (DBProduct.Postgresql == dbProduct) { - String postgreSQLTableString = genericTableCreatePreString + fullTableName + postgreSQLTablePostString; - if (tc.isDebugEnabled()) - Tr.debug(tc, "Create PostgreSQL table using: " + postgreSQLTableString); + String db2IndexString = indexPreString + _recoveryIndexName + logIdentifierString + _recoveryTableNameSuffix + + " ON " + fullTableName + indexPostString; + if (tc.isDebugEnabled()) + Tr.debug(tc, "Create DB2 Index using: " + db2IndexString); + // Create the DB2 table + createTableStmt.executeUpdate(db2TableString); + // Create index on the new table + createTableStmt.executeUpdate(db2IndexString); + break; + case Postgresql: + String postgreSQLTableString = genericTableCreatePreString + fullTableName + postgreSQLTablePostString; + if (tc.isDebugEnabled()) + Tr.debug(tc, "Create PostgreSQL table using: " + postgreSQLTableString); - String postgreSQLIndexString = indexPreString + _recoveryIndexName + logIdentifierString + _recoveryTableNameSuffix + - " ON " + fullTableName + postgreSQLIndexPostString; - if (tc.isDebugEnabled()) - Tr.debug(tc, "Create PostgreSQL index using: " + postgreSQLIndexString); - conn.rollback(); - // Create the PostgreSQL table - createTableStmt.execute(postgreSQLTableString); - // Create index on the new table - createTableStmt.execute(postgreSQLIndexString); - } else if (DBProduct.Sqlserver == dbProduct) { - String sqlServerTableString = genericTableCreatePreString + fullTableName + sqlServerTablePostString; - if (tc.isDebugEnabled()) - Tr.debug(tc, "Create SQL Server table using: " + sqlServerTableString); + String postgreSQLIndexString = indexPreString + _recoveryIndexName + logIdentifierString + _recoveryTableNameSuffix + + " ON " + fullTableName + postgreSQLIndexPostString; + if (tc.isDebugEnabled()) + Tr.debug(tc, "Create PostgreSQL index using: " + postgreSQLIndexString); + conn.rollback(); + // Create the PostgreSQL table + createTableStmt.execute(postgreSQLTableString); + // Create index on the new table + createTableStmt.execute(postgreSQLIndexString); + break; + case Sqlserver: + String sqlServerTableString = genericTableCreatePreString + fullTableName + sqlServerTablePostString; + if (tc.isDebugEnabled()) + Tr.debug(tc, "Create SQL Server table using: " + sqlServerTableString); - String sqlServerIndexString = indexPreString + _recoveryIndexName + logIdentifierString + _recoveryTableNameSuffix + - " ON " + fullTableName + indexPostString; + String sqlServerIndexString = indexPreString + _recoveryIndexName + logIdentifierString + _recoveryTableNameSuffix + + " ON " + fullTableName + indexPostString; - if (tc.isDebugEnabled()) - Tr.debug(tc, "Create SQL Server index using: " + sqlServerIndexString); - conn.rollback(); - // Create the SQL Server table - createTableStmt.execute(sqlServerTableString); - // Create index on the new table - createTableStmt.execute(sqlServerIndexString); - } else { - String genericTableString = genericTableCreatePreString + fullTableName + genericTablePostString; - if (tc.isDebugEnabled()) - Tr.debug(tc, "Create Generic Table using: " + genericTableString); + if (tc.isDebugEnabled()) + Tr.debug(tc, "Create SQL Server index using: " + sqlServerIndexString); + conn.rollback(); + // Create the SQL Server table + createTableStmt.execute(sqlServerTableString); + // Create index on the new table + createTableStmt.execute(sqlServerIndexString); + break; + case Derby: + case Unknown: + String genericTableString = genericTableCreatePreString + fullTableName + genericTablePostString; + if (tc.isDebugEnabled()) + Tr.debug(tc, "Create Generic Table using: " + genericTableString); - String genericIndexString = indexPreString + _recoveryIndexName + logIdentifierString + _recoveryTableNameSuffix + - " ON " + fullTableName + indexPostString; - if (tc.isDebugEnabled()) - Tr.debug(tc, "Create Generic Index using: " + genericIndexString); - // Create the DB2 table - createTableStmt.executeUpdate(genericTableString); - // Create index on the new table - createTableStmt.executeUpdate(genericIndexString); + String genericIndexString = indexPreString + _recoveryIndexName + logIdentifierString + _recoveryTableNameSuffix + + " ON " + fullTableName + indexPostString; + if (tc.isDebugEnabled()) + Tr.debug(tc, "Create Generic Index using: " + genericIndexString); + // Create the DB2 table + createTableStmt.executeUpdate(genericTableString); + // Create index on the new table + createTableStmt.executeUpdate(genericIndexString); + break; } // Insert the HA Locking row @@ -2951,7 +2933,7 @@ private void createDBTable(Connection conn, String logIdentifierString) throws S fir1 = System.currentTimeMillis(); } - insertLockingRow(conn, specStatement, fullTableName, serviceId, fir1); + insertLockingRow(conn, fullTableName, serviceId, fir1); conn.commit(); // the table and index creation may not be transactional but the INSERT of the locking row IS - commit success = true; @@ -2960,9 +2942,6 @@ private void createDBTable(Connection conn, String logIdentifierString) throws S if (createTableStmt != null && !createTableStmt.isClosed()) { createTableStmt.close(); } - if (specStatement != null && !specStatement.isClosed()) { - specStatement.close(); - } if (!success) conn.rollback(); // should not be needed really } @@ -2975,37 +2954,38 @@ private void createDBTable(Connection conn, String logIdentifierString) throws S * Insert the control, or HA Locking, row containing metadata into the recovery log table * * @param conn - * @param specStatement * @param fullTableName * @param serviceId * @param sectionId * @throws SQLException */ - private void insertLockingRow(Connection conn, PreparedStatement specStatement, String fullTableName, short serviceId, long sectionId) throws SQLException { + private void insertLockingRow(Connection conn, String fullTableName, short serviceId, long sectionId) throws SQLException { if (tc.isEntryEnabled()) - Tr.entry(tc, "insertLockingRow", new java.lang.Object[] { conn, specStatement, fullTableName, serviceId, sectionId, this }); + Tr.entry(tc, "insertLockingRow", conn, fullTableName, serviceId, sectionId, this); + String insertString = "INSERT INTO " + fullTableName + " (SERVER_NAME, SERVICE_ID, RU_ID, RUSECTION_ID, RUSECTION_DATA_INDEX, DATA)" + " VALUES (?,?,?,?,?,?)"; if (tc.isDebugEnabled()) Tr.debug(tc, "Insert LOCKING row using - " + insertString); - specStatement = conn.prepareStatement(insertString); - specStatement.setString(1, _currentProcessServerName); - specStatement.setShort(2, serviceId); - specStatement.setLong(3, -1); // NOTE RU_ID SET TO -1 - specStatement.setLong(4, sectionId); - specStatement.setShort(5, (short) 1); - byte buf[] = new byte[2]; - specStatement.setBytes(6, buf); - int ret = specStatement.executeUpdate(); + + int ret; + try (PreparedStatement specStatement = conn.prepareStatement(insertString)) { + specStatement.setString(1, _currentProcessServerName); + specStatement.setShort(2, serviceId); + specStatement.setLong(3, -1); // NOTE RU_ID SET TO -1 + specStatement.setLong(4, sectionId); + specStatement.setShort(5, (short) 1); + byte buf[] = new byte[2]; + specStatement.setBytes(6, buf); + ret = specStatement.executeUpdate(); + } + if (tc.isDebugEnabled()) Tr.debug(tc, "Have inserted HA LOCKING ROW with return: " + ret); if (tc.isEntryEnabled()) Tr.exit(tc, "insertLockingRow"); - - if (tc.isDebugEnabled()) - Tr.debug(tc, "Have inserted HA Lock row with return: " + ret); } //------------------------------------------------------------------------------ @@ -3023,21 +3003,16 @@ private boolean dropDBTable(Connection conn, String logIdentifierString) throws if (tc.isEntryEnabled()) Tr.entry(tc, "dropDBTable", new java.lang.Object[] { conn, logIdentifierString, this }); - Statement dropTableStmt = null; - Statement lockingStmt = null; - ResultSet lockingRS = null; boolean dropSuccess = false; - try { - lockingStmt = conn.createStatement(); - String queryString = "SELECT SERVER_NAME" + - " FROM " + _recoveryTableName + logIdentifierString + _recoveryTableNameSuffix + - (DBProduct.Sqlserver == dbProduct ? " WITH (ROWLOCK, UPDLOCK, HOLDLOCK)" : "") + - " WHERE RU_ID=-1" + - (DBProduct.Sqlserver == dbProduct ? "" : " FOR UPDATE"); - if (tc.isDebugEnabled()) - Tr.debug(tc, "Attempt to select the HA LOCKING ROW using - " + queryString); - lockingRS = lockingStmt.executeQuery(queryString); + String queryString = "SELECT SERVER_NAME" + + " FROM " + _recoveryTableName + logIdentifierString + _recoveryTableNameSuffix + + (DBProduct.Sqlserver == dbProduct ? " WITH (ROWLOCK, UPDLOCK, HOLDLOCK)" : "") + + " WHERE RU_ID=-1" + + (DBProduct.Sqlserver == dbProduct ? "" : " FOR UPDATE"); + if (tc.isDebugEnabled()) + Tr.debug(tc, "Attempt to select the HA LOCKING ROW using - " + queryString); + try (Statement lockingStmt = conn.createStatement(); ResultSet lockingRS = lockingStmt.executeQuery(queryString)) { if (lockingRS.next()) { // We found the HA Lock row String storedServerName = lockingRS.getString(1); @@ -3055,13 +3030,11 @@ private boolean dropDBTable(Connection conn, String logIdentifierString) throws Tr.audit(tc, "WTRN0107W: " + "Could not find the lock row, so cannot delete SQL RecoveryLog " + _logName + " for server " + _serverName); } - if (lockingRS != null && !lockingRS.isClosed()) - lockingRS.close(); - if (lockingStmt != null && !lockingStmt.isClosed()) - lockingStmt.close(); - // Proceed if we found the locking row and this server is the owner - if (dropSuccess) { - dropTableStmt = conn.createStatement(); + } + + // Proceed if we found the locking row and this server is the owner + if (dropSuccess) { + try (Statement dropTableStmt = conn.createStatement()) { String fullTableName = _recoveryTableName + logIdentifierString + _recoveryTableNameSuffix; @@ -3072,14 +3045,6 @@ private boolean dropDBTable(Connection conn, String logIdentifierString) throws // Drop the table dropTableStmt.executeUpdate(dropTableString); } - } finally { - if (dropTableStmt != null && !dropTableStmt.isClosed()) { - dropTableStmt.close(); - } - if (lockingRS != null && !lockingRS.isClosed()) - lockingRS.close(); - if (lockingStmt != null && !lockingStmt.isClosed()) - lockingStmt.close(); } if (tc.isEntryEnabled()) @@ -4271,20 +4236,15 @@ public void internalHeartBeat(Connection conn) throws SQLException { if (tc.isEntryEnabled()) Tr.entry(tc, "internalHeartBeat", new Object[] { conn }); - Statement lockingStmt = null; - ResultSet lockingRS = null; - - try { - lockingStmt = conn.createStatement(); - String queryString = "SELECT RUSECTION_ID" + - " FROM " + _recoveryTableName + "PARTNER_LOG" + _recoveryTableNameSuffix + - (DBProduct.Sqlserver == dbProduct ? " WITH (ROWLOCK, UPDLOCK, HOLDLOCK)" : "") + - " WHERE RU_ID=-1" + - (DBProduct.Sqlserver == dbProduct ? "" : " FOR UPDATE"); - if (tc.isDebugEnabled()) - Tr.debug(tc, "Attempt to select the HA LOCKING ROW for UPDATE using - " + queryString); - lockingRS = lockingStmt.executeQuery(queryString); + String queryString = "SELECT RUSECTION_ID" + + " FROM " + _recoveryTableName + "PARTNER_LOG" + _recoveryTableNameSuffix + + (DBProduct.Sqlserver == dbProduct ? " WITH (ROWLOCK, UPDLOCK, HOLDLOCK)" : "") + + " WHERE RU_ID=-1" + + (DBProduct.Sqlserver == dbProduct ? "" : " FOR UPDATE"); + if (tc.isDebugEnabled()) + Tr.debug(tc, "Attempt to select the HA LOCKING ROW for UPDATE using - " + queryString); + try (Statement lockingStmt = conn.createStatement(); ResultSet lockingRS = lockingStmt.executeQuery(queryString)) { if (lockingRS.next()) { // We found the HA Lock row long storedTimestamp = lockingRS.getLong(1); @@ -4308,12 +4268,8 @@ public void internalHeartBeat(Connection conn) throws SQLException { if (tc.isDebugEnabled()) Tr.debug(tc, "Could not find HA Lock row, unable to update timestamp"); } - } finally { - if (lockingRS != null && !lockingRS.isClosed()) - lockingRS.close(); - if (lockingStmt != null && !lockingStmt.isClosed()) - lockingStmt.close(); } + if (tc.isEntryEnabled()) Tr.exit(tc, "internalHeartBeat"); } @@ -4882,7 +4838,7 @@ public void retryCode(Connection conn) throws SQLException, Exception { if (_serverStopping) { Tr.debug(tc, "Server is stopping will not claim logs"); } else { - int initialIsolation = prepareConnectionForBatch(conn); + prepareConnectionForBatch(conn); assertDBTableExists(conn, "PARTNER_LOG"); assertDBTableExists(conn, "TRAN_LOG"); diff --git a/dev/com.ibm.rls.jdbc/src/com/ibm/ws/recoverylog/custom/jdbc/impl/SQLSharedServerLeaseLog.java b/dev/com.ibm.rls.jdbc/src/com/ibm/ws/recoverylog/custom/jdbc/impl/SQLSharedServerLeaseLog.java index 50ede1840bc..e2f63b66af6 100644 --- a/dev/com.ibm.rls.jdbc/src/com/ibm/ws/recoverylog/custom/jdbc/impl/SQLSharedServerLeaseLog.java +++ b/dev/com.ibm.rls.jdbc/src/com/ibm/ws/recoverylog/custom/jdbc/impl/SQLSharedServerLeaseLog.java @@ -938,11 +938,7 @@ private void createLeaseTable(Connection conn) throws SQLException { if (tc.isEntryEnabled()) Tr.entry(tc, "createLeaseTable", conn, this); - Statement createTableStmt = null; - - try { - createTableStmt = conn.createStatement(); - + try (Statement createTableStmt = conn.createStatement()) { if (DBProduct.Oracle == dbProduct) { String oracleTableString = oracleTablePreString + _leaseTableName + oracleTablePostString; if (tc.isDebugEnabled()) @@ -984,11 +980,6 @@ private void createLeaseTable(Connection conn) throws SQLException { // Create index on the new table createTableStmt.execute(genericIndexString); } - - } finally { - if (createTableStmt != null && !createTableStmt.isClosed()) { - createTableStmt.close(); - } } if (tc.isEntryEnabled()) From 3cc145b19b4d2d6e434841a0fed193df06bc931e Mon Sep 17 00:00:00 2001 From: Joe Chacko <143064+joe-chacko@users.noreply.github.com> Date: Wed, 13 Nov 2024 16:42:42 +0000 Subject: [PATCH 43/67] style: whitespace --- .../publish/servers/jakartaee8/bootstrap.properties | 2 +- .../publish/servers/jakartaee8/server.xml | 2 +- .../internal/monitor_fat/BaseTestClass.java | 12 ++++++------ .../monitor_fat/ConnectionPoolMetricsTest.java | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/dev/com.ibm.ws.kernel.feature.resolver_fat/publish/servers/jakartaee8/bootstrap.properties b/dev/com.ibm.ws.kernel.feature.resolver_fat/publish/servers/jakartaee8/bootstrap.properties index 035182ebc1f..79059d111e2 100644 --- a/dev/com.ibm.ws.kernel.feature.resolver_fat/publish/servers/jakartaee8/bootstrap.properties +++ b/dev/com.ibm.ws.kernel.feature.resolver_fat/publish/servers/jakartaee8/bootstrap.properties @@ -4,7 +4,7 @@ # are made available under the terms of the Eclipse Public License 2.0 # which accompanies this distribution, and is available at # http://www.eclipse.org/legal/epl-2.0/ -# +# # SPDX-License-Identifier: EPL-2.0 # # Contributors: diff --git a/dev/com.ibm.ws.kernel.feature.resolver_fat/publish/servers/jakartaee8/server.xml b/dev/com.ibm.ws.kernel.feature.resolver_fat/publish/servers/jakartaee8/server.xml index dd40f7eefa6..0e19a5ba2e2 100644 --- a/dev/com.ibm.ws.kernel.feature.resolver_fat/publish/servers/jakartaee8/server.xml +++ b/dev/com.ibm.ws.kernel.feature.resolver_fat/publish/servers/jakartaee8/server.xml @@ -6,7 +6,7 @@ http://www.eclipse.org/legal/epl-2.0/ SPDX-License-Identifier: EPL-2.0 - + Contributors: IBM Corporation - initial API and implementation --> diff --git a/dev/io.openliberty.microprofile.telemetry.internal.monitor_fat/fat/src/io/openliberty/microprofile/telemetry/internal/monitor_fat/BaseTestClass.java b/dev/io.openliberty.microprofile.telemetry.internal.monitor_fat/fat/src/io/openliberty/microprofile/telemetry/internal/monitor_fat/BaseTestClass.java index f6828649d1b..bb47d3a0c18 100644 --- a/dev/io.openliberty.microprofile.telemetry.internal.monitor_fat/fat/src/io/openliberty/microprofile/telemetry/internal/monitor_fat/BaseTestClass.java +++ b/dev/io.openliberty.microprofile.telemetry.internal.monitor_fat/fat/src/io/openliberty/microprofile/telemetry/internal/monitor_fat/BaseTestClass.java @@ -105,9 +105,9 @@ protected void checkStrings(String metricsText, String[] expectedString) { * @param expectedString String array of expected strings */ protected void matchStringsWithRetries(Supplier metricsOutput, String[] expectedString) throws InterruptedException { - matchStringsWithRetries(metricsOutput, expectedString, 5); + matchStringsWithRetries(metricsOutput, expectedString, 5); } - + /** * Waits one second before checking the condition. Will wait 1 second for every retry amount. * @@ -126,16 +126,16 @@ protected void matchStringsWithRetries(Supplier metricsOutput, String[] Log.info(c, "assertTrueRetryWithTimeout", String.format("It took %d retries and %d seconds of waiting to be succesful)", x, (x + 1))); return; } - + } Assert.fail(String.format("Failed to find all expected strings. The /metrics output is:\n%s", metricsString)); - + } private static BiFunction doMatching = (metricsText, expectedString) -> { - + for (String m : expectedString) { try (Scanner sc = new Scanner(metricsText)) { boolean isFound = false; @@ -197,5 +197,5 @@ protected String requestHttpServlet(String servletPath, LibertyServer server, St con.disconnect(); } - } + } } diff --git a/dev/io.openliberty.microprofile.telemetry.internal.monitor_fat/fat/src/io/openliberty/microprofile/telemetry/internal/monitor_fat/ConnectionPoolMetricsTest.java b/dev/io.openliberty.microprofile.telemetry.internal.monitor_fat/fat/src/io/openliberty/microprofile/telemetry/internal/monitor_fat/ConnectionPoolMetricsTest.java index 3cba1b6c60a..0494d531ac9 100644 --- a/dev/io.openliberty.microprofile.telemetry.internal.monitor_fat/fat/src/io/openliberty/microprofile/telemetry/internal/monitor_fat/ConnectionPoolMetricsTest.java +++ b/dev/io.openliberty.microprofile.telemetry.internal.monitor_fat/fat/src/io/openliberty/microprofile/telemetry/internal/monitor_fat/ConnectionPoolMetricsTest.java @@ -96,7 +96,7 @@ public void connectionPoolTest() throws Exception { Log.info(c, testName, "------- connectionpool metrics should be available ------"); // Allow time for the collector to receive and expose metrics - matchStringsWithRetries(() -> getContainerCollectorMetrics(container), + matchStringsWithRetries(() -> getContainerCollectorMetrics(container), new String[] { "io_openliberty_connection_pool_handle_count\\{instance=\"[a-zA-Z0-9-]*\",io_openliberty_datasource_name=\"jdbc/exampleDS1\",job=\"unknown_service\"\\}.*", "io_openliberty_connection_pool_connection_free\\{instance=\"[a-zA-Z0-9-]*\",io_openliberty_datasource_name=\"jdbc/exampleDS1\",job=\"unknown_service\"\\}.*", "io_openliberty_connection_pool_connection_destroyed_total\\{instance=\"[a-zA-Z0-9-]*\",io_openliberty_datasource_name=\"jdbc/exampleDS1\",job=\"unknown_service\"\\}.*", From 9ad0b05eab25d5f9996f6a6fa1310ee33f0ee54b Mon Sep 17 00:00:00 2001 From: Joe Chacko <143064+joe-chacko@users.noreply.github.com> Date: Wed, 13 Nov 2024 17:08:05 +0000 Subject: [PATCH 44/67] style: newlines --- .../src/com/ibm/ws/recoverylog/custom/jdbc/impl/DBUtils.java | 2 +- .../publish/servers/jakartaee8/server.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dev/com.ibm.rls.jdbc/src/com/ibm/ws/recoverylog/custom/jdbc/impl/DBUtils.java b/dev/com.ibm.rls.jdbc/src/com/ibm/ws/recoverylog/custom/jdbc/impl/DBUtils.java index 4519da303c7..a5ff7872169 100644 --- a/dev/com.ibm.rls.jdbc/src/com/ibm/ws/recoverylog/custom/jdbc/impl/DBUtils.java +++ b/dev/com.ibm.rls.jdbc/src/com/ibm/ws/recoverylog/custom/jdbc/impl/DBUtils.java @@ -39,4 +39,4 @@ public static DBProduct identifyDB(Connection conn) throws SQLException { return DBProduct.Unknown; } } -} \ No newline at end of file +} diff --git a/dev/com.ibm.ws.kernel.feature.resolver_fat/publish/servers/jakartaee8/server.xml b/dev/com.ibm.ws.kernel.feature.resolver_fat/publish/servers/jakartaee8/server.xml index 0e19a5ba2e2..101dcc2ccff 100644 --- a/dev/com.ibm.ws.kernel.feature.resolver_fat/publish/servers/jakartaee8/server.xml +++ b/dev/com.ibm.ws.kernel.feature.resolver_fat/publish/servers/jakartaee8/server.xml @@ -20,4 +20,4 @@ - \ No newline at end of file + From 0c661ca281f6017a74bf438699ec974b9c31b8d2 Mon Sep 17 00:00:00 2001 From: Jon Hawkes Date: Tue, 19 Nov 2024 16:36:19 +0000 Subject: [PATCH 45/67] dbProduct must be volatile --- .../recoverylog/custom/jdbc/impl/SQLMultiScopeRecoveryLog.java | 2 +- .../recoverylog/custom/jdbc/impl/SQLSharedServerLeaseLog.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dev/com.ibm.rls.jdbc/src/com/ibm/ws/recoverylog/custom/jdbc/impl/SQLMultiScopeRecoveryLog.java b/dev/com.ibm.rls.jdbc/src/com/ibm/ws/recoverylog/custom/jdbc/impl/SQLMultiScopeRecoveryLog.java index 6433e625478..5bc05c74932 100644 --- a/dev/com.ibm.rls.jdbc/src/com/ibm/ws/recoverylog/custom/jdbc/impl/SQLMultiScopeRecoveryLog.java +++ b/dev/com.ibm.rls.jdbc/src/com/ibm/ws/recoverylog/custom/jdbc/impl/SQLMultiScopeRecoveryLog.java @@ -144,7 +144,7 @@ public class SQLMultiScopeRecoveryLog implements LogCursorCallback, MultiScopeLo /** * Which RDBMS are we working against? */ - private DBProduct dbProduct; + volatile private DBProduct dbProduct; private boolean isolationFailureReported; diff --git a/dev/com.ibm.rls.jdbc/src/com/ibm/ws/recoverylog/custom/jdbc/impl/SQLSharedServerLeaseLog.java b/dev/com.ibm.rls.jdbc/src/com/ibm/ws/recoverylog/custom/jdbc/impl/SQLSharedServerLeaseLog.java index e2f63b66af6..5716236c17d 100644 --- a/dev/com.ibm.rls.jdbc/src/com/ibm/ws/recoverylog/custom/jdbc/impl/SQLSharedServerLeaseLog.java +++ b/dev/com.ibm.rls.jdbc/src/com/ibm/ws/recoverylog/custom/jdbc/impl/SQLSharedServerLeaseLog.java @@ -70,7 +70,7 @@ public class SQLSharedServerLeaseLog extends LeaseLogImpl implements SharedServe /** * Which RDBMS are we working against? */ - private DBProduct dbProduct; + volatile private DBProduct dbProduct; volatile private boolean _leaseTableExists; private boolean _sqlTransientErrorHandlingEnabled = true; From 383d21854c871eac061c7b588ccfc29a00e7b049 Mon Sep 17 00:00:00 2001 From: Joe Chacko <143064+joe-chacko@users.noreply.github.com> Date: Tue, 19 Nov 2024 17:22:09 +0000 Subject: [PATCH 46/67] style: fix whitespace --- .../servers/com.ibm.ws.kernel.active.condition/server.xml | 2 +- dev/com.ibm.ws.kernel.feature_fat/test.active.condition.bnd | 2 +- .../telemetry/internal/monitor_fat/BaseTestClass.java | 2 +- .../internal/monitor_fat/ConnectionPoolMetricsTest.java | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dev/com.ibm.ws.kernel.feature_fat/publish/servers/com.ibm.ws.kernel.active.condition/server.xml b/dev/com.ibm.ws.kernel.feature_fat/publish/servers/com.ibm.ws.kernel.active.condition/server.xml index 2a2c6d0a55d..a937993a6c2 100755 --- a/dev/com.ibm.ws.kernel.feature_fat/publish/servers/com.ibm.ws.kernel.active.condition/server.xml +++ b/dev/com.ibm.ws.kernel.feature_fat/publish/servers/com.ibm.ws.kernel.active.condition/server.xml @@ -5,5 +5,5 @@ test.active.condition-1.0 - + diff --git a/dev/com.ibm.ws.kernel.feature_fat/test.active.condition.bnd b/dev/com.ibm.ws.kernel.feature_fat/test.active.condition.bnd index d4ec46b727a..8a976dab9e8 100644 --- a/dev/com.ibm.ws.kernel.feature_fat/test.active.condition.bnd +++ b/dev/com.ibm.ws.kernel.feature_fat/test.active.condition.bnd @@ -4,7 +4,7 @@ # are made available under the terms of the Eclipse Public License 2.0 # which accompanies this distribution, and is available at # http://www.eclipse.org/legal/epl-2.0/ -# +# # SPDX-License-Identifier: EPL-2.0 # # Contributors: diff --git a/dev/io.openliberty.microprofile.telemetry.internal.monitor_fat/fat/src/io/openliberty/microprofile/telemetry/internal/monitor_fat/BaseTestClass.java b/dev/io.openliberty.microprofile.telemetry.internal.monitor_fat/fat/src/io/openliberty/microprofile/telemetry/internal/monitor_fat/BaseTestClass.java index bb47d3a0c18..780b33d046b 100644 --- a/dev/io.openliberty.microprofile.telemetry.internal.monitor_fat/fat/src/io/openliberty/microprofile/telemetry/internal/monitor_fat/BaseTestClass.java +++ b/dev/io.openliberty.microprofile.telemetry.internal.monitor_fat/fat/src/io/openliberty/microprofile/telemetry/internal/monitor_fat/BaseTestClass.java @@ -133,7 +133,7 @@ protected void matchStringsWithRetries(Supplier metricsOutput, String[] } - + private static BiFunction doMatching = (metricsText, expectedString) -> { for (String m : expectedString) { diff --git a/dev/io.openliberty.microprofile.telemetry.internal.monitor_fat/fat/src/io/openliberty/microprofile/telemetry/internal/monitor_fat/ConnectionPoolMetricsTest.java b/dev/io.openliberty.microprofile.telemetry.internal.monitor_fat/fat/src/io/openliberty/microprofile/telemetry/internal/monitor_fat/ConnectionPoolMetricsTest.java index 0494d531ac9..63cad61abea 100644 --- a/dev/io.openliberty.microprofile.telemetry.internal.monitor_fat/fat/src/io/openliberty/microprofile/telemetry/internal/monitor_fat/ConnectionPoolMetricsTest.java +++ b/dev/io.openliberty.microprofile.telemetry.internal.monitor_fat/fat/src/io/openliberty/microprofile/telemetry/internal/monitor_fat/ConnectionPoolMetricsTest.java @@ -94,7 +94,7 @@ public void connectionPoolTest() throws Exception { checkStrings(requestHttpServlet("/testJDBCApp/testJDBCServlet?operation=create", server), new String[] { "sql: create table cities" }); Log.info(c, testName, "------- connectionpool metrics should be available ------"); - + // Allow time for the collector to receive and expose metrics matchStringsWithRetries(() -> getContainerCollectorMetrics(container), new String[] { "io_openliberty_connection_pool_handle_count\\{instance=\"[a-zA-Z0-9-]*\",io_openliberty_datasource_name=\"jdbc/exampleDS1\",job=\"unknown_service\"\\}.*", From 64873f74d7597ed4028ac9457f4a793da095ef3d Mon Sep 17 00:00:00 2001 From: Joe Chacko <143064+joe-chacko@users.noreply.github.com> Date: Tue, 19 Nov 2024 17:28:29 +0000 Subject: [PATCH 47/67] style: order modifiers --- .../custom/jdbc/impl/SQLMultiScopeRecoveryLog.java | 4 ++-- .../recoverylog/custom/jdbc/impl/SQLSharedServerLeaseLog.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dev/com.ibm.rls.jdbc/src/com/ibm/ws/recoverylog/custom/jdbc/impl/SQLMultiScopeRecoveryLog.java b/dev/com.ibm.rls.jdbc/src/com/ibm/ws/recoverylog/custom/jdbc/impl/SQLMultiScopeRecoveryLog.java index 5bc05c74932..3425ab88b01 100644 --- a/dev/com.ibm.rls.jdbc/src/com/ibm/ws/recoverylog/custom/jdbc/impl/SQLMultiScopeRecoveryLog.java +++ b/dev/com.ibm.rls.jdbc/src/com/ibm/ws/recoverylog/custom/jdbc/impl/SQLMultiScopeRecoveryLog.java @@ -144,7 +144,7 @@ public class SQLMultiScopeRecoveryLog implements LogCursorCallback, MultiScopeLo /** * Which RDBMS are we working against? */ - volatile private DBProduct dbProduct; + private volatile DBProduct dbProduct; private boolean isolationFailureReported; @@ -223,7 +223,7 @@ public class SQLMultiScopeRecoveryLog implements LogCursorCallback, MultiScopeLo * A flag to indicate that the log was being recovered by a peer * but it has been reclaimed by its "home" server. */ - volatile private boolean _peerServerLostLogOwnership; + private volatile boolean _peerServerLostLogOwnership; /** * These strings are used for Database table creation. DDL is diff --git a/dev/com.ibm.rls.jdbc/src/com/ibm/ws/recoverylog/custom/jdbc/impl/SQLSharedServerLeaseLog.java b/dev/com.ibm.rls.jdbc/src/com/ibm/ws/recoverylog/custom/jdbc/impl/SQLSharedServerLeaseLog.java index 5716236c17d..8d49e061a74 100644 --- a/dev/com.ibm.rls.jdbc/src/com/ibm/ws/recoverylog/custom/jdbc/impl/SQLSharedServerLeaseLog.java +++ b/dev/com.ibm.rls.jdbc/src/com/ibm/ws/recoverylog/custom/jdbc/impl/SQLSharedServerLeaseLog.java @@ -70,9 +70,9 @@ public class SQLSharedServerLeaseLog extends LeaseLogImpl implements SharedServe /** * Which RDBMS are we working against? */ - volatile private DBProduct dbProduct; + private volatile DBProduct dbProduct; - volatile private boolean _leaseTableExists; + private volatile boolean _leaseTableExists; private boolean _sqlTransientErrorHandlingEnabled = true; private boolean _logRetriesEnabled; private int _leaseTimeout; From 648e1c467b7101af1cd6d04526ff734ca7dc1643 Mon Sep 17 00:00:00 2001 From: Andrew Rouse Date: Tue, 19 Nov 2024 17:41:05 +0000 Subject: [PATCH 48/67] OpenAPI: Don't use default ports for CacheTest CacheTest was using ApplicationProcessorServer which expects the test to manually set the ports. Use a different generic mpOpenAPI server instead. --- .../openliberty/microprofile/openapi20/fat/cache/CacheTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/io.openliberty.microprofile.openapi.2.0.internal_fat/fat/src/io/openliberty/microprofile/openapi20/fat/cache/CacheTest.java b/dev/io.openliberty.microprofile.openapi.2.0.internal_fat/fat/src/io/openliberty/microprofile/openapi20/fat/cache/CacheTest.java index 48ad6024129..27a694df515 100644 --- a/dev/io.openliberty.microprofile.openapi.2.0.internal_fat/fat/src/io/openliberty/microprofile/openapi20/fat/cache/CacheTest.java +++ b/dev/io.openliberty.microprofile.openapi.2.0.internal_fat/fat/src/io/openliberty/microprofile/openapi20/fat/cache/CacheTest.java @@ -44,7 +44,7 @@ @RunWith(FATRunner.class) public class CacheTest { - private static final String SERVER_NAME = "ApplicationProcessorServer"; + private static final String SERVER_NAME = "OpenAPITestServer"; @Server(SERVER_NAME) public static LibertyServer server; From 7ae2ad96f5d02169c04e7bb0c24870ecd65eaa24 Mon Sep 17 00:00:00 2001 From: Thomas Watson Date: Tue, 19 Nov 2024 12:48:59 -0600 Subject: [PATCH 49/67] Remove read-write lock for bundle context access Use constructor injection to allow final fields. This removes the need for a lock on accessing the context and there is no need to null out the references to deactivate. --- .../ConnectorModuleRuntimeContainer.java | 136 +++++------------- 1 file changed, 39 insertions(+), 97 deletions(-) diff --git a/dev/com.ibm.ws.jca/src/com/ibm/ws/jca/internal/ConnectorModuleRuntimeContainer.java b/dev/com.ibm.ws.jca/src/com/ibm/ws/jca/internal/ConnectorModuleRuntimeContainer.java index 3eeb8b59bdb..c04fbd467fd 100644 --- a/dev/com.ibm.ws.jca/src/com/ibm/ws/jca/internal/ConnectorModuleRuntimeContainer.java +++ b/dev/com.ibm.ws.jca/src/com/ibm/ws/jca/internal/ConnectorModuleRuntimeContainer.java @@ -1,10 +1,10 @@ /******************************************************************************* - * Copyright (c) 2013, 2014 IBM Corporation and others. + * Copyright (c) 2013, 2024 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * * Contributors: @@ -22,7 +22,6 @@ import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; -import java.util.concurrent.locks.ReentrantReadWriteLock; import javax.resource.spi.BootstrapContext; @@ -34,7 +33,7 @@ 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.ConfigurationPolicy; import org.osgi.service.component.annotations.Reference; @@ -64,18 +63,13 @@ public class ConnectorModuleRuntimeContainer implements ModuleRuntimeContainer { private static final TraceComponent tc = Tr.register(ConnectorModuleRuntimeContainer.class); - private BundleContext bundleContext = null; + private final BundleContext bundleContext; - private ConfigurationAdmin configAdmin; + private final ConfigurationAdmin configAdmin; - private FutureMonitor futureMonitor; + private final FutureMonitor futureMonitor; - /** - * Read/write lock for bundleContext - */ - private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); - - private MetaDataService metaDataService; + private final MetaDataService metaDataService; private final ConcurrentHashMap moduleMetatype = new ConcurrentHashMap();; @@ -84,50 +78,17 @@ public class ConnectorModuleRuntimeContainer implements ModuleRuntimeContainer { */ private final ConcurrentHashMap serviceListeners = new ConcurrentHashMap(); - protected void activate(ComponentContext context) { - lock.writeLock().lock(); - try { - bundleContext = Utils.priv.getBundleContext(context); - } finally { - lock.writeLock().unlock(); - } - } - - protected void deactivate(ComponentContext context) { - lock.writeLock().lock(); - try { - bundleContext = null; - } finally { - lock.writeLock().unlock(); - } - } - - @Reference - protected void setConfigurationAdmin(ConfigurationAdmin configAdmin) { + @Activate + public ConnectorModuleRuntimeContainer(BundleContext bundleContext, // + @Reference ConfigurationAdmin configAdmin, + @Reference FutureMonitor futureMonitor, + @Reference MetaDataService metaDataService) { + this.bundleContext = bundleContext; this.configAdmin = configAdmin; - } - - protected void unsetConfigurationAdmin(ConfigurationAdmin configAdmin) { - this.configAdmin = null; - } - - @Reference(name = "futureMonitor") - protected void setFutureMonitor(FutureMonitor futureMonitor) { this.futureMonitor = futureMonitor; - } - - protected void unsetFutureMonitor(FutureMonitor futureMonitor) { - this.futureMonitor = null; - } - - @Reference(name = "metaDataService") - protected void setMetaDataService(MetaDataService metaDataService) { this.metaDataService = metaDataService; } - protected void unsetMetaDataService(MetaDataService metaDataService) { - } - /* * (non-Javadoc) * @@ -152,17 +113,13 @@ public ModuleMetaData createModuleMetaData(ExtendedModuleInfo moduleInfo) throws */ private void removeServiceListeners(String id) { final ServiceListener[] listeners = serviceListeners.remove(id); - if (listeners != null) - for (ServiceListener listener : listeners) + if (listeners != null) { + for (ServiceListener listener : listeners) { if (listener != null) { - lock.readLock().lock(); - try { - if (bundleContext != null) - bundleContext.removeServiceListener(listener); - } finally { - lock.readLock().unlock(); - } + bundleContext.removeServiceListener(listener); } + } + } } private class RARInstallListener implements ServiceListener { @@ -227,31 +184,25 @@ private RARInstallListener(String id, String bootstrapContextFactoryPid, boolean final ServiceListener[] listeners = new ServiceListener[4]; serviceListeners.put(id, listeners); - lock.readLock().lock(); - try { - if (bundleContext != null) { - // properties for resourceAdapter - bundleContext.addServiceListener(listeners[0] = this, - "(&(objectClass=ja*.resource.spi.BootstrapContext)(id=" + id + "))"); - - // properties for adminObject, jmsDestination, jmsQueue, jmsTopic - bundleContext.addServiceListener(listeners[1] = new ResourceListener(), - "(&(objectClass=com.ibm.ws.jca.service.AdminObjectService)(properties.0.config.referenceType=com.ibm.ws.jca.*.properties." - + id + ".*))"); - - // properties for connectionFactory, jmsConnectionFactory, jmsQueueConnectionFactory, jmsTopicConnectionFactory - bundleContext.addServiceListener(listeners[2] = new ResourceListener(), - "(&(objectClass=com.ibm.ws.jca.service.ConnectionFactoryService)(properties.0.config.referenceType=com.ibm.ws.jca.*onnectionFactory.properties." - + id + ".*))"); - - // properties for activationSpec, jmsActivationSpec - bundleContext.addServiceListener(listeners[3] = new ResourceListener(), - "(&(objectClass=com.ibm.ws.jca.service.EndpointActivationService)(properties.0.config.referenceType=com.ibm.ws.jca.*ctivationSpec.properties." - + id + ".*))"); - } - } finally { - lock.readLock().unlock(); - } + // properties for resourceAdapter + bundleContext.addServiceListener(listeners[0] = this, + "(&(objectClass=ja*.resource.spi.BootstrapContext)(id=" + id + "))"); + + // properties for adminObject, jmsDestination, jmsQueue, jmsTopic + bundleContext.addServiceListener(listeners[1] = new ResourceListener(), + "(&(objectClass=com.ibm.ws.jca.service.AdminObjectService)(properties.0.config.referenceType=com.ibm.ws.jca.*.properties." + + id + ".*))"); + + // properties for connectionFactory, jmsConnectionFactory, jmsQueueConnectionFactory, jmsTopicConnectionFactory + bundleContext.addServiceListener(listeners[2] = new ResourceListener(), + "(&(objectClass=com.ibm.ws.jca.service.ConnectionFactoryService)(properties.0.config.referenceType=com.ibm.ws.jca.*onnectionFactory.properties." + + id + ".*))"); + + // properties for activationSpec, jmsActivationSpec + bundleContext.addServiceListener(listeners[3] = new ResourceListener(), + "(&(objectClass=com.ibm.ws.jca.service.EndpointActivationService)(properties.0.config.referenceType=com.ibm.ws.jca.*ctivationSpec.properties." + + id + ".*))"); + } /** @@ -282,13 +233,9 @@ public void serviceChanged(ServiceEvent event) { if ("com.ibm.ws.jca.resourceAdapter.properties".equals(pid)) { latch.countDown(); if (autoStart) { - lock.readLock().lock(); try { - if (bundleContext != null) - Utils.priv.getService(bundleContext, event.getServiceReference()); + Utils.priv.getService(bundleContext, event.getServiceReference()); } catch (Throwable x) { - } finally { - lock.readLock().unlock(); } } } else { @@ -403,12 +350,7 @@ public Future startModule(ExtendedModuleInfo moduleInfo) throws StateCh try { Collection> refs; - lock.readLock().lock(); - try { - refs = bundleContext == null ? null : Utils.priv.getServiceReferences(bundleContext, BootstrapContext.class, "(id=" + id + ')'); - } finally { - lock.readLock().unlock(); - } + refs = Utils.priv.getServiceReferences(bundleContext, BootstrapContext.class, "(id=" + id + ')'); if (refs == null || refs.isEmpty()) { FFDCFilter.processException(x, getClass().getName(), "420", this, new Object[] { id, bootstrapContextFactoryPid }); futureMonitor.setResult(rarInstallListener.future, x); From d07e9168c3d7d26e6b58b43d728aa6b20def2ffb Mon Sep 17 00:00:00 2001 From: Wendy Raschke Date: Tue, 19 Nov 2024 15:14:43 -0600 Subject: [PATCH 50/67] Restore fake product code changes for testing only --- .../jbatch/container/internal/resources/JBatchMessages.nlsprops | 2 ++ .../public/xmlWS-4.0/io.openliberty.xmlWS-4.0.feature | 2 ++ .../resources/l10n/io.openliberty.xmlWS-4.0.properties | 2 ++ 3 files changed, 6 insertions(+) diff --git a/dev/com.ibm.jbatch.container/resources/com/ibm/jbatch/container/internal/resources/JBatchMessages.nlsprops b/dev/com.ibm.jbatch.container/resources/com/ibm/jbatch/container/internal/resources/JBatchMessages.nlsprops index da3e373661c..45d150ae57a 100644 --- a/dev/com.ibm.jbatch.container/resources/com/ibm/jbatch/container/internal/resources/JBatchMessages.nlsprops +++ b/dev/com.ibm.jbatch.container/resources/com/ibm/jbatch/container/internal/resources/JBatchMessages.nlsprops @@ -1,3 +1,5 @@ +# Test commit only. +# ############################################################################### # Copyright (c) 2014 IBM Corporation and others. # All rights reserved. This program and the accompanying materials diff --git a/dev/com.ibm.websphere.appserver.features/visibility/public/xmlWS-4.0/io.openliberty.xmlWS-4.0.feature b/dev/com.ibm.websphere.appserver.features/visibility/public/xmlWS-4.0/io.openliberty.xmlWS-4.0.feature index b14f6ab620e..285af2286aa 100644 --- a/dev/com.ibm.websphere.appserver.features/visibility/public/xmlWS-4.0/io.openliberty.xmlWS-4.0.feature +++ b/dev/com.ibm.websphere.appserver.features/visibility/public/xmlWS-4.0/io.openliberty.xmlWS-4.0.feature @@ -1,3 +1,5 @@ +# Test commit only. +# -include= ~${workspace}/cnf/resources/bnd/feature.props symbolicName=io.openliberty.xmlWS-4.0 visibility=public diff --git a/dev/com.ibm.websphere.appserver.features/visibility/public/xmlWS-4.0/resources/l10n/io.openliberty.xmlWS-4.0.properties b/dev/com.ibm.websphere.appserver.features/visibility/public/xmlWS-4.0/resources/l10n/io.openliberty.xmlWS-4.0.properties index 390c091c87b..9f4a2315097 100644 --- a/dev/com.ibm.websphere.appserver.features/visibility/public/xmlWS-4.0/resources/l10n/io.openliberty.xmlWS-4.0.properties +++ b/dev/com.ibm.websphere.appserver.features/visibility/public/xmlWS-4.0/resources/l10n/io.openliberty.xmlWS-4.0.properties @@ -1,3 +1,5 @@ +# Test commit only. +# ############################################################################### # Copyright (c) 2020,2021 IBM Corporation and others. # All rights reserved. This program and the accompanying materials From c22642bb873c5aed391bf074c6be56a55c6fd659 Mon Sep 17 00:00:00 2001 From: Smitha Subbarao Date: Tue, 19 Nov 2024 16:27:50 -0600 Subject: [PATCH 51/67] Update Batch Checkpoint files with Copyright headers --- .../batch/fat/junit/DynamicConfigRuleCheckpoint.java | 2 +- .../fat/src/batch/fat/junit/FATSuite.java | 2 +- .../batch/fat/junit/JdbcConfigTestCheckpoint.java | 12 ++++++++++++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/dev/com.ibm.ws.jbatch.open_fat/fat/src/batch/fat/junit/DynamicConfigRuleCheckpoint.java b/dev/com.ibm.ws.jbatch.open_fat/fat/src/batch/fat/junit/DynamicConfigRuleCheckpoint.java index d5c2b7c1ca8..e6298127897 100644 --- a/dev/com.ibm.ws.jbatch.open_fat/fat/src/batch/fat/junit/DynamicConfigRuleCheckpoint.java +++ b/dev/com.ibm.ws.jbatch.open_fat/fat/src/batch/fat/junit/DynamicConfigRuleCheckpoint.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2014, 2020 IBM Corporation and others. + * Copyright (c) 2014, 2024 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at diff --git a/dev/com.ibm.ws.jbatch.open_fat/fat/src/batch/fat/junit/FATSuite.java b/dev/com.ibm.ws.jbatch.open_fat/fat/src/batch/fat/junit/FATSuite.java index 1ced2355142..605a3f056e2 100644 --- a/dev/com.ibm.ws.jbatch.open_fat/fat/src/batch/fat/junit/FATSuite.java +++ b/dev/com.ibm.ws.jbatch.open_fat/fat/src/batch/fat/junit/FATSuite.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012, 2022 IBM Corporation and others. + * Copyright (c) 2012, 2024 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at diff --git a/dev/com.ibm.ws.jbatch.open_fat/fat/src/batch/fat/junit/JdbcConfigTestCheckpoint.java b/dev/com.ibm.ws.jbatch.open_fat/fat/src/batch/fat/junit/JdbcConfigTestCheckpoint.java index 71fb8209605..3bb4f1daaae 100644 --- a/dev/com.ibm.ws.jbatch.open_fat/fat/src/batch/fat/junit/JdbcConfigTestCheckpoint.java +++ b/dev/com.ibm.ws.jbatch.open_fat/fat/src/batch/fat/junit/JdbcConfigTestCheckpoint.java @@ -1,3 +1,15 @@ +/******************************************************************************* + * Copyright (c) 2024 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ package batch.fat.junit; import java.util.Collections; From 51811cfdfccefd7d43638326ce5d572b7d0800f7 Mon Sep 17 00:00:00 2001 From: Wendy Raschke Date: Tue, 19 Nov 2024 18:05:29 -0600 Subject: [PATCH 52/67] Restore simulated product code changes to original state --- .../jbatch/container/internal/resources/JBatchMessages.nlsprops | 2 -- .../public/xmlWS-4.0/io.openliberty.xmlWS-4.0.feature | 2 -- .../resources/l10n/io.openliberty.xmlWS-4.0.properties | 2 -- 3 files changed, 6 deletions(-) diff --git a/dev/com.ibm.jbatch.container/resources/com/ibm/jbatch/container/internal/resources/JBatchMessages.nlsprops b/dev/com.ibm.jbatch.container/resources/com/ibm/jbatch/container/internal/resources/JBatchMessages.nlsprops index 45d150ae57a..da3e373661c 100644 --- a/dev/com.ibm.jbatch.container/resources/com/ibm/jbatch/container/internal/resources/JBatchMessages.nlsprops +++ b/dev/com.ibm.jbatch.container/resources/com/ibm/jbatch/container/internal/resources/JBatchMessages.nlsprops @@ -1,5 +1,3 @@ -# Test commit only. -# ############################################################################### # Copyright (c) 2014 IBM Corporation and others. # All rights reserved. This program and the accompanying materials diff --git a/dev/com.ibm.websphere.appserver.features/visibility/public/xmlWS-4.0/io.openliberty.xmlWS-4.0.feature b/dev/com.ibm.websphere.appserver.features/visibility/public/xmlWS-4.0/io.openliberty.xmlWS-4.0.feature index 285af2286aa..b14f6ab620e 100644 --- a/dev/com.ibm.websphere.appserver.features/visibility/public/xmlWS-4.0/io.openliberty.xmlWS-4.0.feature +++ b/dev/com.ibm.websphere.appserver.features/visibility/public/xmlWS-4.0/io.openliberty.xmlWS-4.0.feature @@ -1,5 +1,3 @@ -# Test commit only. -# -include= ~${workspace}/cnf/resources/bnd/feature.props symbolicName=io.openliberty.xmlWS-4.0 visibility=public diff --git a/dev/com.ibm.websphere.appserver.features/visibility/public/xmlWS-4.0/resources/l10n/io.openliberty.xmlWS-4.0.properties b/dev/com.ibm.websphere.appserver.features/visibility/public/xmlWS-4.0/resources/l10n/io.openliberty.xmlWS-4.0.properties index 9f4a2315097..390c091c87b 100644 --- a/dev/com.ibm.websphere.appserver.features/visibility/public/xmlWS-4.0/resources/l10n/io.openliberty.xmlWS-4.0.properties +++ b/dev/com.ibm.websphere.appserver.features/visibility/public/xmlWS-4.0/resources/l10n/io.openliberty.xmlWS-4.0.properties @@ -1,5 +1,3 @@ -# Test commit only. -# ############################################################################### # Copyright (c) 2020,2021 IBM Corporation and others. # All rights reserved. This program and the accompanying materials From 847d78de4a19ec9921d8aa30d4cce311da8cf091 Mon Sep 17 00:00:00 2001 From: Luke Saker <29537386+sakerl@users.noreply.github.com> Date: Tue, 19 Nov 2024 12:18:06 +0000 Subject: [PATCH 53/67] Simplified API persistent tests use consolidated sender --- .../web/DeliveryDelayServlet.java | 118 ++++++++---------- 1 file changed, 49 insertions(+), 69 deletions(-) diff --git a/dev/com.ibm.ws.messaging.open_jms20deliverydelay_fat/test-applications/DeliveryDelay/src/deliverydelay/web/DeliveryDelayServlet.java b/dev/com.ibm.ws.messaging.open_jms20deliverydelay_fat/test-applications/DeliveryDelay/src/deliverydelay/web/DeliveryDelayServlet.java index abb8775aa9b..5a358d72322 100644 --- a/dev/com.ibm.ws.messaging.open_jms20deliverydelay_fat/test-applications/DeliveryDelay/src/deliverydelay/web/DeliveryDelayServlet.java +++ b/dev/com.ibm.ws.messaging.open_jms20deliverydelay_fat/test-applications/DeliveryDelay/src/deliverydelay/web/DeliveryDelayServlet.java @@ -1312,26 +1312,17 @@ private void testPersistentMessageSimplifiedAPI_send(ConnectionFactory cf, return; } + private String testPersistentQueueMessageIdentifier = "testPersistentQueueMessage"; public void testPersistentMessage( HttpServletRequest request, HttpServletResponse response) throws Exception { - - JMSContext jmsContext = jmsQCFBindings.createContext(); - JMSConsumer jmsConsumer = jmsContext.createConsumer(jmsQueue); - JMSProducer jmsProducer = jmsContext.createProducer(); - - emptyQueue(jmsQCFBindings, jmsQueue); - emptyQueue(jmsQCFBindings, jmsQueue1); - - jmsProducer.setDeliveryMode(DeliveryMode.PERSISTENT).setDeliveryDelay(1000); - - jmsProducer.send(jmsQueue, "testPersistentMessage_PersistentMsg"); - - jmsProducer.setDeliveryDelay(1000).setDeliveryMode(DeliveryMode.NON_PERSISTENT); - jmsProducer.send(jmsQueue1, "testPersistentMessage_NonPersistentMsg"); - - jmsConsumer.close(); - jmsContext.close(); + // Originally used message text "testPersistentMessage_PersistentMsg" "testPersistentMessage_NonPersistentMsg" + // jmsQCFBindings, jmsQueue, jmsQueue1 + + testPersistentMessageSimplifiedAPI_send(jmsQCFBindings, jmsQueue, jmsQueue1, testPersistentQueueMessageIdentifier); + + return; + } public void testPersistentMessageReceive( @@ -1349,7 +1340,7 @@ public void testPersistentMessageReceive( if ( ((recMsg1 == null) || (recMsg1.getText() == null) || - !recMsg1.getText().equals("testPersistentMessage_PersistentMsg")) || + !recMsg1.getText().equals("PersistentMessage_" + testPersistentQueueMessageIdentifier)) || (recMsg2 != null) ) { testFailed = true; } @@ -1363,23 +1354,16 @@ public void testPersistentMessageReceive( } } + private String testPersistentQueueMessageTcpIdentifier = "testPersistentQueueMessageTcp"; + public void testPersistentMessage_Tcp( HttpServletRequest request, HttpServletResponse response) throws Exception { + // Originally used message text "testPersistentMessage_PersistentMsgTcp" "testPersistentMessage_NonPersistentMsgTcp" + // jmsQCFTCP, jmsQueue, jmsQueue1 + + testPersistentMessageSimplifiedAPI_send(jmsQCFTCP, jmsQueue, jmsQueue1, testPersistentQueueMessageTcpIdentifier); - JMSContext jmsContext = jmsQCFTCP.createContext(); - JMSConsumer jmsConsumer = jmsContext.createConsumer(jmsQueue); - JMSProducer jmsProducer = jmsContext.createProducer(); - emptyQueue(jmsQCFTCP, jmsQueue); - emptyQueue(jmsQCFTCP, jmsQueue1); - - jmsProducer.setDeliveryMode(DeliveryMode.PERSISTENT).setDeliveryDelay(1000); - jmsProducer.send(jmsQueue, "testPersistentMessage_PersistentMsgTcp"); - - jmsProducer.setDeliveryDelay(1000).setDeliveryMode(DeliveryMode.NON_PERSISTENT); - jmsProducer.send(jmsQueue1, "testPersistentMessage_NonPersistentMsgTcp"); - - jmsConsumer.close(); - jmsContext.close(); + return; } public void testPersistentMessageReceive_Tcp( @@ -1397,7 +1381,7 @@ public void testPersistentMessageReceive_Tcp( if ( ((recMsg1 == null) || (recMsg1.getText() == null) || - !recMsg1.getText().equals("testPersistentMessage_PersistentMsgTcp")) || + !recMsg1.getText().equals("PersistentMessage_" + testPersistentQueueMessageTcpIdentifier)) || (recMsg2 != null) ) { testFailed = true; } @@ -1411,31 +1395,29 @@ public void testPersistentMessageReceive_Tcp( } } + private String testPersistentTopicMessageIdentifier = "testPersistentTopicMessage"; + public void testPersistentMessageTopic( HttpServletRequest request, HttpServletResponse response) throws Exception { + // Originally used message text "testPersistentMessage_PersistentMsgTopic" "testPersistentMessage_NonPersistentMsgTopic" + // jmsTCFBindings, jmsTopic, jmsTopic1 - JMSContext jmsContext = jmsTCFBindings.createContext(); - JMSConsumer jmsConsumer1 = jmsContext.createDurableConsumer(jmsTopic, "durPersMsg1"); - JMSConsumer jmsConsumer2 = jmsContext.createDurableConsumer(jmsTopic1, "durPersMsg2"); - JMSProducer jmsProducer = jmsContext.createProducer(); - - jmsProducer.setDeliveryMode(DeliveryMode.PERSISTENT) .setDeliveryDelay(1000); - jmsProducer.send(jmsTopic, "testPersistentMessage_PersistentMsgTopic"); - - jmsProducer.setDeliveryDelay(1000).setDeliveryMode(DeliveryMode.NON_PERSISTENT); - jmsProducer.send(jmsTopic1, "testPersistentMessage_NonPersistentMsgTopic"); - - // First half of test .. verification in the second half. + testPersistentMessageSimplifiedAPI_send(jmsTCFBindings, jmsTopic, jmsTopic1, testPersistentTopicMessageIdentifier); + + return; } public void testPersistentMessageReceiveTopic( HttpServletRequest request, HttpServletResponse response) throws Exception { boolean testFailed = false; + + String subscriber1Name = "durPersMsg1_" + testPersistentTopicMessageIdentifier; + String subscriber2Name = "durPersMsg2_" + testPersistentTopicMessageIdentifier; JMSContext jmsContext = jmsTCFBindings.createContext(); - JMSConsumer jmsConsumer1 = jmsContext.createDurableConsumer(jmsTopic, "durPersMsg1"); - JMSConsumer jmsConsumer2 = jmsContext.createDurableConsumer(jmsTopic1, "durPersMsg2"); + JMSConsumer jmsConsumer1 = jmsContext.createDurableConsumer(jmsTopic, subscriber1Name); + JMSConsumer jmsConsumer2 = jmsContext.createDurableConsumer(jmsTopic1, subscriber2Name); JMSProducer jmsProducer = jmsContext.createProducer(); TextMessage recMsg1 = (TextMessage) jmsConsumer1.receive(30000); @@ -1443,15 +1425,15 @@ public void testPersistentMessageReceiveTopic( if ( ((recMsg1 == null) || (recMsg1.getText() == null) || - !recMsg1.getText().equals("testPersistentMessage_PersistentMsgTopic")) || - (recMsg2 != null)) { + !recMsg1.getText().equals("PersistentMessage_" + testPersistentTopicMessageIdentifier)) || + (recMsg2 != null) ) { testFailed = true; } jmsConsumer1.close(); jmsConsumer2.close(); - jmsContext.unsubscribe("durPersMsg1"); - jmsContext.unsubscribe("durPersMsg2"); + jmsContext.unsubscribe(subscriber1Name); + jmsContext.unsubscribe(subscriber2Name); jmsContext.close(); if ( testFailed ) { @@ -1459,31 +1441,29 @@ public void testPersistentMessageReceiveTopic( } } + private String testPersistentTopicMessageTcpIdentifier = "testPersistentTopicMessageTcp"; + public void testPersistentMessageTopic_Tcp( HttpServletRequest request, HttpServletResponse response) throws Exception { - - JMSContext jmsContext = jmsTCFTCP.createContext(); - JMSConsumer jmsConsumer1 = jmsContext.createDurableConsumer(jmsTopic, "durPersMsgTcp1"); - JMSConsumer jmsConsumer2 = jmsContext.createDurableConsumer(jmsTopic1, "durPersMsgTcp2"); - JMSProducer jmsProducer = jmsContext.createProducer(); - - jmsProducer.setDeliveryMode(DeliveryMode.PERSISTENT).setDeliveryDelay(1000); - jmsProducer.send(jmsTopic, "testPersistentMessage_PersistentMsgTopicTcp"); - - jmsProducer.setDeliveryDelay(1000).setDeliveryMode(DeliveryMode.NON_PERSISTENT); - jmsProducer.send(jmsTopic1, "testPersistentMessage_NonPersistentMsgTopicTcp"); - - // First half of test .. verification in the second half. + // Originally used message text "testPersistentMessage_PersistentMsgTopicTcp" "testPersistentMessage_NonPersistentMsgTopicTcp" + // jmsTCFTCP, jmsTopic, jmsTopic1 + + testPersistentMessageSimplifiedAPI_send(jmsTCFTCP, jmsTopic, jmsTopic1, testPersistentTopicMessageTcpIdentifier); + + return; } public void testPersistentMessageReceiveTopic_Tcp( HttpServletRequest request, HttpServletResponse response) throws Exception { boolean testFailed = false; + + String subscriber1Name = "durPersMsg1_" + testPersistentTopicMessageTcpIdentifier; + String subscriber2Name = "durPersMsg2_" + testPersistentTopicMessageTcpIdentifier; JMSContext jmsContext = jmsTCFTCP.createContext(); - JMSConsumer jmsConsumer1 = jmsContext.createDurableConsumer(jmsTopic, "durPersMsgTcp1"); - JMSConsumer jmsConsumer2 = jmsContext.createDurableConsumer(jmsTopic1, "durPersMsgTcp2"); + JMSConsumer jmsConsumer1 = jmsContext.createDurableConsumer(jmsTopic, subscriber1Name); + JMSConsumer jmsConsumer2 = jmsContext.createDurableConsumer(jmsTopic1, subscriber2Name); JMSProducer jmsProducer = jmsContext.createProducer(); TextMessage recMsg1 = (TextMessage) jmsConsumer1.receive(30000); @@ -1491,15 +1471,15 @@ public void testPersistentMessageReceiveTopic_Tcp( if ( ((recMsg1 == null) || (recMsg1.getText() == null) || - !recMsg1.getText().equals("testPersistentMessage_PersistentMsgTopicTcp")) || + !recMsg1.getText().equals("PersistentMessage_" + testPersistentTopicMessageTcpIdentifier)) || (recMsg2 != null) ) { testFailed = true; } jmsConsumer1.close(); jmsConsumer2.close(); - jmsContext.unsubscribe("durPersMsgTcp1"); - jmsContext.unsubscribe("durPersMsgTcp2"); + jmsContext.unsubscribe(subscriber1Name); + jmsContext.unsubscribe(subscriber2Name); jmsContext.close(); if ( testFailed ) { From 3ec366b8b6be974c702584a03bec26ce802db064 Mon Sep 17 00:00:00 2001 From: Andrew Rouse Date: Tue, 19 Nov 2024 15:15:36 +0000 Subject: [PATCH 54/67] Disable OpenAPI UI FAT screen recordings Currently our OpenAPI FAT tests are set up to record a screen capture of the UI as the test runs, and to save it if any tests fail. However, we're sometimes seeing failures where the Vnc container which does the recording doesn't start correctly. I'm not sure if that's the only problem or whether the Vnc container error is masking another failure. To get more information on these failures, I'd like to disable screen recording for now so that we can see if there's an actual failure underneath. It's possible that in future we'll need to reenable screen recording if we need it for debugging. --- .../fat/src/com/ibm/ws/openapi/ui/fat/tests/UIBasicTest.java | 4 ++-- .../openapi/ui/internal/fat/tests/UIBasicTest.java | 4 ++-- .../openapi/ui/internal/fat/tests/UICustomPathTest.java | 5 ++--- .../openapi/ui/internal/fat/tests/UIOauthTest.java | 4 ++-- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/dev/com.ibm.ws.openapi.ui_fat/fat/src/com/ibm/ws/openapi/ui/fat/tests/UIBasicTest.java b/dev/com.ibm.ws.openapi.ui_fat/fat/src/com/ibm/ws/openapi/ui/fat/tests/UIBasicTest.java index 77e6630111e..810aa410848 100644 --- a/dev/com.ibm.ws.openapi.ui_fat/fat/src/com/ibm/ws/openapi/ui/fat/tests/UIBasicTest.java +++ b/dev/com.ibm.ws.openapi.ui_fat/fat/src/com/ibm/ws/openapi/ui/fat/tests/UIBasicTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2023 IBM Corporation and others. + * Copyright (c) 2023, 2024 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at @@ -65,7 +65,7 @@ public class UIBasicTest { @Rule public BrowserWebDriverContainer chrome = new BrowserWebDriverContainer<>().withCapabilities(new ChromeOptions()) .withAccessToHost(true) - .withRecordingMode(VncRecordingMode.RECORD_FAILING, + .withRecordingMode(VncRecordingMode.SKIP, Props.getInstance().getFileProperty(Props.DIR_LOG), VncRecordingFormat.MP4) .withLogConsumer(new SimpleLogConsumer(UIBasicTest.class, "selenium-driver")); diff --git a/dev/io.openliberty.microprofile.openapi.ui.internal_fat/fat/src/io/openliberty/microprofile/openapi/ui/internal/fat/tests/UIBasicTest.java b/dev/io.openliberty.microprofile.openapi.ui.internal_fat/fat/src/io/openliberty/microprofile/openapi/ui/internal/fat/tests/UIBasicTest.java index cf85026b961..1a3b88c9fe3 100644 --- a/dev/io.openliberty.microprofile.openapi.ui.internal_fat/fat/src/io/openliberty/microprofile/openapi/ui/internal/fat/tests/UIBasicTest.java +++ b/dev/io.openliberty.microprofile.openapi.ui.internal_fat/fat/src/io/openliberty/microprofile/openapi/ui/internal/fat/tests/UIBasicTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2023 IBM Corporation and others. + * Copyright (c) 2023, 2024 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at @@ -67,7 +67,7 @@ public class UIBasicTest { @Rule public BrowserWebDriverContainer chrome = new BrowserWebDriverContainer<>().withCapabilities(new ChromeOptions()) .withAccessToHost(true) - .withRecordingMode(VncRecordingMode.RECORD_FAILING, + .withRecordingMode(VncRecordingMode.SKIP, Props.getInstance().getFileProperty(Props.DIR_LOG), VncRecordingFormat.MP4) .withLogConsumer(new SimpleLogConsumer(UIBasicTest.class, "selenium-driver")); diff --git a/dev/io.openliberty.microprofile.openapi.ui.internal_fat/fat/src/io/openliberty/microprofile/openapi/ui/internal/fat/tests/UICustomPathTest.java b/dev/io.openliberty.microprofile.openapi.ui.internal_fat/fat/src/io/openliberty/microprofile/openapi/ui/internal/fat/tests/UICustomPathTest.java index 7fd567df483..3b52357fb1b 100644 --- a/dev/io.openliberty.microprofile.openapi.ui.internal_fat/fat/src/io/openliberty/microprofile/openapi/ui/internal/fat/tests/UICustomPathTest.java +++ b/dev/io.openliberty.microprofile.openapi.ui.internal_fat/fat/src/io/openliberty/microprofile/openapi/ui/internal/fat/tests/UICustomPathTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2023 IBM Corporation and others. + * Copyright (c) 2023, 2024 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at @@ -17,7 +17,6 @@ import static org.junit.Assert.assertNotNull; import java.time.Duration; -import java.util.Arrays; import org.hamcrest.Matchers; import org.jboss.shrinkwrap.api.ShrinkWrap; @@ -69,7 +68,7 @@ public class UICustomPathTest { @Rule public BrowserWebDriverContainer chrome = new BrowserWebDriverContainer<>().withCapabilities(new ChromeOptions()).withAccessToHost(true) - .withRecordingMode(VncRecordingMode.RECORD_FAILING, + .withRecordingMode(VncRecordingMode.SKIP, Props.getInstance().getFileProperty(Props.DIR_LOG), VncRecordingFormat.MP4) .withLogConsumer(new SimpleLogConsumer(UICustomPathTest.class, "selenium-driver")); diff --git a/dev/io.openliberty.microprofile.openapi.ui.internal_fat/fat/src/io/openliberty/microprofile/openapi/ui/internal/fat/tests/UIOauthTest.java b/dev/io.openliberty.microprofile.openapi.ui.internal_fat/fat/src/io/openliberty/microprofile/openapi/ui/internal/fat/tests/UIOauthTest.java index ece5326f789..19f633cfa3e 100644 --- a/dev/io.openliberty.microprofile.openapi.ui.internal_fat/fat/src/io/openliberty/microprofile/openapi/ui/internal/fat/tests/UIOauthTest.java +++ b/dev/io.openliberty.microprofile.openapi.ui.internal_fat/fat/src/io/openliberty/microprofile/openapi/ui/internal/fat/tests/UIOauthTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2023 IBM Corporation and others. + * Copyright (c) 2023, 2024 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at @@ -83,7 +83,7 @@ public class UIOauthTest { @Rule public BrowserWebDriverContainer chrome = new BrowserWebDriverContainer<>().withCapabilities(new ChromeOptions()) .withAccessToHost(true) - .withRecordingMode(BrowserWebDriverContainer.VncRecordingMode.RECORD_FAILING, + .withRecordingMode(BrowserWebDriverContainer.VncRecordingMode.SKIP, Props.getInstance().getFileProperty(Props.DIR_LOG), VncRecordingFormat.MP4) .withLogConsumer(new SimpleLogConsumer(UIBasicTest.class, "selenium-driver")); From ee999aeea494d6ed6429e71fcdbf4c9b4f59d9ce Mon Sep 17 00:00:00 2001 From: Thomas Watson Date: Tue, 19 Nov 2024 16:26:56 -0600 Subject: [PATCH 55/67] Add names to synchronized locks using KeyBaseLockStore --- .../zip/cache/internal/ZipFileReaper.java | 20 +++++++++++++------ .../internal/ClassLoadingServiceImpl.java | 8 ++++---- .../classloader/NameBasedClassLoaderLock.java | 20 +++++++++++++------ .../kernel/boot/utils/KeyBasedLockStore.java | 12 +++++------ 4 files changed, 38 insertions(+), 22 deletions(-) diff --git a/dev/com.ibm.ws.artifact.zip/src/com/ibm/ws/artifact/zip/cache/internal/ZipFileReaper.java b/dev/com.ibm.ws.artifact.zip/src/com/ibm/ws/artifact/zip/cache/internal/ZipFileReaper.java index b8cfb1736b0..038bc4cb341 100644 --- a/dev/com.ibm.ws.artifact.zip/src/com/ibm/ws/artifact/zip/cache/internal/ZipFileReaper.java +++ b/dev/com.ibm.ws.artifact.zip/src/com/ibm/ws/artifact/zip/cache/internal/ZipFileReaper.java @@ -25,8 +25,7 @@ import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; -import java.util.function.Supplier; -//import java.util.function.Consumer; +import java.util.function.Function; import java.util.zip.ZipException; import java.util.zip.ZipFile; @@ -917,12 +916,21 @@ private static class PendingStorageLock { // - private static final class ZipFilePathLock { } + private static final class ZipFilePathLock { + private final String path; + ZipFilePathLock(String path){ + this.path = path; + } + @Override + public String toString() { + return "ZipFilePathLock: " + path; + } + } - private static KeyBasedLockStore zipFilePathLockStore = new KeyBasedLockStore<>(new Supplier() { + private static KeyBasedLockStore zipFilePathLockStore = new KeyBasedLockStore<>(new Function() { @Override - public ZipFilePathLock get() { - return new ZipFilePathLock(); + public ZipFilePathLock apply(String path) { + return new ZipFilePathLock(path); } }); diff --git a/dev/com.ibm.ws.classloading/src/com/ibm/ws/classloading/internal/ClassLoadingServiceImpl.java b/dev/com.ibm.ws.classloading/src/com/ibm/ws/classloading/internal/ClassLoadingServiceImpl.java index f76d0cab678..76bedff1305 100644 --- a/dev/com.ibm.ws.classloading/src/com/ibm/ws/classloading/internal/ClassLoadingServiceImpl.java +++ b/dev/com.ibm.ws.classloading/src/com/ibm/ws/classloading/internal/ClassLoadingServiceImpl.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010, 2023 IBM Corporation and others. + * Copyright (c) 2010, 2024 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at @@ -41,7 +41,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.locks.ReentrantLock; -import java.util.function.Supplier; +import java.util.function.Function; import org.eclipse.equinox.region.RegionDigraph; import org.osgi.framework.Bundle; @@ -112,9 +112,9 @@ public class ClassLoadingServiceImpl implements LibertyClassLoadingService tcclLockStore = new KeyBasedLockStore<>(new Supplier() { + private static final KeyBasedLockStore tcclLockStore = new KeyBasedLockStore<>(new Function() { @Override - public ReentrantLock get() { + public ReentrantLock apply(String key) { return new ReentrantLock(); } }); diff --git a/dev/com.ibm.ws.kernel.boot.common/src/com/ibm/ws/kernel/boot/classloader/NameBasedClassLoaderLock.java b/dev/com.ibm.ws.kernel.boot.common/src/com/ibm/ws/kernel/boot/classloader/NameBasedClassLoaderLock.java index 86ac3dc1a70..bd8c528626a 100644 --- a/dev/com.ibm.ws.kernel.boot.common/src/com/ibm/ws/kernel/boot/classloader/NameBasedClassLoaderLock.java +++ b/dev/com.ibm.ws.kernel.boot.common/src/com/ibm/ws/kernel/boot/classloader/NameBasedClassLoaderLock.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2023 IBM Corporation and others. + * Copyright (c) 2023, 2024 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at @@ -9,17 +9,25 @@ *******************************************************************************/ package com.ibm.ws.kernel.boot.classloader; -import java.util.function.Supplier; +import java.util.function.Function; public class NameBasedClassLoaderLock { - public static final Supplier LOCK_SUPPLIER = new Supplier() { + public static final Function LOCK_SUPPLIER = new Function() { @Override - public NameBasedClassLoaderLock get() { - return new NameBasedClassLoaderLock(); + public NameBasedClassLoaderLock apply(String className) { + return new NameBasedClassLoaderLock(className); } }; - private NameBasedClassLoaderLock() { + private final String className; + + private NameBasedClassLoaderLock(String className) { + this.className = className; + } + + @Override + public String toString() { + return "NameBasedClassLoaderLock: " + className; } } diff --git a/dev/com.ibm.ws.kernel.boot.core/src/com/ibm/ws/kernel/boot/utils/KeyBasedLockStore.java b/dev/com.ibm.ws.kernel.boot.core/src/com/ibm/ws/kernel/boot/utils/KeyBasedLockStore.java index fb19038f54d..b9937b85690 100644 --- a/dev/com.ibm.ws.kernel.boot.core/src/com/ibm/ws/kernel/boot/utils/KeyBasedLockStore.java +++ b/dev/com.ibm.ws.kernel.boot.core/src/com/ibm/ws/kernel/boot/utils/KeyBasedLockStore.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2022, 2023 IBM Corporation and others. + * Copyright (c) 2022, 2024 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at @@ -15,18 +15,18 @@ import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Supplier; +import java.util.function.Function; import com.ibm.websphere.ras.annotation.Trivial; @Trivial public final class KeyBasedLockStore { - private final ReferenceQueue refQueue = new ReferenceQueue<>(); + final ReferenceQueue refQueue = new ReferenceQueue<>(); private final ConcurrentHashMap lockMap = new ConcurrentHashMap<>(); - private final Supplier lockCreator; + private final Function lockCreator; - public KeyBasedLockStore(Supplier lockCreator) { + public KeyBasedLockStore(Function lockCreator) { this.lockCreator = lockCreator; } @@ -48,7 +48,7 @@ public final Lock getLock(Key key) { return lock; } - lock = lockCreator.get(); + lock = lockCreator.apply(key); while (true) { LockWeakRef retVal = lockMap.putIfAbsent(key, new LockWeakRef(lock, key)); From 434e422f6285e5468880d48b4e0cb6a0b84d11c8 Mon Sep 17 00:00:00 2001 From: Andrew Rouse Date: Wed, 20 Nov 2024 15:22:37 +0000 Subject: [PATCH 56/67] OpenAPI: Use mark when checking for log messages Tests in MergeConfigServerXMLTest that are checking for the presence or absence of messages created in the same test must use a log mark to avoid picking up messages created by other tests. --- .../openapi20/fat/deployments/MergeConfigServerXMLTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dev/io.openliberty.microprofile.openapi.2.0.internal_fat/fat/src/io/openliberty/microprofile/openapi20/fat/deployments/MergeConfigServerXMLTest.java b/dev/io.openliberty.microprofile.openapi.2.0.internal_fat/fat/src/io/openliberty/microprofile/openapi20/fat/deployments/MergeConfigServerXMLTest.java index 25d2fa798ad..988630223f5 100644 --- a/dev/io.openliberty.microprofile.openapi.2.0.internal_fat/fat/src/io/openliberty/microprofile/openapi20/fat/deployments/MergeConfigServerXMLTest.java +++ b/dev/io.openliberty.microprofile.openapi.2.0.internal_fat/fat/src/io/openliberty/microprofile/openapi20/fat/deployments/MergeConfigServerXMLTest.java @@ -120,7 +120,7 @@ public void testDefaultInclusion() throws Exception { OpenAPITestUtil.checkPaths(openapiNode, 1, "/test"); // Test that merging disabled message was output (at some point) - assertThat(server.findStringsInLogs(" I CWWKO1663I:.*Combining OpenAPI documentation from multiple modules is disabled."), + assertThat(server.findStringsInLogsUsingMark(" I CWWKO1663I:.*Combining OpenAPI documentation from multiple modules is disabled.", server.getDefaultLogFile()), hasSize(1)); // remove app 1 @@ -136,7 +136,7 @@ public void testDefaultInclusion() throws Exception { OpenAPITestUtil.checkPaths(openapiNode, 2, "/test1/test", "/test2/test"); // Check there's no "first module only" message - assertThat(server.findStringsInLogs("CWWKO1663I"), + assertThat(server.findStringsInLogsUsingMark("CWWKO1663I", server.getDefaultLogFile()), hasSize(0)); } } From 714120c968ffadc6c5cabe21b10d9485b89d6f6a Mon Sep 17 00:00:00 2001 From: Jon Hawkes Date: Wed, 20 Nov 2024 16:03:23 +0000 Subject: [PATCH 57/67] WSTXMPR002AFVT can tolerate DataStoreAdapterException & ResourceAllocationException --- .../fat/src/tests/MultiRecoveryTest1.java | 1 + .../fat/src/tests/DBRerouteRecoveryTest.java | 107 ------------------ 2 files changed, 1 insertion(+), 107 deletions(-) delete mode 100644 dev/com.ibm.ws.wsat.recovery_fat.multi.8.ee10/fat/src/tests/DBRerouteRecoveryTest.java diff --git a/dev/com.ibm.ws.wsat.recovery_fat.multi.1/fat/src/tests/MultiRecoveryTest1.java b/dev/com.ibm.ws.wsat.recovery_fat.multi.1/fat/src/tests/MultiRecoveryTest1.java index 755e17c204f..01ffbfb0924 100644 --- a/dev/com.ibm.ws.wsat.recovery_fat.multi.1/fat/src/tests/MultiRecoveryTest1.java +++ b/dev/com.ibm.ws.wsat.recovery_fat.multi.1/fat/src/tests/MultiRecoveryTest1.java @@ -44,6 +44,7 @@ public void WSTXMPR001CFVT() throws Exception { } @Test + @AllowedFFDC(value = { "com.ibm.ws.rsadapter.exceptions.DataStoreAdapterException", "javax.resource.spi.ResourceAllocationException"}) public void WSTXMPR002AFVT() throws Exception { recoveryTest(server1, server2, "201","server1"); } diff --git a/dev/com.ibm.ws.wsat.recovery_fat.multi.8.ee10/fat/src/tests/DBRerouteRecoveryTest.java b/dev/com.ibm.ws.wsat.recovery_fat.multi.8.ee10/fat/src/tests/DBRerouteRecoveryTest.java deleted file mode 100644 index 2a56a4c20f2..00000000000 --- a/dev/com.ibm.ws.wsat.recovery_fat.multi.8.ee10/fat/src/tests/DBRerouteRecoveryTest.java +++ /dev/null @@ -1,107 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2020, 2024 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License 2.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ -package tests; - -import org.jboss.shrinkwrap.api.spec.WebArchive; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.runner.RunWith; - -import com.ibm.websphere.simplicity.ShrinkHelper; -import com.ibm.websphere.simplicity.log.Log; -import com.ibm.ws.transaction.fat.util.FATUtils; -import com.ibm.ws.transaction.fat.util.SetupRunner; -import com.ibm.ws.transaction.fat.util.TxTestContainerSuite; -import com.ibm.ws.wsat.fat.util.DBTestBase; - -import componenttest.annotation.AllowedFFDC; -import componenttest.annotation.Server; -import componenttest.containers.SimpleLogConsumer; -import componenttest.custom.junit.runner.FATRunner; -import componenttest.topology.database.container.DatabaseContainerType; -import componenttest.topology.database.container.DatabaseContainerUtil; -import componenttest.topology.database.container.PostgreSQLContainer; -import componenttest.topology.impl.LibertyServer; - -@AllowedFFDC(value = { "com.ibm.tx.jta.ut.util.AlreadyDumpedException", "javax.transaction.SystemException", "javax.transaction.xa.XAException", "java.io.IOException", "java.io.EOFException" }) -@RunWith(FATRunner.class) -public class DBRerouteRecoveryTest extends MultiRecoveryTest1 { - - @Server("WSATRecovery3") - public static LibertyServer server3; - - public static String[] serverNames = new String[] {"WSATRecoveryClient1", "WSATRecoveryServer1", "WSATRecovery3"}; - - @BeforeClass - public static void beforeClass() throws Exception { - Log.info(DBRerouteRecoveryTest.class, "beforeClass", ""); - - runner = new SetupRunner() { - @Override - public void run(LibertyServer s) throws Exception { - Log.info(DBRerouteRecoveryTest.class, "setupRunner.run", "Setting up "+s.getServerName()+" for testcontainers"); - - //Get driver name - s.addEnvVar("DB_DRIVER", DatabaseContainerType.valueOf(TxTestContainerSuite.testContainer).getDriverName()); - - //Setup server DataSource properties - DatabaseContainerUtil.setupDataSourceDatabaseProperties(s, TxTestContainerSuite.testContainer); - - s.setServerStartTimeout(FATUtils.LOG_SEARCH_TIMEOUT); - } - }; - -// System.getProperties().entrySet().stream().forEach(e -> Log.info(RerouteTest.class, "Properties", e.getKey() + " -> " + e.getValue())); -// System.getenv().entrySet().stream().forEach(e -> Log.info(RerouteTest.class, "Environment", e.getKey() + " -> " + e.getValue())); - - BASE_URL = "http://" + server1.getHostname() + ":" + server1.getHttpDefaultPort(); - - server2.setHttpDefaultPort(Integer.parseInt(System.getProperty("HTTP_secondary"))); - BASE_URL2 = "http://" + server2.getHostname() + ":" + server2.getHttpDefaultPort(); - - server3.setHttpDefaultPort(Integer.parseInt(System.getProperty("HTTP_tertiary"))); - - DBTestBase.initWSATTest(server1); - DBTestBase.initWSATTest(server2); - - final WebArchive clientApp = ShrinkHelper.buildDefaultApp("recoveryClient", "client.*"); - ShrinkHelper.exportDropinAppToServer(server1, clientApp); - ShrinkHelper.exportDropinAppToServer(server2, clientApp); - - final WebArchive serverApp = ShrinkHelper.buildDefaultApp("recoveryServer", "server.*"); - ShrinkHelper.exportDropinAppToServer(server1, serverApp); - ShrinkHelper.exportDropinAppToServer(server2, serverApp); - } - - @AfterClass - public static void afterClass() throws Exception { - Log.info(DBRerouteRecoveryTest.class, "afterClass", ""); - - DBTestBase.cleanupWSATTest(server1); - DBTestBase.cleanupWSATTest(server2); - } - - @Before - public void before() throws Exception { - Log.info(DBRerouteRecoveryTest.class, "before", ""); - FATUtils.startServers(runner, server1, server2, server3); - } - - @After - public void after() throws Exception { - Log.info(DBRerouteRecoveryTest.class, "after", ""); - FATUtils.stopServers(server1, server2, server3); - } -} From d799a995bbd7dd2381668edcc601fb9b36dc230b Mon Sep 17 00:00:00 2001 From: Thomas Watson Date: Mon, 18 Nov 2024 12:55:51 -0600 Subject: [PATCH 58/67] Update to Equinox Framework version 3.21.0 Remove overlays from previous releases --- .../check_this_in_if_it_changes/pom.xml | 2 +- dev/cnf/oss_dependencies.maven | 2 +- .../publish/platform/kernel-1.0.mf | 2 +- dev/com.ibm.wsspi.thirdparty.equinox/bnd.bnd | 2 +- dev/org.eclipse.osgi/bnd.bnd | 7 +- dev/org.eclipse.osgi/bnd.overrides | 4 +- .../osgi/internal/cds/CDSBundleFile.java | 169 -- .../internal/cds/CDSHookConfigurator.java | 82 - .../osgi/internal/cds/CDSHookImpls.java | 258 -- .../eclipse/osgi/internal/debug/Debug.java | 376 --- .../internal/loader/EquinoxClassLoader.java | 6 +- .../internal/loader/ModuleClassLoader.java | 6 +- .../internal/url/URLStreamHandlerProxy.java | 3 +- .../src/org/eclipse/osgi/storage/Storage.java | 2243 ----------------- 14 files changed, 19 insertions(+), 3143 deletions(-) delete mode 100644 dev/org.eclipse.osgi/src/org/eclipse/osgi/internal/cds/CDSBundleFile.java delete mode 100644 dev/org.eclipse.osgi/src/org/eclipse/osgi/internal/cds/CDSHookConfigurator.java delete mode 100644 dev/org.eclipse.osgi/src/org/eclipse/osgi/internal/cds/CDSHookImpls.java delete mode 100644 dev/org.eclipse.osgi/src/org/eclipse/osgi/internal/debug/Debug.java delete mode 100644 dev/org.eclipse.osgi/src/org/eclipse/osgi/storage/Storage.java diff --git a/dev/cnf/dependabot/check_this_in_if_it_changes/pom.xml b/dev/cnf/dependabot/check_this_in_if_it_changes/pom.xml index 8507b74ee09..d007b8bf6fb 100644 --- a/dev/cnf/dependabot/check_this_in_if_it_changes/pom.xml +++ b/dev/cnf/dependabot/check_this_in_if_it_changes/pom.xml @@ -3289,7 +3289,7 @@ org.eclipse.platform org.eclipse.osgi - 3.18.600 + 3.21.0 org.eclipse.transformer diff --git a/dev/cnf/oss_dependencies.maven b/dev/cnf/oss_dependencies.maven index 7c773bb2409..11e1e8a9db7 100644 --- a/dev/cnf/oss_dependencies.maven +++ b/dev/cnf/oss_dependencies.maven @@ -653,7 +653,7 @@ org.eclipse.persistence:org.eclipse.persistence.jpa:4.0.3 org.eclipse.persistence:org.eclipse.persistence.jpa:5.0.0-B03 org.eclipse.persistence:org.eclipse.persistence.json:4.0.3 org.eclipse.persistence:org.eclipse.persistence.json:5.0.0-B03 -org.eclipse.platform:org.eclipse.osgi:3.18.600 +org.eclipse.platform:org.eclipse.osgi:3.21.0 org.eclipse.transformer:org.eclipse.transformer.bnd.analyzer:0.5.0 org.eclipse.transformer:org.eclipse.transformer.cli:0.5.0 org.eclipse.transformer:org.eclipse.transformer.jakarta:0.5.0 diff --git a/dev/com.ibm.ws.kernel.boot/publish/platform/kernel-1.0.mf b/dev/com.ibm.ws.kernel.boot/publish/platform/kernel-1.0.mf index 538e8596690..0c569d615ea 100644 --- a/dev/com.ibm.ws.kernel.boot/publish/platform/kernel-1.0.mf +++ b/dev/com.ibm.ws.kernel.boot/publish/platform/kernel-1.0.mf @@ -56,7 +56,7 @@ Subsystem-Content: README.TXT; location:="README.TXT"; type="file", com.ibm.wsspi.org.osgi.service.log; version="[1.2,1.3)"; location:="dev/spi/spec/"; type="jar", com.ibm.wsspi.org.osgi.service.metatype; version="[1.1,1.2)"; location:="dev/spi/spec/"; type="jar", com.ibm.wsspi.org.osgi.service.metatype.annotations; version="[1,1.1)"; location:="dev/spi/spec/"; type="jar", - com.ibm.wsspi.thirdparty.equinox; version="[1.1,1.4)"; location:="dev/spi/third-party/"; type="jar", + com.ibm.wsspi.thirdparty.equinox; version="[1.1,1.5)"; location:="dev/spi/third-party/"; type="jar", com.ibm.websphere.appserver.api.config; version="[1,1.3)"; type="jar"; location:="dev/api/ibm/", com.ibm.websphere.appserver.api.config_1.2-javadoc.zip; type="file"; location:="dev/api/ibm/javadoc/com.ibm.websphere.appserver.api.config_1.2-javadoc.zip", com.ibm.ws.config.schemagen; version="[1,1.1)"; type="jar", diff --git a/dev/com.ibm.wsspi.thirdparty.equinox/bnd.bnd b/dev/com.ibm.wsspi.thirdparty.equinox/bnd.bnd index a33253762bb..e46a10fbfb0 100644 --- a/dev/com.ibm.wsspi.thirdparty.equinox/bnd.bnd +++ b/dev/com.ibm.wsspi.thirdparty.equinox/bnd.bnd @@ -11,7 +11,7 @@ # IBM Corporation - initial API and implementation #******************************************************************************* -include= ~../cnf/resources/bnd/bundle.props -bVersion=1.3 +bVersion=1.4 Bundle-SymbolicName: com.ibm.wsspi.thirdparty.equinox Bundle-Name: WebSphere Equinox Third-Party SPI diff --git a/dev/org.eclipse.osgi/bnd.bnd b/dev/org.eclipse.osgi/bnd.bnd index d69def37e6b..a5521d57a7d 100644 --- a/dev/org.eclipse.osgi/bnd.bnd +++ b/dev/org.eclipse.osgi/bnd.bnd @@ -10,16 +10,15 @@ # Contributors: # IBM Corporation - initial API and implementation #******************************************************************************* --include= jar:${fileuri;${repo;org.eclipse.platform:org.eclipse.osgi;3.18.600}}!/META-INF/MANIFEST.MF,bnd.overrides +-include= jar:${fileuri;${repo;org.eclipse.platform:org.eclipse.osgi;3.21.0}}!/META-INF/MANIFEST.MF,bnd.overrides -nouses: true -nodefaultversion: true instrument.disabled: true -includeresource: \ - @${repo;org.eclipse.platform:org.eclipse.osgi;3.18.600}!/!module-info.class, \ + @${repo;org.eclipse.platform:org.eclipse.osgi;3.21.0}!/!module-info.class, \ org/eclipse=${bin}/org/eclipse -buildpath: \ - org.eclipse.platform:org.eclipse.osgi;version=3.18.600, \ - io.openliberty.com.ibm.oti.shared;version=latest + org.eclipse.platform:org.eclipse.osgi;version=3.21.0 diff --git a/dev/org.eclipse.osgi/bnd.overrides b/dev/org.eclipse.osgi/bnd.overrides index 591a6bd26c7..c63ed98b695 100644 --- a/dev/org.eclipse.osgi/bnd.overrides +++ b/dev/org.eclipse.osgi/bnd.overrides @@ -1,6 +1,6 @@ -include= ~../cnf/resources/bnd/rejar.props -bVersion=3.18.600 -bFullVersion=3.18.600 +bVersion=3.21.0 +bFullVersion=3.21.0 Bundle-SymbolicName: org.eclipse.osgi; singleton:=true diff --git a/dev/org.eclipse.osgi/src/org/eclipse/osgi/internal/cds/CDSBundleFile.java b/dev/org.eclipse.osgi/src/org/eclipse/osgi/internal/cds/CDSBundleFile.java deleted file mode 100644 index 312f85b9bef..00000000000 --- a/dev/org.eclipse.osgi/src/org/eclipse/osgi/internal/cds/CDSBundleFile.java +++ /dev/null @@ -1,169 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2006, 2018 IBM Corp. and others - * - * This program and the accompanying materials are made available under - * the terms of the Eclipse Public License 2.0 which accompanies this - * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ - * or the Apache License, Version 2.0 which accompanies this distribution and - * is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * This Source Code may also be made available under the following - * Secondary Licenses when the conditions for such availability set - * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU - * General Public License, version 2 with the GNU Classpath - * Exception [1] and GNU General Public License, version 2 with the - * OpenJDK Assembly Exception [2]. - * - * [1] https://www.gnu.org/software/classpath/license.html - * [2] http://openjdk.java.net/legal/assembly-exception.html - * - * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception - *******************************************************************************/ - -package org.eclipse.osgi.internal.cds; - -import static org.eclipse.osgi.internal.cds.CDSHookConfigurator.print; - -import java.net.MalformedURLException; -import java.net.URL; - -import org.eclipse.osgi.internal.debug.Debug; -import org.eclipse.osgi.storage.bundlefile.BundleEntry; -import org.eclipse.osgi.storage.bundlefile.BundleFile; -import org.eclipse.osgi.storage.bundlefile.BundleFileWrapper; - -import com.ibm.oti.shared.SharedClassURLHelper; - -/** - * Wraps an actual BundleFile object for purposes of loading classes from the - * shared classes cache. - */ -public class CDSBundleFile extends BundleFileWrapper { - private final static String classFileExt = ".class"; //$NON-NLS-1$ - private final URL url; // the URL to the content of the real bundle file - private SharedClassURLHelper urlHelper; // the url helper set by the classloader - private boolean primed = false; - private final Debug debug; - - /** - * The constructor - * - * @param wrapped the real bundle file - */ - public CDSBundleFile(BundleFile wrapped, Debug debug) { - super(wrapped); - this.debug = debug; - // get the url to the content of the real bundle file - URL content = null; - try { - content = new URL("file", "", wrapped.getBaseFile().getAbsolutePath()); //$NON-NLS-1$ //$NON-NLS-2$ - } catch (MalformedURLException e) { - // do nothing - } - this.url = content; - } - - public CDSBundleFile(BundleFile bundleFile, Debug debug, SharedClassURLHelper urlHelper) { - this(bundleFile, debug); - this.urlHelper = urlHelper; - } - - /* - * (non-Javadoc) - * - * @see - * org.eclipse.osgi.storage.bundlefile.BundleFile#getEntry(java.lang.String) - * - * If path is not for a class then just use the wrapped bundle file to answer - * the call. If the path is for a class, it returns a CDSBundleEntry object. If - * the path is for a class, it will look for the magic cookie in the shared - * classes cache. If found, the bytes representing the magic cookie are stored - * in CDSBundleEntry object. - */ - @Override - public BundleEntry getEntry(String path) { - if (!primed || !path.endsWith(classFileExt)) { - return super.getEntry(path); - } - byte[] classbytes = getClassBytes(path.substring(0, path.length() - classFileExt.length())); - if (classbytes == null) { - BundleEntry fromSuper = super.getEntry(path); - if (fromSuper != null) { - print(debug, () -> "Defining class from original bytes: " + url + ' ' + fromSuper.getName()); //$NON-NLS-1$ - } - return fromSuper; - } - - BundleEntry be = new CDSBundleEntry(path, classbytes, this); - return be; - } - - BundleEntry getWrappedEntry(String path) { - return super.getEntry(path); - } - - /** - * Returns the file url to the content of the actual bundle file - * - * @return the file url to the content of the actual bundle file - */ - URL getURL() { - return url; - } - - /** - * Returns the url helper for this bundle file. This is set by the class loading - * hook - * - * @return the url helper for this bundle file - */ - SharedClassURLHelper getURLHelper() { - return urlHelper; - } - - /** - * Sets the url helper for this bundle file. This is called by the class loading - * hook. - * - * @param urlHelper the url helper - */ - void setURLHelper(SharedClassURLHelper urlHelper) { - this.urlHelper = urlHelper; - this.primed = false; // always unprime when a new urlHelper is set - } - - /** - * Sets the primed flag for the bundle file. This is called by the class loading - * hook after the first class has been loaded from disk for this bundle file. - * - * @param primed the primed flag - */ - void setPrimed(boolean primed) { - this.primed = primed; - } - - /** - * Searches in the shared classes cache for the specified class name. - * - * @param name the name of the class - * @return the magic cookie to the shared class or null if the class is not in - * the cache. - */ - private byte[] getClassBytes(String name) { - if (urlHelper == null || url == null) - return null; - byte[] results = urlHelper.findSharedClass(null, url, name); - print(debug, () -> results != null ? "Found shared class bytes for: " + name + ' ' + url //$NON-NLS-1$ - : "No shared class bytes found for: " + name + ' ' + url); //$NON-NLS-1$ - return results; - } - - /** - * Returns the primed flag for this bundle file. - * - * @return the primed flag - */ - public boolean getPrimed() { - return this.primed; - } -} diff --git a/dev/org.eclipse.osgi/src/org/eclipse/osgi/internal/cds/CDSHookConfigurator.java b/dev/org.eclipse.osgi/src/org/eclipse/osgi/internal/cds/CDSHookConfigurator.java deleted file mode 100644 index dc0f307ba92..00000000000 --- a/dev/org.eclipse.osgi/src/org/eclipse/osgi/internal/cds/CDSHookConfigurator.java +++ /dev/null @@ -1,82 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2006, 2018 IBM Corp. and others - * - * This program and the accompanying materials are made available under - * the terms of the Eclipse Public License 2.0 which accompanies this - * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ - * or the Apache License, Version 2.0 which accompanies this distribution and - * is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * This Source Code may also be made available under the following - * Secondary Licenses when the conditions for such availability set - * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU - * General Public License, version 2 with the GNU Classpath - * Exception [1] and GNU General Public License, version 2 with the - * OpenJDK Assembly Exception [2]. - * - * [1] https://www.gnu.org/software/classpath/license.html - * [2] http://openjdk.java.net/legal/assembly-exception.html - * - * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception - *******************************************************************************/ - -package org.eclipse.osgi.internal.cds; - -import java.util.function.Supplier; - -import org.eclipse.osgi.framework.log.FrameworkLogEntry; -import org.eclipse.osgi.internal.debug.Debug; -import org.eclipse.osgi.internal.framework.EquinoxContainer; -import org.eclipse.osgi.internal.hookregistry.HookConfigurator; -import org.eclipse.osgi.internal.hookregistry.HookRegistry; -import org.eclipse.osgi.internal.log.EquinoxLogServices; - -public class CDSHookConfigurator implements HookConfigurator { - - private static final String REPORT_ERRORS = "j9.cds.reporterrors"; //$NON-NLS-1$ - private static final String DISABLE_CDS = "j9.cds.disable"; //$NON-NLS-1$ - private static final String OLD_CDS_CONFIGURATOR = "com.ibm.cds.CDSHookConfigurator"; //$NON-NLS-1$ - private static final String J9_SHARED_CLASS_HELPER_CLASS = "com.ibm.oti.shared.SharedClassHelperFactory"; //$NON-NLS-1$ - - static void print(Debug debug, Supplier msg) { - if (debug.DEBUG_LOADER_CDS) { - Debug.println(msg.get()); - } - } - @Override - public void addHooks(HookRegistry hookRegistry) { - Debug debug = hookRegistry.getConfiguration().getDebug(); - boolean disableCDS = Boolean.valueOf(hookRegistry.getConfiguration().getProperty(DISABLE_CDS)); - if (disableCDS) { - print(debug, () -> "Class sharing is disabled by: " + DISABLE_CDS); //$NON-NLS-1$ - return; - } - // check for the external com.ibm.cds system.bundle fragment - try { - Class.forName(OLD_CDS_CONFIGURATOR); - // the old com.ibm.cds fragment is installed; disable build-in one - print(debug, () -> "Detected old com.ibm.cds fragment."); //$NON-NLS-1$ - return; - } catch (ClassNotFoundException e) { - // expected - } - try { - Class.forName(J9_SHARED_CLASS_HELPER_CLASS); - print(debug, () -> "Found Eclipse OpenJ9 support class: " + J9_SHARED_CLASS_HELPER_CLASS); //$NON-NLS-1$ - } catch (ClassNotFoundException e) { - print(debug, () -> "Not running on Eclipse OpenJ9."); //$NON-NLS-1$ - boolean reportErrors = Boolean.valueOf(hookRegistry.getConfiguration().getProperty(REPORT_ERRORS)); - // not running on J9 - if (reportErrors) { - EquinoxContainer container = hookRegistry.getContainer(); - EquinoxLogServices logServices = container.getLogServices(); - logServices.log(EquinoxContainer.NAME, FrameworkLogEntry.WARNING, - "The J9 Class Sharing Adaptor will not work in this configuration. You are not running on a J9 Java VM.", //$NON-NLS-1$ - null); - } - return; - } - new CDSHookImpls(debug).registerHooks(hookRegistry); - } - -} diff --git a/dev/org.eclipse.osgi/src/org/eclipse/osgi/internal/cds/CDSHookImpls.java b/dev/org.eclipse.osgi/src/org/eclipse/osgi/internal/cds/CDSHookImpls.java deleted file mode 100644 index d120023ee58..00000000000 --- a/dev/org.eclipse.osgi/src/org/eclipse/osgi/internal/cds/CDSHookImpls.java +++ /dev/null @@ -1,258 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2006, 2018 IBM Corp. and others - * - * This program and the accompanying materials are made available under - * the terms of the Eclipse Public License 2.0 which accompanies this - * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ - * or the Apache License, Version 2.0 which accompanies this distribution and - * is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * This Source Code may also be made available under the following - * Secondary Licenses when the conditions for such availability set - * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU - * General Public License, version 2 with the GNU Classpath - * Exception [1] and GNU General Public License, version 2 with the - * OpenJDK Assembly Exception [2]. - * - * [1] https://www.gnu.org/software/classpath/license.html - * [2] http://openjdk.java.net/legal/assembly-exception.html - * - * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception - *******************************************************************************/ - -package org.eclipse.osgi.internal.cds; - -import static org.eclipse.osgi.internal.cds.CDSHookConfigurator.print; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; - -import org.eclipse.osgi.internal.debug.Debug; -import org.eclipse.osgi.internal.hookregistry.BundleFileWrapperFactoryHook; -import org.eclipse.osgi.internal.hookregistry.ClassLoaderHook; -import org.eclipse.osgi.internal.hookregistry.HookRegistry; -import org.eclipse.osgi.internal.loader.ModuleClassLoader; -import org.eclipse.osgi.internal.loader.classpath.ClasspathEntry; -import org.eclipse.osgi.internal.loader.classpath.ClasspathManager; -import org.eclipse.osgi.internal.loader.classpath.FragmentClasspath; -import org.eclipse.osgi.storage.BundleInfo.Generation; -import org.eclipse.osgi.storage.ContentProvider.Type; -import org.eclipse.osgi.storage.bundlefile.BundleEntry; -import org.eclipse.osgi.storage.bundlefile.BundleFile; -import org.eclipse.osgi.storage.bundlefile.BundleFileWrapper; -import org.eclipse.osgi.storage.bundlefile.BundleFileWrapperChain; - -import com.ibm.oti.shared.HelperAlreadyDefinedException; -import com.ibm.oti.shared.Shared; -import com.ibm.oti.shared.SharedClassHelperFactory; -import com.ibm.oti.shared.SharedClassURLHelper; - -public class CDSHookImpls extends ClassLoaderHook implements BundleFileWrapperFactoryHook { - private static SharedClassHelperFactory factory = Shared.getSharedClassHelperFactory(); - - private final Debug debug; - - public CDSHookImpls(Debug debug) { - this.debug = debug; - } - - // With Equinox bug 226038 (v3.4), the framework will now pass an instance - // of BundleFileWrapperChain rather than the wrapped BundleFile. This is - // so that multiple wrapping hooks can each wrap the BundleFile and all - // wrappers are accessible. - // - // The Wrapper chain will look like below: - // WrapperChain -> Wrapper -> WrapperChain -> CDSBundleFile -> WrapperChain - // -> BundleFile - // - private static CDSBundleFile getCDSBundleFile(BundleFile bundleFile) { - if (bundleFile instanceof BundleFileWrapperChain) { - return ((BundleFileWrapperChain) bundleFile).getWrappedType(CDSBundleFile.class); - } - return null; - } - - @Override - public void recordClassDefine(String name, Class clazz, byte[] classbytes, ClasspathEntry classpathEntry, - BundleEntry entry, ClasspathManager manager) { // only attempt to record the class define if: - // 1) the class was found (clazz != null) - // 2) the class has the magic class number CAFEBABE indicating a real class - // 3) the bundle file for the classpath entry is of type CDSBundleFile - // 4) class bytes is same as passed to weaving hook i.e. weaving hook did not - // modify the class bytes - if (null == clazz) { - print(debug, () -> "No class to store: " + name); //$NON-NLS-1$ - return; - } - if ((false == hasMagicClassNumber(classbytes))) { - print(debug, () -> "Class was already stored: " + name); //$NON-NLS-1$ - return; - } - CDSBundleFile cdsFile = getCDSBundleFile(classpathEntry.getBundleFile()); - if (null == cdsFile) { - print(debug, () -> "No CDSBundleFile for class: " + name); //$NON-NLS-1$ - return; - } - try { - // check if weaving hook modified the class bytes - byte originalClassBytes[] = entry.getBytes(); - if (originalClassBytes != classbytes) { - // weaving hook has potentially modified the class bytes - boolean modified = false; - if (originalClassBytes.length == classbytes.length) { - // do a byte-by-byte comparison - modified = !Arrays.equals(classbytes, originalClassBytes); - } else { - modified = true; - } - if (modified) { - // Class bytes have been modified by weaving hooks. - // Such classes need to be stored as Orphans, so skip the call to - // storeSharedClass() - print(debug, () -> "class bytes have changed, cannot store."); //$NON-NLS-1$ - return; - } - } - } catch (IOException e) { - // this should never happen, but in case it does, its safe to return - return; - } - - if (null == cdsFile.getURL()) { - // something went wrong trying to determine the url to the real bundle file - return; - } - - // look for the urlHelper; if it does not exist then we are not sharing for this - // class loader - SharedClassURLHelper urlHelper = cdsFile.getURLHelper(); - if (urlHelper == null) { - // this should never happen but just in case get the helper from the base host - // bundle file. - CDSBundleFile hostBundleFile = getCDSBundleFile(manager.getGeneration().getBundleFile()); - if (null != hostBundleFile) { - // try getting the helper from the host base cdsFile - urlHelper = hostBundleFile.getURLHelper(); - } - - if (null != urlHelper) { - cdsFile.setURLHelper(urlHelper); - } - } - if (null != urlHelper) { - // store the class in the cache - boolean successStore = urlHelper.storeSharedClass(null, cdsFile.getURL(), clazz); - print(debug, () -> successStore ? "Stored class: " + name : "Failed to store class: " + name); //$NON-NLS-1$//$NON-NLS-2$ - cdsFile.setPrimed(true); - } else { - print(debug, () -> "No helper found to store class: " + name); //$NON-NLS-1$ - } - } - - private boolean hasMagicClassNumber(byte[] classbytes) { - if (classbytes == null || classbytes.length < 4) - return false; - // TODO maybe there is a better way to do this? I'm not sure why I had to AND - // each byte with the value I was checking ... - return (classbytes[0] & 0xCA) == 0xCA && (classbytes[1] & 0xFE) == 0xFE && (classbytes[2] & 0xBA) == 0xBA - && (classbytes[3] & 0xBE) == 0xBE; - } - - @Override - public void classLoaderCreated(ModuleClassLoader classLoader) { - // try to get the url helper for this class loader - if (factory == null) { - return; - } - try { - SharedClassURLHelper urlHelper = factory.getURLHelper(classLoader); - boolean minimizeUpdateChecks = urlHelper.setMinimizeUpdateChecks(); - // set the url helper for the host base CDSBundleFile - CDSBundleFile hostFile = getCDSBundleFile( - classLoader.getClasspathManager().getGeneration().getBundleFile()); - if (hostFile != null) { - hostFile.setURLHelper(urlHelper); - if (minimizeUpdateChecks) { - // no need to prime if we were able to setMinimizeUpdateChecks - hostFile.setPrimed(true); - } - } - // No need to prime if we were able to setMinimizeUpdateChecks. - // Mark all the BundleFiles on the classpath as primed. - ClasspathManager cpManager = classLoader.getClasspathManager(); - for (ClasspathEntry entry : cpManager.getHostClasspathEntries()) { - CDSBundleFile cdsBundleFile = getCDSBundleFile(entry.getBundleFile()); - if (cdsBundleFile != null) { - cdsBundleFile.setURLHelper(urlHelper); - if (minimizeUpdateChecks) { - cdsBundleFile.setPrimed(true); - } - } - } - for (FragmentClasspath fragCP : cpManager.getFragmentClasspaths()) { - for (ClasspathEntry entry : fragCP.getEntries()) { - CDSBundleFile cdsBundleFile = getCDSBundleFile(entry.getBundleFile()); - if (cdsBundleFile != null) { - cdsBundleFile.setURLHelper(urlHelper); - if (minimizeUpdateChecks) { - cdsBundleFile.setPrimed(true); - } - } - } - } - } catch (HelperAlreadyDefinedException e) { - // We should never get here. - // If we do, we simply won't share for this ClassLoader - } - } - - @Override - public boolean addClassPathEntry(ArrayList cpEntries, String cp, ClasspathManager hostmanager, - Generation sourceGeneration) { - CDSBundleFile hostFile = getCDSBundleFile(hostmanager.getGeneration().getBundleFile()); - CDSBundleFile sourceFile = getCDSBundleFile(sourceGeneration.getBundleFile()); - if ((hostFile != sourceFile) && (null != hostFile) && (null != sourceFile)) { - // Set the helper that got set on the host base bundle file in - // classLoaderCreated. - // This is to handle the case where fragments are dynamically attached - SharedClassURLHelper urlHelper = hostFile.getURLHelper(); - sourceFile.setURLHelper(urlHelper); - sourceFile.setPrimed(hostFile.getPrimed()); - } - - return false; - } - - //////////////// BundleFileWrapperFactoryHook ////////////// - @Override - public BundleFileWrapper wrapBundleFile(BundleFile bundleFile, Generation generation, boolean base) { - if (generation.getContentType() == Type.CONNECT) { - return null; - } - // wrap the real bundle file for purposes of loading shared classes. - CDSBundleFile newBundleFile; - if (!base && generation.getBundleInfo().getBundleId() != 0) { - // initialize the urlHelper from the base one. - SharedClassURLHelper urlHelper = null; - BundleFile baseFile = generation.getBundleFile(); - if ((baseFile = getCDSBundleFile(baseFile)) != null) { - urlHelper = ((CDSBundleFile) baseFile).getURLHelper(); - } - newBundleFile = new CDSBundleFile(bundleFile, debug, urlHelper); - } else { - newBundleFile = new CDSBundleFile(bundleFile, debug); - } - - return newBundleFile; - } - - void registerHooks(HookRegistry hookRegistry) { - // only register if sharing is enabled - if (!Shared.isSharingEnabled()) { - return; - } - hookRegistry.addClassLoaderHook(this); - hookRegistry.addBundleFileWrapperFactoryHook(this); - } -} diff --git a/dev/org.eclipse.osgi/src/org/eclipse/osgi/internal/debug/Debug.java b/dev/org.eclipse.osgi/src/org/eclipse/osgi/internal/debug/Debug.java deleted file mode 100644 index f63deb75737..00000000000 --- a/dev/org.eclipse.osgi/src/org/eclipse/osgi/internal/debug/Debug.java +++ /dev/null @@ -1,376 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2003, 2018 IBM Corporation and others. - * - * This program and the accompanying materials - * are made available under the terms of the Eclipse Public License 2.0 - * which accompanies this distribution, and is available at - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ - -package org.eclipse.osgi.internal.debug; - -import java.io.PrintStream; - -import org.eclipse.osgi.internal.framework.EquinoxContainer; -import org.eclipse.osgi.internal.util.SupplementDebug; -import org.eclipse.osgi.service.debug.DebugOptions; -import org.eclipse.osgi.service.debug.DebugOptionsListener; - -/** - * This class has debug constants which can be used by the Framework - * implementation and Adaptor implementations - * - * @since 3.1 - */ -public class Debug implements DebugOptionsListener { - /** - * Base debug option key (org.eclispe.osgi). - */ - public static final String ECLIPSE_OSGI = EquinoxContainer.NAME; - /** - * General Debug option key. - */ - public static final String OPTION_DEBUG_GENERAL = ECLIPSE_OSGI + "/debug"; //$NON-NLS-1$ - /** - * Bundle time Debug option key. - */ - public static final String OPTION_DEBUG_BUNDLE_TIME = ECLIPSE_OSGI + "/debug/bundleTime"; //$NON-NLS-1$ - - /** - * Bundle start time Debug option key. - */ - public static final String OPTION_DEBUG_BUNDLE_START_TIME = ECLIPSE_OSGI + "/debug/bundleStartTime"; //$NON-NLS-1$ - /** - * Loader Debug option key. - */ - public static final String OPTION_DEBUG_LOADER = ECLIPSE_OSGI + "/debug/loader"; //$NON-NLS-1$ - - /** - * Loader Debug option key. - */ - public static final String OPTION_DEBUG_LOADER_CDS = ECLIPSE_OSGI + "/debug/loader/cds"; //$NON-NLS-1$ - - /** - * Storage Debug option key. - */ - public static final String OPTION_DEBUG_STORAGE = ECLIPSE_OSGI + "/debug/storage"; //$NON-NLS-1$ - /** - * Events Debug option key. - */ - public static final String OPTION_DEBUG_EVENTS = ECLIPSE_OSGI + "/debug/events"; //$NON-NLS-1$ - /** - * Services Debug option key. - */ - public static final String OPTION_DEBUG_SERVICES = ECLIPSE_OSGI + "/debug/services"; //$NON-NLS-1$ - /** - * Services Debug option key. - */ - public static final String OPTION_DEBUG_HOOKS = ECLIPSE_OSGI + "/debug/hooks"; //$NON-NLS-1$ - /** - * Manifest Debug option key. - */ - public static final String OPTION_DEBUG_MANIFEST = ECLIPSE_OSGI + "/debug/manifest"; //$NON-NLS-1$ - /** - * Filter Debug option key. - */ - public static final String OPTION_DEBUG_FILTER = ECLIPSE_OSGI + "/debug/filter"; //$NON-NLS-1$ - /** - * Security Debug option key. - */ - public static final String OPTION_DEBUG_SECURITY = ECLIPSE_OSGI + "/debug/security"; //$NON-NLS-1$ - /** - * Start level Debug option key. - */ - public static final String OPTION_DEBUG_STARTLEVEL = ECLIPSE_OSGI + "/debug/startlevel"; //$NON-NLS-1$ - /** - * PackageAdmin Debug option key. - */ - public static final String OPTION_DEBUG_PACKAGEADMIN = ECLIPSE_OSGI + "/debug/packageadmin"; //$NON-NLS-1$ - /** - * PackageAdmin timing Debug option key. - */ - public static final String OPTION_DEBUG_PACKAGEADMIN_TIMING = ECLIPSE_OSGI + "/debug/packageadmin/timing"; //$NON-NLS-1$ - /** - * Monitor activation Debug option key. - */ - public static final String OPTION_MONITOR_ACTIVATION = ECLIPSE_OSGI + "/monitor/activation"; //$NON-NLS-1$ - - /** - * Monitor lazy activation Debug option key - */ - public static final String OPTION_MONITOR_LAZY = ECLIPSE_OSGI + "/monitor/lazy"; //$NON-NLS-1$ - /** - * Message bundles Debug option key. - */ - public static final String OPTION_DEBUG_MESSAGE_BUNDLES = ECLIPSE_OSGI + "/debug/messageBundles"; //$NON-NLS-1$ - - public static final String OPTION_DEBUG_LOCATION = ECLIPSE_OSGI + "/debug/location"; //$NON-NLS-1$ - - public static final String OPTION_CACHED_MANIFEST = ECLIPSE_OSGI + "/debug/cachedmanifest"; //$NON-NLS-1$ - - public static final String OPTION_DEBUG_SYSTEM_BUNDLE = ECLIPSE_OSGI + "/debug/systemBundle"; //$NON-NLS-1$ - - public static final String OPTION_DEBUG_BUNDLE_FILE = ECLIPSE_OSGI + "/debug/bundleFile"; //$NON-NLS-1$ - - public static final String OPTION_DEBUG_BUNDLE_FILE_OPEN = ECLIPSE_OSGI + "/debug/bundleFile/open"; //$NON-NLS-1$ - - public static final String OPTION_DEBUG_BUNDLE_FILE_CLOSE = ECLIPSE_OSGI + "/debug/bundleFile/close"; //$NON-NLS-1$ - - /** - * General debug flag. - */ - public boolean DEBUG_GENERAL = false; // "debug" - /** - * Bundle time debug flag. - */ - public boolean DEBUG_BUNDLE_TIME = false; // "debug.bundleTime" - /** - * Loader debug flag. - */ - public boolean DEBUG_LOADER = false; // "debug.loader" - /** - * Loader debug flag. - */ - public boolean DEBUG_LOADER_CDS = false; // "debug.loader" - /** - * Storage debug flag. - */ - public boolean DEBUG_STORAGE = false; // "debug.storage" - /** - * Events debug flag. - */ - public boolean DEBUG_EVENTS = false; // "debug.events" - /** - * Services debug flag. - */ - public boolean DEBUG_SERVICES = false; // "debug.services" - - /** - * Hooks debug flag. - */ - public boolean DEBUG_HOOKS = false; // "debug.hooks" - /** - * Manifest debug flag. - */ - public boolean DEBUG_MANIFEST = false; // "debug.manifest" - /** - * Filter debug flag. - */ - public boolean DEBUG_FILTER = false; // "debug.filter" - /** - * Security debug flag. - */ - public boolean DEBUG_SECURITY = false; // "debug.security" - /** - * Start level debug flag. - */ - public boolean DEBUG_STARTLEVEL = false; // "debug.startlevel" - /** - * PackageAdmin debug flag. - */ - public boolean DEBUG_PACKAGEADMIN = false; // "debug.packageadmin" - /** - * PackageAdmin timing debug flag. - */ - // TODO remove this or use it somewhere - public boolean DEBUG_PACKAGEADMIN_TIMING = false; // "debug.packageadmin/timing" - /** - * Message debug flag. - */ - public boolean DEBUG_MESSAGE_BUNDLES = false; // "/debug/messageBundles" - /** - * Monitor activation debug flag. - */ - public boolean MONITOR_ACTIVATION = false; // "monitor/activation" - - public boolean DEBUG_LOCATION = false; // debug/location - - public boolean DEBUG_CACHED_MANIFEST = false; - - public boolean DEBUG_SYSTEM_BUNDLE = false; // debug/systemBundle - - public boolean DEBUG_BUNDLE_FILE = false; // debug/bundleFile - - public boolean DEBUG_BUNDLE_FILE_OPEN = false; // debug/bundleFile/open - - public boolean DEBUG_BUNDLE_FILE_CLOSE = false; // debug/bundleFile/close - - public Debug(DebugOptions dbgOptions) { - optionsChanged(dbgOptions); - } - - @Override - public void optionsChanged(DebugOptions dbgOptions) { - DEBUG_GENERAL = dbgOptions.getBooleanOption(OPTION_DEBUG_GENERAL, false); - DEBUG_BUNDLE_TIME = dbgOptions.getBooleanOption(OPTION_DEBUG_BUNDLE_TIME, false) - || dbgOptions.getBooleanOption("org.eclipse.core.runtime/timing/startup", false); //$NON-NLS-1$ - DEBUG_LOADER = dbgOptions.getBooleanOption(OPTION_DEBUG_LOADER, false); - DEBUG_LOADER_CDS = dbgOptions.getBooleanOption(OPTION_DEBUG_LOADER_CDS, false); - DEBUG_STORAGE = dbgOptions.getBooleanOption(OPTION_DEBUG_STORAGE, false); - DEBUG_EVENTS = dbgOptions.getBooleanOption(OPTION_DEBUG_EVENTS, false); - DEBUG_SERVICES = dbgOptions.getBooleanOption(OPTION_DEBUG_SERVICES, false); - DEBUG_HOOKS = dbgOptions.getBooleanOption(OPTION_DEBUG_HOOKS, false); - DEBUG_MANIFEST = dbgOptions.getBooleanOption(OPTION_DEBUG_MANIFEST, false); - SupplementDebug.STATIC_DEBUG_MANIFEST = DEBUG_MANIFEST; - DEBUG_FILTER = dbgOptions.getBooleanOption(OPTION_DEBUG_FILTER, false); - DEBUG_SECURITY = dbgOptions.getBooleanOption(OPTION_DEBUG_SECURITY, false); - DEBUG_STARTLEVEL = dbgOptions.getBooleanOption(OPTION_DEBUG_STARTLEVEL, false); - DEBUG_PACKAGEADMIN = dbgOptions.getBooleanOption(OPTION_DEBUG_PACKAGEADMIN, false); - DEBUG_PACKAGEADMIN_TIMING = dbgOptions.getBooleanOption(OPTION_DEBUG_PACKAGEADMIN_TIMING, false) - || dbgOptions.getBooleanOption("org.eclipse.core.runtime/debug", false); //$NON-NLS-1$ - DEBUG_MESSAGE_BUNDLES = dbgOptions.getBooleanOption(OPTION_DEBUG_MESSAGE_BUNDLES, false); - SupplementDebug.STATIC_DEBUG_MESSAGE_BUNDLES = DEBUG_MESSAGE_BUNDLES; - MONITOR_ACTIVATION = dbgOptions.getBooleanOption(OPTION_MONITOR_ACTIVATION, false); - DEBUG_LOCATION = dbgOptions.getBooleanOption(OPTION_DEBUG_LOCATION, false); - DEBUG_CACHED_MANIFEST = dbgOptions.getBooleanOption(OPTION_CACHED_MANIFEST, false); - DEBUG_SYSTEM_BUNDLE = dbgOptions.getBooleanOption(OPTION_DEBUG_SYSTEM_BUNDLE, false); - DEBUG_BUNDLE_FILE = dbgOptions.getBooleanOption(OPTION_DEBUG_BUNDLE_FILE, false); - DEBUG_BUNDLE_FILE_OPEN = dbgOptions.getBooleanOption(OPTION_DEBUG_BUNDLE_FILE_OPEN, false); - DEBUG_BUNDLE_FILE_CLOSE = dbgOptions.getBooleanOption(OPTION_DEBUG_BUNDLE_FILE_CLOSE, false); - } - - /** - * The PrintStream to print debug messages to. - */ - public static PrintStream out = System.out; - - /** - * Prints x to the PrintStream - */ - public static void print(boolean x) { - out.print(x); - } - - /** - * Prints x to the PrintStream - */ - public static void print(char x) { - out.print(x); - } - - /** - * Prints x to the PrintStream - */ - public static void print(int x) { - out.print(x); - } - - /** - * Prints x to the PrintStream - */ - public static void print(long x) { - out.print(x); - } - - /** - * Prints x to the PrintStream - */ - public static void print(float x) { - out.print(x); - } - - /** - * Prints x to the PrintStream - */ - public static void print(double x) { - out.print(x); - } - - /** - * Prints x to the PrintStream - */ - public static void print(char x[]) { - out.print(x); - } - - /** - * Prints x to the PrintStream - */ - public static void print(String x) { - out.print(x); - } - - /** - * Prints x to the PrintStream - */ - public static void print(Object x) { - out.print(x); - } - - /** - * Prints x to the PrintStream - */ - public static void println(boolean x) { - out.println(x); - } - - /** - * Prints x to the PrintStream - */ - public static void println(char x) { - out.println(x); - } - - /** - * Prints x to the PrintStream - */ - public static void println(int x) { - out.println(x); - } - - /** - * Prints x to the PrintStream - */ - public static void println(long x) { - out.println(x); - } - - /** - * Prints x to the PrintStream - */ - public static void println(float x) { - out.println(x); - } - - /** - * Prints x to the PrintStream - */ - public static void println(double x) { - out.println(x); - } - - /** - * Prints x to the PrintStream - */ - public static void println(char x[]) { - out.println(x); - } - - /** - * Prints x to the PrintStream - */ - public static void println(String x) { - out.println(x); - } - - /** - * Prints x to the PrintStream - */ - public static void println(Object x) { - out.println(x); - } - - /** - * Prints t to the PrintStream - */ - public static void printStackTrace(Throwable t) { - if (t == null) - return; - t.printStackTrace(out); - } -} diff --git a/dev/org.eclipse.osgi/src/org/eclipse/osgi/internal/loader/EquinoxClassLoader.java b/dev/org.eclipse.osgi/src/org/eclipse/osgi/internal/loader/EquinoxClassLoader.java index b4480a3a4dc..b7defd1509a 100644 --- a/dev/org.eclipse.osgi/src/org/eclipse/osgi/internal/loader/EquinoxClassLoader.java +++ b/dev/org.eclipse.osgi/src/org/eclipse/osgi/internal/loader/EquinoxClassLoader.java @@ -21,8 +21,10 @@ public class EquinoxClassLoader extends ModuleClassLoader { static { - if (!ClassLoader.registerAsParallelCapable()) { - throw new IllegalStateException("Failed to register as parallel capabable."); //$NON-NLS-1$ + try { + ClassLoader.registerAsParallelCapable(); + } catch (Throwable t) { + // ignore all exceptions; substrate native image fails here } } private final EquinoxConfiguration configuration; diff --git a/dev/org.eclipse.osgi/src/org/eclipse/osgi/internal/loader/ModuleClassLoader.java b/dev/org.eclipse.osgi/src/org/eclipse/osgi/internal/loader/ModuleClassLoader.java index cd65014eb3e..0d6e7e7ba18 100644 --- a/dev/org.eclipse.osgi/src/org/eclipse/osgi/internal/loader/ModuleClassLoader.java +++ b/dev/org.eclipse.osgi/src/org/eclipse/osgi/internal/loader/ModuleClassLoader.java @@ -62,8 +62,10 @@ public Bundle getBundle() { */ protected static final PermissionCollection ALLPERMISSIONS; static { - if (!ClassLoader.registerAsParallelCapable()) { - throw new IllegalStateException("Failed to register as parallel capabable."); //$NON-NLS-1$ + try { + ClassLoader.registerAsParallelCapable(); + } catch (Throwable t) { + // ignore all exceptions; substrate native image fails here } } diff --git a/dev/org.eclipse.osgi/src/org/eclipse/osgi/internal/url/URLStreamHandlerProxy.java b/dev/org.eclipse.osgi/src/org/eclipse/osgi/internal/url/URLStreamHandlerProxy.java index b40c8448e66..f62fac292c4 100644 --- a/dev/org.eclipse.osgi/src/org/eclipse/osgi/internal/url/URLStreamHandlerProxy.java +++ b/dev/org.eclipse.osgi/src/org/eclipse/osgi/internal/url/URLStreamHandlerProxy.java @@ -70,7 +70,8 @@ public URLStreamHandlerProxy(String protocol, BundleContext context) { new ServiceTrackerCustomizer() { @Override - public LazyURLStreamHandlerService addingService(ServiceReference reference) { + public LazyURLStreamHandlerService addingService( + ServiceReference reference) { return new LazyURLStreamHandlerService(context, reference); } diff --git a/dev/org.eclipse.osgi/src/org/eclipse/osgi/storage/Storage.java b/dev/org.eclipse.osgi/src/org/eclipse/osgi/storage/Storage.java deleted file mode 100644 index c8e1d0654aa..00000000000 --- a/dev/org.eclipse.osgi/src/org/eclipse/osgi/storage/Storage.java +++ /dev/null @@ -1,2243 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2012, 2021 IBM Corporation and others. - * - * This program and the accompanying materials - * are made available under the terms of the Eclipse Public License 2.0 - * which accompanies this distribution, and is available at - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * IBM Corporation - initial API and implementation - * Christoph Laeubrich - Bug 527175 - Storage#getSystemContent() should first make the file absolute - * Hannes Wellmann - Bug 577432 - Speed up and improve file processing in Storage - *******************************************************************************/ -package org.eclipse.osgi.storage; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.lang.reflect.Method; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLConnection; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Dictionary; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Hashtable; -import java.util.Iterator; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Properties; -import java.util.Set; -import java.util.StringTokenizer; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.stream.Stream; -import org.eclipse.core.runtime.adaptor.EclipseStarter; -import org.eclipse.osgi.container.Module; -import org.eclipse.osgi.container.ModuleCapability; -import org.eclipse.osgi.container.ModuleContainer; -import org.eclipse.osgi.container.ModuleContainerAdaptor; -import org.eclipse.osgi.container.ModuleDatabase; -import org.eclipse.osgi.container.ModuleRevision; -import org.eclipse.osgi.container.ModuleRevisionBuilder; -import org.eclipse.osgi.container.ModuleWire; -import org.eclipse.osgi.container.ModuleWiring; -import org.eclipse.osgi.container.builders.OSGiManifestBuilderFactory; -import org.eclipse.osgi.container.namespaces.EclipsePlatformNamespace; -import org.eclipse.osgi.framework.internal.reliablefile.ReliableFile; -import org.eclipse.osgi.framework.log.FrameworkLogEntry; -import org.eclipse.osgi.framework.util.FilePath; -import org.eclipse.osgi.framework.util.ObjectPool; -import org.eclipse.osgi.framework.util.SecureAction; -import org.eclipse.osgi.internal.container.InternalUtils; -import org.eclipse.osgi.internal.debug.Debug; -import org.eclipse.osgi.internal.framework.EquinoxConfiguration; -import org.eclipse.osgi.internal.framework.EquinoxContainer; -import org.eclipse.osgi.internal.framework.EquinoxContainerAdaptor; -import org.eclipse.osgi.internal.framework.FilterImpl; -import org.eclipse.osgi.internal.hookregistry.BundleFileWrapperFactoryHook; -import org.eclipse.osgi.internal.hookregistry.StorageHookFactory; -import org.eclipse.osgi.internal.hookregistry.StorageHookFactory.StorageHook; -import org.eclipse.osgi.internal.location.EquinoxLocations; -import org.eclipse.osgi.internal.location.LocationHelper; -import org.eclipse.osgi.internal.log.EquinoxLogServices; -import org.eclipse.osgi.internal.messages.Msg; -import org.eclipse.osgi.internal.permadmin.SecurityAdmin; -import org.eclipse.osgi.internal.url.URLStreamHandlerFactoryImpl; -import org.eclipse.osgi.service.datalocation.Location; -import org.eclipse.osgi.storage.BundleInfo.Generation; -import org.eclipse.osgi.storage.ContentProvider.Type; -import org.eclipse.osgi.storage.bundlefile.BundleEntry; -import org.eclipse.osgi.storage.bundlefile.BundleFile; -import org.eclipse.osgi.storage.bundlefile.BundleFileWrapper; -import org.eclipse.osgi.storage.bundlefile.BundleFileWrapperChain; -import org.eclipse.osgi.storage.bundlefile.DirBundleFile; -import org.eclipse.osgi.storage.bundlefile.MRUBundleFileList; -import org.eclipse.osgi.storage.bundlefile.NestedDirBundleFile; -import org.eclipse.osgi.storage.bundlefile.ZipBundleFile; -import org.eclipse.osgi.storage.url.reference.Handler; -import org.eclipse.osgi.storagemanager.ManagedOutputStream; -import org.eclipse.osgi.storagemanager.StorageManager; -import org.eclipse.osgi.util.ManifestElement; -import org.eclipse.osgi.util.NLS; -import org.osgi.framework.Bundle; -import org.osgi.framework.BundleContext; -import org.osgi.framework.BundleException; -import org.osgi.framework.Constants; -import org.osgi.framework.Filter; -import org.osgi.framework.InvalidSyntaxException; -import org.osgi.framework.Version; -import org.osgi.framework.connect.ConnectModule; -import org.osgi.framework.namespace.HostNamespace; -import org.osgi.framework.namespace.NativeNamespace; -import org.osgi.framework.namespace.PackageNamespace; -import org.osgi.framework.wiring.BundleCapability; -import org.osgi.framework.wiring.BundleRevision; -import org.osgi.framework.wiring.BundleWiring; -import org.osgi.resource.Namespace; -import org.osgi.resource.Requirement; - -public class Storage { - public static class StorageException extends RuntimeException { - private static final long serialVersionUID = 1L; - - public StorageException() { - super(); - } - - public StorageException(String message, Throwable cause) { - super(message, cause); - } - - public StorageException(String message) { - super(message); - } - - public StorageException(Throwable cause) { - super(cause); - } - - } - - public static final int VERSION = 6; - private static final int CONTENT_TYPE_VERSION = 6; - private static final int CACHED_SYSTEM_CAPS_VERION = 5; - private static final int MR_JAR_VERSION = 4; - private static final int LOWEST_VERSION_SUPPORTED = 3; - public static final String BUNDLE_DATA_DIR = "data"; //$NON-NLS-1$ - public static final String BUNDLE_FILE_NAME = "bundleFile"; //$NON-NLS-1$ - public static final String FRAMEWORK_INFO = "framework.info"; //$NON-NLS-1$ - public static final String ECLIPSE_SYSTEMBUNDLE = "Eclipse-SystemBundle"; //$NON-NLS-1$ - public static final String DELETE_FLAG = ".delete"; //$NON-NLS-1$ - public static final String LIB_TEMP = "libtemp"; //$NON-NLS-1$ - - private static final String JAVASE = "JavaSE"; //$NON-NLS-1$ - private static final String PROFILE_EXT = ".profile"; //$NON-NLS-1$ - private static final String NUL = new String(new byte[] {0}); - private static final String INITIAL_LOCATION = "initial@"; //$NON-NLS-1$ - - static final SecureAction secureAction = AccessController.doPrivileged(SecureAction.createSecureAction()); - - private final EquinoxContainer equinoxContainer; - private final String installPath; - private final Location osgiLocation; - private final File childRoot; - private final File parentRoot; - private final PermissionData permissionData; - private final SecurityAdmin securityAdmin; - private final EquinoxContainerAdaptor adaptor; - private final ModuleDatabase moduleDatabase; - private final ModuleContainer moduleContainer; - private final Object saveMonitor = new Object(); - private long lastSavedTimestamp = -1; - private final MRUBundleFileList mruList; - private final FrameworkExtensionInstaller extensionInstaller; - private final List cachedHeaderKeys = Arrays.asList(Constants.BUNDLE_SYMBOLICNAME, Constants.BUNDLE_ACTIVATIONPOLICY, "Service-Component"); //$NON-NLS-1$ - private final boolean allowRestrictedProvides; - private final AtomicBoolean refreshMRBundles = new AtomicBoolean(false); - private final Version runtimeVersion; - private final String javaSpecVersion; - - public static Storage createStorage(EquinoxContainer container) throws IOException, BundleException { - String[] cachedInfo = new String[3]; - Storage storage = new Storage(container, cachedInfo); - // Do some operations that need to happen on the fully constructed Storage before returning it - storage.checkSystemBundle(cachedInfo); - storage.refreshStaleBundles(); - storage.installExtensions(); - // TODO hack to make sure all bundles are in UNINSTALLED state before system - // bundle init is called - storage.getModuleContainer().setInitialModuleStates(); - return storage; - } - - private Storage(EquinoxContainer container, String[] cachedInfo) throws IOException { - // default to Java 8 since that is our min - Version defaultVersion = Version.valueOf("1.8"); //$NON-NLS-1$ - Version javaVersion = defaultVersion; - // set the profile and EE based off of the java.specification.version - String javaSpecVersionProp = System.getProperty(EquinoxConfiguration.PROP_JVM_SPEC_VERSION); - StringTokenizer st = new StringTokenizer(javaSpecVersionProp, " _-"); //$NON-NLS-1$ - javaSpecVersionProp = st.nextToken(); - try { - String[] vComps = javaSpecVersionProp.split("\\."); //$NON-NLS-1$ - // only pay attention to the first three components of the version - int major = vComps.length > 0 ? Integer.parseInt(vComps[0]) : 0; - int minor = vComps.length > 1 ? Integer.parseInt(vComps[1]) : 0; - int micro = vComps.length > 2 ? Integer.parseInt(vComps[2]) : 0; - javaVersion = new Version(major, minor, micro); - } catch (IllegalArgumentException e) { - // do nothing - } - if (javaVersion.compareTo(defaultVersion) < 0) { - // the Java specification property is wrong, we are compiled to the - // defaultVersion - // just use it instead. - javaVersion = defaultVersion; - } - runtimeVersion = javaVersion; - javaSpecVersion = javaSpecVersionProp; - mruList = new MRUBundleFileList(getBundleFileLimit(container.getConfiguration()), container.getConfiguration().getDebug()); - equinoxContainer = container; - extensionInstaller = new FrameworkExtensionInstaller(container.getConfiguration()); - allowRestrictedProvides = Boolean.parseBoolean(container.getConfiguration().getConfiguration(EquinoxConfiguration.PROP_ALLOW_RESTRICTED_PROVIDES)); - - // we need to set the install path as soon as possible so we can determine - // the absolute location of install relative URLs - Location installLoc = container.getLocations().getInstallLocation(); - URL installURL = installLoc.getURL(); - // assume install URL is file: based - installPath = installURL.getPath(); - - Location configLocation = container.getLocations().getConfigurationLocation(); - Location parentConfigLocation = configLocation.getParentLocation(); - Location osgiParentLocation = null; - if (parentConfigLocation != null) { - osgiParentLocation = parentConfigLocation.createLocation(null, parentConfigLocation.getDataArea(EquinoxContainer.NAME), true); - } - this.osgiLocation = configLocation.createLocation(osgiParentLocation, configLocation.getDataArea(EquinoxContainer.NAME), configLocation.isReadOnly()); - this.childRoot = new File(osgiLocation.getURL().getPath()); - - if (Boolean.valueOf(container.getConfiguration().getConfiguration(EquinoxConfiguration.PROP_CLEAN)).booleanValue()) { - cleanOSGiStorage(osgiLocation, childRoot); - } - if (!this.osgiLocation.isReadOnly()) { - this.childRoot.mkdirs(); - } - Location parent = this.osgiLocation.getParentLocation(); - parentRoot = parent == null ? null : new File(parent.getURL().getPath()); - - if (container.getConfiguration().getConfiguration(Constants.FRAMEWORK_STORAGE) == null) { - // Set the derived value if not already set as part of configuration. - // Note this is the parent directory of where the framework stores data (org.eclipse.osgi/) - container.getConfiguration().setConfiguration(Constants.FRAMEWORK_STORAGE, childRoot.getParentFile().getAbsolutePath()); - } - - InputStream info = getInfoInputStream(); - DataInputStream data = info == null ? null : new DataInputStream(new BufferedInputStream(info)); - try { - Map generations; - try { - generations = loadGenerations(data, cachedInfo); - } catch (IllegalArgumentException e) { - equinoxContainer.getLogServices().log(EquinoxContainer.NAME, FrameworkLogEntry.WARNING, "The persistent format for the framework data has changed. The framework will be reinitialized: " + e.getMessage(), null); //$NON-NLS-1$ - generations = new HashMap<>(0); - data = null; - cleanOSGiStorage(osgiLocation, childRoot); - } - this.permissionData = loadPermissionData(data); - this.securityAdmin = new SecurityAdmin(null, this.permissionData); - this.adaptor = new EquinoxContainerAdaptor(equinoxContainer, this, generations); - this.moduleDatabase = new ModuleDatabase(this.adaptor); - this.moduleContainer = new ModuleContainer(this.adaptor, this.moduleDatabase); - if (data != null) { - try { - moduleDatabase.load(data); - lastSavedTimestamp = moduleDatabase.getTimestamp(); - } catch (IllegalArgumentException e) { - equinoxContainer.getLogServices().log(EquinoxContainer.NAME, FrameworkLogEntry.WARNING, "Incompatible version. Starting with empty framework.", e); //$NON-NLS-1$ - // Clean up the cache. - // No need to clean up the database. Nothing got loaded. - cleanOSGiStorage(osgiLocation, childRoot); - // should free up the generations map - generations.clear(); - } - } - } finally { - if (data != null) { - try { - data.close(); - } catch (IOException e) { - // just move on - } - } - } - } - - public Version getRuntimeVersion() { - return runtimeVersion; - } - - public MRUBundleFileList getMRUBundleFileList() { - return mruList; - } - - private int getBundleFileLimit(EquinoxConfiguration configuration) { - int propValue = 100; // enable to 100 open files by default - try { - String prop = configuration.getConfiguration(EquinoxConfiguration.PROP_FILE_LIMIT); - if (prop != null) - propValue = Integer.parseInt(prop); - } catch (NumberFormatException e) { - // use default of 100 - } - return propValue; - } - - private void installExtensions() { - Module systemModule = moduleContainer.getModule(0); - ModuleRevision systemRevision = systemModule == null ? null : systemModule.getCurrentRevision(); - ModuleWiring systemWiring = systemRevision == null ? null : systemRevision.getWiring(); - if (systemWiring == null) { - return; - } - Collection fragments = new ArrayList<>(); - for (ModuleWire hostWire : systemWiring.getProvidedModuleWires(HostNamespace.HOST_NAMESPACE)) { - fragments.add(hostWire.getRequirer()); - } - try { - getExtensionInstaller().addExtensionContent(fragments, null); - } catch (BundleException e) { - getLogServices().log(EquinoxContainer.NAME, FrameworkLogEntry.ERROR, e.getMessage(), e); - } - } - - private static PermissionData loadPermissionData(DataInputStream in) throws IOException { - PermissionData permData = new PermissionData(); - if (in != null) { - permData.readPermissionData(in); - } - return permData; - } - - private void refreshStaleBundles() throws BundleException { - Collection needsRefresh = new ArrayList<>(0); - - // First uninstall any modules that had their content changed or deleted - for (Module module : moduleContainer.getModules()) { - if (module.getId() == Constants.SYSTEM_BUNDLE_ID) - continue; - ModuleRevision revision = module.getCurrentRevision(); - Generation generation = (Generation) revision.getRevisionInfo(); - if (needsDiscarding(generation)) { - needsRefresh.add(module); - moduleContainer.uninstall(module); - generation.delete(); - } - } - // Next check if we need to refresh Multi-Release Jar bundles - // because the runtime version changed. - if (refreshMRBundles.get()) { - needsRefresh.addAll(refreshMRJarBundles()); - } - - // refresh the modules that got deleted or are Multi-Release bundles - if (!needsRefresh.isEmpty()) { - moduleContainer.refresh(needsRefresh); - } - } - - private boolean needsDiscarding(Generation generation) { - for (StorageHook hook : generation.getStorageHooks()) { - try { - hook.validate(); - } catch (IllegalStateException e) { - equinoxContainer.getLogServices().log(EquinoxContainer.NAME, FrameworkLogEntry.WARNING, "Error validating installed bundle.", e); //$NON-NLS-1$ - return true; - } - } - File content = generation.getContent(); - if (content == null) { - return false; - } - if (getConfiguration().inCheckConfigurationMode()) { - if (generation.isDirectory()) { - content = new File(content, "META-INF/MANIFEST.MF"); //$NON-NLS-1$ - } - return generation.getLastModified() != secureAction.lastModified(content); - } - if (!content.exists()) { - // the content got deleted since last time! - return true; - } - return false; - } - - private void checkSystemBundle(String[] cachedInfo) { - Module systemModule = moduleContainer.getModule(0); - Generation newGeneration = null; - try { - if (systemModule == null) { - BundleInfo info = new BundleInfo(this, 0, Constants.SYSTEM_BUNDLE_LOCATION, 0); - newGeneration = info.createGeneration(); - - File contentFile = getSystemContent(); - newGeneration.setContent(contentFile, Type.DEFAULT); - - // First we must make sure the VM profile has been loaded - loadVMProfile(newGeneration); - // dealing with system bundle find the extra capabilities and exports - String extraCapabilities = getSystemExtraCapabilities(); - String extraExports = getSystemExtraPackages(); - - ModuleRevisionBuilder builder = getBuilder(newGeneration, extraCapabilities, extraExports); - systemModule = moduleContainer.install(null, Constants.SYSTEM_BUNDLE_LOCATION, builder, newGeneration); - moduleContainer.resolve(Collections.singletonList(systemModule), false); - } else { - ModuleRevision currentRevision = systemModule.getCurrentRevision(); - Generation currentGeneration = currentRevision == null ? null : (Generation) currentRevision.getRevisionInfo(); - if (currentGeneration == null) { - throw new IllegalStateException("No current revision for system bundle."); //$NON-NLS-1$ - } - try { - // First we must make sure the VM profile has been loaded - loadVMProfile(currentGeneration); - // dealing with system bundle find the extra capabilities and exports - String extraCapabilities = getSystemExtraCapabilities(); - String extraExports = getSystemExtraPackages(); - File contentFile = currentGeneration.getContent(); - if (systemNeedsUpdate(contentFile, currentRevision, currentGeneration, extraCapabilities, extraExports, cachedInfo)) { - newGeneration = currentGeneration.getBundleInfo().createGeneration(); - newGeneration.setContent(contentFile, Type.DEFAULT); - ModuleRevisionBuilder newBuilder = getBuilder(newGeneration, extraCapabilities, extraExports); - moduleContainer.update(systemModule, newBuilder, newGeneration); - moduleContainer.refresh(Collections.singleton(systemModule)); - } else { - if (currentRevision.getWiring() == null) { - // must resolve before continuing to ensure extensions get attached - moduleContainer.resolve(Collections.singleton(systemModule), true); - } - } - } catch (BundleException e) { - throw new IllegalStateException("Could not create a builder for the system bundle.", e); //$NON-NLS-1$ - } - } - ModuleRevision currentRevision = systemModule.getCurrentRevision(); - List nativeEnvironments = currentRevision.getModuleCapabilities(NativeNamespace.NATIVE_NAMESPACE); - Map configMap = equinoxContainer.getConfiguration().getInitialConfig(); - for (ModuleCapability nativeEnvironment : nativeEnvironments) { - nativeEnvironment.setTransientAttrs(configMap); - } - Version frameworkVersion = null; - if (newGeneration != null) { - frameworkVersion = findFrameworkVersion(); - } else { - String sVersion = cachedInfo[0]; - frameworkVersion = sVersion == null ? findFrameworkVersion() : Version.parseVersion(sVersion); - } - if (frameworkVersion != null) { - this.equinoxContainer.getConfiguration().setConfiguration(Constants.FRAMEWORK_VERSION, frameworkVersion.toString()); - } - } catch (Exception e) { - if (e instanceof RuntimeException) { - throw (RuntimeException) e; - } - throw new RuntimeException("Error occurred while checking the system module.", e); //$NON-NLS-1$ - } finally { - if (newGeneration != null) { - newGeneration.getBundleInfo().unlockGeneration(newGeneration); - } - } - } - - private Version findFrameworkVersion() { - Requirement osgiPackageReq = ModuleContainer.createRequirement(PackageNamespace.PACKAGE_NAMESPACE, Collections.singletonMap(Namespace.REQUIREMENT_FILTER_DIRECTIVE, "(" + PackageNamespace.PACKAGE_NAMESPACE + "=org.osgi.framework)"), Collections.emptyMap()); //$NON-NLS-1$ //$NON-NLS-2$ - Collection osgiPackages = moduleContainer.getFrameworkWiring().findProviders(osgiPackageReq); - for (BundleCapability packageCapability : osgiPackages) { - if (packageCapability.getRevision().getBundle().getBundleId() == 0) { - Version v = (Version) packageCapability.getAttributes().get(PackageNamespace.CAPABILITY_VERSION_ATTRIBUTE); - if (v != null) { - return v; - } - } - } - return null; - } - - private Collection refreshMRJarBundles() throws BundleException { - Collection mrJarBundles = new ArrayList<>(); - for (Module m : moduleContainer.getModules()) { - Generation generation = (Generation) m.getCurrentRevision().getRevisionInfo(); - // Note that we check the raw headers here incase we are working off an old version of the persistent storage - if (Boolean.parseBoolean(generation.getRawHeaders().get(BundleInfo.MULTI_RELEASE_HEADER))) { - refresh(m); - mrJarBundles.add(m); - } - } - return mrJarBundles; - } - - public void close() { - try { - save(); - } catch (IOException e) { - getLogServices().log(EquinoxContainer.NAME, FrameworkLogEntry.ERROR, "Error saving on shutdown", e); //$NON-NLS-1$ - } - - // close all the generations - List modules = moduleContainer.getModules(); - for (Module module : modules) { - for (ModuleRevision revision : module.getRevisions().getModuleRevisions()) { - Generation generation = (Generation) revision.getRevisionInfo(); - if (generation != null) { - generation.close(); - } - } - } - for (ModuleRevision removalPending : moduleContainer.getRemovalPending()) { - Generation generation = (Generation) removalPending.getRevisionInfo(); - if (generation != null) { - generation.close(); - } - } - mruList.shutdown(); - adaptor.shutdownExecutors(); - } - - private boolean systemNeedsUpdate(File systemContent, ModuleRevision currentRevision, Generation existing, String extraCapabilities, String extraExports, String[] cachedInfo) throws BundleException { - if (!extraCapabilities.equals(cachedInfo[1])) { - return true; - } - if (!extraExports.equals(cachedInfo[2])) { - return true; - } - if (systemContent == null) { - // only do a version check in this case - ModuleRevisionBuilder newBuilder = getBuilder(existing, extraCapabilities, extraExports); - return !currentRevision.getVersion().equals(newBuilder.getVersion()); - } - if (existing.isDirectory()) { - systemContent = new File(systemContent, "META-INF/MANIFEST.MF"); //$NON-NLS-1$ - } - return existing.getLastModified() != secureAction.lastModified(systemContent); - - } - - private void cleanOSGiStorage(Location location, File root) { - if (location.isReadOnly() || !StorageUtil.rm(root, getConfiguration().getDebug().DEBUG_STORAGE)) { - equinoxContainer.getLogServices().log(EquinoxContainer.NAME, FrameworkLogEntry.ERROR, "The -clean (osgi.clean) option was not successful. Unable to clean the storage area: " + root.getAbsolutePath(), null); //$NON-NLS-1$ - } - if (!location.isReadOnly()) { - // make sure to recreate to root folder - root.mkdirs(); - } - } - - public ModuleDatabase getModuleDatabase() { - return moduleDatabase; - } - - public ModuleContainerAdaptor getAdaptor() { - return adaptor; - } - - public ModuleContainer getModuleContainer() { - return moduleContainer; - } - - public EquinoxConfiguration getConfiguration() { - return equinoxContainer.getConfiguration(); - } - - public EquinoxLogServices getLogServices() { - return equinoxContainer.getLogServices(); - } - - public FrameworkExtensionInstaller getExtensionInstaller() { - return extensionInstaller; - } - - public boolean isReadOnly() { - return osgiLocation.isReadOnly(); - } - - public URLConnection getContentConnection(Module module, String bundleLocation, final InputStream in) - throws BundleException { - try { - List> storageHooks = getConfiguration().getHookRegistry() - .getStorageHookFactories(); - for (StorageHookFactory storageHook : storageHooks) { - URLConnection hookContent = storageHook.handleContentConnection(module, bundleLocation, in); - if (hookContent != null) { - return hookContent; - } - } - - if (in != null) { - return new URLConnection(null) { - /** - * @throws IOException - */ - @Override - public void connect() throws IOException { - connected = true; - } - - /** - * @throws IOException - */ - @Override - public InputStream getInputStream() throws IOException { - return (in); - } - }; - } - if (module == null) { - if (bundleLocation == null) { - throw new IllegalArgumentException("Module and location cannot be null"); //$NON-NLS-1$ - } - return getContentConnection(bundleLocation); - } - return getContentConnection(getUpdateLocation(module)); - } catch (IOException e) { - throw new BundleException("Error reading bundle content.", e); //$NON-NLS-1$ - } - } - - private String getUpdateLocation(final Module module) { - if (System.getSecurityManager() == null) - return getUpdateLocation0(module); - return AccessController.doPrivileged((PrivilegedAction) () -> getUpdateLocation0(module)); - } - - String getUpdateLocation0(Module module) { - ModuleRevision current = module.getCurrentRevision(); - Generation generation = (Generation) current.getRevisionInfo(); - String updateLocation = generation.getHeaders().get(Constants.BUNDLE_UPDATELOCATION); - if (updateLocation == null) { - updateLocation = module.getLocation(); - } - if (updateLocation.startsWith(INITIAL_LOCATION)) { - updateLocation = updateLocation.substring(INITIAL_LOCATION.length()); - } - return updateLocation; - } - - private URLConnection getContentConnection(final String spec) throws IOException { - if (System.getSecurityManager() == null) { - return LocationHelper.getConnection(createURL(spec)); - } - try { - return AccessController.doPrivileged((PrivilegedExceptionAction) () -> LocationHelper.getConnection(createURL(spec))); - } catch (PrivilegedActionException e) { - if (e.getException() instanceof IOException) - throw (IOException) e.getException(); - throw (RuntimeException) e.getException(); - } - } - - URL createURL(String spec) throws MalformedURLException { - if (spec.startsWith(URLStreamHandlerFactoryImpl.PROTOCOL_REFERENCE)) { - return new URL(null, spec, new Handler(equinoxContainer.getConfiguration().getConfiguration(EquinoxLocations.PROP_INSTALL_AREA))); - } - return new URL(spec); - } - - public Generation install(Module origin, String bundleLocation, InputStream toInstall) throws BundleException { - URLConnection content = getContentConnection(null, bundleLocation, toInstall); - if (osgiLocation.isReadOnly()) { - throw new BundleException("The framework storage area is read only.", BundleException.INVALID_OPERATION); //$NON-NLS-1$ - } - URL sourceURL = content.getURL(); - InputStream in; - try { - in = content.getInputStream(); - } catch (Throwable e) { - throw new BundleException("Error reading bundle content.", e); //$NON-NLS-1$ - } - - // Check if the bundle already exists at this location - // before doing the staging and generation creation. - // This is important since some installers seem to continually - // re-install bundles using the same location each startup - Module existingLocation = moduleContainer.getModule(bundleLocation); - if (existingLocation != null) { - // NOTE this same logic is also in the ModuleContainer - // This is necessary because the container does the location locking. - // Another thread could win the location lock and install before this thread does. - try { - in.close(); - } catch (IOException e) { - // ignore - } - if (origin != null) { - // Check that the existing location is visible from the origin module - Bundle bundle = origin.getBundle(); - BundleContext context = bundle == null ? null : bundle.getBundleContext(); - if (context != null && context.getBundle(existingLocation.getId()) == null) { - Bundle b = existingLocation.getBundle(); - throw new BundleException(NLS.bind(Msg.ModuleContainer_NameCollisionWithLocation, new Object[] {b.getSymbolicName(), b.getVersion(), bundleLocation}), BundleException.REJECTED_BY_HOOK); - } - } - return (Generation) existingLocation.getCurrentRevision().getRevisionInfo(); - } - - ContentProvider contentProvider = getContentProvider(in, sourceURL); - Type contentType = contentProvider.getType(); - File staged = contentProvider.getContent(); - - Generation generation = null; - try { - Long nextID = moduleDatabase.getAndIncrementNextId(); - BundleInfo info = new BundleInfo(this, nextID, bundleLocation, 0); - generation = info.createGeneration(); - - File contentFile = getContentFile(staged, contentType, nextID, generation.getGenerationId()); - generation.setContent(contentFile, contentType); - // Check that we can open the bundle file - generation.getBundleFile().open(); - setStorageHooks(generation); - - ModuleRevisionBuilder builder = getBuilder(generation); - builder.setId(nextID); - - Module m = moduleContainer.install(origin, bundleLocation, builder, generation); - if (!nextID.equals(m.getId())) { - // this revision is already installed. delete the generation - generation.delete(); - return (Generation) m.getCurrentRevision().getRevisionInfo(); - } - return generation; - } catch (Throwable t) { - if (contentType == Type.DEFAULT) { - try { - delete(staged); - } catch (IOException e) { - // tried our best - } - } - if (generation != null) { - generation.delete(); - generation.getBundleInfo().delete(); - } - if (t instanceof SecurityException) { - // TODO hack from ModuleContainer - // if the cause is a bundle exception then throw that - if (t.getCause() instanceof BundleException) { - throw (BundleException) t.getCause(); - } - throw (SecurityException) t; - } - if (t instanceof BundleException) { - throw (BundleException) t; - } - throw new BundleException("Error occurred installing a bundle.", t); //$NON-NLS-1$ - } finally { - if (generation != null) { - generation.getBundleInfo().unlockGeneration(generation); - } - } - } - - ContentProvider getContentProvider(final InputStream in, final URL sourceURL) { - if (in instanceof ContentProvider) { - return (ContentProvider) in; - } - return new ContentProvider() { - - @Override - public Type getType() { - return Type.DEFAULT; - } - - @Override - public File getContent() throws BundleException { - return stageContent(in, sourceURL); - } - }; - } - - private void setStorageHooks(Generation generation) throws BundleException { - if (generation.getBundleInfo().getBundleId() == 0) { - return; // ignore system bundle - } - List> factories = new ArrayList<>(getConfiguration().getHookRegistry().getStorageHookFactories()); - List> hooks = new ArrayList<>(factories.size()); - for (StorageHookFactory storageHookFactory : factories) { - @SuppressWarnings("unchecked") - StorageHookFactory> next = (StorageHookFactory>) storageHookFactory; - StorageHook hook = next.createStorageHookAndValidateFactoryClass(generation); - if (hook != null) { - hooks.add(hook); - } - } - generation.setStorageHooks(Collections.unmodifiableList(hooks), true); - for (StorageHook hook : hooks) { - hook.initialize(generation.getHeaders()); - } - } - - public ModuleRevisionBuilder getBuilder(Generation generation) throws BundleException { - return getBuilder(generation, null, null); - } - - public ModuleRevisionBuilder getBuilder(Generation generation, String extraCapabilities, String extraExports) throws BundleException { - Dictionary headers = generation.getHeaders(); - Map mapHeaders; - if (headers instanceof Map) { - @SuppressWarnings("unchecked") - Map unchecked = (Map) headers; - mapHeaders = unchecked; - } else { - mapHeaders = new HashMap<>(); - for (Enumeration eKeys = headers.keys(); eKeys.hasMoreElements();) { - String key = eKeys.nextElement(); - mapHeaders.put(key, headers.get(key)); - } - } - if (generation.getBundleInfo().getBundleId() != 0) { - ModuleRevisionBuilder builder = OSGiManifestBuilderFactory.createBuilder(mapHeaders, null, // - (generation.getContentType() == Type.CONNECT ? "" : null), //$NON-NLS-1$ - (allowRestrictedProvides ? "" : null)); //$NON-NLS-1$ - if ((builder.getTypes() & BundleRevision.TYPE_FRAGMENT) != 0) { - for (ModuleRevisionBuilder.GenericInfo reqInfo : builder.getRequirements(HostNamespace.HOST_NAMESPACE)) { - if (HostNamespace.EXTENSION_BOOTCLASSPATH.equals(reqInfo.getDirectives().get(HostNamespace.REQUIREMENT_EXTENSION_DIRECTIVE))) { - throw new BundleException("Boot classpath extensions are not supported.", //$NON-NLS-1$ - BundleException.UNSUPPORTED_OPERATION, new UnsupportedOperationException()); - } - } - } - return builder; - } - - return OSGiManifestBuilderFactory.createBuilder(mapHeaders, Constants.SYSTEM_BUNDLE_SYMBOLICNAME, extraExports, extraCapabilities); - } - - private String getSystemExtraCapabilities() { - EquinoxConfiguration equinoxConfig = equinoxContainer.getConfiguration(); - StringBuilder result = new StringBuilder(); - - String systemCapabilities = equinoxConfig.getConfiguration(Constants.FRAMEWORK_SYSTEMCAPABILITIES); - if (systemCapabilities != null && systemCapabilities.trim().length() > 0) { - result.append(systemCapabilities).append(", "); //$NON-NLS-1$ - } - - String extraSystemCapabilities = equinoxConfig.getConfiguration(Constants.FRAMEWORK_SYSTEMCAPABILITIES_EXTRA); - if (extraSystemCapabilities != null && extraSystemCapabilities.trim().length() > 0) { - result.append(extraSystemCapabilities).append(", "); //$NON-NLS-1$ - } - - result.append(EclipsePlatformNamespace.ECLIPSE_PLATFORM_NAMESPACE).append("; "); //$NON-NLS-1$ - result.append(EquinoxConfiguration.PROP_OSGI_OS).append("=").append(equinoxConfig.getOS()).append("; "); //$NON-NLS-1$ //$NON-NLS-2$ - result.append(EquinoxConfiguration.PROP_OSGI_WS).append("=").append(equinoxConfig.getWS()).append("; "); //$NON-NLS-1$ //$NON-NLS-2$ - result.append(EquinoxConfiguration.PROP_OSGI_ARCH).append("=").append(equinoxConfig.getOSArch()).append("; "); //$NON-NLS-1$ //$NON-NLS-2$ - result.append(EquinoxConfiguration.PROP_OSGI_NL).append("=").append(equinoxConfig.getNL()); //$NON-NLS-1$ - - String osName = equinoxConfig.getConfiguration(Constants.FRAMEWORK_OS_NAME); - osName = osName == null ? null : osName.toLowerCase(); - String processor = equinoxConfig.getConfiguration(Constants.FRAMEWORK_PROCESSOR); - processor = processor == null ? null : processor.toLowerCase(); - String osVersion = equinoxConfig.getConfiguration(Constants.FRAMEWORK_OS_VERSION); - osVersion = osVersion == null ? null : osVersion.toLowerCase(); - String language = equinoxConfig.getConfiguration(Constants.FRAMEWORK_LANGUAGE); - language = language == null ? null : language.toLowerCase(); - - result.append(", "); //$NON-NLS-1$ - result.append(NativeNamespace.NATIVE_NAMESPACE).append("; "); //$NON-NLS-1$ - if (osName != null) { - osName = getAliasList(equinoxConfig.getAliasMapper().getOSNameAliases(osName)); - result.append(NativeNamespace.CAPABILITY_OSNAME_ATTRIBUTE).append(":List=").append(osName).append("; "); //$NON-NLS-1$ //$NON-NLS-2$ - } - if (processor != null) { - processor = getAliasList(equinoxConfig.getAliasMapper().getProcessorAliases(processor)); - result.append(NativeNamespace.CAPABILITY_PROCESSOR_ATTRIBUTE).append(":List=").append(processor).append("; "); //$NON-NLS-1$ //$NON-NLS-2$ - } - result.append(NativeNamespace.CAPABILITY_OSVERSION_ATTRIBUTE).append(":Version").append("=\"").append(osVersion).append("\"; "); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - result.append(NativeNamespace.CAPABILITY_LANGUAGE_ATTRIBUTE).append("=\"").append(language).append('\"'); //$NON-NLS-1$ - return result.toString(); - } - - String getAliasList(Collection aliases) { - if (aliases.isEmpty()) { - return null; - } - StringBuilder builder = new StringBuilder(); - builder.append('"'); - for (String alias : aliases) { - builder.append(alias).append(','); - } - builder.setLength(builder.length() - 1); - builder.append('"'); - return builder.toString(); - } - - private String getSystemExtraPackages() { - EquinoxConfiguration equinoxConfig = equinoxContainer.getConfiguration(); - StringBuilder result = new StringBuilder(); - - String systemPackages = equinoxConfig.getConfiguration(Constants.FRAMEWORK_SYSTEMPACKAGES); - if (systemPackages != null) { - result.append(systemPackages); - } - - String extraSystemPackages = equinoxConfig.getConfiguration(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA); - if (extraSystemPackages != null && extraSystemPackages.trim().length() > 0) { - if (result.length() > 0) { - result.append(", "); //$NON-NLS-1$ - } - result.append(extraSystemPackages); - } - - return result.toString(); - } - - private void refresh(Module module) throws BundleException { - ModuleRevision current = module.getCurrentRevision(); - Generation currentGen = (Generation) current.getRevisionInfo(); - File content = currentGen.getContent(); - if (content == null) { - // TODO Handle connect bundle - return; - } - String spec = (currentGen.getContentType() == Type.REFERENCE ? "reference:" : "") + content.toURI().toString(); //$NON-NLS-1$ //$NON-NLS-2$ - URLConnection contentConn; - try { - contentConn = getContentConnection(spec); - } catch (IOException e) { - throw new BundleException("Error reading bundle content.", e); //$NON-NLS-1$ - } - update(module, contentConn); - } - - public Generation update(Module module, InputStream updateIn) throws BundleException { - return update(module, getContentConnection(module, null, updateIn)); - } - - private Generation update(Module module, URLConnection content) throws BundleException { - - if (osgiLocation.isReadOnly()) { - throw new BundleException("The framework storage area is read only.", BundleException.INVALID_OPERATION); //$NON-NLS-1$ - } - URL sourceURL = content.getURL(); - InputStream in; - try { - in = content.getInputStream(); - } catch (Throwable e) { - throw new BundleException("Error reading bundle content.", e); //$NON-NLS-1$ - } - - ContentProvider contentProvider = getContentProvider(in, sourceURL); - Type contentType = contentProvider.getType(); - File staged = contentProvider.getContent(); - - ModuleRevision current = module.getCurrentRevision(); - Generation currentGen = (Generation) current.getRevisionInfo(); - - BundleInfo bundleInfo = currentGen.getBundleInfo(); - Generation newGen = bundleInfo.createGeneration(); - - try { - File contentFile = getContentFile(staged, contentType, bundleInfo.getBundleId(), newGen.getGenerationId()); - newGen.setContent(contentFile, contentType); - // Check that we can open the bundle file - newGen.getBundleFile().open(); - setStorageHooks(newGen); - - ModuleRevisionBuilder builder = getBuilder(newGen); - moduleContainer.update(module, builder, newGen); - } catch (Throwable t) { - if (contentType == Type.DEFAULT) { - try { - delete(staged); - } catch (IOException e) { - // tried our best - } - } - newGen.delete(); - if (t instanceof SecurityException) { - // TODO hack from ModuleContainer - // if the cause is a bundle exception then throw that - if (t.getCause() instanceof BundleException) { - throw (BundleException) t.getCause(); - } - throw (SecurityException) t; - } - if (t instanceof BundleException) { - throw (BundleException) t; - } - throw new BundleException("Error occurred updating a bundle.", t); //$NON-NLS-1$ - } finally { - bundleInfo.unlockGeneration(newGen); - } - return newGen; - } - - private File getContentFile(final File staged, Type contentType, final long bundleID, final long generationID) throws BundleException { - if (System.getSecurityManager() == null) - return getContentFile0(staged, contentType, bundleID, generationID); - try { - return AccessController.doPrivileged((PrivilegedExceptionAction) () -> getContentFile0(staged, contentType, bundleID, generationID)); - } catch (PrivilegedActionException e) { - if (e.getException() instanceof BundleException) - throw (BundleException) e.getException(); - throw (RuntimeException) e.getException(); - } - } - - File getContentFile0(File staged, Type contentType, long bundleID, long generationID) throws BundleException { - File contentFile = staged; - - if (contentType == Type.DEFAULT) { - File generationRoot = new File(childRoot, bundleID + "/" + generationID); //$NON-NLS-1$ - generationRoot.mkdirs(); - if (!generationRoot.isDirectory()) { - throw new BundleException("Could not create generation directory: " + generationRoot.getAbsolutePath()); //$NON-NLS-1$ - } - contentFile = new File(generationRoot, BUNDLE_FILE_NAME); - try { - StorageUtil.move(staged, contentFile, getConfiguration().getDebug().DEBUG_STORAGE); - } catch (IOException e) { - throw new BundleException("Error while renaming bundle file to final location: " + contentFile, //$NON-NLS-1$ - BundleException.READ_ERROR, e); - } - } - return contentFile; - } - - private static String getBundleFilePath(long bundleID, long generationID) { - return bundleID + "/" + generationID + "/" + BUNDLE_FILE_NAME; //$NON-NLS-1$ //$NON-NLS-2$ - } - - /** - * Gets a file from storage and conditionally checks the parent storage area - * if the file does not exist in the child configuration. - * Note, this method does not check for escaping of paths from the root storage area. - * @param path the path relative to the root of the storage area - * @param checkParent if true then check the parent storage (if any) when the file - * does not exist in the child storage area - * @return the file being requested. A {@code null} value is never returned. The file - * returned may not exist. - * @throws StorageException if there was an issue getting the file - */ - public File getFile(String path, boolean checkParent) throws StorageException { - return getFile(null, path, checkParent); - } - - /** - * Same as {@link #getFile(String, boolean)} except takes a base parameter which is - * appended to the root storage area before looking for the path. If base is not - * null then additional checks are done to make sure the path does not escape out - * of the base path. - * @param base the additional base path to append to the root storage area. May be - * {@code null}, in which case no check is done for escaping out of the base path. - * @param path the path relative to the root + base storage area. - * @param checkParent if true then check the parent storage (if any) when the file - * does not exist in the child storage area - * @return the file being requested. A {@code null} value is never returned. The file - * returned may not exist. - * @throws StorageException if there was an issue getting the file - */ - public File getFile(String base, String path, boolean checkParent) throws StorageException { - // first check the child location - File childPath = getFile(childRoot, base, path); - // now check the parent - if (checkParent && parentRoot != null) { - if (childPath.exists()) { - return childPath; - } - File parentPath = getFile(parentRoot, base, path); - if (parentPath.exists()) { - // only use the parent file only if it exists; - return parentPath; - } - } - // did not exist in both locations; use the child path - return childPath; - } - - private static File getFile(File root, String base, String path) { - if (base == null) { - // return quick; no need to check for path traversal - return new File(root, path); - } - - // if base is not null then move root to include the base - File rootBase = new File(root, base); - File result = new File(rootBase, path); - if (path.contains("..")) { //$NON-NLS-1$ - // do the extra check to make sure the path did not escape the root path - Path resultNormalized = result.toPath().normalize(); - Path rootBaseNormalized = rootBase.toPath().normalize(); - if (!resultNormalized.startsWith(rootBaseNormalized)) { - throw new StorageException("Invalid path: " + path); //$NON-NLS-1$ - } - } - // Additional check if it is a special device instead of a regular file. - if (StorageUtil.isReservedFileName(result)) { - throw new StorageException("Invalid filename: " + path); //$NON-NLS-1$ - } - return result; - } - - File stageContent(final InputStream in, final URL sourceURL) throws BundleException { - if (System.getSecurityManager() == null) - return stageContent0(in, sourceURL); - try { - return AccessController.doPrivileged((PrivilegedExceptionAction) () -> stageContent0(in, sourceURL)); - } catch (PrivilegedActionException e) { - if (e.getException() instanceof BundleException) - throw (BundleException) e.getException(); - throw (RuntimeException) e.getException(); - } - } - - File stageContent0(InputStream in, URL sourceURL) throws BundleException { - File outFile = null; - try (InputStream stream = in) { - outFile = ReliableFile.createTempFile(BUNDLE_FILE_NAME, ".tmp", childRoot); //$NON-NLS-1$ - String protocol = sourceURL == null ? null : sourceURL.getProtocol(); - - if ("file".equals(protocol)) { //$NON-NLS-1$ - File inFile = new File(sourceURL.getPath()); - inFile = LocationHelper.decodePath(inFile); - if (inFile.isDirectory()) { - // need to delete the outFile because it is not a directory - outFile.delete(); - } - StorageUtil.copy(inFile, outFile); - } else { - StorageUtil.readFile(in, outFile); - } - return outFile; - } catch (IOException e) { - if (outFile != null) { - outFile.delete(); - } - throw new BundleException(Msg.BUNDLE_READ_EXCEPTION, BundleException.READ_ERROR, e); - } - } - - /** - * Attempts to set the permissions of the file in a system dependent way. - * @param file the file to set the permissions on - */ - public void setPermissions(File file) { - String commandProp = getConfiguration().getConfiguration(EquinoxConfiguration.PROP_SETPERMS_CMD); - if (commandProp == null) - commandProp = getConfiguration().getConfiguration(Constants.FRAMEWORK_EXECPERMISSION); - if (commandProp == null) - return; - String[] commandComponents = ManifestElement.getArrayFromList(commandProp, " "); //$NON-NLS-1$ - List command = new ArrayList<>(commandComponents.length + 1); - boolean foundFullPath = false; - for (String commandComponent : commandComponents) { - if ("[fullpath]".equals(commandComponent) || "${abspath}".equals(commandComponent)) { //$NON-NLS-1$ //$NON-NLS-2$ - command.add(file.getAbsolutePath()); - foundFullPath = true; - } else { - command.add(commandComponent); - } - } - if (!foundFullPath) - command.add(file.getAbsolutePath()); - try { - Runtime.getRuntime().exec(command.toArray(new String[command.size()])).waitFor(); - } catch (Exception e) { - e.printStackTrace(); - } - } - - public BundleFile createBundleFile(File content, Generation generation, boolean isDirectory, boolean isBase) { - BundleFile result = null; - ConnectModule connectModule = null; - if (generation.getContentType() == Type.CONNECT) { - connectModule = equinoxContainer.getConnectModules().getConnectModule(generation.getBundleInfo().getLocation()); - } - try { - if (connectModule != null && isBase) { - result = equinoxContainer.getConnectModules().getConnectBundleFile(connectModule, content, generation, - mruList, getConfiguration().getDebug()); - } else if (isDirectory) { - boolean strictPath = Boolean.parseBoolean(getConfiguration().getConfiguration( - EquinoxConfiguration.PROPERTY_STRICT_BUNDLE_ENTRY_PATH, Boolean.FALSE.toString())); - result = new DirBundleFile(content, strictPath); - } else { - result = new ZipBundleFile(content, generation, mruList, getConfiguration().getDebug(), - getConfiguration().runtimeVerifySignedBundles); - } - } catch (IOException e) { - throw new RuntimeException("Could not create bundle file.", e); //$NON-NLS-1$ - } - return wrapBundleFile(result, generation, isBase); - } - - public BundleFile createNestedBundleFile(String nestedDir, BundleFile bundleFile, Generation generation) { - return createNestedBundleFile(nestedDir, bundleFile, generation, Collections.emptyList()); - } - - public BundleFile createNestedBundleFile(String nestedDir, BundleFile bundleFile, Generation generation, Collection filterPrefixes) { - // here we assume the content is a path offset into the base bundle file; create a NestedDirBundleFile - return wrapBundleFile(new NestedDirBundleFile(bundleFile, nestedDir, filterPrefixes), generation, false); - } - - public BundleFile wrapBundleFile(BundleFile bundleFile, Generation generation, boolean isBase) { - // try creating a wrapper bundlefile out of it. - List wrapperFactories = getConfiguration().getHookRegistry().getBundleFileWrapperFactoryHooks(); - BundleFileWrapperChain wrapped = wrapperFactories.isEmpty() ? null : new BundleFileWrapperChain(bundleFile, null); - for (BundleFileWrapperFactoryHook wrapperFactory : wrapperFactories) { - BundleFileWrapper wrapperBundle = wrapperFactory.wrapBundleFile(bundleFile, generation, isBase); - if (wrapperBundle != null && wrapperBundle != bundleFile) - bundleFile = wrapped = new BundleFileWrapperChain(wrapperBundle, wrapped); - } - - return bundleFile; - } - - public void compact() { - if (!osgiLocation.isReadOnly()) { - compact(childRoot); - } - } - - private void compact(File directory) { - if (getConfiguration().getDebug().DEBUG_STORAGE) - Debug.println("compact(" + directory.getPath() + ")"); //$NON-NLS-1$ //$NON-NLS-2$ - String list[] = directory.list(); - if (list == null) - return; - - int len = list.length; - for (int i = 0; i < len; i++) { - if (BUNDLE_DATA_DIR.equals(list[i])) - continue; /* do not examine the bundles data dir. */ - File target = new File(directory, list[i]); - // if the file is a directory - if (!target.isDirectory()) - continue; - File delete = new File(target, DELETE_FLAG); - // and the directory is marked for delete - if (delete.exists()) { - try { - deleteFlaggedDirectory(target); - } catch (IOException e) { - if (getConfiguration().getDebug().DEBUG_STORAGE) { - Debug.println("Unable to write " + delete.getPath() + ": " + e.getMessage()); //$NON-NLS-1$ //$NON-NLS-2$ - } - } - } else { - compact(target); /* descend into directory */ - } - } - } - - void delete(final File delete) throws IOException { - if (System.getSecurityManager() == null) { - deleteFlaggedDirectory(delete); - } else { - try { - AccessController.doPrivileged((PrivilegedExceptionAction) () -> { - deleteFlaggedDirectory(delete); - return null; - }); - } catch (PrivilegedActionException e) { - if (e.getException() instanceof IOException) - throw (IOException) e.getException(); - throw (RuntimeException) e.getException(); - } - } - } - - private void deleteFlaggedDirectory(File delete) throws IOException { - if (!StorageUtil.rm(delete, getConfiguration().getDebug().DEBUG_STORAGE)) { - ensureDeleteFlagFileExists(delete.toPath()); - } - } - - public void save() throws IOException { - if (isReadOnly()) { - return; - } - if (System.getSecurityManager() == null) { - save0(); - } else { - try { - AccessController.doPrivileged((PrivilegedExceptionAction) () -> { - save0(); - return null; - }); - } catch (PrivilegedActionException e) { - if (e.getException() instanceof IOException) - throw (IOException) e.getException(); - throw (RuntimeException) e.getException(); - } - } - } - - void save0() throws IOException { - StorageManager childStorageManager = null; - ManagedOutputStream mos = null; - DataOutputStream out = null; - boolean success = false; - moduleDatabase.readLock(); - synchronized (this.saveMonitor) { - try { - if (lastSavedTimestamp == moduleDatabase.getTimestamp()) - return; - childStorageManager = getChildStorageManager(); - mos = childStorageManager.getOutputStream(FRAMEWORK_INFO); - out = new DataOutputStream(new BufferedOutputStream(mos)); - saveGenerations(out); - savePermissionData(out); - moduleDatabase.store(out, true); - lastSavedTimestamp = moduleDatabase.getTimestamp(); - success = true; - } finally { - moduleDatabase.readUnlock(); - if (!success) { - if (mos != null) { - mos.abort(); - } - } - if (out != null) { - try { - out.close(); - } catch (IOException e) { - // tried our best - } - } - if (childStorageManager != null) { - childStorageManager.close(); - } - } - } - } - - private void savePermissionData(DataOutputStream out) throws IOException { - permissionData.savePermissionData(out); - } - - private void saveGenerations(DataOutputStream out) throws IOException { - List modules = moduleContainer.getModules(); - List generations = new ArrayList<>(); - for (Module module : modules) { - ModuleRevision revision = module.getCurrentRevision(); - if (revision != null) { - Generation generation = (Generation) revision.getRevisionInfo(); - if (generation != null) { - generations.add(generation); - } - } - } - out.writeInt(VERSION); - - out.writeUTF(runtimeVersion.toString()); - - Version curFrameworkVersion = findFrameworkVersion(); - out.writeUTF(curFrameworkVersion == null ? Version.emptyVersion.toString() : curFrameworkVersion.toString()); - - saveLongString(out, getSystemExtraCapabilities()); - saveLongString(out, getSystemExtraPackages()); - - out.writeInt(cachedHeaderKeys.size()); - for (String headerKey : cachedHeaderKeys) { - out.writeUTF(headerKey); - } - - out.writeInt(generations.size()); - for (Generation generation : generations) { - BundleInfo bundleInfo = generation.getBundleInfo(); - out.writeLong(bundleInfo.getBundleId()); - out.writeUTF(bundleInfo.getLocation()); - out.writeLong(bundleInfo.getNextGenerationId()); - out.writeLong(generation.getGenerationId()); - out.writeBoolean(generation.isDirectory()); - Type contentType = generation.getContentType(); - out.writeInt(contentType.ordinal()); - out.writeBoolean(generation.hasPackageInfo()); - if (bundleInfo.getBundleId() == 0 || contentType == Type.CONNECT) { - // just write empty string for system bundle content and connect content in this case - out.writeUTF(""); //$NON-NLS-1$ - } else { - if (contentType == Type.REFERENCE) { - // make reference installs relative to the install path - out.writeUTF(new FilePath(installPath).makeRelative(new FilePath(generation.getContent().getAbsolutePath()))); - } else { - // make normal installs relative to the storage area - out.writeUTF(Storage.getBundleFilePath(bundleInfo.getBundleId(), generation.getGenerationId())); - } - } - out.writeLong(generation.getLastModified()); - - Dictionary headers = generation.getHeaders(); - for (String headerKey : cachedHeaderKeys) { - String value = headers.get(headerKey); - if (value != null) { - out.writeUTF(value); - } else { - out.writeUTF(NUL); - } - } - - out.writeBoolean(generation.isMRJar()); - } - - saveStorageHookData(out, generations); - } - - private void saveLongString(DataOutputStream out, String value) throws IOException { - if (value == null) { - out.writeInt(0); - } else { - // don't use out.writeUTF because it has a hard string limit - byte[] data = value.getBytes(StandardCharsets.UTF_8); - out.writeInt(data.length); - out.write(data); - } - } - - private String readLongString(DataInputStream in) throws IOException { - int length = in.readInt(); - byte[] data = new byte[length]; - in.readFully(data); - return new String(data, StandardCharsets.UTF_8); - } - - private void saveStorageHookData(DataOutputStream out, List generations) throws IOException { - List> factories = getConfiguration().getHookRegistry().getStorageHookFactories(); - out.writeInt(factories.size()); - for (StorageHookFactory factory : factories) { - out.writeUTF(factory.getKey()); - out.writeInt(factory.getStorageVersion()); - - // create a temporary in memory stream so we can figure out the length - ByteArrayOutputStream tempBytes = new ByteArrayOutputStream(); - try (DataOutputStream temp = new DataOutputStream(tempBytes)) { - Object saveContext = factory.createSaveContext(); - for (Generation generation : generations) { - if (generation.getBundleInfo().getBundleId() == 0) { - continue; // ignore system bundle - } - @SuppressWarnings({"rawtypes", "unchecked"}) - StorageHook hook = generation.getStorageHook((Class) factory.getClass()); - if (hook != null) { - hook.save(saveContext, temp); - } - } - } - out.writeInt(tempBytes.size()); - out.write(tempBytes.toByteArray()); - } - } - - private Map loadGenerations(DataInputStream in, String[] cachedInfo) throws IOException { - if (in == null) { - return new HashMap<>(0); - } - int version = in.readInt(); - if (version > VERSION || version < LOWEST_VERSION_SUPPORTED) { - throw new IllegalArgumentException("Found persistent version \"" + version + "\" expecting \"" + VERSION + "\""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - } - Version savedRuntimeVersion = (version >= MR_JAR_VERSION) ? Version.parseVersion(in.readUTF()) : null; - if (savedRuntimeVersion == null || !savedRuntimeVersion.equals(runtimeVersion)) { - refreshMRBundles.set(true); - } - - cachedInfo[0] = (version >= CACHED_SYSTEM_CAPS_VERION) ? in.readUTF() : null; - cachedInfo[1] = (version >= CACHED_SYSTEM_CAPS_VERION) ? readLongString(in) : null; - cachedInfo[2] = (version >= CACHED_SYSTEM_CAPS_VERION) ? readLongString(in) : null; - - int numCachedHeaders = in.readInt(); - List storedCachedHeaderKeys = new ArrayList<>(numCachedHeaders); - for (int i = 0; i < numCachedHeaders; i++) { - storedCachedHeaderKeys.add(ObjectPool.intern(in.readUTF())); - } - - int numInfos = in.readInt(); - Map result = new HashMap<>(numInfos); - List generations = new ArrayList<>(numInfos); - Type[] contentTypes = Type.values(); - for (int i = 0; i < numInfos; i++) { - long infoId = in.readLong(); - String infoLocation = ObjectPool.intern(in.readUTF()); - long nextGenId = in.readLong(); - long generationId = in.readLong(); - boolean isDirectory = in.readBoolean(); - - Type contentType = Type.DEFAULT; - if (version >= CONTENT_TYPE_VERSION) { - contentType = contentTypes[in.readInt()]; - } else { - if (in.readBoolean()) { - contentType = Type.REFERENCE; - } - } - - boolean hasPackageInfo = in.readBoolean(); - String contentPath = in.readUTF(); - long lastModified = in.readLong(); - - Map cachedHeaders = new HashMap<>(storedCachedHeaderKeys.size()); - for (String headerKey : storedCachedHeaderKeys) { - String value = in.readUTF(); - if (NUL.equals(value)) { - value = null; - } else { - value = ObjectPool.intern(value); - } - cachedHeaders.put(headerKey, value); - } - boolean isMRJar = (version >= MR_JAR_VERSION) ? in.readBoolean() : false; - - File content = null; - if (contentType != Type.CONNECT) { - if (infoId == 0) { - content = getSystemContent(); - isDirectory = content != null ? content.isDirectory() : false; - // Note that we do not do any checking for absolute paths with - // the system bundle. We always take the content as discovered - // by getSystemContent() - } else { - content = new File(contentPath); - if (!content.isAbsolute()) { - // make sure it has the absolute location instead - switch (contentType) { - case REFERENCE: - // reference installs are relative to the installPath - content = new File(installPath, contentPath); - break; - case DEFAULT: - // normal installs are relative to the storage area - content = getFile(contentPath, true); - break; - default: - throw new IllegalArgumentException("Unknown type: " + contentType); //$NON-NLS-1$ - } - } - } - } - BundleInfo info = new BundleInfo(this, infoId, infoLocation, nextGenId); - Generation generation = info.restoreGeneration(generationId, content, isDirectory, contentType, hasPackageInfo, cachedHeaders, lastModified, isMRJar); - result.put(infoId, generation); - generations.add(generation); - } - - connectPersistentBundles(generations); - loadStorageHookData(generations, in); - return result; - } - - private void connectPersistentBundles(List generations) { - generations.forEach(g -> { - try { - if (g.getContentType() == Type.CONNECT) { - equinoxContainer.getConnectModules().connect(g.getBundleInfo().getLocation()); - } - } catch (IllegalStateException e) { - if (!(e.getCause() instanceof BundleException)) { - throw e; - } - } - }); - } - - private void loadStorageHookData(List generations, DataInputStream in) throws IOException { - List> factories = new ArrayList<>(getConfiguration().getHookRegistry().getStorageHookFactories()); - Map>> hookMap = new HashMap<>(); - int numFactories = in.readInt(); - for (int i = 0; i < numFactories; i++) { - String factoryName = in.readUTF(); - int version = in.readInt(); - StorageHookFactory> factory = null; - for (Iterator> iFactories = factories.iterator(); iFactories.hasNext();) { - @SuppressWarnings("unchecked") - StorageHookFactory> next = (StorageHookFactory>) iFactories.next(); - if (next.getKey().equals(factoryName)) { - factory = next; - iFactories.remove(); - break; - } - } - int dataSize = in.readInt(); - byte[] bytes = new byte[dataSize]; - in.readFully(bytes); - if (factory != null) { - try (DataInputStream temp = new DataInputStream(new ByteArrayInputStream(bytes))) { - if (factory.isCompatibleWith(version)) { - Object loadContext = factory.createLoadContext(version); - for (Generation generation : generations) { - if (generation.getBundleInfo().getBundleId() == 0) { - continue; // ignore system bundle - } - StorageHook hook = factory.createStorageHookAndValidateFactoryClass(generation); - if (hook != null) { - hook.load(loadContext, temp); - getHooks(hookMap, generation).add(hook); - } - } - } else { - // recover by reinitializing the hook - for (Generation generation : generations) { - if (generation.getBundleInfo().getBundleId() == 0) { - continue; // ignore system bundle - } - StorageHook hook = factory.createStorageHookAndValidateFactoryClass(generation); - if (hook != null) { - hook.initialize(generation.getHeaders()); - getHooks(hookMap, generation).add(hook); - } - } - } - } catch (BundleException e) { - throw new IOException(e); - } - } - } - // now we need to recover for any hooks that are left - for (StorageHookFactory storageHookFactory : factories) { - @SuppressWarnings("unchecked") - StorageHookFactory> next = (StorageHookFactory>) storageHookFactory; - // recover by reinitializing the hook - for (Generation generation : generations) { - if (generation.getBundleInfo().getBundleId() == 0) { - continue; // ignore system bundle - } - StorageHook hook = next.createStorageHookAndValidateFactoryClass(generation); - if (hook != null) { - try { - hook.initialize(generation.getHeaders()); - getHooks(hookMap, generation).add(hook); - } catch (BundleException e) { - throw new IOException(e); - } - } - } - } - // now set the hooks to the generations - for (Generation generation : generations) { - generation.setStorageHooks(Collections.unmodifiableList(getHooks(hookMap, generation)), false); - } - } - - private static List> getHooks(Map>> hookMap, Generation generation) { - List> result = hookMap.get(generation); - if (result == null) { - result = new ArrayList<>(); - hookMap.put(generation, result); - } - return result; - } - - private File getSystemContent() { - String frameworkValue = equinoxContainer.getConfiguration().getConfiguration(EquinoxConfiguration.PROP_FRAMEWORK); - if (frameworkValue == null || !frameworkValue.startsWith("file:")) { //$NON-NLS-1$ - return null; - } - // TODO assumes the location is a file URL - File result = new File(frameworkValue.substring(5)).getAbsoluteFile(); - if (!result.exists()) { - throw new IllegalStateException("Configured framework location does not exist: " + result.getAbsolutePath()); //$NON-NLS-1$ - } - return result; - } - - @SuppressWarnings("deprecation") - private void loadVMProfile(Generation systemGeneration) { - EquinoxConfiguration equinoxConfig = equinoxContainer.getConfiguration(); - Properties profileProps = findVMProfile(systemGeneration); - String systemExports = equinoxConfig.getConfiguration(Constants.FRAMEWORK_SYSTEMPACKAGES); - // set the system exports property using the vm profile; only if the property is not already set - if (systemExports == null) { - systemExports = profileProps.getProperty(Constants.FRAMEWORK_SYSTEMPACKAGES); - if (systemExports != null) - equinoxConfig.setConfiguration(Constants.FRAMEWORK_SYSTEMPACKAGES, systemExports); - } - - // set the org.osgi.framework.bootdelegation property according to the java profile - String type = equinoxConfig.getConfiguration(EquinoxConfiguration.PROP_OSGI_JAVA_PROFILE_BOOTDELEGATION); // a null value means ignore - String profileBootDelegation = profileProps.getProperty(Constants.FRAMEWORK_BOOTDELEGATION); - if (EquinoxConfiguration.PROP_OSGI_BOOTDELEGATION_OVERRIDE.equals(type)) { - if (profileBootDelegation == null) - equinoxConfig.clearConfiguration(Constants.FRAMEWORK_BOOTDELEGATION); // override with a null value - else - equinoxConfig.setConfiguration(Constants.FRAMEWORK_BOOTDELEGATION, profileBootDelegation); // override with the profile value - } else if (EquinoxConfiguration.PROP_OSGI_BOOTDELEGATION_NONE.equals(type)) - equinoxConfig.clearConfiguration(Constants.FRAMEWORK_BOOTDELEGATION); // remove the bootdelegation property in case it was set - // set the org.osgi.framework.executionenvironment property according to the java profile - if (equinoxConfig.getConfiguration(Constants.FRAMEWORK_EXECUTIONENVIRONMENT) == null) { - // get the ee from the java profile; if no ee is defined then try the java profile name - String ee = profileProps.getProperty(Constants.FRAMEWORK_EXECUTIONENVIRONMENT, profileProps.getProperty(EquinoxConfiguration.PROP_OSGI_JAVA_PROFILE_NAME)); - if (ee != null) - equinoxConfig.setConfiguration(Constants.FRAMEWORK_EXECUTIONENVIRONMENT, ee); - } - // set the org.osgi.framework.system.capabilities property according to the java profile - if (equinoxConfig.getConfiguration(Constants.FRAMEWORK_SYSTEMCAPABILITIES) == null) { - String systemCapabilities = profileProps.getProperty(Constants.FRAMEWORK_SYSTEMCAPABILITIES); - if (systemCapabilities != null) - equinoxConfig.setConfiguration(Constants.FRAMEWORK_SYSTEMCAPABILITIES, systemCapabilities); - } - } - - private Properties findVMProfile(Generation systemGeneration) { - Properties result = readConfiguredJavaProfile(systemGeneration); - String vmProfile = null; - try { - if (result != null) { - return result; - } - - if (Version.valueOf("9").compareTo(runtimeVersion) <= 0) { //$NON-NLS-1$ - result = calculateVMProfile(runtimeVersion); - if (result != null) { - return result; - } - // could not calculate; fall back to reading profile files - } - - String embeddedProfileName = "-"; //$NON-NLS-1$ - // If javaSE 1.8 then check for release file for profile name. - if (runtimeVersion != null && Version.valueOf("1.8").compareTo(runtimeVersion) <= 0) { //$NON-NLS-1$ - String javaHome = System.getProperty("java.home"); //$NON-NLS-1$ - if (javaHome != null) { - File release = new File(javaHome, "release"); //$NON-NLS-1$ - if (release.exists()) { - Properties releaseProps = new Properties(); - try (InputStream releaseStream = new FileInputStream(release)) { - releaseProps.load(releaseStream); - String releaseName = releaseProps.getProperty("JAVA_PROFILE"); //$NON-NLS-1$ - if (releaseName != null) { - // make sure to remove extra quotes - releaseName = releaseName.replaceAll("^\\s*\"?|\"?\\s*$", ""); //$NON-NLS-1$ //$NON-NLS-2$ - embeddedProfileName = "_" + releaseName + "-"; //$NON-NLS-1$ //$NON-NLS-2$ - } - } catch (IOException e) { - // ignore - } - } - } - } - - result = new Properties(); - vmProfile = JAVASE + embeddedProfileName + javaSpecVersion; - try (InputStream profileIn = createProfileStream(systemGeneration, vmProfile, embeddedProfileName)) { - if (profileIn != null) { - result.load(profileIn); - } - } catch (IOException e) { - // ignore - // TODO consider logging ... - } - } finally { - // set the profile name if it does not provide one - if (result != null && result.getProperty(EquinoxConfiguration.PROP_OSGI_JAVA_PROFILE_NAME) == null) { - if (vmProfile != null) { - result.put(EquinoxConfiguration.PROP_OSGI_JAVA_PROFILE_NAME, vmProfile.replace('_', '/')); - } else { - // last resort; default to the absolute minimum profile name for the framework - result.put(EquinoxConfiguration.PROP_OSGI_JAVA_PROFILE_NAME, "JavaSE-1.7"); //$NON-NLS-1$ - } - } - } - return result; - } - - private InputStream createProfileStream(Generation systemGeneration, String vmProfile, - String embeddedProfileName) { - InputStream profileIn = null; - if (vmProfile != null) { - // look for a profile in the system bundle based on the vm profile - String javaProfile = vmProfile + PROFILE_EXT; - profileIn = findInSystemBundle(systemGeneration, javaProfile); - if (profileIn == null) { - profileIn = getNextBestProfile(systemGeneration, JAVASE, runtimeVersion, embeddedProfileName); - } - } - if (profileIn == null) { - // the profile url is still null then use the min profile the framework can use - profileIn = findInSystemBundle(systemGeneration, "JavaSE-1.8.profile"); //$NON-NLS-1$ - } - return profileIn; - } - - private Properties readConfiguredJavaProfile(Generation systemGeneration) { - // check for the java profile property for a url - String propJavaProfile = equinoxContainer.getConfiguration().getConfiguration(EquinoxConfiguration.PROP_OSGI_JAVA_PROFILE); - if (propJavaProfile != null) { - try (InputStream profileIn = createPropStream(systemGeneration, propJavaProfile)){ - if (profileIn != null) { - Properties result = new Properties(); - result.load(profileIn); - return result; - } - } catch (IOException e) { - // consider logging - } - } - return null; - } - - private InputStream createPropStream(Generation systemGeneration, String propJavaProfile) { - try { - // we assume a URL - return new URL(propJavaProfile).openStream(); - } catch (IOException e) { - // try using a relative path in the system bundle - return findInSystemBundle(systemGeneration, propJavaProfile); - } - } - - @SuppressWarnings("deprecation") - private Properties calculateVMProfile(Version javaVersion) { - String systemPackages = calculateVMPackages(); - if (systemPackages == null) { - return null; - } - String executionEnvs = calculateVMExecutionEnvs(javaVersion); - String eeCapabilities = calculateEECapabilities(javaVersion); - - Properties result = new Properties(); - result.put(Constants.FRAMEWORK_SYSTEMPACKAGES, systemPackages); - result.put(Constants.FRAMEWORK_EXECUTIONENVIRONMENT, executionEnvs); - result.put(Constants.FRAMEWORK_SYSTEMCAPABILITIES, eeCapabilities); - return result; - } - - private String calculateVMExecutionEnvs(Version javaVersion) { - StringBuilder result = new StringBuilder("OSGi/Minimum-1.0, OSGi/Minimum-1.1, OSGi/Minimum-1.2, JavaSE/compact1-1.8, JavaSE/compact2-1.8, JavaSE/compact3-1.8, JRE-1.1, J2SE-1.2, J2SE-1.3, J2SE-1.4, J2SE-1.5, JavaSE-1.6, JavaSE-1.7, JavaSE-1.8"); //$NON-NLS-1$ - Version v = new Version(9, 0, 0); - while (v.compareTo(javaVersion) <= 0) { - result.append(',').append(' ').append(JAVASE).append('-').append(v.getMajor()); - if (v.getMinor() > 0) { - result.append('.').append(v.getMinor()); - } - if (v.getMajor() == javaVersion.getMajor()) { - v = new Version(v.getMajor(), v.getMinor() + 1, 0); - } else { - v = new Version(v.getMajor() + 1, 0, 0); - } - } - return result.toString(); - } - - private String calculateEECapabilities(Version javaVersion) { - Version v = new Version(9, 0, 0); - StringBuilder versionsBulder = new StringBuilder(); - while (v.compareTo(javaVersion) <= 0) { - versionsBulder.append(',').append(' ').append(v.getMajor()).append('.').append(v.getMinor()); - if (v.getMajor() == javaVersion.getMajor()) { - v = new Version(v.getMajor(), v.getMinor() + 1, 0); - } else { - v = new Version(v.getMajor() + 1, 0, 0); - } - } - String versionsList = versionsBulder.toString(); - - StringBuilder result = new StringBuilder("osgi.ee; osgi.ee=\"OSGi/Minimum\"; version:List=\"1.0, 1.1, 1.2\", osgi.ee; osgi.ee=\"JRE\"; version:List=\"1.0, 1.1\", osgi.ee; osgi.ee=\"JavaSE\"; version:List=\"1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8"); //$NON-NLS-1$ - result.append(versionsList).append("\""); //$NON-NLS-1$ - result.append(",osgi.ee; osgi.ee=\"JavaSE/compact1\"; version:List=\"1.8"); //$NON-NLS-1$ - result.append(versionsList).append("\""); //$NON-NLS-1$ - result.append(",osgi.ee; osgi.ee=\"JavaSE/compact2\"; version:List=\"1.8"); //$NON-NLS-1$ - result.append(versionsList).append("\""); //$NON-NLS-1$ - result.append(",osgi.ee; osgi.ee=\"JavaSE/compact3\"; version:List=\"1.8"); //$NON-NLS-1$ - result.append(versionsList).append("\""); //$NON-NLS-1$ - - return result.toString(); - } - - @SuppressWarnings("unchecked") - private String calculateVMPackages() { - try { - List packages = new ArrayList<>(); - Method classGetModule = Class.class.getMethod("getModule"); //$NON-NLS-1$ - Object thisModule = classGetModule.invoke(getClass()); - Class moduleLayerClass = Class.forName("java.lang.ModuleLayer"); //$NON-NLS-1$ - Method boot = moduleLayerClass.getMethod("boot"); //$NON-NLS-1$ - Method modules = moduleLayerClass.getMethod("modules"); //$NON-NLS-1$ - Class moduleClass = Class.forName("java.lang.Module"); //$NON-NLS-1$ - Method getDescriptor = moduleClass.getMethod("getDescriptor"); //$NON-NLS-1$ - Class moduleDescriptorClass = Class.forName("java.lang.module.ModuleDescriptor"); //$NON-NLS-1$ - Method exports = moduleDescriptorClass.getMethod("exports"); //$NON-NLS-1$ - Method isAutomatic = moduleDescriptorClass.getMethod("isAutomatic"); //$NON-NLS-1$ - Method packagesMethod = moduleDescriptorClass.getMethod("packages"); //$NON-NLS-1$ - Class exportsClass = Class.forName("java.lang.module.ModuleDescriptor$Exports"); //$NON-NLS-1$ - Method isQualified = exportsClass.getMethod("isQualified"); //$NON-NLS-1$ - Method source = exportsClass.getMethod("source"); //$NON-NLS-1$ - - Object bootLayer = boot.invoke(null); - Set bootModules = (Set) modules.invoke(bootLayer); - for (Object m : bootModules) { - if (m.equals(thisModule)) { - // Do not calculate the exports from the framework module. - // This is to handle the case where the framework is on the module path - // to avoid double exports from the system.bundles - continue; - } - Object descriptor = getDescriptor.invoke(m); - if ((Boolean) isAutomatic.invoke(descriptor)) { - /* - * Automatic modules are supposed to export all their packages. - * However, java.lang.module.ModuleDescriptor::exports returns an empty set for them. - * Add all their packages (as returned by java.lang.module.ModuleDescriptor::packages) - * to the list of VM supplied packages. - */ - packages.addAll((Set) packagesMethod.invoke(descriptor)); - } else { - for (Object export : (Set) exports.invoke(descriptor)) { - String pkg = (String) source.invoke(export); - if (!((Boolean) isQualified.invoke(export))) { - packages.add(pkg); - } - } - } - } - Collections.sort(packages); - StringBuilder result = new StringBuilder(); - for (String pkg : packages) { - if (result.length() != 0) { - result.append(',').append(' '); - } - result.append(pkg); - } - return result.toString(); - } catch (Exception e) { - equinoxContainer.getLogServices().log(EquinoxContainer.NAME, FrameworkLogEntry.ERROR, "Error determining system packages.", e); //$NON-NLS-1$ - return null; - } - } - - private InputStream getNextBestProfile(Generation systemGeneration, String javaEdition, Version javaVersion, String embeddedProfileName) { - if (javaVersion == null || javaEdition != JAVASE) - return null; // we cannot automatically choose the next best profile unless this is a JavaSE vm - InputStream bestProfile = findNextBestProfile(systemGeneration, javaEdition, javaVersion, embeddedProfileName); - if (bestProfile == null && !"-".equals(embeddedProfileName)) { //$NON-NLS-1$ - // Just use the base javaEdition name without the profile name as backup - return getNextBestProfile(systemGeneration, javaEdition, javaVersion, "-"); //$NON-NLS-1$ - } - return bestProfile; - } - - private InputStream findNextBestProfile(Generation systemGeneration, String javaEdition, Version javaVersion, String embeddedProfileName) { - InputStream result = null; - int major = javaVersion.getMajor(); - int minor = javaVersion.getMinor(); - do { - // If minor is zero then it is not included in the name - String profileResourceName = javaEdition + embeddedProfileName + major + ((minor > 0) ? "." + minor : "") + PROFILE_EXT; //$NON-NLS-1$ //$NON-NLS-2$ - result = findInSystemBundle(systemGeneration, profileResourceName); - if (minor > 0) { - minor -= 1; - } else if (major > 9) { - major -= 1; - } else if (major <= 9 && major > 1) { - minor = 8; - major = 1; - } else { - // we have reached the end of our search; return the existing result; - return result; - } - } while (result == null && minor >= 0); - return result; - } - - private InputStream findInSystemBundle(Generation systemGeneration, String entry) { - BundleFile systemContent = systemGeneration.getBundleFile(); - BundleEntry systemEntry = systemContent != null ? systemContent.getEntry(entry) : null; - InputStream result = null; - if (systemEntry != null) { - try { - result = systemEntry.getInputStream(); - } catch (IOException e) { - // Do nothing - } - } - if (result == null) { - // Check the ClassLoader in case we're launched off the Java boot classpath - ClassLoader loader = getClass().getClassLoader(); - result = loader == null ? ClassLoader.getSystemResourceAsStream(entry) : loader.getResourceAsStream(entry); - } - return result; - } - - public static Enumeration findEntries(List generations, String path, String filePattern, int options) { - List bundleFiles = new ArrayList<>(generations.size()); - for (Generation generation : generations) - bundleFiles.add(generation.getBundleFile()); - // search all the bundle files - List pathList = listEntryPaths(bundleFiles, path, filePattern, options); - // return null if no entries found - if (pathList.size() == 0) - return null; - // create an enumeration to enumerate the pathList (generations must not change) - Stream entries = pathList.stream().flatMap(p -> generations.stream().map(g -> g.getEntry(p))) - .filter(Objects::nonNull); - return InternalUtils.asEnumeration(entries.iterator()); - } - - /** - * Returns the names of resources available from a list of bundle files. - * No duplicate resource names are returned, each name is unique. - * @param bundleFiles the list of bundle files to search in - * @param path The path name in which to look. - * @param filePattern The file name pattern for selecting resource names in - * the specified path. - * @param options The options for listing resource names. - * @return a list of resource names. If no resources are found then - * the empty list is returned. - * @see BundleWiring#listResources(String, String, int) - */ - public static List listEntryPaths(List bundleFiles, String path, String filePattern, int options) { - // Use LinkedHashSet for optimized performance of contains() plus - // ordering guarantees. - LinkedHashSet pathList = new LinkedHashSet<>(); - Filter patternFilter = null; - Hashtable patternProps = null; - if (filePattern != null) { - // Optimization: If the file pattern does not include a wildcard or escape char then it must represent a single file. - // Avoid pattern matching and use BundleFile.getEntry() if recursion was not requested. - if ((options & BundleWiring.FINDENTRIES_RECURSE) == 0 && filePattern.indexOf('*') == -1 && filePattern.indexOf('\\') == -1) { - if (path.length() == 0) - path = filePattern; - else - path += path.charAt(path.length() - 1) == '/' ? filePattern : '/' + filePattern; - for (BundleFile bundleFile : bundleFiles) { - if (bundleFile.getEntry(path) != null && !pathList.contains(path)) - pathList.add(path); - } - return new ArrayList<>(pathList); - } - // For when the file pattern includes a wildcard. - try { - // create a file pattern filter with 'filename' as the key - patternFilter = FilterImpl.newInstance("(filename=" + sanitizeFilterInput(filePattern) + ")"); //$NON-NLS-1$ //$NON-NLS-2$ - // create a single hashtable to be shared during the recursive search - patternProps = new Hashtable<>(2); - } catch (InvalidSyntaxException e) { - // TODO something unexpected happened; log error and return nothing - // Bundle b = context == null ? null : context.getBundle(); - // eventPublisher.publishFrameworkEvent(FrameworkEvent.ERROR, b, e); - return new ArrayList<>(pathList); - } - } - // find the entry paths for the datas - for (BundleFile bundleFile : bundleFiles) { - listEntryPaths(bundleFile, path, patternFilter, patternProps, options, pathList); - } - return new ArrayList<>(pathList); - } - - public static String sanitizeFilterInput(String filePattern) throws InvalidSyntaxException { - StringBuilder buffer = null; - boolean foundEscape = false; - for (int i = 0; i < filePattern.length(); i++) { - char c = filePattern.charAt(i); - switch (c) { - case '\\' : - // we either used the escape found or found a new escape. - foundEscape = foundEscape ? false : true; - if (buffer != null) - buffer.append(c); - break; - case '(' : - case ')' : - if (!foundEscape) { - if (buffer == null) { - buffer = new StringBuilder(filePattern.length() + 16); - buffer.append(filePattern.substring(0, i)); - } - // must escape with '\' - buffer.append('\\'); - } else { - foundEscape = false; // used the escape found - } - if (buffer != null) - buffer.append(c); - break; - default : - // if we found an escape it has been used - foundEscape = false; - if (buffer != null) - buffer.append(c); - break; - } - } - if (foundEscape) - throw new InvalidSyntaxException("Trailing escape characters must be escaped.", filePattern); //$NON-NLS-1$ - return buffer == null ? filePattern : buffer.toString(); - } - - // Use LinkedHashSet for optimized performance of contains() plus ordering - // guarantees. - private static LinkedHashSet listEntryPaths(BundleFile bundleFile, String path, Filter patternFilter, Hashtable patternProps, int options, LinkedHashSet pathList) { - if (pathList == null) - pathList = new LinkedHashSet<>(); - boolean recurse = (options & BundleWiring.FINDENTRIES_RECURSE) != 0; - Enumeration entryPaths = bundleFile.getEntryPaths(path, recurse); - if (entryPaths == null) - return pathList; - while (entryPaths.hasMoreElements()) { - String entry = entryPaths.nextElement(); - int lastSlash = entry.lastIndexOf('/'); - if (patternProps != null) { - int secondToLastSlash = entry.lastIndexOf('/', lastSlash - 1); - int fileStart; - int fileEnd = entry.length(); - if (lastSlash < 0) - fileStart = 0; - else if (lastSlash != entry.length() - 1) - fileStart = lastSlash + 1; - else { - fileEnd = lastSlash; // leave the lastSlash out - if (secondToLastSlash < 0) - fileStart = 0; - else - fileStart = secondToLastSlash + 1; - } - String fileName = entry.substring(fileStart, fileEnd); - // set the filename to the current entry - patternProps.put("filename", fileName); //$NON-NLS-1$ - } - // prevent duplicates and match on the patternFilter - if (!pathList.contains(entry) && (patternFilter == null || patternFilter.matchCase(patternProps))) - pathList.add(entry); - } - return pathList; - } - - public String copyToTempLibrary(Generation generation, String absolutePath) { - File libTempDir = new File(childRoot, LIB_TEMP); - // we assume the absolutePath is a File path - File realLib = new File(absolutePath); - String libName = realLib.getName(); - // find a temp dir for the bundle data and the library; - File bundleTempDir = null; - File libTempFile = null; - // We need a somewhat predictable temp dir for the libraries of a given bundle; - // This is not strictly necessary but it does help scenarios where one native library loads another native library without using java. - // On some OSes this causes issues because the second library is cannot be found. - // This has been worked around by the bundles loading the libraries in a particular order (and setting some LIB_PATH env). - // The one catch is that the libraries need to be in the same directory and they must use their original lib names. - // - // This bit of code attempts to do that by using the bundle ID as an ID for the temp dir along with an incrementing ID - // in cases where the temp dir may already exist. - long bundleID = generation.getBundleInfo().getBundleId(); - for (int i = 0; i < Integer.MAX_VALUE; i++) { - bundleTempDir = new File(libTempDir, bundleID + "_" + i); //$NON-NLS-1$ - libTempFile = new File(bundleTempDir, libName); - if (bundleTempDir.exists()) { - if (libTempFile.exists()) - continue; // to to next temp file - break; - } - break; - } - if (!bundleTempDir.isDirectory()) { - bundleTempDir.mkdirs(); - bundleTempDir.deleteOnExit(); - // This is just a safeguard incase the VM is terminated unexpectantly, it also looks like deleteOnExit cannot really work because - // the VM likely will still have a lock on the lib file at the time of VM exit. - try { // need to create a delete flag to force removal the temp libraries - ensureDeleteFlagFileExists(libTempDir.toPath()); - } catch (IOException e) { - // do nothing; that would mean we did not make the temp dir successfully - } - } - // copy the library file - try { - StorageUtil.copy(realLib, libTempFile); - // set permissions if needed - setPermissions(libTempFile); - libTempFile.deleteOnExit(); // this probably will not work because the VM will probably have the lib locked at exit - // return the temporary path - return libTempFile.getAbsolutePath(); - } catch (IOException e) { - equinoxContainer.getLogServices().log(EquinoxContainer.NAME, FrameworkLogEntry.ERROR, e.getMessage(), e); - return null; - } - } - - private static void ensureDeleteFlagFileExists(Path directory) throws IOException { - Path deleteFlag = directory.resolve(DELETE_FLAG); - if (!Files.exists(deleteFlag) ) { - Files.createFile(deleteFlag); - } - } - - public SecurityAdmin getSecurityAdmin() { - return securityAdmin; - } - - protected StorageManager getChildStorageManager() throws IOException { - String locking = getConfiguration().getConfiguration(LocationHelper.PROP_OSGI_LOCKING, LocationHelper.LOCKING_NIO); - StorageManager sManager = new StorageManager(childRoot, isReadOnly() ? LocationHelper.LOCKING_NONE : locking, isReadOnly()); - try { - sManager.open(!isReadOnly()); - } catch (IOException ex) { - if (getConfiguration().getDebug().DEBUG_STORAGE) { - Debug.println("Error reading framework.info: " + ex.getMessage()); //$NON-NLS-1$ - Debug.printStackTrace(ex); - } - String message = NLS.bind(Msg.ECLIPSE_STARTUP_FILEMANAGER_OPEN_ERROR, ex.getMessage()); - equinoxContainer.getLogServices().log(EquinoxContainer.NAME, FrameworkLogEntry.ERROR, message, ex); - getConfiguration().setProperty(EclipseStarter.PROP_EXITCODE, "15"); //$NON-NLS-1$ - String errorDialog = "" + Msg.ADAPTOR_STORAGE_INIT_FAILED_TITLE + "" + NLS.bind(Msg.ADAPTOR_STORAGE_INIT_FAILED_MSG, childRoot) + "\n" + ex.getMessage(); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - getConfiguration().setProperty(EclipseStarter.PROP_EXITDATA, errorDialog); - throw ex; - } - return sManager; - } - - private InputStream getInfoInputStream() throws IOException { - StorageManager storageManager = getChildStorageManager(); - InputStream storageStream = null; - try { - storageStream = storageManager.getInputStream(FRAMEWORK_INFO); - } catch (IOException ex) { - if (getConfiguration().getDebug().DEBUG_STORAGE) { - Debug.println("Error reading framework.info: " + ex.getMessage()); //$NON-NLS-1$ - Debug.printStackTrace(ex); - } - } finally { - storageManager.close(); - } - if (storageStream == null && parentRoot != null) { - StorageManager parentStorageManager = null; - try { - parentStorageManager = new StorageManager(parentRoot, LocationHelper.LOCKING_NONE, true); - parentStorageManager.open(false); - storageStream = parentStorageManager.getInputStream(FRAMEWORK_INFO); - } catch (IOException e1) { - // That's ok we will regenerate the framework.info - } finally { - if (parentStorageManager != null) { - parentStorageManager.close(); - } - } - } - return storageStream; - } - - EquinoxContainer getEquinoxContainer() { - return equinoxContainer; - } -} From 67aee08356003c7219526de061ba233c541aa62d Mon Sep 17 00:00:00 2001 From: Ethan Fritz Date: Tue, 19 Nov 2024 10:50:13 -0500 Subject: [PATCH 59/67] Disable pbRTCBuild.yml from running on !build --- .ci-orchestrator/pbRTCBuild.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.ci-orchestrator/pbRTCBuild.yml b/.ci-orchestrator/pbRTCBuild.yml index 9c2bf8454b7..bfe627c3c68 100644 --- a/.ci-orchestrator/pbRTCBuild.yml +++ b/.ci-orchestrator/pbRTCBuild.yml @@ -11,12 +11,6 @@ triggers: aliasKeywords: - "#pb" -- type: github - triggerName: "ol-pb-build" - triggerRank: 20 - groups: ["LibertyDev"] - keyword: "!build" - - type: github triggerName: "ol-fullpb" triggerRank: 20 From 2fd78c33aad66711533b7108293f0c7e889ac0cb Mon Sep 17 00:00:00 2001 From: Ethan Fritz Date: Tue, 19 Nov 2024 14:15:41 -0500 Subject: [PATCH 60/67] Delete .ci-orchestrator/pbRTCBuild.yml --- .ci-orchestrator/pbRTCBuild.yml | 117 -------------------------------- 1 file changed, 117 deletions(-) delete mode 100644 .ci-orchestrator/pbRTCBuild.yml diff --git a/.ci-orchestrator/pbRTCBuild.yml b/.ci-orchestrator/pbRTCBuild.yml deleted file mode 100644 index bfe627c3c68..00000000000 --- a/.ci-orchestrator/pbRTCBuild.yml +++ /dev/null @@ -1,117 +0,0 @@ -type: pipeline_definition -product: Liberty -name: Open Liberty Personal Build RTC -description: A build run against Open Liberty Pull Requests -triggers: -- type: github - triggerName: "ol-pb" - triggerRank: 20 - groups: ["LibertyDev"] - keyword: "!pb" - aliasKeywords: - - "#pb" - -- type: github - triggerName: "ol-fullpb" - triggerRank: 20 - groups: ["LibertyDev"] - keyword: "!fullpb" - aliasKeywords: - - "#fullpb" - propertyDefinitions: - - name: fat.test.mode - defaultValue: full - steps: - - stepName: Compile - - name: create.im.repo - defaultValue: true - steps: - - stepName: Compile - - name: spawn.zos - defaultValue: true - steps: - - stepName: Compile - - name: fat.buckets.to.run - defaultValue: all - steps: - - stepName: Compile - -steps: -- stepName: PR Changes - workType: PRChangesDetection - timeoutInMinutes: 30 - properties: - githubPRApi: ${github_pr_api} - githubPRNumber: ${github_pr_number} - -- stepName: Copyright Header Check - workType: Jenkins - projectName: copyrightHeaderCheck - timeoutInMinutes: 120 - properties: - githubPRApi: ${github_pr_api} - githubPRNumber: ${github_pr_number} - -- stepName: Prohibited Terms Check - workType: Jenkins - projectName: prohibitedTermsCheck - timeoutInMinutes: 120 - properties: - githubPRApi: ${github_pr_api} - githubPRNumber: ${github_pr_number} - -- stepName: Code Checklist Creation - workType: Jenkins - projectName: codeCheckListBuilder - timeoutInMinutes: 120 - dependsOn: - - stepName: PR Changes - awaitOutputProperties: true - properties: - githubPRApi: ${github_pr_api} - githubPRNumber: ${github_pr_number} - isBvtCodeChanged: ${PR Changes:is.bvt.code.changed} - isFatCodeChanged: ${PR Changes:is.fat.code.changed} - isFeatureFilesChanged: ${PR Changes:is.feature.files.changed} - isInfraCodeChanged: ${PR Changes:is.infra.code.changed} - isMsgsFilesChanged: ${PR Changes:is.msgs.files.changed} - isNlsFilesChanged: ${PR Changes:is.nls.files.changed} - isProductCodeChanged: ${PR Changes:is.product.code.changed} - isTestInfraCodeChanged: ${PR Changes:is.test.infra.code.changed} - isUnittestCodeChanged: ${PR Changes:is.unittest.code.changed} - bvtFilesCount: ${PR Changes:bvt.files.count} - fatFilesCount: ${PR Changes:fat.files.count} - infraFilesCount: ${PR Changes:infra.files.count} - msgsFiles: ${PR Changes:msgs.files} - nlsFiles: ${PR Changes:nls.files} - productFilesCount: ${PR Changes:product.files.count} - testInfraFilesCount: ${PR Changes:test.infra.files.count} - unittestFilesCount: ${PR Changes:unittest.files.count} - -- stepName: Compile - coreStep: true - workType: RTC - projectName: "Liberty Personal Build - EBC" - timeoutInMinutes: 2160 - dependsOn: - - stepName: PR Changes - awaitOutputProperties: true - properties: - run.packaging.verification: ${PR Changes:run.packaging.verification} - fat.buckets.to.run: ${PR Changes:fat.buckets.to.run} - disable.run.runBvtTests: ${PR Changes:disable.run.runBvtTests} - disable.run.runUnitTests: ${PR Changes:disable.run.runUnitTests} - run.chkpii: ${PR Changes:run.chkpii} - run.findbugs: ${PR Changes:run.findbugs} - spawn.zos: ${PR Changes:spawn.zos} - create.im.repo: ${PR Changes:create.im.repo} - personal.im.build: ${PR Changes:personal.im.build} - disable.run.createDoc: ${PR Changes:disable.run.createDoc} - skip.open.liberty.build.if.possible: ${PR Changes:skip.open.liberty.build.if.possible} - skip.open.liberty.fats.if.possible: ${PR Changes:skip.open.liberty.fats.if.possible} - fat.run.count: ${PR Changes:fat.run.count} - spawn.fullfat.buckets: ${PR Changes:spawn.fullfat.buckets} - zos.fat.buckets.to.exclude: ${PR Changes:zos.fat.buckets.to.exclude} - zos.unittests.to.exclude: ${PR Changes:zos.unittests.to.exclude} - includeProperties: - - file: compilePersonalRTC.properties From f9b426a6cb47af84cf49983ef9eb2b85a4c9a781 Mon Sep 17 00:00:00 2001 From: Ethan Fritz Date: Tue, 19 Nov 2024 14:18:35 -0500 Subject: [PATCH 61/67] Add !pb, #pb, !fullpb, and #fullpb keywords to pb.yml --- .ci-orchestrator/pb.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.ci-orchestrator/pb.yml b/.ci-orchestrator/pb.yml index 0c867ce130c..302e95d3193 100644 --- a/.ci-orchestrator/pb.yml +++ b/.ci-orchestrator/pb.yml @@ -10,9 +10,11 @@ triggers: groups: ["LibertyDev"] keyword: "!pbbeta" aliasKeywords: - - "#build" - - "#pbbeta" - "!build" + - "!pb" + - "#pbbeta" + - "#build" + - "#pb" propertyDefinitions: # If a user defines this property, set it for all steps that use it except the "Distributed Full FATs" step. - name: fat.buckets.to.run @@ -77,7 +79,9 @@ triggers: groups: ["LibertyDev"] keyword: "!fullpbbeta" aliasKeywords: + - "!fullpb" - "#fullpbbeta" + - "#fullpb" propertyDefinitions: # Run all buckets in full mode. - name: fat.buckets.to.run From 962a031a282a08d84a6b491c7264602e4644d2e3 Mon Sep 17 00:00:00 2001 From: Nathan Rauh Date: Wed, 20 Nov 2024 14:59:06 -0600 Subject: [PATCH 62/67] Address review comments --- .../cdi/resources/CWWKCMessages.nlsprops | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/dev/io.openliberty.concurrent.internal.cdi/resources/io/openliberty/concurrent/internal/cdi/resources/CWWKCMessages.nlsprops b/dev/io.openliberty.concurrent.internal.cdi/resources/io/openliberty/concurrent/internal/cdi/resources/CWWKCMessages.nlsprops index 20b4c3913f0..f4fac0a0f1a 100644 --- a/dev/io.openliberty.concurrent.internal.cdi/resources/io/openliberty/concurrent/internal/cdi/resources/CWWKCMessages.nlsprops +++ b/dev/io.openliberty.concurrent.internal.cdi/resources/io/openliberty/concurrent/internal/cdi/resources/CWWKCMessages.nlsprops @@ -38,19 +38,20 @@ CWWKC1410.schedule.lacks.seconds.useraction=Modify the seconds field of the \ Schedule annotation to specify a non-empty value, or omit the seconds field \ from the Schedule. -CWWKC1411.qualified.res.err=CWWKC1411E: An error occurred creating a {0} bean \ - for the {1} annotation or {2} deployment descriptor element with the \ - {3} name and {4} qualifiers that is defined in the {5} application artifact. \ - The error is: {5} -CWWKC1411.qualified.res.err.explanation=An error occurred when creating the \ - resource or attempting to register it as a bean. +CWWKC1411.qualified.res.err=CWWKC1411E: The server did not create a {0} bean \ + for the {1} annotation or {2} deployment descriptor element. \ + The annotation or deployment descriptor element has the \ + {3} name and {4} qualifiers and is defined in the {5} application artifact. \ + The error is {6} +CWWKC1411.qualified.res.err.explanation=The code did not create the resource \ + or did not register the resource as a bean. CWWKC1411.qualified.res.err.useraction=Ensure that the resource is configured \ correctly. CWWKC1412.qualifier.conflict=CWWKC1412E: The {0} application artifact includes \ multiple {1} resource definitions that have the {2} qualifiers. The names of \ - the conflicting {1} resource definitions are: {3}. -CWWKC1412.qualifier.conflict.explanation=Qualifiers must uniquely identify a \ - resource type. -CWWKC1412.qualifier.conflict.useraction=Each resource definition of the same \ - type must have different qualifiers or must not have any qualifiers. + the conflicting {1} resource definitions are {3}. +CWWKC1412.qualifier.conflict.explanation=Each resource definition of the \ + same type that has a qualifier must have a different qualifier. +CWWKC1412.qualifier.conflict.useraction=Ensure that each resource definition \ + of the same type has a different qualifier or does not have any qualifiers. From e0f3f61da3e15a0ccebf6f4ab6b497cfebf65ee6 Mon Sep 17 00:00:00 2001 From: Nathan Rauh Date: Wed, 20 Nov 2024 15:11:32 -0600 Subject: [PATCH 63/67] Address other review comment --- .../cdi/resources/CWWKCMessages.nlsprops | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/dev/io.openliberty.concurrent.internal.cdi/resources/io/openliberty/concurrent/internal/cdi/resources/CWWKCMessages.nlsprops b/dev/io.openliberty.concurrent.internal.cdi/resources/io/openliberty/concurrent/internal/cdi/resources/CWWKCMessages.nlsprops index f4fac0a0f1a..8ea6fa9f8f8 100644 --- a/dev/io.openliberty.concurrent.internal.cdi/resources/io/openliberty/concurrent/internal/cdi/resources/CWWKCMessages.nlsprops +++ b/dev/io.openliberty.concurrent.internal.cdi/resources/io/openliberty/concurrent/internal/cdi/resources/CWWKCMessages.nlsprops @@ -26,17 +26,17 @@ # All messages must use the range CWWKC1410 to CWWKC1499 -CWWKC1410.schedule.lacks.seconds=CWWKC1410E: The Schedule, {0}, specifies an \ - empty value for the seconds at which to run. You must specify a non-empty value. \ - Alternatively, omit the seconds from the Schedule and rely on the default \ - behavior of scheduling the task to run at the second at the start of the minute. +CWWKC1410.schedule.lacks.seconds=CWWKC1410E: The Schedule annotation, {0}, \ + specifies an empty value for the seconds at which the task runs. \ + Specify a nonempty value for the seconds field, or omit the seconds field \ + from the Schedule annotation. Omitting the seconds field schedules the task \ + to run at the start of the minute. CWWKC1410.schedule.lacks.seconds.explanation=The empty array value indicates that \ - the field must be disregarded when computing scheduled times. The seconds field \ - cannot accept an empty value because it is the most granular unit and cannot be \ - disregarded. + the seconds field must be disregarded when scheduled times are computed. \ + Omitting the seconds field schedules the task to run at the start of the minute. CWWKC1410.schedule.lacks.seconds.useraction=Modify the seconds field of the \ - Schedule annotation to specify a non-empty value, or omit the seconds field \ - from the Schedule. + Schedule annotation to specify a nonempty value, or omit the seconds field \ + from the Schedule annotation. CWWKC1411.qualified.res.err=CWWKC1411E: The server did not create a {0} bean \ for the {1} annotation or {2} deployment descriptor element. \ From ad11ca9277429f02a91c9c939aeefd35caf7a64f Mon Sep 17 00:00:00 2001 From: Chuck Bridgham Date: Wed, 20 Nov 2024 18:01:15 -0500 Subject: [PATCH 64/67] Removing transitive test dep --- .../src/io/openliberty/depScanner/BestMatch.java | 1 + 1 file changed, 1 insertion(+) diff --git a/dev/build.depScanner/src/io/openliberty/depScanner/BestMatch.java b/dev/build.depScanner/src/io/openliberty/depScanner/BestMatch.java index 0c31fc332b3..b8e24bb0cfe 100644 --- a/dev/build.depScanner/src/io/openliberty/depScanner/BestMatch.java +++ b/dev/build.depScanner/src/io/openliberty/depScanner/BestMatch.java @@ -296,6 +296,7 @@ private static boolean filteredLibraries(Module library) { return (library.getGroupId().equals("org.glassfish") && (library.getArtifactId().equals("javax.faces"))) || (library.getArtifactId().equals("tomcat-embed-core")) || (library.getArtifactId().equals("woodstox-core") && (library.getVersion().equals("6.2.6") || library.getVersion().equals("6.2.4"))) || + (library.getArtifactId().equals("commons-io") && (library.getVersion().equals("2.13.0"))) || (library.getArtifactId().equals("netty-codec-http") && (library.getVersion().equals("4.1.73.Final") || library.getVersion().equals("4.1.78.Final") || library.getVersion().equals("4.1.92.Final"))) || From 1d2739818add17d8e9fe1b115cf3360d36b8168c Mon Sep 17 00:00:00 2001 From: Wendy Raschke Date: Wed, 20 Nov 2024 17:40:14 -0600 Subject: [PATCH 65/67] Update product and bundle version for release 25.0.0.1; copyright year --- dev/cnf/resources/bnd/liberty-release.props | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/dev/cnf/resources/bnd/liberty-release.props b/dev/cnf/resources/bnd/liberty-release.props index a394d669d73..b069929b753 100644 --- a/dev/cnf/resources/bnd/liberty-release.props +++ b/dev/cnf/resources/bnd/liberty-release.props @@ -1,5 +1,5 @@ #******************************************************************************* -# Copyright (c) 2019, 2024 IBM Corporation and others. +# Copyright (c) 2019, 2025 IBM Corporation and others. # All rights reserved. This program and the accompanying materials # are made available under the terms of the Eclipse Public License 2.0 # which accompanies this distribution, and is available at @@ -13,14 +13,14 @@ releaseTypeGA=true -libertyBaseVersion=24.0.0 -libertyFixpackVersion=12 +libertyBaseVersion=25.0.0 +libertyFixpackVersion=1 libertyServiceVersion=${libertyBaseVersion}.${libertyFixpackVersion} -libertyBetaVersion=2024.12.0.0 +libertyBetaVersion=2025.1.0.0 libertyRelease=${if;${releaseTypeGA};${libertyServiceVersion};${libertyBetaVersion}} -libertyBundleMicroVersion=96 -copyrightBuildYear=2024 +libertyBundleMicroVersion=97 +copyrightBuildYear=2025 buildID=${libertyRelease}-${def;buildLabel} productEdition=BASE_ILAN productLicenseType=ILAN From 2ce60823e2da89ed90384d3f36dcf6ba90baae76 Mon Sep 17 00:00:00 2001 From: Benjamin Confino Date: Thu, 21 Nov 2024 17:22:46 +0000 Subject: [PATCH 66/67] Clean up obsolete comment --- .../publish/tckRunner/tck/tck-suite.xml | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/dev/io.openliberty.microprofile.rest.client.4.0.internal_fat_tck/publish/tckRunner/tck/tck-suite.xml b/dev/io.openliberty.microprofile.rest.client.4.0.internal_fat_tck/publish/tckRunner/tck/tck-suite.xml index 56ea4d6f8cb..1b48dc5ff55 100644 --- a/dev/io.openliberty.microprofile.rest.client.4.0.internal_fat_tck/publish/tckRunner/tck/tck-suite.xml +++ b/dev/io.openliberty.microprofile.rest.client.4.0.internal_fat_tck/publish/tckRunner/tck/tck-suite.xml @@ -16,17 +16,5 @@ - - \ No newline at end of file + From 94be76ebdd9e750b5d85f87180fd8bc0804973c4 Mon Sep 17 00:00:00 2001 From: Wendy Raschke Date: Thu, 21 Nov 2024 12:16:08 -0600 Subject: [PATCH 67/67] Correct year in copyright header --- dev/cnf/resources/bnd/liberty-release.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/cnf/resources/bnd/liberty-release.props b/dev/cnf/resources/bnd/liberty-release.props index b069929b753..15723a913af 100644 --- a/dev/cnf/resources/bnd/liberty-release.props +++ b/dev/cnf/resources/bnd/liberty-release.props @@ -1,5 +1,5 @@ #******************************************************************************* -# Copyright (c) 2019, 2025 IBM Corporation and others. +# Copyright (c) 2019, 2024 IBM Corporation and others. # All rights reserved. This program and the accompanying materials # are made available under the terms of the Eclipse Public License 2.0 # which accompanies this distribution, and is available at