/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.axis2.jaxws.runtime.description.marshal.impl; import org.apache.axis2.jaxws.ExceptionFactory; import org.apache.axis2.jaxws.description.FaultDescription; import org.apache.axis2.jaxws.description.OperationDescription; import org.apache.axis2.jaxws.description.ServiceDescription; import org.apache.axis2.jaxws.message.factory.MessageFactory; import org.apache.axis2.jaxws.registry.FactoryRegistry; import org.apache.axis2.jaxws.runtime.description.marshal.AnnotationDesc; import org.apache.axis2.jaxws.runtime.description.marshal.FaultBeanDesc; import org.apache.axis2.jaxws.runtime.description.marshal.MarshalServiceRuntimeDescription; import org.apache.axis2.jaxws.runtime.description.marshal.impl.AnnotationDescImpl; import org.apache.axis2.jaxws.runtime.description.marshal.impl.MarshalServiceRuntimeDescriptionImpl; import org.apache.axis2.jaxws.utility.PropertyDescriptorPlus; import org.apache.axis2.jaxws.utility.XMLRootElementUtil; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.lang.reflect.Method; import java.util.Map; import java.util.Map.Entry; import java.util.TreeSet; import javax.xml.namespace.QName; public class MarshalServiceRuntimeDescriptionImpl implements MarshalServiceRuntimeDescription { private static final Log log = LogFactory.getLog(MarshalServiceRuntimeDescriptionImpl.class); private ServiceDescription serviceDesc; private String key; private TreeSet<String> packages; private String packagesKey; private Map<String, AnnotationDesc> annotationMap = null; private Map<Class, Map<String, PropertyDescriptorPlus>> pdMapCache = null; private Map<OperationDescription, String> requestWrapperMap = null; private Map<OperationDescription, String> responseWrapperMap = null; private Map<FaultDescription, FaultBeanDesc> faultBeanDescMap = null; private Map<OperationDescription, Method> methodMap = null; private MessageFactory messageFactory = (MessageFactory)FactoryRegistry.getFactory(MessageFactory.class); protected MarshalServiceRuntimeDescriptionImpl(String key, ServiceDescription serviceDesc) { if (log.isDebugEnabled()) { QName qName = (serviceDesc == null) ? null : serviceDesc.getServiceQName(); log.debug("Create MarshalServiceRuntimeDescriptionImpl for " + serviceDesc); } this.serviceDesc = serviceDesc; this.key = key; } public ServiceDescription getServiceDescription() { return serviceDesc; } public String getKey() { return key; } public TreeSet<String> getPackages() { return packages; } public String getPackagesKey() { return packagesKey; } void setPackages(TreeSet<String> packages) { this.packages = packages; this.packagesKey = getObjectIdentity(packages); // Unique key for searches } public AnnotationDesc getAnnotationDesc(Class cls) { if (log.isDebugEnabled()) { log.debug("getAnnotationDesc for class " + cls); } String className = cls.getCanonicalName(); AnnotationDesc aDesc = annotationMap.get(className); if (aDesc == null) { // Cache miss if (log.isDebugEnabled()) { log.debug("creating AnnotationDesc"); } aDesc = AnnotationDescImpl.create(cls); } if (log.isDebugEnabled()) { log.debug("getAnnotationDesc is " + aDesc); } return aDesc; } public AnnotationDesc getAnnotationDesc(String clsName) { if (log.isDebugEnabled()) { log.debug("getAnnotationDesc for " + clsName); } AnnotationDesc aDesc = annotationMap.get(clsName); if (log.isDebugEnabled()) { log.debug("getAnnotationDesc is " + aDesc); } return aDesc; } void setAnnotationMap(Map<String, AnnotationDesc> map) { this.annotationMap = map; } public Map<String, PropertyDescriptorPlus> getPropertyDescriptorMap(Class cls) { // We are caching by class. Map<String, PropertyDescriptorPlus> pdMap = pdMapCache.get(cls); if (pdMap != null) { // Cache hit return pdMap; } // Cache miss...this can occur if the classloader changed. // We cannot add this new pdMap at this point due to sync issues. try { pdMap = XMLRootElementUtil.createPropertyDescriptorMap(cls); } catch (Throwable t) { throw ExceptionFactory.makeWebServiceException(t); } return pdMap; } void setPropertyDescriptorMapCache(Map<Class, Map<String, PropertyDescriptorPlus>> cache) { this.pdMapCache = cache; } public String getRequestWrapperClassName(OperationDescription operationDesc) { return requestWrapperMap.get(operationDesc); } void setRequestWrapperMap(Map<OperationDescription, String> map) { requestWrapperMap = map; } public String getResponseWrapperClassName(OperationDescription operationDesc) { return responseWrapperMap.get(operationDesc); } void setResponseWrapperMap(Map<OperationDescription, String> map) { responseWrapperMap = map; } public FaultBeanDesc getFaultBeanDesc(FaultDescription faultDesc) { return faultBeanDescMap.get(faultDesc); } void setFaultBeanDescMap(Map<FaultDescription, FaultBeanDesc> map) { faultBeanDescMap = map; } /** * Get the Method for the specified OperationDescription */ public Method getMethod(OperationDescription operationDesc) { return methodMap.get(operationDesc); } /** * Set the Map containing the OperationDescription->Method mapping */ void setMethodMap(Map<OperationDescription, Method> map) { methodMap = map; } public String toString() { try { final String newline = "\n"; final String sameline = " "; StringBuffer string = new StringBuffer(); string.append(newline); string.append(" MarshalServiceRuntime:" + getKey()); string.append(newline); String pkgs = (getPackages() == null) ? "none" : getPackages().toString(); string.append(" Packages = " + pkgs); for (Entry<String, AnnotationDesc> entry : this.annotationMap.entrySet()) { string.append(newline); string.append(" AnnotationDesc cached for:" + entry.getKey()); string.append(entry.getValue().toString()); } for (Entry<Class, Map<String, PropertyDescriptorPlus>> entry : this.pdMapCache.entrySet()) { string.append(newline); string.append(" PropertyDescriptorPlus Map cached for:" + entry.getKey().getCanonicalName()); for (PropertyDescriptorPlus pdp : entry.getValue().values()) { string.append(newline); string.append(" propertyName =" + pdp.getPropertyName()); string.append(newline); string.append(" xmlName =" + pdp.getXmlName()); string.append(newline); string.append(" propertyType =" + pdp.getPropertyType().getCanonicalName()); string.append(newline); } } string.append(" RequestWrappers"); for (Entry<OperationDescription, String> entry : this.requestWrapperMap.entrySet()) { string.append(newline); string.append(" Operation:" + entry.getKey().getJavaMethodName() + " RequestWrapper:" + entry.getValue()); } string.append(" ResponseWrappers"); for (Entry<OperationDescription, String> entry : this.responseWrapperMap.entrySet()) { string.append(newline); string.append(" Operation:" + entry.getKey().getJavaMethodName() + " ResponseWrapper:" + entry.getValue()); } string.append(" FaultBeanDesc"); for (Entry<FaultDescription, FaultBeanDesc> entry : this.faultBeanDescMap.entrySet()) { string.append(newline); string.append(" FaultException:" + entry.getKey().getExceptionClassName()); string.append(newline); string.append(entry.getValue().toString()); } string.append(" Methods"); for (Entry<OperationDescription, Method> entry : this.methodMap.entrySet()) { string.append(newline); string.append(" Method Name:" + entry.getKey().getJavaMethodName() + " Method:" + entry.getValue().toString()); } return string.toString(); } catch (Throwable t) { // A problem occurred while dumping the contents. // This should not be re-thrown. return "An error occured while dumping the debug contents of MarshalServiceRuntimeDescriptionImpl:" + t.toString(); } } public MessageFactory getMessageFactory() { return messageFactory; } /** * Java does not provide a way to uniquely identify an object. This makes * it difficult to distinguish one object from another in a trace. The * default Object.toString() produces a string of the form: * * obj.getClass().getName() + "@" + Integer.toHexString(obj.hashCode()) * * This is "as-good-as-it-gets". If 'hashCode' has been overridden, it gets * worse. Specifically, if hashCode has been overriden such that: * * obj1.equals(obj2) ==> obj1.hashCode() == obj2.hashCode() * * then it becomes impossible to distinguish between obj1 and obj2 in a trace: * - dumping values is (almost) guaranteed to reveal that both have same content. * - dumping hashCode (see Object.toString() comment above) gives same hashCode. * * [For example, JNDI Reference objects exhibit this behavior] * * The purpose of getObjectIdentity is to attempt to duplicate the "original" * behavior of Object.toString(). On some JVMs, the 'original' hashCode * corresponds to a memory reference to the object - which is unique. * * This is NOT guaranteed to work on all JVMs. But again, this seems to be * "as-good-as-it-gets". * * @return obj.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(obj)); */ private static String getObjectIdentity(Object obj) { if (obj == null) { return "null"; } return obj.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(obj)); } }