src/share/jaxws_classes/com/sun/xml/internal/ws/model/ExternalMetadataReader.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.model;
    28 import com.oracle.xmlns.internal.webservices.jaxws_databinding.JavaMethod;
    29 import com.oracle.xmlns.internal.webservices.jaxws_databinding.JavaParam;
    30 import com.oracle.xmlns.internal.webservices.jaxws_databinding.JavaWsdlMappingType;
    31 import com.oracle.xmlns.internal.webservices.jaxws_databinding.ObjectFactory;
    32 import com.sun.xml.internal.bind.api.JAXBRIContext;
    33 import com.sun.xml.internal.ws.streaming.XMLStreamReaderUtil;
    34 import com.sun.xml.internal.ws.util.xml.XmlUtil;
    35 import org.w3c.dom.Element;
    36 import org.xml.sax.SAXException;
    38 import javax.xml.bind.JAXBContext;
    39 import javax.xml.bind.JAXBElement;
    40 import javax.xml.bind.JAXBException;
    41 import javax.xml.bind.Unmarshaller;
    42 import javax.xml.bind.util.JAXBResult;
    43 import javax.xml.stream.XMLInputFactory;
    44 import javax.xml.stream.XMLStreamException;
    45 import javax.xml.stream.XMLStreamReader;
    46 import javax.xml.transform.Source;
    47 import javax.xml.transform.Transformer;
    48 import javax.xml.transform.TransformerException;
    49 import javax.xml.transform.TransformerFactory;
    50 import javax.xml.transform.stream.StreamSource;
    51 import javax.xml.validation.Schema;
    52 import javax.xml.validation.SchemaFactory;
    53 import java.io.*;
    54 import java.lang.annotation.Annotation;
    55 import java.lang.reflect.Method;
    56 import java.net.URL;
    57 import java.util.*;
    59 import static com.oracle.xmlns.internal.webservices.jaxws_databinding.ExistingAnnotationsType.MERGE;
    61 /**
    62  * Metadata Reader able to read from either class annotations or external metadata files or combine both,
    63  * depending on configuration provided in xml file itself.
    64  *
    65  * @author shih-chang.chen@oracle.com, miroslav.kos@oracle.com
    66  */
    67 public class ExternalMetadataReader extends ReflectAnnotationReader {
    69     private static final String NAMESPACE_WEBLOGIC_WSEE_DATABINDING = "http://xmlns.oracle.com/weblogic/weblogic-wsee-databinding";
    70     private static final String NAMESPACE_JAXWS_RI_EXTERNAL_METADATA = "http://xmlns.oracle.com/webservices/jaxws-databinding";
    72     /**
    73      * map of readers for defined java types
    74      */
    75     private Map<String, JavaWsdlMappingType> readers = new HashMap<String, JavaWsdlMappingType>();
    77     public ExternalMetadataReader(Collection<File> files, Collection<String> resourcePaths, ClassLoader classLoader,
    78                                   boolean xsdValidation, boolean disableXmlSecurity) {
    80         if (files != null) {
    81             for (File file : files) {
    82                 try {
    83                     String namespace = Util.documentRootNamespace(newSource(file), disableXmlSecurity);
    84                     JavaWsdlMappingType externalMapping = parseMetadata(xsdValidation, newSource(file), namespace, disableXmlSecurity);
    85                     readers.put(externalMapping.getJavaTypeName(), externalMapping);
    86                 } catch (Exception e) {
    87                     throw new RuntimeModelerException("runtime.modeler.external.metadata.unable.to.read", file.getAbsolutePath());
    88                 }
    89             }
    90         }
    92         if (resourcePaths != null) {
    93             for (String resourcePath : resourcePaths) {
    94                 try {
    95                     String namespace = Util.documentRootNamespace(newSource(resourcePath, classLoader), disableXmlSecurity);
    96                     JavaWsdlMappingType externalMapping = parseMetadata(xsdValidation, newSource(resourcePath, classLoader), namespace, disableXmlSecurity);
    97                     readers.put(externalMapping.getJavaTypeName(), externalMapping);
    98                 } catch (Exception e) {
    99                     throw new RuntimeModelerException("runtime.modeler.external.metadata.unable.to.read", resourcePath);
   100                 }
   101             }
   102         }
   103     }
   105     private StreamSource newSource(String resourcePath, ClassLoader classLoader) {
   106         InputStream is = classLoader.getResourceAsStream(resourcePath);
   107         return new StreamSource(is);
   108     }
   110     private JavaWsdlMappingType parseMetadata(boolean xsdValidation, StreamSource source, String namespace, boolean disableXmlSecurity) throws JAXBException, IOException, TransformerException {
   111         if (NAMESPACE_WEBLOGIC_WSEE_DATABINDING.equals(namespace)) {
   112             return Util.transformAndRead(source, disableXmlSecurity);
   113         } if (NAMESPACE_JAXWS_RI_EXTERNAL_METADATA.equals(namespace)) {
   114             return Util.read(source, xsdValidation, disableXmlSecurity);
   115         } else {
   116             throw new RuntimeModelerException("runtime.modeler.external.metadata.unsupported.schema", namespace, Arrays.asList(NAMESPACE_WEBLOGIC_WSEE_DATABINDING, NAMESPACE_JAXWS_RI_EXTERNAL_METADATA).toString());
   117         }
   118     }
   120     private StreamSource newSource(File file) {
   121         try {
   122             return new StreamSource(new FileInputStream(file));
   123         } catch (FileNotFoundException e) {
   124             throw new RuntimeModelerException("runtime.modeler.external.metadata.unable.to.read", file.getAbsolutePath());
   125         }
   126     }
   128     public <A extends Annotation> A getAnnotation(Class<A> annType, Class<?> cls) {
   129         JavaWsdlMappingType r = reader(cls);
   130         return r == null ? super.getAnnotation(annType, cls) : Util.annotation(r, annType);
   131     }
   133     private JavaWsdlMappingType reader(Class<?> cls) {
   134         return readers.get(cls.getName());
   135     }
   137     Annotation[] getAnnotations(List<Object> objects) {
   138         ArrayList<Annotation> list = new ArrayList<Annotation>();
   139         for (Object a : objects) {
   140             if (Annotation.class.isInstance(a)) {
   141                 list.add(Annotation.class.cast(a));
   142             }
   143         }
   144         return list.toArray(new Annotation[list.size()]);
   145     }
   147     public Annotation[] getAnnotations(final Class<?> c) {
   149         Merger<Annotation[]> merger = new Merger<Annotation[]>(reader(c)) {
   150             Annotation[] reflection() {
   151                 return ExternalMetadataReader.super.getAnnotations(c);
   152             }
   154             Annotation[] external() {
   155                 return getAnnotations(reader.getClassAnnotation());
   156             }
   157         };
   158         return merger.merge();
   159     }
   161     public Annotation[] getAnnotations(final Method m) {
   162         Merger<Annotation[]> merger = new Merger<Annotation[]>(reader(m.getDeclaringClass())) {
   163             Annotation[] reflection() {
   164                 return ExternalMetadataReader.super.getAnnotations(m);
   165             }
   167             Annotation[] external() {
   168                 JavaMethod jm = getJavaMethod(m, reader);
   169                 return (jm == null) ? new Annotation[0] : getAnnotations(jm.getMethodAnnotation());
   170             }
   171         };
   172         return merger.merge();
   173     }
   175     @SuppressWarnings("unchecked")
   176     public <A extends Annotation> A getAnnotation(final Class<A> annType, final Method m) {
   177         Merger<Annotation> merger = new Merger<Annotation>(reader(m.getDeclaringClass())) {
   178             Annotation reflection() {
   179                 return ExternalMetadataReader.super.getAnnotation(annType, m);
   180             }
   182             Annotation external() {
   183                 JavaMethod jm = getJavaMethod(m, reader);
   184                 return Util.annotation(jm, annType);
   185             }
   186         };
   187         return (A) merger.merge();
   188     }
   190     public Annotation[][] getParameterAnnotations(final Method m) {
   191         Merger<Annotation[][]> merger = new Merger<Annotation[][]>(reader(m.getDeclaringClass())) {
   192             Annotation[][] reflection() {
   193                 return ExternalMetadataReader.super.getParameterAnnotations(m);
   194             }
   196             Annotation[][] external() {
   197                 JavaMethod jm = getJavaMethod(m, reader);
   198                 Annotation[][] a = m.getParameterAnnotations();
   199                 for (int i = 0; i < m.getParameterTypes().length; i++) {
   200                     if (jm == null) continue;
   201                     JavaParam jp = jm.getJavaParams().getJavaParam().get(i);
   202                     a[i] = getAnnotations(jp.getParamAnnotation());
   203                 }
   204                 return a;
   205             }
   206         };
   207         return merger.merge();
   208     }
   210     public void getProperties(final Map<String, Object> prop, final Class<?> cls) {
   212         JavaWsdlMappingType r = reader(cls);
   214         // no external reader or it requires annotations merging ...
   215         if (r == null || MERGE.equals(r.getExistingAnnotations())) {
   216             super.getProperties(prop, cls);
   217         }
   219     }
   221     public void getProperties(final Map<String, Object> prop, final Method m) {
   223         JavaWsdlMappingType r = reader(m.getDeclaringClass());
   225         // no external reader or it requires annotations merging ...
   226         if (r == null || MERGE.equals(r.getExistingAnnotations())) {
   227             super.getProperties(prop, m);
   228         }
   230         if (r != null) {
   231             JavaMethod jm = getJavaMethod(m, r);
   232             Element[] e = Util.annotation(jm);
   233             prop.put("eclipselink-oxm-xml.xml-element", findXmlElement(e));
   234         }
   236     }
   238     public void getProperties(final Map<String, Object> prop, final Method m, int pos) {
   240         JavaWsdlMappingType r = reader(m.getDeclaringClass());
   242         // no external reader or it requires annotations merging ...
   243         if (r == null || MERGE.equals(r.getExistingAnnotations())) {
   244             super.getProperties(prop, m, pos);
   245         }
   247         if (r != null) {
   248             JavaMethod jm = getJavaMethod(m, r);
   249             if (jm == null) return;
   250             JavaParam jp = jm.getJavaParams().getJavaParam().get(pos);
   251             Element[] e = Util.annotation(jp);
   252             prop.put("eclipselink-oxm-xml.xml-element", findXmlElement(e));
   253         }
   254     }
   256     JavaMethod getJavaMethod(Method method, JavaWsdlMappingType r) {
   258         JavaWsdlMappingType.JavaMethods javaMethods = r.getJavaMethods();
   259         if (javaMethods == null) {
   260             return null;
   261         }
   263         List<JavaMethod> sameName = new ArrayList<JavaMethod>();
   264         for (JavaMethod jm : javaMethods.getJavaMethod()) {
   265             if (method.getName().equals(jm.getName())) {
   266                 sameName.add(jm);
   267             }
   268         }
   270         if (sameName.isEmpty()) {
   271             return null;
   272         } else {
   273             if (sameName.size() == 1) {
   274                 return sameName.get(0);
   275             } else {
   276                 Class<?>[] argCls = method.getParameterTypes();
   277                 for (JavaMethod jm : sameName) {
   278                     JavaMethod.JavaParams params = jm.getJavaParams();
   279                     if (params != null && params.getJavaParam() != null && params.getJavaParam().size() == argCls.length) {
   280                         int count = 0;
   281                         for (int i = 0; i < argCls.length; i++) {
   282                             JavaParam jp = params.getJavaParam().get(i);
   283                             if (argCls[i].getName().equals(jp.getJavaType())) {
   284                                 count++;
   285                             }
   286                         }
   287                         if (count == argCls.length) {
   288                             return jm;
   289                         }
   290                     }
   291                 }
   292             }
   293         }
   294         return null;
   295     }
   297     Element findXmlElement(Element[] xa) {
   298         if (xa == null) return null;
   299         for (Element e : xa) {
   300             if (e.getLocalName().equals("java-type")) return e;
   301             if (e.getLocalName().equals("xml-element")) return e;
   302         }
   303         return null;
   304     }
   306     /**
   307      * Helper class to merge two different arrays of annotation objects. It merges annotations based on attribute
   308      * <code>existing-annotations</code> in external customization file.
   309      * <p/>
   310      * We suppose that in the result array there wouldn't be two annotations of same type:
   311      * annotation.annotationType().getName(); if there are found such annotations the one from reflection is
   312      * considered overriden and is thrown away.
   313      * <p/>
   314      * The helper can work either with one and two dimensional array, but it can be used for two single Annotation
   315      * objects;
   316      */
   317     static abstract class Merger<T> {
   319         JavaWsdlMappingType reader;
   321         Merger(JavaWsdlMappingType r) {
   322             this.reader = r;
   323         }
   325         abstract T reflection();
   327         abstract T external();
   329         @SuppressWarnings("unchecked")
   330         T merge() {
   331             T reflection = reflection();
   332             if (reader == null) {
   333                 return reflection;
   334             }
   336             T external = external();
   337             if (!MERGE.equals(reader.getExistingAnnotations())) {
   338                 return external;
   339             }
   341             if (reflection instanceof Annotation) {
   342                 return (T) doMerge((Annotation) reflection, (Annotation) external);
   343             } else if (reflection instanceof Annotation[][]) {
   344                 return (T) doMerge((Annotation[][]) reflection, (Annotation[][]) external);
   345             } else {
   346                 return (T) doMerge((Annotation[]) reflection, (Annotation[]) external);
   347             }
   348         }
   350         private Annotation doMerge(Annotation reflection, Annotation external) {
   351             return external != null ? external : reflection;
   352         }
   354         private Annotation[][] doMerge(Annotation[][] reflection, Annotation[][] external) {
   355             for (int i = 0; i < reflection.length; i++) {
   356                 reflection[i] = doMerge(reflection[i], external.length > i ? external[i] : null);
   357             }
   358             return reflection;
   359         }
   361         private Annotation[] doMerge(Annotation[] annotations, Annotation[] externalAnnotations) {
   362             HashMap<String, Annotation> mergeMap = new HashMap<String, Annotation>();
   363             if (annotations != null) {
   364                 for (Annotation reflectionAnnotation : annotations) {
   365                     mergeMap.put(reflectionAnnotation.annotationType().getName(), reflectionAnnotation);
   366                 }
   367             }
   369             // overriding happens here, based on annotationType().getName() ...
   370             if (externalAnnotations != null) {
   371                 for (Annotation externalAnnotation : externalAnnotations) {
   372                     mergeMap.put(externalAnnotation.annotationType().getName(), externalAnnotation);
   373                 }
   374             }
   375             Collection<Annotation> values = mergeMap.values();
   376             int size = values.size();
   377             return size == 0 ? null : values.toArray(new Annotation[size]);
   378         }
   380     }
   382     static class Util {
   384         //private static final String DATABINDING_XSD = "com/sun/xml/internal/ws/model/jaxws-databinding.xsd";
   385         private static final String DATABINDING_XSD = "jaxws-databinding.xsd";
   386         //private static final String TRANSLATE_NAMESPACES_XSL = "/com/sun/xml/internal/ws/model/jaxws-databinding-translate-namespaces.xml";
   387         private static final String TRANSLATE_NAMESPACES_XSL = "jaxws-databinding-translate-namespaces.xml";
   389         static Schema schema;
   390         static JAXBContext jaxbContext;
   392         static {
   393             SchemaFactory sf = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
   394             try {
   395                 URL xsdUrl = getResource();
   396                 if (xsdUrl != null) {
   397                     schema = sf.newSchema(xsdUrl);
   398                 }
   399             } catch (SAXException e1) {
   400                 //      e1.printStackTrace();
   401             }
   403             jaxbContext = createJaxbContext(false);
   404         }
   406         private static URL getResource() {
   407             ClassLoader classLoader = Util.class.getClassLoader();
   408             return classLoader != null ? classLoader.getResource(DATABINDING_XSD) : ClassLoader.getSystemResource(DATABINDING_XSD);
   409         }
   411         private static JAXBContext createJaxbContext(boolean disableXmlSecurity) {
   412             Class[] cls = {ObjectFactory.class};
   413             try {
   414                 if (disableXmlSecurity) {
   415                     Map<String, Object> properties = new HashMap<String, Object>();
   416                     properties.put(JAXBRIContext.DISABLE_XML_SECURITY, disableXmlSecurity);
   417                     return JAXBContext.newInstance(cls, properties);
   418                 } else {
   419                     return JAXBContext.newInstance(cls);
   420                 }
   421             } catch (JAXBException e) {
   422                 e.printStackTrace();
   423                 return null;
   424             }
   425         }
   427         @SuppressWarnings("unchecked")
   428         public static JavaWsdlMappingType read(Source src, boolean xsdValidation, boolean disableXmlSecurity) throws IOException, JAXBException {
   429             JAXBContext ctx = jaxbContext(disableXmlSecurity);
   430             try {
   431                 Unmarshaller um = ctx.createUnmarshaller();
   432                 if (xsdValidation) {
   433                     if (schema == null) {
   434                         //TODO 0 warning for schema == null
   435                     }
   436                     um.setSchema(schema);
   437                 }
   438                 Object o = um.unmarshal(src);
   439                 return getJavaWsdlMapping(o);
   440             } catch (JAXBException e) {
   441                 // throw new
   442                 // WebServiceException(WsDatabindingMessages.mappingFileCannotRead
   443                 // (src.getSystemId()), e);
   444                 URL url = new URL(src.getSystemId());
   445                 Source s = new StreamSource(url.openStream());
   446                 Unmarshaller um = ctx.createUnmarshaller();
   447                 if (xsdValidation) {
   448                     if (schema == null) {
   449                         //TODO 0 warning for schema == null
   450                     }
   451                     um.setSchema(schema);
   452                 }
   453                 Object o = um.unmarshal(s);
   454                 return getJavaWsdlMapping(o);
   455             }
   456         }
   458         private static JAXBContext jaxbContext(boolean disableXmlSecurity) {
   459             // as it is supposed to have security enabled in most cases, we create and don't cache
   460             // "insecure" JAXBContext - these should be corner cases
   461             return disableXmlSecurity ? createJaxbContext(true) : jaxbContext;
   462         }
   464         public static JavaWsdlMappingType transformAndRead(Source src, boolean disableXmlSecurity) throws TransformerException, JAXBException {
   465             Source xsl = new StreamSource(Util.class.getResourceAsStream(TRANSLATE_NAMESPACES_XSL));
   466             JAXBResult result = new JAXBResult(jaxbContext(disableXmlSecurity));
   467             TransformerFactory tf = XmlUtil.newTransformerFactory(!disableXmlSecurity);
   468             Transformer transformer = tf.newTemplates(xsl).newTransformer();
   469             transformer.transform(src, result);
   470             return getJavaWsdlMapping(result.getResult());
   471         }
   474         static JavaWsdlMappingType getJavaWsdlMapping(Object o) {
   475             Object val = (o instanceof JAXBElement) ? ((JAXBElement) o).getValue() : o;
   476             if (val instanceof JavaWsdlMappingType) return (JavaWsdlMappingType) val;
   477             //    else if (val instanceof JavaWsdlMappings)
   478             //      for (JavaWsdlMappingType m: ((JavaWsdlMappings) val).getJavaWsdlMapping())
   479             //        if (seiName.equals(m.javaTypeName)) return m;
   480             return null;
   481         }
   483         static <T> T findInstanceOf(Class<T> type, List<Object> objects) {
   484             for (Object o : objects) {
   485                 if (type.isInstance(o)) {
   486                     return type.cast(o);
   487                 }
   488             }
   489             return null;
   490         }
   492         static public <T> T annotation(JavaWsdlMappingType jwse, Class<T> anntype) {
   493             if (jwse == null || jwse.getClassAnnotation() == null) {
   494                 return null;
   495             }
   496             return findInstanceOf(anntype, jwse.getClassAnnotation());
   497         }
   499         static public <T> T annotation(JavaMethod jm, Class<T> anntype) {
   500             if (jm == null || jm.getMethodAnnotation() == null) {
   501                 return null;
   502             }
   503             return findInstanceOf(anntype, jm.getMethodAnnotation());
   504         }
   506         static public <T> T annotation(JavaParam jp, Class<T> anntype) {
   507             if (jp == null || jp.getParamAnnotation() == null) {
   508                 return null;
   509             }
   510             return findInstanceOf(anntype, jp.getParamAnnotation());
   511         }
   513         static public Element[] annotation(JavaMethod jm) {
   514             if (jm == null || jm.getMethodAnnotation() == null) {
   515                 return null;
   516             }
   517             return findElements(jm.getMethodAnnotation());
   518         }
   520         static public Element[] annotation(JavaParam jp) {
   521             if (jp == null || jp.getParamAnnotation() == null) {
   522                 return null;
   523             }
   524             return findElements(jp.getParamAnnotation());
   525         }
   527         private static Element[] findElements(List<Object> objects) {
   528             List<Element> elems = new ArrayList<Element>();
   529             for (Object o : objects) {
   530                 if (o instanceof Element) {
   531                     elems.add((Element) o);
   532                 }
   533             }
   534             return elems.toArray(new Element[elems.size()]);
   535         }
   537         static String documentRootNamespace(Source src, boolean disableXmlSecurity) throws XMLStreamException {
   538             XMLInputFactory factory;
   539             factory = XmlUtil.newXMLInputFactory(!disableXmlSecurity);
   540             XMLStreamReader streamReader = factory.createXMLStreamReader(src);
   541             XMLStreamReaderUtil.nextElementContent(streamReader);
   542             String namespaceURI = streamReader.getName().getNamespaceURI();
   543             XMLStreamReaderUtil.close(streamReader);
   544             return namespaceURI;
   545         }
   546     }
   549 }

mercurial