Coverage Report - org.seasar.cubby.plugins.guice.CubbyModule
 
Classes in this File Line Coverage Branch Coverage Complexity
CubbyModule
88%
62/70
100%
6/6
0
CubbyModule$1
100%
3/3
N/A
0
CubbyModule$2
100%
4/4
N/A
0
CubbyModule$3
100%
3/3
N/A
0
CubbyModule$4
100%
4/4
N/A
0
CubbyModule$5
100%
3/3
N/A
0
CubbyModule$6
100%
4/4
N/A
0
 
 1  
 /*
 2  
  * Copyright 2004-2009 the Seasar Foundation and the Others.
 3  
  *
 4  
  * Licensed under the Apache License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  *     http://www.apache.org/licenses/LICENSE-2.0
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 13  
  * either express or implied. See the License for the specific language
 14  
  * governing permissions and limitations under the License.
 15  
  */
 16  
 package org.seasar.cubby.plugins.guice;
 17  
 
 18  
 import java.util.Collection;
 19  
 import java.util.Collections;
 20  
 import java.util.HashSet;
 21  
 import java.util.LinkedHashSet;
 22  
 import java.util.Set;
 23  
 
 24  
 import javax.servlet.http.HttpServletRequest;
 25  
 
 26  
 import org.seasar.cubby.action.ActionContext;
 27  
 import org.seasar.cubby.action.ActionErrors;
 28  
 import org.seasar.cubby.action.FlashMap;
 29  
 import org.seasar.cubby.action.impl.ActionContextImpl;
 30  
 import org.seasar.cubby.action.impl.ActionErrorsImpl;
 31  
 import org.seasar.cubby.action.impl.FlashMapImpl;
 32  
 import org.seasar.cubby.controller.FormatPattern;
 33  
 import org.seasar.cubby.controller.MessagesBehaviour;
 34  
 import org.seasar.cubby.controller.RequestParser;
 35  
 import org.seasar.cubby.controller.impl.DefaultFormatPattern;
 36  
 import org.seasar.cubby.controller.impl.DefaultMessagesBehaviour;
 37  
 import org.seasar.cubby.controller.impl.DefaultRequestParser;
 38  
 import org.seasar.cubby.controller.impl.MultipartRequestParser;
 39  
 import org.seasar.cubby.converter.Converter;
 40  
 import org.seasar.cubby.converter.impl.BigDecimalConverter;
 41  
 import org.seasar.cubby.converter.impl.BigIntegerConverter;
 42  
 import org.seasar.cubby.converter.impl.BooleanConverter;
 43  
 import org.seasar.cubby.converter.impl.ByteArrayFileItemConverter;
 44  
 import org.seasar.cubby.converter.impl.ByteConverter;
 45  
 import org.seasar.cubby.converter.impl.CharacterConverter;
 46  
 import org.seasar.cubby.converter.impl.DateConverter;
 47  
 import org.seasar.cubby.converter.impl.DoubleConverter;
 48  
 import org.seasar.cubby.converter.impl.EnumConverter;
 49  
 import org.seasar.cubby.converter.impl.FloatConverter;
 50  
 import org.seasar.cubby.converter.impl.InputStreamFileItemConverter;
 51  
 import org.seasar.cubby.converter.impl.IntegerConverter;
 52  
 import org.seasar.cubby.converter.impl.LongConverter;
 53  
 import org.seasar.cubby.converter.impl.ShortConverter;
 54  
 import org.seasar.cubby.converter.impl.SqlDateConverter;
 55  
 import org.seasar.cubby.converter.impl.SqlTimeConverter;
 56  
 import org.seasar.cubby.converter.impl.SqlTimestampConverter;
 57  
 import org.seasar.cubby.plugins.guice.spi.GuiceContainerProvider;
 58  
 import org.seasar.cubby.plugins.guice.spi.GuiceConverterProvider;
 59  
 import org.seasar.cubby.plugins.guice.spi.GuicePathResolverProvider;
 60  
 import org.seasar.cubby.plugins.guice.spi.GuiceRequestParserProvider;
 61  
 import org.seasar.cubby.routing.PathResolver;
 62  
 import org.seasar.cubby.routing.PathTemplateParser;
 63  
 import org.seasar.cubby.routing.impl.PathResolverImpl;
 64  
 import org.seasar.cubby.routing.impl.PathTemplateParserImpl;
 65  
 import org.seasar.cubby.spi.BeanDescProvider;
 66  
 import org.seasar.cubby.spi.ContainerProvider;
 67  
 import org.seasar.cubby.spi.ConverterProvider;
 68  
 import org.seasar.cubby.spi.PathResolverProvider;
 69  
 import org.seasar.cubby.spi.RequestParserProvider;
 70  
 import org.seasar.cubby.spi.beans.impl.DefaultBeanDescProvider;
 71  
 import org.seasar.cubby.util.ActionUtils;
 72  
 
 73  
 import com.google.inject.AbstractModule;
 74  
 import com.google.inject.Injector;
 75  
 import com.google.inject.Key;
 76  
 import com.google.inject.Module;
 77  
 import com.google.inject.Provides;
 78  
 import com.google.inject.Singleton;
 79  
 import com.google.inject.TypeLiteral;
 80  
 import com.google.inject.matcher.AbstractMatcher;
 81  
 import com.google.inject.servlet.RequestScoped;
 82  
 import com.google.inject.spi.TypeEncounter;
 83  
 import com.google.inject.spi.TypeListener;
 84  
 
 85  
 /**
 86  
  * Cubby の設定を行う {@link Module} です。
 87  
  * 
 88  
  * @author baba
 89  
  */
 90  40
 public class CubbyModule extends AbstractModule {
 91  
 
 92  
         /** コンテナに登録されたアクションクラスのセット。 */
 93  1
         private final Set<Class<?>> actionClasses = new LinkedHashSet<Class<?>>();
 94  
 
 95  
         /** コンテナからコンバータを取得するための {@link Key} のセット。 */
 96  1
         private final Set<Key<? extends Converter>> converterKeys = new LinkedHashSet<Key<? extends Converter>>();
 97  
 
 98  
         /** コンテナから要求解析器を取得するための {@link Key} のセット。 */
 99  1
         private final Set<Key<? extends RequestParser>> requestParserKeys = new LinkedHashSet<Key<? extends RequestParser>>();
 100  
 
 101  
         /**
 102  
          * Cubby を構成します。
 103  
          */
 104  
         @Override
 105  
         public void configure() {
 106  1
                 configureTypeListeners();
 107  1
                 configureProviders();
 108  1
                 configureComponents();
 109  1
                 configureDefaultRequestParsers();
 110  1
                 configureDefaultConverters();
 111  1
         }
 112  
 
 113  
         /**
 114  
          * {@link TypeListener} をバインドします。
 115  
          */
 116  
         private void configureTypeListeners() {
 117  
                 // action class listener
 118  1
                 bindListener(new AbstractMatcher<TypeLiteral<?>>() {
 119  
 
 120  
                         public boolean matches(final TypeLiteral<?> typeLiteral) {
 121  39
                                 final boolean matches = ActionUtils.isActionClass(typeLiteral
 122  
                                                 .getRawType());
 123  39
                                 return matches;
 124  
                         }
 125  
 
 126  1
                 }, new TypeListener() {
 127  
 
 128  
                         public <I> void hear(final TypeLiteral<I> typeLiteral,
 129  
                                         final TypeEncounter<I> typeEncounter) {
 130  1
                                 final Class<?> actionClass = typeLiteral.getRawType();
 131  1
                                 actionClasses.add(actionClass);
 132  1
                         }
 133  
 
 134  
                 });
 135  
 
 136  
                 // converter listener
 137  1
                 bindListener(new AbstractMatcher<TypeLiteral<?>>() {
 138  
 
 139  
                         public boolean matches(final TypeLiteral<?> typeLiteral) {
 140  39
                                 final boolean matches = Converter.class
 141  
                                                 .isAssignableFrom(typeLiteral.getRawType());
 142  39
                                 return matches;
 143  
                         }
 144  
 
 145  1
                 }, new TypeListener() {
 146  
 
 147  
                         public <I> void hear(final TypeLiteral<I> typeLiteral,
 148  
                                         final TypeEncounter<I> typeEncounter) {
 149  17
                                 final Key<? extends Converter> key = key(typeLiteral);
 150  17
                                 converterKeys.add(key);
 151  17
                         }
 152  
 
 153  
                 });
 154  
 
 155  
                 // request parser listener
 156  1
                 bindListener(new AbstractMatcher<TypeLiteral<?>>() {
 157  
 
 158  
                         public boolean matches(final TypeLiteral<?> typeLiteral) {
 159  39
                                 final boolean matches = RequestParser.class
 160  
                                                 .isAssignableFrom(typeLiteral.getRawType());
 161  39
                                 return matches;
 162  
                         }
 163  
 
 164  1
                 }, new TypeListener() {
 165  
 
 166  
                         public <I> void hear(final TypeLiteral<I> typeLiteral,
 167  
                                         final TypeEncounter<I> typeEncounter) {
 168  2
                                 final Key<? extends RequestParser> key = key(typeLiteral);
 169  2
                                 requestParserKeys.add(key);
 170  2
                         }
 171  
 
 172  
                 });
 173  1
         }
 174  
 
 175  
         /**
 176  
          * 以下のクラスをバインドします。
 177  
          * <ul>
 178  
          * <li>{@link ContainerProvider}</li>
 179  
          * <li>{@link BeanDescProvider}</li>
 180  
          * <li>{@link RequestParserProvider}</li>
 181  
          * <li>{@link ConverterProvider}</li>
 182  
          * <li>{@link PathResolverProvider}</li>
 183  
          * </ul>
 184  
          */
 185  
         private void configureProviders() {
 186  1
                 bind(ContainerProvider.class).to(GuiceContainerProvider.class)
 187  
                                 .asEagerSingleton();
 188  1
                 bind(BeanDescProvider.class).to(DefaultBeanDescProvider.class)
 189  
                                 .asEagerSingleton();
 190  1
                 bind(RequestParserProvider.class).to(GuiceRequestParserProvider.class)
 191  
                                 .asEagerSingleton();
 192  1
                 bind(ConverterProvider.class).to(GuiceConverterProvider.class)
 193  
                                 .asEagerSingleton();
 194  1
                 bind(PathResolverProvider.class).to(GuicePathResolverProvider.class)
 195  
                                 .asEagerSingleton();
 196  1
         }
 197  
 
 198  
         /**
 199  
          * 以下のクラスをバインドします。
 200  
          * <ul>
 201  
          * <li>{@link MessagesBehaviour}</li>
 202  
          * <li>{@link FormatPattern}</li>
 203  
          * </ul>
 204  
          */
 205  
         private void configureComponents() {
 206  1
                 bind(MessagesBehaviour.class).to(DefaultMessagesBehaviour.class)
 207  
                                 .asEagerSingleton();
 208  1
                 bind(FormatPattern.class).to(DefaultFormatPattern.class)
 209  
                                 .asEagerSingleton();
 210  1
         }
 211  
 
 212  
         /**
 213  
          * 標準の要求解析器をコンテナに登録します。
 214  
          * <p>
 215  
          * 以下の要求解析器を登録します。
 216  
          * <ol>
 217  
          * <li>{@link MultipartRequestParser}</li>
 218  
          * <li>{@link DefaultRequestParser}</li>
 219  
          * </ol>
 220  
          * </p>
 221  
          * <p>
 222  
          * 要求を解析する場合は、コンテナに登録された順序で
 223  
          * {@link RequestParser#isParsable(javax.servlet.http.HttpServletRequest)}
 224  
          * が評価されて、最初に <code>true</code> を返したインスタンスを解析に使用します。
 225  
          * {@link DefaultRequestParser#isParsable(javax.servlet.http.HttpServletRequest)}
 226  
          * は、常に <code>true</code> を返すので、 このメソッドをオーバーライドする場合は
 227  
          * {@link DefaultRequestParser} のインスタンスを最後に登録するようにしてください。
 228  
          * </p>
 229  
          */
 230  
         protected void configureDefaultRequestParsers() {
 231  1
                 bind(MultipartRequestParser.class).asEagerSingleton();
 232  1
                 bind(DefaultRequestParser.class).asEagerSingleton();
 233  1
         }
 234  
 
 235  
         /**
 236  
          * 標準のコンバータをコンテナに登録します。
 237  
          * <p>
 238  
          * 以下のコンバータが登録されます。
 239  
          * <ul>
 240  
          * <li>{@link BigDecimalConverter}</li>
 241  
          * <li>{@link BigIntegerConverter}</li>
 242  
          * <li>{@link BooleanConverter}</li>
 243  
          * <li>{@link ByteArrayFileItemConverter}</li>
 244  
          * <li>{@link ByteConverter}</li>
 245  
          * <li>{@link CharacterConverter}</li>
 246  
          * <li>{@link DateConverter}</li>
 247  
          * <li>{@link DoubleConverter}</li>
 248  
          * <li>{@link EnumConverter}</li>
 249  
          * <li>{@link FloatConverter}</li>
 250  
          * <li>{@link InputStreamFileItemConverter}</li>
 251  
          * <li>{@link IntegerConverter}</li>
 252  
          * <li>{@link LongConverter}</li>
 253  
          * <li>{@link ShortConverter}</li>
 254  
          * <li>{@link SqlDateConverter}</li>
 255  
          * <li>{@link SqlTimeConverter}</li>
 256  
          * <li>{@link SqlTimestampConverter}</li>
 257  
          * </ul>
 258  
          * </p>
 259  
          */
 260  
         protected void configureDefaultConverters() {
 261  1
                 bind(BigDecimalConverter.class).asEagerSingleton();
 262  1
                 bind(BigIntegerConverter.class).asEagerSingleton();
 263  1
                 bind(BooleanConverter.class).asEagerSingleton();
 264  1
                 bind(ByteArrayFileItemConverter.class).asEagerSingleton();
 265  1
                 bind(ByteConverter.class).asEagerSingleton();
 266  1
                 bind(CharacterConverter.class).asEagerSingleton();
 267  1
                 bind(DateConverter.class).asEagerSingleton();
 268  1
                 bind(DoubleConverter.class).asEagerSingleton();
 269  1
                 bind(EnumConverter.class).asEagerSingleton();
 270  1
                 bind(FloatConverter.class).asEagerSingleton();
 271  1
                 bind(InputStreamFileItemConverter.class).asEagerSingleton();
 272  1
                 bind(IntegerConverter.class).asEagerSingleton();
 273  1
                 bind(LongConverter.class).asEagerSingleton();
 274  1
                 bind(ShortConverter.class).asEagerSingleton();
 275  1
                 bind(SqlDateConverter.class).asEagerSingleton();
 276  1
                 bind(SqlTimeConverter.class).asEagerSingleton();
 277  1
                 bind(SqlTimestampConverter.class).asEagerSingleton();
 278  1
         }
 279  
 
 280  
         // Provider methods ------------------------------------------------
 281  
 
 282  
         @Provides
 283  
         @Singleton
 284  
         Collection<RequestParser> provideRequestParsers(final Injector injector) {
 285  1
                 final Set<RequestParser> requestParsers = new LinkedHashSet<RequestParser>();
 286  1
                 for (final Key<? extends RequestParser> key : requestParserKeys) {
 287  2
                         final RequestParser requestParser = injector.getInstance(key);
 288  2
                         requestParsers.add(requestParser);
 289  2
                 }
 290  1
                 return Collections.unmodifiableCollection(requestParsers);
 291  
         }
 292  
 
 293  
         @Provides
 294  
         @Singleton
 295  
         Collection<Converter> provideConverters(final Injector injector) {
 296  1
                 final Set<Converter> converters = new HashSet<Converter>();
 297  1
                 for (final Key<? extends Converter> key : converterKeys) {
 298  17
                         final Converter converter = injector.getInstance(key);
 299  17
                         converters.add(converter);
 300  17
                 }
 301  1
                 return Collections.unmodifiableCollection(converters);
 302  
         }
 303  
 
 304  
         @Provides
 305  
         @Singleton
 306  
         PathTemplateParser providePathTemplateParser() {
 307  0
                 final PathTemplateParser pathTemplateParser = new PathTemplateParserImpl();
 308  0
                 return pathTemplateParser;
 309  
         }
 310  
 
 311  
         @Provides
 312  
         @Singleton
 313  
         PathResolver providePathResolver(final PathTemplateParser pathTemplateParser) {
 314  1
                 final PathResolver pathResolver = new PathResolverImpl(
 315  
                                 pathTemplateParser);
 316  1
                 for (final Class<?> actionClass : actionClasses) {
 317  1
                         pathResolver.add(actionClass);
 318  
                 }
 319  1
                 return pathResolver;
 320  
         }
 321  
 
 322  
         @Provides
 323  
         @RequestScoped
 324  
         ActionErrors provideActionErrors() {
 325  0
                 final ActionErrors actionErrors = new ActionErrorsImpl();
 326  0
                 return actionErrors;
 327  
         }
 328  
 
 329  
         @Provides
 330  
         @RequestScoped
 331  
         FlashMap provideFlashMap(final HttpServletRequest request) {
 332  0
                 final FlashMap flashMap = new FlashMapImpl(request);
 333  0
                 return flashMap;
 334  
         }
 335  
 
 336  
         @Provides
 337  
         @RequestScoped
 338  
         ActionContext provideActionContext() {
 339  0
                 final ActionContext actionContext = new ActionContextImpl();
 340  0
                 return actionContext;
 341  
         }
 342  
 
 343  
         private static <T> Key<T> key(final TypeLiteral<?> typeLiteral) {
 344  
                 @SuppressWarnings("unchecked")
 345  19
                 final Key<T> key = (Key<T>) Key.get(typeLiteral);
 346  19
                 return key;
 347  
         }
 348  
 
 349  
 }