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.filter.FilterException;
7 import org.jmage.resource.ResourceException;
8 import org.jmage.util.XmlUtil;
9 import org.w3c.dom.Document;
10
11 import javax.servlet.ServletContext;
12 import java.io.File;
13 import java.io.FileInputStream;
14 import java.io.InputStream;
15 import java.net.URI;
16 import java.util.Properties;
17
18 /***
19 * Creates a filter filterchain from serialized xml format
20 */
21 public class XmlFilterChainFactory implements FilterChainFactory {
22 protected XmlFilterChainDeserializer xmlFilterChainDeserializer;
23 protected ApplicationContext applicationContext = null;
24 protected ServletContext servletContext = null;
25
26 protected static Logger log = Logger.getLogger(XmlFilterChainFactory.class.getName());
27
28 private static XmlUtil xmlUtil = new XmlUtil();
29
30 private static final String FILE_LOADED = " loaded xml filterchain from file: ";
31 private static final String FILE_LOADERROR = "unable to load xml filterchain from file: ";
32 private static final String FILTERCHAIN_ERROR = "unable to create xml filterchain: ";
33 private static final String CAUSE = ", cause: ";
34 private static final String XML_SUFFIX = ".xml";
35 private static final String REGEX_DOT = "//.";
36 private static final String SLASH = "/";
37 private static final String SERVLET_CONTEXT = "SERVLET_CONTEXT";
38 private static final String XML = "xml";
39 private static final String SERVLET_LOADERROR = "unable to load xml filterchain from servlet container";
40 private static final String SERVLET_LOADED = " loaded xml filterchain from servlet container: ";
41 private static final String CURRENT_DIR = ".";
42 private static final String resourcedir = "resourcedir";
43 private static final String REGEX_BACKSLASH = "////";
44 private static final String DOLLAR = "$";
45 private static final String DOT = ".";
46
47
48 public XmlFilterChainFactory() {
49 xmlFilterChainDeserializer = new XmlFilterChainDeserializer();
50 }
51
52 public void configure(ApplicationContext context) {
53 this.applicationContext = context;
54 servletContext = (ServletContext) this.applicationContext.get(SERVLET_CONTEXT);
55 }
56
57 /***
58 * Creates a FilterChain for a given filterChainUri by deserializing it from xml.
59 *
60 * @param filterChainUri the unique filterChainUri
61 * @return the filter filterchain
62 */
63 public FilterChain createFrom(URI filterChainUri) throws FilterChainException {
64 try {
65 Document doc = xmlUtil.read(this.getFromFile(this.mapURItoFile(filterChainUri)));
66 if (this.hasInternalChain(filterChainUri)) {
67 return xmlFilterChainDeserializer.deserialize(doc, filterChainUri.getSchemeSpecificPart());
68 } else {
69 return xmlFilterChainDeserializer.deserialize(doc);
70 }
71 } catch (Exception e) {
72 String message = FILTERCHAIN_ERROR + filterChainUri + CAUSE + e.getMessage();
73 if (log.isInfoEnabled()) log.info(message);
74 throw new FilterChainException(message);
75 }
76 }
77
78 /***
79 * Creates a FilterChain for a given name by deserializing it from xml and then applying
80 * additional filter properties on top.
81 *
82 * @param name the unique name
83 * @param filterProperties the additional filter properties
84 * @return the FilterChain
85 * @throws FilterChainException
86 */
87 public FilterChain createFrom(URI name, Properties filterProperties) throws FilterChainException {
88 try {
89 FilterChain chain = this.createFrom(name);
90 chain.updateConfigurableFilters(filterProperties);
91 return chain;
92 } catch (FilterException e) {
93 String message = FILTERCHAIN_ERROR + e.getMessage();
94 if (log.isInfoEnabled()) log.info(message);
95 throw new FilterChainException(message);
96 }
97 }
98
99 protected File mapURItoFile(URI uri) {
100 String fileName = uri.getSchemeSpecificPart();
101 fileName = fileName.replaceAll(REGEX_DOT, SLASH);
102
103
104 if (fileName.indexOf(DOLLAR) > -1) {
105 fileName = fileName.substring(0, fileName.indexOf(DOLLAR));
106 }
107
108
109 if (!fileName.endsWith(XML_SUFFIX)) {
110 fileName += XML_SUFFIX;
111 }
112
113 File file = new File(fileName);
114
115 return file;
116 }
117
118 protected boolean hasInternalChain(URI filterChainUri) {
119 return filterChainUri.toString().indexOf(DOLLAR) > -1;
120 }
121
122 /***
123 * Get the image resource from a file.
124 *
125 * @param file the file
126 * @return the image
127 * @throws org.jmage.resource.ResourceException
128 *
129 */
130 protected InputStream getFromFile(File file) throws ResourceException {
131 InputStream xml = null;
132
133
134 xml = xml == null ? this.getServletContainerResource(file) : xml;
135
136
137 xml = xml == null ? this.getJMAGEResourceDirFile(file) : xml;
138
139
140 xml = xml == null ? this.getClassPathResource(file) : xml;
141
142
143 xml = xml == null ? this.getCurrentDirFile(file) : xml;
144
145
146 if (xml == null) {
147
148
149
150 throw new ResourceException(FILE_LOADERROR + file);
151 }
152 return xml;
153 }
154
155 /***
156 * Get the xml file as inputstream from the ServletContainer.
157 *
158 * @param file the file
159 * @return the inputstream
160 */
161 protected InputStream getServletContainerResource(File file) {
162 InputStream inputStream = null;
163
164
165 if (servletContext == null) {
166 Object ctx = this.applicationContext.get(SERVLET_CONTEXT);
167 if (ctx == null) {
168 ctx = ApplicationContext.getContext().get(SERVLET_CONTEXT);
169 }
170 if (ctx != null) {
171 servletContext = (ServletContext) ctx;
172 } else {
173
174 return null;
175 }
176 }
177
178 if (!file.isAbsolute() && servletContext != null) {
179 try {
180 inputStream = servletContext.getResourceAsStream(file.getPath().replaceAll(REGEX_BACKSLASH, SLASH));
181
182
183 if (inputStream == null) {
184 file = new File(XML, file.getPath());
185 inputStream = servletContext.getResourceAsStream(file.getPath().replaceAll(REGEX_BACKSLASH, SLASH));
186 }
187 if (inputStream == null) {
188 File derived = new File(SLASH + XML, file.getPath());
189 inputStream = servletContext.getResourceAsStream(derived.getPath().replaceAll(REGEX_BACKSLASH, SLASH));
190 }
191 if (inputStream == null) {
192 File derived = new File(SLASH, file.getPath());
193 inputStream = servletContext.getResourceAsStream(derived.getPath().replaceAll(REGEX_BACKSLASH, SLASH));
194 }
195 if (log.isDebugEnabled()) log.debug(SERVLET_LOADED + file.getPath().replaceAll(REGEX_BACKSLASH, SLASH));
196 return inputStream;
197 } catch (Exception e) {
198 if (log.isDebugEnabled()) log.debug(SERVLET_LOADERROR + file.getPath().replaceAll(REGEX_BACKSLASH, SLASH));
199 }
200 }
201 return null;
202 }
203
204 /***
205 * Get the file from the classpath as a system resource
206 *
207 * @param file
208 * @return true | false
209 * @throws ResourceException
210 */
211 protected InputStream getClassPathResource(File file) throws ResourceException {
212 InputStream inputStream = null;
213 ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
214
215
216 inputStream = classLoader.getResourceAsStream(file.getPath().replaceAll(REGEX_BACKSLASH, SLASH));
217 if (inputStream == null) {
218 File derived = new File(XML, file.getPath());
219 inputStream = classLoader.getResourceAsStream(derived.getPath().replaceAll(REGEX_BACKSLASH, SLASH));
220 }
221 if (inputStream == null) {
222 File derived = new File(SLASH + XML, file.getPath());
223 inputStream = classLoader.getResourceAsStream(derived.getPath().replaceAll(REGEX_BACKSLASH, SLASH));
224 }
225 if (inputStream == null) {
226 File derived = new File(SLASH, file.getPath());
227 inputStream = classLoader.getResourceAsStream(derived.getPath().replaceAll(REGEX_BACKSLASH, SLASH));
228 }
229
230
231 classLoader = this.getClass().getClassLoader();
232
233
234 if (inputStream == null) {
235 inputStream = classLoader.getResourceAsStream(file.getPath().replaceAll(REGEX_BACKSLASH, SLASH));
236 }
237 if (inputStream == null) {
238 File derived = new File(XML, file.getPath());
239 inputStream = classLoader.getResourceAsStream(derived.getPath().replaceAll(REGEX_BACKSLASH, SLASH));
240 }
241 if (inputStream == null) {
242 File derived = new File(SLASH + XML, file.getPath());
243 inputStream = classLoader.getResourceAsStream(derived.getPath().replaceAll(REGEX_BACKSLASH, SLASH));
244 }
245 if (inputStream == null) {
246 File derived = new File(SLASH, file.getPath());
247 inputStream = classLoader.getResourceAsStream(derived.getPath().replaceAll(REGEX_BACKSLASH, SLASH));
248 }
249
250 if (inputStream != null) {
251 if (log.isDebugEnabled()) log.debug(FILE_LOADED + file.getPath());
252 } else {
253 if (log.isDebugEnabled()) log.debug(FILE_LOADERROR + file.getPath());
254 }
255 return inputStream;
256 }
257
258 /***
259 * Get the file from the current application directory.
260 *
261 * @param file the file
262 * @return the image
263 */
264 protected InputStream getCurrentDirFile(File file) {
265 InputStream inputStream = null;
266 File current = new File(CURRENT_DIR);
267 File xmlFile = new File(current, file.getPath());
268 if (xmlFile.isFile() && xmlFile.exists()) {
269 try {
270 inputStream = new FileInputStream(file);
271 if (log.isDebugEnabled()) log.debug(FILE_LOADED + xmlFile.getAbsolutePath());
272 } catch (Exception e) {
273 if (log.isDebugEnabled()) log.debug(FILE_LOADERROR, e);
274 }
275 }
276 return inputStream;
277 }
278
279 /***
280 * Get the file from the dir specified trough the resourcedir property
281 *
282 * @param file the file
283 * @return the image or null
284 */
285 protected InputStream getJMAGEResourceDirFile(File file) {
286 InputStream inputStream = null;
287 String resourceDirName = this.applicationContext.getProperty(resourcedir);
288
289 if (resourceDirName == null) {
290 return null;
291 }
292
293 File xmlResourceDir = new File(resourceDirName, XML);
294 if (xmlResourceDir != null && xmlResourceDir.isDirectory() && xmlResourceDir.exists()) {
295 File xmlFile = new File(xmlResourceDir, file.getPath());
296 if (xmlFile.isFile() && xmlFile.exists()) {
297 try {
298 inputStream = new FileInputStream(xmlFile);
299 if (log.isDebugEnabled()) log.debug(FILE_LOADED + xmlFile.getAbsolutePath());
300 } catch (Exception e) {
301 if (log.isEnabledFor(Priority.ERROR)) log.error(FILE_LOADERROR, e);
302 }
303 }
304 }
305 return inputStream;
306 }
307
308 public String toString() {
309 return "[" + this.getClass().getName() + "#" + this.hashCode() + "]";
310 }
311 }