Source code: org/apache/axis/description/OperationDesc.java
1 /*
2 * Copyright 2002-2004 The Apache Software Foundation.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package org.apache.axis.description;
17
18 import org.apache.axis.components.logger.LogFactory;
19 import org.apache.axis.constants.Style;
20 import org.apache.axis.constants.Use;
21 import org.apache.commons.logging.Log;
22
23 import javax.xml.namespace.QName;
24 import javax.wsdl.OperationType;
25 import java.io.Serializable;
26 import java.io.IOException;
27 import java.lang.reflect.Method;
28 import java.util.ArrayList;
29 import java.util.Iterator;
30 import java.util.Map;
31 import java.util.HashMap;
32
33
34 /**
35 * An OperationDesc is an abstract description of an operation on a service.
36 *
37 * !!! WORK IN PROGRESS
38 *
39 * @author Glen Daniels (gdaniels@apache.org)
40 */
41 public class OperationDesc implements Serializable {
42 // Constants for "message style" operation patterns. If this OperationDesc
43 // is message style, the Java method will have one of these signatures:
44
45 // public SOAPBodyElement [] method(SOAPBodyElement [])
46 public static final int MSG_METHOD_BODYARRAY = 1;
47 // public void method(SOAPEnvelope, SOAPEnvelope)
48 public static final int MSG_METHOD_SOAPENVELOPE = 2;
49 // public Element [] method(Element [])
50 public static final int MSG_METHOD_ELEMENTARRAY = 3;
51 // public Document method(Document)
52 public static final int MSG_METHOD_DOCUMENT = 4;
53
54 public static final int MSG_METHOD_NONCONFORMING = -4;
55
56 public static Map mepStrings = new HashMap();
57
58 static {
59 mepStrings.put("request-response", OperationType.REQUEST_RESPONSE);
60 mepStrings.put("oneway", OperationType.ONE_WAY);
61 mepStrings.put("solicit-response", OperationType.SOLICIT_RESPONSE);
62 mepStrings.put("notification", OperationType.NOTIFICATION);
63 }
64
65 protected static Log log =
66 LogFactory.getLog(OperationDesc.class.getName());
67
68 /** The service we're a part of */
69 private ServiceDesc parent;
70
71 /** Parameter list */
72 private ArrayList parameters = new ArrayList();
73
74 /** The operation name (String, or QName?) */
75 private String name;
76
77 /** An XML QName which should dispatch to this method */
78 private QName elementQName;
79
80 /** The actual Java method associated with this operation, if known */
81 private transient Method method;
82
83 /** This operation's style/use. If null, we default to our parent's */
84 private Style style = null;
85 private Use use = null;
86
87 /** The number of "in" params (i.e. IN or INOUT) for this operation */
88 private int numInParams = 0;
89 /** The number of "out" params (i.e. OUT or INOUT) for this operation */
90 private int numOutParams = 0;
91
92 /** A unique SOAPAction value for this operation */
93 private String soapAction = null;
94
95 /** Faults for this operation */
96 private ArrayList faults = null;
97
98 private ParameterDesc returnDesc = new ParameterDesc();
99
100 /** If we're a message-style operation, what's our signature? */
101 private int messageOperationStyle = -1;
102
103 /** The documentation for the operation */
104 private String documentation = null;
105
106 /** The MEP for this Operation - uses the WSDL4J OperationType for now
107 * but we might want to have our own extensible enum for WSDL 2.0
108 */
109 private OperationType mep = OperationType.REQUEST_RESPONSE;
110
111 /**
112 * Default constructor.
113 */
114 public OperationDesc() {
115 returnDesc.setMode(ParameterDesc.OUT);
116 returnDesc.setIsReturn(true);
117 }
118
119 /**
120 * "Complete" constructor
121 */
122 public OperationDesc(String name, ParameterDesc [] parameters, QName returnQName) {
123 this.name = name;
124 returnDesc.setQName(returnQName);
125 returnDesc.setMode(ParameterDesc.OUT);
126 returnDesc.setIsReturn(true);
127 for (int i = 0; i < parameters.length; i++) {
128 addParameter(parameters[i]);
129 }
130 }
131
132 /**
133 * Return the operation's name
134 */
135 public String getName() {
136 return name;
137 }
138
139 /**
140 * Set the operation's name
141 */
142 public void setName(String name) {
143 this.name = name;
144 }
145
146 /**
147 * get the documentation for the operation
148 */
149 public String getDocumentation() {
150 return documentation;
151 }
152
153 /**
154 * set the documentation for the operation
155 */
156 public void setDocumentation(String documentation) {
157 this.documentation = documentation;
158 }
159
160 public QName getReturnQName() {
161 return returnDesc.getQName();
162 }
163
164 public void setReturnQName(QName returnQName) {
165 returnDesc.setQName(returnQName);
166 }
167
168 public QName getReturnType() {
169 return returnDesc.getTypeQName();
170 }
171
172 public void setReturnType(QName returnType) {
173 log.debug("@" + Integer.toHexString(hashCode()) + "setReturnType(" + returnType +")");
174 returnDesc.setTypeQName(returnType);
175 }
176
177 public Class getReturnClass() {
178 return returnDesc.getJavaType();
179 }
180
181 public void setReturnClass(Class returnClass) {
182 returnDesc.setJavaType(returnClass);
183 }
184
185 public QName getElementQName() {
186 return elementQName;
187 }
188
189 public void setElementQName(QName elementQName) {
190 this.elementQName = elementQName;
191 }
192
193 public ServiceDesc getParent() {
194 return parent;
195 }
196
197 public void setParent(ServiceDesc parent) {
198 this.parent = parent;
199 }
200
201 public String getSoapAction() {
202 return soapAction;
203 }
204
205 public void setSoapAction(String soapAction) {
206 this.soapAction = soapAction;
207 }
208
209 public void setStyle(Style style)
210 {
211 this.style = style;
212 }
213
214 /**
215 * Return the style of the operation, defaulting to the parent
216 * ServiceDesc's style if we don't have one explicitly set.
217 */
218 public Style getStyle()
219 {
220 if (style == null) {
221 if (parent != null) {
222 return parent.getStyle();
223 }
224 return Style.DEFAULT; // Default
225 }
226
227 return style;
228 }
229
230 public void setUse(Use use)
231 {
232 this.use = use;
233 }
234
235 /**
236 * Return the use of the operation, defaulting to the parent
237 * ServiceDesc's use if we don't have one explicitly set.
238 */
239 public Use getUse()
240 {
241 if (use == null) {
242 if (parent != null) {
243 return parent.getUse();
244 }
245 return Use.DEFAULT; // Default
246 }
247
248 return use;
249 }
250
251 public void addParameter(ParameterDesc param)
252 {
253 // Should we enforce adding INs then INOUTs then OUTs?
254
255 param.setOrder(getNumParams());
256 parameters.add(param);
257 if ((param.getMode() == ParameterDesc.IN) ||
258 (param.getMode() == ParameterDesc.INOUT)) {
259 numInParams++;
260 }
261 if ((param.getMode() == ParameterDesc.OUT) ||
262 (param.getMode() == ParameterDesc.INOUT)) {
263 numOutParams++;
264 }
265 log.debug("@" + Integer.toHexString(hashCode()) + " added parameter >" + param + "@" + Integer.toHexString(param.hashCode()) + "<total parameters:" +getNumParams());
266 }
267
268 public void addParameter(QName paramName,
269 QName xmlType,
270 Class javaType,
271 byte parameterMode,
272 boolean inHeader,
273 boolean outHeader) {
274 ParameterDesc param =
275 new ParameterDesc(paramName, parameterMode, xmlType,
276 javaType, inHeader, outHeader);
277 addParameter(param);
278 }
279
280 public ParameterDesc getParameter(int i)
281 {
282 if (parameters.size() <= i)
283 return null;
284
285 return (ParameterDesc)parameters.get(i);
286 }
287
288 public ArrayList getParameters() {
289 return parameters;
290 }
291
292 /**
293 * Set the parameters wholesale.
294 *
295 * @param newParameters an ArrayList of ParameterDescs
296 */
297 public void setParameters(ArrayList newParameters) {
298 parameters = new ArrayList(); //Keep numInParams correct.
299 numInParams = 0;
300 numOutParams = 0;
301
302 for( java.util.ListIterator li= newParameters.listIterator();
303 li.hasNext(); ){
304 addParameter((ParameterDesc) li.next());
305 }
306 }
307
308 public int getNumInParams() {
309 return numInParams;
310 }
311
312 public int getNumOutParams() {
313 return numOutParams;
314 }
315
316 public int getNumParams() {
317 return parameters.size();
318 }
319
320 public Method getMethod() {
321 return method;
322 }
323
324 public void setMethod(Method method) {
325 this.method = method;
326 }
327
328 /**
329 * Is the return value in the header of the response message?
330 */
331 public boolean isReturnHeader() {
332 return returnDesc.isOutHeader();
333 }
334
335 /**
336 * Set whether the return value is in the response message.
337 */
338 public void setReturnHeader(boolean value) {
339 returnDesc.setOutHeader(value);
340 }
341
342 public ParameterDesc getParamByQName(QName qname)
343 {
344 for (Iterator i = parameters.iterator(); i.hasNext();) {
345 ParameterDesc param = (ParameterDesc) i.next();
346 if (param.getQName().equals(qname))
347 return param;
348 }
349
350 return null;
351 }
352
353 public ParameterDesc getInputParamByQName(QName qname)
354 {
355 ParameterDesc param = null;
356
357 param = getParamByQName(qname);
358
359 if ((param == null) || (param.getMode() == ParameterDesc.OUT)) {
360 param = null;
361 }
362
363 return param;
364 }
365
366 public ParameterDesc getOutputParamByQName(QName qname)
367 {
368 ParameterDesc param = null;
369
370 for (Iterator i = parameters.iterator(); i.hasNext();) {
371 ParameterDesc pnext = (ParameterDesc)i.next();
372 if (pnext.getQName().equals(qname) &&
373 pnext.getMode() != ParameterDesc.IN) {
374 param = pnext;
375 break;
376 }
377 }
378
379 if (param == null) {
380 if (null == returnDesc.getQName() ){
381 param= new ParameterDesc( returnDesc); //Create copy
382 param.setQName(qname);
383 }
384 else if ( qname.equals(returnDesc.getQName())) {
385 param = returnDesc;
386 }
387 }
388
389 return param;
390 }
391
392 /**
393 * Return a list of ALL "in" params (including INOUTs)
394 *
395 * Note: if we were sure the order went IN->INOUT->OUT, we could optimize
396 * this.
397 *
398 * @return
399 */
400 public ArrayList getAllInParams() {
401 ArrayList result = new ArrayList();
402 for (Iterator i = parameters.iterator(); i.hasNext();) {
403 ParameterDesc desc = (ParameterDesc) i.next();
404 if (desc.getMode() != ParameterDesc.OUT) {
405 result.add(desc);
406 }
407 }
408 return result;
409 }
410
411 /**
412 * Return a list of ALL "out" params (including INOUTs)
413 *
414 * Note: if we were sure the order went IN->INOUT->OUT, we could optimize
415 * this.
416 *
417 * @return
418 */
419 public ArrayList getAllOutParams() {
420 ArrayList result = new ArrayList();
421 for (Iterator i = parameters.iterator(); i.hasNext();) {
422 ParameterDesc desc = (ParameterDesc) i.next();
423 if (desc.getMode() != ParameterDesc.IN) {
424 result.add(desc);
425 }
426 }
427 return result;
428 }
429 /**
430 * Returns an ordered list of out params (NOT inouts)
431 */
432 public ArrayList getOutParams() {
433 ArrayList result = new ArrayList();
434 for (Iterator i = parameters.iterator(); i.hasNext();) {
435 ParameterDesc desc = (ParameterDesc) i.next();
436 if (desc.getMode() == ParameterDesc.OUT) {
437 result.add(desc);
438 }
439 }
440 return result;
441 }
442
443 public void addFault(FaultDesc fault)
444 {
445 if (faults == null)
446 faults = new ArrayList();
447 faults.add(fault);
448 }
449
450 public ArrayList getFaults()
451 {
452 return faults;
453 }
454
455 /**
456 * Returns the FaultDesc for the fault class given.
457 * Returns null if not found.
458 */
459 public FaultDesc getFaultByClass(Class cls) {
460 if (faults == null || cls == null) {
461 return null;
462 }
463
464 while (cls != null) {
465 // Check each class in the inheritance hierarchy, stopping at
466 // java.* or javax.* classes.
467
468 for (Iterator iterator = faults.iterator(); iterator.hasNext();) {
469 FaultDesc desc = (FaultDesc) iterator.next();
470 if (cls.getName().equals(desc.getClassName())) {
471 return desc;
472 }
473 }
474
475 cls = cls.getSuperclass();
476 if (cls != null && (cls.getName().startsWith("java.") ||
477 cls.getName().startsWith("javax."))) {
478 cls = null;
479 }
480 }
481
482 return null;
483 }
484
485 /**
486 * Returns the FaultDesc for the fault class given.
487 * Returns null if not found.
488 */
489 public FaultDesc getFaultByClass(Class cls, boolean checkParents) {
490 if (checkParents) {
491 return getFaultByClass(cls);
492 }
493
494 if (faults == null || cls == null) {
495 return null;
496 }
497
498 for (Iterator iterator = faults.iterator(); iterator.hasNext();) {
499 FaultDesc desc = (FaultDesc) iterator.next();
500 if (cls.getName().equals(desc.getClassName())) {
501 return desc;
502 }
503 }
504
505 return null;
506 }
507
508 /**
509 * Returns the FaultDesc for a QName (which is typically found
510 * in the details element of a SOAP fault).
511 * Returns null if not found.
512 */
513 public FaultDesc getFaultByQName(QName qname) {
514 if (faults != null) {
515 for (Iterator iterator = faults.iterator(); iterator.hasNext();) {
516 FaultDesc desc = (FaultDesc) iterator.next();
517 if (qname.equals(desc.getQName())) {
518 return desc;
519 }
520 }
521 }
522 return null;
523 }
524 /**
525 * Returns the FaultDesc for an XMLType.
526 * Returns null if not found.
527 */
528 public FaultDesc getFaultByXmlType(QName xmlType) {
529 if (faults != null) {
530 for (Iterator iterator = faults.iterator(); iterator.hasNext();) {
531 FaultDesc desc = (FaultDesc) iterator.next();
532 if (xmlType.equals(desc.getXmlType())) {
533 return desc;
534 }
535 }
536 }
537 return null;
538 }
539 public ParameterDesc getReturnParamDesc() {
540 return returnDesc;
541 }
542
543 public String toString() {
544 return toString("");
545 }
546 public String toString(String indent) {
547 String text ="";
548 text+=indent+"name: " + getName() + "\n";
549 text+=indent+"returnQName: " + getReturnQName() + "\n";
550 text+=indent+"returnType: " + getReturnType() + "\n";
551 text+=indent+"returnClass: " + getReturnClass() + "\n";
552 text+=indent+"elementQName:" + getElementQName() + "\n";
553 text+=indent+"soapAction: " + getSoapAction() + "\n";
554 text+=indent+"style: " + getStyle().getName() + "\n";
555 text+=indent+"use: " + getUse().getName() + "\n";
556 text+=indent+"numInParams: " + getNumInParams() + "\n";
557 text+=indent+"method:" + getMethod() + "\n";
558 for (int i=0; i<parameters.size(); i++) {
559 text+=indent+" ParameterDesc[" + i + "]:\n";
560 text+=indent+ ((ParameterDesc)parameters.get(i)).toString(" ") + "\n";
561 }
562 if (faults != null) {
563 for (int i=0; i<faults.size(); i++) {
564 text+=indent+" FaultDesc[" + i + "]:\n";
565 text+=indent+ ((FaultDesc)faults.get(i)).toString(" ") + "\n";
566 }
567 }
568 return text;
569 }
570
571 public int getMessageOperationStyle() {
572 return messageOperationStyle;
573 }
574
575 public void setMessageOperationStyle(int messageOperationStyle) {
576 this.messageOperationStyle = messageOperationStyle;
577 }
578
579 public OperationType getMep() {
580 return mep;
581 }
582
583 public void setMep(OperationType mep) {
584 this.mep = mep;
585 }
586
587 /**
588 * Set the MEP using a string like "request-response"
589 * @param mepString
590 */
591 public void setMep(String mepString) {
592 OperationType newMep = (OperationType)mepStrings.get(mepString);
593 if (newMep != null) {
594 mep = newMep;
595 }
596 }
597
598 private void writeObject(java.io.ObjectOutputStream out) throws IOException {
599 out.defaultWriteObject();
600 if (method != null){
601 out.writeObject(method.getDeclaringClass());
602 out.writeObject(method.getName());
603 out.writeObject(method.getParameterTypes());
604 } else {
605 out.writeObject(null);
606 }
607 }
608
609 private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException{
610 in.defaultReadObject();
611 Class clazz = (Class) in.readObject();
612 if (clazz != null){
613 String methodName = (String) in.readObject();
614 Class[] parameterTypes = (Class[]) in.readObject();
615 try {
616 method = clazz.getMethod(methodName, parameterTypes);
617 } catch (NoSuchMethodException e) {
618 throw new IOException("Unable to deserialize the operation's method: "+ methodName);
619 }
620 }
621 }
622 }
623