/**
  * Finds a single instance of the specified component type.
  *
  * <p>This method searches for a single instance of the specified type. If there are no instances
  * or multiple instances, then null is returned.
  *
  * @param <T> the type
  * @param type the type to get, not null
  * @return the component information, null if not found
  */
 public <T> T findInstance(final Class<T> type) {
   ArgumentChecker.notNull(type, "type");
   final ComponentTypeInfo typeInfo = findTypeInfo(type);
   if (typeInfo == null) {
     return null;
   }
   if (typeInfo.getInfoMap().size() != 1) {
     return null;
   }
   final Object result = getInstance(typeInfo.getInfoMap().values().iterator().next());
   return type.cast(result);
 }
 /**
  * Gets all the component information objects for the specified type.
  *
  * <p>This method will return all registered information objects for the specified type.
  *
  * @param type the type to get, not null
  * @return the component informations, not null
  */
 public Collection<ComponentInfo> getInfos(final Class<?> type) {
   ArgumentChecker.notNull(type, "type");
   final ComponentTypeInfo info = findTypeInfo(type);
   final ArrayList<ComponentInfo> result = new ArrayList<ComponentInfo>();
   if (info != null) {
     result.addAll(info.getInfoMap().values());
   }
   return result;
 }
 /**
  * Finds the component information.
  *
  * <p>This method is lenient, ignoring case and matching simple type names.
  *
  * @param type the type to get, not null
  * @param classifier the classifier that distinguishes the component, case insensitive, not null
  * @return the component information, null if not found
  */
 public ComponentInfo findInfo(final Class<?> type, final String classifier) {
   ArgumentChecker.notNull(type, "type");
   final ComponentTypeInfo typeInfo = findTypeInfo(type);
   if (typeInfo != null) {
     for (final String realClassifier : typeInfo.getInfoMap().keySet()) {
       if (realClassifier.equalsIgnoreCase(classifier)) {
         return typeInfo.getInfo(realClassifier);
       }
     }
   }
   return null;
 }
  /**
   * 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);
    }
  }