package org.ow2.chameleon.fuchsia.exporter.cxf;

import org.apache.cxf.Bus;
import org.apache.cxf.endpoint.Server;
import org.apache.cxf.frontend.ServerFactoryBean;
import org.apache.cxf.transport.servlet.CXFNonSpringServlet;
import org.apache.felix.ipojo.annotations.*;
import org.osgi.framework.BundleContext;
import org.osgi.service.http.HttpService;
import org.osgi.service.http.NamespaceException;
import org.ow2.chameleon.fuchsia.core.FuchsiaUtils;
import org.ow2.chameleon.fuchsia.core.component.AbstractExporterComponent;
import org.ow2.chameleon.fuchsia.core.component.ExporterService;
import org.ow2.chameleon.fuchsia.core.declaration.ExportDeclaration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.ServletException;
import java.util.HashMap;
import java.util.Map;

@Component(name = "CxfExporterFactory")
@Provides(specifications = {ExporterService.class})
public class CxfExporterFactory extends AbstractExporterComponent {

    private Bus cxfbus;

    private BundleContext context;

    private Logger logger=LoggerFactory.getLogger(this.getClass());

    private Map<String,Server> exportedDeclaration=new HashMap<String,Server>();

    @Requires
    HttpService http;

    @ServiceProperty(name = "target")
    private String filter;


    public CxfExporterFactory(BundleContext context){
        this.context=context;
    }

    @Override
    public void useExportDeclaration(ExportDeclaration exportDeclaration) {

        System.out.println("trying to export");

        final String classname = (String) exportDeclaration.getMetadata().get(Constants.CXF_EXPORT_TYPE);
        final String webcontext = (String) exportDeclaration.getMetadata().get(Constants.CXF_EXPORT_WEB_CONTEXT);
        final Object instance = exportDeclaration.getMetadata().get(Constants.CXF_EXPORT_INSTANCE);

        //ClassLoader loader = Thread.currentThread().getContextClassLoader();

        //Thread.currentThread().setContextClassLoader(CXFNonSpringServlet.class.getClassLoader());

        try {

            ServerFactoryBean srvFactory = new ServerFactoryBean();

            Class ref = FuchsiaUtils.loadClass(this.context,classname);

            //Class ref = Class.forName(classname);

            srvFactory.setServiceClass(ref);

            srvFactory.setBus(cxfbus);

            srvFactory.setServiceBean(instance);

            srvFactory.setAddress(webcontext);

            Server endpoint = srvFactory.create();

            exportedDeclaration.put(webcontext,endpoint);

            logger.info("Pushing CXF endpoint: {}",endpoint.getEndpoint().getEndpointInfo().getAddress());

        } catch (Exception e) {

            logger.error("Failed exporting in CXF, with the message {}",e.getMessage());
            throw new RuntimeException(e);

        }

        //Thread.currentThread().setContextClassLoader(loader);

    }

    @Override
    protected void denyExportDeclaration(ExportDeclaration exportDeclaration) {
        System.out.println("trying to unexport");

        final String webcontext = (String) exportDeclaration.getMetadata().get(Constants.CXF_EXPORT_WEB_CONTEXT);

        Server exported=exportedDeclaration.get(webcontext);

        if(exported!=null){
            exported.destroy();
            logger.info("Endpoint destroyed: {}",webcontext);
        }else {
            logger.warn("Error destroying endpoint {}, is was not registered before.",webcontext);
        }

    }

    public String getName() {
        return this.getClass().getSimpleName();
    }

    @Validate
    public void start() {

        System.setProperty("org.apache.cxf.nofastinfoset", "true");

        CXFNonSpringServlet cxfServlet = new CXFNonSpringServlet();

        try {

            http.registerServlet(Constants.CXF_SERVLET, cxfServlet, null, null);

        } catch (ServletException e) {
            logger.error("Failed registering CXF servlet, with the message {}",e.getMessage());
            e.printStackTrace();
        } catch (NamespaceException e) {
            logger.error("Failed registering CXF servlet, with the message {}",e.getMessage());
            e.printStackTrace();
        }

        cxfbus = cxfServlet.getBus();

    }

    @Invalidate
    public void stop(){

        http.unregister(Constants.CXF_SERVLET);

        for(Map.Entry<String,Server> item:exportedDeclaration.entrySet()){
            item.getValue().destroy();
        }

    }

}


@@ -1474,45 +1474,66 @@
     
-System.out.println(%22trying to export%22
+logger.info(%22exporting %7B%7D%22,exportDeclaration.getMetadata()
 );%0A%0A
@@ -2195,61 +2195,8 @@
 );%0A%0A
-            //Class ref = Class.forName(classname);%0A%0A
     
@@ -2937,24 +2937,25 @@
 tion) %7B%0A
+%0A
         
 System.o
@@ -2950,47 +2950,79 @@
     
-System.out.println(%22
+logger.info(%22des
 tr
+o
 ying 
-to unexport%22
+exportation %7B%7D%22,exportDeclaration.getMetadata()
 );%0A%0A
@@ -3713,24 +3713,24 @@
 Servlet();%0A%0A
+
         try 
@@ -3723,33 +3723,32 @@
 %0A%0A        try %7B%0A
-%0A
             http

remove syso and add log instead