diff --git a/dev/io.openliberty.concurrent.internal/bnd.bnd b/dev/io.openliberty.concurrent.internal/bnd.bnd index e408459330f..c928a7925a8 100644 --- a/dev/io.openliberty.concurrent.internal/bnd.bnd +++ b/dev/io.openliberty.concurrent.internal/bnd.bnd @@ -1,5 +1,5 @@ #******************************************************************************* -# Copyright (c) 2021, 2022 IBM Corporation and others. +# Copyright (c) 2021, 2023 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 @@ -48,23 +48,24 @@ instrument.classesExcludes: io/openliberty/concurrent/internal/resources/*.class io.openliberty.concurrent.internal.trigger.ZonedTriggerService -buildpath: \ - com.ibm.websphere.appserver.spi.kernel.service;version=latest,\ - com.ibm.websphere.appserver.spi.logging;version=latest,\ - com.ibm.websphere.org.osgi.core;version=latest,\ - com.ibm.websphere.org.osgi.service.cm;version=latest,\ - com.ibm.websphere.org.osgi.service.component;version=latest,\ - com.ibm.wsspi.org.osgi.service.cm;version=latest,\ - com.ibm.wsspi.org.osgi.service.component.annotations;version=latest,\ - com.ibm.wsspi.org.osgi.service.metatype;version=latest,\ - com.ibm.ws.concurrency.policy;version=latest,\ - com.ibm.ws.concurrent.jakarta;version=latest,\ - com.ibm.ws.config;version=latest,\ - com.ibm.ws.container.service;version=latest,\ - com.ibm.ws.context;version=latest,\ - com.ibm.ws.injection;version=latest,\ - com.ibm.ws.javaee.dd.common;version=latest,\ - com.ibm.ws.kernel.service;version=latest,\ - com.ibm.ws.logging.core;version=latest,\ - com.ibm.ws.resource;version=latest,\ - com.ibm.ws.org.osgi.annotation.versioning;version=latest,\ - io.openliberty.jakarta.concurrency.3.0;version=latest \ No newline at end of file + com.ibm.websphere.appserver.spi.kernel.service;version=latest,\ + com.ibm.websphere.appserver.spi.logging;version=latest,\ + com.ibm.websphere.org.osgi.core;version=latest,\ + com.ibm.websphere.org.osgi.service.cm;version=latest,\ + com.ibm.websphere.org.osgi.service.component;version=latest,\ + com.ibm.wsspi.org.osgi.service.cm;version=latest,\ + com.ibm.wsspi.org.osgi.service.component.annotations;version=latest,\ + com.ibm.wsspi.org.osgi.service.metatype;version=latest,\ + com.ibm.ws.concurrency.policy;version=latest,\ + com.ibm.ws.concurrent.jakarta;version=latest,\ + com.ibm.ws.config;version=latest,\ + com.ibm.ws.container.service;version=latest,\ + com.ibm.ws.context;version=latest,\ + com.ibm.ws.injection;version=latest,\ + com.ibm.ws.javaee.dd.common;version=latest,\ + com.ibm.ws.javaee.version;version=latest,\ + com.ibm.ws.kernel.service;version=latest,\ + com.ibm.ws.logging.core;version=latest,\ + com.ibm.ws.resource;version=latest,\ + com.ibm.ws.org.osgi.annotation.versioning;version=latest,\ + io.openliberty.jakarta.concurrency.3.1;version=latest diff --git a/dev/io.openliberty.concurrent.internal/src/io/openliberty/concurrent/internal/processor/ContextServiceDefinitionBinding.java b/dev/io.openliberty.concurrent.internal/src/io/openliberty/concurrent/internal/processor/ContextServiceDefinitionBinding.java index d786a2c53db..2c2f552c766 100644 --- a/dev/io.openliberty.concurrent.internal/src/io/openliberty/concurrent/internal/processor/ContextServiceDefinitionBinding.java +++ b/dev/io.openliberty.concurrent.internal/src/io/openliberty/concurrent/internal/processor/ContextServiceDefinitionBinding.java @@ -1,10 +1,10 @@ /******************************************************************************* - * Copyright (c) 2021,2022 IBM Corporation and others. + * Copyright (c) 2021, 2023 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: @@ -45,9 +45,12 @@ public class ContextServiceDefinitionBinding extends InjectionBinding[] DEFAULT_QUALIFIERS = new Class[] {}; private String[] cleared; private boolean XMLcleared; @@ -58,12 +61,15 @@ public class ContextServiceDefinitionBinding extends InjectionBinding properties; - private final Set XMLProperties = new HashSet(); - private String[] unchanged; private boolean XMLunchanged; + private Class[] qualifiers; + private boolean XMLqualifers; + + private Map properties; + private final Set XMLProperties = new HashSet(); + public ContextServiceDefinitionBinding(String jndiName, ComponentNameSpaceConfiguration nameSpaceConfig) { super(null, nameSpaceConfig); setJndiName(jndiName); @@ -86,7 +92,8 @@ public void merge(ContextServiceDefinition annotation, Class instanceClass, M Tr.entry(this, tc, "merge", toString(annotation), instanceClass, member, (XMLcleared ? " (xml)" : " ") + "cleared: " + toString(cleared) + " << " + toString(annotation.cleared()), (XMLpropagated ? "(xml)" : " ") + "propagated: " + toString(propagated) + " << " + toString(annotation.propagated()), - (XMLunchanged ? " (xml)" : " ") + "unchanged: " + toString(unchanged) + " << " + toString(annotation.unchanged())); + (XMLunchanged ? " (xml)" : " ") + "unchanged: " + toString(unchanged) + " << " + toString(annotation.unchanged()), + (XMLqualifers ? " (xml)" : " ") + "qualifiers: " + toString(qualifiers) + " << " + toString(annotation.qualifiers())); if (member != null) { // ContextServiceDefinition is a class-level annotation only. @@ -101,15 +108,18 @@ public void merge(ContextServiceDefinition annotation, Class instanceClass, M propagated = mergeAnnotationValue(propagated == DEFAULT_PROPAGATED ? null : propagated, XMLpropagated, annotation.propagated(), KEY_PROPAGATED, DEFAULT_PROPAGATED); - properties = mergeAnnotationProperties(properties, XMLProperties, new String[] {}); // ContextServiceDefinition has no properties attribute + unchanged = mergeAnnotationValue(unchanged, XMLunchanged, annotation.unchanged(), KEY_UNCHANGED, DEFAULT_UNCHANGED); - unchanged = mergeAnnotationValue(unchanged, XMLunchanged, annotation.unchanged(), KEY_UNCHANGED, new String[0]); + qualifiers = mergeAnnotationValue(qualifiers, XMLqualifers, annotation.qualifiers(), KEY_QUALIFIERS, DEFAULT_QUALIFIERS); + + properties = mergeAnnotationProperties(properties, XMLProperties, new String[] {}); // ContextServiceDefinition has no properties attribute if (trace) Tr.exit(this, tc, "merge", new String[] { (XMLcleared ? " (xml)" : " ") + "cleared= " + toString(cleared), (XMLpropagated ? "(xml)" : " ") + "propagated= " + toString(propagated), - (XMLunchanged ? " (xml)" : " ") + "unchanged= " + toString(unchanged) + (XMLunchanged ? " (xml)" : " ") + "unchanged= " + toString(unchanged), + (XMLqualifers ? " (xml)" : " ") + "qualifiers= " + toString(qualifiers) }); } @@ -119,7 +129,8 @@ void mergeXML(ContextService csd) throws InjectionConfigurationException { Tr.entry(this, tc, "mergeXML", csd, csd.getName(), (XMLcleared ? " (xml)" : " ") + "cleared: " + toString(cleared) + " << " + toString(csd.getCleared()), (XMLpropagated ? "(xml)" : " ") + "propagated: " + toString(propagated) + " << " + toString(csd.getPropagated()), - (XMLunchanged ? " (xml)" : " ") + "unchanged: " + toString(unchanged) + " << " + toString(csd.getUnchanged())); + (XMLunchanged ? " (xml)" : " ") + "unchanged: " + toString(unchanged) + " << " + toString(csd.getUnchanged()), + (XMLqualifers ? " (xml)" : " ") + "qualifiers: " + toString(qualifiers) + " << " + toString(csd.getQualifiers())); List descriptionList = csd.getDescriptions(); @@ -146,20 +157,33 @@ void mergeXML(ContextService csd) throws InjectionConfigurationException { XMLpropagated = true; } - List csdProps = csd.getProperties(); - properties = mergeXMLProperties(properties, XMLProperties, csdProps); - String[] unchangedValues = csd.getUnchanged(); if (unchangedValues != null && unchangedValues.length > 0) { unchanged = mergeXMLValue(unchanged, unchangedValues, "unchanged", KEY_UNCHANGED, null); XMLunchanged |= true; } + String[] qualifierValues = csd.getQualifiers(); + if (qualifierValues == null || qualifierValues.length == 0) { + if (qualifiers == null) + qualifiers = DEFAULT_QUALIFIERS; + } else if (qualifierValues.length == 1 && qualifierValues[0].isEmpty()) { + qualifiers = DEFAULT_QUALIFIERS; + XMLqualifers = true; + } else { + qualifiers = mergeXMLValue(qualifiers, toQualifierClassArray(qualifierValues), "qualifier", KEY_QUALIFIERS, null); + XMLqualifers = true; + } + + List csdProps = csd.getProperties(); + properties = mergeXMLProperties(properties, XMLProperties, csdProps); + if (trace) Tr.exit(this, tc, "mergeXML", new String[] { (XMLcleared ? " (xml)" : " ") + "cleared= " + toString(cleared), (XMLpropagated ? "(xml)" : " ") + "propagated= " + toString(propagated), - (XMLunchanged ? " (xml)" : " ") + "unchanged= " + toString(unchanged) + (XMLunchanged ? " (xml)" : " ") + "unchanged= " + toString(unchanged), + (XMLqualifers ? " (xml)" : " ") + "qualifiers= " + toString(qualifiers) }); } @@ -170,8 +194,10 @@ public void mergeSaved(InjectionBinding injectionBindi mergeSavedValue(cleared, contextServiceBinding.cleared, "cleared"); mergeSavedValue(description, contextServiceBinding.description, "description"); mergeSavedValue(propagated, contextServiceBinding.propagated, "propagated"); - mergeSavedValue(properties, contextServiceBinding.properties, "properties"); mergeSavedValue(unchanged, contextServiceBinding.unchanged, "unchanged"); + mergeSavedValue(qualifiers, contextServiceBinding.qualifiers, "qualifier"); + mergeSavedValue(properties, contextServiceBinding.properties, "properties"); + } void resolve() throws InjectionException { @@ -186,6 +212,7 @@ void resolve() throws InjectionException { addOrRemoveProperty(props, KEY_DESCRIPTION, description); addOrRemoveProperty(props, KEY_PROPAGATED, propagated); addOrRemoveProperty(props, KEY_UNCHANGED, unchanged); + addOrRemoveProperty(props, KEY_QUALIFIERS, qualifiers); setObjects(null, createDefinitionReference(null, jakarta.enterprise.concurrent.ContextService.class.getName(), props)); } @@ -198,17 +225,33 @@ static final String toString(ContextServiceDefinition anno) { .append(", cleared=").append(Arrays.toString(anno.cleared())) // .append(", propagated=").append(Arrays.toString(anno.propagated())) // .append(", unchanged=").append(Arrays.toString(anno.unchanged())) // + .append(", qualifiers=").append(Arrays.toString(anno.qualifiers())) // .append(")"); return b.toString(); } @Trivial - private static final String toString(String[] list) { + private static final String toString(T[] list) { if (list == null || list.length == 0) return "Unspecified"; boolean none = true; for (int i = 0; none && i < list.length; i++) - none &= list[i] == null || list[i].length() == 0; + none &= list[i] == null || list[i].toString().isEmpty(); return none ? "None" : Arrays.toString(list); } + + @Trivial + private static final Class[] toQualifierClassArray(String[] classList) throws IllegalArgumentException { + Class[] clazzArray = new Class[classList.length]; + for (int i = 0; i < classList.length; i++) { + try { + //TODO is there a certain classloader I should be using to load this class? ApplicationClassLoader? + clazzArray[i] = Class.forName(classList[i]); + } catch (ClassNotFoundException e) { + throw new IllegalArgumentException(Tr.formatMessage(tc, "CWWKC1205.qualifier.class.not.found", classList[i]), e); + } + } + + return clazzArray; + } } diff --git a/dev/io.openliberty.concurrent.internal/src/io/openliberty/concurrent/internal/processor/ContextServiceDefinitionProvider.java b/dev/io.openliberty.concurrent.internal/src/io/openliberty/concurrent/internal/processor/ContextServiceDefinitionProvider.java index 8a5b55727c8..6314ff0c620 100644 --- a/dev/io.openliberty.concurrent.internal/src/io/openliberty/concurrent/internal/processor/ContextServiceDefinitionProvider.java +++ b/dev/io.openliberty.concurrent.internal/src/io/openliberty/concurrent/internal/processor/ContextServiceDefinitionProvider.java @@ -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.concurrent.internal/src/io/openliberty/concurrent/internal/processor/ManagedExecutorDefinitionBinding.java b/dev/io.openliberty.concurrent.internal/src/io/openliberty/concurrent/internal/processor/ManagedExecutorDefinitionBinding.java index 3cbc90be5c7..b3199c468e6 100644 --- a/dev/io.openliberty.concurrent.internal/src/io/openliberty/concurrent/internal/processor/ManagedExecutorDefinitionBinding.java +++ b/dev/io.openliberty.concurrent.internal/src/io/openliberty/concurrent/internal/processor/ManagedExecutorDefinitionBinding.java @@ -1,10 +1,10 @@ /******************************************************************************* - * Copyright (c) 2021,2022 IBM Corporation and others. + * Copyright (c) 2021, 2023 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,6 +13,7 @@ package io.openliberty.concurrent.internal.processor; import java.lang.reflect.Member; +import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -45,6 +46,11 @@ public class ManagedExecutorDefinitionBinding extends InjectionBinding[] DEFAULT_QUALIFIERS = new Class[] {}; private String contextServiceJndiName; private boolean XMLContextServiceRef; @@ -58,6 +64,12 @@ public class ManagedExecutorDefinitionBinding extends InjectionBinding[] qualifiers; + private boolean XMLqualifers; + private Map properties; private final Set XMLProperties = new HashSet(); @@ -83,7 +95,9 @@ public void merge(ManagedExecutorDefinition annotation, Class instanceClass, Tr.entry(this, tc, "merge", toString(annotation), instanceClass, member, (XMLContextServiceRef ? "(xml)" : " ") + "contextServiceRef: " + contextServiceJndiName + " << " + annotation.context(), (XMLHungTaskThreshold ? "(xml)" : " ") + "hungTaskThreshold: " + hungTaskThreshold + " << " + annotation.hungTaskThreshold(), - (XMLMaxAsync ? " (xml)" : " ") + "maxAsync: " + maxAsync + " << " + annotation.maxAsync()); + (XMLMaxAsync ? " (xml)" : " ") + "maxAsync: " + maxAsync + " << " + annotation.maxAsync(), + (XMLvirtual ? " (xml)" : " ") + "virtual: " + virtual + " << " + annotation.virtual(), + (XMLqualifers ? " (xml)" : " ") + "qualifiers: " + toString(qualifiers) + " << " + toString(annotation.qualifiers())); if (member != null) { // ManagedExecutorDefinition is a class-level annotation only. @@ -94,13 +108,17 @@ public void merge(ManagedExecutorDefinition annotation, Class instanceClass, description = mergeAnnotationValue(description, XMLDescription, "", KEY_DESCRIPTION, ""); // ManagedExecutorDefinition has no description attribute hungTaskThreshold = mergeAnnotationValue(hungTaskThreshold, XMLHungTaskThreshold, annotation.hungTaskThreshold(), KEY_HUNG_TASK_THRESHOLD, -1L); maxAsync = mergeAnnotationValue(maxAsync, XMLMaxAsync, annotation.maxAsync(), KEY_MAX_ASYNC, -1); + virtual = mergeAnnotationBoolean(virtual, XMLvirtual, annotation.virtual(), KEY_VIRTUAL, DEFAULT_VIRTUAL); + qualifiers = mergeAnnotationValue(qualifiers, XMLqualifers, annotation.qualifiers(), KEY_QUALIFIERS, DEFAULT_QUALIFIERS); properties = mergeAnnotationProperties(properties, XMLProperties, new String[] {}); // ManagedExecutorDefinition has no properties attribute if (trace) Tr.exit(this, tc, "merge", new String[] { (XMLContextServiceRef ? "(xml)" : " ") + "contextServiceRef= " + contextServiceJndiName, (XMLHungTaskThreshold ? "(xml)" : " ") + "hungTaskThreshold= " + hungTaskThreshold, - (XMLMaxAsync ? " (xml)" : " ") + "maxAsync= " + maxAsync + (XMLMaxAsync ? " (xml)" : " ") + "maxAsync= " + maxAsync, + (XMLvirtual ? " (xml)" : " ") + "virtual= " + virtual, + (XMLqualifers ? " (xml)" : " ") + "qualifiers= " + toString(qualifiers) }); } @@ -110,7 +128,9 @@ void mergeXML(ManagedExecutor mxd) throws InjectionConfigurationException { Tr.entry(this, tc, "mergeXML", mxd, mxd.getName(), (XMLContextServiceRef ? "(xml)" : " ") + "contextServiceRef: " + contextServiceJndiName + " << " + mxd.getContextServiceRef(), (XMLHungTaskThreshold ? "(xml)" : " ") + "hungTaskThreshold: " + hungTaskThreshold + " << " + mxd.getHungTaskThreshold(), - (XMLMaxAsync ? " (xml)" : " ") + "maxAsync: " + maxAsync + " << " + mxd.getMaxAsync()); + (XMLMaxAsync ? " (xml)" : " ") + "maxAsync: " + maxAsync + " << " + mxd.getMaxAsync(), + (XMLvirtual ? " (xml)" : " ") + "virtual: " + virtual + " << " + mxd.isVirtual(), + (XMLqualifers ? " (xml)" : " ") + "qualifiers: " + toString(qualifiers) + " << " + toString(mxd.getQualifiers())); List descriptionList = mxd.getDescriptions(); @@ -135,6 +155,23 @@ void mergeXML(ManagedExecutor mxd) throws InjectionConfigurationException { XMLMaxAsync = true; } + if (mxd.isSetVirtual()) { + virtual = mergeXMLValue(virtual, mxd.isVirtual(), "virtual", KEY_VIRTUAL, null); + XMLvirtual = true; + } + + String[] qualifierValues = mxd.getQualifiers(); + if (qualifierValues == null || qualifierValues.length == 0) { + if (qualifiers == null) + qualifiers = DEFAULT_QUALIFIERS; + } else if (qualifierValues.length == 1 && qualifierValues[0].isEmpty()) { + qualifiers = DEFAULT_QUALIFIERS; + XMLqualifers = true; + } else { + qualifiers = mergeXMLValue(qualifiers, toQualifierClassArray(qualifierValues), "qualifier", KEY_QUALIFIERS, null); + XMLqualifers = true; + } + List mxdProps = mxd.getProperties(); properties = mergeXMLProperties(properties, XMLProperties, mxdProps); @@ -142,7 +179,9 @@ void mergeXML(ManagedExecutor mxd) throws InjectionConfigurationException { Tr.exit(this, tc, "mergeXML", new String[] { (XMLContextServiceRef ? "(xml)" : " ") + "contextServiceRef= " + contextServiceJndiName, (XMLHungTaskThreshold ? "(xml)" : " ") + "hungTaskThreshold= " + hungTaskThreshold, - (XMLMaxAsync ? " (xml)" : " ") + "maxAsync= " + maxAsync + (XMLMaxAsync ? " (xml)" : " ") + "maxAsync= " + maxAsync, + (XMLvirtual ? " (xml)" : " ") + "virtual= " + virtual, + (XMLqualifers ? " (xml)" : " ") + "qualifiers= " + toString(qualifiers) }); } @@ -154,6 +193,8 @@ public void mergeSaved(InjectionBinding injectionBind mergeSavedValue(description, managedExecutorBinding.description, "description"); mergeSavedValue(hungTaskThreshold, managedExecutorBinding.hungTaskThreshold, "hung-task-threshold"); mergeSavedValue(maxAsync, managedExecutorBinding.maxAsync, "max-async"); + mergeSavedValue(virtual, managedExecutorBinding.virtual, "virtual"); + mergeSavedValue(qualifiers, managedExecutorBinding.qualifiers, "qualifier"); mergeSavedValue(properties, managedExecutorBinding.properties, "properties"); } @@ -169,6 +210,8 @@ void resolve() throws InjectionException { addOrRemoveProperty(props, KEY_DESCRIPTION, description); addOrRemoveProperty(props, KEY_HUNG_TASK_THRESHOLD, hungTaskThreshold); addOrRemoveProperty(props, KEY_MAX_ASYNC, maxAsync); + addOrRemoveProperty(props, KEY_VIRTUAL, virtual); + addOrRemoveProperty(props, KEY_QUALIFIERS, qualifiers); setObjects(null, createDefinitionReference(null, ManagedExecutorService.class.getName(), props)); } @@ -181,7 +224,34 @@ static final String toString(ManagedExecutorDefinition anno) { .append(", context=").append(anno.context()) // .append(", hungTaskThreshold=").append(anno.hungTaskThreshold()) // .append(", maxAsync=").append(anno.maxAsync()) // + .append(", virtual=").append(anno.virtual()) // + .append(", qualifiers=").append(Arrays.toString(anno.qualifiers())) // .append(")"); return b.toString(); } + + @Trivial + private static final String toString(T[] list) { + if (list == null || list.length == 0) + return "Unspecified"; + boolean none = true; + for (int i = 0; none && i < list.length; i++) + none &= list[i] == null || list[i].toString().isEmpty(); + return none ? "None" : Arrays.toString(list); + } + + @Trivial + private static final Class[] toQualifierClassArray(String[] classList) throws IllegalArgumentException { + Class[] clazzArray = new Class[classList.length]; + for (int i = 0; i < classList.length; i++) { + try { + //TODO is there a certain classloader I should be using to load this class? ApplicationClassLoader? + clazzArray[i] = Class.forName(classList[i]); + } catch (ClassNotFoundException e) { + throw new IllegalArgumentException(Tr.formatMessage(tc, "CWWKC1205.qualifier.class.not.found", classList[i]), e); + } + } + + return clazzArray; + } } diff --git a/dev/io.openliberty.concurrent.internal/src/io/openliberty/concurrent/internal/processor/ManagedScheduledExecutorDefinitionBinding.java b/dev/io.openliberty.concurrent.internal/src/io/openliberty/concurrent/internal/processor/ManagedScheduledExecutorDefinitionBinding.java index 5c693f7f6f0..4280023d10a 100644 --- a/dev/io.openliberty.concurrent.internal/src/io/openliberty/concurrent/internal/processor/ManagedScheduledExecutorDefinitionBinding.java +++ b/dev/io.openliberty.concurrent.internal/src/io/openliberty/concurrent/internal/processor/ManagedScheduledExecutorDefinitionBinding.java @@ -1,10 +1,10 @@ /******************************************************************************* - * Copyright (c) 2021,2022 IBM Corporation and others. + * Copyright (c) 2021, 2023 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,6 +13,7 @@ package io.openliberty.concurrent.internal.processor; import java.lang.reflect.Member; +import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -45,6 +46,11 @@ public class ManagedScheduledExecutorDefinitionBinding extends InjectionBinding< private static final String KEY_DESCRIPTION = "description"; private static final String KEY_HUNG_TASK_THRESHOLD = "hungTaskThreshold"; private static final String KEY_MAX_ASYNC = "maxAsync"; + private static final String KEY_VIRTUAL = "virtual"; + private static final String KEY_QUALIFIERS = "qualifiers"; + + private static final boolean DEFAULT_VIRTUAL = false; + private static final Class[] DEFAULT_QUALIFIERS = new Class[] {}; private String contextServiceJndiName; private boolean XMLContextServiceRef; @@ -58,6 +64,12 @@ public class ManagedScheduledExecutorDefinitionBinding extends InjectionBinding< private Integer maxAsync; private boolean XMLMaxAsync; + private boolean virtual; + private boolean XMLvirtual; + + private Class[] qualifiers; + private boolean XMLqualifers; + private Map properties; private final Set XMLProperties = new HashSet(); @@ -83,7 +95,9 @@ public void merge(ManagedScheduledExecutorDefinition annotation, Class instan Tr.entry(this, tc, "merge", toString(annotation), instanceClass, member, (XMLContextServiceRef ? "(xml)" : " ") + "contextServiceRef: " + contextServiceJndiName + " << " + annotation.context(), (XMLHungTaskThreshold ? "(xml)" : " ") + "hungTaskThreshold: " + hungTaskThreshold + " << " + annotation.hungTaskThreshold(), - (XMLMaxAsync ? " (xml)" : " ") + "maxAsync: " + maxAsync + " << " + annotation.maxAsync()); + (XMLMaxAsync ? " (xml)" : " ") + "maxAsync: " + maxAsync + " << " + annotation.maxAsync(), + (XMLvirtual ? " (xml)" : " ") + "virtual: " + virtual + " << " + annotation.virtual(), + (XMLqualifers ? " (xml)" : " ") + "qualifiers: " + toString(qualifiers) + " << " + toString(annotation.qualifiers())); if (member != null) { // ManagedScheduledExecutorDefinition is a class-level annotation only. @@ -94,13 +108,17 @@ public void merge(ManagedScheduledExecutorDefinition annotation, Class instan description = mergeAnnotationValue(description, XMLDescription, "", KEY_DESCRIPTION, ""); // ManagedScheduledExecutorDefinition has no description attribute hungTaskThreshold = mergeAnnotationValue(hungTaskThreshold, XMLHungTaskThreshold, annotation.hungTaskThreshold(), KEY_HUNG_TASK_THRESHOLD, -1L); maxAsync = mergeAnnotationValue(maxAsync, XMLMaxAsync, annotation.maxAsync(), KEY_MAX_ASYNC, -1); + virtual = mergeAnnotationBoolean(virtual, XMLvirtual, annotation.virtual(), KEY_VIRTUAL, DEFAULT_VIRTUAL); + qualifiers = mergeAnnotationValue(qualifiers, XMLqualifers, annotation.qualifiers(), KEY_QUALIFIERS, DEFAULT_QUALIFIERS); properties = mergeAnnotationProperties(properties, XMLProperties, new String[] {}); // ManagedScheduledExecutorDefinition has no properties attribute if (trace) Tr.exit(this, tc, "merge", new String[] { (XMLContextServiceRef ? "(xml)" : " ") + "contextServiceRef= " + contextServiceJndiName, (XMLHungTaskThreshold ? "(xml)" : " ") + "hungTaskThreshold= " + hungTaskThreshold, - (XMLMaxAsync ? " (xml)" : " ") + "maxAsync= " + maxAsync + (XMLMaxAsync ? " (xml)" : " ") + "maxAsync= " + maxAsync, + (XMLvirtual ? " (xml)" : " ") + "virtual= " + virtual, + (XMLqualifers ? " (xml)" : " ") + "qualifiers= " + toString(qualifiers) }); } @@ -110,7 +128,9 @@ void mergeXML(ManagedScheduledExecutor mxd) throws InjectionConfigurationExcepti Tr.entry(this, tc, "mergeXML", mxd, mxd.getName(), (XMLContextServiceRef ? "(xml)" : " ") + "contextServiceRef: " + contextServiceJndiName + " << " + mxd.getContextServiceRef(), (XMLHungTaskThreshold ? "(xml)" : " ") + "hungTaskThreshold: " + hungTaskThreshold + " << " + mxd.getHungTaskThreshold(), - (XMLMaxAsync ? " (xml)" : " ") + "maxAsync: " + maxAsync + " << " + mxd.getMaxAsync()); + (XMLMaxAsync ? " (xml)" : " ") + "maxAsync: " + maxAsync + " << " + mxd.getMaxAsync(), + (XMLvirtual ? " (xml)" : " ") + "virtual: " + virtual + " << " + mxd.isVirtual(), + (XMLqualifers ? " (xml)" : " ") + "qualifiers: " + toString(qualifiers) + " << " + toString(mxd.getQualifiers())); List descriptionList = mxd.getDescriptions(); @@ -135,6 +155,23 @@ void mergeXML(ManagedScheduledExecutor mxd) throws InjectionConfigurationExcepti XMLMaxAsync = true; } + if (mxd.isSetVirtual()) { + virtual = mergeXMLValue(virtual, mxd.isVirtual(), "virtual", KEY_VIRTUAL, null); + XMLvirtual = true; + } + + String[] qualifierValues = mxd.getQualifiers(); + if (qualifierValues == null || qualifierValues.length == 0) { + if (qualifiers == null) + qualifiers = DEFAULT_QUALIFIERS; + } else if (qualifierValues.length == 1 && qualifierValues[0].isEmpty()) { + qualifiers = DEFAULT_QUALIFIERS; + XMLqualifers = true; + } else { + qualifiers = mergeXMLValue(qualifiers, toQualifierClassArray(qualifierValues), "qualifier", KEY_QUALIFIERS, null); + XMLqualifers = true; + } + List mxdProps = mxd.getProperties(); properties = mergeXMLProperties(properties, XMLProperties, mxdProps); @@ -142,7 +179,9 @@ void mergeXML(ManagedScheduledExecutor mxd) throws InjectionConfigurationExcepti Tr.exit(this, tc, "mergeXML", new String[] { (XMLContextServiceRef ? "(xml)" : " ") + "contextServiceRef= " + contextServiceJndiName, (XMLHungTaskThreshold ? "(xml)" : " ") + "hungTaskThreshold= " + hungTaskThreshold, - (XMLMaxAsync ? " (xml)" : " ") + "maxAsync= " + maxAsync + (XMLMaxAsync ? " (xml)" : " ") + "maxAsync= " + maxAsync, + (XMLvirtual ? " (xml)" : " ") + "virtual= " + virtual, + (XMLqualifers ? " (xml)" : " ") + "qualifiers= " + toString(qualifiers) }); } @@ -154,6 +193,8 @@ public void mergeSaved(InjectionBinding inje mergeSavedValue(description, managedScheduledExecutorBinding.description, "description"); mergeSavedValue(hungTaskThreshold, managedScheduledExecutorBinding.hungTaskThreshold, "hung-task-threshold"); mergeSavedValue(maxAsync, managedScheduledExecutorBinding.maxAsync, "max-async"); + mergeSavedValue(virtual, managedScheduledExecutorBinding.virtual, "virtual"); + mergeSavedValue(qualifiers, managedScheduledExecutorBinding.qualifiers, "qualifier"); mergeSavedValue(properties, managedScheduledExecutorBinding.properties, "properties"); } @@ -169,6 +210,8 @@ void resolve() throws InjectionException { addOrRemoveProperty(props, KEY_DESCRIPTION, description); addOrRemoveProperty(props, KEY_HUNG_TASK_THRESHOLD, hungTaskThreshold); addOrRemoveProperty(props, KEY_MAX_ASYNC, maxAsync); + addOrRemoveProperty(props, KEY_VIRTUAL, virtual); + addOrRemoveProperty(props, KEY_QUALIFIERS, qualifiers); setObjects(null, createDefinitionReference(null, ManagedScheduledExecutorService.class.getName(), props)); } @@ -181,7 +224,34 @@ static final String toString(ManagedScheduledExecutorDefinition anno) { .append(", context=").append(anno.context()) // .append(", hungTaskThreshold=").append(anno.hungTaskThreshold()) // .append(", maxAsync=").append(anno.maxAsync()) // + .append(", virtual=").append(anno.virtual()) // + .append(", qualifiers=").append(Arrays.toString(anno.qualifiers())) // .append(")"); return b.toString(); } + + @Trivial + private static final String toString(T[] list) { + if (list == null || list.length == 0) + return "Unspecified"; + boolean none = true; + for (int i = 0; none && i < list.length; i++) + none &= list[i] == null || list[i].toString().isEmpty(); + return none ? "None" : Arrays.toString(list); + } + + @Trivial + private static final Class[] toQualifierClassArray(String[] classList) throws IllegalArgumentException { + Class[] clazzArray = new Class[classList.length]; + for (int i = 0; i < classList.length; i++) { + try { + //TODO is there a certain classloader I should be using to load this class? ApplicationClassLoader? + clazzArray[i] = Class.forName(classList[i]); + } catch (ClassNotFoundException e) { + throw new IllegalArgumentException(Tr.formatMessage(tc, "CWWKC1205.qualifier.class.not.found", classList[i]), e); + } + } + + return clazzArray; + } } diff --git a/dev/io.openliberty.concurrent.internal/src/io/openliberty/concurrent/internal/processor/ManagedThreadFactoryDefinitionBinding.java b/dev/io.openliberty.concurrent.internal/src/io/openliberty/concurrent/internal/processor/ManagedThreadFactoryDefinitionBinding.java index 4a7f1fa20e6..b9842a8a519 100644 --- a/dev/io.openliberty.concurrent.internal/src/io/openliberty/concurrent/internal/processor/ManagedThreadFactoryDefinitionBinding.java +++ b/dev/io.openliberty.concurrent.internal/src/io/openliberty/concurrent/internal/processor/ManagedThreadFactoryDefinitionBinding.java @@ -1,10 +1,10 @@ /******************************************************************************* - * Copyright (c) 2021,2022 IBM Corporation and others. + * Copyright (c) 2021, 2023 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,6 +13,7 @@ package io.openliberty.concurrent.internal.processor; import java.lang.reflect.Member; +import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -43,6 +44,11 @@ public class ManagedThreadFactoryDefinitionBinding extends InjectionBinding[] DEFAULT_QUALIFIERS = new Class[] {}; private String contextServiceJndiName; private boolean XMLContextServiceRef; @@ -53,6 +59,12 @@ public class ManagedThreadFactoryDefinitionBinding extends InjectionBinding[] qualifiers; + private boolean XMLqualifers; + private Map properties; private final Set XMLProperties = new HashSet(); @@ -77,7 +89,9 @@ public void merge(ManagedThreadFactoryDefinition annotation, Class instanceCl if (trace) Tr.entry(this, tc, "merge", toString(annotation), instanceClass, member, (XMLContextServiceRef ? "(xml)" : " ") + "contextServiceRef: " + contextServiceJndiName + " << " + annotation.context(), - (XMLPriority ? " (xml)" : " ") + "priority: " + priority + " << " + annotation.priority()); + (XMLPriority ? " (xml)" : " ") + "priority: " + priority + " << " + annotation.priority(), + (XMLvirtual ? " (xml)" : " ") + "virtual: " + virtual + " << " + annotation.virtual(), + (XMLqualifers ? " (xml)" : " ") + "qualifiers: " + toString(qualifiers) + " << " + toString(annotation.qualifiers())); if (member != null) { // ManagedThreadFactoryDefinition is a class-level annotation only. @@ -87,12 +101,16 @@ public void merge(ManagedThreadFactoryDefinition annotation, Class instanceCl contextServiceJndiName = mergeAnnotationValue(contextServiceJndiName, XMLContextServiceRef, annotation.context(), KEY_CONTEXT, "java:comp/DefaultContextService"); description = mergeAnnotationValue(description, XMLDescription, "", KEY_DESCRIPTION, ""); // ManagedThreadFactoryDefinition has no description attribute priority = mergeAnnotationValue(priority, XMLPriority, annotation.priority(), KEY_PRIORITY, Thread.NORM_PRIORITY); + virtual = mergeAnnotationBoolean(virtual, XMLvirtual, annotation.virtual(), KEY_VIRTUAL, DEFAULT_VIRTUAL); + qualifiers = mergeAnnotationValue(qualifiers, XMLqualifers, annotation.qualifiers(), KEY_QUALIFIERS, DEFAULT_QUALIFIERS); properties = mergeAnnotationProperties(properties, XMLProperties, new String[] {}); // ManagedThreadFactoryDefinition has no properties attribute if (trace) Tr.exit(this, tc, "merge", new String[] { (XMLContextServiceRef ? "(xml)" : " ") + "contextServiceRef= " + contextServiceJndiName, - (XMLPriority ? " (xml)" : " ") + "priority= " + priority + (XMLPriority ? " (xml)" : " ") + "priority= " + priority, + (XMLvirtual ? " (xml)" : " ") + "virtual= " + virtual, + (XMLqualifers ? " (xml)" : " ") + "qualifiers= " + toString(qualifiers) }); } @@ -101,7 +119,9 @@ void mergeXML(ManagedThreadFactory mtfd) throws InjectionConfigurationException if (trace) Tr.entry(this, tc, "mergeXML", mtfd, mtfd.getName(), (XMLContextServiceRef ? "(xml)" : " ") + "contextServiceRef: " + contextServiceJndiName + " << " + mtfd.getContextServiceRef(), - (XMLPriority ? " (xml)" : " ") + "priority: " + priority + " << " + mtfd.getPriority()); + (XMLPriority ? " (xml)" : " ") + "priority: " + priority + " << " + mtfd.getPriority(), + (XMLvirtual ? " (xml)" : " ") + "virtual: " + virtual + " << " + mtfd.isVirtual(), + (XMLqualifers ? " (xml)" : " ") + "qualifiers: " + toString(qualifiers) + " << " + toString(mtfd.getQualifiers())); List descriptionList = mtfd.getDescriptions(); @@ -121,13 +141,32 @@ void mergeXML(ManagedThreadFactory mtfd) throws InjectionConfigurationException XMLPriority = true; } + if (mtfd.isSetVirtual()) { + virtual = mergeXMLValue(virtual, mtfd.isVirtual(), "virtual", KEY_VIRTUAL, null); + XMLvirtual = true; + } + + String[] qualifierValues = mtfd.getQualifiers(); + if (qualifierValues == null || qualifierValues.length == 0) { + if (qualifiers == null) + qualifiers = DEFAULT_QUALIFIERS; + } else if (qualifierValues.length == 1 && qualifierValues[0].isEmpty()) { + qualifiers = DEFAULT_QUALIFIERS; + XMLqualifers = true; + } else { + qualifiers = mergeXMLValue(qualifiers, toQualifierClassArray(qualifierValues), "qualifier", KEY_QUALIFIERS, null); + XMLqualifers = true; + } + List mxdProps = mtfd.getProperties(); properties = mergeXMLProperties(properties, XMLProperties, mxdProps); if (trace) Tr.exit(this, tc, "mergeXML", new String[] { (XMLContextServiceRef ? "(xml)" : " ") + "contextServiceRef= " + contextServiceJndiName, - (XMLPriority ? " (xml)" : " ") + "priority= " + priority + (XMLPriority ? " (xml)" : " ") + "priority= " + priority, + (XMLvirtual ? " (xml)" : " ") + "virtual= " + virtual, + (XMLqualifers ? " (xml)" : " ") + "qualifiers= " + toString(qualifiers) }); } @@ -138,6 +177,8 @@ public void mergeSaved(InjectionBinding injectio mergeSavedValue(contextServiceJndiName, managedThreadFactoryBinding.contextServiceJndiName, "context-service-ref"); mergeSavedValue(description, managedThreadFactoryBinding.description, "description"); mergeSavedValue(priority, managedThreadFactoryBinding.priority, "priority"); + mergeSavedValue(virtual, managedThreadFactoryBinding.virtual, "virtual"); + mergeSavedValue(qualifiers, managedThreadFactoryBinding.qualifiers, "qualifier"); mergeSavedValue(properties, managedThreadFactoryBinding.properties, "properties"); } @@ -152,6 +193,8 @@ void resolve() throws InjectionException { addOrRemoveProperty(props, KEY_CONTEXT, contextServiceJndiName); addOrRemoveProperty(props, KEY_DESCRIPTION, description); addOrRemoveProperty(props, KEY_PRIORITY, priority); + addOrRemoveProperty(props, KEY_VIRTUAL, virtual); + addOrRemoveProperty(props, KEY_QUALIFIERS, qualifiers); setObjects(null, createDefinitionReference(null, jakarta.enterprise.concurrent.ManagedThreadFactory.class.getName(), props)); } @@ -163,7 +206,34 @@ static final String toString(ManagedThreadFactoryDefinition anno) { .append("(name=").append(anno.name()) // .append(", context=").append(anno.context()) // .append(", priority=").append(anno.priority()) // + .append(", virtual=").append(anno.virtual()) // + .append(", qualifiers=").append(Arrays.toString(anno.qualifiers())) // .append(")"); return b.toString(); } + + @Trivial + private static final String toString(T[] list) { + if (list == null || list.length == 0) + return "Unspecified"; + boolean none = true; + for (int i = 0; none && i < list.length; i++) + none &= list[i] == null || list[i].toString().isEmpty(); + return none ? "None" : Arrays.toString(list); + } + + @Trivial + private static final Class[] toQualifierClassArray(String[] classList) throws IllegalArgumentException { + Class[] clazzArray = new Class[classList.length]; + for (int i = 0; i < classList.length; i++) { + try { + //TODO is there a certain classloader I should be using to load this class? ApplicationClassLoader? + clazzArray[i] = Class.forName(classList[i]); + } catch (ClassNotFoundException e) { + throw new IllegalArgumentException(Tr.formatMessage(tc, "CWWKC1205.qualifier.class.not.found", classList[i]), e); + } + } + + return clazzArray; + } }