001 package net.sf.jolene.struts; 002 003 import net.sf.jolene.util.PrefsReader; 004 import net.sf.jolene.dom.Document; 005 import net.sf.jolene.dom.HTMLElement; 006 import net.sf.jolene.dom.Label; 007 import net.sf.jolene.dom.Text; 008 import net.sf.jolene.factories.DocumentFactory; 009 import org.apache.log4j.LogManager; 010 import org.apache.log4j.Logger; 011 import org.apache.struts.action.ActionForm; 012 import org.apache.struts.action.ActionForward; 013 import org.apache.struts.action.ActionMapping; 014 import org.apache.struts.actions.DispatchAction; 015 import org.apache.struts.util.MessageResources; 016 017 import javax.servlet.http.HttpServletRequest; 018 import javax.servlet.http.HttpServletResponse; 019 import java.io.IOException; 020 021 /** 022 * Default action servlet for jolene. Implements a modified DispatchAction which can match request uri string 023 * to the method name of the action class. The primary purpose is to associate a uri to a document object. 024 * There are several ways to do this see the method descriptions. 025 * 026 * @author Dan Howard 027 * @since Sep 23, 2006 5:40:15 PM 028 */ 029 public class DomletAction extends DispatchAction { 030 031 private static final Logger log = LogManager.getLogger(DomletAction.class); 032 033 /** 034 * Performs a basic dispatch of the request looking for the parameter from the struts mapping or by using 035 * the struts action name itself. 036 * 037 * @param mapping ActionMapping 038 * @param form ActionForm 039 * @param request HttpServletRequest 040 * @param response HttpServletResponse 041 * @return ActionForward 042 * @throws Exception 043 */ 044 @Override 045 public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 046 047 log.info("DomletAction Initializing PrefsReader..."); 048 PrefsReader.init(); 049 050 // Identify the request parameter containing the method name 051 log.debug("QUERY_STRING :" + request.getQueryString()); 052 053 // Identify the method name to be dispatched to. 054 // Either it's the parameter or the path name itself minus .do etc. 055 String parameter = mapping.getParameter(); 056 String name; 057 if (parameter != null) { 058 name = request.getParameter(parameter); 059 } else { 060 String path = mapping.getPath(); 061 name = path; 062 if (path.lastIndexOf("/") != -1) { 063 name = path.substring(path.lastIndexOf("/") + 1); 064 } 065 } 066 067 // Invoke the named method, and return the result 068 return dispatchMethod(mapping, form, request, response, name); 069 070 } 071 072 073 /** 074 * Retrives a document object based on the mapping input attribute and attaches it to the proper scope. 075 * The reason for this method is to allow a default document to be associated with an action since 076 * actions can have many forwards. 077 * <p/> 078 * For example, calling this method would get the document from the <code>/domlet/login.html<code> uri. 079 * <p/> 080 * <pre> 081 * <action 082 * path="/login" 083 * type="domlet.kbsample.web.actions.LoginAction" 084 * name="LoginForm" 085 * scope="session" 086 * validate="false" 087 * input="/domlet/login.html"> 088 * 089 * <forward name="success" path="/browse.do"/> 090 * <forward name="fail" path="/domlet/error.html"/> 091 * <forward name="login" path="/domlet/login.html"/> 092 * </action> 093 * </pre> 094 * 095 * @param mapping ActionMapping 096 * @param request HttpServletRequest 097 * @return Document or null if the uri for input mapping is undefined in struts-config.xml 098 * @throws IOException if an IOException occurs 099 */ 100 public Document getDocument(ActionMapping mapping, HttpServletRequest request) throws IOException { 101 String uri = mapping.getInput(); 102 log.debug("mapping URI: " + uri); 103 if (uri == null) { 104 log.error("NO URI Specified in struts-config.xml for " + mapping.getPath()); 105 return null; 106 } 107 return getDocument(request, uri, mapping); 108 } 109 110 /** 111 * Retrives a document object based on the specified forward. 112 * <p/> 113 * For example, using the following in struts-config.xml: 114 * <p/> 115 * <pre> 116 * <action 117 * path="/login" 118 * type="domlet.kbsample.web.actions.LoginAction" 119 * name="LoginForm" 120 * scope="session" 121 * validate="false" 122 * input="/domlet/login.html"> 123 * 124 * <forward name="success" path="/browse.do"/> 125 * <forward name="fail" path="/domlet/error.html"/> 126 * <forward name="login" path="/domlet/login.html"/> 127 * </action> 128 * </pre> 129 * <p/> 130 * <code>getDocument(mapping, "fail", request); </code> Returns document from /domlet/error.html <br> 131 * <code>getDocument(mapping, "login", request);</code> Returns document from /domlet/login.html 132 * 133 * @param mapping ActionMapping 134 * @param forward forward string 135 * @param request HttpServletRequest 136 * @return Document or null if the forward cannot be found in struts-config.xml 137 * @throws IOException if an IOException occurs 138 */ 139 public Document getDocument(ActionMapping mapping, String forward, HttpServletRequest request) throws IOException { 140 141 String uri = mapping.findForward(forward).getPath(); 142 log.debug("Mapping URI from forward: " + forward + ": " + uri); 143 return getDocument(request, uri, mapping); 144 145 } 146 147 private Document getDocument(HttpServletRequest request, String uri, ActionMapping mapping) throws IOException { 148 String file; 149 file = request.getSession().getServletContext().getRealPath(uri); 150 151 Document document; 152 if ("request".equalsIgnoreCase(mapping.getScope())) { 153 if (request.getAttribute(uri) == null) { 154 document = DocumentFactory.getInstance().getDocument(file, request.getContextPath(), uri); 155 } else { 156 document = (Document) request.getAttribute(uri); 157 } 158 request.setAttribute(uri, document); 159 } else { 160 if (request.getSession().getAttribute(uri) == null) { 161 document = DocumentFactory.getInstance().getDocument(file, request.getContextPath(), uri); 162 } else { 163 document = (Document) request.getSession().getAttribute(uri); 164 } 165 request.getSession().setAttribute(uri, document); 166 } 167 168 translate(document, request); 169 return document; 170 } 171 172 /** 173 * Translates labels texts and input type button/submit 174 * 175 * @param document 176 * @param request 177 */ 178 private void translate(Document document, HttpServletRequest request) { 179 if (document.isTranslated()) { 180 return; 181 } 182 183 MessageResources messages = getResources(request); 184 185 // Get the URI /somfolder/somehtml.html to convert to somefolder.somehtml as a start key for the resources 186 String docKey = document.getUri(); 187 if (docKey.startsWith("/")) { 188 docKey = docKey.substring(1); 189 } 190 int n = docKey.indexOf("."); 191 if (n > -1) { 192 docKey = docKey.substring(0, n); 193 } 194 docKey = docKey.replace("/", "."); 195 docKey = docKey.replace("\\", "."); 196 docKey = docKey.toLowerCase(); 197 //--------------------------------- 198 log.debug("docKey " + docKey); 199 200 HTMLElement element; 201 String formKey; 202 for (int j = 0; j < document.getFormCount(); j++) { 203 formKey = document.forms(j).getName(); 204 if (formKey.trim().length() == 0) { 205 formKey = "form" + (j + 1); 206 } 207 208 String elementName; 209 for (int k = 0; k < document.forms(j).getElementCount(); k++) { 210 element = document.forms(j).elements(k); 211 elementName = docKey + "." + formKey + "." + element.getName(); 212 log.debug("Element name " + elementName); 213 214 // Check for labels. 215 if (element instanceof Label && !(element instanceof Text)) { 216 217 if (messages.isPresent(elementName)) { 218 element.setValue(messages.getMessage(elementName)); 219 } 220 } else { 221 // Check for buttons - buttons display the value attribute 222 if (element.hasAttribute("type") && (element.getAttribute("type").equalsIgnoreCase("button") || element.getAttribute("type").equalsIgnoreCase("submit"))) { 223 224 if (messages.isPresent(elementName)) { 225 log.debug("setting element " + elementName); 226 element.setValue(messages.getMessage(elementName)); 227 } 228 } 229 } 230 231 // check for title attribute 232 if (element.hasAttribute("title")) { 233 log.debug("Element name title: " + elementName + ".title"); 234 if (messages.isPresent(elementName + ".title")) { 235 log.debug("setting title " + elementName); 236 element.setAttribute("title", messages.getMessage(elementName + ".title")); 237 } 238 } 239 } 240 } 241 document.setTranslated(true); 242 243 } 244 245 246 }