src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/dtd/bindinfo/BIUserConversion.java

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

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

merge

     1 /*
     2  * Copyright (c) 1997, 2012, 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.tools.internal.xjc.reader.dtd.bindinfo;
    28 import java.io.IOException;
    29 import java.io.StringReader;
    30 import java.util.Map;
    32 import javax.xml.bind.annotation.adapters.XmlAdapter;
    33 import javax.xml.parsers.DocumentBuilderFactory;
    34 import javax.xml.parsers.ParserConfigurationException;
    36 import com.sun.codemodel.internal.JClass;
    37 import com.sun.codemodel.internal.JClassAlreadyExistsException;
    38 import com.sun.codemodel.internal.JCodeModel;
    39 import com.sun.codemodel.internal.JDefinedClass;
    40 import com.sun.codemodel.internal.JExpr;
    41 import com.sun.codemodel.internal.JExpression;
    42 import com.sun.codemodel.internal.JMethod;
    43 import com.sun.codemodel.internal.JMod;
    44 import com.sun.codemodel.internal.JPackage;
    45 import com.sun.codemodel.internal.JPrimitiveType;
    46 import com.sun.codemodel.internal.JType;
    47 import com.sun.codemodel.internal.JVar;
    48 import com.sun.tools.internal.xjc.model.CAdapter;
    49 import com.sun.tools.internal.xjc.model.CBuiltinLeafInfo;
    50 import com.sun.tools.internal.xjc.model.TypeUse;
    51 import com.sun.tools.internal.xjc.model.TypeUseFactory;
    53 import com.sun.xml.internal.bind.v2.util.XmlFactory;
    54 import org.w3c.dom.Element;
    55 import org.xml.sax.InputSource;
    56 import org.xml.sax.Locator;
    57 import org.xml.sax.SAXException;
    59 /**
    60  * <conversion> declaration in the binding file.
    61  * This declaration declares a conversion by user-specified methods.
    62  */
    63 public class BIUserConversion implements BIConversion
    64 {
    65     /**
    66      * Wraps a given <conversion> element in the binding file.
    67      */
    68     BIUserConversion( BindInfo bi, Element _e ) {
    69         this.owner = bi;
    70         this.e = _e;
    71     }
    73     private static void add( Map<String,BIConversion> m, BIConversion c ) {
    74         m.put( c.name(), c );
    75     }
    77     /** Adds all built-in conversions into the given map. */
    78     static void addBuiltinConversions( BindInfo bi, Map<String,BIConversion> m ) {
    79         add( m, new BIUserConversion( bi, parse("<conversion name='boolean' type='java.lang.Boolean' parse='getBoolean' />")));
    80         add( m, new BIUserConversion( bi, parse("<conversion name='byte' type='java.lang.Byte' parse='parseByte' />")));
    81         add( m, new BIUserConversion( bi, parse("<conversion name='short' type='java.lang.Short' parse='parseShort' />")));
    82         add( m, new BIUserConversion( bi, parse("<conversion name='int' type='java.lang.Integer' parse='parseInt' />")));
    83         add( m, new BIUserConversion( bi, parse("<conversion name='long' type='java.lang.Long' parse='parseLong' />")));
    84         add( m, new BIUserConversion( bi, parse("<conversion name='float' type='java.lang.Float' parse='parseFloat' />")));
    85         add( m, new BIUserConversion( bi, parse("<conversion name='double' type='java.lang.Double' parse='parseDouble' />")));
    86     }
    88     private static Element parse(String text) {
    89         try {
    90             //this is parsing well known schemas, do not configure secure processing - always true
    91             DocumentBuilderFactory dbf = XmlFactory.createDocumentBuilderFactory(false);
    92             InputSource is = new InputSource(new StringReader(text));
    93             return dbf.newDocumentBuilder().parse(is).getDocumentElement();
    94         } catch (SAXException x) {
    95             throw new Error(x);
    96         } catch (IOException x) {
    97             throw new Error(x);
    98         } catch (ParserConfigurationException x) {
    99             throw new Error(x);
   100         }
   101     }
   104     /** The owner {@link BindInfo} object to which this object belongs. */
   105     private final BindInfo owner;
   107     /** &lt;conversion> element which this object is wrapping. */
   108     private final Element e;
   112     /** Gets the location where this declaration is declared. */
   113     public Locator getSourceLocation() {
   114         return DOMLocator.getLocationInfo(e);
   115     }
   117     /** Gets the conversion name. */
   118     public String name() { return DOMUtil.getAttribute(e,"name"); }
   120     /** Gets a transducer for this conversion. */
   121     public TypeUse getTransducer() {
   123         String ws = DOMUtil.getAttribute(e,"whitespace");
   124         if(ws==null)    ws = "collapse";
   126         String type = DOMUtil.getAttribute(e,"type");
   127         if(type==null)  type=name();
   128         JType t=null;
   130         int idx = type.lastIndexOf('.');
   131         if(idx<0) {
   132             // no package name is specified.
   133             try {
   134                 t = JPrimitiveType.parse(owner.codeModel,type);
   135             } catch( IllegalArgumentException ex ) {
   136                 // otherwise treat it as a class name in the current package
   137                 type = owner.getTargetPackage().name()+'.'+type;
   138             }
   139         }
   140         if(t==null) {
   141             try {
   142                 // TODO: revisit this later
   143                 JDefinedClass cls = owner.codeModel._class(type);
   144                 cls.hide();
   145                 t = cls;
   146             } catch( JClassAlreadyExistsException ex ) {
   147                 t = ex.getExistingClass();
   148             }
   149         }
   151         String parse = DOMUtil.getAttribute(e,"parse");
   152         if(parse==null)  parse="new";
   154         String print = DOMUtil.getAttribute(e,"print");
   155         if(print==null)  print="toString";
   157         JDefinedClass adapter = generateAdapter(owner.codeModel, parse, print, t.boxify());
   159         // XmlJavaType customization always converts between string and an user-defined type.
   160         return TypeUseFactory.adapt(CBuiltinLeafInfo.STRING,new CAdapter(adapter));
   161     }
   163     // TODO: anyway to reuse this code between XML Schema compiler?
   164     private JDefinedClass generateAdapter(JCodeModel cm, String parseMethod, String printMethod, JClass inMemoryType) {
   165         JDefinedClass adapter = null;
   167         int id = 1;
   168         while(adapter==null) {
   169             try {
   170                 JPackage pkg = owner.getTargetPackage();
   171                 adapter = pkg._class("Adapter"+id);
   172             } catch (JClassAlreadyExistsException ex) {
   173                 // try another name in search for an unique name.
   174                 // this isn't too efficient, but we expect people to usually use
   175                 // a very small number of adapters.
   176                 id++;
   177             }
   178         }
   180         adapter._extends(cm.ref(XmlAdapter.class).narrow(String.class).narrow(inMemoryType));
   182         JMethod unmarshal = adapter.method(JMod.PUBLIC, inMemoryType, "unmarshal");
   183         JVar $value = unmarshal.param(String.class, "value");
   185         JExpression inv;
   187         if( parseMethod.equals("new") ) {
   188             // "new" indicates that the constructor of the target type
   189             // will do the unmarshalling.
   191             // RESULT: new <type>()
   192             inv = JExpr._new(inMemoryType).arg($value);
   193         } else {
   194             int idx = parseMethod.lastIndexOf('.');
   195             if(idx<0) {
   196                 // parseMethod specifies the static method of the target type
   197                 // which will do the unmarshalling.
   199                 // because of an error check at the constructor,
   200                 // we can safely assume that this cast works.
   201                 inv = inMemoryType.staticInvoke(parseMethod).arg($value);
   202             } else {
   203                 inv = JExpr.direct(parseMethod+"(value)");
   204             }
   205         }
   206         unmarshal.body()._return(inv);
   209         JMethod marshal = adapter.method(JMod.PUBLIC, String.class, "marshal");
   210         $value = marshal.param(inMemoryType,"value");
   212         int idx = printMethod.lastIndexOf('.');
   213         if(idx<0) {
   214             // printMethod specifies a method in the target type
   215             // which performs the serialization.
   217             // RESULT: <value>.<method>()
   218             inv = $value.invoke(printMethod);
   219         } else {
   220             // RESULT: <className>.<method>(<value>)
   221             inv = JExpr.direct(printMethod+"(value)");
   222         }
   223         marshal.body()._return(inv);
   225         return adapter;
   226     }
   227 }

mercurial