package io.graceland.filter; import javax.servlet.Filter; import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import com.google.inject.Binder; import com.google.inject.Provider; import com.google.inject.multibindings.Multibinder; import io.graceland.inject.Graceland; /** * Used to create and bind a {@link io.graceland.filter.FilterSpec}. * * @see io.graceland.filter.FilterSpec * @see io.graceland.filter.FilterProvider * @see io.graceland.filter.FilterPattern */ public class FilterBinder { public static final int DEFAULT_PRIORITY = 500; public static final FilterPattern DEFAULT_PATTERN = FilterPattern.forPatterns("/*"); private final Binder binder; private final Class<? extends Filter> filterClass; private final Provider<? extends Filter> filterProvider; private final ImmutableList.Builder<FilterPattern> filterPatterns; private int priority = DEFAULT_PRIORITY; private Optional<String> name = Optional.absent(); FilterBinder( Binder binder, Class<? extends Filter> filterClass, Provider<? extends Filter> filterProvider) { this.binder = Preconditions.checkNotNull(binder, "Binder cannot be null."); this.filterClass = Preconditions.checkNotNull(filterClass, "Filter Class cannot be null."); this.filterProvider = Preconditions.checkNotNull(filterProvider, "Filter Provider cannot be null."); this.filterPatterns = ImmutableList.builder(); } /** * Builds a Filter Binder using a Filter instance rather than a class. It will use a * {@link io.graceland.filter.FilterProvider} as the provider. * * @param binder The Binder for the current Guice module. * @param filter The Filter to be bound. * @return A working FilterBinder. */ public static FilterBinder forInstance(Binder binder, Filter filter) { Preconditions.checkNotNull(filter, "Filter cannot be null."); return new FilterBinder(binder, filter.getClass(), new FilterProvider(filter)); } /** * Builds a Filter Binder using a Filter Class rather than an instance. It will use the {@link com.google.inject.Binder} * to create a {@link com.google.inject.Provider} used in the Filter Binder. * * @param binder The Binder for the current Guice module. * @param filterClass The Class of a Filter to be bound. * @return A working FilterBinder. */ public static FilterBinder forClass( Binder binder, Class<? extends Filter> filterClass) { Preconditions.checkNotNull(binder, "Binder cannot be null."); Preconditions.checkNotNull(filterClass, "Filter Class cannot be null."); return new FilterBinder( binder, filterClass, binder.getProvider(filterClass)); } /** * Sets the priority of the filter. If none is set, the {@link io.graceland.filter.FilterBinder#DEFAULT_PRIORITY} * is used. * * @param filterPriority The priority to use for the filter. * @return The current Filter Binder. */ public FilterBinder withPriority(int filterPriority) { this.priority = filterPriority; return this; } /** * Sets the name of the filter. If none is set, the filter's class simple name will be used. * * @param filterName The name to use for the filter. * @return The current Filter Binder. */ public FilterBinder withName(String filterName) { this.name = Optional.fromNullable(filterName); return this; } /** * Adds a {@link io.graceland.filter.FilterPattern} to the final filter. You can add more than one with the binder. * * @param filterPattern The filter pattern to add. * @return The current Filter Binder. */ public FilterBinder addPattern(FilterPattern filterPattern) { Preconditions.checkNotNull(filterPattern, "Filter Pattern cannot be null."); filterPatterns.add(filterPattern); return this; } /** * Builds a {@link io.graceland.filter.FilterSpec} and adds it to the Guice dependency graph. */ public void bind() { FilterSpec fitlerSpec = new FilterSpec( filterProvider, priority, name.or(filterClass.getSimpleName()), buildPatterns()); Multibinder .newSetBinder(binder, FilterSpec.class, Graceland.class) .addBinding() .toInstance(fitlerSpec); } private ImmutableList<FilterPattern> buildPatterns() { ImmutableList<FilterPattern> patterns = filterPatterns.build(); if (patterns.isEmpty()) { patterns = ImmutableList.of(FilterBinder.DEFAULT_PATTERN); } return patterns; } }