Package fr.imag.adele.apam.distriman.provider

Source Code of fr.imag.adele.apam.distriman.provider.CxfEndpointFactory

/**
* Copyright 2011-2012 Universite Joseph Fourier, LIG, ADELE team
*   Licensed 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 fr.imag.adele.apam.distriman.provider;

import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

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.osgi.service.http.HttpService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.HashMultimap;
import com.google.common.collect.SetMultimap;
import com.google.common.collect.Sets;

import fr.imag.adele.apam.Component;
import fr.imag.adele.apam.Instance;
import fr.imag.adele.apam.RelationManager;
import fr.imag.adele.apam.Resolved;
import fr.imag.adele.apam.declarations.references.resources.ResourceReference;
import fr.imag.adele.apam.distriman.DistrimanConstant;
import fr.imag.adele.apam.distriman.client.RemoteMachine;
import fr.imag.adele.apam.distriman.dto.RemoteDependency;
import fr.imag.adele.apam.distriman.dto.RemoteDependencyDeclaration;
import fr.imag.adele.apam.distriman.provider.impl.EndpointRegistrationImpl;
import fr.imag.adele.apam.impl.ComponentImpl;
import fr.imag.adele.apam.impl.RelToResolveImpl;

/**
* User: barjo Date: 18/12/12 Time: 14:15
*
* @ThreadSafe
*/
public class CxfEndpointFactory {

    private static Logger logger = LoggerFactory
      .getLogger(CxfEndpointFactory.class);

    public static final String PROTOCOL_NAME = "cxf";
    public static final String ROOT_NAME = "/ws";

    private final RelationManager apamMan;

    private Bus cxfbus;

    /**
     * Multimap containing the exported Instances and their Endpoint
     * registrations
     */
    private final SetMultimap<Instance, EndpointRegistration> endpoints = HashMultimap
      .create();

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

    public CxfEndpointFactory(RelationManager manager) {
  apamMan = manager;
    }

    /**
     * Create the Instance ServiceObject endpoint with CXF.
     *
     * @param instance
     * @throws ClassNotFoundException
     */
    private Map<Class, String> createEndpoint(Instance instance)
      throws ClassNotFoundException {
  Object obj = instance.getServiceObject();
  ServerFactoryBean srvFactory;

  Map<Class, String> result = new HashMap<Class, String>();

  Collection<Class> classes = loadInterfaceForProxyExport(instance);

  for (Class iface : classes) {

      // ClassLoader loader =
      // Thread.currentThread().getContextClassLoader();
      // Thread.currentThread().setContextClassLoader(
      // ServerFactoryBean.class.getClassLoader());

      try {

    srvFactory = new ServerFactoryBean();

    srvFactory.setServiceClass(iface);

    srvFactory.setBus(cxfbus); // Use the OSGi Servlet as the
             // dispatcher
    srvFactory.setServiceBean(obj);

    srvFactory.setAddress("/" + instance.getName() + "/"
      + iface.getCanonicalName().replaceAll("\\.", "/"));

    // HashMap props = new HashMap();
    // try {
    // props.put("jaxb.additionalContextClasses", new Class[] {
    // Class.forName("fr.imag.adele.apam.pax.test.iface.P2SpecKeeper")
    // });
    // srvFactory.setProperties(props);
    // } catch (ClassNotFoundException e) {
    // // TODO Auto-generated catch block
    // e.printStackTrace();
    // }

    Server res = srvFactory.create();

    while (!res.isStarted()) {
        try {
      logger.info("Server {} not started, waiting..",
        srvFactory.getAddress());
      Thread.sleep(1000);
        } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
        }
    }

    logger.info("Server {} started!", res.getEndpoint()
      .getEndpointInfo().getAddress());

    webservices.put(srvFactory.getAddress(), res);

    result.put(iface, res.getEndpoint().getEndpointInfo()
      .getAddress());

      } finally {
    // reset the context classloader to the original one.
    // Thread.currentThread().setContextClassLoader(loader);
      }

  }

  return result;

    }

    public void destroyEndpoints() {

  logger.info("destroying endpoints..");

  for (Map.Entry<String, Server> element : webservices.entrySet()) {
      String wsUrl = element.getKey();
      Server entrypoint = element.getValue();
      entrypoint.stop();
      logger.info("endpoint {} destroyed.", wsUrl);
      webservices.remove(element.getKey());
  }

    }

    public SetMultimap<Instance, EndpointRegistration> getEndpoints() {
  return endpoints;
    }

    private Collection<Class> loadInterfaceForProxyExport(Instance instance)
      throws ClassNotFoundException {

  Collection<Class> classes = new HashSet<Class>();

  logger.info("gigging interfaces used in the apam instance {}",
    instance.getName());

  if (instance instanceof ComponentImpl) {

      logger.info("getting reference for the interfaces of the instance..");

      for (ResourceReference ref : instance.getSpec().getApformSpec()
        .getDeclaration().getProvidedResources()) {
    logger.info("adding {} as interfaces for this instance",
      ref.getName());
    classes.add(Class.forName(ref.getName()));
      }

      logger.info("done.");

  }

  return classes;
    }

    public EndpointRegistration resolveAndExport(
      RemoteDependencyDeclaration dependency, RemoteMachine client)
      throws ClassNotFoundException {
  Instance neo = null; // The chosen one
  EndpointRegistration registration = null;
  // Get local instance matching the RemoteDependency

  logger.info("requesting apam instance {} to resolve the dependency {}",
    apamMan, dependency.getIdentifier());

  RemoteDependency remote = new RemoteDependency(dependency, null);

  // ((RelationImpl)client.getApamComponent().getRelation(dependency.getIdentifier()))

  RelToResolveImpl rel = new RelToResolveImpl(client.getApamComponent(),
    dependency);
  // rel.computeFilters(client.getApamComponent());

  Resolved<?> resolved = apamMan.resolve(rel);

  // resolveDependency( client.getServiceObject(),remote, true);

  // No local instance matching the RemoteDependency
  if (resolved == null) {

      logger.info("impossile to solve dependency, the number of instances was zero");

      return null;
  }

  // logger.info("solve dependency, {} instance(s) where found",
  // resolved.toInstantiate);

  // Check if we already have an endpoint for the instances
  synchronized (endpoints) {

      Sets.SetView<? extends Component> alreadyExported = Sets.intersection(
        Collections.singleton(resolved.singletonResolved),
        endpoints.keySet());

      // Nope, create a new endpoint
      if (alreadyExported.isEmpty()) {

    neo = (Instance) resolved.singletonResolved; // instances.iterator().next();

    logger.info(
      "dependency {} was NOT exported before, preparing endpoint for instance {}",
      dependency.getIdentifier(), neo);

    Map<Class, String> localEndpoints = createEndpoint(neo);

    registration = new EndpointRegistrationImpl(this, neo, client,
      PROTOCOL_NAME);

    for (Map.Entry<Class, String> endpoint : localEndpoints
      .entrySet()) {

        registration.getEndpoint().put(
          endpoint.getKey().getCanonicalName(),
          client.getURLRoot()
            + DistrimanConstant.PROVIDER_CXF_DOMAIN
            + endpoint.getValue());

    }

    endpoints.put(neo, registration);

      } else {

    neo = (Instance) alreadyExported.iterator().next();

    logger.info(
      "dependency {} was exported before, using instance {}",
      dependency.getIdentifier(), neo);

    registration = endpoints.get(neo).iterator().next();
      }

  }

  return registration;
    }

    public void start(HttpService http) {
  // TODO distriman: Disable the fast infoset as it's not compatible (yet)
  System.setProperty("org.apache.cxf.nofastinfoset", "true");

  // Register the CXF Servlet
  ClassLoader loader = Thread.currentThread().getContextClassLoader();

  // switch to the cxg minimal bundle class loader
  Thread.currentThread().setContextClassLoader(
    CXFNonSpringServlet.class.getClassLoader());

  try {
      CXFNonSpringServlet servlet = new CXFNonSpringServlet();

      // Register a CXF Servlet dispatcher
      http.registerServlet(ROOT_NAME, servlet, null, null);

      // get the bus
      cxfbus = servlet.getBus();

  } catch (Exception e) {
      // TODO log
      throw new RuntimeException(e);
  } finally {
      Thread.currentThread().setContextClassLoader(loader);
  }

  // compute the PROP_CXF_URL property

    }

    public void stop(HttpService http) {
  // Unregister servlet dispatcher
  http.unregister(ROOT_NAME);
    }

}
TOP

Related Classes of fr.imag.adele.apam.distriman.provider.CxfEndpointFactory

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.