You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by jl...@apache.org on 2018/04/16 22:45:26 UTC
[22/38] tomee git commit: Different CDI approach
Different CDI approach
Project: http://git-wip-us.apache.org/repos/asf/tomee/repo
Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/d81bd39d
Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/d81bd39d
Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/d81bd39d
Branch: refs/heads/master
Commit: d81bd39d0df71608bc2ae9f334df344e04b5081f
Parents: 2b9950f
Author: Jean-Louis Monteiro <je...@gmail.com>
Authored: Fri Mar 2 08:52:59 2018 +0100
Committer: Jean-Louis Monteiro <je...@gmail.com>
Committed: Fri Mar 2 08:52:59 2018 +0100
----------------------------------------------------------------------
.../tomee/microprofile/jwt/cdi/ClaimBean.java | 187 ++++++++++
.../jwt/cdi/ClaimInjectionPoint.java | 69 ++++
.../jwt/cdi/ClaimProviderBeanAttributes.java | 66 ----
.../jwt/cdi/ClaimValueProducer.java | 80 -----
.../microprofile/jwt/cdi/DefaultLiteral.java | 24 ++
.../microprofile/jwt/cdi/JsonValueProducer.java | 109 ------
.../microprofile/jwt/cdi/JsonbProducer.java | 2 +-
.../microprofile/jwt/cdi/MPJWTCDIExtension.java | 347 +++----------------
.../microprofile/jwt/cdi/MPJWTProducer.java | 4 +
.../jwt/cdi/RawClaimTypeProducer.java | 80 -----
tck/mp-jwt-embedded/src/test/resources/dev.xml | 12 +-
11 files changed, 329 insertions(+), 651 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/tomee/blob/d81bd39d/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/cdi/ClaimBean.java
----------------------------------------------------------------------
diff --git a/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/cdi/ClaimBean.java b/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/cdi/ClaimBean.java
new file mode 100644
index 0000000..d04d807
--- /dev/null
+++ b/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/cdi/ClaimBean.java
@@ -0,0 +1,187 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomee.microprofile.jwt.cdi;
+
+import org.eclipse.microprofile.jwt.Claim;
+import org.eclipse.microprofile.jwt.Claims;
+
+import javax.enterprise.context.Dependent;
+import javax.enterprise.context.spi.CreationalContext;
+import javax.enterprise.inject.spi.Annotated;
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.InjectionPoint;
+import javax.enterprise.inject.spi.PassivationCapable;
+import javax.inject.Provider;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+
+public class ClaimBean<T> implements Bean<T>, PassivationCapable {
+
+ private final static Set<Annotation> QUALIFIERS = new HashSet<>();
+
+ private final BeanManager bm;
+ private final Class rawType;
+ private final Set<Type> types;
+ private final String id;
+
+ public ClaimBean(final BeanManager bm, final Type type) {
+ this.bm = bm;
+ types = new HashSet<>();
+ types.add(type);
+ rawType = getRawType(type);
+ this.id = "ClaimBean_" + types;
+ }
+
+ private Class getRawType(Type type) {
+ if (type instanceof Class) {
+ return (Class) type;
+
+ } else if (type instanceof ParameterizedType) {
+ final ParameterizedType paramType = (ParameterizedType) type;
+
+ return (Class) paramType.getRawType();
+ }
+
+ // todo deal with Optional here?
+
+ throw new UnsupportedOperationException("Unsupported type " + type);
+ }
+
+
+ @Override
+ public Set<InjectionPoint> getInjectionPoints() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public Class<?> getBeanClass() {
+ return rawType;
+ }
+
+ @Override
+ public boolean isNullable() {
+ return false;
+ }
+
+ @Override
+ public void destroy(T instance, CreationalContext<T> context) {
+
+ }
+
+ @Override
+ public Set<Type> getTypes() {
+ return types;
+ }
+
+ @Override
+ public Set<Annotation> getQualifiers() {
+ return QUALIFIERS;
+ }
+
+ @Override
+ public Class<? extends Annotation> getScope() {
+ return Dependent.class;
+ }
+
+ @Override
+ public String getName() {
+ return null;
+ }
+
+ @Override
+ public Set<Class<? extends Annotation>> getStereotypes() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public boolean isAlternative() {
+ return false;
+ }
+
+ @Override
+ public String getId() {
+ return id;
+ }
+
+ @Override
+ public T create(final CreationalContext<T> context) {
+ final InjectionPoint ip = (InjectionPoint) bm.getInjectableReference(new ClaimInjectionPoint(this), context);
+ if (ip == null) {
+ throw new IllegalStateException("Could not retrieve InjectionPoint");
+ }
+
+ final Annotated annotated = ip.getAnnotated();
+ Claim claim = annotated.getAnnotation(Claim.class);
+ final String key = getClaimKey(claim);
+
+ if (annotated.getBaseType() instanceof ParameterizedType) {
+ final ParameterizedType paramType = (ParameterizedType) annotated.getBaseType();
+ final Type rawType = paramType.getRawType();
+ if (rawType instanceof Class && paramType.getActualTypeArguments().length == 1) {
+
+ final Class<?> rawTypeClass = ((Class<?>) rawType);
+
+ // handle Provider<T>
+ if (rawTypeClass.isAssignableFrom(Provider.class)) {
+ final Class clazz = (Class) paramType.getActualTypeArguments()[0]; //X TODO check type again, etc
+ return (T) getClaimValue(key, clazz);
+ }
+
+ // handle Optional<T>
+ if (rawTypeClass.isAssignableFrom(Optional.class)) {
+ final Class clazz = (Class) paramType.getActualTypeArguments()[0]; //X TODO check type again, etc
+ return (T) getClaimValue(key, clazz);
+ }
+
+ // handle Set<T>
+ if (rawTypeClass.isAssignableFrom(Set.class)) {
+ Class clazz = (Class) paramType.getActualTypeArguments()[0]; //X TODO check type again, etc
+ return getClaimValue(key, clazz);
+ }
+
+ // handle List<T>
+ if (rawTypeClass.isAssignableFrom(List.class)) {
+ final Class clazz = (Class) paramType.getActualTypeArguments()[0]; //X TODO check type again, etc
+ return getClaimValue(key, clazz);
+ }
+ }
+
+ } else {
+ // handle Raw types
+ final Class clazz = (Class) annotated.getBaseType();
+ return getClaimValue(key, clazz);
+ }
+
+ throw new IllegalStateException("Unhandled ClaimValue type");
+ }
+
+ public static String getClaimKey(final Claim claim) {
+ return claim.standard() == Claims.UNKNOWN ? claim.value() : claim.standard().name();
+ }
+
+ private T getClaimValue(final String key, final Class clazz) {
+ return null; // todo
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/tomee/blob/d81bd39d/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/cdi/ClaimInjectionPoint.java
----------------------------------------------------------------------
diff --git a/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/cdi/ClaimInjectionPoint.java b/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/cdi/ClaimInjectionPoint.java
new file mode 100644
index 0000000..a281014
--- /dev/null
+++ b/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/cdi/ClaimInjectionPoint.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomee.microprofile.jwt.cdi;
+
+import javax.enterprise.inject.spi.Annotated;
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.InjectionPoint;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Member;
+import java.lang.reflect.Type;
+import java.util.Collections;
+import java.util.Set;
+
+class ClaimInjectionPoint implements InjectionPoint{
+ private final Bean bean;
+
+ ClaimInjectionPoint(Bean bean) {
+ this.bean = bean;
+ }
+
+ @Override
+ public boolean isTransient() {
+ return false;
+ }
+
+ @Override
+ public boolean isDelegate() {
+ return false;
+ }
+
+ @Override
+ public Type getType() {
+ return InjectionPoint.class;
+ }
+
+ @Override
+ public Set<Annotation> getQualifiers() {
+ return Collections.singleton(DefaultLiteral.INSTANCE);
+ }
+
+ @Override
+ public Member getMember() {
+ return null;
+ }
+
+ @Override
+ public Bean<?> getBean() {
+ return bean;
+ }
+
+ @Override
+ public Annotated getAnnotated() {
+ return null;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/d81bd39d/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/cdi/ClaimProviderBeanAttributes.java
----------------------------------------------------------------------
diff --git a/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/cdi/ClaimProviderBeanAttributes.java b/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/cdi/ClaimProviderBeanAttributes.java
deleted file mode 100644
index f15a3fe..0000000
--- a/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/cdi/ClaimProviderBeanAttributes.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.tomee.microprofile.jwt.cdi;
-
-import javax.enterprise.inject.spi.BeanAttributes;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Type;
-import java.util.Set;
-
-public class ClaimProviderBeanAttributes implements BeanAttributes<Object> {
-
- private final BeanAttributes<Object> delegate;
- private final Set<Type> types;
- private final Set<Annotation> qualifiers;
-
- public ClaimProviderBeanAttributes(final BeanAttributes<Object> delegate, final Set<Type> types, final Set<Annotation> qualifiers) {
- this.delegate = delegate;
- this.types = types;
- this.qualifiers = qualifiers;
- }
-
- @Override
- public Set<Type> getTypes() {
- return types;
- }
-
- @Override
- public Set<Annotation> getQualifiers() {
- return qualifiers;
- }
-
- @Override
- public Class<? extends Annotation> getScope() {
- return delegate.getScope();
- }
-
- @Override
- public String getName() {
- return delegate.getName();
- }
-
- @Override
- public Set<Class<? extends Annotation>> getStereotypes() {
- return delegate.getStereotypes();
- }
-
- @Override
- public boolean isAlternative() {
- return delegate.isAlternative();
- }
-
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/d81bd39d/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/cdi/ClaimValueProducer.java
----------------------------------------------------------------------
diff --git a/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/cdi/ClaimValueProducer.java b/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/cdi/ClaimValueProducer.java
deleted file mode 100644
index b0e2e7b..0000000
--- a/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/cdi/ClaimValueProducer.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.tomee.microprofile.jwt.cdi;
-
-import org.eclipse.microprofile.jwt.Claim;
-import org.eclipse.microprofile.jwt.ClaimValue;
-import org.eclipse.microprofile.jwt.Claims;
-
-import javax.enterprise.inject.Produces;
-import javax.enterprise.inject.spi.InjectionPoint;
-import javax.inject.Inject;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.util.Optional;
-
-public class ClaimValueProducer<T> {
-
- @Inject
- private MPJWTProducer producer;
-
- @Produces
- @Claim("")
- ClaimValue<T> produce(final InjectionPoint ip) {
- String name = getName(ip);
- ClaimValue<Optional<T>> cv = producer.generalClaimValueProducer(name);
- ClaimValue<T> returnValue = (ClaimValue<T>) cv;
- Optional<T> value = cv.getValue();
-
- // Pull out the ClaimValue<T> T type,
- Type matchType = ip.getType();
- Type actualType = Object.class;
- boolean isOptional = false;
- if (matchType instanceof ParameterizedType) {
- actualType = ((ParameterizedType) matchType).getActualTypeArguments()[0];
-
- if (actualType instanceof ParameterizedType) {
- isOptional = ParameterizedType.class.cast(actualType).getRawType().getTypeName()
- .startsWith(Optional.class.getTypeName());
- }
-
- if (isOptional) {
- actualType = ((ParameterizedType) actualType).getActualTypeArguments()[0];
- }
- }
-
- if (!actualType.getTypeName().startsWith(Optional.class.getTypeName())) {
- T nestedValue = value.orElse(null);
- ClaimValueWrapper<T> wrapper = new ClaimValueWrapper<>(cv.getName());
- wrapper.setValue(nestedValue);
- returnValue = wrapper;
- }
- return returnValue;
- }
-
- private String getName(final InjectionPoint ip) {
- String name = null;
- for (Annotation ann : ip.getQualifiers()) {
- if (ann instanceof Claim) {
- Claim claim = (Claim) ann;
- name = claim.standard() == Claims.UNKNOWN ? claim.value() : claim.standard().name();
- }
- }
- return name;
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/d81bd39d/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/cdi/DefaultLiteral.java
----------------------------------------------------------------------
diff --git a/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/cdi/DefaultLiteral.java b/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/cdi/DefaultLiteral.java
new file mode 100644
index 0000000..d741258
--- /dev/null
+++ b/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/cdi/DefaultLiteral.java
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomee.microprofile.jwt.cdi;
+
+import javax.enterprise.inject.Default;
+import javax.enterprise.util.AnnotationLiteral;
+
+class DefaultLiteral extends AnnotationLiteral<Default> implements Default {
+ public static Default INSTANCE = new DefaultLiteral();
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/d81bd39d/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/cdi/JsonValueProducer.java
----------------------------------------------------------------------
diff --git a/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/cdi/JsonValueProducer.java b/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/cdi/JsonValueProducer.java
deleted file mode 100644
index 645b41b..0000000
--- a/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/cdi/JsonValueProducer.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.tomee.microprofile.jwt.cdi;
-
-import org.eclipse.microprofile.jwt.Claim;
-import org.eclipse.microprofile.jwt.Claims;
-
-import javax.enterprise.inject.Produces;
-import javax.enterprise.inject.spi.InjectionPoint;
-import javax.inject.Inject;
-import javax.json.JsonArray;
-import javax.json.JsonNumber;
-import javax.json.JsonObject;
-import javax.json.JsonString;
-import javax.json.JsonValue;
-import java.lang.annotation.Annotation;
-import java.util.Optional;
-import java.util.Set;
-
-public class JsonValueProducer {
-
- @Inject
- private MPJWTProducer producer;
-
- @Produces
- @Claim("")
- public JsonString getJsonString(final InjectionPoint ip) {
- return getValue(ip);
- }
-
- @Produces
- @Claim("")
- public Optional<JsonString> getOptionalJsonString(final InjectionPoint ip) {
- return getOptionalValue(ip);
- }
-
- @Produces
- @Claim("")
- public JsonNumber getJsonNumber(final InjectionPoint ip) {
- return getValue(ip);
- }
-
- @Produces
- @Claim("")
- public Optional<JsonNumber> getOptionalJsonNumber(final InjectionPoint ip) {
- return getOptionalValue(ip);
- }
-
- @Produces
- @Claim("")
- public JsonArray getJsonArray(final InjectionPoint ip) {
- return getValue(ip);
- }
-
- @Produces
- @Claim("")
- public Optional<JsonArray> getOptionalJsonArray(final InjectionPoint ip) {
- return getOptionalValue(ip);
- }
-
- @Produces
- @Claim("")
- public JsonObject getJsonObject(final InjectionPoint ip) {
- return getValue(ip);
- }
-
- @Produces
- @Claim("")
- public Optional<JsonObject> getOptionalJsonObject(final InjectionPoint ip) {
- return getOptionalValue(ip);
- }
-
- public <T extends JsonValue> T getValue(final InjectionPoint ip) {
- String name = getName(ip);
- T jsonValue = (T) producer.generalJsonValueProducer(name);
- return jsonValue;
- }
-
- public <T extends JsonValue> Optional<T> getOptionalValue(final InjectionPoint ip) {
- String name = getName(ip);
- T jsonValue = (T) producer.generalJsonValueProducer(name);
- return Optional.ofNullable(jsonValue);
- }
-
- String getName(final InjectionPoint ip) {
- String name = null;
- for (Annotation ann : ip.getQualifiers()) {
- if (ann instanceof Claim) {
- Claim claim = (Claim) ann;
- name = claim.standard() == Claims.UNKNOWN ? claim.value() : claim.standard().name();
- }
- }
- return name;
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/d81bd39d/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/cdi/JsonbProducer.java
----------------------------------------------------------------------
diff --git a/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/cdi/JsonbProducer.java b/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/cdi/JsonbProducer.java
index 7774cbf..297dfb3 100644
--- a/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/cdi/JsonbProducer.java
+++ b/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/cdi/JsonbProducer.java
@@ -30,7 +30,7 @@ public class JsonbProducer {
private static Logger log = Logger.getLogger(MPJWTCDIExtension.class.getName());
@Produces
- public Jsonb jsonb() {
+ public Jsonb create() {
return JsonbBuilder.create();
}
http://git-wip-us.apache.org/repos/asf/tomee/blob/d81bd39d/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/cdi/MPJWTCDIExtension.java
----------------------------------------------------------------------
diff --git a/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/cdi/MPJWTCDIExtension.java b/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/cdi/MPJWTCDIExtension.java
index 7375d65..88981d4 100644
--- a/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/cdi/MPJWTCDIExtension.java
+++ b/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/cdi/MPJWTCDIExtension.java
@@ -21,348 +21,79 @@ import org.apache.tomee.microprofile.jwt.MPJWTInitializer;
import org.apache.tomee.microprofile.jwt.TCKTokenParser;
import org.apache.tomee.microprofile.jwt.config.JWTAuthContextInfoProvider;
import org.eclipse.microprofile.jwt.Claim;
-import org.eclipse.microprofile.jwt.Claims;
-import javax.enterprise.context.ApplicationScoped;
-import javax.enterprise.context.SessionScoped;
import javax.enterprise.event.Observes;
import javax.enterprise.inject.spi.AfterBeanDiscovery;
import javax.enterprise.inject.spi.AfterDeploymentValidation;
-import javax.enterprise.inject.spi.BeanAttributes;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.BeforeBeanDiscovery;
-import javax.enterprise.inject.spi.DeploymentException;
import javax.enterprise.inject.spi.Extension;
import javax.enterprise.inject.spi.InjectionPoint;
-import javax.enterprise.inject.spi.ProcessBeanAttributes;
import javax.enterprise.inject.spi.ProcessInjectionPoint;
-import javax.enterprise.inject.spi.ProcessProducer;
import javax.inject.Provider;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.Optional;
+import java.util.Map;
import java.util.Set;
+import java.util.function.Predicate;
import java.util.logging.Logger;
+import java.util.stream.Collectors;
public class MPJWTCDIExtension implements Extension {
- private static Logger log = Logger.getLogger(MPJWTCDIExtension.class.getName());
- /**
- * A map of claim,type pairs to the injection site information
- */
- private HashMap<ClaimIPType, ClaimIP> claims = new HashMap<>();
- private Set<Type> providerOptionalTypes = new HashSet<>();
- private Set<Type> providerTypes = new HashSet<>();
- private Set<Type> rawTypes = new HashSet<>();
- private Set<Annotation> rawTypeQualifiers = new HashSet<>();
- private Set<Annotation> providerQualifiers = new HashSet<>();
- /**
- * Register the MPJWTProducer JsonWebToken producer bean
- *
- * @param bbd before discovery event
- * @param beanManager cdi bean manager
- */
- public void observeBeforeBeanDiscovery(@Observes BeforeBeanDiscovery bbd, BeanManager beanManager) {
- log.fine("MPJWTExtension(), added JWTPrincipalProducer");
- bbd.addAnnotatedType(beanManager.createAnnotatedType(TCKTokenParser.class));
- bbd.addAnnotatedType(beanManager.createAnnotatedType(JsonbProducer.class));
- bbd.addAnnotatedType(beanManager.createAnnotatedType(MPJWTFilter.class));
- bbd.addAnnotatedType(beanManager.createAnnotatedType(MPJWTInitializer.class));
- bbd.addAnnotatedType(beanManager.createAnnotatedType(JWTAuthContextInfoProvider.class));
- bbd.addAnnotatedType(beanManager.createAnnotatedType(MPJWTProducer.class));
- bbd.addAnnotatedType(beanManager.createAnnotatedType(RawClaimTypeProducer.class));
- bbd.addAnnotatedType(beanManager.createAnnotatedType(ClaimValueProducer.class));
- bbd.addAnnotatedType(beanManager.createAnnotatedType(JsonValueProducer.class));
- }
+ private static Logger logger = Logger.getLogger(MPJWTCDIExtension.class.getName());
- /**
- * Replace the general producer method BeanAttributes with one bound to the collected injection site
- * types to properly reflect all of the type locations the producer method applies to.
- *
- * @param pba the ProcessBeanAttributes
- * @see ClaimProviderBeanAttributes
- */
- public void addTypeToClaimProducer(@Observes ProcessBeanAttributes pba) {
- if (pba.getAnnotated().isAnnotationPresent(Claim.class)) {
- Claim claim = pba.getAnnotated().getAnnotation(Claim.class);
- if (claim.value().length() == 0 && claim.standard() == Claims.UNKNOWN) {
- log.fine(String.format("addTypeToClaimProducer: %s\n", pba.getAnnotated()));
- BeanAttributes delegate = pba.getBeanAttributes();
- String name = delegate.getName();
- if (delegate.getTypes().contains(Optional.class)) {
- if (providerOptionalTypes.size() == 0) {
- providerOptionalTypes.add(Optional.class);
- }
- pba.setBeanAttributes(new ClaimProviderBeanAttributes(delegate, providerOptionalTypes, providerQualifiers));
- // This is
- } else if (name != null && name.startsWith("RawClaimTypeProducer#")) {
- if (rawTypes.size() == 0) {
- rawTypes.add(Object.class);
- }
- pba.setBeanAttributes(new ClaimProviderBeanAttributes(delegate, rawTypes, rawTypeQualifiers));
- log.fine(String.format("Setup RawClaimTypeProducer BeanAttributes"));
- }
- }
- }
- }
+ private static final Predicate<InjectionPoint> NOT_PROVIDERS = ip -> (ip.getType() instanceof Class) || (ip.getType() instanceof ParameterizedType && ((ParameterizedType)ip.getType()).getRawType() != Provider.class);
+ private static final Map<Type, Type> REPLACED_TYPES = new HashMap<>();
- public void afterDeploymentValidation(@Observes AfterDeploymentValidation event, BeanManager beanManager) {
+ static {
+ REPLACED_TYPES.put(double.class, Double.class);
+ REPLACED_TYPES.put(int.class, Integer.class);
+ REPLACED_TYPES.put(float.class, Float.class);
+ REPLACED_TYPES.put(long.class, Long.class);
+ REPLACED_TYPES.put(boolean.class, Boolean.class);
}
- void doProcessProducers(@Observes ProcessProducer pp) {
- }
+ private Set<InjectionPoint> injectionPoints = new HashSet<>();
- /**
- * Handle the non-{@linkplain Provider}, {@linkplain org.eclipse.microprofile.jwt.ClaimValue}, and
- * {@linkplain javax.json.JsonValue} claim injection types.
- *
- * @param pip - the injection point event information
- * @see RawClaimTypeProducer
- */
- void processClaimInjections(@Observes ProcessInjectionPoint pip) {
- log.fine(String.format("pipRaw: %s", pip.getInjectionPoint()));
- InjectionPoint ip = pip.getInjectionPoint();
- if (ip.getAnnotated().isAnnotationPresent(Claim.class)) {
- Claim claim = ip.getAnnotated().getAnnotation(Claim.class);
- if (ip.getType() instanceof Class) {
- Class rawClass = (Class) ip.getType();
- // Primative types
- if (Modifier.isFinal(rawClass.getModifiers())) {
- rawTypes.add(ip.getType());
- rawTypeQualifiers.add(claim);
- log.fine(String.format("+++ Added Claim raw type: %s", ip.getType()));
- Class declaringClass = ip.getMember().getDeclaringClass();
- Annotation[] appScoped = declaringClass.getAnnotationsByType(ApplicationScoped.class);
- Annotation[] sessionScoped = declaringClass.getAnnotationsByType(SessionScoped.class);
- if ((appScoped != null && appScoped.length > 0) || (sessionScoped != null && sessionScoped.length > 0)) {
- String err = String.format("A raw type cannot be injected into application/session scope: IP=%s", ip);
- pip.addDefinitionError(new DeploymentException(err));
- }
- }
- // This handles collections of primative types
- } else if (isRawParameterizedType(ip.getType())) {
- log.fine(String.format("+++ Added Claim ParameterizedType: %s", ip.getType()));
- rawTypes.add(ip.getType());
- rawTypeQualifiers.add(claim);
- }
- } else {
- log.fine(String.format("Skipping pip: %s, type: %s/%s", ip, ip.getType(), ip.getType().getClass()));
+ public void collectConfigProducer(@Observes final ProcessInjectionPoint<?, ?> pip) {
+ final Claim claim = pip.getInjectionPoint().getAnnotated().getAnnotation(Claim.class);
+ if (claim != null) {
+ injectionPoints.add(pip.getInjectionPoint());
}
}
- /**
- * Collect the types of all {@linkplain Provider} injection points annotated with {@linkplain Claim}.
- *
- * @param pip - the injection point event information
- */
- void processClaimProviderInjections(@Observes ProcessInjectionPoint<?, ? extends Provider> pip) {
- log.fine(String.format("pip: %s", pip.getInjectionPoint()));
- final InjectionPoint ip = pip.getInjectionPoint();
- if (ip.getAnnotated().isAnnotationPresent(Claim.class)) {
- Claim claim = ip.getAnnotated().getAnnotation(Claim.class);
- if (claim.value().length() == 0 && claim.standard() == Claims.UNKNOWN) {
- pip.addDefinitionError(new DeploymentException("@Claim at: " + ip + " has no name or valid standard enum setting"));
- }
- boolean usesEnum = claim.standard() != Claims.UNKNOWN;
- final String claimName = usesEnum ? claim.standard().name() : claim.value();
- log.fine(String.format("Checking Provider Claim(%s), ip: %s", claimName, ip));
- ClaimIP claimIP = claims.get(claimName);
- Type matchType = ip.getType();
- // The T from the Provider<T> injection site
- Type actualType = ((ParameterizedType) matchType).getActualTypeArguments()[0];
- // Don't add Optional or JsonValue as this is handled specially
- if (!optionalOrJsonValue(actualType)) {
- rawTypes.add(actualType);
- } else if (!actualType.getTypeName().startsWith("javax.json.Json")) {
- // Validate that this is not an Optional<JsonValue>
- Type innerType = ((ParameterizedType) actualType).getActualTypeArguments()[0];
- if (!innerType.getTypeName().startsWith("javax.json.Json")) {
- providerOptionalTypes.add(actualType);
- providerQualifiers.add(claim);
- }
- }
- rawTypeQualifiers.add(claim);
- ClaimIPType key = new ClaimIPType(claimName, actualType);
- if (claimIP == null) {
- claimIP = new ClaimIP(actualType, actualType, false, claim);
- claimIP.setProviderSite(true);
- claims.put(key, claimIP);
- }
- claimIP.getInjectionPoints().add(ip);
- log.fine(String.format("+++ Added Provider Claim(%s) ip: %s", claimName, ip));
+ public void registerConfigProducer(@Observes final AfterBeanDiscovery abd, final BeanManager bm) {
+ final Set<Type> types = injectionPoints.stream()
+ .filter(NOT_PROVIDERS)
+ .map(ip -> REPLACED_TYPES.getOrDefault(ip.getType(), ip.getType()))
+ .collect(Collectors.toSet());
- }
- }
-
- /**
- * Create producer methods for each ClaimValue injection site
- *
- * @param event - AfterBeanDiscovery
- * @param beanManager - CDI bean manager
- */
- void observesAfterBeanDiscovery(@Observes final AfterBeanDiscovery event, final BeanManager beanManager) {
- log.fine(String.format("observesAfterBeanDiscovery, %s", claims));
- installClaimValueProducerMethodsViaSyntheticBeans(event, beanManager);
-
- //installClaimValueProducesViaTemplateType(event, beanManager);
- }
+ final Set<Type> providerTypes = injectionPoints.stream()
+ .filter(NOT_PROVIDERS.negate())
+ .map(ip -> ((ParameterizedType)ip.getType()).getActualTypeArguments()[0])
+ .collect(Collectors.toSet());
- /**
- * Create a synthetic bean with a custom Producer for the non-Provider injection sites.
- *
- * @param event - AfterBeanDiscovery
- * @param beanManager - CDI bean manager
- */
- private void installClaimValueProducerMethodsViaSyntheticBeans(final AfterBeanDiscovery event, final BeanManager beanManager) {
+ types.addAll(providerTypes);
+ types.stream()
+ .map(type -> new ClaimBean<>(bm, type))
+ .forEach(abd::addBean);
}
- private boolean optionalOrJsonValue(Type type) {
- boolean isOptionOrJson = type.getTypeName().startsWith(Optional.class.getTypeName())
- | type.getTypeName().startsWith("javax.json.Json");
- return isOptionOrJson;
+ public void validate(@Observes final AfterDeploymentValidation add) {
+ // not sure yet if we can eagerly check
}
- private boolean isRawParameterizedType(Type type) {
- boolean isRawParameterizedType = false;
- if (type instanceof ParameterizedType) {
- ParameterizedType ptype = ParameterizedType.class.cast(type);
- Type rawType = ptype.getRawType();
- String rawTypeName = rawType.getTypeName();
- isRawParameterizedType = !rawTypeName.startsWith("org.eclipse.microprofile.jwt");
- }
- return isRawParameterizedType;
- }
-
- /**
- * A key for a claim,injection site type pair
- */
- public static class ClaimIPType implements Comparable<ClaimIPType> {
- private String claimName;
- private Type ipType;
-
- public ClaimIPType(String claimName, Type ipType) {
- this.claimName = claimName;
- this.ipType = ipType;
- }
-
- /**
- * Order the @Claim ClaimValue<T> on the @Claim.value and then T type name
- *
- * @param o - ClaimIP to compare to
- * @return the ordering of this claim relative to o
- */
- @Override
- public int compareTo(ClaimIPType o) {
- int compareTo = claimName.compareTo(o.claimName);
- if (compareTo == 0) {
- compareTo = ipType.getTypeName().compareTo(o.ipType.getTypeName());
- }
- return compareTo;
- }
+ public void observeBeforeBeanDiscovery(@Observes final BeforeBeanDiscovery bbd, final BeanManager beanManager) {
+ bbd.addAnnotatedType(beanManager.createAnnotatedType(TCKTokenParser.class));
+ bbd.addAnnotatedType(beanManager.createAnnotatedType(JsonbProducer.class));
+ bbd.addAnnotatedType(beanManager.createAnnotatedType(MPJWTFilter.class));
+ bbd.addAnnotatedType(beanManager.createAnnotatedType(MPJWTInitializer.class));
+ bbd.addAnnotatedType(beanManager.createAnnotatedType(JWTAuthContextInfoProvider.class));
+ bbd.addAnnotatedType(beanManager.createAnnotatedType(MPJWTProducer.class));
}
- /**
- * The representation of an @Claim annotated injection site
- */
- public static class ClaimIP {
- /**
- * The injection site value type
- */
- private Type matchType;
- /**
- * The actual type of of the ParameterizedType matchType
- */
- private Type valueType;
- /**
- * Is valueType actually wrapped in an Optional
- */
- private boolean isOptional;
- private boolean isProviderSite;
- private boolean isNonStandard;
- private boolean isJsonValue;
- /**
- * The injection site @Claim annotation value
- */
- private Claim claim;
- /**
- * The location that share the @Claim/type combination
- */
- private HashSet<InjectionPoint> injectionPoints = new HashSet<>();
-
- /**
- * Create a ClaimIP from the injection site information
- *
- * @param matchType - the outer type of the injection site
- * @param valueType - the parameterized type of the injection site
- * @param isOptional - is the injection site an Optional
- * @param claim - the Claim qualifier
- */
- public ClaimIP(Type matchType, Type valueType, boolean isOptional, Claim claim) {
- this.matchType = matchType;
- this.valueType = valueType;
- this.claim = claim;
- }
-
- public Type getMatchType() {
- return matchType;
- }
-
- public String getClaimName() {
- return claim.standard() == Claims.UNKNOWN ? claim.value() : claim.standard().name();
- }
-
- public Claim getClaim() {
- return claim;
- }
-
- public Type getValueType() {
- return valueType;
- }
-
- public boolean isOptional() {
- return isOptional;
- }
-
- public boolean isProviderSite() {
- return isProviderSite;
- }
-
- public void setProviderSite(boolean providerSite) {
- this.isProviderSite = providerSite;
- }
-
- public boolean isNonStandard() {
- return isNonStandard;
- }
-
- public void setNonStandard(boolean nonStandard) {
- isNonStandard = nonStandard;
- }
-
- public boolean isJsonValue() {
- return isJsonValue;
- }
-
- public void setJsonValue(boolean jsonValue) {
- isJsonValue = jsonValue;
- }
-
- public Set<InjectionPoint> getInjectionPoints() {
- return injectionPoints;
- }
-
- @Override
- public String toString() {
- return "ClaimIP{" +
- "type=" + matchType +
- ", claim=" + claim +
- ", ips=" + injectionPoints +
- '}';
- }
- }
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/d81bd39d/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/cdi/MPJWTProducer.java
----------------------------------------------------------------------
diff --git a/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/cdi/MPJWTProducer.java b/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/cdi/MPJWTProducer.java
index 16876fb..1d83a08 100644
--- a/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/cdi/MPJWTProducer.java
+++ b/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/cdi/MPJWTProducer.java
@@ -16,18 +16,22 @@
*/
package org.apache.tomee.microprofile.jwt.cdi;
+import org.eclipse.microprofile.jwt.Claim;
import org.eclipse.microprofile.jwt.ClaimValue;
+import org.eclipse.microprofile.jwt.Claims;
import org.eclipse.microprofile.jwt.JsonWebToken;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.context.RequestScoped;
import javax.enterprise.inject.Produces;
+import javax.enterprise.inject.spi.InjectionPoint;
import javax.inject.Inject;
import javax.json.Json;
import javax.json.JsonArrayBuilder;
import javax.json.JsonObject;
import javax.json.JsonValue;
import javax.json.bind.Jsonb;
+import java.lang.annotation.Annotation;
import java.util.Collection;
import java.util.Map;
import java.util.Optional;
http://git-wip-us.apache.org/repos/asf/tomee/blob/d81bd39d/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/cdi/RawClaimTypeProducer.java
----------------------------------------------------------------------
diff --git a/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/cdi/RawClaimTypeProducer.java b/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/cdi/RawClaimTypeProducer.java
deleted file mode 100644
index fbc037b..0000000
--- a/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/cdi/RawClaimTypeProducer.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.tomee.microprofile.jwt.cdi;
-
-import org.eclipse.microprofile.jwt.Claim;
-import org.eclipse.microprofile.jwt.ClaimValue;
-import org.eclipse.microprofile.jwt.Claims;
-
-import javax.enterprise.inject.Produces;
-import javax.enterprise.inject.spi.InjectionPoint;
-import javax.inject.Inject;
-import javax.inject.Named;
-import java.lang.annotation.Annotation;
-import java.util.HashSet;
-import java.util.Optional;
-import java.util.Set;
-
-public class RawClaimTypeProducer {
-
- @Inject
- private MPJWTProducer producer;
-
- @Produces
- @Claim("")
- public Set<String> getSetOfString(final InjectionPoint ip) {
- final String name = getName(ip);
- ClaimValue<Optional<String>> cv = producer.generalClaimValueProducer(name);
- Optional<String> value = cv.getValue();
- if (value.isPresent()) {
- return new HashSet<String>() {{
- add(value.get());
- }};
- }
- return null;
- }
-
- @Produces
- @Claim("")
- @Named("RawClaimTypeProducer#getValue")
- public Object getValue(final InjectionPoint ip) {
- String name = getName(ip);
- ClaimValue<Optional<Object>> cv = producer.generalClaimValueProducer(name);
- Optional<Object> value = cv.getValue();
- return value.orElse(null);
- }
-
- @Produces
- @Claim("")
- @Named("RawClaimTypeProducer#getOptionalValue")
- public Optional getOptionalValue(final InjectionPoint ip) {
- String name = getName(ip);
- ClaimValue<Optional<Object>> cv = producer.generalClaimValueProducer(name);
- return cv.getValue();
- }
-
- private String getName(final InjectionPoint ip) {
- String name = null;
- for (Annotation ann : ip.getQualifiers()) {
- if (ann instanceof Claim) {
- Claim claim = (Claim) ann;
- name = claim.standard() == Claims.UNKNOWN ? claim.value() : claim.standard().name();
- }
- }
- return name;
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/d81bd39d/tck/mp-jwt-embedded/src/test/resources/dev.xml
----------------------------------------------------------------------
diff --git a/tck/mp-jwt-embedded/src/test/resources/dev.xml b/tck/mp-jwt-embedded/src/test/resources/dev.xml
index 88932f9..b347b26 100644
--- a/tck/mp-jwt-embedded/src/test/resources/dev.xml
+++ b/tck/mp-jwt-embedded/src/test/resources/dev.xml
@@ -42,22 +42,24 @@
</groups>
<classes>
<!-- OK
- -->
<class name="org.eclipse.microprofile.jwt.tck.parsing.TokenValidationTest" />
<class name="org.eclipse.microprofile.jwt.tck.util.TokenUtilsTest" />
<class name="org.eclipse.microprofile.jwt.tck.parsing.TestTokenClaimTypesTest" />
<class name="org.eclipse.microprofile.jwt.tck.container.jaxrs.UnsecuredPingTest" />
<class name="org.eclipse.microprofile.jwt.tck.container.jaxrs.RequiredClaimsTest" />
+ -->
+ <class name="org.eclipse.microprofile.jwt.tck.container.jaxrs.PrimitiveInjectionTest" />
<class name="org.eclipse.microprofile.jwt.tck.container.jaxrs.ClaimValueInjectionTest" />
<class name="org.eclipse.microprofile.jwt.tck.container.jaxrs.JsonValueInjectionTest" />
<class name="org.eclipse.microprofile.jwt.tck.container.jaxrs.ProviderInjectionTest" />
+ <!-- KO
<class name="org.eclipse.microprofile.jwt.tck.container.jaxrs.RolesAllowedTest" />
<class name="org.eclipse.microprofile.jwt.tck.container.jaxrs.InvalidTokenTest" />
- <!-- KO
-->
</classes>
</test>
+ <!--
<test name="extended-tests" verbose="10">
<groups>
<define name="extended-groups">
@@ -76,14 +78,10 @@
</run>
</groups>
<classes>
- <!-- OK
- -->
<class name="org.eclipse.microprofile.jwt.tck.container.ejb.EjbTest" />
<class name="org.eclipse.microprofile.jwt.tck.container.servlet.ServletTest" />
<class name="org.eclipse.microprofile.jwt.tck.container.jacc.SubjectTest" />
- <!-- KO
- -->
</classes>
</test>
-
+ -->
</suite>