001: /* Copyright (c) 2001 - 2007 TOPP - www.openplans.org. All rights reserved.
002: * This code is licensed under the GPL 2.0 license, availible at the root
003: * application directory.
004: */
005: package org.vfny.geoserver.config;
006:
007: import org.apache.commons.digester.Digester;
008: import org.apache.struts.Globals;
009: import org.apache.struts.action.ActionServlet;
010: import org.apache.struts.config.FormBeanConfig;
011: import org.apache.struts.config.ModuleConfig;
012: import org.apache.struts.config.ModuleConfigFactory;
013: import org.springframework.core.io.Resource;
014: import org.springframework.web.context.support.WebApplicationContextUtils;
015: import org.xml.sax.InputSource;
016: import org.xml.sax.SAXException;
017: import java.io.IOException;
018: import java.io.InputStream;
019: import java.net.MalformedURLException;
020: import java.net.URL;
021: import java.util.Enumeration;
022: import javax.servlet.ServletException;
023: import javax.servlet.UnavailableException;
024:
025: public class MultipleActionServlet extends ActionServlet {
026: /**
027: *
028: */
029: private static final long serialVersionUID = -5222456011963238678L;
030:
031: /**
032: * <p>Initialize this servlet. Most of the processing has been factored into
033: * support methods so that you can override particular functionality at a
034: * fairly granular level.</p>
035: *
036: * @exception ServletException if we cannot configure ourselves correctly
037: */
038: public void init() throws ServletException {
039: // Wraps the entire initialization in a try/catch to better handle
040: // unexpected exceptions and errors to provide better feedback
041: // to the developer
042: try {
043: initInternal();
044: initOther();
045: initServlet();
046:
047: getServletContext().setAttribute(
048: Globals.ACTION_SERVLET_KEY, this );
049: initModuleConfigFactory();
050:
051: // Initialize modules as needed
052: ModuleConfig moduleConfig = initModuleConfig("", config);
053: initModuleMessageResources(moduleConfig);
054: initModuleDataSources(moduleConfig);
055: initModulePlugIns(moduleConfig);
056: moduleConfig.freeze();
057:
058: Enumeration names = getServletConfig()
059: .getInitParameterNames();
060:
061: while (names.hasMoreElements()) {
062: String name = (String) names.nextElement();
063:
064: if (!name.startsWith("config/")) {
065: continue;
066: }
067:
068: String prefix = name.substring(6);
069: moduleConfig = initModuleConfig(prefix,
070: getServletConfig().getInitParameter(name));
071: initModuleMessageResources(moduleConfig);
072: initModuleDataSources(moduleConfig);
073: initModulePlugIns(moduleConfig);
074: moduleConfig.freeze();
075: }
076:
077: this .initModulePrefixes(this .getServletContext());
078:
079: this .destroyConfigDigester();
080: } catch (UnavailableException ex) {
081: throw ex;
082: } catch (Throwable t) {
083: // The follow error message is not retrieved from internal message
084: // resources as they may not have been able to have been
085: // initialized
086: log
087: .error(
088: "Unable to initialize Struts ActionServlet due to an "
089: + "unexpected exception or error thrown, so marking the "
090: + "servlet as unavailable. Most likely, this is due to an "
091: + "incorrect or missing library dependency.",
092: t);
093: throw new UnavailableException(t.getMessage());
094: }
095: }
096:
097: /**
098: * <p>Initialize the module configuration information for the
099: * specified module.</p>
100: *
101: * @param prefix Module prefix for this module
102: * @param paths Comma-separated list of context-relative resource path(s)
103: * for this modules's configuration resource(s)
104: *
105: * @exception ServletException if initialization cannot be performed
106: * @since Struts 1.1
107: */
108: protected ModuleConfig initModuleConfig(String prefix, String paths)
109: throws ServletException {
110: // :FIXME: Document UnavailableException? (Doesn't actually throw anything)
111: if (log.isDebugEnabled()) {
112: log.debug("Initializing module path '" + prefix
113: + "' configuration from '" + paths + "'");
114: }
115:
116: // Parse the configuration for this module
117: ModuleConfigFactory factoryObject = ModuleConfigFactory
118: .createFactory();
119: ModuleConfig config = factoryObject.createModuleConfig(prefix);
120:
121: // Configure the Digester instance we will use
122: Digester digester = initConfigDigester();
123:
124: // Process each specified resource path
125: while (paths.length() > 0) {
126: digester.push(config);
127:
128: String path = null;
129: int comma = paths.indexOf(',');
130:
131: if (comma >= 0) {
132: path = paths.substring(0, comma).trim();
133: paths = paths.substring(comma + 1);
134: } else {
135: path = paths.trim();
136: paths = "";
137: }
138:
139: if (path.length() < 1) {
140: break;
141: }
142:
143: this .parseModuleConfigFile(digester, path);
144: }
145:
146: getServletContext().setAttribute(
147: Globals.MODULE_KEY + config.getPrefix(), config);
148:
149: // Force creation and registration of DynaActionFormClass instances
150: // for all dynamic form beans we wil be using
151: FormBeanConfig[] fbs = config.findFormBeanConfigs();
152:
153: for (int i = 0; i < fbs.length; i++) {
154: if (fbs[i].getDynamic()) {
155: fbs[i].getDynaActionFormClass();
156: }
157: }
158:
159: return config;
160: }
161:
162: /**
163: * <p>Parses one module config file.</p>
164: *
165: * @param digester Digester instance that does the parsing
166: * @param path The path to the config file to parse.
167: *
168: * @throws UnavailableException if file cannot be read or parsed
169: * @since Struts 1.2
170: */
171: protected void parseModuleConfigFile(Digester digester, String path)
172: throws UnavailableException {
173: InputStream input = null;
174:
175: try {
176: Resource[] resources = WebApplicationContextUtils
177: .getWebApplicationContext(getServletContext())
178: .getResources(path);
179: final int length = resources.length;
180:
181: for (int i = 0; i < length; i++) {
182: URL url = resources[i].getURL(); /*getServletContext().getResource(path)*/
183: ;
184:
185: // If the config isn't in the servlet context, try the class loader
186: // which allows the config files to be stored in a jar
187: if (url == null) {
188: url = getClass().getResource(path);
189: }
190:
191: if (url == null) {
192: String msg = internal.getMessage("configMissing",
193: path);
194: log.error(msg);
195: throw new UnavailableException(msg);
196: }
197:
198: InputSource is = new InputSource(url.toExternalForm());
199: input = url.openStream();
200: is.setByteStream(input);
201: digester.parse(is);
202: }
203: } catch (MalformedURLException e) {
204: handleConfigException(path, e);
205: } catch (IOException e) {
206: handleConfigException(path, e);
207: } catch (SAXException e) {
208: handleConfigException(path, e);
209: } finally {
210: if (input != null) {
211: try {
212: input.close();
213: } catch (IOException e) {
214: throw new UnavailableException(e.getMessage());
215: }
216: }
217: }
218: }
219:
220: /**
221: * <p>Simplifies exception handling in the <code>parseModuleConfigFile</code> method.<p>
222: * @param path
223: * @param e
224: * @throws UnavailableException as a wrapper around Exception
225: */
226: private void handleConfigException(String path, Exception e)
227: throws UnavailableException {
228: String msg = internal.getMessage("configParse", path);
229: log.error(msg, e);
230: throw new UnavailableException(msg);
231: }
232: }
|