src/share/jaxws_classes/com/sun/xml/internal/ws/client/sei/BodyBuilder.java

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

mercurial