Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Concurrency 3.1 injection binding for qualifier and virtual #27340

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 27 additions & 21 deletions dev/io.openliberty.concurrent.internal/bnd.bnd
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#*******************************************************************************
# Copyright (c) 2021, 2022 IBM Corporation and others.
# Copyright (c) 2021, 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
Expand All @@ -24,6 +24,11 @@ Bundle-Description: Jakarta Concurrency 3.0+ implementation; version=${bVersion}

WS-TraceGroup: concurrent

Import-Package: \
jakarta.enterprise.concurrent; version="[3.0.0,4.0.0)", \
jakarta.enterprise.concurrent.spi; version="[3.0.0,4.0.0)", \
*

Export-Package: \
io.openliberty.concurrent.internal.messages

Expand All @@ -48,23 +53,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
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
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
/*******************************************************************************
* Copyright (c) 2021,2022 IBM Corporation and others.
* Copyright (c) 2021, 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:
Expand Down Expand Up @@ -45,9 +45,16 @@ public class ContextServiceDefinitionBinding extends InjectionBinding<ContextSer
private static final String KEY_DESCRIPTION = "description";
private static final String KEY_PROPAGATED = "propagated";
private static final String KEY_UNCHANGED = "unchanged";
private static final String KEY_QUALIFIERS = "qualifiers";

private static final String[] DEFAULT_CLEARED = new String[] { ContextServiceDefinition.TRANSACTION };
private static final String[] DEFAULT_PROPAGATED = new String[] { ContextServiceDefinition.ALL_REMAINING };
private static final String[] DEFAULT_UNCHANGED = new String[] {};
private static final String[] DEFAULT_QUALIFIERS = new String[] {};

private final int eeVersion;

// Concurrent 3.0 attributes

private String[] cleared;
private boolean XMLcleared;
Expand All @@ -58,15 +65,23 @@ public class ContextServiceDefinitionBinding extends InjectionBinding<ContextSer
private String[] propagated;
private boolean XMLpropagated;

private Map<String, String> properties;
private final Set<String> XMLProperties = new HashSet<String>();

private String[] unchanged;
private boolean XMLunchanged;

public ContextServiceDefinitionBinding(String jndiName, ComponentNameSpaceConfiguration nameSpaceConfig) {
// Concurrent 3.1 attributes

private String[] qualifiers;
private boolean XMLqualifers;

// General attribute

private Map<String, String> properties;
private final Set<String> XMLProperties = new HashSet<String>();

public ContextServiceDefinitionBinding(String jndiName, ComponentNameSpaceConfiguration nameSpaceConfig, int eeVersion) {
super(null, nameSpaceConfig);
setJndiName(jndiName);
this.eeVersion = eeVersion;
}

@Override
Expand All @@ -83,10 +98,11 @@ protected JNDIEnvironmentRefType getJNDIEnvironmentRefType() {
public void merge(ContextServiceDefinition annotation, Class<?> instanceClass, Member member) throws InjectionException {
final boolean trace = TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled();
if (trace)
Tr.entry(this, tc, "merge", toString(annotation), instanceClass, member,
Tr.entry(this, tc, "merge", toString(annotation, eeVersion), 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) + " << " + (eeVersion >= 11 ? toString(annotation.qualifiers()) : "Unspecified"));

if (member != null) {
// ContextServiceDefinition is a class-level annotation only.
Expand All @@ -101,15 +117,20 @@ 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]);
//Only merge EE 11 annotations when present, otherwise rely on defaults from mergeXML
if (eeVersion >= 11)
qualifiers = mergeAnnotationValue(qualifiers, XMLqualifers, toQualifierStringArray(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)
});
}

Expand All @@ -119,7 +140,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<Description> descriptionList = csd.getDescriptions();

Expand All @@ -146,20 +168,36 @@ void mergeXML(ContextService csd) throws InjectionConfigurationException {
XMLpropagated = true;
}

List<Property> 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) {
// No qualifiers provided via xml
if (qualifiers == null)
qualifiers = DEFAULT_QUALIFIERS;
} else if (qualifierValues.length == 1 && qualifierValues[0].isEmpty()) {
// Special case <qualifier></qualifier>
qualifiers = DEFAULT_QUALIFIERS;
XMLqualifers = true;
} else {
// List of qualifiers provided
qualifiers = mergeXMLValue(qualifiers, qualifierValues, "qualifier", KEY_QUALIFIERS, null);
XMLqualifers = true;
}

List<Property> 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)
});
}

Expand All @@ -170,8 +208,10 @@ public void mergeSaved(InjectionBinding<ContextServiceDefinition> 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 {
Expand All @@ -186,29 +226,45 @@ 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));
}

@Trivial
static final String toString(ContextServiceDefinition anno) {
static final String toString(ContextServiceDefinition anno, int eeVersion) {
StringBuilder b = new StringBuilder();
b.append("ContextServiceDefinition@").append(Integer.toHexString(anno.hashCode())) //
b.append("ContextServiceDefinition@") //
.append(Integer.toHexString(anno.hashCode())) //
.append("#EE").append(eeVersion) //
.append("(name=").append(anno.name()) //
.append(", cleared=").append(Arrays.toString(anno.cleared())) //
.append(", propagated=").append(Arrays.toString(anno.propagated())) //
.append(", unchanged=").append(Arrays.toString(anno.unchanged())) //
.append(")");
.append(", unchanged=").append(Arrays.toString(anno.unchanged()));

if (eeVersion >= 11)
b.append(", qualifiers=").append(Arrays.toString(anno.qualifiers()));

b.append(")");
return b.toString();
}

@Trivial
private static final String toString(String[] list) {
private static final <T> 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 String[] toQualifierStringArray(Class<?>[] classList) {
String[] qualifierNames = new String[classList.length];
for (int i = 0; i < classList.length; i++) {
qualifierNames[i] = classList[i].getCanonicalName();
}
return qualifierNames;
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
/*******************************************************************************
* Copyright (c) 2021,2022 IBM Corporation and others.
* Copyright (c) 2021, 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:
Expand All @@ -17,13 +17,17 @@
import java.util.Collections;
import java.util.List;

import org.osgi.framework.ServiceReference;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferencePolicyOption;

import com.ibm.websphere.ras.Tr;
import com.ibm.websphere.ras.TraceComponent;
import com.ibm.websphere.ras.annotation.Trivial;
import com.ibm.ws.javaee.dd.common.ContextService;
import com.ibm.ws.javaee.dd.common.JNDIEnvironmentRef;
import com.ibm.ws.javaee.version.JavaEEVersion;
import com.ibm.ws.kernel.service.util.SecureAction;
import com.ibm.wsspi.injectionengine.InjectionBinding;
import com.ibm.wsspi.injectionengine.InjectionException;
Expand All @@ -45,6 +49,11 @@ public class ContextServiceDefinitionProvider extends InjectionProcessorProvider
private static final List<Class<? extends JNDIEnvironmentRef>> REF_CLASSES = //
Collections.<Class<? extends JNDIEnvironmentRef>> singletonList(ContextService.class);

/**
* The Jakarta EE major version (ex. 10)
*/
private int eeVersion;

@Override
@Trivial
public Class<ContextServiceDefinition> getAnnotationClass() {
Expand All @@ -68,6 +77,16 @@ public InjectionProcessor<ContextServiceDefinition, ContextServiceDefinition.Lis
return new Processor();
}

/**
* The service ranking of JavaEEVersion ensures we get the highest
* Jakarta EE version for the configured features.
*/
@Reference(policyOption = ReferencePolicyOption.GREEDY)
protected void setEEVersion(ServiceReference<JavaEEVersion> ref) {
String version = (String) ref.getProperty("version");
eeVersion = Integer.parseInt(version.substring(0, version.indexOf('.')));
}

class Processor extends InjectionProcessor<ContextServiceDefinition, ContextServiceDefinition.List> {
@Trivial
public Processor() {
Expand All @@ -80,10 +99,10 @@ public InjectionBinding<ContextServiceDefinition> createInjectionBinding(Context
String jndiName) throws InjectionException {
final boolean trace = TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled();
if (trace)
Tr.entry(this, tc, "createInjectionBinding", ContextServiceDefinitionBinding.toString(annotation), instanceClass, member, jndiName);
Tr.entry(this, tc, "createInjectionBinding", ContextServiceDefinitionBinding.toString(annotation, eeVersion), instanceClass, member, jndiName);

InjectionBinding<ContextServiceDefinition> injectionBinding = //
new ContextServiceDefinitionBinding(jndiName, ivNameSpaceConfig);
new ContextServiceDefinitionBinding(jndiName, ivNameSpaceConfig, eeVersion);
injectionBinding.merge(annotation, instanceClass, null);

if (trace)
Expand Down Expand Up @@ -125,7 +144,7 @@ public void processXML() throws InjectionException {

ContextServiceDefinitionBinding binding;
if (injectionBinding == null) {
binding = new ContextServiceDefinitionBinding(jndiName, ivNameSpaceConfig);
binding = new ContextServiceDefinitionBinding(jndiName, ivNameSpaceConfig, eeVersion);
addInjectionBinding(binding);
} else {
binding = (ContextServiceDefinitionBinding) injectionBinding;
Expand Down
Loading