src/share/jaxws_classes/com/sun/xml/internal/ws/binding/WebServiceFeatureList.java

Thu, 31 Aug 2017 15:18:52 +0800

author
aoqi
date
Thu, 31 Aug 2017 15:18:52 +0800
changeset 637
9c07ef4934dd
parent 408
b0610cd08440
parent 0
373ffda63c9a
permissions
-rw-r--r--

merge

     1 /*
     2  * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    26 package com.sun.xml.internal.ws.binding;
    28 import com.sun.istack.internal.NotNull;
    29 import com.sun.istack.internal.Nullable;
    30 import com.sun.xml.internal.ws.api.BindingID;
    31 import com.sun.xml.internal.ws.api.FeatureListValidator;
    32 import com.sun.xml.internal.ws.api.FeatureListValidatorAnnotation;
    33 import com.sun.xml.internal.ws.api.ImpliesWebServiceFeature;
    34 import com.sun.xml.internal.ws.api.SOAPVersion;
    35 import com.sun.xml.internal.ws.api.WSBinding;
    36 import com.sun.xml.internal.ws.api.WSFeatureList;
    37 import com.sun.xml.internal.ws.api.FeatureConstructor;
    38 import com.sun.xml.internal.ws.api.model.wsdl.WSDLPort;
    39 import com.sun.xml.internal.ws.api.model.wsdl.WSDLFeaturedObject;
    40 import com.sun.xml.internal.ws.model.RuntimeModelerException;
    41 import com.sun.xml.internal.ws.resources.ModelerMessages;
    42 import com.sun.xml.internal.bind.util.Which;
    44 import javax.xml.ws.RespectBinding;
    45 import javax.xml.ws.RespectBindingFeature;
    46 import javax.xml.ws.WebServiceException;
    47 import javax.xml.ws.WebServiceFeature;
    48 import javax.xml.ws.soap.Addressing;
    49 import javax.xml.ws.soap.AddressingFeature;
    50 import javax.xml.ws.soap.MTOM;
    51 import javax.xml.ws.soap.MTOMFeature;
    52 import javax.xml.ws.spi.WebServiceFeatureAnnotation;
    54 import com.oracle.webservices.internal.api.EnvelopeStyleFeature;
    56 import java.lang.annotation.Annotation;
    57 import java.lang.reflect.InvocationTargetException;
    58 import java.lang.reflect.Method;
    59 import java.lang.reflect.Constructor;
    60 import java.util.*;
    61 import java.util.logging.Logger;
    63 /**
    64  * Represents a list of {@link WebServiceFeature}s that has bunch of utility
    65  * methods pertaining to web service features.
    66  *
    67  * @author Rama Pulavarthi
    68  */
    69 public final class WebServiceFeatureList extends AbstractMap<Class<? extends WebServiceFeature>, WebServiceFeature> implements WSFeatureList {
    70     public static WebServiceFeatureList toList(Iterable<WebServiceFeature> features) {
    71         if (features instanceof WebServiceFeatureList)
    72             return (WebServiceFeatureList) features;
    73         WebServiceFeatureList w = new WebServiceFeatureList();
    74         if (features != null)
    75             w.addAll(features);
    76         return w;
    77     }
    79     private Map<Class<? extends WebServiceFeature>, WebServiceFeature> wsfeatures = new HashMap<Class<? extends WebServiceFeature>, WebServiceFeature>();
    80     private boolean isValidating = false;
    82     public WebServiceFeatureList() {
    83     }
    85     /**
    86      * Delegate to this parent if non-null.
    87      */
    88     private @Nullable
    89         WSDLFeaturedObject parent;
    91     public WebServiceFeatureList(@NotNull WebServiceFeature... features) {
    92         if (features != null) {
    93             for (WebServiceFeature f : features) {
    94                 addNoValidate(f);
    95             }
    96         }
    97     }
    99     public void validate() {
   100         if (!isValidating) {
   101             isValidating = true;
   103             // validation
   104             for (WebServiceFeature ff : this) {
   105                 validate(ff);
   106             }
   107         }
   108     }
   110     private void validate(WebServiceFeature feature) {
   111         // run validation
   112         FeatureListValidatorAnnotation fva = feature.getClass().getAnnotation(FeatureListValidatorAnnotation.class);
   113         if (fva != null) {
   114             Class<? extends FeatureListValidator> beanClass = fva.bean();
   115             try {
   116                 FeatureListValidator validator = beanClass.newInstance();
   117                 validator.validate(this);
   118             } catch (InstantiationException e) {
   119                 throw new WebServiceException(e);
   120             } catch (IllegalAccessException e) {
   121                 throw new WebServiceException(e);
   122             }
   123         }
   124     }
   126     public WebServiceFeatureList(WebServiceFeatureList features) {
   127         if (features != null) {
   128             wsfeatures.putAll(features.wsfeatures);
   129             parent = features.parent;
   130             isValidating = features.isValidating;
   131         }
   132     }
   134     /**
   135      * Creates a list by reading featuers from the annotation on a class.
   136      */
   137     public WebServiceFeatureList(@NotNull Class<?> endpointClass) {
   138         parseAnnotations(endpointClass);
   139     }
   141     /**
   142      * Adds the corresponding features to the list for feature annotations(i.e
   143      * which have {@link WebServiceFeatureAnnotation} meta annotation)
   144      *
   145      * @param annIt collection of annotations(that can have non-feature annotations)
   146      */
   147     public void parseAnnotations(Iterable<Annotation> annIt) {
   148         for(Annotation ann : annIt) {
   149             WebServiceFeature feature = getFeature(ann);
   150             if (feature != null) {
   151                 add(feature);
   152             }
   153         }
   154     }
   156     /**
   157      * Returns a corresponding feature for a feature annotation(i.e which has
   158      * {@link WebServiceFeatureAnnotation} meta annotation)
   159      *
   160      * @return corresponding feature for the annotation
   161      *         null, if the annotation is nota feature annotation
   162      */
   163     public static WebServiceFeature getFeature(Annotation a) {
   164         WebServiceFeature ftr = null;
   165         if (!(a.annotationType().isAnnotationPresent(WebServiceFeatureAnnotation.class))) {
   166             ftr = null;
   167         } else if (a instanceof Addressing) {
   168             Addressing addAnn = (Addressing) a;
   169             try {
   170                 ftr = new AddressingFeature(addAnn.enabled(), addAnn.required(),addAnn.responses());
   171             } catch(NoSuchMethodError e) {
   172                 //throw error. We can't default to Responses.ALL as we dont know if the user has not used 2.2 annotation with responses.
   173                 throw new RuntimeModelerException(ModelerMessages.RUNTIME_MODELER_ADDRESSING_RESPONSES_NOSUCHMETHOD(toJar(Which.which(Addressing.class))));
   174             }
   175         } else if (a instanceof MTOM) {
   176             MTOM mtomAnn = (MTOM) a;
   177             ftr = new MTOMFeature(mtomAnn.enabled(), mtomAnn.threshold());
   178         } else if (a instanceof RespectBinding) {
   179             RespectBinding rbAnn = (RespectBinding) a;
   180             ftr = new RespectBindingFeature(rbAnn.enabled());
   181         } else {
   182             ftr = getWebServiceFeatureBean(a);
   183         }
   184         return ftr;
   185     }
   187     /**
   188      *
   189      * @param endpointClass web service impl class
   190      */
   191     public void parseAnnotations(Class<?> endpointClass) {
   192         for (Annotation a : endpointClass.getAnnotations()) {
   193             WebServiceFeature ftr = getFeature(a);
   194             if (ftr != null) {
   195                 if (ftr instanceof MTOMFeature) {
   196                     // check conflict with @BindingType
   197                     BindingID bindingID = BindingID.parse(endpointClass);
   198                     MTOMFeature bindingMtomSetting = bindingID.createBuiltinFeatureList().get(MTOMFeature.class);
   199                     if (bindingMtomSetting != null && bindingMtomSetting.isEnabled() ^ ftr.isEnabled()) {
   200                         throw new RuntimeModelerException(
   201                             ModelerMessages.RUNTIME_MODELER_MTOM_CONFLICT(bindingID, ftr.isEnabled()));
   202                     }
   203                 }
   204                 add(ftr);
   205             }
   206         }
   207     }
   209     /**
   210      * Given the URL String inside jar, returns the URL to the jar itself.
   211      */
   212     private static String toJar(String url) {
   213         if(!url.startsWith("jar:"))
   214             return url;
   215         url = url.substring(4); // cut off jar:
   216         return url.substring(0,url.lastIndexOf('!'));    // cut off everything after '!'
   217     }
   219     private static WebServiceFeature getWebServiceFeatureBean(Annotation a) {
   220         WebServiceFeatureAnnotation wsfa = a.annotationType().getAnnotation(WebServiceFeatureAnnotation.class);
   221         Class<? extends WebServiceFeature> beanClass = wsfa.bean();
   222         WebServiceFeature bean;
   224         Constructor ftrCtr = null;
   225         String[] paramNames = null;
   226         for (Constructor con : beanClass.getConstructors()) {
   227             FeatureConstructor ftrCtrAnn = (FeatureConstructor) con.getAnnotation(FeatureConstructor.class);
   228             if (ftrCtrAnn != null) {
   229                 if (ftrCtr == null) {
   230                     ftrCtr = con;
   231                     paramNames = ftrCtrAnn.value();
   232                 } else {
   233                     throw new WebServiceException(
   234                         ModelerMessages.RUNTIME_MODELER_WSFEATURE_MORETHANONE_FTRCONSTRUCTOR(a, beanClass));
   235                 }
   236             }
   237         }
   238         if (ftrCtr == null) {
   239             bean = getWebServiceFeatureBeanViaBuilder(a, beanClass);
   240             if (bean != null) {
   241                 return bean;
   242             } else {
   243                 throw new WebServiceException(
   244                     ModelerMessages.RUNTIME_MODELER_WSFEATURE_NO_FTRCONSTRUCTOR(a, beanClass));
   245             }
   246         }
   247         if (ftrCtr.getParameterTypes().length != paramNames.length) {
   248             throw new WebServiceException(
   249                 ModelerMessages.RUNTIME_MODELER_WSFEATURE_ILLEGAL_FTRCONSTRUCTOR(a, beanClass));
   250         }
   252         try {
   253             Object[] params = new Object[paramNames.length];
   254             for (int i = 0; i < paramNames.length; i++) {
   255                 Method m = a.annotationType().getDeclaredMethod(paramNames[i]);
   256                 params[i] = m.invoke(a);
   257             }
   258             bean = (WebServiceFeature) ftrCtr.newInstance(params);
   259         } catch (Exception e) {
   260             throw new WebServiceException(e);
   261         }
   262         return bean;
   263     }
   265     private static WebServiceFeature getWebServiceFeatureBeanViaBuilder(
   266         final Annotation annotation,
   267         final Class<? extends WebServiceFeature> beanClass)
   268     {
   269         try {
   270             final Method featureBuilderMethod = beanClass.getDeclaredMethod("builder");
   271             final Object builder = featureBuilderMethod.invoke(beanClass);
   272             final Method buildMethod = builder.getClass().getDeclaredMethod("build");
   274             for (Method builderMethod : builder.getClass().getDeclaredMethods()) {
   275                 if (!builderMethod.equals(buildMethod)) {
   276                     final String methodName = builderMethod.getName();
   277                     final Method annotationMethod = annotation.annotationType().getDeclaredMethod(methodName);
   278                     final Object annotationFieldValue = annotationMethod.invoke(annotation);
   279                     final Object[] arg = { annotationFieldValue };
   280                     if (skipDuringOrgJvnetWsToComOracleWebservicesPackageMove(builderMethod, annotationFieldValue)) {
   281                         continue;
   282                     }
   283                     builderMethod.invoke(builder, arg);
   284                 }
   285             }
   287             final Object result = buildMethod.invoke(builder);
   288             if (result instanceof WebServiceFeature) {
   289                 return (WebServiceFeature) result;
   290             } else {
   291                 throw new WebServiceException("Not a WebServiceFeature: " + result);
   292             }
   293         } catch (final NoSuchMethodException e) {
   294             return null;
   295         } catch (final IllegalAccessException e) {
   296             throw new WebServiceException(e);
   297         } catch (final InvocationTargetException e) {
   298             throw new WebServiceException(e);
   299         }
   300     }
   302     // TODO this will be removed after package move is complete.
   303     private static boolean skipDuringOrgJvnetWsToComOracleWebservicesPackageMove(
   304         final Method builderMethod,
   305         final Object annotationFieldValue)
   306     {
   307         final Class<?> annotationFieldValueClass = annotationFieldValue.getClass();
   308         if (! annotationFieldValueClass.isEnum()) {
   309             return false;
   310         }
   311         final Class<?>[] builderMethodParameterTypes = builderMethod.getParameterTypes();
   312         if (builderMethodParameterTypes.length != 1) {
   313             throw new WebServiceException("expected only 1 parameter");
   314         }
   315         final String builderParameterTypeName = builderMethodParameterTypes[0].getName();
   316         if (! builderParameterTypeName.startsWith("com.oracle.webservices.internal.test.features_annotations_enums.apinew") &&
   317             ! builderParameterTypeName.startsWith("com.oracle.webservices.internal.api")) {
   318             return false;
   319         }
   320         return false;
   321     }
   323     public Iterator<WebServiceFeature> iterator() {
   324         if (parent != null)
   325             return new MergedFeatures(parent.getFeatures());
   326         return wsfeatures.values().iterator();
   327     }
   329     public @NotNull
   330         WebServiceFeature[] toArray() {
   331         if (parent != null)
   332             return new MergedFeatures(parent.getFeatures()).toArray();
   333         return wsfeatures.values().toArray(new WebServiceFeature[] {});
   334     }
   336     public boolean isEnabled(@NotNull Class<? extends WebServiceFeature> feature) {
   337         WebServiceFeature ftr = get(feature);
   338         return ftr != null && ftr.isEnabled();
   339     }
   341     public boolean contains(@NotNull Class<? extends WebServiceFeature> feature) {
   342         WebServiceFeature ftr = get(feature);
   343         return ftr != null;
   344     }
   346     public @Nullable
   347         <F extends WebServiceFeature> F get(@NotNull Class<F> featureType) {
   348         WebServiceFeature f = featureType.cast(wsfeatures.get(featureType));
   349         if (f == null && parent != null) {
   350             return parent.getFeatures().get(featureType);
   351         }
   352         return (F) f;
   353     }
   355     /**
   356      * Adds a feature to the list if it's not already added.
   357      */
   358     public void add(@NotNull WebServiceFeature f) {
   359         if(addNoValidate(f) && isValidating)
   360             validate(f);
   361     }
   363     private boolean addNoValidate(@NotNull WebServiceFeature f) {
   364         if (!wsfeatures.containsKey(f.getClass())) {
   365             wsfeatures.put(f.getClass(), f);
   367             if (f instanceof ImpliesWebServiceFeature)
   368                 ((ImpliesWebServiceFeature) f).implyFeatures(this);
   370             return true;
   371         }
   373         return false;
   374     }
   376     /**
   377      * Adds features to the list if it's not already added.
   378      */
   379     public void addAll(@NotNull Iterable<WebServiceFeature> list) {
   380         for (WebServiceFeature f : list)
   381             add(f);
   382     }
   384     /**
   385      * Sets MTOM feature, overriding any existing feature.  This is necessary for compatibility
   386      * with the existing {@link SOAPBinding.setMTOMEnabled}.
   387      * @param b if MTOM will be enabled
   388      */
   389     void setMTOMEnabled(boolean b) {
   390         wsfeatures.put(MTOMFeature.class, new MTOMFeature(b));
   391     }
   393     public boolean equals(Object other) {
   394         if (!(other instanceof WebServiceFeatureList))
   395             return false;
   397         WebServiceFeatureList w = (WebServiceFeatureList) other;
   398         return wsfeatures.equals(w.wsfeatures) && (parent == w.parent);
   399     }
   401     public String toString() {
   402         return wsfeatures.toString();
   403     }
   405     /**
   406      * Merges the extra features that are not already set on binding.
   407      * i.e, if a feature is set already on binding through some other API
   408      * the corresponding wsdlFeature is not set.
   409      *
   410      * @param features          Web Service features that need to be merged with already configured features.
   411      * @param reportConflicts   If true, checks if the feature setting in WSDL (wsdl extension or
   412      *                          policy configuration) conflicts with feature setting in Deployed Service and
   413      *                          logs warning if there are any conflicts.
   414      */
   415     public void mergeFeatures(@NotNull Iterable<WebServiceFeature> features, boolean reportConflicts) {
   416         for (WebServiceFeature wsdlFtr : features) {
   417             if (get(wsdlFtr.getClass()) == null) {
   418                 add(wsdlFtr);
   419             } else if (reportConflicts) {
   420                 if (isEnabled(wsdlFtr.getClass()) != wsdlFtr.isEnabled()) {
   421                     LOGGER.warning(ModelerMessages.RUNTIME_MODELER_FEATURE_CONFLICT(
   422                                        get(wsdlFtr.getClass()), wsdlFtr));
   423                 }
   424             }
   425         }
   426     }
   428     public void mergeFeatures(WebServiceFeature[] features, boolean reportConflicts) {
   429         for (WebServiceFeature wsdlFtr : features) {
   430             if (get(wsdlFtr.getClass()) == null) {
   431                 add(wsdlFtr);
   432             } else if (reportConflicts) {
   433                 if (isEnabled(wsdlFtr.getClass()) != wsdlFtr.isEnabled()) {
   434                     LOGGER.warning(ModelerMessages.RUNTIME_MODELER_FEATURE_CONFLICT(
   435                                        get(wsdlFtr.getClass()), wsdlFtr));
   436                 }
   437             }
   438         }
   439     }
   441     /**
   442      * Extracts features from {@link WSDLPort#getFeatures()}. Extra features
   443      * that are not already set on binding. i.e, if a feature is set already on
   444      * binding through some other API the corresponding wsdlFeature is not set.
   445      *
   446      * @param wsdlPort
   447      *            WSDLPort model
   448      * @param honorWsdlRequired
   449      *            If this is true add WSDL Feature only if wsd:Required=true In
   450      *            SEI case, it should be false In Provider case, it should be
   451      *            true
   452      * @param reportConflicts
   453      *            If true, checks if the feature setting in WSDL (wsdl extension
   454      *            or policy configuration) conflicts with feature setting in
   455      *            Deployed Service and logs warning if there are any conflicts.
   456      */
   457     public void mergeFeatures(@NotNull WSDLPort wsdlPort,
   458                               boolean honorWsdlRequired, boolean reportConflicts) {
   459         if (honorWsdlRequired && !isEnabled(RespectBindingFeature.class))
   460             return;
   461         if (!honorWsdlRequired) {
   462             addAll(wsdlPort.getFeatures());
   463             return;
   464         }
   465         // Add only if isRequired returns true, when honorWsdlRequired is true
   466         for (WebServiceFeature wsdlFtr : wsdlPort.getFeatures()) {
   467             if (get(wsdlFtr.getClass()) == null) {
   468                 try {
   469                     // if it is a WSDL Extension , it will have required
   470                     // attribute
   471                     Method m = (wsdlFtr.getClass().getMethod("isRequired"));
   472                     try {
   473                         boolean required = (Boolean) m.invoke(wsdlFtr);
   474                         if (required)
   475                             add(wsdlFtr);
   476                     } catch (IllegalAccessException e) {
   477                         throw new WebServiceException(e);
   478                     } catch (InvocationTargetException e) {
   479                         throw new WebServiceException(e);
   480                     }
   481                 } catch (NoSuchMethodException e) {
   482                     // this wsdlFtr is not an WSDL extension, just add it
   483                     add(wsdlFtr);
   484                 }
   485             } else if (reportConflicts) {
   486                 if (isEnabled(wsdlFtr.getClass()) != wsdlFtr.isEnabled()) {
   487                     LOGGER.warning(ModelerMessages.RUNTIME_MODELER_FEATURE_CONFLICT(
   488                                        get(wsdlFtr.getClass()), wsdlFtr));
   489                 }
   491             }
   492         }
   493     }
   495     /**
   496      * Set the parent features. Basically the parent feature list will be
   497      * overriden by this feature list.
   498      */
   499     public void setParentFeaturedObject(@NotNull WSDLFeaturedObject parent) {
   500         this.parent = parent;
   501     }
   503     public static @Nullable <F extends WebServiceFeature> F getFeature(@NotNull WebServiceFeature[] features,
   504                                                                        @NotNull Class<F> featureType) {
   505         for (WebServiceFeature f : features) {
   506             if (f.getClass() == featureType)
   507                 return (F) f;
   508         }
   509         return null;
   510     }
   512     /**
   513      * A Union of this WebServiceFeatureList and the parent.
   514      */
   515     private final class MergedFeatures implements Iterator<WebServiceFeature> {
   516         private final Stack<WebServiceFeature> features = new Stack<WebServiceFeature>();
   518         public MergedFeatures(@NotNull WSFeatureList parent) {
   520             for (WebServiceFeature f : wsfeatures.values()) {
   521                 features.push(f);
   522             }
   524             for (WebServiceFeature f : parent) {
   525                 if (!wsfeatures.containsKey(f.getClass())) {
   526                     features.push(f);
   527                 }
   528             }
   529         }
   531         public boolean hasNext() {
   532             return !features.empty();
   533         }
   535         public WebServiceFeature next() {
   536             if (!features.empty()) {
   537                 return features.pop();
   538             }
   539             throw new NoSuchElementException();
   540         }
   542         public void remove() {
   543             if (!features.empty()) {
   544                 features.pop();
   545             }
   546         }
   548         public WebServiceFeature[] toArray() {
   549             return features.toArray(new WebServiceFeature[] {});
   550         }
   551     }
   553     private static final Logger LOGGER = Logger.getLogger(WebServiceFeatureList.class.getName());
   555     @Override
   556     public Set<java.util.Map.Entry<Class<? extends WebServiceFeature>, WebServiceFeature>> entrySet() {
   557         return wsfeatures.entrySet();
   558     }
   560     @Override
   561     public WebServiceFeature put(Class<? extends WebServiceFeature> key, WebServiceFeature value) {
   562         return wsfeatures.put(key, value);
   563     }
   565     static public SOAPVersion getSoapVersion(WSFeatureList features) {
   566         {
   567             EnvelopeStyleFeature env = features.get(EnvelopeStyleFeature.class);
   568             if (env != null) {
   569                 return SOAPVersion.from(env);
   570             }
   571         }
   572         com.oracle.webservices.internal.api.EnvelopeStyleFeature env = features.get(com.oracle.webservices.internal.api.EnvelopeStyleFeature.class);
   573         return env != null ? SOAPVersion.from(env) : null;
   574     }
   576     static public boolean isFeatureEnabled(Class<? extends WebServiceFeature> type, WebServiceFeature[] features) {
   577         WebServiceFeature ftr = getFeature(features, type);
   578         return ftr != null && ftr.isEnabled();
   579     }
   581     static public WebServiceFeature[] toFeatureArray(WSBinding binding) {
   582         //TODO scchen convert BindingID  to WebServiceFeature[]
   583         if(!binding.isFeatureEnabled(EnvelopeStyleFeature.class)) {
   584             WebServiceFeature[] f = { binding.getSOAPVersion().toFeature() };
   585             binding.getFeatures().mergeFeatures(f, false);
   586         }
   587         return binding.getFeatures().toArray();
   588     }
   589 }

mercurial