001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common Development
008: * and Distribution License("CDDL") (collectively, the "License"). You
009: * may not use this file except in compliance with the License. You can obtain
010: * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
011: * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
012: * language governing permissions and limitations under the License.
013: *
014: * When distributing the software, include this License Header Notice in each
015: * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
016: * Sun designates this particular file as subject to the "Classpath" exception
017: * as provided by Sun in the GPL Version 2 section of the License file that
018: * accompanied this code. If applicable, add the following below the License
019: * Header, with the fields enclosed by brackets [] replaced by your own
020: * identifying information: "Portions Copyrighted [year]
021: * [name of copyright owner]"
022: *
023: * Contributor(s):
024: *
025: * If you wish your version of this file to be governed by only the CDDL or
026: * only the GPL Version 2, indicate your decision by adding "[Contributor]
027: * elects to include this software in this distribution under the [CDDL or GPL
028: * Version 2] license." If you don't indicate a single choice of license, a
029: * recipient has the option to distribute your version of this file under
030: * either the CDDL, the GPL Version 2 or to extend the choice of license to
031: * its licensees as provided above. However, if you add GPL Version 2 code
032: * and therefore, elected the GPL Version 2 license, then the option applies
033: * only if the new code is made subject to such option by the copyright
034: * holder.
035: */
036: package com.sun.xml.ws.server.sei;
037:
038: import com.sun.xml.bind.api.AccessorException;
039: import com.sun.xml.bind.api.Bridge;
040: import com.sun.xml.bind.api.CompositeStructure;
041: import com.sun.xml.bind.api.RawAccessor;
042: import com.sun.xml.ws.api.SOAPVersion;
043: import com.sun.xml.ws.api.message.Message;
044: import com.sun.xml.ws.api.message.Messages;
045: import com.sun.xml.ws.message.jaxb.JAXBMessage;
046: import com.sun.xml.ws.model.ParameterImpl;
047: import com.sun.xml.ws.model.WrapperParameter;
048:
049: import javax.xml.bind.JAXBException;
050: import javax.xml.namespace.QName;
051: import javax.xml.ws.Holder;
052: import javax.xml.ws.WebServiceException;
053: import java.util.List;
054:
055: /**
056: * Builds a JAXB object that represents the payload.
057: *
058: * @see MessageFiller
059: * @author Jitendra Kotamraju
060: */
061: abstract class EndpointResponseMessageBuilder {
062: abstract Message createMessage(Object[] methodArgs,
063: Object returnValue);
064:
065: static final EndpointResponseMessageBuilder EMPTY_SOAP11 = new Empty(
066: SOAPVersion.SOAP_11);
067: static final EndpointResponseMessageBuilder EMPTY_SOAP12 = new Empty(
068: SOAPVersion.SOAP_12);
069:
070: private static final class Empty extends
071: EndpointResponseMessageBuilder {
072: private final SOAPVersion soapVersion;
073:
074: public Empty(SOAPVersion soapVersion) {
075: this .soapVersion = soapVersion;
076: }
077:
078: Message createMessage(Object[] methodArgs, Object returnValue) {
079: return Messages.createEmpty(soapVersion);
080: }
081: }
082:
083: /**
084: * Base class for those {@link EndpointResponseMessageBuilder}s that build a {@link Message}
085: * from JAXB objects.
086: */
087: private static abstract class JAXB extends
088: EndpointResponseMessageBuilder {
089: /**
090: * This object determines the binding of the object returned
091: * from {@link #createMessage(Object[], Object)}
092: */
093: private final Bridge bridge;
094: private final SOAPVersion soapVersion;
095:
096: protected JAXB(Bridge bridge, SOAPVersion soapVersion) {
097: assert bridge != null;
098: this .bridge = bridge;
099: this .soapVersion = soapVersion;
100: }
101:
102: final Message createMessage(Object[] methodArgs,
103: Object returnValue) {
104: return JAXBMessage.create(bridge, build(methodArgs,
105: returnValue), soapVersion);
106: }
107:
108: /**
109: * Builds a JAXB object that becomes the payload.
110: */
111: abstract Object build(Object[] methodArgs, Object returnValue);
112: }
113:
114: /**
115: * Used to create a payload JAXB object just by taking
116: * one of the parameters.
117: */
118: final static class Bare extends JAXB {
119: /**
120: * The index of the method invocation parameters that goes into the payload.
121: */
122: private final int methodPos;
123:
124: private final ValueGetter getter;
125:
126: /**
127: * Creates a {@link EndpointResponseMessageBuilder} from a bare parameter.
128: */
129: Bare(ParameterImpl p, SOAPVersion soapVersion) {
130: super (p.getBridge(), soapVersion);
131: this .methodPos = p.getIndex();
132: this .getter = ValueGetter.get(p);
133: }
134:
135: /**
136: * Picks up an object from the method arguments and uses it.
137: */
138: Object build(Object[] methodArgs, Object returnValue) {
139: if (methodPos == -1) {
140: return returnValue;
141: }
142: return getter.get(methodArgs[methodPos]);
143: }
144: }
145:
146: /**
147: * Used to handle a 'wrapper' style request.
148: * Common part of rpc/lit and doc/lit.
149: */
150: abstract static class Wrapped extends JAXB {
151:
152: /**
153: * Where in the method argument list do they come from?
154: */
155: protected final int[] indices;
156:
157: /**
158: * Abstracts away the {@link Holder} handling when touching method arguments.
159: */
160: protected final ValueGetter[] getters;
161:
162: protected Wrapped(WrapperParameter wp, SOAPVersion soapVersion) {
163: super (wp.getBridge(), soapVersion);
164:
165: List<ParameterImpl> children = wp.getWrapperChildren();
166:
167: indices = new int[children.size()];
168: getters = new ValueGetter[children.size()];
169: for (int i = 0; i < indices.length; i++) {
170: ParameterImpl p = children.get(i);
171: indices[i] = p.getIndex();
172: getters[i] = ValueGetter.get(p);
173: }
174: }
175: }
176:
177: /**
178: * Used to create a payload JAXB object by wrapping
179: * multiple parameters into one "wrapper bean".
180: */
181: final static class DocLit extends Wrapped {
182: /**
183: * How does each wrapped parameter binds to XML?
184: */
185: private final RawAccessor[] accessors;
186:
187: //private final RawAccessor retAccessor;
188:
189: /**
190: * Wrapper bean.
191: */
192: private final Class wrapper;
193:
194: /**
195: * Creates a {@link EndpointResponseMessageBuilder} from a {@link WrapperParameter}.
196: */
197: DocLit(WrapperParameter wp, SOAPVersion soapVersion) {
198: super (wp, soapVersion);
199:
200: wrapper = (Class) wp.getBridge().getTypeReference().type;
201:
202: List<ParameterImpl> children = wp.getWrapperChildren();
203:
204: accessors = new RawAccessor[children.size()];
205: for (int i = 0; i < accessors.length; i++) {
206: ParameterImpl p = children.get(i);
207: QName name = p.getName();
208: try {
209: accessors[i] = p.getOwner().getJAXBContext()
210: .getElementPropertyAccessor(wrapper,
211: name.getNamespaceURI(),
212: name.getLocalPart());
213: } catch (JAXBException e) {
214: throw new WebServiceException( // TODO: i18n
215: wrapper
216: + " do not have a property of the name "
217: + name, e);
218: }
219: }
220:
221: }
222:
223: /**
224: * Packs a bunch of arguments into a {@link CompositeStructure}.
225: */
226: Object build(Object[] methodArgs, Object returnValue) {
227: try {
228: Object bean = wrapper.newInstance();
229:
230: // fill in wrapped parameters from methodArgs
231: for (int i = indices.length - 1; i >= 0; i--) {
232: if (indices[i] == -1) {
233: accessors[i].set(bean, returnValue);
234: } else {
235: accessors[i].set(bean, getters[i]
236: .get(methodArgs[indices[i]]));
237: }
238: }
239:
240: return bean;
241: } catch (InstantiationException e) {
242: // this is irrecoverable
243: Error x = new InstantiationError(e.getMessage());
244: x.initCause(e);
245: throw x;
246: } catch (IllegalAccessException e) {
247: // this is irrecoverable
248: Error x = new IllegalAccessError(e.getMessage());
249: x.initCause(e);
250: throw x;
251: } catch (AccessorException e) {
252: // this can happen when the set method throw a checked exception or something like that
253: throw new WebServiceException(e); // TODO:i18n
254: }
255: }
256: }
257:
258: /**
259: * Used to create a payload JAXB object by wrapping
260: * multiple parameters into a {@link CompositeStructure}.
261: *
262: * <p>
263: * This is used for rpc/lit, as we don't have a wrapper bean for it.
264: * (TODO: Why don't we have a wrapper bean for this, when doc/lit does!?)
265: */
266: final static class RpcLit extends Wrapped {
267: /**
268: * How does each wrapped parameter binds to XML?
269: */
270: private final Bridge[] parameterBridges;
271:
272: /**
273: * Used for error diagnostics.
274: */
275: private final List<ParameterImpl> children;
276:
277: /**
278: * Creates a {@link EndpointResponseMessageBuilder} from a {@link WrapperParameter}.
279: */
280: RpcLit(WrapperParameter wp, SOAPVersion soapVersion) {
281: super (wp, soapVersion);
282: // we'll use CompositeStructure to pack requests
283: assert wp.getTypeReference().type == CompositeStructure.class;
284:
285: this .children = wp.getWrapperChildren();
286:
287: parameterBridges = new Bridge[children.size()];
288: for (int i = 0; i < parameterBridges.length; i++)
289: parameterBridges[i] = children.get(i).getBridge();
290: }
291:
292: /**
293: * Packs a bunch of arguments intoa {@link CompositeStructure}.
294: */
295: CompositeStructure build(Object[] methodArgs, Object returnValue) {
296: CompositeStructure cs = new CompositeStructure();
297: cs.bridges = parameterBridges;
298: cs.values = new Object[parameterBridges.length];
299:
300: // fill in wrapped parameters from methodArgs
301: for (int i = indices.length - 1; i >= 0; i--) {
302: Object v;
303: if (indices[i] == -1) {
304: v = getters[i].get(returnValue);
305: } else {
306: v = getters[i].get(methodArgs[indices[i]]);
307: }
308: if (v == null) {
309: throw new WebServiceException(
310: "Method Parameter: "
311: + children.get(i).getName()
312: + " cannot be null. This is BP 1.1 R2211 violation.");
313: }
314: cs.values[i] = v;
315: }
316:
317: return cs;
318: }
319: }
320: }
|