Package juzu.impl.inject.spi.guice

Source Code of juzu.impl.inject.spi.guice.GuiceContext

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

import com.google.inject.AbstractModule;
import com.google.inject.Binding;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.ProvisionException;
import com.google.inject.TypeLiteral;
import com.google.inject.binder.LinkedBindingBuilder;
import com.google.inject.binder.ScopedBindingBuilder;
import com.google.inject.internal.BindingImpl;
import com.google.inject.internal.Scoping;
import com.google.inject.matcher.Matchers;
import com.google.inject.name.Named;
import com.google.inject.spi.TypeEncounter;
import com.google.inject.spi.TypeListener;
import juzu.Scope;
import juzu.impl.common.Tools;
import juzu.impl.inject.ScopeController;
import juzu.impl.inject.spi.InjectorProvider;
import juzu.impl.inject.spi.InjectionContext;

import javax.annotation.PreDestroy;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/** @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a> */
public class GuiceContext extends InjectionContext<GuiceBean, Object> {

  /** . */
  private Injector injector;

  /** . */
  private final ClassLoader classLoader;

  /** . */
  private final Map<String, Key<?>> nameMap;

  /** . */
  private final ScopeController scopeController;

  public GuiceContext(final GuiceInjector bootstrap) {

    //
    this.scopeController = new ScopeController();

    AbstractModule module = new AbstractModule() {
      @Override
      protected void configure() {
        //
        bindListener(Matchers.any(), new TypeListener() {
          public <I> void hear(TypeLiteral<I> type, TypeEncounter<I> encounter) {
            encounter.register(new PostConstructInjectionListener());
          }
        });

        // Bind guice scopes
        for (Scope scope : bootstrap.scopes) {
          if (!scope.isBuiltIn()) {
            bindScope(scope.getAnnotationType(), new GuiceScope(scope, scopeController));
          }
        }

        // Bind beans
        for (BeanBinding<?> beanBinding : bootstrap.bindings) {

          // Get a binding key
          Key key;
          if (beanBinding.qualifiers != null && beanBinding.qualifiers.size() > 0) {
            Iterator<Annotation> i = beanBinding.qualifiers.iterator();
            // Construction to make compiler happy
//            b = a.annotatedWith(i.next());
//            while (i.hasNext()) {
//              b = a.annotatedWith(i.next());
//            }
            key = Key.get(beanBinding.type, i.next());
          }
          else {
            key = Key.get(beanBinding.type);
          }
          LinkedBindingBuilder b = bind(key);

          //
          ScopedBindingBuilder c;
          if (beanBinding instanceof BeanBinding.ToInstance) {
            BeanBinding.ToInstance d = (BeanBinding.ToInstance)beanBinding;
            b.toInstance(d.instance);
            c = b;
          }
          else if (beanBinding instanceof BeanBinding.ToProviderInstance) {
            BeanBinding.ToProviderInstance d = (BeanBinding.ToProviderInstance)beanBinding;
            c = b.toProvider(d);
            if (beanBinding.scopeType != null) {
              c.in(beanBinding.scopeType);
            }
          }
          else {
            if (beanBinding instanceof BeanBinding.ToProviderType) {
              BeanBinding.ToProviderType d = (BeanBinding.ToProviderType)beanBinding;
              c = b.toProvider(d.provider);
            }
            else {
              BeanBinding.ToType d = (BeanBinding.ToType)beanBinding;
              if (d.qualifiers != null) {
                if (d.implementationType != null) {
                  c = b.to(d.implementationType);
                  // Guice trick : need to bind alias so the implementation type will be bound with the qualifier
                  bind(Key.get(d.implementationType, key.getAnnotation())).toProvider(new BeanAlias(key));
                }
                else {
                  c = b.to(beanBinding.type);
                }
              }
              else {
                if (d.implementationType != null) {
                  c = b.to(d.implementationType);
                }
                else {
                  c = b;
                }
              }
            }
            if (beanBinding.scopeType != null) {
              c.in(beanBinding.scopeType);
            }
          }
        }

        // Bind the manager itself
        bind(InjectionContext.class).toInstance(GuiceContext.this);
      }

      private <T> void bind(Class<T> clazz, T instance) {
        bind(clazz).toInstance(instance);
      }
    };

    //
    Map<String, Key<?>> nameMap = new HashMap<String, Key<?>>();
    Injector injector = Guice.createInjector(module);
    for (Key<?> key : injector.getBindings().keySet()) {
      Class<? extends Annotation> annotationType = key.getAnnotationType();
      if (annotationType != null && Named.class.isAssignableFrom(annotationType)) {
        Named named = (Named)key.getAnnotation();
        nameMap.put(named.value(), key);
      }
    }

    //
    this.injector = injector;
    this.nameMap = nameMap;
    this.classLoader = bootstrap.classLoader;
  }

  public InjectorProvider getProvider() {
    return InjectorProvider.GUICE;
  }

  @Override
  public ScopeController getScopeController() {
    return scopeController;
  }

  public ClassLoader getClassLoader() {
    return classLoader;
  }

  public GuiceBean resolveBean(Class<?> type) {
    Binding<?> binding = injector.getBinding(type);
    return binding != null ? new GuiceBean(binding) : null;
  }

  public Iterable<GuiceBean> resolveBeans(Class<?> type) {
    List<GuiceBean> beans = new ArrayList<GuiceBean>();
    Map<Key<?>, Binding<?>> allBindings = injector.getAllBindings();
    Collection<Binding<?>> bindings = allBindings.values();
    for (Binding<?> binding : bindings) {
      Class bindingType = binding.getKey().getTypeLiteral().getRawType();
      if (type.isAssignableFrom(bindingType)) {
        beans.add(new GuiceBean(binding));
      }
    }
    return beans;
  }

  public GuiceBean resolveBean(String name) {
    Key<?> key = nameMap.get(name);
    GuiceBean bean = null;
    if (key != null) {
      bean = new GuiceBean(injector.getBinding(key));
    }
    return bean;
  }

  public Object createContext(GuiceBean bean) throws InvocationTargetException {
    try {
      return bean.binding.getProvider().get();
    }
    catch (ProvisionException e) {
      throw new InvocationTargetException(Tools.safeCause(e));
    }
  }

  public Object getInstance(GuiceBean bean, Object context) throws InvocationTargetException {
    return context;
  }

  public void releaseContext(GuiceBean bean, Object context) {
    Scoping scoping = ((BindingImpl)bean.binding).getScoping();
    if (scoping.isNoScope()) {
      invokePreDestroy(context);
    }
  }

  static void invokePreDestroy(Object o) {
    for (Method method : o.getClass().getMethods()) {
      if (
        Modifier.isPublic(method.getModifiers()) &&
          !Modifier.isStatic(method.getModifiers()) &&
          method.getAnnotation(PreDestroy.class) != null) {
        try {
          method.invoke(o);
        }
        catch (IllegalAccessException e) {
          throw new UnsupportedOperationException("handle me gracefully", e);
        }
        catch (InvocationTargetException e) {
          throw new UnsupportedOperationException("handle me gracefully", e);
        }
      }
    }
  }

  public void close() {
    for (Binding<?> binding : injector.getAllBindings().values()) {
      Scoping scoping = ((BindingImpl)binding).getScoping();
      if (scoping == Scoping.SINGLETON_INSTANCE) {
        invokePreDestroy(binding.getProvider().get());
      }
    }
  }
}
TOP

Related Classes of juzu.impl.inject.spi.guice.GuiceContext

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.