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