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 */
017package org.apache.wicket.guice;
018
019import com.google.inject.Guice;
020import com.google.inject.ImplementedBy;
021import com.google.inject.Injector;
022import com.google.inject.Module;
023import com.google.inject.Stage;
024import org.apache.wicket.Application;
025import org.apache.wicket.Component;
026import org.apache.wicket.IBehaviorInstantiationListener;
027import org.apache.wicket.Session;
028import org.apache.wicket.application.IComponentInstantiationListener;
029import org.apache.wicket.behavior.Behavior;
030import org.apache.wicket.injection.IFieldValueFactory;
031import org.apache.wicket.model.Model;
032
033/**
034 * Injects field members of components and behaviors using Guice.
035 * <p>
036 * Add this to your application in its {@link Application#init()} method like so:
037 * 
038 * <pre>
039 * getComponentInstantiationListeners().add(new GuiceComponentInjector(this));
040 * </pre>
041 * 
042 * <p>
043 * There are different constructors for this object depending on how you want to wire things. See
044 * the javadoc for the constructors for more information.
045 * </p>
046 * <p>
047 * Only Wicket {@link Component}s and {@link Behavior}s are automatically injected, other classes
048 * such as {@link Session}, {@link Model}, and any other POJO can be injected by calling
049 * <code>Injector.get().inject(this)</code> in their constructor.
050 * </p>
051 * 
052 * @author Alastair Maw
053 */
054public class GuiceComponentInjector extends org.apache.wicket.injection.Injector
055        implements
056                IComponentInstantiationListener,
057                IBehaviorInstantiationListener
058{
059        private final IFieldValueFactory fieldValueFactory;
060
061        /**
062         * Creates a new Wicket GuiceComponentInjector instance.
063         * <p>
064         * Internally this will create a new Guice {@link Injector} instance, with no {@link Module}
065         * instances. This is only useful if your beans have appropriate {@link ImplementedBy}
066         * annotations on them so that they can be automatically picked up with no extra configuration
067         * code.
068         * 
069         * @param app
070         */
071        public GuiceComponentInjector(final Application app)
072        {
073                this(app, new Module[0]);
074        }
075
076        /**
077         * Creates a new Wicket GuiceComponentInjector instance, using the supplied Guice {@link Module}
078         * instances to create a new Guice {@link Injector} instance internally.
079         * 
080         * @param app
081         * @param modules
082         */
083        public GuiceComponentInjector(final Application app, final Module... modules)
084        {
085                this(app, Guice.createInjector(app.usesDeploymentConfig() ? Stage.PRODUCTION
086                        : Stage.DEVELOPMENT, modules), true);
087        }
088
089        /**
090         * Constructor
091         * 
092         * @param app
093         * @param injector
094         */
095        public GuiceComponentInjector(final Application app, final Injector injector)
096        {
097                this(app, injector, true);
098        }
099
100        /**
101         * Creates a new Wicket GuiceComponentInjector instance, using the provided Guice
102         * {@link Injector} instance.
103         * 
104         * @param app
105         * @param injector
106         * @param wrapInProxies
107         *            whether or not wicket should wrap dependencies with specialized proxies that can
108         *            be safely serialized. in most cases this should be set to true.
109         */
110        public GuiceComponentInjector(final Application app, final Injector injector,
111                final boolean wrapInProxies)
112        {
113                app.setMetaData(GuiceInjectorHolder.INJECTOR_KEY, new GuiceInjectorHolder(injector));
114                fieldValueFactory = new GuiceFieldValueFactory(wrapInProxies);
115                app.getBehaviorInstantiationListeners().add(this);
116                bind(app);
117        }
118
119        @Override
120        public void inject(final Object object)
121        {
122                inject(object, fieldValueFactory);
123        }
124
125        @Override
126        public void onInstantiation(final Component component)
127        {
128                inject(component);
129        }
130
131        @Override
132        public void onInstantiation(Behavior behavior)
133        {
134                inject(behavior);
135        }
136}