Package fr.imag.adele.apam.apform.legacy.osgi

Source Code of fr.imag.adele.apam.apform.legacy.osgi.OSGiMan

/**
* 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.apform.legacy.osgi;

import java.util.HashSet;
import java.util.Set;

import org.apache.felix.ipojo.annotations.Instantiate;
import org.apache.felix.ipojo.annotations.Invalidate;
import org.apache.felix.ipojo.annotations.Provides;
import org.apache.felix.ipojo.annotations.Requires;
import org.apache.felix.ipojo.annotations.Validate;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.Filter;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.util.tracker.ServiceTracker;
import org.osgi.util.tracker.ServiceTrackerCustomizer;

import fr.imag.adele.apam.Apam;
import fr.imag.adele.apam.ApamManagers;
import fr.imag.adele.apam.CST;
import fr.imag.adele.apam.Component;
import fr.imag.adele.apam.DynamicManager;
import fr.imag.adele.apam.Implementation;
import fr.imag.adele.apam.Instance;
import fr.imag.adele.apam.Link;
import fr.imag.adele.apam.Specification;
import fr.imag.adele.apam.apform.Apform2Apam;
import fr.imag.adele.apam.apform.ApformImplementation;
import fr.imag.adele.apam.declarations.references.resources.InterfaceReference;
import fr.imag.adele.apam.declarations.references.resources.MessageReference;
import fr.imag.adele.apam.impl.ComponentBrokerImpl;


/**
* This class is in charge of reifying native OSGi services as Apam instances, so
* that they can be used directly by Apam applications using the relation resolution
* mechanisms.
*
* This class uses a simple strategy to decide which services to reify in Apam. Applications
* MUST define a specification to represent the required services, and this manager will try to
* match native services to defined specifications.
*
* Matching of a specification is based on the following criteria :
*
* - The specification MUST NOT declare dependencies
* - The specification MUST provide only interfaces, not messages
* - The registered interfaces of the service MUST include the provided interfaces of
*   the specification.
* - The defined properties of the specification MUST include the registered properties
*   of the service
*   
*   
* TODO currently this class has an important performance overhead, as it reacts to every event
* in the registry by trying to match all the declared Apam specifications. A more fine-grained
* approach will be to build a service tracker for each Apam specification with the appropriate
* registry filter, that reacts only to meaningful events.
*  
* @author vega
*
*/

@org.apache.felix.ipojo.annotations.Component(name = "OSGiMan" , immediate=true)
@Provides(specifications={DynamicManager.class})
@Instantiate(name = "OSGiMan-Instance")

public class OSGiMan implements DynamicManager, ServiceTrackerCustomizer {


  /**
   * A reference to the APAM machine
   */
  @Requires(proxy = false)
  private Apam apam;

    /**
     * The instances service tracker.
     */
    private ServiceTracker      instancesServiceTracker;

    /**
     * The bundle context associated with this manager
     */
    private final BundleContext context;


  @Override
  public String getName() {
    return "OSGiMan";
  }

    public OSGiMan(BundleContext context) {
        this.context = context;
    }
   
  @Validate
  private synchronized void start() {
    ApamManagers.addDynamicManager(this);
   
      Filter filter;
    try {
      filter = context.createFilter("(" + Constants.OBJECTCLASS + "=*)");
          instancesServiceTracker = new ServiceTracker(context,filter, this);
          instancesServiceTracker.open(true);
    } catch (InvalidSyntaxException ignored) {
    }
   
  }
 
  @Invalidate
  private synchronized void stop() {
    ApamManagers.removeDynamicManager(this);
        instancesServiceTracker.close();
  }

  /**
   * Whether the specification is a possible candidate to be matched to an OSGi services
   */
  private static boolean isMatchable(Specification specification) {
   
    if (!specification.getRelations().isEmpty())
      return false;
   
    if (! specification.getDeclaration().getProvidedResources(MessageReference.class).isEmpty())
      return false;

    if (specification.getDeclaration().getProvidedResources(InterfaceReference.class).isEmpty())
      return false;
   
    return true;
  }
 
  /**
   * Whether the service is a possible candidate to be matched to APAM specifications
   */
  private static boolean isMatchable(ServiceReference reference) {
   
        /*
         * ignore services that are iPojo, these are treated separately
         *
         * In this tracker we avoid getting the service object, as this
         * may interfere with delayed service creation when using the
         * service factory pattern
         *
         */
       
        if (reference.getProperty("factory.name") != null)
          return false;

        if (reference.getProperty("instance.name") != null)
          return false;
   
    return true;
  }

 
  /**
   * Whether the service matches the specification
   */
  private static boolean matches(Specification specification, ServiceReference reference) {
   
      Set<InterfaceReference> providedServices = new HashSet<InterfaceReference>();
    for (String interfaceName : (String[]) reference.getProperty(Constants.OBJECTCLASS)) {
      providedServices.add(new InterfaceReference(interfaceName));
    }
   
    return providedServices.containsAll(specification.getDeclaration().getProvidedResources(InterfaceReference.class));
  }
 
    /**
     * Find all specifications matching the osgi service
     */
    private Set<Specification> getMatchingSpecifications(ServiceReference reference) {
     

    Set<Specification> matches  = new HashSet<Specification>();
   
    for (Specification specification : CST.componentBroker.getSpecs()) {
     
      if (isMatchable(specification) && matches(specification,reference))
        matches.add(specification);
    }
   
    return matches;
     
    }

  /**
     * Get a representation of all the possible Apam instances that match the specified
     * reference.
     *
     * Notice that we return apform objects that ARE NOT reified in Apam, this can be used
     * to decide if the instance has already be created or not.
     */
    private Set<ApformOSGiInstance> getMatchingInstances(ServiceReference reference) {

    Set<Specification> specifications   = getMatchingSpecifications(reference);
    Set<ApformOSGiInstance> instances  = new HashSet<ApformOSGiInstance>();

    for(Specification specification : specifications) {
      instances.add(new ApformOSGiInstance(specification, reference));
    }
   
    return instances;
    }
   
    @Override
    public Object addingService(ServiceReference reference) {

        /*
         * Ignore events while APAM is not available
         */
        if (apam == null)
            return null;

        /*
         * ignore services that are not matchable
         *
         */
        if (! isMatchable(reference))
          return null;
       
        /*
         * Create all instances and implementations required in APAM
         */
        Set<ApformOSGiInstance> instances = getMatchingInstances(reference);
      for(ApformOSGiInstance instance : instances) {

      ApformImplementation implementation = new ApformOSGiImplementation(instance);

      if (CST.componentBroker.getImpl(implementation.getDeclaration().getName()) == null) {
        Apform2Apam.newImplementation(implementation);
      }

      if (CST.componentBroker.getInst(instance.getDeclaration().getName()) == null) {
        Apform2Apam.newInstance(instance);
      }

      }

      /*
       * Track all services to be sure to be informed when they are unregistered
       */
        return reference;
    }

    @Override
    public void removedService(ServiceReference reference, Object tracked) {

      /*
       * Destroy all Apam instances created, and garbage-collect implementations
       * if needed.
       */
        Set<ApformOSGiInstance> instances = getMatchingInstances(reference);
        if (instances.isEmpty())
            return;

      for(ApformOSGiInstance instance : instances) {

        Instance apamInstance = CST.componentBroker.getInst(instance.getDeclaration().getName());
       
        if (apamInstance == null)
          continue;
       
        Implementation apamImplementation = apamInstance.getImpl();
       
        if (apamInstance != null)
          ((ComponentBrokerImpl)CST.componentBroker).disappearedComponent(apamInstance);
       
        if (apamImplementation.getInsts().isEmpty())
          ((ComponentBrokerImpl)CST.componentBroker).disappearedComponent(apamImplementation);
      }

    }

    @Override
    public void modifiedService(ServiceReference reference, Object instance) {
     
        ApformOSGiInstance osgiInstance  = (ApformOSGiInstance) instance;
      Instance apamInstance       = CST.componentBroker.getInst(osgiInstance.getDeclaration().getName());

      if (apamInstance == null)
        return;
     

        for (String key : reference.getPropertyKeys()) {
            if (osgiInstance.getSpecification().getPropertyDefinition(key) != null) {
                String value = reference.getProperty(key).toString();
                if (value != apamInstance.getProperty(key))
                  apamInstance.setProperty(key, value);
            }
        }

    }
       


  @Override
  public void addedComponent(Component component) {
   
    /*
     * If a new specification is defined we need to try match existing services in the registry 
     */
    if (!(component instanceof Specification))
      return;
   
    Specification specification = (Specification) component;

    if (!isMatchable(specification))
      return;
   
    StringBuilder filter = new StringBuilder();
    filter.append("(").append("&");
    for (InterfaceReference providedInterface : specification.getDeclaration().getProvidedResources(InterfaceReference.class)) {
      filter.append("(").append(Constants.OBJECTCLASS).append("=").append(providedInterface.getName()).append(")");
    }
    filter.append(")");
   
    String filterText = filter.toString();
   
    ServiceReference[] matchedServices = null;
    try {
      matchedServices = context.getAllServiceReferences(null,filterText);
    } catch (InvalidSyntaxException e) {
    }
   
    if (matchedServices == null)
      return;
     
    for (ServiceReference reference : matchedServices)  {
     
      if (!isMatchable(reference))
        continue;
       
      ApformOSGiInstance instance     = new ApformOSGiInstance(specification, reference);
      ApformImplementation implementation = new ApformOSGiImplementation(instance);

      if (CST.componentBroker.getImpl(implementation.getDeclaration().getName()) == null) {
        Apform2Apam.newImplementation(implementation);
      }

      if (CST.componentBroker.getInst(instance.getDeclaration().getName()) == null) {
        Apform2Apam.newInstance(instance);
      }
       
      }
  }


  @Override
  public void removedComponent(Component component) {
  }

  @Override
  public void removedLink(Link wire) {
  }


  @Override
  public void addedLink(Link wire) {
  }

}
TOP

Related Classes of fr.imag.adele.apam.apform.legacy.osgi.OSGiMan

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.