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.jaxws.runtime.description.marshal.impl;
020:
021: import org.apache.axis2.java.security.AccessController;
022: import org.apache.axis2.jaxws.description.EndpointDescription;
023: import org.apache.axis2.jaxws.description.EndpointInterfaceDescription;
024: import org.apache.axis2.jaxws.description.FaultDescription;
025: import org.apache.axis2.jaxws.description.OperationDescription;
026: import org.apache.axis2.jaxws.description.ParameterDescription;
027: import org.apache.axis2.jaxws.description.ServiceDescription;
028: import org.apache.axis2.jaxws.runtime.description.marshal.AnnotationDesc;
029: import org.apache.axis2.jaxws.runtime.description.marshal.FaultBeanDesc;
030: import org.apache.axis2.jaxws.utility.ClassUtils;
031: import org.apache.commons.logging.Log;
032: import org.apache.commons.logging.LogFactory;
033:
034: import javax.xml.bind.JAXBElement;
035: import java.lang.reflect.Method;
036: import java.security.PrivilegedActionException;
037: import java.security.PrivilegedExceptionAction;
038: import java.util.HashMap;
039: import java.util.Map;
040:
041: /**
042: * Walks the ServiceDescription and its child *Description classes to find all of the types. An
043: * AnnotationDesc is built for each of the types
044: */
045: public class AnnotationBuilder {
046:
047: private static Log log = LogFactory.getLog(AnnotationBuilder.class);
048:
049: /** This is a static utility class. The constructor is intentionally private */
050: private AnnotationBuilder() {
051: }
052:
053: /**
054: * @param serviceDescription ServiceDescription
055: * @param ap ArtifactProcessor which found/produced artifact classes
056: * @return AnnotationDesc Map
057: */
058: public static Map<String, AnnotationDesc> getAnnotationDescs(
059: ServiceDescription serviceDesc, ArtifactProcessor ap) {
060: Map<String, AnnotationDesc> map = new HashMap<String, AnnotationDesc>();
061: EndpointDescription[] endpointDescs = serviceDesc
062: .getEndpointDescriptions();
063:
064: // Build a set of packages from all of the endpoints
065: if (endpointDescs != null) {
066: for (int i = 0; i < endpointDescs.length; i++) {
067: getAnnotationDescs(endpointDescs[i], ap, map);
068: }
069: }
070: return map;
071: }
072:
073: /**
074: * @param endpointDesc
075: * @param ap ArtifactProcessor which found/produced artifact classes
076: * @param map
077: */
078: private static void getAnnotationDescs(
079: EndpointDescription endpointDesc, ArtifactProcessor ap,
080: Map<String, AnnotationDesc> map) {
081: EndpointInterfaceDescription endpointInterfaceDesc = endpointDesc
082: .getEndpointInterfaceDescription();
083: if (endpointInterfaceDesc != null) {
084: getAnnotationDescs(endpointInterfaceDesc, ap, map);
085: }
086: }
087:
088: /**
089: * @param endpointInterfaceDesc
090: * @param ap ArtifactProcessor which found/produced artifact classes
091: * @param map
092: */
093: private static void getAnnotationDescs(
094: EndpointInterfaceDescription endpointInterfaceDesc,
095: ArtifactProcessor ap, Map<String, AnnotationDesc> map) {
096: OperationDescription[] opDescs = endpointInterfaceDesc
097: .getOperations();
098:
099: // Build a set of packages from all of the opertions
100: if (opDescs != null) {
101: for (int i = 0; i < opDescs.length; i++) {
102: getAnnotationDescs(opDescs[i], ap, map);
103: }
104: }
105: }
106:
107: /**
108: * Get annotations for this operation
109: *
110: * @param opDesc
111: * @param ap ArtifactProcessor which found/produced artifact classes
112: * @param map
113: */
114: private static void getAnnotationDescs(OperationDescription opDesc,
115: ArtifactProcessor ap, Map<String, AnnotationDesc> map) {
116:
117: // Walk the parameter information
118: ParameterDescription[] parameterDescs = opDesc
119: .getParameterDescriptions();
120: if (parameterDescs != null) {
121: for (int i = 0; i < parameterDescs.length; i++) {
122: getAnnotationDescs(parameterDescs[i], map);
123: }
124: }
125:
126: // Walk the fault information
127: FaultDescription[] faultDescs = opDesc.getFaultDescriptions();
128: if (faultDescs != null) {
129: for (int i = 0; i < faultDescs.length; i++) {
130: getAnnotationDescs(faultDescs[i], ap, map);
131: }
132: }
133:
134: // Also consider the request and response wrappers
135: String wrapperName = ap.getRequestWrapperMap().get(opDesc);
136: if (wrapperName != null) {
137: addAnnotation(wrapperName, map);
138: }
139: wrapperName = ap.getResponseWrapperMap().get(opDesc);
140: if (wrapperName != null) {
141: addAnnotation(wrapperName, map);
142: }
143:
144: // Finally consider the result type
145: Class cls = opDesc.getResultActualType();
146: if (cls != null && cls != void.class && cls != Void.class) {
147: addAnnotation(cls, map);
148: }
149: }
150:
151: private static void getAnnotationDescs(
152: ParameterDescription paramDesc,
153: Map<String, AnnotationDesc> map) {
154:
155: // Get the type that defines the actual data. (this is never a holder )
156: Class paramClass = paramDesc.getParameterActualType();
157:
158: if (paramClass != null) {
159: getTypeAnnotationDescs(paramClass, map);
160: }
161:
162: }
163:
164: /**
165: * Update the package set with the packages referenced by this FaultDescription
166: *
167: * @param faultDesc FaultDescription
168: * @param set Set<Package> that is updated
169: */
170: private static void getAnnotationDescs(FaultDescription faultDesc,
171: ArtifactProcessor ap, Map<String, AnnotationDesc> map) {
172: FaultBeanDesc faultBeanDesc = ap.getFaultBeanDescMap().get(
173: faultDesc);
174: Class faultBean = loadClass(faultBeanDesc
175: .getFaultBeanClassName());
176: if (faultBean != null) {
177: getTypeAnnotationDescs(faultBean, map);
178: }
179: }
180:
181: private final static Class[] noClass = new Class[] {};
182:
183: /**
184: * Get the annotations for this type
185: *
186: * @param cls
187: */
188: private static void getTypeAnnotationDescs(Class cls,
189: Map<String, AnnotationDesc> map) {
190:
191: if (JAXBElement.class.isAssignableFrom(cls)) {
192: try {
193: Method m = cls.getMethod("getValue", noClass);
194: Class cls2 = m.getReturnType();
195: addAnnotation(cls2, map);
196:
197: } catch (Exception e) {
198: // We should never get here
199: if (log.isDebugEnabled()) {
200: log
201: .debug("Cannot find JAXBElement.getValue method.");
202: }
203: }
204: } else {
205: addAnnotation(cls, map);
206: }
207: }
208:
209: private static void addAnnotation(String className,
210: Map<String, AnnotationDesc> map) {
211:
212: if (map.get(className) == null) {
213: Class clz = loadClass(className);
214: if (clz != null) {
215: addAnnotation(clz, map);
216: }
217: }
218: }
219:
220: private static void addAnnotation(Class cls,
221: Map<String, AnnotationDesc> map) {
222:
223: String className = cls.getCanonicalName();
224: if (map.get(className) == null) {
225: AnnotationDesc desc = AnnotationDescImpl.create(cls);
226: map.put(className, desc);
227: if (cls.isPrimitive()) {
228: Class class2 = ClassUtils.getWrapperClass(cls);
229: AnnotationDesc desc2 = AnnotationDescImpl
230: .create(class2);
231: map.put(class2.getCanonicalName(), desc2);
232: } else {
233: Class class2 = ClassUtils.getPrimitiveClass(cls);
234: if (class2 != null) {
235: AnnotationDesc desc2 = AnnotationDescImpl
236: .create(class2);
237: map.put(class2.getCanonicalName(), desc2);
238: }
239: }
240: }
241: }
242:
243: /**
244: * Loads the class
245: *
246: * @param className
247: * @return Class (or null if the class cannot be loaded)
248: */
249: private static Class loadClass(String className) {
250: // Don't make this public, its a security exposure
251: if (className == null || className.length() == 0) {
252: return null;
253: }
254: try {
255:
256: return forName(className, true, getContextClassLoader());
257: //Catch Throwable as ClassLoader can throw an NoClassDefFoundError that
258: //does not extend Exception, so lets catch everything that extends Throwable
259: //rather than just Exception.
260: } catch (Throwable e) {
261: // TODO Should the exception be swallowed ?
262: if (log.isDebugEnabled()) {
263: log
264: .debug("PackageSetBuilder cannot load the following class:"
265: + className);
266: }
267: }
268: return null;
269: }
270:
271: /**
272: * Return the class for this name
273: *
274: * @return Class
275: */
276: static Class forName(final String className,
277: final boolean initialize, final ClassLoader classloader)
278: throws ClassNotFoundException {
279: // NOTE: This method must remain protected because it uses AccessController
280: Class cl = null;
281: try {
282: cl = (Class) AccessController
283: .doPrivileged(new PrivilegedExceptionAction() {
284: public Object run()
285: throws ClassNotFoundException {
286: // Class.forName does not support primitives
287: Class cls = ClassUtils
288: .getPrimitiveClass(className);
289: if (cls == null) {
290: cls = Class.forName(className,
291: initialize, classloader);
292: }
293: return cls;
294: }
295: });
296: } catch (PrivilegedActionException e) {
297: if (log.isDebugEnabled()) {
298: log.debug("Exception thrown from AccessController: "
299: + e);
300: }
301: throw (ClassNotFoundException) e.getException();
302: }
303:
304: return cl;
305: }
306:
307: /** @return ClassLoader */
308: static ClassLoader getContextClassLoader() {
309: // NOTE: This method must remain private because it uses AccessController
310: ClassLoader cl = null;
311: try {
312: cl = (ClassLoader) AccessController
313: .doPrivileged(new PrivilegedExceptionAction() {
314: public Object run()
315: throws ClassNotFoundException {
316: return Thread.currentThread()
317: .getContextClassLoader();
318: }
319: });
320: } catch (PrivilegedActionException e) {
321: if (log.isDebugEnabled()) {
322: log.debug("Exception thrown from AccessController: "
323: + e);
324: }
325: throw (RuntimeException) e.getException();
326: }
327:
328: return cl;
329: }
330: }
|