src/share/jaxws_classes/com/sun/xml/internal/ws/model/WrapperBeanGenerator.java

Thu, 12 Oct 2017 19:44:07 +0800

author
aoqi
date
Thu, 12 Oct 2017 19:44:07 +0800
changeset 760
e530533619ec
parent 637
9c07ef4934dd
permissions
-rw-r--r--

merge

aoqi@0 1 /*
aoqi@0 2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
aoqi@0 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
aoqi@0 4 *
aoqi@0 5 * This code is free software; you can redistribute it and/or modify it
aoqi@0 6 * under the terms of the GNU General Public License version 2 only, as
aoqi@0 7 * published by the Free Software Foundation. Oracle designates this
aoqi@0 8 * particular file as subject to the "Classpath" exception as provided
aoqi@0 9 * by Oracle in the LICENSE file that accompanied this code.
aoqi@0 10 *
aoqi@0 11 * This code is distributed in the hope that it will be useful, but WITHOUT
aoqi@0 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
aoqi@0 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
aoqi@0 14 * version 2 for more details (a copy is included in the LICENSE file that
aoqi@0 15 * accompanied this code).
aoqi@0 16 *
aoqi@0 17 * You should have received a copy of the GNU General Public License version
aoqi@0 18 * 2 along with this work; if not, write to the Free Software Foundation,
aoqi@0 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
aoqi@0 20 *
aoqi@0 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
aoqi@0 22 * or visit www.oracle.com if you need additional information or have any
aoqi@0 23 * questions.
aoqi@0 24 */
aoqi@0 25
aoqi@0 26 package com.sun.xml.internal.ws.model;
aoqi@0 27
aoqi@0 28 import com.sun.xml.internal.ws.model.AbstractWrapperBeanGenerator.BeanMemberFactory;
aoqi@0 29 import com.sun.xml.internal.bind.v2.model.annotation.AnnotationReader;
aoqi@0 30 import com.sun.xml.internal.bind.v2.model.annotation.RuntimeInlineAnnotationReader;
aoqi@0 31 import com.sun.xml.internal.bind.v2.model.nav.Navigator;
aoqi@0 32 import com.sun.xml.internal.ws.org.objectweb.asm.*;
aoqi@0 33 import static com.sun.xml.internal.ws.org.objectweb.asm.Opcodes.*;
aoqi@0 34 import com.sun.xml.internal.ws.org.objectweb.asm.Type;
aoqi@0 35
aoqi@0 36 import javax.xml.bind.annotation.XmlAttachmentRef;
aoqi@0 37 import javax.xml.bind.annotation.XmlElement;
aoqi@0 38 import javax.xml.bind.annotation.XmlList;
aoqi@0 39 import javax.xml.bind.annotation.XmlMimeType;
aoqi@0 40 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
aoqi@0 41 import javax.xml.namespace.QName;
aoqi@0 42 import javax.xml.ws.Holder;
aoqi@0 43 import javax.xml.ws.WebServiceException;
aoqi@0 44 import java.lang.annotation.Annotation;
aoqi@0 45 import java.lang.reflect.*;
aoqi@0 46 import java.util.*;
aoqi@0 47 import java.util.logging.Level;
aoqi@0 48 import java.util.logging.Logger;
aoqi@0 49
aoqi@0 50 /**
aoqi@0 51 * Runtime Wrapper and exception bean generator implementation.
aoqi@0 52 * It uses ASM to generate request, response and exception beans.
aoqi@0 53 *
aoqi@0 54 * @author Jitendra Kotamraju
aoqi@0 55 */
aoqi@0 56 public class WrapperBeanGenerator {
aoqi@0 57
aoqi@0 58 private static final Logger LOGGER = Logger.getLogger(WrapperBeanGenerator.class.getName());
aoqi@0 59
aoqi@0 60 private static final FieldFactory FIELD_FACTORY = new FieldFactory();
aoqi@0 61
aoqi@0 62 private static final AbstractWrapperBeanGenerator RUNTIME_GENERATOR =
aoqi@0 63 new RuntimeWrapperBeanGenerator(new RuntimeInlineAnnotationReader(),
aoqi@0 64 (Navigator<java.lang.reflect.Type, Class, ?, Method>) Utils.REFLECTION_NAVIGATOR, FIELD_FACTORY);
aoqi@0 65
aoqi@0 66 private static final class RuntimeWrapperBeanGenerator extends AbstractWrapperBeanGenerator<java.lang.reflect.Type, Class, java.lang.reflect.Method, Field> {
aoqi@0 67
aoqi@0 68 protected RuntimeWrapperBeanGenerator(AnnotationReader<java.lang.reflect.Type, Class, ?, Method> annReader, Navigator<java.lang.reflect.Type, Class, ?, Method> nav, BeanMemberFactory<java.lang.reflect.Type, Field> beanMemberFactory) {
aoqi@0 69 super(annReader, nav, beanMemberFactory);
aoqi@0 70 }
aoqi@0 71
aoqi@0 72 @Override
aoqi@0 73 protected java.lang.reflect.Type getSafeType(java.lang.reflect.Type type) {
aoqi@0 74 return type;
aoqi@0 75 }
aoqi@0 76
aoqi@0 77 @Override
aoqi@0 78 protected java.lang.reflect.Type getHolderValueType(java.lang.reflect.Type paramType) {
aoqi@0 79 if (paramType instanceof ParameterizedType) {
aoqi@0 80 ParameterizedType p = (ParameterizedType)paramType;
aoqi@0 81 if (p.getRawType().equals(Holder.class)) {
aoqi@0 82 return p.getActualTypeArguments()[0];
aoqi@0 83 }
aoqi@0 84 }
aoqi@0 85 return null;
aoqi@0 86 }
aoqi@0 87
aoqi@0 88 @Override
aoqi@0 89 protected boolean isVoidType(java.lang.reflect.Type type) {
aoqi@0 90 return type == Void.TYPE;
aoqi@0 91 }
aoqi@0 92
aoqi@0 93 }
aoqi@0 94
aoqi@0 95 private static final class FieldFactory implements BeanMemberFactory<java.lang.reflect.Type, Field> {
aoqi@0 96 @Override
aoqi@0 97 public Field createWrapperBeanMember(java.lang.reflect.Type paramType,
aoqi@0 98 String paramName, List<Annotation> jaxb) {
aoqi@0 99 return new Field(paramName, paramType, getASMType(paramType), jaxb);
aoqi@0 100 }
aoqi@0 101 }
aoqi@0 102
aoqi@0 103 // Creates class's bytes
aoqi@0 104 private static byte[] createBeanImage(String className,
aoqi@0 105 String rootName, String rootNS,
aoqi@0 106 String typeName, String typeNS,
aoqi@0 107 Collection<Field> fields) throws Exception {
aoqi@0 108
aoqi@0 109 ClassWriter cw = new ClassWriter(0);
aoqi@0 110 //org.objectweb.asm.util.TraceClassVisitor cw = new org.objectweb.asm.util.TraceClassVisitor(actual, new java.io.PrintWriter(System.out));
aoqi@0 111
aoqi@0 112 cw.visit(V1_5, ACC_PUBLIC + ACC_SUPER, replaceDotWithSlash(className), null, "java/lang/Object", null);
aoqi@0 113
aoqi@0 114 AnnotationVisitor root = cw.visitAnnotation("Ljavax/xml/bind/annotation/XmlRootElement;", true);
aoqi@0 115 root.visit("name", rootName);
aoqi@0 116 root.visit("namespace", rootNS);
aoqi@0 117 root.visitEnd();
aoqi@0 118
aoqi@0 119 AnnotationVisitor type = cw.visitAnnotation("Ljavax/xml/bind/annotation/XmlType;", true);
aoqi@0 120 type.visit("name", typeName);
aoqi@0 121 type.visit("namespace", typeNS);
aoqi@0 122 if (fields.size() > 1) {
aoqi@0 123 AnnotationVisitor propVisitor = type.visitArray("propOrder");
aoqi@0 124 for(Field field : fields) {
aoqi@0 125 propVisitor.visit("propOrder", field.fieldName);
aoqi@0 126 }
aoqi@0 127 propVisitor.visitEnd();
aoqi@0 128 }
aoqi@0 129 type.visitEnd();
aoqi@0 130
aoqi@0 131 for(Field field : fields) {
aoqi@0 132 FieldVisitor fv = cw.visitField(ACC_PUBLIC, field.fieldName, field.asmType.getDescriptor(), field.getSignature(), null);
aoqi@0 133
aoqi@0 134 for(Annotation ann : field.jaxbAnnotations) {
aoqi@0 135 if (ann instanceof XmlMimeType) {
aoqi@0 136 AnnotationVisitor mime = fv.visitAnnotation("Ljavax/xml/bind/annotation/XmlMimeType;", true);
aoqi@0 137 mime.visit("value", ((XmlMimeType)ann).value());
aoqi@0 138 mime.visitEnd();
aoqi@0 139 } else if (ann instanceof XmlJavaTypeAdapter) {
aoqi@0 140 AnnotationVisitor ada = fv.visitAnnotation("Ljavax/xml/bind/annotation/adapters/XmlJavaTypeAdapter;", true);
aoqi@0 141 ada.visit("value", getASMType(((XmlJavaTypeAdapter)ann).value()));
aoqi@0 142 // XmlJavaTypeAdapter.type() is for package only. No need to copy.
aoqi@0 143 // ada.visit("type", ((XmlJavaTypeAdapter)ann).type());
aoqi@0 144 ada.visitEnd();
aoqi@0 145 } else if (ann instanceof XmlAttachmentRef) {
aoqi@0 146 AnnotationVisitor att = fv.visitAnnotation("Ljavax/xml/bind/annotation/XmlAttachmentRef;", true);
aoqi@0 147 att.visitEnd();
aoqi@0 148 } else if (ann instanceof XmlList) {
aoqi@0 149 AnnotationVisitor list = fv.visitAnnotation("Ljavax/xml/bind/annotation/XmlList;", true);
aoqi@0 150 list.visitEnd();
aoqi@0 151 } else if (ann instanceof XmlElement) {
aoqi@0 152 AnnotationVisitor elem = fv.visitAnnotation("Ljavax/xml/bind/annotation/XmlElement;", true);
aoqi@0 153 XmlElement xmlElem = (XmlElement)ann;
aoqi@0 154 elem.visit("name", xmlElem.name());
aoqi@0 155 elem.visit("namespace", xmlElem.namespace());
aoqi@0 156 if (xmlElem.nillable()) {
aoqi@0 157 elem.visit("nillable", true);
aoqi@0 158 }
aoqi@0 159 if (xmlElem.required()) {
aoqi@0 160 elem.visit("required", true);
aoqi@0 161 }
aoqi@0 162 elem.visitEnd();
aoqi@0 163 } else {
aoqi@0 164 throw new WebServiceException("Unknown JAXB annotation " + ann);
aoqi@0 165 }
aoqi@0 166 }
aoqi@0 167
aoqi@0 168 fv.visitEnd();
aoqi@0 169 }
aoqi@0 170
aoqi@0 171 MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
aoqi@0 172 mv.visitCode();
aoqi@0 173 mv.visitVarInsn(ALOAD, 0);
aoqi@0 174 mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
aoqi@0 175 mv.visitInsn(RETURN);
aoqi@0 176 mv.visitMaxs(1, 1);
aoqi@0 177 mv.visitEnd();
aoqi@0 178
aoqi@0 179 cw.visitEnd();
aoqi@0 180
aoqi@0 181 if (LOGGER.isLoggable(Level.FINE)) {
aoqi@0 182 // Class's @XmlRootElement
aoqi@0 183 StringBuilder sb = new StringBuilder();
aoqi@0 184 sb.append("\n");
aoqi@0 185 sb.append("@XmlRootElement(name=").append(rootName)
aoqi@0 186 .append(", namespace=").append(rootNS).append(")");
aoqi@0 187
aoqi@0 188 // Class's @XmlType
aoqi@0 189 sb.append("\n");
aoqi@0 190 sb.append("@XmlType(name=").append(typeName)
aoqi@0 191 .append(", namespace=").append(typeNS);
aoqi@0 192 if (fields.size() > 1) {
aoqi@0 193 sb.append(", propOrder={");
aoqi@0 194 for(Field field : fields) {
aoqi@0 195 sb.append(" ");
aoqi@0 196 sb.append(field.fieldName);
aoqi@0 197 }
aoqi@0 198 sb.append(" }");
aoqi@0 199 }
aoqi@0 200 sb.append(")");
aoqi@0 201
aoqi@0 202 // class declaration
aoqi@0 203 sb.append("\n");
aoqi@0 204 sb.append("public class ").append(className).append(" {");
aoqi@0 205
aoqi@0 206 // fields declaration
aoqi@0 207 for(Field field : fields) {
aoqi@0 208 sb.append("\n");
aoqi@0 209
aoqi@0 210 // Field's other JAXB annotations
aoqi@0 211 for(Annotation ann : field.jaxbAnnotations) {
aoqi@0 212 sb.append("\n ");
aoqi@0 213
aoqi@0 214 if (ann instanceof XmlMimeType) {
aoqi@0 215 sb.append("@XmlMimeType(value=").append(((XmlMimeType)ann).value()).append(")");
aoqi@0 216 } else if (ann instanceof XmlJavaTypeAdapter) {
aoqi@0 217 sb.append("@XmlJavaTypeAdapter(value=").append(getASMType(((XmlJavaTypeAdapter)ann).value())).append(")");
aoqi@0 218 } else if (ann instanceof XmlAttachmentRef) {
aoqi@0 219 sb.append("@XmlAttachmentRef");
aoqi@0 220 } else if (ann instanceof XmlList) {
aoqi@0 221 sb.append("@XmlList");
aoqi@0 222 } else if (ann instanceof XmlElement) {
aoqi@0 223 XmlElement xmlElem = (XmlElement)ann;
aoqi@0 224 sb.append("\n ");
aoqi@0 225 sb.append("@XmlElement(name=").append(xmlElem.name())
aoqi@0 226 .append(", namespace=").append(xmlElem.namespace());
aoqi@0 227 if (xmlElem.nillable()) {
aoqi@0 228 sb.append(", nillable=true");
aoqi@0 229 }
aoqi@0 230 if (xmlElem.required()) {
aoqi@0 231 sb.append(", required=true");
aoqi@0 232 }
aoqi@0 233 sb.append(")");
aoqi@0 234 } else {
aoqi@0 235 throw new WebServiceException("Unknown JAXB annotation " + ann);
aoqi@0 236 }
aoqi@0 237 }
aoqi@0 238
aoqi@0 239 // Field declaration
aoqi@0 240 sb.append("\n ");
aoqi@0 241 sb.append("public ");
aoqi@0 242 if (field.getSignature() == null) {
aoqi@0 243 sb.append(field.asmType.getDescriptor());
aoqi@0 244 } else {
aoqi@0 245 sb.append(field.getSignature());
aoqi@0 246 }
aoqi@0 247 sb.append(" ");
aoqi@0 248 sb.append(field.fieldName);
aoqi@0 249 }
aoqi@0 250
aoqi@0 251 sb.append("\n\n}");
aoqi@0 252 LOGGER.fine(sb.toString());
aoqi@0 253 }
aoqi@0 254
aoqi@0 255 return cw.toByteArray();
aoqi@0 256 }
aoqi@0 257
aoqi@0 258 private static String replaceDotWithSlash(String name) {
aoqi@0 259 return name.replace('.', '/');
aoqi@0 260 }
aoqi@0 261
aoqi@0 262 static Class createRequestWrapperBean(String className, Method method, QName reqElemName, ClassLoader cl) {
aoqi@0 263
aoqi@0 264 if (LOGGER.isLoggable(Level.FINE)) {
aoqi@0 265 LOGGER.log(Level.FINE, "Request Wrapper Class : {0}", className);
aoqi@0 266 }
aoqi@0 267
aoqi@0 268 List<Field> requestMembers = RUNTIME_GENERATOR.collectRequestBeanMembers(
aoqi@0 269 method);
aoqi@0 270
aoqi@0 271 byte[] image;
aoqi@0 272 try {
aoqi@0 273 image = createBeanImage(className, reqElemName.getLocalPart(), reqElemName.getNamespaceURI(),
aoqi@0 274 reqElemName.getLocalPart(), reqElemName.getNamespaceURI(),
aoqi@0 275 requestMembers);
aoqi@0 276 } catch(Exception e) {
aoqi@0 277 throw new WebServiceException(e);
aoqi@0 278 }
aoqi@0 279 // write(image, className);
aoqi@0 280 return Injector.inject(cl, className, image);
aoqi@0 281 }
aoqi@0 282
aoqi@0 283 static Class createResponseWrapperBean(String className, Method method, QName resElemName, ClassLoader cl) {
aoqi@0 284
aoqi@0 285 if (LOGGER.isLoggable(Level.FINE)) {
aoqi@0 286 LOGGER.log(Level.FINE, "Response Wrapper Class : {0}", className);
aoqi@0 287 }
aoqi@0 288
aoqi@0 289 List<Field> responseMembers = RUNTIME_GENERATOR.collectResponseBeanMembers(method);
aoqi@0 290
aoqi@0 291 byte[] image;
aoqi@0 292 try {
aoqi@0 293 image = createBeanImage(className, resElemName.getLocalPart(), resElemName.getNamespaceURI(),
aoqi@0 294 resElemName.getLocalPart(), resElemName.getNamespaceURI(),
aoqi@0 295 responseMembers);
aoqi@0 296 } catch(Exception e) {
aoqi@0 297 throw new WebServiceException(e);
aoqi@0 298 }
aoqi@0 299 // write(image, className);
aoqi@0 300
aoqi@0 301 return Injector.inject(cl, className, image);
aoqi@0 302 }
aoqi@0 303
aoqi@0 304
aoqi@0 305 private static Type getASMType(java.lang.reflect.Type t) {
aoqi@0 306 assert t!=null;
aoqi@0 307
aoqi@0 308 if (t instanceof Class) {
aoqi@0 309 return Type.getType((Class)t);
aoqi@0 310 }
aoqi@0 311
aoqi@0 312 if (t instanceof ParameterizedType) {
aoqi@0 313 ParameterizedType pt = (ParameterizedType)t;
aoqi@0 314 if (pt.getRawType() instanceof Class) {
aoqi@0 315 return Type.getType((Class)pt.getRawType());
aoqi@0 316 }
aoqi@0 317 }
aoqi@0 318 if (t instanceof GenericArrayType) {
aoqi@0 319 return Type.getType(FieldSignature.vms(t));
aoqi@0 320 }
aoqi@0 321
aoqi@0 322 if (t instanceof WildcardType) {
aoqi@0 323 return Type.getType(FieldSignature.vms(t));
aoqi@0 324 }
aoqi@0 325
aoqi@0 326 if (t instanceof TypeVariable) {
aoqi@0 327 TypeVariable tv = (TypeVariable)t;
aoqi@0 328 if (tv.getBounds()[0] instanceof Class) {
aoqi@0 329 return Type.getType((Class)tv.getBounds()[0]);
aoqi@0 330 }
aoqi@0 331 }
aoqi@0 332
aoqi@0 333 throw new IllegalArgumentException("Not creating ASM Type for type = "+t);
aoqi@0 334 }
aoqi@0 335
aoqi@0 336
aoqi@0 337 static Class createExceptionBean(String className, Class exception, String typeNS, String elemName, String elemNS, ClassLoader cl) {
aoqi@0 338 return createExceptionBean(className, exception, typeNS, elemName, elemNS, cl, true);
aoqi@0 339 }
aoqi@0 340
aoqi@0 341 static Class createExceptionBean(String className, Class exception, String typeNS, String elemName, String elemNS, ClassLoader cl, boolean decapitalizeExceptionBeanProperties) {
aoqi@0 342
aoqi@0 343 Collection<Field> fields = RUNTIME_GENERATOR.collectExceptionBeanMembers(exception, decapitalizeExceptionBeanProperties);
aoqi@0 344
aoqi@0 345 byte[] image;
aoqi@0 346 try {
aoqi@0 347 image = createBeanImage(className, elemName, elemNS,
aoqi@0 348 exception.getSimpleName(), typeNS,
aoqi@0 349 fields);
aoqi@0 350 } catch(Exception e) {
aoqi@0 351 throw new WebServiceException(e);
aoqi@0 352 }
aoqi@0 353
aoqi@0 354 return Injector.inject(cl, className, image);
aoqi@0 355 }
aoqi@0 356
aoqi@0 357 /**
aoqi@0 358 * Note: this class has a natural ordering that is inconsistent with equals.
aoqi@0 359 */
aoqi@0 360 private static class Field implements Comparable<Field> {
aoqi@0 361 private final java.lang.reflect.Type reflectType;
aoqi@0 362 private final Type asmType;
aoqi@0 363 private final String fieldName;
aoqi@0 364 private final List<Annotation> jaxbAnnotations;
aoqi@0 365
aoqi@0 366 Field(String paramName, java.lang.reflect.Type paramType, Type asmType,
aoqi@0 367 List<Annotation> jaxbAnnotations) {
aoqi@0 368 this.reflectType = paramType;
aoqi@0 369 this.asmType = asmType;
aoqi@0 370 this.fieldName = paramName;
aoqi@0 371 this.jaxbAnnotations = jaxbAnnotations;
aoqi@0 372 }
aoqi@0 373
aoqi@0 374 String getSignature() {
aoqi@0 375 if (reflectType instanceof Class) {
aoqi@0 376 return null;
aoqi@0 377 }
aoqi@0 378 if (reflectType instanceof TypeVariable) {
aoqi@0 379 return null;
aoqi@0 380 }
aoqi@0 381 return FieldSignature.vms(reflectType);
aoqi@0 382 }
aoqi@0 383
aoqi@0 384 @Override
aoqi@0 385 public int compareTo(Field o) {
aoqi@0 386 return fieldName.compareTo(o.fieldName);
aoqi@0 387 }
aoqi@0 388 }
aoqi@0 389
aoqi@0 390 static void write(byte[] b, String className) {
aoqi@0 391 className = className.substring(className.lastIndexOf(".")+1);
aoqi@0 392 try {
aoqi@0 393 java.io.FileOutputStream fo = new java.io.FileOutputStream(className + ".class");
aoqi@0 394 fo.write(b);
aoqi@0 395 fo.flush();
aoqi@0 396 fo.close();
aoqi@0 397 } catch (java.io.IOException e) {
aoqi@0 398 LOGGER.log(Level.INFO, "Error Writing class", e);
aoqi@0 399 }
aoqi@0 400 }
aoqi@0 401
aoqi@0 402 }

mercurial