Package com.carrotgarden.osgi.factory.impl

Source Code of com.carrotgarden.osgi.factory.impl.FidgetManagerProvider$TaskUnbind

/**
* Copyright (C) 2010-2012 Andrei Pozolotin <Andrei.Pozolotin@gmail.com>
*
* All rights reserved. Licensed under the OSI BSD License.
*
* http://www.opensource.org/licenses/bsd-license.php
*/
package com.carrotgarden.osgi.factory.impl;

import java.util.ArrayList;
import java.util.Dictionary;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.LinkedBlockingQueue;

import org.apache.sling.commons.threads.ThreadPool;
import org.apache.sling.commons.threads.ThreadPoolManager;
import org.osgi.framework.Bundle;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.ComponentFactory;
import org.osgi.service.component.ComponentInstance;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
import org.osgi.service.event.Event;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.carrotgarden.osgi.event.api.EventAdminService;
import com.carrotgarden.osgi.event.api.EventUtil;
import com.carrotgarden.osgi.factory.api.FactoryEvent;
import com.carrotgarden.osgi.factory.api.FactoryHandler;
import com.carrotgarden.osgi.factory.api.Fidget;
import com.carrotgarden.osgi.factory.api.FidgetManager;
import com.carrotgarden.osgi.factory.api.FidgetManagerBase;
import com.carrotgarden.osgi.factory.impl.util.Props;

/**
*
* factory for factory
*
*/
@Component(factory = FidgetManagerBase.FACTORY)
public class FidgetManagerProvider<F extends Fidget> implements
    FidgetManager<F> {

  private static final String POOL_NAME = FidgetManagerProvider.class
      .getName();

  protected final Logger log = LoggerFactory.getLogger(getClass());

  //

  /** factory cache : [factoryId, factory wrapper] */
  private final Map<String, FactoryInstance> factoryMap = new ConcurrentHashMap<String, FactoryInstance>();

  /** instance cache : [instanceId, instance wrapper] */
  private final Map<String, ComponentInstance> instanceMap = new ConcurrentHashMap<String, ComponentInstance>();

  /** factory deferred bind registration queue */
  private final BlockingQueue<FactoryContext> bindQueue = new LinkedBlockingQueue<FactoryContext>();

  //

  /**  */
  private volatile Class<F> interfaceClass;

  /**
   * @return factory bind/unbind filter interface
   */
  private Class<F> getFidgetInterface() {
    return interfaceClass;
  }

  //

  private boolean isActive;

  /** @return are we inside activate/deactivate stage ? */
  protected final boolean isActive() {
    return isActive;
  }

  @SuppressWarnings("unchecked")
  @Activate
  protected final void activate(final ComponentContext context)
      throws Exception {

    threadPool = threadPoolManager.get(POOL_NAME);

    final Dictionary<String, String> props = context.getProperties();

    final String bundleId = props.get(FidgetManagerBase.PROP_BUNDLE_ID);

    final String interfaceName = props
        .get(FidgetManagerBase.PROP_INTERFACE);

    final long id = Long.parseLong(bundleId);

    final Bundle bundle = context.getBundleContext().getBundle(id);

    interfaceClass = (Class<F>) bundle.loadClass(interfaceName);

    //

    synchronized (this) {
      isActive = true;
    }

    final List<FactoryContext> bindList = new LinkedList<FactoryContext>();

    bindQueue.drainTo(bindList);

    for (final FactoryContext serviceContext : bindList) {
      execute(new TaskBind(serviceContext));
    }

    log.debug("activate manager for : {}", getFidgetInterface());

  }

  @Deactivate
  protected final void deactivate(final ComponentContext context) {

    for (final FactoryInstance factory : factoryMap.values()) {
      // blocking
      new TaskUnbind(factory.factoryContext).run();
    }

    factoryMap.clear();

    //

    for (final ComponentInstance wrapper : instanceMap.values()) {
      // blocking
      wrapper.dispose();
    }

    instanceMap.clear();

    //

    synchronized (this) {
      isActive = false;
    }

    threadPoolManager.release(threadPool);

    interfaceClass = null;

    log.debug("deactivate manager for : {}", getFidgetInterface());

  }

  //

  /**
   * @return valid factory or null for invalid conditions
   */
  protected final FactoryInstance discoverNew(final FactoryContext context) {

    try {

      final Class<F> fidgetInterface = getFidgetInterface();

      final Class<?> fidgetClass = helper.fidgetClass(context);

      final boolean isManagedHere = //
      fidgetInterface.isAssignableFrom(fidgetClass);

      if (!isManagedHere) {
        return null;
      }

      final String factoryId = helper.factoryId(context);

      final Map<String, String> factoryDescriptor = helper
          .fidgetDescriptor(context);

      final FactoryInstance factoryNew = new FactoryInstance(factoryId,
          fidgetClass, factoryDescriptor, context);

      return factoryNew;

    } catch (final Exception e) {

      helper.logFactoryProps(context);

      log.error("discover failed", e);

      return null;

    }

  }

  protected final FactoryInstance discoverOld(final FactoryContext context) {

    final String factoryId = helper.factoryId(context);

    return factoryMap.get(factoryId);

  }

  private class TaskBind implements Runnable {

    private final FactoryContext serviceContext;

    TaskBind(final FactoryContext serviceContext) {
      this.serviceContext = serviceContext;
    }

    @Override
    public void run() {

      final FactoryInstance factory = discoverNew(serviceContext);

      if (factory == null) {
        // error or foreign
        return;
      }

      final String factoryId = factory.factoryId;

      if (hasFactory(factoryId)) {
        log.error("duplicate factory id", new Exception(factoryId));
        return;
      }

      log.debug("factory bind   : {}", factory);

      factoryMap.put(factoryId, factory);

      final Props props = Props.make();
      props.put(FactoryEvent.PROP_FACTORY_ID, factoryId);
      eventer.send(FactoryEvent.FACTORY_ENABLED, props);

      sender.sendState(FidgetManagerProvider.this, factoryId,
          FactoryHandler.ON);

    }
  };

  private class TaskUnbind implements Runnable {

    private final FactoryContext serviceContext;

    TaskUnbind(final FactoryContext serviceContext) {
      this.serviceContext = serviceContext;
    }

    @Override
    public void run() {

      final FactoryInstance factory = discoverOld(serviceContext);

      if (factory == null) {
        // missing or foreign
        return;
      }

      final String factoryId = factory.factoryId;

      if (!hasFactory(factoryId)) {
        log.error("unknown factory id", new Exception(factoryId));
        return;
      }

      log.debug("factory unbind : {}", factory);

      final Props props = Props.make();
      props.put(FactoryEvent.PROP_FACTORY_ID, factoryId);
      eventer.send(FactoryEvent.FACTORY_DISABLED, props);

      sender.sendState(FidgetManagerProvider.this, factoryId,
          FactoryHandler.OFF);

      factoryMap.remove(factoryId);

    }
  };

  protected final void execute(final Runnable task) {

    final ThreadPool exec = threadPool;

    if (exec == null) {
      log.debug("executor is unbound");
    } else {
      exec.execute(task);
    }

  }

  @Override
  public List<String> getFactoryIds() {

    return new ArrayList<String>(factoryMap.keySet());

  }

  @Override
  public final F create(final String factoryId,
      final Map<String, String> props) {

    if (factoryId == null) {
      log.error("factoryId==null", new Exception());
      return null;
    }

    final FactoryInstance factoryWrapper = factoryMap.get(factoryId);

    if (factoryWrapper == null) {
      log.error("unknown factory id", new Exception(factoryId));
      return null;
    }

    final ComponentInstance instanceWrapper;

    try {
      instanceWrapper = factoryWrapper.newInstance(props);
    } catch (final Exception e) {
      log.error("factory can not produce instance", new Exception(
          factoryId));
      return null;
    }

    @SuppressWarnings("unchecked")
    final F instance = (F) instanceWrapper.getInstance();
    if (instance == null) {
      log.error("instance == null", new Exception(factoryId));
      instanceWrapper.dispose();
      return null;
    }

    final String instanceId;

    try {
      instanceId = instance.getInstanceId();
    } catch (final Exception e) {
      log.error("invalid instanceId", new Exception(factoryId));
      instanceWrapper.dispose();
      return null;
    }

    if (instanceId == null) {
      log.error("instanceId == null", new Exception(factoryId));
      instanceWrapper.dispose();
      return null;
    }

    if (instanceMap.containsKey(instanceId)) {
      log.error("duplicate instance id", new Exception(instanceId));
      instanceWrapper.dispose();
      return null;
    }

    instanceMap.put(instanceId, instanceWrapper);

    log.debug("created : {}", instance);

    return instance;

  }

  @Override
  public final boolean destroy(final F fidget) {

    if (fidget == null) {
      log.error("fidget == null", new Exception());
      return false;
    }

    final String instanceId;

    try {
      instanceId = fidget.getInstanceId();
    } catch (final Exception e) {
      log.error("invalid fidget.getInstanceId", e);
      return false;
    }

    if (instanceId == null) {
      log.error("instanceId == null", new Exception());
      return false;
    }

    final ComponentInstance instanceWrapper = instanceMap.remove(instanceId);
    if (instanceWrapper == null) {
      log.error("unknown instance id", new Exception(instanceId));
      return false;
    }

    final Object instance = instanceWrapper.getInstance();
    if (instance == null) {
      log.error("instance == null", new Exception(instanceId));
      return false;
    }

    instanceWrapper.dispose();

    log.debug("destroyed : {}", fidget);

    return true;

  }

  //

  @Override
  public final boolean hasFactory(final String factoryId) {

    return factoryMap.containsKey(factoryId);

  }

  //

  @Override
  public final boolean hasInstance(final String instanceId) {

    return instanceMap.containsKey(instanceId);

  }

  @Override
  public final F getInstance(final String instanceId) {

    final ComponentInstance instanceWrapper = instanceMap.get(instanceId);

    if (instanceWrapper == null) {
      return null;
    }

    @SuppressWarnings("unchecked")
    final F fidget = (F) instanceWrapper.getInstance();

    return fidget;

  }

  @Override
  public final List<F> getInstances() {

    final List<F> list = new ArrayList<F>(instanceMap.size());

    for (final ComponentInstance wrapper : instanceMap.values()) {

      @SuppressWarnings("unchecked")
      final F fidget = (F) wrapper.getInstance();

      if (fidget == null) {
        // destroyed
        continue;
      }

      list.add(fidget);

    }

    return list;

  }

  @Override
  public final List<F> getInstances(final String factoryId) {

    final List<F> list = new LinkedList<F>();

    if (factoryId == null) {
      log.error("factoryId == null", new Exception());
      return list;
    }

    final FactoryInstance factory = factoryMap.get(factoryId);

    if (factory == null) {
      log.error("unknown factory id", new Exception(factoryId));
      return list;
    }

    final Class<?> fidgetClass = factory.fidgetClass;

    if (fidgetClass == null) {
      log.error("fidgetClass == null", new Exception(factoryId));
      return list;
    }

    for (final ComponentInstance wrapper : instanceMap.values()) {

      @SuppressWarnings("unchecked")
      final F fidget = (F) wrapper.getInstance();

      if (fidget == null) {
        // destoyed
        continue;
      }

      if (fidgetClass == fidget.getClass()) {
        list.add(fidget);
      }

    }

    return list;

  }

  @Override
  public final boolean hasFiredEnabled(final Event event) {

    return hasFired(event, FactoryEvent.FACTORY_ENABLED);

  }

  @Override
  public final boolean hasFiredDisabled(final Event event) {

    return hasFired(event, FactoryEvent.FACTORY_DISABLED);

  }

  private final boolean hasFired(final Event event, final String name) {

    if (event == null) {
      log.error("event == null", new Exception());
      return false;
    }

    if (!EventUtil.is(event, name)) {
      // non manager event
      return false;
    }

    final String factoryId = EventUtil.getProperty(event,
        FactoryEvent.PROP_FACTORY_ID);

    if (factoryId == null) {
      log.error("factoryId == null", new Exception());
      return false;
    }

    return hasFactory(factoryId);

  }

  @Override
  public final String getFactoryId(final Event event) {

    if (event == null) {
      log.error("event == null", new Exception());
      return null;
    }

    final String factoryId = EventUtil.getProperty(event,
        FactoryEvent.PROP_FACTORY_ID);

    if (factoryId == null) {
      // non manager event
      return null;
    }

    if (hasFactory(factoryId)) {
      return factoryId;
    } else {
      return null;
    }

  }

  //

  @Override
  public Map<String, String> getFactoryDescriptor(final String factoryId) {

    if (factoryId == null) {
      log.error("factoryId == null", new Exception());
      return null;
    }

    final FactoryInstance factory = factoryMap.get(factoryId);

    if (factory == null) {
      // destroyed
      return null;
    }

    final Map<String, String> map = factory.factoryDescriptor;

    if (map == null) {
      // not provided
      return null;
    }

    return map;

  }

  // ######################################

  //

  private FactoryHelper helper;

  @Reference
  protected void bind(final FactoryHelper h) {
    helper = h;
  }

  protected void unbind(final FactoryHelper h) {
    helper = null;
  }

  //

  private ThreadPool threadPool;

  private ThreadPoolManager threadPoolManager;

  @Reference
  protected void bind(final ThreadPoolManager s) {
    threadPoolManager = s;
  }

  protected void unbind(final ThreadPoolManager s) {
    threadPoolManager = null;
  }

  //

  private EventAdminService eventer;

  @Reference
  protected void bind(final EventAdminService e) {
    eventer = e;
  }

  protected void unbind(final EventAdminService e) {
    eventer = null;
  }

  //

  private HandlerSender<FidgetManager<F>> sender;

  @Reference
  protected void bind(final HandlerSender<FidgetManager<F>> s) {
    sender = s;
  }

  protected void unbind(final HandlerSender<FidgetManager<F>> s) {
    sender = null;
  }

  //

  @Reference( //
  cardinality = ReferenceCardinality.MULTIPLE, //
  policy = ReferencePolicy.DYNAMIC //
  )
  protected final void bind(final ComponentFactory factoryOSGI,
      final Map<String, String> factoryProps) {

    final FactoryContext serviceContext = new FactoryContext(factoryOSGI,
        factoryProps);

    synchronized (this) {
      if (isActive()) {
        execute(new TaskBind(serviceContext));
      } else {
        try {
          bindQueue.put(serviceContext);
        } catch (final Exception e) {
          log.error("unexpected", e);
        }
      }
    }

  }

  protected final void unbind(final ComponentFactory factoryOSGI,
      final Map<String, String> factoryProps) {

    final FactoryContext serviceContext = new FactoryContext(factoryOSGI,
        factoryProps);

    synchronized (this) {
      if (isActive()) {
        execute(new TaskUnbind(serviceContext));
      }
    }

  }

}
TOP

Related Classes of com.carrotgarden.osgi.factory.impl.FidgetManagerProvider$TaskUnbind

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.