001: /*
002: * Portions Copyright 2006 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025: package com.sun.xml.internal.ws.model.soap;
026:
027: import com.sun.xml.internal.bind.api.RawAccessor;
028: import com.sun.xml.internal.bind.api.TypeReference;
029: import com.sun.xml.internal.messaging.saaj.soap.SOAPVersionMismatchException;
030: import com.sun.xml.internal.ws.encoding.jaxb.JAXBBridgeInfo;
031: import com.sun.xml.internal.ws.encoding.jaxb.RpcLitPayload;
032: import com.sun.xml.internal.ws.encoding.soap.SOAPConstants;
033: import com.sun.xml.internal.ws.encoding.soap.internal.BodyBlock;
034: import com.sun.xml.internal.ws.encoding.soap.internal.HeaderBlock;
035: import com.sun.xml.internal.ws.encoding.soap.internal.InternalMessage;
036: import com.sun.xml.internal.ws.encoding.soap.message.*;
037: import com.sun.xml.internal.ws.model.*;
038: import com.sun.xml.internal.ws.pept.ept.MessageInfo;
039: import com.sun.xml.internal.ws.server.ServerRtException;
040: import com.sun.xml.internal.ws.util.MessageInfoUtil;
041:
042: import javax.xml.namespace.QName;
043: import javax.xml.ws.soap.SOAPFaultException;
044: import javax.xml.soap.SOAPFault;
045:
046: import java.util.Collection;
047: import java.util.HashSet;
048: import java.util.Iterator;
049: import java.util.List;
050: import java.util.Locale;
051: import java.util.Set;
052:
053: /**
054: * Creates SOAP specific RuntimeModel
055: *
056: * @author Vivek Pandey
057: */
058: public class SOAPRuntimeModel extends RuntimeModel {
059:
060: protected void createDecoderInfo() {
061: Collection<JavaMethod> methods = getJavaMethods();
062: for (JavaMethod m : methods) {
063: if (m.isAsync())
064: continue;
065: SOAPBinding binding = (SOAPBinding) m.getBinding();
066: setDecoderInfo(m.getRequestParameters(), binding, Mode.IN);
067: setDecoderInfo(m.getResponseParameters(), binding, Mode.OUT);
068: for (CheckedException ce : m.getCheckedExceptions()) {
069: JAXBBridgeInfo bi = new JAXBBridgeInfo(getBridge(ce
070: .getDetailType()));
071: addDecoderInfo(ce.getDetailType().tagName, bi);
072: }
073: }
074:
075: }
076:
077: private void setDecoderInfo(List<Parameter> params,
078: SOAPBinding binding, Mode mode) {
079: for (Parameter param : params) {
080: ParameterBinding paramBinding = (mode == Mode.IN) ? param
081: .getInBinding() : param.getOutBinding();
082: if (paramBinding.isBody() && binding.isRpcLit()) {
083: RpcLitPayload payload = new RpcLitPayload(param
084: .getName());
085: WrapperParameter wp = (WrapperParameter) param;
086: for (Parameter p : wp.getWrapperChildren()) {
087: if (p.getBinding().isUnbound())
088: continue;
089: JAXBBridgeInfo bi = new JAXBBridgeInfo(getBridge(p
090: .getTypeReference()), null);
091: payload.addParameter(bi);
092: }
093: addDecoderInfo(param.getName(), payload);
094: } else {
095: JAXBBridgeInfo bi = new JAXBBridgeInfo(getBridge(param
096: .getTypeReference()), null);
097: addDecoderInfo(param.getName(), bi);
098: }
099: }
100: }
101:
102: /*
103: * @see RuntimeModel#populateMaps()
104: */
105: @Override
106: protected void populateMaps() {
107: int emptyBodyCount = 0;
108: for (JavaMethod jm : getJavaMethods()) {
109: put(jm.getMethod(), jm);
110: boolean bodyFound = false;
111: for (Parameter p : jm.getRequestParameters()) {
112: ParameterBinding binding = p.getBinding();
113: if (binding.isBody()) {
114: put(p.getName(), jm);
115: bodyFound = true;
116: }
117: }
118: if (!bodyFound) {
119: put(emptyBodyName, jm);
120: // System.out.println("added empty body for: "+jm.getMethod().getName());
121: emptyBodyCount++;
122: }
123: }
124: if (emptyBodyCount > 1) {
125: //TODO throw exception
126: // System.out.println("Error: Unqiue signature violation - more than 1 empty body!");
127: }
128: }
129:
130: /*
131: * @see RuntimeModel#fillTypes(JavaMethod, List)
132: */
133: @Override
134: protected void fillTypes(JavaMethod m, List<TypeReference> types) {
135: if (!(m.getBinding() instanceof SOAPBinding)) {
136: //TODO throws exception
137: System.out.println("Error: Wrong Binding!");
138: return;
139: }
140: if (((SOAPBinding) m.getBinding()).isDocLit()) {
141: super .fillTypes(m, types);
142: return;
143: }
144:
145: //else is rpclit
146: addTypes(m.getRequestParameters(), types, Mode.IN);
147: addTypes(m.getResponseParameters(), types, Mode.OUT);
148: }
149:
150: /**
151: * @param params
152: * @param types
153: * @param mode
154: */
155: private void addTypes(List<Parameter> params,
156: List<TypeReference> types, Mode mode) {
157: for (Parameter p : params) {
158: ParameterBinding binding = (mode == Mode.IN) ? p
159: .getInBinding() : p.getOutBinding();
160: if (!p.isWrapperStyle()) {
161: types.add(p.getTypeReference());
162: } else if (binding.isBody()) {
163: List<Parameter> wcParams = ((WrapperParameter) p)
164: .getWrapperChildren();
165: for (Parameter wc : wcParams) {
166: types.add(wc.getTypeReference());
167: }
168: }
169: }
170: }
171:
172: public Set<QName> getKnownHeaders() {
173: Set<QName> headers = new HashSet<QName>();
174: Iterator<JavaMethod> methods = getJavaMethods().iterator();
175: while (methods.hasNext()) {
176: JavaMethod method = methods.next();
177: // fill in request headers
178: Iterator<Parameter> params = method.getRequestParameters()
179: .iterator();
180: fillHeaders(params, headers, Mode.IN);
181:
182: // fill in response headers
183: params = method.getResponseParameters().iterator();
184: fillHeaders(params, headers, Mode.OUT);
185: }
186: return headers;
187: }
188:
189: /**
190: * @param params
191: * @param headers
192: */
193: private void fillHeaders(Iterator<Parameter> params,
194: Set<QName> headers, Mode mode) {
195: while (params.hasNext()) {
196: Parameter param = params.next();
197: ParameterBinding binding = (mode == Mode.IN) ? param
198: .getInBinding() : param.getOutBinding();
199: QName name = param.getName();
200: if (binding.isHeader() && !headers.contains(name)) {
201: headers.add(name);
202: }
203: }
204: }
205:
206: /**
207: * Called by server
208: *
209: * @param obj
210: * @param actor
211: * @param detail
212: * @param internalMsg
213: * @return the InternalMessage for a fault
214: */
215: public static InternalMessage createFaultInBody(Object obj,
216: String actor, Object detail, InternalMessage internalMsg) {
217: SOAPFaultInfo faultInfo;
218: if (obj instanceof SOAPFaultInfo) {
219: faultInfo = (SOAPFaultInfo) obj;
220: } else if (obj instanceof ServerRtException) {
221: Throwable cause = ((ServerRtException) obj).getCause();
222: Throwable th = (cause == null) ? (ServerRtException) obj
223: : cause;
224: faultInfo = createSOAPFaultInfo(th, actor, detail);
225:
226: } else if (obj instanceof SOAPFaultException) {
227: SOAPFaultException e = (SOAPFaultException) obj;
228: faultInfo = new SOAPFaultInfo(e.getFault());
229: } else if (obj instanceof SOAPVersionMismatchException) {
230: QName faultCode = SOAPConstants.FAULT_CODE_VERSION_MISMATCH;
231: String faultString = "SOAP envelope version mismatch";
232: faultInfo = new SOAPFaultInfo(faultString, faultCode,
233: actor, null,
234: javax.xml.ws.soap.SOAPBinding.SOAP11HTTP_BINDING);
235: } else if (obj instanceof Exception) {
236: faultInfo = createSOAPFaultInfo((Exception) obj, actor,
237: detail);
238: } else {
239: QName faultCode = SOAPConstants.FAULT_CODE_SERVER;
240: String faultString = "Unknown fault type:" + obj.getClass();
241: faultInfo = new SOAPFaultInfo(faultString, faultCode,
242: actor, null,
243: javax.xml.ws.soap.SOAPBinding.SOAP11HTTP_BINDING);
244: }
245:
246: if (internalMsg == null) {
247: internalMsg = new InternalMessage();
248: }
249:
250: BodyBlock bodyBlock = internalMsg.getBody();
251: if (bodyBlock == null) {
252: bodyBlock = new BodyBlock(faultInfo);
253: internalMsg.setBody(bodyBlock);
254: } else {
255: bodyBlock.setFaultInfo(faultInfo);
256: }
257:
258: return internalMsg;
259: }
260:
261: public static InternalMessage createSOAP12FaultInBody(Object obj,
262: String role, String node, Object detail, InternalMessage im) {
263: SOAP12FaultInfo faultInfo;
264: if (obj instanceof SOAP12FaultInfo) {
265: faultInfo = (SOAP12FaultInfo) obj;
266: } else if (obj instanceof ServerRtException) {
267: Throwable cause = ((ServerRtException) obj).getCause();
268: Throwable th = (cause == null) ? (ServerRtException) obj
269: : cause;
270: faultInfo = createSOAP12FaultInfo(th, role, node, detail);
271:
272: } else if (obj instanceof SOAPFaultException) {
273: SOAPFaultException e = (SOAPFaultException) obj;
274: faultInfo = new SOAP12FaultInfo(e.getFault());
275: } else if (obj instanceof SOAPVersionMismatchException) {
276: String faultString = "SOAP envelope version mismatch";
277: FaultCode code = new FaultCode(
278: FaultCodeEnum.VersionMismatch, (FaultSubcode) null);
279: FaultReason reason = new FaultReason(new FaultReasonText(
280: faultString, Locale.getDefault()));
281: faultInfo = new SOAP12FaultInfo(code, reason, null, null,
282: null);
283: } else if (obj instanceof Exception) {
284: faultInfo = createSOAP12FaultInfo((Exception) obj, role,
285: node, detail);
286: } else {
287: String faultString = "Unknown fault type:" + obj.getClass();
288: FaultCode code = new FaultCode(FaultCodeEnum.Receiver,
289: (FaultSubcode) null);
290: FaultReason reason = new FaultReason(new FaultReasonText(
291: faultString, Locale.getDefault()));
292: faultInfo = new SOAP12FaultInfo(code, reason, null, null,
293: null);
294: }
295: if (im == null) {
296: im = new InternalMessage();
297: }
298: BodyBlock bodyBlock = im.getBody();
299: if (bodyBlock == null) {
300: bodyBlock = new BodyBlock(faultInfo);
301: im.setBody(bodyBlock);
302: } else {
303: bodyBlock.setValue(faultInfo);
304: }
305: return im;
306: }
307:
308: // currently adds not understood header blocks if there are any
309: public static void addHeaders(InternalMessage message,
310: MessageInfo mi) {
311: Set<HeaderBlock> notUnderstoodHeaders = MessageInfoUtil
312: .getNotUnderstoodHeaders(mi);
313: if (notUnderstoodHeaders != null) {
314: for (HeaderBlock block : notUnderstoodHeaders) {
315: message.addHeader(block);
316: }
317: }
318: }
319:
320: private static SOAP12FaultInfo createSOAP12FaultInfo(Throwable e,
321: String role, String node, Object detail) {
322: SOAPFaultException soapFaultException = null;
323: FaultCode code = null;
324: FaultReason reason = null;
325: String faultRole = null;
326: String faultNode = null;
327: Throwable cause = e.getCause();
328: if (e instanceof SOAPFaultException) {
329: soapFaultException = (SOAPFaultException) e;
330: } else if (cause != null && cause instanceof SOAPFaultException) {
331: soapFaultException = (SOAPFaultException) e.getCause();
332: }
333: if (soapFaultException != null) {
334: SOAPFault soapFault = soapFaultException.getFault();
335: code = new FaultCode(FaultCodeEnum.get(soapFault
336: .getFaultCodeAsQName()), (FaultSubcode) null);
337: reason = new FaultReason(
338: new FaultReasonText(soapFault.getFaultString(),
339: soapFault.getFaultStringLocale()));
340: faultRole = soapFault.getFaultRole();
341: if (faultRole == null)
342: faultRole = role;
343: faultNode = soapFault.getFaultNode();
344: if (faultNode == null)
345: faultNode = node;
346: }
347:
348: if (code == null || ((code != null) && code.getValue() == null)) {
349: code = new FaultCode(FaultCodeEnum.Receiver,
350: (FaultSubcode) null);
351: }
352:
353: if (reason == null) {
354: String faultString = e.getMessage();
355: if (faultString == null) {
356: faultString = e.toString();
357: }
358:
359: reason = new FaultReason(new FaultReasonText(faultString,
360: Locale.getDefault()));
361: }
362:
363: if ((detail == null) && (soapFaultException != null)) {
364: detail = soapFaultException.getFault().getDetail();
365: }
366:
367: return new SOAP12FaultInfo(code, reason, faultRole, faultNode,
368: detail);
369: }
370:
371: //TODO: createSOAP12HeaderFault()
372:
373: /**
374: * @param obj
375: * @param actor
376: * @param detailBlock
377: * @param internalMsg
378: * @return the <code>InteralMessage</code> for a HeaderFault
379: */
380: public static InternalMessage createHeaderFault(Object obj,
381: String actor, JAXBBridgeInfo detailBlock,
382: InternalMessage internalMsg) {
383: //its headerfault so, create body fault with no detail. detail object goes as a header block
384: internalMsg = createFaultInBody(obj, actor, null, internalMsg);
385: HeaderBlock hdrBlock = new HeaderBlock(detailBlock);
386: internalMsg.addHeader(hdrBlock);
387: return internalMsg;
388: }
389:
390: /**
391: * @param e
392: * @param actor
393: * @param detail
394: * @return
395: */
396: private static SOAPFaultInfo createSOAPFaultInfo(Throwable e,
397: String actor, Object detail) {
398: // e.printStackTrace();
399: SOAPFaultException soapFaultException = null;
400: QName faultCode = null;
401: String faultString = null;
402: String faultActor = null;
403: Throwable cause = e.getCause();
404: if (e instanceof SOAPFaultException) {
405: soapFaultException = (SOAPFaultException) e;
406: } else if (cause != null && cause instanceof SOAPFaultException) {
407: soapFaultException = (SOAPFaultException) e.getCause();
408: }
409: if (soapFaultException != null) {
410: faultCode = soapFaultException.getFault()
411: .getFaultCodeAsQName();
412: faultString = soapFaultException.getFault()
413: .getFaultString();
414: faultActor = soapFaultException.getFault().getFaultActor();
415: }
416:
417: if (faultCode == null) {
418: faultCode = SOAPConstants.FAULT_CODE_SERVER;
419: }
420:
421: if (faultString == null) {
422: faultString = e.getMessage();
423: if (faultString == null) {
424: faultString = e.toString();
425: }
426: }
427:
428: if (faultActor == null) {
429: faultActor = actor;
430: }
431:
432: if (detail == null && soapFaultException != null) {
433: detail = soapFaultException.getFault().getDetail();
434: }
435:
436: return new SOAPFaultInfo(faultString, faultCode, faultActor,
437: detail,
438: javax.xml.ws.soap.SOAPBinding.SOAP11HTTP_BINDING);
439: }
440:
441: }
|