1 /*
2 * Title: Factory
3 * Description:
4 *
5 * This software is published under the terms of the OpenSymphony Software
6 * License version 1.1, of which a copy has been included with this
7 * distribution in the LICENSE.txt file.
8 */
9
10 package com.opensymphony.module.sitemesh;
11
12 import com.opensymphony.module.sitemesh.factory.FactoryException;
13 import com.opensymphony.module.sitemesh.util.Container;
14
15 import javax.naming.InitialContext;
16 import javax.rmi.PortableRemoteObject;
17 import java.lang.reflect.Constructor;
18
19 /**
20 * Factory responsible for creating appropriate instances of implementations.
21 * This is specific to a web context and is obtained through {@link #getInstance(com.opensymphony.module.sitemesh.Config)}.
22 *
23 * <p>The actual Factory method used is determined by the enviroment entry <code>sitemesh.factory</code>.
24 * If this doesn't exist, it defaults to {@link com.opensymphony.module.sitemesh.factory.DefaultFactory} .</p>
25 *
26 * @author <a href="mailto:joe@truemesh.com">Joe Walnes</a>
27 * @version $Revision: 1.5 $
28 */
29 public abstract class Factory {
30 /** Web context lookup key */
31 private static final String SITEMESH_FACTORY = "sitemesh.factory";
32
33 /**
34 * Entry-point for obtaining singleton instance of Factory. The default factory class
35 * that will be instantiated can be overridden with the environment
36 * entry <code>sitemesh.factory</code>.
37 */
38 public static Factory getInstance(Config config) {
39 Factory instance = (Factory)config.getServletContext().getAttribute(SITEMESH_FACTORY);
40 if (instance == null) {
41 String factoryClass = getEnvEntry("sitemesh.factory", "com.opensymphony.module.sitemesh.factory.DefaultFactory");
42 try {
43 Class cls;
44 try {
45 cls = Class.forName(factoryClass);
46 }
47 catch (NoClassDefFoundError e) {
48 cls = Class.forName(factoryClass, true, Thread.currentThread().getContextClassLoader());
49 }
50
51 Constructor con = cls.getConstructor(new Class[] { Config.class });
52 instance = (Factory)con.newInstance(new Config[] { config });
53 config.getServletContext().setAttribute(SITEMESH_FACTORY, instance);
54 }
55 catch (Exception e) {
56 report("Cannot construct Factory : " + factoryClass, e);
57 }
58 }
59 return instance;
60 }
61
62 /** Return instance of DecoratorMapper. */
63 public abstract DecoratorMapper getDecoratorMapper();
64
65 /**
66 * Create a PageParser suitable for the given content-type.
67 *
68 * <p>For example, if the supplied parameter is <code>text/html</code>
69 * a parser shall be returned that can parse HTML accordingly.</p> Never returns null.
70 *
71 * @param contentType The MIME content-type of the data to be parsed
72 * @return Appropriate <code>PageParser</code> for reading data
73 *
74 */
75 public abstract PageParser getPageParser(String contentType);
76
77 /** Determine whether a Page of given content-type should be parsed or not. */
78 public abstract boolean shouldParsePage(String contentType);
79
80 /**
81 * Determine whether the given path should be excluded from decoration or not.
82 */
83 public abstract boolean isPathExcluded(String path);
84
85 /** Report a problem. */
86 protected static void report(String msg, Exception e) {
87 throw new FactoryException(msg, e);
88 }
89
90 /** Find String environment entry, or return default if not found. */
91 private static String getEnvEntry(String envEntry, String defaultValue) {
92 String result = null;
93 try {
94 if (Container.get() != Container.JRUN) {
95 // TODO: JRun really isn't happy with this
96 InitialContext ctx = new InitialContext();
97 Object o = ctx.lookup("java:comp/env/" + envEntry);
98 ctx.close();
99 result = (String)PortableRemoteObject.narrow(o, String.class); // rmi-iiop friendly.
100 }
101 }
102 catch (Exception e) { } // failed - don't moan, just return default.
103 return result == null || result.trim().length() == 0 ? defaultValue : result;
104 }
105 }