Package fr.imag.adele.apam.impl

Source Code of fr.imag.adele.apam.impl.ApamMan

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

import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import fr.imag.adele.apam.CST;
import fr.imag.adele.apam.Component;
import fr.imag.adele.apam.Implementation;
import fr.imag.adele.apam.Instance;
import fr.imag.adele.apam.RelToResolve;
import fr.imag.adele.apam.RelationManager;
import fr.imag.adele.apam.Resolved;
import fr.imag.adele.apam.Specification;
import fr.imag.adele.apam.apform.Apform2Apam;
import fr.imag.adele.apam.declarations.ComponentKind;
import fr.imag.adele.apam.declarations.references.components.ComponentReference;
import fr.imag.adele.apam.declarations.references.components.ImplementationReference;
import fr.imag.adele.apam.declarations.references.components.InstanceReference;
import fr.imag.adele.apam.declarations.references.components.SpecificationReference;
import fr.imag.adele.apam.declarations.references.resources.ResourceReference;
import fr.imag.adele.apam.util.Util;

public class ApamMan implements RelationManager {

  static Logger logger = LoggerFactory.getLogger(ApamMan.class);

  private BundleContext context;

  //  public ApamMan() {
  //  }

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

  @Override
  public String getName() {
    return CST.APAMMAN;
  }


  /**
   * This is an INTERNAL manager that will be invoked by the core.
   *
   * So in this method we signal that we are not part of the external handlers to
   * invoke for this resolution request.
   *
   */
  @Override
  public boolean beginResolving(RelToResolve dep) {
    return false;
  }


  /**
   * dep target can be a specification, an implementation or a resource:
   * interface or message. We have to find out all the implementations and all
   * the instances that can be a target for that relation and satisfy
   * visibility and the constraints,
   *
   * First compute all the implementations, visible or not that is a good
   * target; then add in insts all the instances of these implementations that
   * satisfy the constraints and are visible.
   *
   * If parameter needsInstances is null, do not take care of the instances.
   *
   * Then remove the implementations that are not visible.
   *
   */
  @Override
  public Resolved<?> resolve(RelToResolve relToResolve) {

    Component source = relToResolve.getLinkSource();
   
    Set<Implementation> impls = null;
    String name = relToResolve.getTarget().getName();

    /*
     * For target by name, wait until the declaration has been processed
     */
    if (Apform2Apam.isReifying(name) )
      Apform2Apam.waitForComponent(name);

    /*
     * First analyze the component references
     */
    if (relToResolve.getTarget() instanceof SpecificationReference) {
      Specification spec = CST.componentBroker.getSpec(name);
      if (spec == null) {
        return null;
      }
      if (relToResolve.getTargetKind() == ComponentKind.SPECIFICATION) {
        return new Resolved<Specification>(spec);
      }
      impls = spec.getImpls();
    } else if (relToResolve.getTarget() instanceof ImplementationReference) {
      Implementation impl = CST.componentBroker.getImpl(name);
      if (impl == null) {
        return null;
      }
      if (relToResolve.getTargetKind() == ComponentKind.IMPLEMENTATION) {
        return new Resolved<Implementation>(impl);
      }
      impls = new HashSet<Implementation>();
      impls.add(impl);
    } else if (relToResolve.getTarget() instanceof InstanceReference) {
      Instance inst = CST.componentBroker.getInst(name);
      if (inst == null) {
        return null;
      }
      if (relToResolve.getTargetKind() == ComponentKind.INSTANCE) {
        return new Resolved<Instance>(inst);
      }
      logger.debug("if (relToResolve.getTarget() instanceof InstanceReference) ") ;
      return null;
    } else if (relToResolve.getTarget() instanceof ComponentReference<?>) {
      logger.error("Invalid target reference : " + relToResolve.getTarget());
      return null;
    }

    /*
     * We have computed all component references It is either already
     * resolved, or the implems are in impls. Now Resolve by resource.
     */
    else if (relToResolve.getTarget() instanceof ResourceReference) {
      if (relToResolve.getTargetKind() == ComponentKind.SPECIFICATION) {
        Set<Specification> specs = new HashSet<Specification>();
        for (Specification spec : CST.componentBroker.getSpecs()) {
          if (spec.getProvidedResources().contains(relToResolve.getTarget())) {
            specs.add(spec);
          }
        }
        return relToResolve.getResolved(specs, false);
      }

      /*
       * target Kind is implem or instance get all the implems that
       * implement the resource
       */
      impls = new HashSet<Implementation>();
      for (Implementation impl : CST.componentBroker.getImpls()) {
        if (impl.getProvidedResources().contains((relToResolve.getTarget()))) {
          impls.add(impl);
        }
      }
    }

    // TargetKind is implem or instance, but no implem found.
    if (impls == null || impls.isEmpty()) {
      return null;
    }

    // If TargetKind is implem, select the good one(s)
    if (relToResolve.getTargetKind() == ComponentKind.IMPLEMENTATION) {
      return relToResolve.getResolved(impls, false);
    }

    /*
     * We have in impls all the implementations satisfying the relation
     * target (type and name only). We are looking for instances. Take all
     * the instances of these implementations satisfying the relation
     * constraints and visibility.
     */

    /*
     *  Fast track : if looking for one instance and no preferences, return the first valid instance
     */
    boolean fast = (!relToResolve.isMultiple() && !relToResolve.hasPreferences());

    Set<Instance> insts = new HashSet<Instance>();
    for (Implementation impl : impls) {
      for (Instance inst : impl.getInsts()) {
        if (inst.isSharable() && source.canSee(inst) && inst.matchRelationConstraints(relToResolve)) {
          if (fast) {
            return new Resolved<Instance>(inst);
          }
          insts.add(inst);
        }
      }
    }

    if (!insts.isEmpty()) {
      /*
       * If relation is singleton, select the best instance.
       */
      if (relToResolve.isMultiple()) {
        return new Resolved<Instance>(insts);
      }
      return new Resolved<Instance>(relToResolve.getPrefered(insts));
    }

    /*
     * Keep only the implementations satisfying the constraints of the
     * relation
     */
    Set<Implementation> valid = new HashSet<Implementation>();
    for (Implementation impl : impls) {
      if (relToResolve.matchRelationConstraints(ComponentKind.IMPLEMENTATION, impl.getAllProperties())) {
        valid.add(impl);
      }
    }

    if (!!!valid.isEmpty()) {
      return new Resolved<Instance>(relToResolve.getPrefered(valid), true);
    }

    /*
     * In case no solution is found, before to return null ...
     * If some bundle are starting, they may contain the solution (especially during the starting phase)
     * Just way for these bundles to complete their starting phase.
     */
        logger.debug("Checking newBundleArrived()");
        if (newBundleArrived()) {
            logger.debug("a newBundleArrived(), calling resolve again");
      return resolve(relToResolve) ;
    }
    return null ;
  }


  /**
   * If some bundle are starting, they may contain the solution (especially during the starting phase)
   * Just way a short while to let these bundles complete their starting phase.
   * @return false for there is not starting bundles : no solution.
   *        true if new components have been added : try again
   */
  private boolean newBundleArrived () {
    if (!!!isStartingBundles()) {
      return false ;
    }
    //Some bundles are starting
    int loop = 0 ;
    try {
      while (isStartingBundles()) {
        loop += 1 ;
        if (loop > 6) {
          logger.error(" looping 7 time 300ms waiting for bundles to start  ... Give up. ");
          return true ;
        }
        //Some bundles are currently starting : wait a bit
        Thread.sleep(300) ;
      }
    } catch (InterruptedException e) { }
    return true ;
  }

  /**
   * return true if some bundles are in state "starting"
   * @return
   */
  private boolean isStartingBundles () {
    for (Bundle bundle : context.getBundles()) {
      if (bundle.getState() == Bundle.STARTING) {
        logger.debug ("Bundle " + bundle.getSymbolicName() + " is starting. Waiting for the bundle to be ready.");
        return true ;
      }
    }
    return false ;
  }


  // when in Felix.
  public void start() {
    // Wait for all bundles to be analyzed
    newBundleArrived() ;
    try {
      Util.printFileToConsole(context.getBundle().getResource("logo.txt"));
    } catch (IOException e) {
    }

    System.out.println("APAMMAN started");
  }

  public void stop() {
    System.out.println("APAMMAN stoped");
  }
}
TOP

Related Classes of fr.imag.adele.apam.impl.ApamMan

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.