FrontController.java 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  1. package com.udapsoft.waf.system.controller;
  2. import java.io.IOException;
  3. import java.net.URL;
  4. import java.text.SimpleDateFormat;
  5. import java.util.Calendar;
  6. import java.util.Enumeration;
  7. import java.util.HashMap;
  8. import java.util.Iterator;
  9. import java.util.Locale;
  10. import java.util.Map;
  11. import java.util.StringTokenizer;
  12. import javax.naming.InitialContext;
  13. import javax.naming.NamingException;
  14. import javax.servlet.ServletConfig;
  15. import javax.servlet.ServletContext;
  16. import javax.servlet.ServletException;
  17. import javax.servlet.http.HttpServlet;
  18. import javax.servlet.http.HttpServletRequest;
  19. import javax.servlet.http.HttpServletResponse;
  20. import javax.transaction.HeuristicMixedException;
  21. import javax.transaction.HeuristicRollbackException;
  22. import javax.transaction.NotSupportedException;
  23. import javax.transaction.RollbackException;
  24. import javax.transaction.SystemException;
  25. import javax.transaction.UserTransaction;
  26. import kr.co.hsnc.common.base.WAFFactory;
  27. import kr.co.hsnc.common.base.WAFLogger;
  28. import kr.co.hsnc.common.loader.FileChangeListener;
  29. import kr.co.hsnc.common.loader.FileMonitor;
  30. import kr.co.hsnc.j2ee.waf.controller.web.action.ActionHandler;
  31. import kr.co.hsnc.j2ee.waf.controller.web.util.WebKeys;
  32. import kr.co.hsnc.j2ee.waf.view.template.Screen;
  33. import kr.co.hsnc.j2ee.waf.view.template.ScreenDefinitionDAO;
  34. import kr.co.hsnc.j2ee.waf.view.template.Screens;
  35. import com.udapsoft.waf.system.HandlerStorage;
  36. public class FrontController extends HttpServlet implements FileChangeListener {
  37. private static final long serialVersionUID = 4556105374329449270L;
  38. private HashMap<String, Screens> allScreens;
  39. private ServletConfig config;
  40. private ServletContext context;
  41. private String defaultLocale;
  42. private boolean cachePreviousScreenAttributes = false;
  43. private boolean cachePreviousScreenParameters = false;
  44. private static final String PREVIOUS_SCREEN = "PREVIOUS";
  45. private boolean isDebug = false;
  46. // FileChangeListener Variables
  47. private long interval = 2000L;
  48. private FileMonitor monitor;
  49. private SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
  50. /**
  51. * Called by the servlet container to indicate to a servlet that the servlet
  52. * is being placed into service.
  53. *
  54. * @param config
  55. * ServletConfig
  56. * @exception ServletException
  57. * - if an exception occurs that interrupts the servlet's
  58. * normal operation.
  59. */
  60. public void init(ServletConfig config) throws ServletException {
  61. super.init(config);
  62. this.config = config;
  63. this.context = config.getServletContext();
  64. this.monitor = FileMonitor.getInstance();
  65. // enable the caching of previous screen attributes
  66. String cachePreviousScreenAttributesString = config.getInitParameter("cache_previous_screen_attributes");
  67. if (cachePreviousScreenAttributesString != null) {
  68. if (cachePreviousScreenAttributesString.toLowerCase().equals("true")) {
  69. WAFLogger.sys("FrontController: Enabled caching of previous screen attributes.");
  70. cachePreviousScreenAttributes = true;
  71. }
  72. }
  73. // enable the caching of previous screen parameters
  74. String cachePreviousScreenParametersString = config.getInitParameter("cache_previous_screen_parameters");
  75. if (cachePreviousScreenParametersString != null) {
  76. if (cachePreviousScreenParametersString.toLowerCase().equals("true")) {
  77. WAFLogger.sys("FrontController: Enabled caching of previous screen parameters.");
  78. cachePreviousScreenParameters = true;
  79. }
  80. }
  81. allScreens = new HashMap<String, Screens>();
  82. defaultLocale = config.getInitParameter("default_locale");
  83. if (defaultLocale == null) {
  84. defaultLocale = (Locale.getDefault()).toString();
  85. }
  86. String locales = config.getInitParameter("locales");
  87. if (locales != null) {
  88. StringTokenizer strTok = new StringTokenizer(locales, ",");
  89. while (strTok.hasMoreTokens()) {
  90. initScreens(config.getServletContext(), strTok.nextToken());
  91. }
  92. }
  93. }
  94. /**
  95. * FileChangeListener.fileChanged() Implementation....
  96. *
  97. * @param fileName
  98. * screendefinitions file name.
  99. */
  100. public void fileChanged(String fileName) {
  101. WAFLogger.sys("["
  102. + this.formatter.format(Calendar.getInstance().getTime())
  103. + "] FrontController.fileChanged()... -> " + fileName);
  104. initScreens(context, defaultLocale);
  105. }
  106. /**
  107. * initialize screens.
  108. *
  109. * @param context
  110. * ServletContext.
  111. * @param language
  112. * locale language.
  113. */
  114. protected synchronized void initScreens(ServletContext context,
  115. String language) {
  116. URL screenDefinitionURL = null;
  117. String screenDefinitionRealPath = null;
  118. try {
  119. screenDefinitionURL = context.getResource("/WEB-INF/screendefinitions_" + language + ".xml");
  120. screenDefinitionRealPath = context.getRealPath("/WEB-INF/screendefinitions_" + language + ".xml");
  121. this.monitor.addFileChangeListener(this, screenDefinitionRealPath, this.interval);
  122. } catch (java.net.MalformedURLException ex) {
  123. WAFLogger.sys("FrontController.initScreens(): malformed URL exception: " + ex);
  124. } catch (java.io.IOException ex) {
  125. WAFLogger.sys("FrontController.initScreens(): IOException: " + ex);
  126. }
  127. if (screenDefinitionURL != null) {
  128. Screens screenDefinitions = ScreenDefinitionDAO.loadScreenDefinitions(screenDefinitionURL);
  129. if (screenDefinitions != null) {
  130. allScreens.put(language, screenDefinitions);
  131. } else {
  132. WAFLogger.sys("Template Servlet Error Loading Screen Definitions: Confirm that file at URL /WEB-INF/screendefinitions_"
  133. + language
  134. + ".xml contains the screen definitions");
  135. }
  136. } else {
  137. WAFLogger.sys("Template Servlet Error Loading Screen Definitions: URL /WEB-INF/screendefinitions_" + language + ".xml not found");
  138. }
  139. }
  140. /**
  141. * Called by the servlet container to indicate to a servlet that the servlet
  142. * is being placed into service.
  143. *
  144. * @param request
  145. * HttpServletRequest
  146. * @param response
  147. * HttpServletResponse
  148. * @exception ServletException
  149. * if an exception occurs that interferes with the servlet's
  150. * normal operation occurred
  151. * @exception IOException
  152. * if an input or output exception occurs
  153. */
  154. public void service(HttpServletRequest request, HttpServletResponse response)
  155. throws IOException, ServletException {
  156. request.setAttribute("WAF.TIMESTAMP", new Long(System.currentTimeMillis()));
  157. /**
  158. * 브라우저 Cache Expire 시키기
  159. */
  160. if (request.getProtocol().compareTo("HTTP/1.0") == 0) {
  161. response.setHeader("Pragma", "no-cache");
  162. } else if (request.getProtocol().compareTo("HTTP/1.1") == 0) {
  163. response.setHeader("Cache-Control", "no-cache");
  164. }
  165. response.setDateHeader("Expires", 0);
  166. String screenName = null;
  167. String localeString = null;
  168. String currentURI = request.getRequestURI();
  169. if (request.getSession().getAttribute(WebKeys.CURRENT_URI) != null) {
  170. request.getSession().removeAttribute(WebKeys.CURRENT_URI);
  171. }
  172. request.getSession().setAttribute(WebKeys.CURRENT_URI, currentURI);
  173. debug(" currentURI=" + currentURI);
  174. String languageParam = request.getParameter("locale");
  175. // The language when specified as a parameter overrides the language set
  176. // in the session
  177. if (request.getSession().getAttribute(WebKeys.LOCALE) == null) {
  178. Locale locale = new Locale(defaultLocale.substring(0, 2), defaultLocale.substring(3, 5));
  179. request.getSession().setAttribute(WebKeys.LOCALE, locale);
  180. }
  181. if (languageParam != null) {
  182. localeString = languageParam;
  183. } else if (request.getSession().getAttribute(WebKeys.LOCALE) != null) {
  184. localeString = ((Locale) request.getSession().getAttribute(
  185. WebKeys.LOCALE)).toString();
  186. }
  187. if (allScreens.get(localeString) == null) {
  188. localeString = defaultLocale;
  189. }
  190. // get the screen name
  191. // int lastPathSeparator = currentURI.lastIndexOf("/") + 1;
  192. // int lastDot = currentURI.lastIndexOf(".");
  193. String currentScreen = currentURI.substring(request.getContextPath().length());
  194. int lastDot = currentScreen.lastIndexOf(".");
  195. // if (lastPathSeparator != -1 && lastDot != -1 && lastDot >
  196. // lastPathSeparator) {
  197. if (lastDot != -1) {
  198. // screenName = currentURI.substring(lastPathSeparator, lastDot);
  199. screenName = currentScreen.substring(0, lastDot);
  200. }
  201. debug(" screenName=" + screenName);
  202. // check if request is for the previous screen
  203. if (screenName.equals(PREVIOUS_SCREEN)) {
  204. String longScreenName = (String) request.getSession().getAttribute(
  205. WebKeys.PREVIOUS_SCREEN);
  206. int lastDot2 = longScreenName.lastIndexOf(".");
  207. if (lastDot2 != -1 && lastDot2 > 0) {
  208. screenName = longScreenName.substring(0, lastDot2);
  209. }
  210. // put the request attributes stored in the session in the request
  211. if (cachePreviousScreenParameters) {
  212. Map<?, ?> previousParams = (Map<?, ?>) request.getSession().getAttribute(WebKeys.PREVIOUS_REQUEST_PARAMETERS);
  213. Map<String, String[]> params = (Map<String, String[]>) request.getParameterMap();
  214. Iterator<?> it = previousParams.keySet().iterator();
  215. while (it.hasNext()) {
  216. String key = (String) it.next();
  217. Object value = previousParams.get(key);
  218. params.put(key, (String[]) value);
  219. }
  220. }
  221. // put in the previous request attributes
  222. if (cachePreviousScreenAttributes) {
  223. Map<?, ?> previousAttributes = (Map<?, ?>) request.getSession().getAttribute(WebKeys.PREVIOUS_REQUEST_ATTRIBUTES);
  224. Iterator<?> it2 = previousAttributes.keySet().iterator();
  225. // put the request attributes stored in the session in the
  226. // request
  227. while (it2.hasNext()) {
  228. String key = (String) it2.next();
  229. Object value = previousAttributes.get(key);
  230. request.setAttribute(key, value);
  231. }
  232. }
  233. } else {
  234. String extension = currentURI.substring(lastDot, currentURI.length());
  235. request.getSession().setAttribute(WebKeys.PREVIOUS_SCREEN, screenName + extension);
  236. if (cachePreviousScreenParameters) {
  237. // copy all the parameters into a new map
  238. HashMap<String, Object> newParams = new HashMap<String, Object>();
  239. Map<?, ?> params = (Map<?, ?>) request.getParameterMap();
  240. Iterator<?> it = params.keySet().iterator();
  241. // put the request attributes stored in the session in the
  242. // request
  243. while (it.hasNext()) {
  244. String key = (String) it.next();
  245. Object value = params.get(key);
  246. newParams.put(key, value);
  247. }
  248. request.getSession().setAttribute(WebKeys.PREVIOUS_REQUEST_PARAMETERS, newParams);
  249. }
  250. if (cachePreviousScreenAttributes) {
  251. // put the request attributes into a map
  252. HashMap<String, Object> attributes = new HashMap<String, Object>();
  253. Enumeration<?> enums = request.getAttributeNames();
  254. while (enums.hasMoreElements()) {
  255. String key = (String) enums.nextElement();
  256. Object value = request.getAttribute(key);
  257. attributes.put(key, value);
  258. }
  259. request.getSession().setAttribute(WebKeys.PREVIOUS_REQUEST_ATTRIBUTES, attributes);
  260. }
  261. }
  262. // get the screen information for the coresponding language
  263. Screen screen = null;
  264. if (screenName != null) {
  265. Screens localeScreens = (Screens) allScreens.get(localeString);
  266. if (localeScreens != null) {
  267. // **********************************************************************
  268. if (request.getSession().getAttribute(WebKeys.SCREENS) == null) {
  269. request.getSession().setAttribute(WebKeys.SCREENS, localeScreens);
  270. }
  271. // **********************************************************************
  272. screen = (Screen) localeScreens.getScreen(screenName);
  273. }
  274. // default to the default locale screen if it was not defined in the
  275. // locale specific definitions
  276. if (screen == null) {
  277. WAFLogger.debug("Screen not Found loading default from " + defaultLocale);
  278. localeScreens = (Screens) allScreens.get(defaultLocale);
  279. screen = (Screen) localeScreens.getScreen(screenName);
  280. }
  281. if (screen != null) {
  282. String handler = screen.getHandler();
  283. debug("##### -> handler = " + (handler == "" ? "NULL" : handler));
  284. if (handler != "") {
  285. // **********************************************************************
  286. request.setAttribute(HandlerStorage.KEY, currentURI + "_" + request.getParameter("event"));
  287. String screenname = processRequest(request, response, handler);
  288. if (screenname != null) {
  289. screenName = screenname;
  290. screen = (Screen) localeScreens.getScreen(screenName);
  291. debug(" 1 screenName = " + screenName);
  292. }
  293. }
  294. debug(" 2 screenName = " + screenName);
  295. request.setAttribute(WebKeys.CURRENT_SCREEN, screen);
  296. String templateName = localeScreens.getTemplate(screenName);
  297. debug(" 3 templateName = " + templateName);
  298. if (templateName != null) {
  299. insertTemplate(request, response, templateName);
  300. }
  301. } else {
  302. WAFLogger.debug("Error: Definition for screen " + screenName + " not found");
  303. response.setStatus(javax.servlet.http.HttpServletResponse.SC_MOVED_TEMPORARILY);
  304. response.setHeader("Location", request.getContextPath() + "/error.screen?code=WAF-400&param1=" + screenName);
  305. }
  306. }
  307. }
  308. /**
  309. * process request.
  310. *
  311. * @param request
  312. * HttpServletRequest
  313. * @param response
  314. * HttpServletResponse
  315. * @param handlerName
  316. * handler name
  317. */
  318. protected String processRequest(HttpServletRequest request, HttpServletResponse response, String handlerName) {
  319. String screen = null;
  320. // FlowHandler handler = null;
  321. ActionHandler handler = null;
  322. try {
  323. debug("processRequest()...1 " + handlerName);
  324. // handler =
  325. // (FlowHandler)getClass().getClassLoader().loadClass(handlerName).newInstance();
  326. /*
  327. * if ( request.getSession().getAttribute(handlerName) == null) {
  328. * debug("processRequest()...1-1 ");
  329. * //request.getSession().setAttribute(handlerName,
  330. * getClass().getClassLoader
  331. * ().loadClass(handlerName).newInstance());
  332. * request.getSession().setAttribute(handlerName,
  333. * WAFFactory.getInstance(handlerName)); } handler =
  334. * (ActionHandler)request.getSession().getAttribute(handlerName);
  335. */
  336. handler = (ActionHandler) WAFFactory.getInstance(handlerName);
  337. // invoke the processFlow(HttpServletRequest)
  338. handler.doStart(request);
  339. debug("processRequest()...2 " + handler);
  340. // flowResult = handler.processFlow(request);
  341. screen = handler.doHandle(request);
  342. debug("processRequest()...3 screen=" + screen);
  343. handler.doEnd(request);
  344. } catch (Exception e) {
  345. WAFLogger.debug("[Exception]FrontController.processRequest()... "
  346. + e);
  347. WAFLogger.errorStackTraceeElement(e);
  348. } finally {
  349. handler = null;
  350. }
  351. return screen;
  352. }
  353. /**
  354. * insert template.
  355. *
  356. * @param request
  357. * HttpServletRequest
  358. * @param response
  359. * HttpServletResponse
  360. * @param templateName
  361. * template name
  362. * @exception ServletException
  363. * if an exception occurs that interferes with the servlet's
  364. * normal operation occurred
  365. * @exception IOException
  366. * if an input or output exception occurs
  367. */
  368. protected void insertTemplate(HttpServletRequest request,
  369. HttpServletResponse response, String templateName)
  370. throws IOException, ServletException {
  371. // This method tries to wrap the request dispatcher call with-in
  372. // a transaction for making the local EJB access efficient. However,
  373. // it is not a fatal error, if such a transaction can not be started
  374. // for some reason, so it handles them gracefully.
  375. boolean tx_started = false;
  376. UserTransaction ut = null;
  377. try {
  378. // Lookup the UserTransaction object
  379. InitialContext ic = new InitialContext();
  380. ut = (UserTransaction) ic.lookup("java:comp/UserTransaction");
  381. ut.begin(); // start the transaction.
  382. tx_started = true;
  383. /*************************************************************/
  384. // RollbackException
  385. ut.setTransactionTimeout(300); // 5 minutes
  386. /*************************************************************/
  387. } catch (NamingException ne) {
  388. // it should not have happened, but it is a recoverable error.
  389. // Just dont start the transaction.
  390. // ne.printStackTrace();
  391. } catch (NotSupportedException nse) {
  392. // Again this is a recoverable error.
  393. nse.printStackTrace();
  394. } catch (SystemException se) {
  395. // Again this is a recoverable error.
  396. se.printStackTrace();
  397. }
  398. try {
  399. context.getRequestDispatcher(templateName).forward(request, response);
  400. } finally {
  401. // commit the transaction if it was started earlier successfully.
  402. try {
  403. if (tx_started && ut != null) {
  404. ut.commit();
  405. }
  406. } catch (IllegalStateException re) {
  407. re.printStackTrace();
  408. } catch (RollbackException re) {
  409. re.printStackTrace();
  410. } catch (HeuristicMixedException hme) {
  411. hme.printStackTrace();
  412. } catch (HeuristicRollbackException hre) {
  413. hre.printStackTrace();
  414. } catch (SystemException se) {
  415. se.printStackTrace();
  416. }
  417. }
  418. }
  419. private void debug(Object obj) {
  420. if (isDebug)
  421. WAFLogger.debug("[FrontController]" + obj);
  422. }
  423. }