All Downloads are FREE. Search and download functionalities are using the official Maven repository.

juzu.impl.inject.spi.InjectionContext Maven / Gradle / Ivy

There is a newer version: 1.2.0
Show newest version
/*
 * Copyright 2013 eXo Platform SAS
 *
 * 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 juzu.impl.inject.spi;

import juzu.impl.inject.ScopeController;

import java.io.Closeable;
import java.lang.reflect.InvocationTargetException;
import java.util.Iterator;
import java.util.NoSuchElementException;

/** @author Julien Viet */
public abstract class InjectionContext implements Closeable {

  public abstract ScopeController getScopeController();

  /**
   * Returns the injector provider.
   *
   * @return the injector provider
   */
  public abstract InjectorProvider getProvider();

  public abstract ClassLoader getClassLoader();

  public abstract B resolveBean(Class type);

  public abstract B resolveBean(String name);

  public abstract Iterable resolveBeans(Class type);

  /**
   * Create a bean context for the specified bean.
   *
   * @param bean the bean
   * @return the bean context
   * @throws InvocationTargetException wrap any exception thrown by the bean class during its creation.
   */
  public abstract C createContext(B bean) throws InvocationTargetException;

  /**
   * Resolve the specified bean context.
   *
   * @param bean the bean
   * @param context the bean context
   */
  public abstract void releaseContext(B bean, C context);

  /**
   * Get the bean object associated the bean instance.
   *
   * @param bean     the bean
   * @param context the bean instance
   * @return the bean instance
   * @throws InvocationTargetException wrap any exception throws,by the bean class during its creation.
   */
  public abstract Object getInstance(B bean, C context) throws InvocationTargetException;

  /**
   * Close the manager. The implementation should care bout shutting down the existing bean in particular the
   * singleton beans that are managed outside of an explicit scope.
   */
  public abstract void close();

  private static class BeanLifeCycleImpl implements BeanLifeCycle {

    final Class type;
    final InjectionContext manager;
    final B a;
    private C context;
    private I instance;

    private BeanLifeCycleImpl(Class type, InjectionContext manager, B a) {
      this.type = type;
      this.manager = manager;
      this.a = a;
    }

    public I get() throws InvocationTargetException {
      if (instance == null) {
        context = manager.createContext(a);
        instance = type.cast(manager.getInstance(a, context));
      }
      return instance;
    }

    public I peek() {
      return instance;
    }

    public void close() {
      if (context != null) {
        manager.releaseContext(a, context);
      }
    }
  }

  public final  BeanLifeCycle get(Class type) {
    final B a = resolveBean(type);
    if (a == null) {
      return null;
    } else {
      return new BeanLifeCycleImpl(type, this, a);
    }
  }

  public final  Iterable> resolve(final Class type) {
    final Iterable a = resolveBeans(type);
    return new Iterable>() {
      public Iterator> iterator() {
        return new Iterator>() {
          final Iterator i = a.iterator();
          public boolean hasNext() {
            return i.hasNext();
          }
          public BeanLifeCycle next() {
            B b = i.next();
            return new BeanLifeCycleImpl(type, InjectionContext.this, b);
          }
          public void remove() {
            throw new UnsupportedOperationException();
          }
        };
      }
    };
  }

  public final  T resolveInstance(Class beanType) {
    try {
      BeanLifeCycle pluginLifeCycle = get(beanType);
      return pluginLifeCycle != null ? pluginLifeCycle.get() : null;
    }
    catch (InvocationTargetException e) {
      // log.log("Could not retrieve bean of type " + beanType, e.getCause());
      return null;
    }
  }

  public final  Iterable resolveInstances(final Class beanType) {
    return new Iterable() {
      Iterable> lifecycles = resolve(beanType);
      public Iterator iterator() {
        return new Iterator() {
          Iterator> iterator = lifecycles.iterator();
          T next = null;
          public boolean hasNext() {
            while (next == null && iterator.hasNext()) {
              try {
                BeanLifeCycle pluginLifeCycle = iterator.next();
                next = pluginLifeCycle.get();
              }
              catch (InvocationTargetException e) {
                // log.log("Could not retrieve bean of type " + beanType.getName(), e);
              }
            }
            return next != null;
          }
          public T next() {
            if (!hasNext()) {
              throw new NoSuchElementException();
            } else {
              T tmp = next;
              next = null;
              return tmp;
            }
          }
          public void remove() {
            throw new UnsupportedOperationException();
          }
        };
      }
    };
  }
}