/**
   * Registers a non-component object that requires closing or shutdown when the repository stops.
   *
   * <p>Certain interfaces are automatically detected. If it implements {@code InitializingBean},
   * then it will be initialized as though using {@link #initialize(InitializingBean)}.
   *
   * @param obj the object to close/shutdown, not null
   * @param methodName the method name to call, not null
   */
  public void registerLifecycleStop(final Object obj, final String methodName) {
    ArgumentChecker.notNull(obj, "object");
    ArgumentChecker.notNull(methodName, "methodName");
    checkStatus(Status.CREATING);

    initialize0(obj);
    registerLifecycle0(
        new Lifecycle() {
          @Override
          public void stop() {
            ReflectionUtils.invokeNoArgsNoException(obj, methodName);
          }

          @Override
          public void start() {}

          @Override
          public boolean isRunning() {
            return false;
          }

          @Override
          public String toString() {
            return obj.getClass().getSimpleName() + ":" + obj.toString();
          }
        });
    _logger.logDebug(" Registered lifecycle-stop: " + obj);
  }
  /**
   * Registers a non-component object implementing {@code Lifecycle}.
   *
   * <p>Certain interfaces are automatically detected. If it implements {@code InitializingBean},
   * then it will be initialized as though using {@link #initialize(InitializingBean)}.
   *
   * @param lifecycleObject the object that has a lifecycle, not null
   */
  public void registerLifecycle(final Lifecycle lifecycleObject) {
    ArgumentChecker.notNull(lifecycleObject, "lifecycleObject");
    checkStatus(Status.CREATING);

    try {
      initialize0(lifecycleObject);
      registerLifecycle0(lifecycleObject);
      _logger.logDebug(" Registered lifecycle: " + lifecycleObject);

    } catch (final RuntimeException ex) {
      _status.set(Status.FAILED);
      throw new RuntimeException("Failed during registering Lifecycle: " + lifecycleObject, ex);
    }
  }
  /**
   * Registers a non-component object implementing {@code Lifecycle}.
   *
   * <p>Certain interfaces are automatically detected. If it implements {@code InitializingBean},
   * then it will be initialized as though using {@link #initialize(InitializingBean)}.
   *
   * @param servletContextAware the object that requires a servlet context, not null
   */
  public void registerServletContextAware(final ServletContextAware servletContextAware) {
    ArgumentChecker.notNull(servletContextAware, "servletContextAware");
    checkStatus(Status.CREATING);

    try {
      initialize0(servletContextAware);
      registerServletContextAware0(servletContextAware);
      _logger.logDebug(" Registered lifecycle-stop: " + servletContextAware);

    } catch (final RuntimeException ex) {
      _status.set(Status.FAILED);
      throw new RuntimeException(
          "Failed during registering ServletContextAware: " + servletContextAware, ex);
    }
  }
  /**
   * Registers an instance that should be treated as a JMX Managed Resource.
   *
   * @param managedResource the object that should be treated as an MBean
   * @param name The fully qualified JMX ObjectName
   */
  public void registerMBean(final Object managedResource, final ObjectName name) {
    ArgumentChecker.notNull(managedResource, "managedResource");
    ArgumentChecker.notNull(name, "name");
    checkStatus(Status.CREATING);

    try {
      initialize0(managedResource);
      registerMBean0(managedResource, name);
      _logger.logDebug(" Registered mbean: " + managedResource);

    } catch (final RuntimeException ex) {
      _status.set(Status.FAILED);
      throw new RuntimeException(
          "Failed during registering ManagedResource: " + managedResource, ex);
    }
  }
  /**
   * Registers the component specifying the info that describes it.
   *
   * <p>Certain interfaces are automatically detected. If the component implements {@code
   * Lifecycle}, it will be registered as though using {@link #registerLifecycle(Lifecycle)}. If it
   * implements {@code ServletContextAware}, then it will be registered as though using {@link
   * #registerServletContextAware(ServletContextAware)}. If it implements {@code InitializingBean},
   * then it will be initialized as though using {@link #initialize(InitializingBean)}.
   *
   * <p>If the component implements {@code FactoryBean}, it will be checked for the automatically
   * detected interfaces before the factory is evaluated. The evaluated factory will then be
   * registered, and the resulting object will again be checked for automatically detected
   * interfaces.
   *
   * @param info the component info to register, not null
   * @param instance the component instance to register, not null
   * @throws IllegalArgumentException if unable to register
   */
  public void registerComponent(final ComponentInfo info, Object instance) {
    ArgumentChecker.notNull(info, "info");
    ArgumentChecker.notNull(instance, "instance");
    checkStatus(Status.CREATING);

    final ComponentKey key = info.toComponentKey();
    try {
      // initialize
      initialize0(instance);
      registerInstanceInterfaces0(instance);

      // handle factories
      if (instance instanceof FactoryBean<?>) {
        try {
          instance = ((FactoryBean<?>) instance).getObject();
        } catch (final Exception ex) {
          throw new OpenGammaRuntimeException("FactoryBean threw exception", ex);
        }
        initialize0(instance);
        registerInstanceInterfaces0(instance);
      }

      // register into data structures
      final Object current = _instanceMap.putIfAbsent(key, instance);
      if (current != null) {
        throw new IllegalArgumentException(
            "Component already registered for specified information: " + key);
      }
      _infoMap.putIfAbsent(info.getType(), new ComponentTypeInfo(info.getType()));
      final ComponentTypeInfo typeInfo = getTypeInfo(info.getType());
      typeInfo.getInfoMap().put(info.getClassifier(), info);
      registeredComponent(info, instance);

      // If the component being registered is also an MBean, then register it as such
      if (JmxUtils.isMBean(instance.getClass())) {
        registerMBean(instance);
      }
    } catch (final RuntimeException ex) {
      _status.set(Status.FAILED);
      throw new RuntimeException("Failed during registration: " + key, ex);
    }
  }
  /** Marks this repository as complete and ready for use. */
  @Override
  public void start() {
    final Status status = _status.get();
    if (status == Status.STARTING) {
      return; // already starting
    }
    checkStatus(status, Status.CREATING);
    if (_status.compareAndSet(status, Status.STARTING) == false) {
      return; // another thread just beat this one
    }
    try {
      // Spring interfaces
      for (final Lifecycle obj : _lifecycles) {
        obj.start();
      }

      // JMX managed resources
      final MBeanServer jmxServer = findInstance(MBeanServer.class);
      if (jmxServer != null) {
        final MBeanExporter exporter = new MBeanExporter();
        exporter.setServer(jmxServer);
        for (final Map.Entry<ObjectName, Object> resourceEntry : _managedResources.entrySet()) {
          exporter.registerManagedResource(resourceEntry.getValue(), resourceEntry.getKey());
        }
      }

      _status.set(Status.RUNNING);

    } catch (final RuntimeException ex) {
      _status.set(Status.FAILED);
      throw ex;
    } finally {
      // reduce memory usage and avoid memory leaks
      _managedResources.clear();
      _initialized.clear();
    }
  }
 // -------------------------------------------------------------------------
 private void checkStatus(final Status required) {
   checkStatus(_status.get(), required);
 }
 /**
  * Registers an instance that should be treated as a JMX Managed Resource.
  *
  * @param managedResource the object that should be treated as an MBean, not null
  */
 public void registerMBean(final Object managedResource) {
   ArgumentChecker.notNull(managedResource, "managedResource");
   checkStatus(Status.CREATING);
   registerMBean(managedResource, generateObjectName(managedResource));
 }