jaxbAnnotation = collectJAXBAnnotations(method, paramIndex);
aoqi@0: processXmlElement(jaxbAnnotation, paramName, paramNamespace, paramType);
aoqi@0: A member = factory.createWrapperBeanMember(paramType,
aoqi@0: getPropertyName(paramName), jaxbAnnotation);
aoqi@0: responseMembers.add(member);
aoqi@0: }
aoqi@0:
aoqi@0: return responseMembers;
aoqi@0: }
aoqi@0:
aoqi@0: private void processXmlElement(List jaxb, String elemName, String elemNS, T type) {
aoqi@0: XmlElement elemAnn = null;
aoqi@0: for (Annotation a : jaxb) {
aoqi@0: if (a.annotationType() == XmlElement.class) {
aoqi@0: elemAnn = (XmlElement) a;
aoqi@0: jaxb.remove(a);
aoqi@0: break;
aoqi@0: }
aoqi@0: }
aoqi@0: String name = (elemAnn != null && !elemAnn.name().equals("##default"))
aoqi@0: ? elemAnn.name() : elemName;
aoqi@0:
aoqi@0: String ns = (elemAnn != null && !elemAnn.namespace().equals("##default"))
aoqi@0: ? elemAnn.namespace() : elemNS;
aoqi@0:
aoqi@0: boolean nillable = nav.isArray(type)
aoqi@0: || (elemAnn != null && elemAnn.nillable());
aoqi@0:
aoqi@0: boolean required = elemAnn != null && elemAnn.required();
aoqi@0: XmlElementHandler handler = new XmlElementHandler(name, ns, nillable, required);
aoqi@0: XmlElement elem = (XmlElement) Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class>[]{XmlElement.class}, handler);
aoqi@0: jaxb.add(elem);
aoqi@0: }
aoqi@0:
aoqi@0:
aoqi@0: private static class XmlElementHandler implements InvocationHandler {
aoqi@0: private String name;
aoqi@0: private String namespace;
aoqi@0: private boolean nillable;
aoqi@0: private boolean required;
aoqi@0:
aoqi@0: XmlElementHandler(String name, String namespace, boolean nillable,
aoqi@0: boolean required) {
aoqi@0: this.name = name;
aoqi@0: this.namespace = namespace;
aoqi@0: this.nillable = nillable;
aoqi@0: this.required = required;
aoqi@0: }
aoqi@0:
aoqi@0: public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
aoqi@0: String methodName = method.getName();
aoqi@0: if (methodName.equals("name")) {
aoqi@0: return name;
aoqi@0: } else if (methodName.equals("namespace")) {
aoqi@0: return namespace;
aoqi@0: } else if (methodName.equals("nillable")) {
aoqi@0: return nillable;
aoqi@0: } else if (methodName.equals("required")) {
aoqi@0: return required;
aoqi@0: } else {
aoqi@0: throw new WebServiceException("Not handling "+methodName);
aoqi@0: }
aoqi@0: }
aoqi@0: }
aoqi@0:
aoqi@0: /**
aoqi@0: * Computes and sorts exception bean members for a given exception as per
aoqi@0: * the 3.7 section of the spec. It takes all getter properties in the
aoqi@0: * exception and its superclasses(except getCause, getLocalizedMessage,
aoqi@0: * getStackTrace, getClass). The returned collection is sorted based
aoqi@0: * on the property names.
aoqi@0: *
aoqi@0: *
aoqi@0: * But if the exception has @XmlType its values are honored. Only the
aoqi@0: * propOrder properties are considered. The returned collection is sorted
aoqi@0: * as per the given propOrder.
aoqi@0: *
aoqi@0: * @param exception
aoqi@0: * @return list of properties in the correct order for an exception bean
aoqi@0: */
aoqi@0: public Collection collectExceptionBeanMembers(C exception) {
aoqi@0: return collectExceptionBeanMembers(exception, true);
aoqi@0: }
aoqi@0:
aoqi@0: /**
aoqi@0: * Computes and sorts exception bean members for a given exception as per
aoqi@0: * the 3.7 section of the spec. It takes all getter properties in the
aoqi@0: * exception and its superclasses(except getCause, getLocalizedMessage,
aoqi@0: * getStackTrace, getClass). The returned collection is sorted based
aoqi@0: * on the property names.
aoqi@0: *
aoqi@0: *
aoqi@0: * But if the exception has @XmlType its values are honored. Only the
aoqi@0: * propOrder properties are considered. The returned collection is sorted
aoqi@0: * as per the given propOrder.
aoqi@0: *
aoqi@0: * @param exception
aoqi@0: * @param decapitalize if true, all the property names are decapitalized
aoqi@0: *
aoqi@0: * @return list of properties in the correct order for an exception bean
aoqi@0: */
aoqi@0: public Collection collectExceptionBeanMembers(C exception, boolean decapitalize ) {
aoqi@0: TreeMap fields = new TreeMap();
aoqi@0: getExceptionProperties(exception, fields, decapitalize);
aoqi@0:
aoqi@0: // Consider only the @XmlType(propOrder) properties
aoqi@0: XmlType xmlType = annReader.getClassAnnotation(XmlType.class, exception, null);
aoqi@0: if (xmlType != null) {
aoqi@0: String[] propOrder = xmlType.propOrder();
aoqi@0: // If not the default order of properties, use that propOrder
aoqi@0: if (propOrder.length > 0 && propOrder[0].length() != 0) {
aoqi@0: List list = new ArrayList();
aoqi@0: for(String prop : propOrder) {
aoqi@0: A a = fields.get(prop);
aoqi@0: if (a != null) {
aoqi@0: list.add(a);
aoqi@0: } else {
aoqi@0: throw new WebServiceException("Exception "+exception+
aoqi@0: " has @XmlType and its propOrder contains unknown property "+prop);
aoqi@0: }
aoqi@0: }
aoqi@0: return list;
aoqi@0: }
aoqi@0: }
aoqi@0:
aoqi@0: return fields.values();
aoqi@0: }
aoqi@0:
aoqi@0:
aoqi@0: private void getExceptionProperties(C exception, TreeMap fields, boolean decapitalize) {
aoqi@0: C sc = nav.getSuperClass(exception);
aoqi@0: if (sc != null) {
aoqi@0: getExceptionProperties(sc, fields, decapitalize);
aoqi@0: }
aoqi@0: Collection extends M> methods = nav.getDeclaredMethods(exception);
aoqi@0:
aoqi@0: for (M method : methods) {
aoqi@0:
aoqi@0: // 2.1.x is doing the following: no final static, transient, non-public
aoqi@0: // transient cannot used as modifier for method, so not doing it now
aoqi@0: if (!nav.isPublicMethod(method)
aoqi@0: || (nav.isStaticMethod(method) && nav.isFinalMethod(method))) {
aoqi@0: continue;
aoqi@0: }
aoqi@0:
aoqi@0: if (!nav.isPublicMethod(method)) {
aoqi@0: continue;
aoqi@0: }
aoqi@0:
aoqi@0: String name = nav.getMethodName(method);
aoqi@0:
aoqi@0: if (!(name.startsWith("get") || name.startsWith("is")) || skipProperties.contains(name) ||
aoqi@0: name.equals("get") || name.equals("is")) {
aoqi@0: // Don't bother with invalid propertyNames.
aoqi@0: continue;
aoqi@0: }
aoqi@0:
aoqi@0: T returnType = getSafeType(nav.getReturnType(method));
aoqi@0: if (nav.getMethodParameters(method).length == 0) {
aoqi@0: String fieldName = name.startsWith("get") ? name.substring(3) : name.substring(2);
aoqi@0: if (decapitalize) fieldName = StringUtils.decapitalize(fieldName);
aoqi@0: fields.put(fieldName, factory.createWrapperBeanMember(returnType, fieldName, Collections.emptyList()));
aoqi@0: }
aoqi@0: }
aoqi@0:
aoqi@0: }
aoqi@0:
aoqi@0: /**
aoqi@0: * Gets the property name by mangling using JAX-WS rules
aoqi@0: * @param name to be mangled
aoqi@0: * @return property name
aoqi@0: */
aoqi@0: private static String getPropertyName(String name) {
aoqi@0: String propertyName = BindingHelper.mangleNameToVariableName(name);
aoqi@0: //We wont have to do this if JAXBRIContext.mangleNameToVariableName() takes
aoqi@0: //care of mangling java identifiers
aoqi@0: return getJavaReservedVarialbeName(propertyName);
aoqi@0: }
aoqi@0:
aoqi@0:
aoqi@0: //TODO MOVE Names.java to runtime (instead of doing the following)
aoqi@0: /*
aoqi@0: * See if its a java keyword name, if so then mangle the name
aoqi@0: */
aoqi@0: private static @NotNull String getJavaReservedVarialbeName(@NotNull String name) {
aoqi@0: String reservedName = reservedWords.get(name);
aoqi@0: return reservedName == null ? name : reservedName;
aoqi@0: }
aoqi@0:
aoqi@0: private static final Map reservedWords;
aoqi@0:
aoqi@0: static {
aoqi@0: reservedWords = new HashMap();
aoqi@0: reservedWords.put("abstract", "_abstract");
aoqi@0: reservedWords.put("assert", "_assert");
aoqi@0: reservedWords.put("boolean", "_boolean");
aoqi@0: reservedWords.put("break", "_break");
aoqi@0: reservedWords.put("byte", "_byte");
aoqi@0: reservedWords.put("case", "_case");
aoqi@0: reservedWords.put("catch", "_catch");
aoqi@0: reservedWords.put("char", "_char");
aoqi@0: reservedWords.put("class", "_class");
aoqi@0: reservedWords.put("const", "_const");
aoqi@0: reservedWords.put("continue", "_continue");
aoqi@0: reservedWords.put("default", "_default");
aoqi@0: reservedWords.put("do", "_do");
aoqi@0: reservedWords.put("double", "_double");
aoqi@0: reservedWords.put("else", "_else");
aoqi@0: reservedWords.put("extends", "_extends");
aoqi@0: reservedWords.put("false", "_false");
aoqi@0: reservedWords.put("final", "_final");
aoqi@0: reservedWords.put("finally", "_finally");
aoqi@0: reservedWords.put("float", "_float");
aoqi@0: reservedWords.put("for", "_for");
aoqi@0: reservedWords.put("goto", "_goto");
aoqi@0: reservedWords.put("if", "_if");
aoqi@0: reservedWords.put("implements", "_implements");
aoqi@0: reservedWords.put("import", "_import");
aoqi@0: reservedWords.put("instanceof", "_instanceof");
aoqi@0: reservedWords.put("int", "_int");
aoqi@0: reservedWords.put("interface", "_interface");
aoqi@0: reservedWords.put("long", "_long");
aoqi@0: reservedWords.put("native", "_native");
aoqi@0: reservedWords.put("new", "_new");
aoqi@0: reservedWords.put("null", "_null");
aoqi@0: reservedWords.put("package", "_package");
aoqi@0: reservedWords.put("private", "_private");
aoqi@0: reservedWords.put("protected", "_protected");
aoqi@0: reservedWords.put("public", "_public");
aoqi@0: reservedWords.put("return", "_return");
aoqi@0: reservedWords.put("short", "_short");
aoqi@0: reservedWords.put("static", "_static");
aoqi@0: reservedWords.put("strictfp", "_strictfp");
aoqi@0: reservedWords.put("super", "_super");
aoqi@0: reservedWords.put("switch", "_switch");
aoqi@0: reservedWords.put("synchronized", "_synchronized");
aoqi@0: reservedWords.put("this", "_this");
aoqi@0: reservedWords.put("throw", "_throw");
aoqi@0: reservedWords.put("throws", "_throws");
aoqi@0: reservedWords.put("transient", "_transient");
aoqi@0: reservedWords.put("true", "_true");
aoqi@0: reservedWords.put("try", "_try");
aoqi@0: reservedWords.put("void", "_void");
aoqi@0: reservedWords.put("volatile", "_volatile");
aoqi@0: reservedWords.put("while", "_while");
aoqi@0: reservedWords.put("enum", "_enum");
aoqi@0: }
aoqi@0:
aoqi@0: }