View Javadoc

1   package org.jmage.filterchain;
2   
3   import org.apache.log4j.Logger;
4   import org.apache.log4j.Priority;
5   import org.jmage.ApplicationContext;
6   import org.jmage.ImageRequest;
7   import org.jmage.JmageException;
8   import org.jmage.RequestHandler;
9   import org.jmage.filter.FilterException;
10  
11  import javax.media.jai.PlanarImage;
12  import java.net.URI;
13  import java.util.Iterator;
14  import java.util.List;
15  import java.util.Properties;
16  
17  /***
18   * FilterChainManager controls all FilterChains and acts as a delegate to all it's attached
19   * FilterChainFactories. Create FilterChains by specifying a URI filterchain:com.package.FilterChain
20   * and let the delegates work out how to create it. FilterChains can be constructed out of
21   * single filters, in which case the class name of that Filter should be provided.<p>
22   * <p/>
23   * A more sophisticated way to create chains is to serialize them into XML format. See
24   * resources/xml for examples.
25   */
26  public class FilterChainManager implements RequestHandler {
27      protected List filterChainFactories;
28      protected ApplicationContext applicationContext = null;
29  
30      protected static Logger log = Logger.getLogger(FilterChainManager.class.getName());
31      private static final String CHAIN = "chain";
32      private static final String SCHEME_ERROR = "unable to create FilterChain, need to specify a uri, chain:package.FilterChain";
33      private static final String FACTORIES_EMPTY_ERROR = "error, no FilterChainFactories configured";
34      private static final String FACTORY_FAILED_WARNING = "unable to create filter chain with factory, skipping: ";
35      private static final String FILTERCHAIN_ERROR = "unable to create filter chain, all factories failed to handle: ";
36      private static final String FILTERCHAIN_SUCCESS = " created FilterChain for: ";
37  
38      /***
39       * Default Constructor
40       */
41      protected FilterChainManager() {
42          //do nothing
43      }
44  
45      /***
46       * Configure FilterChainManager
47       *
48       * @param context
49       */
50      public void configure(ApplicationContext context) {
51          applicationContext = context;
52      }
53  
54      /***
55       * Creates a EncoderManager for an array of given FilterChainFactories
56       *
57       * @param filterChainFactories
58       */
59      public FilterChainManager(List filterChainFactories) {
60          this.filterChainFactories = filterChainFactories;
61      }
62  
63      /***
64       * Filters an ImageRequest with an existing Filterchain
65       *
66       * @param request the request
67       * @throws FilterChainException
68       * @throws FilterException
69       */
70      public void handle(ImageRequest request) throws JmageException {
71          request.setImage(this.filter(request));
72      }
73  
74      /***
75       * Creates a FilterChain object to use for a given unique chainUri, denoted by a URI
76       * following the convention filterchain:com.package.FilterChain
77       *
78       * @param request the ImageRequest
79       * @return the FilterChain object.
80       * @throws FilterChainException if the filterchain cannot be constructed or handled properly
81       */
82      protected FilterChain[] create(ImageRequest request) throws FilterChainException, FilterException {
83          FilterChain[] chains = null;
84  
85          //validation
86          assert (filterChainFactories.size() > 0) : FACTORIES_EMPTY_ERROR;
87  
88          //see how many chains
89          int chainSize = request.getFilterChainURI().length;
90          chains = new FilterChain[chainSize];
91  
92          //iterate over them
93          for (int i = 0; i < chainSize; i++) {
94              Iterator it = filterChainFactories.iterator();
95              //for each chain, iterate over factories and try to create
96              if (!CHAIN.equals(request.getFilterChainURI()[i].getScheme())) {
97                  throw new FilterChainException(SCHEME_ERROR);
98              }
99              String filterChain = request.getFilterChainURI()[i].getSchemeSpecificPart();
100             do {
101                 FilterChainFactory factory = (FilterChainFactory) it.next();
102                 try {
103                     //create a single filterchain and update it's properties
104                     chains[i] = factory.createFrom(URI.create(this.lookupFilterChainName(filterChain)));
105                     chains[i].updateConfigurableFilters(request.getFilterChainProperties() != null ? request.getFilterChainProperties() : new Properties());
106                     chains[i].updateConfigurableFilters(
107                             request.getFilterChainProperties().get(filterChain) != null ? (Properties) request.getFilterChainProperties().get(filterChain) : new Properties());
108                 } catch (FilterChainException e) {
109                     if (log.isDebugEnabled()) log.debug(FACTORY_FAILED_WARNING + factory.getClass().getName());
110                 }
111             } while (chains[i] == null && it.hasNext());
112         }
113 
114         if (chains[0] != null) {
115             if (log.isInfoEnabled()) log.info(FILTERCHAIN_SUCCESS + request.getFilterChainURI().toString());
116         } else {
117             if (log.isEnabledFor(Priority.ERROR)) log.error(FILTERCHAIN_ERROR + request.getFilterChainURI().toString());
118             throw new FilterChainException(FILTERCHAIN_ERROR + request.getFilterChainURI().toString());
119         }
120         return chains;
121     }
122 
123     /***
124      * Filters an image through an existing FilterChain[].
125      *
126      * @param chains the FilterChain[]
127      * @param image  the image
128      * @return the filtered image
129      * @throws FilterException
130      */
131     protected PlanarImage doFilter(FilterChain[] chains, PlanarImage image) throws FilterException {
132         //iterate over all filterchains and pipe the image through them
133         for (int i = 0; i < chains.length; i++) {
134             image = chains[i].filter(image);
135         }
136         return image;
137     }
138 
139     /***
140      * Convenience method combining filter creation and image filtering. Use this if you need the FilterChain
141      * only for one ImageRequest. Builds an unconfigured FilterChain and filters an image through it instantly.
142      *
143      * @param imageRequest the request
144      * @return the filtered image
145      * @throws FilterChainException if the filterchain can't be created or found
146      * @throws FilterException      if the filterchain can't filter the image.
147      */
148     protected PlanarImage filter(ImageRequest imageRequest) throws FilterChainException, FilterException {
149         FilterChain[] chains = this.create(imageRequest);
150         return this.doFilter(chains, imageRequest.getImage());
151     }
152 
153     protected String lookupFilterChainName(String filterChain) {
154         String filterChainName = applicationContext.getProperty(filterChain);
155         return filterChainName != null ? filterChainName : filterChain;
156     }
157 
158     public String toString() {
159         return "[" + this.getClass().getName() + "#" + this.hashCode() + "]";
160     }
161 }