1 /*
2 * Copyright (c) 1997, 2014, 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
49 import com.sun.xml.internal.ws.spi.db.WrapperComposite;
50
51 import static com.sun.xml.internal.ws.binding.WebServiceFeatureList.getSoapVersion;
52 import static com.sun.xml.internal.ws.model.Utils.REFLECTION_NAVIGATOR;
53
54 import javax.jws.*;
55 import javax.jws.WebParam.Mode;
56 import javax.jws.soap.SOAPBinding;
57 import javax.jws.soap.SOAPBinding.Style;
58 import javax.xml.bind.annotation.XmlElement;
59 import javax.xml.bind.annotation.XmlSeeAlso;
60 import javax.xml.namespace.QName;
61 import javax.xml.ws.*;
62 import javax.xml.ws.soap.MTOM;
63 import javax.xml.ws.soap.MTOMFeature;
64 import java.lang.annotation.Annotation;
65 import java.lang.reflect.Method;
66 import java.lang.reflect.Modifier;
67 import java.lang.reflect.ParameterizedType;
68 import java.lang.reflect.Type;
69 import java.rmi.RemoteException;
70 import java.security.AccessController;
71 import java.util.HashSet;
72 import java.util.Map;
73 import java.util.Set;
74 import java.util.StringTokenizer;
75 import java.util.TreeMap;
76 import java.util.concurrent.Future;
77 import java.util.logging.Logger;
78
79 import static javax.jws.soap.SOAPBinding.ParameterStyle.WRAPPED;
80
81 /**
82 * Creates a runtime model of a SEI (portClass).
83 *
84 * @author WS Developement Team
85 */
86 public class RuntimeModeler {
87 private final WebServiceFeatureList features;
88 private BindingID bindingId;
89 private WSBinding wsBinding;
98 private final WSDLPort binding;
99 private QName serviceName;
100 private QName portName;
101 private Set<Class> classUsesWebMethod;
102 private DatabindingConfig config;
103 private MetadataReader metadataReader;
104 /**
105 *
106 */
107 public static final String PD_JAXWS_PACKAGE_PD = ".jaxws.";
108 /**
109 *
110 */
111 public static final String JAXWS_PACKAGE_PD = "jaxws.";
112 public static final String RESPONSE = "Response";
113 public static final String RETURN = "return";
114 public static final String BEAN = "Bean";
115 public static final String SERVICE = "Service";
116 public static final String PORT = "Port";
117 public static final Class HOLDER_CLASS = Holder.class;
118 public static final Class<RemoteException> REMOTE_EXCEPTION_CLASS = RemoteException.class;
119 public static final Class<RuntimeException> RUNTIME_EXCEPTION_CLASS = RuntimeException.class;
120 public static final Class<Exception> EXCEPTION_CLASS = Exception.class;
121 public static final String DecapitalizeExceptionBeanProperties = "com.sun.xml.internal.ws.api.model.DecapitalizeExceptionBeanProperties";
122 public static final String SuppressDocLitWrapperGeneration = "com.sun.xml.internal.ws.api.model.SuppressDocLitWrapperGeneration";
123 public static final String DocWrappeeNamespapceQualified = "com.sun.xml.internal.ws.api.model.DocWrappeeNamespapceQualified";
124
125 /*public RuntimeModeler(@NotNull Class portClass, @NotNull QName serviceName, @NotNull BindingID bindingId, @NotNull WebServiceFeature... features) {
126 this(portClass, serviceName, null, bindingId, features);
127 }*/
128
129 /**
130 *
131 * creates an instance of RunTimeModeler given a <code>sei</code> and <code>binding</code>
132 * @param portClass The SEI class to be modeled.
133 * @param serviceName The ServiceName to use instead of one calculated from the implementation class
134 * @param wsdlPort {@link com.sun.xml.internal.ws.api.model.wsdl.WSDLPort}
135 * @param features web service features
136 */
137 /*public RuntimeModeler(@NotNull Class portClass, @NotNull QName serviceName, @NotNull WSDLPortImpl wsdlPort, @NotNull WebServiceFeature... features){
138 this(portClass, serviceName, wsdlPort, wsdlPort.getBinding().getBindingId(), features);
569 tokens[i] = tokenizer.nextToken();
570 }
571 }
572 StringBuilder namespace = new StringBuilder("http://");
573 for (int i=0; i<tokens.length; i++) {
574 if (i!=0)
575 namespace.append('.');
576 namespace.append(tokens[i]);
577 }
578 namespace.append('/');
579 return namespace.toString();
580 }
581
582 /*
583 * Returns true if an exception is service specific exception as per JAX-WS rules.
584 * @param exception
585 * @return
586 */
587 private boolean isServiceException(Class<?> exception) {
588 return EXCEPTION_CLASS.isAssignableFrom(exception) &&
589 !(RUNTIME_EXCEPTION_CLASS.isAssignableFrom(exception) || REMOTE_EXCEPTION_CLASS.isAssignableFrom(exception));
590 }
591
592 /**
593 * creates the runtime model for a method on the <code>portClass</code>
594 * @param method the method to model
595 */
596 private void processMethod(Method method) {
597 // int mods = method.getModifiers();
598 WebMethod webMethod = getAnnotation(method, WebMethod.class);
599 if (webMethod != null && webMethod.exclude()) return;
600 /*
601 validations are already done
602
603 if (!Modifier.isPublic(mods) || Modifier.isStatic(mods)) {
604 if(webMethod != null) {
605 // if the user put @WebMethod on these non-qualifying method,
606 // it's an error
607 if(Modifier.isStatic(mods))
608 throw new RuntimeModelerException(ModelerMessages.localizableRUNTIME_MODELER_WEBMETHOD_MUST_BE_NONSTATIC(method));
609 else
1152 ParameterBinding pb = getBinding(operationName, partName, isHeader, Mode.IN);
1153 param.setInBinding(pb);
1154 pb = getBinding(operationName, partName, isHeader, Mode.OUT);
1155 param.setOutBinding(pb);
1156 }else{
1157 if (isHeader) {
1158 typeRef.setGlobalElement(true);
1159 param.setBinding(ParameterBinding.HEADER);
1160 } else {
1161 ParameterBinding pb = getBinding(operationName, partName, false, paramMode);
1162 param.setBinding(pb);
1163 }
1164 }
1165 if(param.getInBinding().isBody()){
1166 typeRef.setGlobalElement(false);
1167 if(!param.isOUT()){
1168 WSDLPart p = getPart(new QName(targetNamespace,operationName), partName, Mode.IN);
1169 if(p == null)
1170 reqRpcParams.put(reqRpcParams.size()+10000, param);
1171 else
1172 reqRpcParams.put(p.getIndex(), param);
1173 }
1174
1175 if(!param.isIN()){
1176 if (isOneway) {
1177 throw new RuntimeModelerException("runtime.modeler.oneway.operation.no.out.parameters",
1178 portClass.getCanonicalName(), methodName);
1179 }
1180 WSDLPart p = getPart(new QName(targetNamespace,operationName), partName, Mode.OUT);
1181 if(p == null)
1182 resRpcParams.put(resRpcParams.size()+10000, param);
1183 else
1184 resRpcParams.put(p.getIndex(), param);
1185 }
1186 }else{
1187 javaMethod.addParameter(param);
1188 }
1189 }
1190 for (ParameterImpl p : reqRpcParams.values())
1191 requestWrapper.addWrapperChild(p);
1192 for (ParameterImpl p : resRpcParams.values())
1193 responseWrapper.addWrapperChild(p);
1194 processExceptions(javaMethod, method);
1195 }
1196
1197 /**
1198 * models the exceptions thrown by <code>method</code> and adds them to the <code>javaMethod</code>
1199 * runtime model object
1200 * @param javaMethod the runtime model object to add the exception model objects to
1201 * @param method the <code>method</code> from which to find the exceptions to model
1202 */
1203 protected void processExceptions(JavaMethodImpl javaMethod, Method method) {
1204 Action actionAnn = getAnnotation(method, Action.class);
1205 FaultAction[] faultActions = {};
1206 if(actionAnn != null)
1207 faultActions = actionAnn.fault();
1208 for (Class<?> exception : method.getExceptionTypes()) {
1209
1210 //Exclude RuntimeException, RemoteException and Error etc
1211 if (!EXCEPTION_CLASS.isAssignableFrom(exception))
1212 continue;
1213 if (RUNTIME_EXCEPTION_CLASS.isAssignableFrom(exception) || REMOTE_EXCEPTION_CLASS.isAssignableFrom(exception))
1214 continue;
1215 if (getAnnotation(exception, javax.xml.bind.annotation.XmlTransient.class) != null)
1216 continue;
1217 Class exceptionBean;
1218 Annotation[] anns;
1219 WebFault webFault = getAnnotation(exception, WebFault.class);
1220 Method faultInfoMethod = getWSDLExceptionFaultInfo(exception);
1221 ExceptionType exceptionType = ExceptionType.WSDLException;
1222 String namespace = targetNamespace;
1223 String name = exception.getSimpleName();
1224 String beanPackage = packageName + PD_JAXWS_PACKAGE_PD;
1225 if (packageName.length() == 0)
1226 beanPackage = JAXWS_PACKAGE_PD;
1227 String className = beanPackage+ name + BEAN;
1228 String messageName = exception.getSimpleName();
1229 if (webFault != null) {
1230 if (webFault.faultBean().length()>0)
1231 className = webFault.faultBean();
1232 if (webFault.name().length()>0)
1233 name = webFault.name();
1627 }
1628
1629 private ParameterBinding getBinding(String operation, String part, boolean isHeader, Mode mode){
1630 if(binding == null){
1631 if(isHeader)
1632 return ParameterBinding.HEADER;
1633 else
1634 return ParameterBinding.BODY;
1635 }
1636 QName opName = new QName(binding.getBinding().getPortType().getName().getNamespaceURI(), operation);
1637 return binding.getBinding().getBinding(opName, part, mode);
1638 }
1639
1640 private WSDLPart getPart(QName opName, String partName, Mode mode){
1641 if(binding != null){
1642 WSDLBoundOperation bo = binding.getBinding().get(opName);
1643 if(bo != null)
1644 return bo.getPart(partName, mode);
1645 }
1646 return null;
1647 }
1648
1649 private static Boolean getBooleanSystemProperty(final String prop) {
1650 return AccessController.doPrivileged(
1651 new java.security.PrivilegedAction<Boolean>() {
1652 public Boolean run() {
1653 String value = System.getProperty(prop);
1654 return value != null ? Boolean.valueOf(value) : Boolean.FALSE;
1655 }
1656 }
1657 );
1658 }
1659
1660 private static QName getReturnQName(Method method, WebResult webResult, XmlElement xmlElem) {
1661 String webResultName = null;
1662 if (webResult != null && webResult.name().length() > 0) {
1663 webResultName = webResult.name();
1664 }
1665 String xmlElemName = null;
1666 if (xmlElem != null && !xmlElem.name().equals("##default")) {
|
1 /*
2 * Copyright (c) 1997, 2016, 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
49 import com.sun.xml.internal.ws.spi.db.WrapperComposite;
50
51 import static com.sun.xml.internal.ws.binding.WebServiceFeatureList.getSoapVersion;
52 import static com.sun.xml.internal.ws.model.Utils.REFLECTION_NAVIGATOR;
53
54 import javax.jws.*;
55 import javax.jws.WebParam.Mode;
56 import javax.jws.soap.SOAPBinding;
57 import javax.jws.soap.SOAPBinding.Style;
58 import javax.xml.bind.annotation.XmlElement;
59 import javax.xml.bind.annotation.XmlSeeAlso;
60 import javax.xml.namespace.QName;
61 import javax.xml.ws.*;
62 import javax.xml.ws.soap.MTOM;
63 import javax.xml.ws.soap.MTOMFeature;
64 import java.lang.annotation.Annotation;
65 import java.lang.reflect.Method;
66 import java.lang.reflect.Modifier;
67 import java.lang.reflect.ParameterizedType;
68 import java.lang.reflect.Type;
69 import java.security.AccessController;
70 import java.util.HashSet;
71 import java.util.Map;
72 import java.util.Set;
73 import java.util.StringTokenizer;
74 import java.util.TreeMap;
75 import java.util.concurrent.Future;
76 import java.util.logging.Logger;
77
78 import static javax.jws.soap.SOAPBinding.ParameterStyle.WRAPPED;
79
80 /**
81 * Creates a runtime model of a SEI (portClass).
82 *
83 * @author WS Developement Team
84 */
85 public class RuntimeModeler {
86 private final WebServiceFeatureList features;
87 private BindingID bindingId;
88 private WSBinding wsBinding;
97 private final WSDLPort binding;
98 private QName serviceName;
99 private QName portName;
100 private Set<Class> classUsesWebMethod;
101 private DatabindingConfig config;
102 private MetadataReader metadataReader;
103 /**
104 *
105 */
106 public static final String PD_JAXWS_PACKAGE_PD = ".jaxws.";
107 /**
108 *
109 */
110 public static final String JAXWS_PACKAGE_PD = "jaxws.";
111 public static final String RESPONSE = "Response";
112 public static final String RETURN = "return";
113 public static final String BEAN = "Bean";
114 public static final String SERVICE = "Service";
115 public static final String PORT = "Port";
116 public static final Class HOLDER_CLASS = Holder.class;
117 public static final String REMOTE_EXCEPTION_CLASS = "java.rmi.RemoteException";
118 public static final Class<RuntimeException> RUNTIME_EXCEPTION_CLASS = RuntimeException.class;
119 public static final Class<Exception> EXCEPTION_CLASS = Exception.class;
120 public static final String DecapitalizeExceptionBeanProperties = "com.sun.xml.internal.ws.api.model.DecapitalizeExceptionBeanProperties";
121 public static final String SuppressDocLitWrapperGeneration = "com.sun.xml.internal.ws.api.model.SuppressDocLitWrapperGeneration";
122 public static final String DocWrappeeNamespapceQualified = "com.sun.xml.internal.ws.api.model.DocWrappeeNamespapceQualified";
123
124 /*public RuntimeModeler(@NotNull Class portClass, @NotNull QName serviceName, @NotNull BindingID bindingId, @NotNull WebServiceFeature... features) {
125 this(portClass, serviceName, null, bindingId, features);
126 }*/
127
128 /**
129 *
130 * creates an instance of RunTimeModeler given a <code>sei</code> and <code>binding</code>
131 * @param portClass The SEI class to be modeled.
132 * @param serviceName The ServiceName to use instead of one calculated from the implementation class
133 * @param wsdlPort {@link com.sun.xml.internal.ws.api.model.wsdl.WSDLPort}
134 * @param features web service features
135 */
136 /*public RuntimeModeler(@NotNull Class portClass, @NotNull QName serviceName, @NotNull WSDLPortImpl wsdlPort, @NotNull WebServiceFeature... features){
137 this(portClass, serviceName, wsdlPort, wsdlPort.getBinding().getBindingId(), features);
568 tokens[i] = tokenizer.nextToken();
569 }
570 }
571 StringBuilder namespace = new StringBuilder("http://");
572 for (int i=0; i<tokens.length; i++) {
573 if (i!=0)
574 namespace.append('.');
575 namespace.append(tokens[i]);
576 }
577 namespace.append('/');
578 return namespace.toString();
579 }
580
581 /*
582 * Returns true if an exception is service specific exception as per JAX-WS rules.
583 * @param exception
584 * @return
585 */
586 private boolean isServiceException(Class<?> exception) {
587 return EXCEPTION_CLASS.isAssignableFrom(exception) &&
588 !(RUNTIME_EXCEPTION_CLASS.isAssignableFrom(exception) || isRemoteException(exception));
589 }
590
591 /**
592 * creates the runtime model for a method on the <code>portClass</code>
593 * @param method the method to model
594 */
595 private void processMethod(Method method) {
596 // int mods = method.getModifiers();
597 WebMethod webMethod = getAnnotation(method, WebMethod.class);
598 if (webMethod != null && webMethod.exclude()) return;
599 /*
600 validations are already done
601
602 if (!Modifier.isPublic(mods) || Modifier.isStatic(mods)) {
603 if(webMethod != null) {
604 // if the user put @WebMethod on these non-qualifying method,
605 // it's an error
606 if(Modifier.isStatic(mods))
607 throw new RuntimeModelerException(ModelerMessages.localizableRUNTIME_MODELER_WEBMETHOD_MUST_BE_NONSTATIC(method));
608 else
1151 ParameterBinding pb = getBinding(operationName, partName, isHeader, Mode.IN);
1152 param.setInBinding(pb);
1153 pb = getBinding(operationName, partName, isHeader, Mode.OUT);
1154 param.setOutBinding(pb);
1155 }else{
1156 if (isHeader) {
1157 typeRef.setGlobalElement(true);
1158 param.setBinding(ParameterBinding.HEADER);
1159 } else {
1160 ParameterBinding pb = getBinding(operationName, partName, false, paramMode);
1161 param.setBinding(pb);
1162 }
1163 }
1164 if(param.getInBinding().isBody()){
1165 typeRef.setGlobalElement(false);
1166 if(!param.isOUT()){
1167 WSDLPart p = getPart(new QName(targetNamespace,operationName), partName, Mode.IN);
1168 if(p == null)
1169 reqRpcParams.put(reqRpcParams.size()+10000, param);
1170 else
1171 reqRpcParams.put(param.getIndex(), param);
1172 }
1173
1174 if(!param.isIN()){
1175 if (isOneway) {
1176 throw new RuntimeModelerException("runtime.modeler.oneway.operation.no.out.parameters",
1177 portClass.getCanonicalName(), methodName);
1178 }
1179 WSDLPart p = getPart(new QName(targetNamespace,operationName), partName, Mode.OUT);
1180 if(p == null)
1181 resRpcParams.put(resRpcParams.size()+10000, param);
1182 else
1183 resRpcParams.put(param.getIndex(), param);
1184 }
1185 }else{
1186 javaMethod.addParameter(param);
1187 }
1188 }
1189 for (ParameterImpl p : reqRpcParams.values())
1190 requestWrapper.addWrapperChild(p);
1191 for (ParameterImpl p : resRpcParams.values())
1192 responseWrapper.addWrapperChild(p);
1193 processExceptions(javaMethod, method);
1194 }
1195
1196 /**
1197 * models the exceptions thrown by <code>method</code> and adds them to the <code>javaMethod</code>
1198 * runtime model object
1199 * @param javaMethod the runtime model object to add the exception model objects to
1200 * @param method the <code>method</code> from which to find the exceptions to model
1201 */
1202 protected void processExceptions(JavaMethodImpl javaMethod, Method method) {
1203 Action actionAnn = getAnnotation(method, Action.class);
1204 FaultAction[] faultActions = {};
1205 if(actionAnn != null)
1206 faultActions = actionAnn.fault();
1207 for (Class<?> exception : method.getExceptionTypes()) {
1208
1209 //Exclude RuntimeException, RemoteException and Error etc
1210 if (!EXCEPTION_CLASS.isAssignableFrom(exception))
1211 continue;
1212 if (RUNTIME_EXCEPTION_CLASS.isAssignableFrom(exception) || isRemoteException(exception))
1213 continue;
1214 if (getAnnotation(exception, javax.xml.bind.annotation.XmlTransient.class) != null)
1215 continue;
1216 Class exceptionBean;
1217 Annotation[] anns;
1218 WebFault webFault = getAnnotation(exception, WebFault.class);
1219 Method faultInfoMethod = getWSDLExceptionFaultInfo(exception);
1220 ExceptionType exceptionType = ExceptionType.WSDLException;
1221 String namespace = targetNamespace;
1222 String name = exception.getSimpleName();
1223 String beanPackage = packageName + PD_JAXWS_PACKAGE_PD;
1224 if (packageName.length() == 0)
1225 beanPackage = JAXWS_PACKAGE_PD;
1226 String className = beanPackage+ name + BEAN;
1227 String messageName = exception.getSimpleName();
1228 if (webFault != null) {
1229 if (webFault.faultBean().length()>0)
1230 className = webFault.faultBean();
1231 if (webFault.name().length()>0)
1232 name = webFault.name();
1626 }
1627
1628 private ParameterBinding getBinding(String operation, String part, boolean isHeader, Mode mode){
1629 if(binding == null){
1630 if(isHeader)
1631 return ParameterBinding.HEADER;
1632 else
1633 return ParameterBinding.BODY;
1634 }
1635 QName opName = new QName(binding.getBinding().getPortType().getName().getNamespaceURI(), operation);
1636 return binding.getBinding().getBinding(opName, part, mode);
1637 }
1638
1639 private WSDLPart getPart(QName opName, String partName, Mode mode){
1640 if(binding != null){
1641 WSDLBoundOperation bo = binding.getBinding().get(opName);
1642 if(bo != null)
1643 return bo.getPart(partName, mode);
1644 }
1645 return null;
1646 }
1647
1648 /*
1649 * Returns true if an exception is a java.rmi.RemoteException or its subtype.
1650 *
1651 * @param exception
1652 * @return true if an exception is a java.rmi.RemoteException or its subtype,
1653 * false otherwise
1654 */
1655 private boolean isRemoteException(Class<?> exception) {
1656 Class<?> c = exception;
1657 while (c != null && !REMOTE_EXCEPTION_CLASS.equals(c.getName())) {
1658 c = c.getSuperclass();
1659 }
1660 return c != null;
1661 }
1662
1663 private static Boolean getBooleanSystemProperty(final String prop) {
1664 return AccessController.doPrivileged(
1665 new java.security.PrivilegedAction<Boolean>() {
1666 public Boolean run() {
1667 String value = System.getProperty(prop);
1668 return value != null ? Boolean.valueOf(value) : Boolean.FALSE;
1669 }
1670 }
1671 );
1672 }
1673
1674 private static QName getReturnQName(Method method, WebResult webResult, XmlElement xmlElem) {
1675 String webResultName = null;
1676 if (webResult != null && webResult.name().length() > 0) {
1677 webResultName = webResult.name();
1678 }
1679 String xmlElemName = null;
1680 if (xmlElem != null && !xmlElem.name().equals("##default")) {
|