src/share/jaxws_classes/com/sun/xml/internal/ws/server/sei/EndpointResponseMessageBuilder.java

changeset 286
f50545b5e2f1
child 368
0989ad8c0860
equal deleted inserted replaced
284:88b85470e72c 286:f50545b5e2f1
1 /*
2 * Copyright (c) 1997, 2010, 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 */
25
26 package com.sun.xml.internal.ws.server.sei;
27
28 import com.sun.xml.internal.ws.api.SOAPVersion;
29 import com.sun.xml.internal.ws.api.message.Message;
30 import com.sun.xml.internal.ws.api.message.Messages;
31 import com.sun.xml.internal.ws.message.jaxb.JAXBMessage;
32 import com.sun.xml.internal.ws.model.ParameterImpl;
33 import com.sun.xml.internal.ws.model.WrapperParameter;
34 import com.sun.xml.internal.ws.spi.db.BindingContext;
35 import com.sun.xml.internal.ws.spi.db.XMLBridge;
36 import com.sun.xml.internal.ws.spi.db.PropertyAccessor;
37 import com.sun.xml.internal.ws.spi.db.WrapperComposite;
38
39 import javax.xml.bind.JAXBException;
40 import javax.xml.namespace.QName;
41 import javax.xml.ws.Holder;
42 import javax.xml.ws.WebServiceException;
43 import java.util.List;
44
45 /**
46 * Builds a JAXB object that represents the payload.
47 *
48 * @see MessageFiller
49 * @author Jitendra Kotamraju
50 */
51 public abstract class EndpointResponseMessageBuilder {
52 public abstract Message createMessage(Object[] methodArgs, Object returnValue);
53
54 public static final EndpointResponseMessageBuilder EMPTY_SOAP11 = new Empty(SOAPVersion.SOAP_11);
55 public static final EndpointResponseMessageBuilder EMPTY_SOAP12 = new Empty(SOAPVersion.SOAP_12);
56
57 private static final class Empty extends EndpointResponseMessageBuilder {
58 private final SOAPVersion soapVersion;
59
60 public Empty(SOAPVersion soapVersion) {
61 this.soapVersion = soapVersion;
62 }
63
64 public Message createMessage(Object[] methodArgs, Object returnValue) {
65 return Messages.createEmpty(soapVersion);
66 }
67 }
68
69 /**
70 * Base class for those {@link EndpointResponseMessageBuilder}s that build a {@link Message}
71 * from JAXB objects.
72 */
73 private static abstract class JAXB extends EndpointResponseMessageBuilder {
74 /**
75 * This object determines the binding of the object returned
76 * from {@link #createMessage(Object[], Object)}
77 */
78 private final XMLBridge bridge;
79 private final SOAPVersion soapVersion;
80
81 protected JAXB(XMLBridge bridge, SOAPVersion soapVersion) {
82 assert bridge!=null;
83 this.bridge = bridge;
84 this.soapVersion = soapVersion;
85 }
86
87 public final Message createMessage(Object[] methodArgs, Object returnValue) {
88 return JAXBMessage.create( bridge, build(methodArgs, returnValue), soapVersion );
89 }
90
91 /**
92 * Builds a JAXB object that becomes the payload.
93 */
94 abstract Object build(Object[] methodArgs, Object returnValue);
95 }
96
97 /**
98 * Used to create a payload JAXB object just by taking
99 * one of the parameters.
100 */
101 public final static class Bare extends JAXB {
102 /**
103 * The index of the method invocation parameters that goes into the payload.
104 */
105 private final int methodPos;
106
107 private final ValueGetter getter;
108
109 /**
110 * Creates a {@link EndpointResponseMessageBuilder} from a bare parameter.
111 */
112 public Bare(ParameterImpl p, SOAPVersion soapVersion) {
113 super(p.getXMLBridge(), soapVersion);
114 this.methodPos = p.getIndex();
115 this.getter = ValueGetter.get(p);
116 }
117
118 /**
119 * Picks up an object from the method arguments and uses it.
120 */
121 Object build(Object[] methodArgs, Object returnValue) {
122 if (methodPos == -1) {
123 return returnValue;
124 }
125 return getter.get(methodArgs[methodPos]);
126 }
127 }
128
129
130 /**
131 * Used to handle a 'wrapper' style request.
132 * Common part of rpc/lit and doc/lit.
133 */
134 abstract static class Wrapped extends JAXB {
135
136 /**
137 * Where in the method argument list do they come from?
138 */
139 protected final int[] indices;
140
141 /**
142 * Abstracts away the {@link Holder} handling when touching method arguments.
143 */
144 protected final ValueGetter[] getters;
145
146 protected Wrapped(WrapperParameter wp, SOAPVersion soapVersion) {
147 super(wp.getXMLBridge(), soapVersion);
148
149 List<ParameterImpl> children = wp.getWrapperChildren();
150
151 indices = new int[children.size()];
152 getters = new ValueGetter[children.size()];
153 for( int i=0; i<indices.length; i++ ) {
154 ParameterImpl p = children.get(i);
155 indices[i] = p.getIndex();
156 getters[i] = ValueGetter.get(p);
157 }
158 }
159 }
160
161 /**
162 * Used to create a payload JAXB object by wrapping
163 * multiple parameters into one "wrapper bean".
164 */
165 public final static class DocLit extends Wrapped {
166 /**
167 * How does each wrapped parameter binds to XML?
168 */
169 private final PropertyAccessor[] accessors;
170
171 //private final RawAccessor retAccessor;
172
173 /**
174 * Wrapper bean.
175 */
176 private final Class wrapper;
177
178 /**
179 * Needed to get wrapper instantiation method.
180 */
181 private BindingContext bindingContext;
182
183 /**
184 * Creates a {@link EndpointResponseMessageBuilder} from a {@link WrapperParameter}.
185 */
186 public DocLit(WrapperParameter wp, SOAPVersion soapVersion) {
187 super(wp, soapVersion);
188 bindingContext = wp.getOwner().getBindingContext();
189
190 wrapper = (Class)wp.getXMLBridge().getTypeInfo().type;
191
192 List<ParameterImpl> children = wp.getWrapperChildren();
193
194 accessors = new PropertyAccessor[children.size()];
195 for( int i=0; i<accessors.length; i++ ) {
196 ParameterImpl p = children.get(i);
197 QName name = p.getName();
198 try {
199 accessors[i] = p.getOwner().getBindingContext().getElementPropertyAccessor(
200 wrapper, name.getNamespaceURI(), name.getLocalPart() );
201 } catch (JAXBException e) {
202 throw new WebServiceException( // TODO: i18n
203 wrapper+" do not have a property of the name "+name,e);
204 }
205 }
206
207 }
208
209 /**
210 * Packs a bunch of arguments into a {@link WrapperComposite}.
211 */
212 Object build(Object[] methodArgs, Object returnValue) {
213 try {
214 //Object bean = wrapper.newInstance();
215 Object bean = bindingContext.newWrapperInstace(wrapper);
216
217 // fill in wrapped parameters from methodArgs
218 for( int i=indices.length-1; i>=0; i-- ) {
219 if (indices[i] == -1) {
220 accessors[i].set(bean, returnValue);
221 } else {
222 accessors[i].set(bean,getters[i].get(methodArgs[indices[i]]));
223 }
224 }
225
226 return bean;
227 } catch (InstantiationException e) {
228 // this is irrecoverable
229 Error x = new InstantiationError(e.getMessage());
230 x.initCause(e);
231 throw x;
232 } catch (IllegalAccessException e) {
233 // this is irrecoverable
234 Error x = new IllegalAccessError(e.getMessage());
235 x.initCause(e);
236 throw x;
237 } catch (com.sun.xml.internal.ws.spi.db.DatabindingException e) {
238 // this can happen when the set method throw a checked exception or something like that
239 throw new WebServiceException(e); // TODO:i18n
240 }
241 }
242 }
243
244
245 /**
246 * Used to create a payload JAXB object by wrapping
247 * multiple parameters into a {@link WrapperComposite}.
248 *
249 * <p>
250 * This is used for rpc/lit, as we don't have a wrapper bean for it.
251 * (TODO: Why don't we have a wrapper bean for this, when doc/lit does!?)
252 */
253 public final static class RpcLit extends Wrapped {
254 /**
255 * How does each wrapped parameter binds to XML?
256 */
257 private final XMLBridge[] parameterBridges;
258
259 /**
260 * Used for error diagnostics.
261 */
262 private final List<ParameterImpl> children;
263
264 /**
265 * Creates a {@link EndpointResponseMessageBuilder} from a {@link WrapperParameter}.
266 */
267 public RpcLit(WrapperParameter wp, SOAPVersion soapVersion) {
268 super(wp, soapVersion);
269 // we'll use CompositeStructure to pack requests
270 assert wp.getTypeInfo().type==WrapperComposite.class;
271
272 this.children = wp.getWrapperChildren();
273
274 parameterBridges = new XMLBridge[children.size()];
275 for( int i=0; i<parameterBridges.length; i++ )
276 parameterBridges[i] = children.get(i).getXMLBridge();
277 }
278
279 /**
280 * Packs a bunch of arguments intoa {@link WrapperComposite}.
281 */
282 WrapperComposite build(Object[] methodArgs, Object returnValue) {
283 WrapperComposite cs = new WrapperComposite();
284 cs.bridges = parameterBridges;
285 cs.values = new Object[parameterBridges.length];
286
287 // fill in wrapped parameters from methodArgs
288 for( int i=indices.length-1; i>=0; i-- ) {
289 Object v;
290 if (indices[i] == -1) {
291 v = getters[i].get(returnValue);
292 } else {
293 v = getters[i].get(methodArgs[indices[i]]);
294 }
295 if(v==null) {
296 throw new WebServiceException("Method Parameter: "+
297 children.get(i).getName() +" cannot be null. This is BP 1.1 R2211 violation.");
298 }
299 cs.values[i] = v;
300 }
301
302 return cs;
303 }
304 }
305 }

mercurial