Coverage Report - org.apache.commons.inject.impl.bind.DefaultBindingBuilder
 
Classes in this File Line Coverage Branch Coverage Complexity
DefaultBindingBuilder
54%
83/151
46%
46/98
0
DefaultBindingBuilder$1
100%
4/4
100%
2/2
0
DefaultBindingBuilder$2
100%
2/2
N/A
0
DefaultBindingBuilder$3
0%
0/2
N/A
0
DefaultBindingBuilder$4
0%
0/2
N/A
0
DefaultBindingBuilder$5
100%
1/1
N/A
0
 
 1  
 /**
 2  
  Licensed to the Apache Software Foundation (ASF) under one or more
 3  
  contributor license agreements.  See the NOTICE file distributed with
 4  
  this work for additional information regarding copyright ownership.
 5  
  The ASF licenses this file to You under the Apache License, Version 2.0
 6  
  (the "License"); you may not use this file except in compliance with
 7  
  the License.  You may obtain a copy of the License at
 8  
 
 9  
       http://www.apache.org/licenses/LICENSE-2.0
 10  
 
 11  
  Unless required by applicable law or agreed to in writing, software
 12  
  distributed under the License is distributed on an "AS IS" BASIS,
 13  
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  See the License for the specific language governing permissions and
 15  
  limitations under the License.
 16  
 */
 17  
 package org.apache.commons.inject.impl.bind;
 18  
 
 19  
 import java.lang.annotation.Annotation;
 20  
 import java.lang.reflect.Constructor;
 21  
 import java.lang.reflect.Method;
 22  
 import java.lang.reflect.Modifier;
 23  
 import java.util.List;
 24  
 
 25  
 import org.apache.commons.inject.api.IBinding;
 26  
 import org.apache.commons.inject.api.IInjector;
 27  
 import org.apache.commons.inject.api.IKey;
 28  
 import org.apache.commons.inject.api.IPoint;
 29  
 import org.apache.commons.inject.api.IProvider;
 30  
 import org.apache.commons.inject.api.Key;
 31  
 import org.apache.commons.inject.api.bind.IAnnotatedBindingBuilder;
 32  
 import org.apache.commons.inject.api.bind.ILinkedBindingBuilder;
 33  
 import org.apache.commons.inject.api.bind.IScopedBindingBuilder;
 34  
 import org.apache.commons.inject.api.bind.Scopes;
 35  
 import org.apache.commons.inject.api.bind.IBinder.IInjectionListener;
 36  
 import org.apache.commons.inject.api.bind.IBinder.IInjectionParticipator;
 37  
 import org.apache.commons.inject.impl.AbstractBaseProvider;
 38  
 import org.apache.commons.inject.impl.AbstractScopedProvider;
 39  
 import org.apache.commons.inject.impl.Introspector;
 40  
 import org.apache.commons.inject.impl.ListPoint;
 41  
 import org.apache.commons.inject.impl.MutableBindingSet;
 42  
 import org.apache.commons.inject.impl.AbstractBindingSet.MappedKey;
 43  
 
 44  
 import com.google.inject.Provider;
 45  
 
 46  
 
 47  
 /**
 48  
  * Default implementation of a binding builder. Implements
 49  
  * {@link IAnnotatedBindingBuilder}, thus {@link IScopedBindingBuilder},
 50  
  * and {@link ILinkedBindingBuilder} as well. In other words: Under the
 51  
  * hood, you are always using this one and only binding builder.
 52  
  */
 53  8
 public class DefaultBindingBuilder<T> implements IAnnotatedBindingBuilder<T> {
 54  
         private final Class<T> sourceType;
 55  
         private final IKey<T> sourceKey;
 56  
         private Annotation sourceAnnotation;
 57  
         private Class<? extends Annotation> sourceAnnotationType;
 58  
         private T targetInstance;
 59  
         private Class<? extends T> targetType;
 60  
         private Constructor<? extends T> targetConstructor;
 61  
         private Method targetMethod;
 62  
         private Provider<? extends T> targetProvider;
 63  
         private IProvider<? extends T> targetIProvider;
 64  
         private Scopes scope;
 65  
 
 66  
         public DefaultBindingBuilder(Class<T> pType) {
 67  20
                 this(pType, Key.NO_NAME);
 68  20
         }
 69  
 
 70  36
         public DefaultBindingBuilder(Class<T> pType, String pName) {
 71  36
                 sourceKey = new Key<T>(pType, pName);
 72  36
                 sourceType = pType;
 73  36
         }
 74  
 
 75  0
         public DefaultBindingBuilder(IKey<T> pKey) {
 76  0
                 sourceKey = pKey;
 77  0
                 sourceType = null;
 78  0
         }
 79  
         
 80  
         @Override
 81  
         public void toInstance(T pInstance) {
 82  8
                 if (pInstance == null) {
 83  0
                         throw new NullPointerException("The target instance must not be null.");
 84  
                 }
 85  8
                 checkNoTarget();
 86  8
                 targetInstance = pInstance;
 87  8
                 asEagerSingleton();
 88  8
         }
 89  
 
 90  
         private void checkNoTarget() {
 91  19
                 if (targetInstance != null
 92  
                         ||  targetType != null
 93  
                         ||  targetConstructor != null
 94  
                         ||  targetMethod != null
 95  
                         ||  targetProvider != null
 96  
                         ||  targetIProvider != null) {
 97  0
                         throw new IllegalStateException("The methods " + TARGET_METHOD_LIST
 98  
                                         + " are mutually exclusive, and may be invoked only once.");
 99  
                 }
 100  19
         }
 101  
 
 102  
         private static final String SCOPE_METHOD_LIST
 103  
                 = "toInstance(Object), scope(Scopes), asEagerSingleton(), and asLazySingleton()";
 104  
         private static final String TARGET_METHOD_LIST
 105  
                 = "toInstance(Object), to(Class), to(Constructor), to(Method),"
 106  
                 + " to(Provider, Class), to(IProvider)";
 107  
         
 108  
         @Override
 109  
         public IScopedBindingBuilder<T> to(Class<? extends T> pImplClass) {
 110  11
                 if (pImplClass == null) {
 111  0
                         throw new NullPointerException("The target class must not be null.");
 112  
                 }
 113  11
                 checkNoTarget();
 114  11
                 targetType = pImplClass;
 115  11
                 return this;
 116  
         }
 117  
 
 118  
         @Override
 119  
         public IScopedBindingBuilder<T> to(Constructor<? extends T> pConstructor) {
 120  0
                 if (pConstructor == null) {
 121  0
                         throw new NullPointerException("The target constructor must not be null.");
 122  
                 }
 123  0
                 checkNoTarget();
 124  0
                 targetConstructor = pConstructor;
 125  0
                 return this;
 126  
         }
 127  
 
 128  
         @Override
 129  
         public IScopedBindingBuilder<T> to(Method pFactoryMethod) {
 130  0
                 if (pFactoryMethod == null) {
 131  0
                         throw new NullPointerException("The target constructor must not be null.");
 132  
                 }
 133  0
                 if (!Modifier.isStatic(pFactoryMethod.getModifiers())) {
 134  0
                         throw new IllegalStateException("The target method must be static.");
 135  
                 }
 136  0
                 if (pFactoryMethod.getReturnType().isPrimitive()) {
 137  0
                         throw new IllegalStateException("The target method must return a non-primitive result.");
 138  
                 }
 139  0
                 if (pFactoryMethod.getReturnType().isArray()) {
 140  0
                         throw new IllegalStateException("The target method must return a single object, and not an array.");
 141  
                 }
 142  0
                 if (Void.TYPE == pFactoryMethod.getReturnType()) {
 143  0
                         throw new IllegalStateException("The target method must return a non-void result.");
 144  
                 }
 145  0
                 checkNoTarget();
 146  0
                 targetMethod = pFactoryMethod;
 147  0
                 return this;
 148  
         }
 149  
 
 150  
         @Override
 151  
         public <S extends T> IScopedBindingBuilder<T> to(Class<S> pType,
 152  
                         Provider<S> pProvider) {
 153  0
                 if (pType == null) {
 154  0
                         throw new NullPointerException("The target type must not be null.");
 155  
                 }
 156  0
                 if (pProvider == null) {
 157  0
                         throw new NullPointerException("The target provider must not be null.");
 158  
                 }
 159  0
                 checkNoTarget();
 160  0
                 targetType = pType;
 161  0
                 targetProvider = pProvider;
 162  0
                 return this;
 163  
         }
 164  
 
 165  
         @Override
 166  
         public IScopedBindingBuilder<T> to(IProvider<? extends T> pProvider) {
 167  0
                 if (pProvider == null) {
 168  0
                         throw new NullPointerException("The target provider must not be null.");
 169  
                 }
 170  0
                 checkNoTarget();
 171  0
                 targetIProvider = pProvider;
 172  0
                 return this;
 173  
         }
 174  
 
 175  
         @Override
 176  
         public void scope(Scopes pScope) {
 177  36
                 if (pScope == null) {
 178  0
                         throw new NullPointerException("The target scope must not be null.");
 179  
                 }
 180  36
                 if (scope != null) {
 181  0
                         throw new IllegalStateException("The methods " + SCOPE_METHOD_LIST
 182  
                                         + " are mutually exclusive, and may be invoked only once.");
 183  
                 }
 184  36
                 scope = pScope;
 185  36
         }
 186  
 
 187  
         @Override
 188  
         public void asEagerSingleton() {
 189  11
                 scope(Scopes.EAGER_SINGLETON);
 190  11
         }
 191  
 
 192  
         @Override
 193  
         public void asLazySingleton() {
 194  3
                 scope(Scopes.LAZY_SINGLETON);
 195  3
         }
 196  
 
 197  
         @Override
 198  
         public ILinkedBindingBuilder<T> annotatedWith(Annotation pAnnotation) {
 199  0
                 if (pAnnotation == null) {
 200  0
                         throw new NullPointerException("The annotation must not be null.");
 201  
                 }
 202  0
                 if (sourceAnnotation != null) {
 203  0
                         throw new IllegalStateException("The method annotatedWith(Annotation) must not be invoked twice.");
 204  
                 }
 205  0
                 sourceAnnotation = pAnnotation;
 206  0
                 return this;
 207  
         }
 208  
 
 209  
         @Override
 210  
         public ILinkedBindingBuilder<T> annotatedWith(
 211  
                         Class<? extends Annotation> pAnnotationType) {
 212  2
                 if (pAnnotationType == null) {
 213  0
                         throw new NullPointerException("The annotation type must not be null.");
 214  
                 }
 215  2
                 if (sourceAnnotationType != null) {
 216  0
                         throw new IllegalStateException("The method annotatedWith(Class) must not be invoked twice.");
 217  
                 }
 218  2
                 sourceAnnotationType = pAnnotationType;
 219  2
                 return this;
 220  
         }
 221  
 
 222  
         public void build(MutableBindingSet pBindings, final List<IInjectionListener> pListeners,
 223  
                         final List<IInjectionParticipator> pParticipators) {
 224  36
                 final Class<T> baseType = getBaseType();
 225  36
                 ListPoint<T> point = Introspector.getInstance().getPoint(baseType, pBindings);
 226  36
                 final IKey<T> key = sourceKey;
 227  36
                 if (pParticipators != null) {
 228  36
                         for (IInjectionParticipator participator : pParticipators) {
 229  2
                                 final List<IPoint<Object>> points = participator.getPoints(key, baseType);
 230  2
                                 if (points != null) {
 231  2
                                         for (IPoint<Object> p : points) {
 232  
                                                 @SuppressWarnings("unchecked")
 233  1
                                                 final IPoint<T> pnt = (IPoint<T>) p;
 234  1
                                                 point.add(pnt);
 235  1
                                         }
 236  
                                 }
 237  2
                         }
 238  
                 }
 239  36
                 if (pListeners != null  &&  !pListeners.isEmpty()) {
 240  9
                         point.add(new IPoint<T>(){
 241  
                                 @Override
 242  
                                 public void injectTo(T pInstance, IInjector pInjector) {
 243  11
                                         for (IInjectionListener listener : pListeners) {
 244  11
                                                 listener.initialized(key, pInstance);
 245  
                                         }
 246  11
                                 }
 247  
                         });
 248  
                 }
 249  36
                 final IProvider<T> baseProvider = getBaseProvider(baseType, point, pBindings);
 250  36
                 final IProvider<T> scopedProvider = getScopedProvider(baseProvider);
 251  36
                 final IBinding<T> binding = new DefaultBinding<T>(scopedProvider, point);
 252  
                 final Annotation[] annotations;
 253  36
                 if (sourceAnnotation == null) {
 254  36
                         annotations = Key.NO_ANNOTATIONS;
 255  
                 } else {
 256  0
                         annotations = new Annotation[]{ sourceAnnotation };
 257  
                 }
 258  36
                 final MappedKey<T> mkey = new MappedKey<T>(sourceKey.getType(), sourceKey.getName(),
 259  
                                 annotations, sourceAnnotationType);
 260  
                                 
 261  36
                 pBindings.add(mkey, binding);
 262  36
         }
 263  
 
 264  
         private Class<T> getBaseType() {
 265  36
                 if (targetInstance != null) {
 266  
                         @SuppressWarnings("unchecked")
 267  8
                         final Class<T> cl = (Class<T>) targetInstance.getClass();
 268  8
                         return cl;
 269  
                 }
 270  28
                 if (targetProvider != null) {
 271  
                         @SuppressWarnings("unchecked")
 272  0
                         final Class<T> cl = (Class<T>) targetType;
 273  0
                         return cl;
 274  
                 }
 275  28
                 if (targetIProvider != null) {
 276  
                         @SuppressWarnings("unchecked")
 277  0
                         final Class<T> cl = (Class<T>) targetIProvider.getType();
 278  0
                         return cl;
 279  
                 }
 280  28
                 if (targetType != null) {
 281  
                         @SuppressWarnings("unchecked")
 282  11
                         final Class<T> cl = (Class<T>) targetType;
 283  11
                         return cl;
 284  
                 }
 285  17
                 if (targetConstructor != null) {
 286  
                         @SuppressWarnings("unchecked")
 287  0
                         final Class<T> cl = (Class<T>) targetConstructor.getDeclaringClass();
 288  0
                         return cl;
 289  
                 }
 290  17
                 if (targetMethod != null) {
 291  
                         @SuppressWarnings("unchecked")
 292  0
                         final Class<T> cl = (Class<T>) targetMethod.getReturnType();
 293  0
                         return cl;
 294  
                 }
 295  17
                 if (sourceType == null) {
 296  0
                         throw new IllegalStateException("Neither of the methods "
 297  
                                         + TARGET_METHOD_LIST + " has been invoked on this binding builder,"
 298  
                                         + " which is required when binding a key.");
 299  
                 }
 300  17
                 if (sourceType.isInterface()  ||  Modifier.isAbstract(sourceType.getModifiers())) {
 301  0
                         throw new IllegalStateException("Neither of the methods "
 302  
                                         + TARGET_METHOD_LIST + " has been invoked on this binding builder, "
 303  
                                         + " but cannot bind " + sourceType.getName()
 304  
                                         + " as target type, because it is an interface, or an abstract class.");
 305  
                 }
 306  17
                 return sourceType;
 307  
         }
 308  
         private AbstractBaseProvider<T> getBaseProvider(Class<T> pType, IPoint<T> pPoint, MutableBindingSet pBindings) {
 309  36
                 if (targetInstance != null) {
 310  8
                         return new AbstractBaseProvider<T>(pType, pPoint){
 311  
                                 @Override
 312  
                                 public T get() {
 313  8
                                         return targetInstance;
 314  
                                 }
 315  
                         };
 316  
                 }
 317  28
                 if (targetProvider != null) {
 318  0
                         return new AbstractBaseProvider<T>(pType, pPoint){
 319  
                                 @Override
 320  
                                 public T get() {
 321  0
                                         return (T) targetProvider.get();
 322  
                                 }
 323  
                         };
 324  
                 }
 325  28
                 if (targetIProvider != null) {
 326  0
                         return new AbstractBaseProvider<T>(pType, pPoint){
 327  
                                 @Override
 328  
                                 public T get() {
 329  0
                                         return (T) targetIProvider.get();
 330  
                                 }
 331  
                                 
 332  
                         };
 333  
                 }
 334  28
                 if (targetType != null) {
 335  
                         @SuppressWarnings("unchecked")
 336  11
                         final Class<T> cl = (Class<T>) targetType;
 337  11
                         final AbstractBaseProvider<T> abp = (AbstractBaseProvider<T>) Introspector.getInstance().getProvider(cl, pPoint, pBindings);
 338  11
                         return abp;
 339  
                 }
 340  17
                 if (targetConstructor != null) {
 341  0
                         final AbstractBaseProvider<T> abp = (AbstractBaseProvider<T>) Introspector.getInstance().getProvider(targetConstructor, pBindings);
 342  0
                         return abp;
 343  
                 }
 344  17
                 if (targetMethod != null) {
 345  
                         @SuppressWarnings("unchecked")
 346  0
                         final AbstractBaseProvider<T> abp = (AbstractBaseProvider<T>) Introspector.getInstance().getProvider(targetMethod, pBindings);
 347  0
                         return abp;
 348  
                 }
 349  17
                 if (sourceType != null) {
 350  17
                         final AbstractBaseProvider<T> abp = (AbstractBaseProvider<T>) Introspector.getInstance().getProvider(sourceType, pPoint, pBindings);
 351  17
                         return abp;
 352  
                 }
 353  0
                 throw new IllegalStateException("Neither of the methods "
 354  
                                 + TARGET_METHOD_LIST + " has been invoked on this binding builder.");
 355  
         }
 356  
 
 357  
         public AbstractScopedProvider<T> getScopedProvider(IProvider<T> pBaseProvider) {
 358  36
                 if (scope == null) {
 359  0
                         throw new IllegalStateException("Neither of the methods "
 360  
                                         + SCOPE_METHOD_LIST + " has been invoked on this binding builder.");
 361  
                         
 362  
                 }
 363  36
                 switch(scope) {
 364  
                 case PER_CALL:
 365  22
                         return new PerCallProvider<T>(pBaseProvider);
 366  
                 case EAGER_SINGLETON:
 367  11
                         return new EagerSingletonProvider<T>(pBaseProvider);
 368  
                 case LAZY_SINGLETON:
 369  3
                         return new LazySingletonProvider<T>(pBaseProvider);
 370  
                 default:
 371  0
                         throw new IllegalStateException("Invalid scope: " + scope);
 372  
                 }
 373  
         }
 374  
 }