/*
 * 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.server.endpoint.lifecycle.impl;

import org.apache.axis2.Constants;
import org.apache.axis2.context.ServiceContext;
import org.apache.axis2.description.AxisService;
import org.apache.axis2.description.Parameter;
import org.apache.axis2.jaxws.ExceptionFactory;
import org.apache.axis2.jaxws.context.WebServiceContextImpl;
import org.apache.axis2.jaxws.context.factory.MessageContextFactory;
import org.apache.axis2.jaxws.core.MessageContext;
import org.apache.axis2.jaxws.description.ServiceDescription;
import org.apache.axis2.jaxws.handler.SoapMessageContext;
import org.apache.axis2.jaxws.i18n.Messages;
import org.apache.axis2.jaxws.injection.ResourceInjectionException;
import org.apache.axis2.jaxws.lifecycle.BaseLifecycleManager;
import org.apache.axis2.jaxws.lifecycle.LifecycleException;
import org.apache.axis2.jaxws.runtime.description.injection.ResourceInjectionServiceRuntimeDescription;
import org.apache.axis2.jaxws.runtime.description.injection.ResourceInjectionServiceRuntimeDescriptionFactory;
import org.apache.axis2.jaxws.server.endpoint.injection.ResourceInjector;
import org.apache.axis2.jaxws.server.endpoint.injection.WebServiceContextInjector;
import org.apache.axis2.jaxws.server.endpoint.injection.factory.ResourceInjectionFactory;
import org.apache.axis2.jaxws.server.endpoint.lifecycle.EndpointLifecycleManager;
import org.apache.axis2.util.Loader;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.xml.ws.WebServiceContext;
import java.lang.reflect.Method;

public class EndpointLifecycleManagerImpl extends BaseLifecycleManager implements
        EndpointLifecycleManager {
    public static final String WEBSERVICE_MESSAGE_CONTEXT = "javax.xml.ws.WebServiceContext";
    private static final Log log = LogFactory.getLog(EndpointLifecycleManagerImpl.class);

    public EndpointLifecycleManagerImpl(Object endpointInstance) {
        this.instance = endpointInstance;
    }

    public EndpointLifecycleManagerImpl() {
    }

    /* (non-Javadoc)
      * @see org.apache.axis2.jaxws.server.endpoint.lifecycle.EndpointLifecycleManager#createServiceInstance(org.apache.axis2.jaxws.core.MessageContext, java.lang.Class)
      */
    public Object createServiceInstance(MessageContext mc, Class serviceImplClass)
                                                                                  throws LifecycleException,
                                                                                  ResourceInjectionException {
        org.apache.axis2.context.MessageContext msgContext = mc.getAxisMessageContext();

        // Get the ServiceDescription and injectionDesc which contain
        // cached information
        ServiceDescription serviceDesc = mc.getEndpointDescription().getServiceDescription();
        ResourceInjectionServiceRuntimeDescription injectionDesc =
                getInjectionDesc(serviceDesc, serviceImplClass);


        Object serviceimpl = retrieveServiceInstance(mc);
        if (serviceimpl != null) {
            this.instance = serviceimpl;

            if (log.isDebugEnabled()) {
                log.debug("Service Instance found in the service context, reusing the instance");
            }

            // If resource injection is needed, create the SOAPMessageContext and update the WebServiceContext
            // Create MessageContext for current invocation.
            if (hasResourceAnnotation(injectionDesc)) {
                performWebServiceContextUpdate(mc);
            }

            //since service impl is there in service context , take that from there
            return serviceimpl;
        } else {
            // create a new service impl class for that service
            serviceimpl = createServiceInstance(msgContext.getAxisService(), serviceImplClass);
            this.instance = serviceimpl;

            if (log.isDebugEnabled()) {
                log.debug("New Service Instance created");
            }

            // If resource injection is needed, create the SOAPMessageContext and build the WebServiceContext
            // Create MessageContext for current invocation.
            if (hasResourceAnnotation(injectionDesc)) {
                performWebServiceContextInjection(mc, serviceimpl);
            }


            //Invoke PostConstruct
            if (injectionDesc != null && injectionDesc.getPostConstructMethod() != null) {
                invokePostConstruct(injectionDesc.getPostConstructMethod());
            }
            ServiceContext serviceContext = msgContext.getServiceContext();
            serviceContext.setProperty(ServiceContext.SERVICE_OBJECT, serviceimpl);
            return serviceimpl;
        }
    }

    /**
     * This method locates an existing service implementation instance if
     * one has been previously stored away.
     */
    protected Object retrieveServiceInstance(MessageContext mc) {
        Object instance = null;
        ServiceContext serviceContext = mc.getAxisMessageContext().getServiceContext();
        instance = serviceContext.getProperty(ServiceContext.SERVICE_OBJECT);
        return instance;
    }

    /**
     * This method will provide the necessary function in order to inject
     * a WebServiceContext instance on a member of the service implementation class.
     */
    protected void performWebServiceContextInjection(MessageContext mc, Object serviceImpl)
                                                                                           throws ResourceInjectionException {
        WebServiceContext wsContext = createWebServiceContext(mc);
        // Inject WebServiceContext
        injectWebServiceContext(mc, wsContext, serviceImpl);
        saveWebServiceContext(mc, wsContext);
    }

    /**
     * This method will provide the necessary function in order to update
     * an existing WebServiceContext instance with a MessageContext for
     * the current request.
     */
    protected void performWebServiceContextUpdate(MessageContext mc)
                                                                    throws ResourceInjectionException {
        javax.xml.ws.handler.MessageContext soapMessageContext = createSOAPMessageContext(mc);
        ServiceContext serviceContext = mc.getAxisMessageContext().getServiceContext();

        //Get WebServiceContext from ServiceContext
        WebServiceContext ws =
                (WebServiceContext) serviceContext.getProperty(WEBSERVICE_MESSAGE_CONTEXT);

        //Add the MessageContext for current invocation
        if (ws != null) {
            updateWebServiceContext(ws, soapMessageContext);
        }
    }

    /**
     * This method will provide the function necessary to save the WebServiceContext
     * associated with the endpoint.
     */
    protected void saveWebServiceContext(MessageContext mc, WebServiceContext wsContext) {
        ServiceContext sc = mc.getAxisMessageContext().getServiceContext();
        sc.setProperty(WEBSERVICE_MESSAGE_CONTEXT, wsContext);
    }

    /**
     * This method will be responsible for creating an instance of a WebServiceContext
     * and initializing the instance with a MessageContext.
     */
    protected WebServiceContext createWebServiceContext(MessageContext mc) {
        javax.xml.ws.handler.MessageContext soapMessageContext = createSOAPMessageContext(mc);
        // Create WebServiceContext
        WebServiceContextImpl wsContext = new WebServiceContextImpl();
        //Add MessageContext for this request.
        wsContext.setSoapMessageContext(soapMessageContext);
        return wsContext;
    }

    /**
     * This method will retrieve a ResourceInjectionServiceRuntimeDescription if one
     * is associated with the current ServiceDescription.
     */
    protected ResourceInjectionServiceRuntimeDescription getInjectionDesc(
                                                                          ServiceDescription serviceDesc,
                                                                          Class serviceImplClass) {
        ResourceInjectionServiceRuntimeDescription injectionDesc = null;
        if (serviceDesc != null) {
            injectionDesc =
                    ResourceInjectionServiceRuntimeDescriptionFactory.get(serviceDesc,
                                                                          serviceImplClass);
        }

        return injectionDesc;
    }

    /**
     * This method indicates whether or not we need to perform WebServiceContext injection
     * on a field within our endpoint instance.
     */
    protected boolean hasResourceAnnotation(ResourceInjectionServiceRuntimeDescription injectionDesc) {
        return (injectionDesc != null && injectionDesc.hasResourceAnnotation());
    }

    private Object createServiceInstance(AxisService service, Class serviceImplClass) {
        if (log.isDebugEnabled()) {
            log.debug("Creating new instance of service endpoint");
        }

        if (serviceImplClass == null) {
            throw ExceptionFactory.makeWebServiceException(Messages.getMessage("EndpointControllerErr5"));
        }

        Object instance = null;
        try {
            // allow alternative definition of makeNewServiceObject
            if (service != null && service.getParameter(Constants.SERVICE_OBJECT_SUPPLIER) != null) {
                ClassLoader classLoader = service.getClassLoader();

                Parameter serviceObjectParam =
                        service.getParameter(Constants.SERVICE_OBJECT_SUPPLIER);
                Class serviceObjectMaker =
                        Loader.loadClass(classLoader,
                                         ((String) serviceObjectParam.getValue()).trim());

                // Find static getServiceObject() method, call it if there
                Method method =
                        serviceObjectMaker.getMethod("getServiceObject",
                                                     new Class[] { AxisService.class });
                if (method != null) {
                    return method.invoke(serviceObjectMaker.newInstance(), new Object[] { service });
                }
            }
            instance = serviceImplClass.newInstance();
        } catch (IllegalAccessException e) {
            throw ExceptionFactory.makeWebServiceException(Messages.getMessage("EndpointControllerErr6",
                                                                               serviceImplClass.getName()));
        } catch (InstantiationException e) {
            throw ExceptionFactory.makeWebServiceException(Messages.getMessage("EndpointControllerErr6",
                                                                               serviceImplClass.getName()));
        } catch (Exception e) {
            throw ExceptionFactory.makeWebServiceException(Messages.getMessage("EndpointControllerErr6",
                                                                               serviceImplClass.getName()));
        }

        return instance;
    }

    protected javax.xml.ws.handler.MessageContext createSOAPMessageContext(MessageContext mc) {
        SoapMessageContext soapMessageContext =
                (SoapMessageContext) MessageContextFactory.createSoapMessageContext(mc);
        return soapMessageContext;
    }

    protected void injectWebServiceContext(MessageContext mc, WebServiceContext wsContext,
                                           Object serviceInstance)
                                                                  throws ResourceInjectionException {
        ResourceInjector ri =
                ResourceInjectionFactory.createResourceInjector(WebServiceContext.class);
        ri.inject(wsContext, serviceInstance);
    }

    protected void updateWebServiceContext(WebServiceContext wsContext,
                                           javax.xml.ws.handler.MessageContext soapMessageContext)
                                                                                                  throws ResourceInjectionException {
        WebServiceContextInjector wci =
                (WebServiceContextInjector) ResourceInjectionFactory.createResourceInjector(WebServiceContextInjector.class);
        wci.addMessageContext(wsContext, soapMessageContext);

    }

}
