001    /**
002     Licensed to the Apache Software Foundation (ASF) under one or more
003     contributor license agreements.  See the NOTICE file distributed with
004     this work for additional information regarding copyright ownership.
005     The ASF licenses this file to You under the Apache License, Version 2.0
006     (the "License"); you may not use this file except in compliance with
007     the License.  You may obtain a copy of the License at
008    
009          http://www.apache.org/licenses/LICENSE-2.0
010    
011     Unless required by applicable law or agreed to in writing, software
012     distributed under the License is distributed on an "AS IS" BASIS,
013     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     See the License for the specific language governing permissions and
015     limitations under the License.
016    */
017    package org.apache.commons.inject.impl;
018    
019    import java.util.ArrayList;
020    import java.util.Arrays;
021    import java.util.Collection;
022    import java.util.List;
023    
024    import org.apache.commons.inject.api.IBinding;
025    import org.apache.commons.inject.api.IInjector;
026    import org.apache.commons.inject.api.IInjectorBuilder;
027    import org.apache.commons.inject.api.IKey;
028    import org.apache.commons.inject.api.IPoint;
029    import org.apache.commons.inject.api.IProvider;
030    import org.apache.commons.inject.api.Key;
031    import org.apache.commons.inject.api.bind.IAnnotatedBindingBuilder;
032    import org.apache.commons.inject.api.bind.IBinder;
033    import org.apache.commons.inject.api.bind.ILinkedBindingBuilder;
034    import org.apache.commons.inject.api.bind.IModule;
035    import org.apache.commons.inject.api.bind.IBinder.IInjectionListener;
036    import org.apache.commons.inject.api.bind.IBinder.IInjectionParticipator;
037    import org.apache.commons.inject.api.bind.IBinder.IInjectorBuildListener;
038    import org.apache.commons.inject.impl.bind.DefaultBinding;
039    import org.apache.commons.inject.impl.bind.DefaultBindingBuilder;
040    
041    public class DefaultInjectorBuilder implements IInjectorBuilder {
042            private final Collection<IModule> modules;
043            private final List<IInjectionListener> injectionListeners = new ArrayList<IInjectionListener>();
044            private final List<IInjectionParticipator> injectionParticipators = new ArrayList<IInjectionParticipator>();
045            private final List<IInjectorBuildListener> injectorBuildListeners = new ArrayList<IInjectorBuildListener>();
046    
047            public DefaultInjectorBuilder(Collection<IModule> pModules) {
048                    modules = pModules;
049            }
050    
051            public DefaultInjectorBuilder() {
052                    modules = new ArrayList<IModule>();
053            }
054    
055            public IInjector build() {
056                    final MutableBindingSet mutableBindings = new MutableBindingSet();
057                    configure(mutableBindings);
058                    final IKey<IInjector> key = new Key<IInjector>(IInjector.class);
059                    final BindingProxy<IInjector> bindingProxy = (BindingProxy<IInjector>) mutableBindings.requireBinding(key, "to create an automatic binding for an injector.");
060                    bindingProxy.setResolvedLater(true);
061                    final ResolvableBindingSet resolvableBindings = new ResolvableBindingSet(mutableBindings);
062                    resolve(resolvableBindings);
063                    final ImmutableBindingSet immutableBindings = new ImmutableBindingSet(resolvableBindings);
064                    final DefaultInjector injector = new DefaultInjector(immutableBindings);
065                    final IProvider<IInjector> provider = new IProvider<IInjector>(){
066                            @Override
067                            public IInjector get() {
068                                    return injector;
069                            }
070    
071                            @Override
072                            public Class<? extends IInjector> getType() {
073                                    return injector.getClass();
074                            }
075    
076                            @Override
077                            public IInjector get(IInjector pInjector) {
078                                    return get();
079                            }
080                    };
081                    final IPoint<IInjector> point = new IPoint<IInjector>(){
082                            @Override
083                            public void injectTo(IInjector pInstance, IInjector pInjector) {
084                                    // Does nothing.
085                            }
086                    };
087                    bindingProxy.setBinding(new DefaultBinding<IInjector>(provider, point));
088                    for (IBinding<?> binding : immutableBindings.getAllBindings()) {
089                            if (binding instanceof IInjectorAware) {
090                                    ((IInjectorAware) binding).init(injector);
091                            } else {
092                                    throw new IllegalStateException("No InjectorAware: " + binding);
093                            }
094                    }
095                    for (IInjectorBuildListener listener : injectorBuildListeners) {
096                            listener.created(injector);
097                    }
098                    return injector;
099            }
100    
101            protected void resolve(ResolvableBindingSet pBindings) {
102                    pBindings.resolve();
103            }
104            
105            protected void configure(final MutableBindingSet mutableBindings) {
106                    final List<DefaultBindingBuilder<?>> builders = new ArrayList<DefaultBindingBuilder<?>>();
107                    final IBinder binder = newBinder(builders);
108                    for (IModule module : modules) {
109                            module.configure(binder);
110                    }
111                    for (DefaultBindingBuilder<?> builder : builders) {
112                            builder.build(mutableBindings, injectionListeners, injectionParticipators);
113                    }
114            }
115    
116            private IBinder newBinder(final List<DefaultBindingBuilder<?>> builders) {
117                    return new IBinder(){
118                            @Override
119                            public <T> IAnnotatedBindingBuilder<T> bind(Class<T> pType) {
120                                    final DefaultBindingBuilder<T> builder = new DefaultBindingBuilder<T>(pType);
121                                    builders.add(builder);
122                                    return builder;
123                            }
124    
125                            @Override
126                            public <T> IAnnotatedBindingBuilder<T> bind(Class<T> pType,
127                                            String pName) {
128                                    final DefaultBindingBuilder<T> builder = new DefaultBindingBuilder<T>(pType, pName);
129                                    builders.add(builder);
130                                    return builder;
131                            }
132    
133                            @Override
134                            public <T> ILinkedBindingBuilder<T> bind(IKey<T> pKey) {
135                                    final DefaultBindingBuilder<T> builder = new DefaultBindingBuilder<T>(pKey);
136                                    builders.add(builder);
137                                    return builder;
138                            }
139    
140                            @Override
141                            public boolean add(IInjectionParticipator pParticipator) {
142                                    if (pParticipator == null) {
143                                            throw new NullPointerException("The participator must not be null.");
144                                    }
145                                    return injectionParticipators.add(pParticipator);
146                            }
147    
148                            @Override
149                            public boolean add(IInjectionListener pListener) {
150                                    if (pListener == null) {
151                                            throw new NullPointerException("The listener must not be null.");
152                                    }
153                                    return injectionListeners.add(pListener);
154                            }
155    
156                            @Override
157                            public boolean add(IInjectorBuildListener pListener) {
158                                    if (pListener == null) {
159                                            throw new NullPointerException("The listener must not be null.");
160                                    }
161                                    return injectorBuildListeners.add(pListener);
162                            }
163                    };
164            }
165    
166            @Override
167            public IInjectorBuilder modules(IModule... pModules) {
168                    if (pModules == null) {
169                            throw new NullPointerException("The module list must not be null.");
170                    }
171                    modules.addAll(Arrays.asList(pModules));
172                    return this;
173            }
174    
175            @Override
176            public IInjectorBuilder modules(Collection<IModule> pModules) {
177                    if (pModules == null) {
178                            throw new NullPointerException("The module list must not be null.");
179                    }
180                    modules.addAll(pModules);
181                    return this;
182            }
183    }