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.web;
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, config);
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: * @param config
168: *
169: * @throws UnavailableException if file cannot be read or parsed
170: * @since Struts 1.2
171: */
172: protected void parseModuleConfigFile(Digester digester,
173: String path, ModuleConfig config)
174: throws UnavailableException {
175: InputStream input = null;
176: Resource[] resources = null;
177:
178: try {
179: resources = WebApplicationContextUtils
180: .getWebApplicationContext(getServletContext())
181: .getResources(path);
182: } catch (IOException ex) {
183: handleConfigException(path, ex);
184: }
185:
186: final int length = resources.length;
187:
188: for (int i = 0; i < length; i++) {
189: try {
190: URL url = resources[i].getURL(); /*getServletContext().getResource(path)*/
191: ;
192:
193: // If the config isn't in the servlet context, try the class loader
194: // which allows the config files to be stored in a jar
195: if (url == null) {
196: url = getClass().getResource(path);
197: }
198:
199: if (url == null) {
200: String msg = internal.getMessage("configMissing",
201: path);
202: log.error(msg);
203: throw new UnavailableException(msg);
204: }
205:
206: InputSource is = new InputSource(url.toExternalForm());
207: input = url.openStream();
208: is.setByteStream(input);
209: digester.parse(is);
210: } catch (MalformedURLException e) {
211: handleConfigException(path, e);
212: } catch (IOException e) {
213: handleConfigException(path, e);
214: } catch (SAXException e) {
215: handleConfigException(path, e);
216: } finally {
217: if (input != null) {
218: try {
219: input.close();
220:
221: if ((length > 1) && (i < (length - 1))) {
222: digester.push(config);
223: }
224: } catch (IOException e) {
225: throw new UnavailableException(e.getMessage());
226: }
227: }
228: }
229: }
230: }
231:
232: /**
233: * <p>Simplifies exception handling in the <code>parseModuleConfigFile</code> method.<p>
234: * @param path
235: * @param e
236: * @throws UnavailableException as a wrapper around Exception
237: */
238: private void handleConfigException(String path, Exception e)
239: throws UnavailableException {
240: String msg = internal.getMessage("configParse", path);
241: log.error(msg, e);
242: throw new UnavailableException(msg);
243: }
244: }
|