325N/A/*
325N/A * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
325N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
325N/A *
325N/A * This code is free software; you can redistribute it and/or modify it
325N/A * under the terms of the GNU General Public License version 2 only, as
325N/A * published by the Free Software Foundation. Oracle designates this
325N/A * particular file as subject to the "Classpath" exception as provided
325N/A * by Oracle in the LICENSE file that accompanied this code.
325N/A *
325N/A * This code is distributed in the hope that it will be useful, but WITHOUT
325N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
325N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
325N/A * version 2 for more details (a copy is included in the LICENSE file that
325N/A * accompanied this code).
325N/A *
325N/A * You should have received a copy of the GNU General Public License version
325N/A * 2 along with this work; if not, write to the Free Software Foundation,
325N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
325N/A *
325N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
325N/A * or visit www.oracle.com if you need additional information or have any
325N/A * questions.
325N/A */
325N/A
325N/Apackage com.sun.xml.internal.ws.binding;
325N/A
325N/Aimport com.sun.istack.internal.NotNull;
325N/Aimport com.sun.istack.internal.Nullable;
325N/Aimport com.sun.xml.internal.ws.api.BindingID;
325N/Aimport com.sun.xml.internal.ws.api.WSFeatureList;
325N/Aimport com.sun.xml.internal.ws.api.FeatureConstructor;
325N/Aimport com.sun.xml.internal.ws.api.model.wsdl.WSDLPort;
325N/Aimport com.sun.xml.internal.ws.api.model.wsdl.WSDLFeaturedObject;
325N/Aimport com.sun.xml.internal.ws.model.RuntimeModelerException;
325N/Aimport com.sun.xml.internal.ws.model.wsdl.WSDLPortImpl;
325N/Aimport com.sun.xml.internal.ws.resources.ModelerMessages;
325N/Aimport com.sun.xml.internal.bind.util.Which;
325N/A
325N/Aimport javax.xml.ws.RespectBinding;
325N/Aimport javax.xml.ws.RespectBindingFeature;
325N/Aimport javax.xml.ws.WebServiceException;
325N/Aimport javax.xml.ws.WebServiceFeature;
325N/Aimport javax.xml.ws.soap.Addressing;
325N/Aimport javax.xml.ws.soap.AddressingFeature;
325N/Aimport javax.xml.ws.soap.MTOM;
325N/Aimport javax.xml.ws.soap.MTOMFeature;
325N/Aimport javax.xml.ws.spi.WebServiceFeatureAnnotation;
325N/Aimport java.lang.annotation.Annotation;
325N/Aimport java.lang.reflect.InvocationTargetException;
325N/Aimport java.lang.reflect.Method;
325N/Aimport java.lang.reflect.Constructor;
325N/Aimport java.util.*;
325N/Aimport java.util.logging.Logger;
325N/A
325N/A/**
325N/A * Represents a list of {@link WebServiceFeature}s that has bunch of utility methods
325N/A * pertaining to web service features.
325N/A *
325N/A * @author Rama Pulavarthi
325N/A */
325N/Apublic final class WebServiceFeatureList implements WSFeatureList {
325N/A private Map<Class<? extends WebServiceFeature>, WebServiceFeature> wsfeatures =
325N/A new HashMap<Class<? extends WebServiceFeature>, WebServiceFeature>();
325N/A
325N/A public WebServiceFeatureList() {
325N/A }
325N/A
325N/A /**
325N/A * Delegate to this parent if non-null.
325N/A */
325N/A private @Nullable WSDLFeaturedObject parent;
325N/A
325N/A public WebServiceFeatureList(@NotNull WebServiceFeature... features) {
325N/A if (features != null)
325N/A for (WebServiceFeature f : features) {
325N/A wsfeatures.put(f.getClass(), f);
325N/A }
325N/A }
325N/A
325N/A /**
325N/A * Creates a list by reading featuers from the annotation on a class.
325N/A */
325N/A public WebServiceFeatureList(@NotNull Class<?> endpointClass) {
325N/A parseAnnotations(endpointClass);
325N/A }
325N/A
325N/A /**
325N/A * Adds the corresponding features to the list for feature annotations(i.e
325N/A * which have {@link WebServiceFeatureAnnotation} meta annotation)
325N/A *
325N/A * @param annIt collection of annotations(that can have non-feature annotations)
325N/A */
325N/A public void parseAnnotations(Iterable<Annotation> annIt) {
325N/A for(Annotation ann : annIt) {
325N/A WebServiceFeature feature = getFeature(ann);
325N/A if (feature != null) {
325N/A add(feature);
325N/A }
325N/A }
325N/A }
325N/A
325N/A /**
325N/A * Returns a corresponding feature for a feature annotation(i.e which has
325N/A * {@link WebServiceFeatureAnnotation} meta annotation)
325N/A *
325N/A * @return corresponding feature for the annotation
325N/A * null, if the annotation is nota feature annotation
325N/A */
325N/A public static WebServiceFeature getFeature(Annotation a) {
325N/A WebServiceFeature ftr;
325N/A if (!(a.annotationType().isAnnotationPresent(WebServiceFeatureAnnotation.class))) {
325N/A ftr = null;
325N/A } else if (a instanceof Addressing) {
325N/A Addressing addAnn = (Addressing) a;
325N/A try {
325N/A ftr = new AddressingFeature(addAnn.enabled(), addAnn.required(),addAnn.responses());
325N/A } catch(NoSuchMethodError e) {
325N/A //throw error. We can't default to Responses.ALL as we dont know if the user has not used 2.2 annotation with responses.
325N/A throw new RuntimeModelerException(ModelerMessages.RUNTIME_MODELER_ADDRESSING_RESPONSES_NOSUCHMETHOD(toJar(Which.which(Addressing.class))));
325N/A }
325N/A } else if (a instanceof MTOM) {
325N/A MTOM mtomAnn = (MTOM) a;
325N/A ftr = new MTOMFeature(mtomAnn.enabled(), mtomAnn.threshold());
325N/A } else if (a instanceof RespectBinding) {
325N/A RespectBinding rbAnn = (RespectBinding) a;
325N/A ftr = new RespectBindingFeature(rbAnn.enabled());
325N/A } else {
325N/A ftr = getWebServiceFeatureBean(a);
325N/A }
325N/A return ftr;
325N/A }
325N/A
325N/A /**
325N/A * Reads {@link WebServiceFeatureAnnotation feature annotations} on a class
325N/A * and adds them to the list.
325N/A *
325N/A * @param endpointClass web service impl class
325N/A */
325N/A public void parseAnnotations(Class<?> endpointClass) {
325N/A for (Annotation a : endpointClass.getAnnotations()) {
325N/A WebServiceFeature ftr = getFeature(a);
325N/A if (ftr != null) {
325N/A if (ftr instanceof MTOMFeature) {
325N/A // check conflict with @BindingType
325N/A BindingID bindingID = BindingID.parse(endpointClass);
325N/A MTOMFeature bindingMtomSetting = bindingID.createBuiltinFeatureList().get(MTOMFeature.class);
325N/A if (bindingMtomSetting != null && bindingMtomSetting.isEnabled() ^ ftr.isEnabled()) {
325N/A throw new RuntimeModelerException(
325N/A ModelerMessages.RUNTIME_MODELER_MTOM_CONFLICT(bindingID, ftr.isEnabled()));
325N/A }
325N/A }
325N/A add(ftr);
325N/A }
325N/A }
325N/A }
325N/A
325N/A /**
325N/A * Given the URL String inside jar, returns the URL to the jar itself.
325N/A */
325N/A private static String toJar(String url) {
325N/A if(!url.startsWith("jar:"))
325N/A return url;
325N/A url = url.substring(4); // cut off jar:
325N/A return url.substring(0,url.lastIndexOf('!')); // cut off everything after '!'
325N/A }
325N/A
325N/A private static WebServiceFeature getWebServiceFeatureBean(Annotation a) {
325N/A WebServiceFeatureAnnotation wsfa = a.annotationType().getAnnotation(WebServiceFeatureAnnotation.class);
325N/A Class<? extends WebServiceFeature> beanClass = wsfa.bean();
325N/A WebServiceFeature bean;
325N/A
325N/A Constructor ftrCtr = null;
325N/A String[] paramNames = null;
325N/A for (Constructor con : beanClass.getConstructors()) {
325N/A FeatureConstructor ftrCtrAnn = (FeatureConstructor) con.getAnnotation(FeatureConstructor.class);
325N/A if (ftrCtrAnn != null) {
325N/A if (ftrCtr == null) {
325N/A ftrCtr = con;
325N/A paramNames = ftrCtrAnn.value();
325N/A } else {
325N/A throw new WebServiceException(ModelerMessages.RUNTIME_MODELER_WSFEATURE_MORETHANONE_FTRCONSTRUCTOR(a, beanClass));
325N/A }
325N/A }
325N/A }
325N/A if (ftrCtr == null) {
325N/A throw new WebServiceException(ModelerMessages.RUNTIME_MODELER_WSFEATURE_NO_FTRCONSTRUCTOR(a, beanClass));
325N/A }
325N/A if (ftrCtr.getParameterTypes().length != paramNames.length) {
325N/A throw new WebServiceException(ModelerMessages.RUNTIME_MODELER_WSFEATURE_ILLEGAL_FTRCONSTRUCTOR(a, beanClass));
325N/A }
325N/A
325N/A try {
325N/A Object[] params = new Object[paramNames.length];
325N/A for (int i = 0; i < paramNames.length; i++) {
325N/A Method m = a.annotationType().getDeclaredMethod(paramNames[i]);
325N/A params[i] = m.invoke(a);
325N/A }
325N/A bean = (WebServiceFeature) ftrCtr.newInstance(params);
325N/A } catch (Exception e) {
325N/A throw new WebServiceException(e);
325N/A }
325N/A return bean;
325N/A }
325N/A
325N/A public Iterator<WebServiceFeature> iterator() {
325N/A if (parent != null)
325N/A return new MergedFeatures(parent.getFeatures());
325N/A return wsfeatures.values().iterator();
325N/A }
325N/A
325N/A public
325N/A @NotNull
325N/A WebServiceFeature[] toArray() {
325N/A if (parent != null)
325N/A return new MergedFeatures(parent.getFeatures()).toArray();
325N/A return wsfeatures.values().toArray(new WebServiceFeature[]{});
325N/A }
325N/A
325N/A public boolean isEnabled(@NotNull Class<? extends WebServiceFeature> feature) {
325N/A WebServiceFeature ftr = get(feature);
325N/A return ftr != null && ftr.isEnabled();
325N/A }
325N/A
325N/A
325N/A public
325N/A @Nullable
325N/A <F extends WebServiceFeature> F get(@NotNull Class<F> featureType) {
325N/A WebServiceFeature f = featureType.cast(wsfeatures.get(featureType));
325N/A if (f == null && parent != null) {
325N/A return parent.getFeatures().get(featureType);
325N/A }
325N/A return (F) f;
325N/A }
325N/A
325N/A /**
325N/A * Adds a feature to the list if it's not already added.
325N/A */
325N/A public void add(@NotNull WebServiceFeature f) {
325N/A if (!wsfeatures.containsKey(f.getClass())) {
325N/A wsfeatures.put(f.getClass(), f);
325N/A }
325N/A }
325N/A
325N/A /**
325N/A * Adds features to the list if it's not already added.
325N/A */
325N/A public void addAll(@NotNull WSFeatureList list) {
325N/A for (WebServiceFeature f : list)
325N/A add(f);
325N/A }
325N/A
325N/A /**
325N/A * Merges the extra features that are not already set on binding.
325N/A * i.e, if a feature is set already on binding through someother API
325N/A * the coresponding wsdlFeature is not set.
325N/A *
325N/A * @param features Web Service features that need to be merged with already configured features.
325N/A * @param reportConflicts If true, checks if the feature setting in WSDL (wsdl extension or
325N/A * policy configuration) colflicts with feature setting in Deployed Service and
325N/A * logs warning if there are any conflicts.
325N/A */
325N/A public void mergeFeatures(@NotNull Iterable<WebServiceFeature> features, boolean reportConflicts) {
325N/A for (WebServiceFeature wsdlFtr : features) {
325N/A if (get(wsdlFtr.getClass()) == null) {
325N/A add(wsdlFtr);
325N/A } else if (reportConflicts) {
325N/A if (isEnabled(wsdlFtr.getClass()) != wsdlFtr.isEnabled()) {
325N/A LOGGER.warning(ModelerMessages.RUNTIME_MODELER_FEATURE_CONFLICT(
325N/A get(wsdlFtr.getClass()), wsdlFtr));
325N/A }
325N/A }
325N/A }
325N/A }
325N/A
325N/A public void mergeFeatures(WebServiceFeature[] features, boolean reportConflicts) {
325N/A for (WebServiceFeature wsdlFtr : features) {
325N/A if (get(wsdlFtr.getClass()) == null) {
325N/A add(wsdlFtr);
325N/A } else if (reportConflicts) {
325N/A if (isEnabled(wsdlFtr.getClass()) != wsdlFtr.isEnabled()) {
325N/A LOGGER.warning(ModelerMessages.RUNTIME_MODELER_FEATURE_CONFLICT(
325N/A get(wsdlFtr.getClass()), wsdlFtr));
325N/A }
325N/A }
325N/A }
325N/A }
325N/A
325N/A /**
325N/A * Set the parent features. Basically the parent feature list will be overriden
325N/A * by this feature list.
325N/A */
325N/A public void setParentFeaturedObject(@NotNull WSDLFeaturedObject parent) {
325N/A this.parent = parent;
325N/A }
325N/A
325N/A public static @Nullable <F extends WebServiceFeature> F getFeature(@NotNull WebServiceFeature[] features, @NotNull Class<F> featureType) {
325N/A for(WebServiceFeature f : features) {
325N/A if (f.getClass() == featureType)
325N/A return (F)f;
325N/A }
325N/A return null;
325N/A }
325N/A
325N/A /**
325N/A * A Union of this WebServiceFeatureList and the parent.
325N/A */
325N/A private final class MergedFeatures implements Iterator<WebServiceFeature> {
325N/A private final Stack<WebServiceFeature> features = new Stack<WebServiceFeature>();
325N/A
325N/A public MergedFeatures(@NotNull WSFeatureList parent) {
325N/A
325N/A for (WebServiceFeature f : wsfeatures.values()) {
325N/A features.push(f);
325N/A }
325N/A
325N/A for (WebServiceFeature f : parent) {
325N/A if (!wsfeatures.containsKey(f.getClass())) {
325N/A features.push(f);
325N/A }
325N/A }
325N/A }
325N/A
325N/A public boolean hasNext() {
325N/A return !features.empty();
325N/A }
325N/A
325N/A public WebServiceFeature next() {
325N/A if (!features.empty()) {
325N/A return features.pop();
325N/A }
325N/A throw new NoSuchElementException();
325N/A }
325N/A
325N/A public void remove() {
325N/A if (!features.empty()) {
325N/A features.pop();
325N/A }
325N/A }
325N/A
325N/A public WebServiceFeature[] toArray() {
325N/A return features.toArray(new WebServiceFeature[]{});
325N/A }
325N/A }
325N/A
325N/A private static final Logger LOGGER = Logger.getLogger(WebServiceFeatureList.class.getName());
325N/A}