/* * 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.engine; import org.apache.axis2.AxisFault; import org.apache.axis2.Constants; import org.apache.axis2.classloader.ThreadContextDescriptor; import org.apache.axis2.context.MessageContext; import org.apache.axis2.context.ServiceContext; import org.apache.axis2.context.ServiceGroupContext; import org.apache.axis2.description.AxisService; import org.apache.axis2.description.AxisServiceGroup; import org.apache.axis2.description.Parameter; import org.apache.axis2.i18n.Messages; import org.apache.axis2.service.Lifecycle; import org.apache.axis2.util.Loader; import org.apache.axis2.util.Utils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.security.PrivilegedAction; import java.util.Iterator; /** * If the service implementation has an init method with 1 or 2 message context as its parameters, then * the DependencyManager calls the init method with appropriate parameters. */ public class DependencyManager { private static final Log log = LogFactory.getLog(DependencyManager.class); public final static String SERVICE_INIT_METHOD = "init"; public final static String SERVICE_DESTROY_METHOD = "destroy"; /** * Initialize a new service object. Essentially, check to see if the object wants to receive * an init() call - if so, call it. * * @param obj the service object * @param serviceContext the active ServiceContext * @throws AxisFault if there's a problem initializing */ public static void initServiceObject(Object obj, ServiceContext serviceContext) throws AxisFault { // This is the way to do things into the future. if (obj instanceof Lifecycle) { ((Lifecycle)obj).init(serviceContext); return; } // ...however, we also still support the old way for now. Note that introspecting for // a method like this is something like 10 times slower than the above instanceof check. Class<?> classToLoad = obj.getClass(); // We can not call classToLoad.getDeclaredMethed() , since there // can be insatnce where mutiple services extends using one class // just for init and other reflection methods Method method = null; try { method = classToLoad.getMethod(SERVICE_INIT_METHOD, new Class[]{ServiceContext.class}); } catch (Exception e) { //We do not need to inform this to user , since this something // Axis2 is checking to support Session. So if the method is // not there we should ignore that } if (method != null) { try { method.invoke(obj, new Object[]{serviceContext}); } catch (IllegalAccessException e) { log.error("Exception trying to call " + SERVICE_INIT_METHOD, e); throw new AxisFault("Can not access the method ", e); } catch (IllegalArgumentException e) { log.error("Exception trying to call " + SERVICE_INIT_METHOD, e); throw new AxisFault(" Incorrect arguments ", e); } catch (InvocationTargetException e) { log.error("Exception trying to call " + SERVICE_INIT_METHOD, e); throw new AxisFault(" problem in invocation the method ", e); } } } /** * To init all the services in application scope * * @param serviceGroupContext the ServiceGroupContext from which to extract all the services * @throws AxisFault if there's a problem initializing */ public static void initService(ServiceGroupContext serviceGroupContext) throws AxisFault { AxisServiceGroup serviceGroup = serviceGroupContext.getDescription(); Iterator<AxisService> serviceItr = serviceGroup.getServices(); while (serviceItr.hasNext()) { AxisService axisService = (AxisService) serviceItr.next(); ServiceContext serviceContext = serviceGroupContext.getServiceContext(axisService); AxisService service = serviceContext.getAxisService(); ClassLoader classLoader = service.getClassLoader(); Parameter implInfoParam = service.getParameter(Constants.SERVICE_CLASS); if (implInfoParam != null) { try { ThreadContextDescriptor tc = ThreadContextDescriptor.setThreadContext(axisService); Class<?> implClass = Loader.loadClass( classLoader, ((String) implInfoParam.getValue()).trim()); Object serviceImpl = makeNewServiceObject(service); serviceContext.setProperty(ServiceContext.SERVICE_OBJECT, serviceImpl); initServiceObject(serviceImpl, serviceContext); restoreThreadContext(tc); } catch (Exception e) { throw AxisFault.makeFault(e); } } } } protected static Object makeNewServiceObject(AxisService service) throws AxisFault { Object serviceObject = Utils.createServiceObject(service); if (serviceObject == null) { throw new AxisFault( Messages.getMessage("paramIsNotSpecified", "SERVICE_OBJECT_SUPPLIER")); } else { return serviceObject; } } /** * Notify a service object that it's on death row. * @param serviceContext the active ServiceContext */ public static void destroyServiceObject(ServiceContext serviceContext) { Object obj = serviceContext.getProperty(ServiceContext.SERVICE_OBJECT); if (obj != null) { // If this is a Lifecycle object, just call it. if (obj instanceof Lifecycle) { ((Lifecycle)obj).destroy(serviceContext); return; } // For now, we also use "raw" introspection to try and find the destroy method. Class<?> classToLoad = obj.getClass(); Method method = null; try { method = classToLoad.getMethod(SERVICE_DESTROY_METHOD, new Class[]{ServiceContext.class}); } catch (NoSuchMethodException e) { //We do not need to inform this to user , since this something // Axis2 is checking to support Session. So if the method is // not there we should ignore that } if(method!=null){ try { method.invoke(obj, new Object[]{serviceContext}); } catch (IllegalAccessException e) { log.info("Exception trying to call " + SERVICE_DESTROY_METHOD, e); } catch (InvocationTargetException e) { log.info("Exception trying to call " + SERVICE_DESTROY_METHOD, e); } } } } protected static void restoreThreadContext(final ThreadContextDescriptor tc) { org.apache.axis2.java.security.AccessController.doPrivileged(new PrivilegedAction() { public Object run() { Thread.currentThread().setContextClassLoader(tc.getOldClassLoader()); return null; } }); MessageContext.currentMessageContext.set(tc.getOldMessageContext()); } }