001: /*
002: * argun 1.0
003: * Web 2.0 delivery framework
004: * Copyright (C) 2007 Hammurapi Group
005: *
006: * This program is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2 of the License, or (at your option) any later version.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: *
020: * URL: http://www.hammurapi.biz
021: * e-Mail: support@hammurapi.biz
022: */
023: package biz.hammurapi.web;
024:
025: import java.io.IOException;
026: import java.io.InputStream;
027: import java.util.HashMap;
028: import java.util.Map;
029:
030: import javax.servlet.ServletConfig;
031: import javax.servlet.ServletException;
032: import javax.xml.parsers.ParserConfigurationException;
033:
034: import org.xml.sax.SAXException;
035:
036: import biz.hammurapi.config.ConfigurationException;
037: import biz.hammurapi.config.DomConfigurable;
038:
039: /**
040: * Action servlet invokes action methods. Action method is any method which takes 3 parameters:
041: * HttpServletRequest, HttpServletResponse, ActionServlet or 2 parameters HttpServletRequest, HttpServletResponse
042: * Return value of action method is processed in the following way:
043: * a) If it is instance of Forward then forward is performed
044: * b) If it is instance of String then it is gets written to response output stream.
045: * c) Otherwise it is XML-ized and then styled.
046: */
047: public class ActionServlet extends DispatchingServlet {
048: private static final String PROFILE_SEPARATOR = "profile-separator";
049: private static final String ROOT_PACKAGE = "root-package";
050: private String profileSeparator = "!";
051: private String rootPackage = "";
052:
053: public void init(ServletConfig config) throws ServletException {
054: super .init(config);
055: config.getServletContext().log(
056: "Initialization: " + config.getServletName());
057:
058: String initParameter = config.getInitParameter(ROOT_PACKAGE);
059: if (initParameter != null) {
060: rootPackage = initParameter;
061: config.getServletContext().log(
062: "root-package=" + rootPackage);
063: }
064:
065: initParameter = config.getInitParameter(PROFILE_SEPARATOR);
066: if (initParameter != null) {
067: profileSeparator = initParameter;
068: config.getServletContext().log(
069: "profile-separator=" + profileSeparator);
070: }
071: }
072:
073: /**
074: * Extracts instance name from the path and returns instance for the path.
075: * @param actionPath
076: * @return Object to invoke action methods
077: * @throws HammurapiWebException
078: */
079: protected Object getActionInstance(String path)
080: throws HammurapiWebException {
081: int idx = path.indexOf('/');
082: if (idx == -1) {
083: throw new HammurapiWebException("Bad path: " + path);
084: }
085:
086: String name = path.substring(0, idx);
087: int pidx = name.indexOf(profileSeparator);
088:
089: String profile = null;
090: if (pidx != -1) {
091: profile = name.substring(pidx + 1);
092: name = name.substring(0, pidx);
093: }
094:
095: try {
096: if (rootPackage.length() == 0) {
097: return getActionInstance(getClass().getClassLoader()
098: .loadClass(name), profile);
099: }
100:
101: return getActionInstance(getClass().getClassLoader()
102: .loadClass(rootPackage + "." + name), profile);
103: } catch (ClassNotFoundException e) {
104: throw new HammurapiWebException(
105: "Action class not found for action " + name, e);
106: }
107: }
108:
109: protected String getActionName(String path)
110: throws HammurapiWebException {
111: int idx = path.indexOf('/');
112: if (idx == -1) {
113: throw new HammurapiWebException("Bad path: " + path);
114: }
115:
116: return path.substring(idx + 1);
117: }
118:
119: /**
120: * @return Position of "/" in the servlet path info which separates action name from style info.
121: */
122: protected int styleSeparatorPosition() {
123: return 1;
124: }
125:
126: /**
127: * Action class instances
128: */
129: private Map instances = new HashMap();
130:
131: public synchronized Object getActionInstance(Class actionClass,
132: String profile) throws HammurapiWebException {
133: String key = actionClass.getName() + profileSeparator + profile;
134: Object instance = instances.get(key);
135: if (instance == null) {
136: try {
137: instance = actionClass.newInstance();
138: } catch (InstantiationException e) {
139: throw new HammurapiWebException(
140: "Cannot instantiate action "
141: + actionClass.getName(), e);
142: } catch (IllegalAccessException e) {
143: throw new HammurapiWebException(
144: "Cannot instantiate action "
145: + actionClass.getName(), e);
146: }
147:
148: String resourceName = actionClass.getName().replace('.',
149: '/');
150: if (profile != null) {
151: resourceName += profileSeparator + profile;
152: }
153:
154: resourceName += ".xml";
155:
156: InputStream is = getClass().getClassLoader()
157: .getResourceAsStream(resourceName);
158: if (profile != null && is == null) {
159: throw new HammurapiWebException("Profile '" + profile
160: + "' does not exist for action class "
161: + actionClass.getName());
162: }
163:
164: if (is != null) {
165: if (DomConfigurable.class.isAssignableFrom(actionClass)) {
166: try {
167: ((DomConfigurable) instance).configure(
168: newDocumentBuilder().parse(is)
169: .getDocumentElement(), null);
170: } catch (IOException e) {
171: throw new HammurapiWebException(
172: "Cannot load configuration for action "
173: + actionClass.getName()
174: + ", profile " + profile, e);
175: } catch (ConfigurationException e) {
176: throw new HammurapiWebException(
177: "Cannot load configuration for action "
178: + actionClass.getName()
179: + ", profile " + profile, e);
180: } catch (SAXException e) {
181: throw new HammurapiWebException(
182: "Cannot load configuration for action "
183: + actionClass.getName()
184: + ", profile " + profile, e);
185: } catch (ParserConfigurationException e) {
186: throw new HammurapiWebException(
187: "Cannot load configuration for action "
188: + actionClass.getName()
189: + ", profile " + profile, e);
190: }
191: } else {
192: throw new HammurapiWebException(actionClass
193: .getName()
194: + " must implement "
195: + DomConfigurable.class.getName()
196: + " in order to be configured");
197: }
198: }
199:
200: instances.put(key, instance);
201: }
202:
203: return instance;
204: }
205: }
|