1 package org.codehaus.xfire.aegis;
2
3 import java.util.Iterator;
4
5 import javax.xml.namespace.QName;
6 import javax.xml.stream.XMLStreamReader;
7 import javax.xml.stream.XMLStreamWriter;
8
9 import org.codehaus.xfire.MessageContext;
10 import org.codehaus.xfire.XFireRuntimeException;
11 import org.codehaus.xfire.aegis.stax.ElementReader;
12 import org.codehaus.xfire.aegis.stax.ElementWriter;
13 import org.codehaus.xfire.aegis.type.DefaultTypeMappingRegistry;
14 import org.codehaus.xfire.aegis.type.Type;
15 import org.codehaus.xfire.aegis.type.TypeMapping;
16 import org.codehaus.xfire.aegis.type.TypeMappingRegistry;
17 import org.codehaus.xfire.aegis.yom.YOMReader;
18 import org.codehaus.xfire.aegis.yom.YOMWriter;
19 import org.codehaus.xfire.fault.XFireFault;
20 import org.codehaus.xfire.service.MessageHeaderInfo;
21 import org.codehaus.xfire.service.MessagePartContainer;
22 import org.codehaus.xfire.service.MessagePartInfo;
23 import org.codehaus.xfire.service.OperationInfo;
24 import org.codehaus.xfire.service.Service;
25 import org.codehaus.xfire.service.binding.AbstractBinding;
26 import org.codehaus.xfire.service.binding.BindingProvider;
27 import org.codehaus.xfire.soap.SoapConstants;
28 import org.codehaus.yom.Element;
29
30 /***
31 * A BindingProvider for the Aegis type system.
32 *
33 * @author <a href="mailto:dan@envoisolutions.com">Dan Diephouse</a>
34 */
35 public class AegisBindingProvider
36 implements BindingProvider
37 {
38 public static final String TYPE_MAPPING_KEY = "type.mapping";
39 public static final String ENCODING_URI_KEY = "type.encodingUri";
40
41 private TypeMappingRegistry registry;
42 private boolean writeOuter = true;
43
44 public AegisBindingProvider()
45 {
46 this(new DefaultTypeMappingRegistry(true));
47 }
48
49 public AegisBindingProvider(TypeMappingRegistry registry)
50 {
51 this.registry = registry;
52 }
53
54 public boolean isWriteOuter()
55 {
56 return writeOuter;
57 }
58
59 public void setWriteOuter(boolean writeOuter)
60 {
61 this.writeOuter = writeOuter;
62 }
63
64 /***
65 * Creates a type mapping for this class and registers it with the TypeMappingRegistry. This needs to be called
66 * before initializeOperations().
67 */
68 public void initialize(Service endpoint)
69 {
70 String encodingStyle = (String) endpoint.getProperty(ENCODING_URI_KEY);
71
72 if (encodingStyle == null)
73 {
74 AbstractBinding binding = (AbstractBinding) endpoint.getBinding();
75 if (binding.getUse().equals(SoapConstants.USE_ENCODED))
76 {
77 encodingStyle = endpoint.getSoapVersion().getSoapEncodingStyle();
78 }
79 else
80 {
81 encodingStyle = SoapConstants.XSD;
82 }
83 }
84
85 endpoint.setProperty(ENCODING_URI_KEY, encodingStyle);
86 final TypeMapping tm = registry.createTypeMapping(encodingStyle, true);
87
88 endpoint.setProperty(TYPE_MAPPING_KEY, tm);
89 registry.register(endpoint.getServiceInfo().getName().getNamespaceURI(), tm);
90
91 for (Iterator itr = endpoint.getServiceInfo().getOperations().iterator(); itr.hasNext();)
92 {
93 OperationInfo opInfo = (OperationInfo) itr.next();
94 try
95 {
96 initializeMessage(endpoint, opInfo.getInputMessage());
97 }
98 catch(XFireRuntimeException e)
99 {
100 e.prepend("Error initializing parameters for method " + opInfo.getMethod());
101 throw e;
102 }
103 try
104 {
105 initializeMessage(endpoint, opInfo.getOutputMessage());
106 }
107 catch(XFireRuntimeException e)
108 {
109 e.prepend("Error initializing return value for method " + opInfo.getMethod());
110 throw e;
111 }
112 }
113 }
114
115 protected void initializeMessage(Service service, MessagePartContainer container)
116 {
117 for (Iterator itr = container.getMessageHeaders().iterator(); itr.hasNext();)
118 {
119 MessageHeaderInfo header = (MessageHeaderInfo) itr.next();
120
121 header.setSchemaType(getParameterType(getTypeMapping(service), header));
122 }
123
124 for (Iterator itr = container.getMessageParts().iterator(); itr.hasNext();)
125 {
126 MessagePartInfo part = (MessagePartInfo) itr.next();
127
128 part.setSchemaType(getParameterType(getTypeMapping(service), part));
129 }
130 }
131
132 public Object readParameter(MessagePartInfo p, XMLStreamReader xsr, MessageContext context)
133 throws XFireFault
134 {
135 Type type = (Type) p.getSchemaType();
136
137 MessageReader reader = new ElementReader(xsr);
138
139 return type.readObject(reader, context);
140 }
141
142 public void writeParameter(MessagePartInfo p,
143 XMLStreamWriter writer,
144 MessageContext context,
145 Object value)
146 throws XFireFault
147 {
148 Type type = (Type) p.getSchemaType();
149
150 MessageWriter mw;
151 if (writeOuter)
152 mw = new ElementWriter(writer, p.getName());
153 else
154 mw = new ElementWriter(writer);
155
156 type.writeObject(value, mw, context);
157
158 if (writeOuter)
159 mw.close();
160 }
161
162 private Type getParameterType(TypeMapping tm, MessagePartInfo param)
163 {
164 Type type = tm.getType(param.getName());
165
166 if (type == null && tm.isRegistered(param.getTypeClass()))
167 {
168 type = tm.getType(param.getTypeClass());
169 }
170
171 if (type == null)
172 {
173 OperationInfo op = param.getContainer().getOperation();
174
175 int index = -1;
176
177 if (op.getInputMessage().getMessageParts().contains(param))
178 index = param.getIndex();
179
180
181
182
183
184 type = tm.getTypeCreator().createType(op.getMethod(), index);
185 type.setTypeMapping(tm);
186 }
187
188 return type;
189 }
190
191 private Type getParameterType(TypeMapping tm, MessageHeaderInfo param)
192 {
193 Type type = tm.getType(param.getName());
194
195 if (type == null && tm.isRegistered(param.getTypeClass()))
196 {
197 type = tm.getType(param.getTypeClass());
198 }
199
200 if (type == null)
201 {
202 OperationInfo op = param.getContainer().getOperation();
203
204 int index = -1;
205
206 if (op.getInputMessage().getMessageHeaders().contains(param))
207 index = param.getIndex();
208
209
210
211
212
213 type = tm.getTypeCreator().createType(op.getMethod(), index);
214 type.setTypeMapping(tm);
215 }
216
217 return type;
218 }
219
220 public static TypeMapping getTypeMapping(Service service)
221 {
222 return (TypeMapping) service.getProperty(TYPE_MAPPING_KEY);
223 }
224
225 public Object readHeader(MessageHeaderInfo p, MessageContext context)
226 throws XFireFault
227 {
228 Type type = (Type) p.getSchemaType();
229
230 QName name = p.getName();
231 Element headers = context.getExchange().getInMessage().getHeader();
232 Element header = headers.getFirstChildElement(name.getLocalPart(), name.getNamespaceURI());
233
234 if (header == null) return null;
235
236 return type.readObject(new YOMReader(header), context);
237 }
238
239 public void writeHeader(MessagePartInfo p, MessageContext context, Object value)
240 throws XFireFault
241 {
242 Type type = (Type) p.getSchemaType();
243
244 MessageWriter mw = new YOMWriter(context.getOutMessage().getHeader());
245
246 type.writeObject(value, mw, context);
247
248 mw.close();
249 }
250
251 }