alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (CheckedProviderMethodsModule.java)

This example Java source code file (CheckedProviderMethodsModule.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

annotation, checkedprovidermethodsmodule, checkedprovides, class, define, errors, key, list, log, logger_key, logging, logprovider, member, object, override, reflection, suppresswarnings, typeliteral, util

The CheckedProviderMethodsModule.java Java example source code

/**
 * Copyright (C) 2010 Google Inc.
 *
 * 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 com.google.inject.throwingproviders;

import static com.google.common.base.Preconditions.checkNotNull;

import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.inject.Binder;
import com.google.inject.Key;
import com.google.inject.Module;
import com.google.inject.Provider;
import com.google.inject.TypeLiteral;
import com.google.inject.internal.Annotations;
import com.google.inject.internal.Errors;
import com.google.inject.internal.UniqueAnnotations;
import com.google.inject.spi.Dependency;
import com.google.inject.spi.Message;
import com.google.inject.util.Modules;

import java.lang.annotation.Annotation;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.util.List;
import java.util.logging.Logger;

/**
 * Creates bindings to methods annotated with {@literal @}{@link CheckedProvides}. Use the scope
 * and binding annotations on the provider method to configure the binding.
 * 
 * @author sameb@google.com (Sam Berlin)
 */
final class CheckedProviderMethodsModule implements Module {
  private static final Key<Logger> LOGGER_KEY = Key.get(Logger.class);

  private final Object delegate;
  private final TypeLiteral<?> typeLiteral;

  private CheckedProviderMethodsModule(Object delegate) {
    this.delegate = checkNotNull(delegate, "delegate");
    this.typeLiteral = TypeLiteral.get(this.delegate.getClass());
  }

  /**
   * Returns a module which creates bindings for provider methods from the given module.
   */
  static Module forModule(Module module) {
    // avoid infinite recursion, since installing a module always installs itself
    if (module instanceof CheckedProviderMethodsModule) {
      return Modules.EMPTY_MODULE;
    }

    return new CheckedProviderMethodsModule(module);
  }
  
  public synchronized void configure(Binder binder) {
    for (CheckedProviderMethod<?> throwingProviderMethod : getProviderMethods(binder)) {
      throwingProviderMethod.configure(binder);
    }
  }

  List<CheckedProviderMethod getProviderMethods(Binder binder) {
    List<CheckedProviderMethod result = Lists.newArrayList();
    for (Class<?> c = delegate.getClass(); c != Object.class; c = c.getSuperclass()) {
      for (Method method : c.getDeclaredMethods()) {
        CheckedProvides checkedProvides = method.getAnnotation(CheckedProvides.class);
        if(checkedProvides != null) {
          result.add(createProviderMethod(binder, method, checkedProvides));
        }
      }
    }
    return result;
  }

  <T> CheckedProviderMethod createProviderMethod(Binder binder, final Method method,
      CheckedProvides checkedProvides) {
    @SuppressWarnings("rawtypes")
    Class<? extends CheckedProvider> throwingProvider = checkedProvides.value();
    binder = binder.withSource(method);
    Errors errors = new Errors(method);

    // prepare the parameter providers
    List<Dependency dependencies = Lists.newArrayList();
    List<Provider parameterProviders = Lists.newArrayList();
    List<TypeLiteral parameterTypes = typeLiteral.getParameterTypes(method);
    Annotation[][] parameterAnnotations = method.getParameterAnnotations();
    for (int i = 0; i < parameterTypes.size(); i++) {
      Key<?> key = getKey(errors, parameterTypes.get(i), method, parameterAnnotations[i]);
      if (key.equals(LOGGER_KEY)) {
        // If it was a Logger, change the key to be unique & bind it to a
        // provider that provides a logger with a proper name.
        // This solves issue 482 (returning a new anonymous logger on every call exhausts memory)
        Key<Logger> loggerKey = Key.get(Logger.class, UniqueAnnotations.create());
        binder.bind(loggerKey).toProvider(new LogProvider(method));
        key = loggerKey;
      }
      dependencies.add(Dependency.get(key));
      parameterProviders.add(binder.getProvider(key));        
    }

    @SuppressWarnings("unchecked") // Define T as the method's return type.
    TypeLiteral<T> returnType = (TypeLiteral) typeLiteral.getReturnType(method);
    List<TypeLiteral exceptionTypes = typeLiteral.getExceptionTypes(method);

    Key<T> key = getKey(errors, returnType, method, method.getAnnotations());
    Class<? extends Annotation> scopeAnnotation
        = Annotations.findScopeAnnotation(errors, method.getAnnotations());

    for (Message message : errors.getMessages()) {
      binder.addError(message);
    }

    return new CheckedProviderMethod<T>(key, method, delegate, ImmutableSet.copyOf(dependencies),
        parameterProviders, scopeAnnotation, throwingProvider, exceptionTypes, 
        checkedProvides.scopeExceptions()); 
  }

  <T> Key getKey(Errors errors, TypeLiteral type, Member member, Annotation[] annotations) {
    Annotation bindingAnnotation = Annotations.findBindingAnnotation(errors, member, annotations);
    return bindingAnnotation == null ? Key.get(type) : Key.get(type, bindingAnnotation);
  }

  @Override public boolean equals(Object o) {
    return o instanceof CheckedProviderMethodsModule
        && ((CheckedProviderMethodsModule) o).delegate == delegate;
  }

  @Override public int hashCode() {
    return delegate.hashCode();
  }
  
  /** A provider that returns a logger based on the method name. */
  private static final class LogProvider implements Provider<Logger> {
    private final String name;
    
    public LogProvider(Method method) {
      this.name = method.getDeclaringClass().getName() + "." + method.getName();
    }
    
    public Logger get() {
      return Logger.getLogger(name);
    }
  }
}

Other Java examples (source code examples)

Here is a short list of links related to this Java CheckedProviderMethodsModule.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.