001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */
019: package org.apache.axis2.description.java2wsdl;
020:
021: import org.apache.axis2.AxisFault;
022: import org.apache.axis2.deployment.util.Utils;
023: import org.apache.axis2.description.AxisMessage;
024: import org.apache.axis2.description.AxisOperation;
025: import org.apache.axis2.description.AxisService;
026: import org.apache.axis2.description.WSDL2Constants;
027: import org.apache.axis2.wsdl.WSDLConstants;
028: import org.apache.commons.logging.Log;
029: import org.apache.commons.logging.LogFactory;
030: import org.apache.ws.commons.schema.*;
031: import org.apache.ws.commons.schema.utils.NamespaceMap;
032: import org.codehaus.jam.*;
033:
034: import javax.xml.namespace.QName;
035: import java.util.*;
036:
037: public class DocLitBareSchemaGenerator extends DefaultSchemaGenerator {
038:
039: private static final Log log = LogFactory
040: .getLog(DocLitBareSchemaGenerator.class);
041: private HashMap processedParameters = new HashMap();
042:
043: public DocLitBareSchemaGenerator(ClassLoader loader,
044: String className, String schematargetNamespace,
045: String schematargetNamespacePrefix, AxisService service)
046: throws Exception {
047: super (loader, className, schematargetNamespace,
048: schematargetNamespacePrefix, service);
049: }
050:
051: protected JMethod[] processMethods(JMethod[] declaredMethods)
052: throws Exception {
053: ArrayList list = new ArrayList();
054: //short the elements in the array
055: Arrays.sort(declaredMethods);
056:
057: // since we do not support overload
058: HashMap uniqueMethods = new HashMap();
059: XmlSchemaComplexType methodSchemaType;
060: XmlSchemaSequence sequence;
061:
062: for (int i = 0; i < declaredMethods.length; i++) {
063: JMethod jMethod = declaredMethods[i];
064: JAnnotation methodAnnon = jMethod
065: .getAnnotation(AnnotationConstants.WEB_METHOD);
066: if (methodAnnon != null) {
067: if (methodAnnon.getValue(AnnotationConstants.EXCLUDE)
068: .asBoolean()) {
069: continue;
070: }
071: }
072: String methodName = getSimpleName(jMethod);
073: // no need to think abt this method , since that is system
074: // config method
075: if (excludeMethods.contains(getSimpleName(jMethod))) {
076: continue;
077: }
078:
079: if (uniqueMethods.get(getSimpleName(jMethod)) != null) {
080: log
081: .warn("We don't support method overloading. Ignoring ["
082: + jMethod.getQualifiedName() + "]");
083: continue;
084: }
085:
086: if (!jMethod.isPublic()) {
087: // no need to generate Schema for non public methods
088: continue;
089: }
090:
091: boolean addToService = false;
092: AxisOperation axisOperation = service
093: .getOperation(new QName(methodName));
094: if (axisOperation == null) {
095: axisOperation = Utils
096: .getAxisOperationForJmethod(jMethod);
097: if (WSDL2Constants.MEP_URI_ROBUST_IN_ONLY
098: .equals(axisOperation
099: .getMessageExchangePattern())) {
100: AxisMessage outMessage = axisOperation
101: .getMessage(WSDLConstants.MESSAGE_LABEL_OUT_VALUE);
102: if (outMessage != null) {
103: outMessage.setName(methodName + RESULT);
104: }
105: }
106: addToService = true;
107: }
108:
109: // Maintain a list of methods we actually work with
110: list.add(jMethod);
111: processException(jMethod, axisOperation);
112: uniqueMethods.put(getSimpleName(jMethod), jMethod);
113: //create the schema type for the method wrapper
114:
115: uniqueMethods.put(getSimpleName(jMethod), jMethod);
116: JParameter[] paras = jMethod.getParameters();
117: String parameterNames[] = methodTable
118: .getParameterNames(methodName);
119: AxisMessage inMessage = axisOperation
120: .getMessage(WSDLConstants.MESSAGE_LABEL_IN_VALUE);
121: if (inMessage != null) {
122: inMessage.setName(methodName + "RequestMessage");
123: }
124: if (paras.length > 1) {
125: sequence = new XmlSchemaSequence();
126: methodSchemaType = createSchemaTypeForMethodPart(getSimpleName(jMethod));
127: methodSchemaType.setParticle(sequence);
128: inMessage.setElementQName(typeTable
129: .getQNamefortheType(methodName));
130: service.addMessageElementQNameToOperationMapping(
131: methodSchemaType.getQName(), axisOperation);
132: inMessage.setPartName(methodName);
133: for (int j = 0; j < paras.length; j++) {
134: JParameter methodParameter = paras[j];
135: if (generateRequestSchema(methodParameter,
136: parameterNames, j, jMethod, sequence)) {
137: break;
138: }
139: }
140: } else if (paras.length == 1) {
141: if (paras[0].getType().isArrayType()) {
142: sequence = new XmlSchemaSequence();
143:
144: methodSchemaType = createSchemaTypeForMethodPart(methodName);
145: methodSchemaType.setParticle(sequence);
146: JParameter methodParameter = paras[0];
147: inMessage.setElementQName(typeTable
148: .getQNamefortheType(methodName));
149: service.addMessageElementQNameToOperationMapping(
150: methodSchemaType.getQName(), axisOperation);
151: inMessage.setPartName(methodName);
152: if (generateRequestSchema(methodParameter,
153: parameterNames, 0, jMethod, sequence)) {
154: break;
155: }
156: } else {
157: String parameterName = null;
158: JParameter methodParameter = paras[0];
159: JAnnotation paramterAnnon = methodParameter
160: .getAnnotation(AnnotationConstants.WEB_PARAM);
161: if (paramterAnnon != null) {
162: parameterName = paramterAnnon.getValue(
163: AnnotationConstants.NAME).asString();
164: }
165: if (parameterName == null
166: || "".equals(parameterName)) {
167: parameterName = (parameterNames != null && parameterNames[0] != null) ? parameterNames[0]
168: : getSimpleName(methodParameter);
169: }
170: JMethod processMethod = (JMethod) processedParameters
171: .get(parameterName);
172: if (processMethod != null) {
173: throw new AxisFault(
174: "Inavalid Java class,"
175: + " there are two methods ["
176: + processMethod.getSimpleName()
177: + " and "
178: + jMethod.getSimpleName()
179: + " ]which have the same parameter names");
180: } else {
181: processedParameters.put(parameterName, jMethod);
182: generateSchemaForType(null, paras[0].getType(),
183: parameterName);
184: inMessage.setElementQName(typeTable
185: .getQNamefortheType(parameterName));
186: inMessage.setPartName(parameterName);
187: inMessage.setWrapped(false);
188: service
189: .addMessageElementQNameToOperationMapping(
190: typeTable
191: .getQNamefortheType(parameterName),
192: axisOperation);
193: }
194: }
195: }
196:
197: // for its return type
198: JClass returnType = jMethod.getReturnType();
199:
200: if (!returnType.isVoidType()) {
201: AxisMessage outMessage = axisOperation
202: .getMessage(WSDLConstants.MESSAGE_LABEL_OUT_VALUE);
203: if (returnType.isArrayType()) {
204: methodSchemaType = createSchemaTypeForMethodPart(getSimpleName(jMethod)
205: + RESULT);
206: sequence = new XmlSchemaSequence();
207: methodSchemaType.setParticle(sequence);
208: JAnnotation returnAnnon = jMethod
209: .getAnnotation(AnnotationConstants.WEB_RESULT);
210: String returnName = "return";
211: if (returnAnnon != null) {
212: returnName = returnAnnon.getValue(
213: AnnotationConstants.NAME).asString();
214: if (returnName != null
215: && !"".equals(returnName)) {
216: returnName = "return";
217: }
218: }
219: if (nonRpcMethods.contains(methodName)) {
220: generateSchemaForType(sequence, null,
221: returnName);
222: } else {
223: generateSchemaForType(sequence, returnType,
224: returnName);
225: }
226: } else {
227: generateSchemaForType(null, returnType, methodName
228: + RESULT);
229: outMessage.setWrapped(false);
230: }
231: outMessage.setElementQName(typeTable
232: .getQNamefortheType(methodName + RESULT));
233: outMessage.setName(methodName + "ResponseMessage");
234: outMessage.setPartName(methodName + RESULT);
235: service.addMessageElementQNameToOperationMapping(
236: typeTable.getQNamefortheType(methodName
237: + RESULT), axisOperation);
238: }
239: if (addToService) {
240: service.addOperation(axisOperation);
241: }
242: }
243: return (JMethod[]) list.toArray(new JMethod[list.size()]);
244: }
245:
246: private boolean generateRequestSchema(JParameter methodParameter,
247: String[] parameterNames, int j, JMethod jMethod,
248: XmlSchemaSequence sequence) throws Exception {
249: String parameterName = null;
250: JAnnotation paramterAnnon = methodParameter
251: .getAnnotation(AnnotationConstants.WEB_PARAM);
252: if (paramterAnnon != null) {
253: parameterName = paramterAnnon.getValue(
254: AnnotationConstants.NAME).asString();
255: }
256: if (parameterName == null || "".equals(parameterName)) {
257: parameterName = (parameterNames != null && parameterNames[j] != null) ? parameterNames[j]
258: : getSimpleName(methodParameter);
259: }
260: JClass paraType = methodParameter.getType();
261: if (nonRpcMethods.contains(getSimpleName(jMethod))) {
262: generateSchemaForType(sequence, null,
263: getSimpleName(jMethod));
264: return true;
265: } else {
266: generateSchemaForType(sequence, paraType, parameterName);
267: }
268: return false;
269: }
270:
271: private QName generateSchemaForType(XmlSchemaSequence sequence,
272: JClass type, String partName) throws Exception {
273:
274: boolean isArrayType = false;
275: if (type != null) {
276: isArrayType = type.isArrayType();
277: }
278: if (isArrayType) {
279: type = type.getArrayComponentType();
280: }
281: if (AxisFault.class.getName().equals(type)) {
282: return null;
283: }
284: String classTypeName;
285: if (type == null) {
286: classTypeName = "java.lang.Object";
287: } else {
288: classTypeName = getQualifiedName(type);
289: }
290: if (isArrayType && "byte".equals(classTypeName)) {
291: classTypeName = "base64Binary";
292: isArrayType = false;
293: }
294: if (isDataHandler(type)) {
295: classTypeName = "base64Binary";
296: }
297: QName schemaTypeName = typeTable
298: .getSimpleSchemaTypeName(classTypeName);
299: if (schemaTypeName == null && type != null) {
300: schemaTypeName = generateSchema(type);
301: addContentToMethodSchemaType(sequence, schemaTypeName,
302: partName, isArrayType);
303: String schemaNamespace = resolveSchemaNamespace(getQualifiedName(type
304: .getContainingPackage()));
305: addImport(getXmlSchema(schemaNamespace), schemaTypeName);
306: if (sequence == null) {
307: generateSchemaForSingleElement(schemaTypeName,
308: partName, isArrayType, type);
309: }
310: } else {
311: if (sequence == null) {
312: generateSchemaForSingleElement(schemaTypeName,
313: partName, isArrayType, type);
314: } else {
315: addContentToMethodSchemaType(sequence, schemaTypeName,
316: partName, isArrayType);
317: }
318: }
319:
320: return schemaTypeName;
321: }
322:
323: protected void generateSchemaForSingleElement(QName schemaTypeName,
324: String paraName, boolean isArray, JClass javaType)
325: throws Exception {
326: XmlSchemaElement elt1 = new XmlSchemaElement();
327: elt1.setName(paraName);
328: elt1.setSchemaTypeName(schemaTypeName);
329: elt1.setNillable(true);
330: QName elementName = new QName(schemaTargetNameSpace, paraName,
331: schema_namespace_prefix);
332: elt1.setQName(elementName);
333: XmlSchema xmlSchema = getXmlSchema(schemaTargetNameSpace);
334: xmlSchema.getElements().add(elementName, elt1);
335: xmlSchema.getItems().add(elt1);
336: typeTable.addComplexSchema(paraName, elementName);
337: }
338:
339: /**
340: * Generate schema construct for given type
341: *
342: * @param javaType
343: */
344: private QName generateSchema(JClass javaType) throws Exception {
345: String name = getQualifiedName(javaType);
346: QName schemaTypeName = typeTable.getComplexSchemaType(name);
347: if (schemaTypeName == null) {
348: String simpleName = getSimpleName(javaType);
349:
350: String packageName = getQualifiedName(javaType
351: .getContainingPackage());
352: String targetNameSpace = resolveSchemaNamespace(packageName);
353:
354: XmlSchema xmlSchema = getXmlSchema(targetNameSpace);
355: String targetNamespacePrefix = (String) targetNamespacePrefixMap
356: .get(targetNameSpace);
357: if (targetNamespacePrefix == null) {
358: targetNamespacePrefix = generatePrefix();
359: targetNamespacePrefixMap.put(targetNameSpace,
360: targetNamespacePrefix);
361: }
362:
363: XmlSchemaComplexType complexType = new XmlSchemaComplexType(
364: xmlSchema);
365: XmlSchemaSequence sequence = new XmlSchemaSequence();
366: XmlSchemaComplexContentExtension complexExtension = new XmlSchemaComplexContentExtension();
367:
368: XmlSchemaElement eltOuter = new XmlSchemaElement();
369: schemaTypeName = new QName(targetNameSpace, simpleName,
370: targetNamespacePrefix);
371: eltOuter.setName(simpleName);
372: eltOuter.setQName(schemaTypeName);
373:
374: JClass sup = javaType.getSuperclass();
375:
376: if ((sup != null)
377: && !("java.lang.Object".compareTo(sup
378: .getQualifiedName()) == 0)
379: && !("org.apache.axis2".compareTo(sup
380: .getContainingPackage().getQualifiedName()) == 0)) {
381: String super ClassName = sup.getQualifiedName();
382: String super classname = getSimpleName(sup);
383: String tgtNamespace;
384: String tgtNamespacepfx;
385: QName qName = typeTable
386: .getSimpleSchemaTypeName(super ClassName);
387: if (qName != null) {
388: tgtNamespace = qName.getNamespaceURI();
389: tgtNamespacepfx = qName.getPrefix();
390: } else {
391: tgtNamespace = resolveSchemaNamespace(sup
392: .getContainingPackage().getQualifiedName());
393: tgtNamespacepfx = (String) targetNamespacePrefixMap
394: .get(tgtNamespace);
395: QName super ClassQname = generateSchema(sup);
396: if (super ClassQname != null) {
397: tgtNamespacepfx = super ClassQname.getPrefix();
398: tgtNamespace = super ClassQname
399: .getNamespaceURI();
400: }
401: }
402:
403: if (tgtNamespacepfx == null) {
404: tgtNamespacepfx = generatePrefix();
405: targetNamespacePrefixMap.put(tgtNamespace,
406: tgtNamespacepfx);
407: }
408:
409: QName basetype = new QName(tgtNamespace,
410: super classname, tgtNamespacepfx);
411:
412: complexExtension.setBaseTypeName(basetype);
413: complexExtension.setParticle(sequence);
414:
415: XmlSchemaComplexContent contentModel = new XmlSchemaComplexContent();
416:
417: contentModel.setContent(complexExtension);
418:
419: complexType.setContentModel(contentModel);
420:
421: } else {
422: complexType.setParticle(sequence);
423: }
424:
425: complexType.setName(simpleName);
426:
427: // xmlSchema.getItems().add(eltOuter);
428: xmlSchema.getElements().add(schemaTypeName, eltOuter);
429: eltOuter.setSchemaTypeName(complexType.getQName());
430:
431: xmlSchema.getItems().add(complexType);
432: xmlSchema.getSchemaTypes().add(schemaTypeName, complexType);
433:
434: // adding this type to the table
435: typeTable.addComplexSchema(name, eltOuter.getQName());
436: // adding this type's package to the table, to support inheritance.
437: typeTable.addComplexSchema(javaType.getContainingPackage()
438: .getQualifiedName(), eltOuter.getQName());
439:
440: Set propertiesSet = new HashSet();
441: Set propertiesNames = new HashSet();
442:
443: JProperty[] tempProperties = javaType
444: .getDeclaredProperties();
445: for (int i = 0; i < tempProperties.length; i++) {
446: propertiesSet.add(tempProperties[i]);
447: }
448:
449: JProperty[] properties = (JProperty[]) propertiesSet
450: .toArray(new JProperty[0]);
451: Arrays.sort(properties);
452: for (int i = 0; i < properties.length; i++) {
453: JProperty property = properties[i];
454: boolean isArryType = property.getType().isArrayType();
455:
456: String propname = getCorrectName(property
457: .getSimpleName());
458:
459: propertiesNames.add(propname);
460:
461: this .generateSchemaforFieldsandProperties(xmlSchema,
462: sequence, property.getType(), propname,
463: isArryType);
464:
465: }
466:
467: JField[] tempFields = javaType.getDeclaredFields();
468: HashMap FieldMap = new HashMap();
469:
470: for (int i = 0; i < tempFields.length; i++) {
471: // create a element for the field only if it is public
472: // and there is no property with the same name
473:
474: if (tempFields[i].isPublic()) {
475:
476: // skip field with same name as a property
477: if (!propertiesNames.contains(tempFields[i]
478: .getSimpleName())) {
479:
480: FieldMap.put(tempFields[i].getSimpleName(),
481: tempFields[i]);
482: }
483: }
484:
485: }
486:
487: // remove fields from super classes patch for defect Annogen-21
488: // getDeclaredFields is incorrectly returning fields of super classes as well
489: // getDeclaredProperties used earlier works correctly
490: JClass supr = javaType.getSuperclass();
491: while (supr != null
492: && supr.getQualifiedName().compareTo(
493: "java.lang.Object") != 0) {
494: JField[] suprFields = supr.getFields();
495: for (int i = 0; i < suprFields.length; i++) {
496: FieldMap.remove(suprFields[i].getSimpleName());
497: }
498: supr = supr.getSuperclass();
499: }
500: // end patch for Annogen -21
501:
502: JField[] froperties = (JField[]) FieldMap.values().toArray(
503: new JField[0]);
504: Arrays.sort(froperties);
505:
506: for (int i = 0; i < froperties.length; i++) {
507: JField field = froperties[i];
508: boolean isArryType = field.getType().isArrayType();
509:
510: this .generateSchemaforFieldsandProperties(xmlSchema,
511: sequence, field.getType(), field
512: .getSimpleName(), isArryType);
513: }
514:
515: }
516: return schemaTypeName;
517: }
518:
519: private XmlSchemaComplexType createSchemaTypeForMethodPart(
520: String localPartName) {
521: XmlSchema xmlSchema = getXmlSchema(schemaTargetNameSpace);
522: QName elementName = new QName(this .schemaTargetNameSpace,
523: localPartName, this .schema_namespace_prefix);
524:
525: XmlSchemaComplexType complexType = getComplexTypeForElement(
526: xmlSchema, elementName);
527: if (complexType == null) {
528: complexType = new XmlSchemaComplexType(xmlSchema);
529:
530: XmlSchemaElement globalElement = new XmlSchemaElement();
531: globalElement.setSchemaType(complexType);
532: globalElement.setName(localPartName);
533: globalElement.setQName(elementName);
534: xmlSchema.getItems().add(globalElement);
535: xmlSchema.getElements().add(elementName, globalElement);
536: }
537: typeTable.addComplexSchema(localPartName, elementName);
538:
539: return complexType;
540: }
541:
542: private XmlSchema getXmlSchema(String targetNamespace) {
543: XmlSchema xmlSchema;
544:
545: if ((xmlSchema = (XmlSchema) schemaMap.get(targetNamespace)) == null) {
546: String targetNamespacePrefix;
547:
548: if (targetNamespace.equals(schemaTargetNameSpace)
549: && schema_namespace_prefix != null) {
550: targetNamespacePrefix = schema_namespace_prefix;
551: } else {
552: targetNamespacePrefix = generatePrefix();
553: }
554:
555: xmlSchema = new XmlSchema(targetNamespace,
556: xmlSchemaCollection);
557: xmlSchema
558: .setAttributeFormDefault(getAttrFormDefaultSetting());
559: xmlSchema
560: .setElementFormDefault(getElementFormDefaultSetting());
561:
562: targetNamespacePrefixMap.put(targetNamespace,
563: targetNamespacePrefix);
564: schemaMap.put(targetNamespace, xmlSchema);
565:
566: NamespaceMap prefixmap = new NamespaceMap();
567: prefixmap.put(DEFAULT_SCHEMA_NAMESPACE_PREFIX,
568: URI_2001_SCHEMA_XSD);
569: prefixmap.put(targetNamespacePrefix, targetNamespace);
570: xmlSchema.setNamespaceContext(prefixmap);
571: }
572: return xmlSchema;
573: }
574:
575: }
|