public String executeAction( String actionname, Map actionconfig, String responsediv, ActionContext actioncontext) { /*-INFO-*/ Lg.inf("Process request"); // TODO: more in-depth trace logging on the request HttpServletRequest request = RequestContext.getHttpRequest(); Map progitcontext = new HashMap(); // execute action (action will have been overridden with an erroraction in error/login redirect // situations) /*-trc-*/ Lg.trc("begin progit execution for action %s", actionname); List progits = (List) actionconfig.get("Processing"); for (int i = 0; i < progits.size(); i++) { /*-trc-*/ Lg.trc("progit #%d", i); Map progitdef = (Map) progits.get(i); IProgit progit = null; // progit class load String progitclass = (String) progitdef.get("Class"); /*-trc-*/ Lg.trc("instantiating progit %s", progitclass); try { progit = (IProgit) PluginLoader.loadPlugin(progitclass); } catch (Exception e) { /*-ERROR-*/ Lg.err("progit load error for %s", progitclass, e); throw EEx.create( "CfgErr-ActionClass", "Controller Action plugin instantiation error: %s", progitclass, e); } /*-trc-*/ Lg.trc("set progit config in actioncontext"); actioncontext.setPluginConfig((Map) progitdef.get("Config")); // progit exec /*-trc-*/ Lg.trc("EXECUTING"); try { // process the progit args Map progitargs = (Map) progitdef.get("Args"); if (progitargs != null) { /*-trc-*/ Lg.trc("process progit arguments"); Map argmap = new HashMap(); for (int arg = 0; arg < progitargs.size(); arg++) { /*-trc-*/ Lg.trc(" arg #%d", arg); Arg argdef = (Arg) progitargs.get(arg); String contextkey = Is.empty(argdef.Key) ? argdef.Name : argdef.Key; if (Is.empty(argdef.Source) || "literal".equals(argdef.Source)) { /*-trc-*/ Lg.trc( " literal key: %s val: %s", contextkey, argdef != null ? argdef.Value : null); argmap.put(contextkey, argdef.Value); } else if ("http".equals(argdef.Source)) { String[] vals = request.getParameterValues(argdef.Name); if (vals != null && vals.length == 1) { /*-trc-*/ Lg.trc(" http key: %s val: %s", contextkey, vals[0]); argmap.put(contextkey, vals[0]); } else { /*-trc-*/ if (Lg.trc()) { String s = ""; if (vals != null) for (int ss = 0; ss < vals.length; ss++) s += vals[ss]; Lg.trc(" http key: %s val: ", contextkey, s); } argmap.put(contextkey, vals); } } else if ("input".equals(argdef.Source)) { /*-trc-*/ Lg.trc(" input key: %s val: %s", contextkey, responsediv); argmap.put(contextkey, responsediv); } else if ("global".equals(argdef.Source)) { ServletConfig srvcfg = getServletConfig(); Object val = srvcfg.getServletContext().getAttribute(argdef.Name); /*-trc-*/ Lg.trc(" global key: %s val: %s", contextkey, val.toString()); argmap.put(contextkey, val); } else if ("resource".equals(argdef.Source)) { String content = ResourceLoader.loadResource( argdef.LocalUrl, argdef.Url, argdef.File, argdef.Resource); /*-trc-*/ Lg.trc(" resource key: %s val: %s", contextkey, content); argmap.put(contextkey, content); } else if ("context".equals(argdef.Source)) { // remap a context key Object o = actioncontext.getProcessingContextMap().get(argdef.Name); /*-trc-*/ Lg.trc(" context key: %s val: %s", contextkey, o); argmap.put(contextkey, o); } else if ("config".equals(argdef.Source)) { // load a config key argmap.put(contextkey, ((Map) ((Map) progitdef).get("Config")).get(argdef.Name)); } else if ("action".equals(argdef.Source)) { // TODO... } else if ("pathinfo".equals(argdef.Source)) { String extrapathinfo = this.getActionPathInfo(request); /*-trc-*/ Lg.trc(" pathinfo key: %s val: %s", contextkey, extrapathinfo); argmap.put(contextkey, extrapathinfo); } } /*-trc-*/ Lg.trc("set argmap in action context"); actioncontext.setArgMap(argmap); } else { actioncontext.setArgMap(null); } try { /*-trc-*/ Lg.trc("====EXEC PROGIT===="); responsediv = progit.execute(progitdef, actioncontext, responsediv); /*-trc-*/ Lg.trc("===PROGIT EXEC DONE==="); actioncontext.setPluginConfig(null); } catch (Exception e) { /*-ERROR-*/ Lg.err("progit exec error for %s", progitclass, e); throw ErrorService.packageActionError( actionname, i, actioncontext, "ActionExecErr", "progit exec error for %s", progitclass, e); } // check for jumps/redirects // if (context.redirectaction != null) { // // REDIRECT!!!! -- TODO: may need to do authenticators for the new // action, lots of open questions here... // /*-trc-*/Lg.trc("redirecting to action %s",context.redirectaction); // // god this is sooooo beautifully dangerous and wrong: reset and // repoint the for loop... // action = // (LSActionHandler)WebConfig.Actions.get(context.redirectaction); // i = -1; // The devil commands it! // context.redirectaction = null; // } } catch (Exception e) { /*-ERROR-*/ Lg.err("progit load error for %s", progitclass, e); throw ErrorService.packageActionError( actionname, i, actioncontext, "ActionExecErr", "Action exec of %s in action %s threw error", progitclass, e); } } return responsediv; }
public String authenticateAction(String actionname, Map actionconfig) { HttpServletRequest request = RequestContext.getHttpRequest(); String failureaction = null; boolean authenticated = false; List authlist = null; if (actionconfig.containsKey("Authentication")) { // action-specific authenticator authlist = (List) CfgUtils.lookup(actionconfig, "[authentication][authenticators]"); } else { // exec global authenticators /*-trc-*/ Lg.trc("get GLOBAL authenticators"); authlist = (List) CfgUtils.lookup(WebConfig, "[global defaults][authentication][authenticator]"); } if (authlist != null) { for (int i = 0; i < authlist.size(); i++) { /*-trc-*/ Lg.trc("exec auth #%d", i); Map auth = (Map) authlist.get(i); IAuthenticator authenticator = null; try { /*-trc-*/ Lg.trc("instantiating auth plugin %s", auth != null ? auth.get("class") : null); authenticator = (IAuthenticator) PluginLoader.loadPlugin((String) auth.get("class")); } catch (Exception e) { /*-ERROR-*/ Lg.err("Load of Authenticator plugin threw an error", e); EEx.create("CfgErr-AuthCreateError", "Load of Authenticator plugin threw an error", e); } try { /*-trc-*/ Lg.trc("EXEC AUTH plugin"); authenticated = authenticator.authenticate((Map) auth.get("config"), actionname, actionconfig); /*-trc-*/ Lg.trc("AUTH EXEC result: %b", authenticated); if (!authenticated) { /*-trc-*/ Lg.trc("auth failure --> store original action, failing plugin, and context"); if (auth.containsKey("authfailaction")) { failureaction = (String) auth.get("authfailaction"); /*-trc-*/ Lg.trc( "auth failure --> redirecting to auth plugin-specific action %s to handle failed authentication", failureaction); } else { // TODO: ?more granularity? // use global action failureaction = (String) CfgUtils.lookup( WebConfig, "[global defaults][authentication][authfailaction]"); /*-trc-*/ Lg.trc( "auth failure --> redirecting to globally specified action %s to handle failed authentication", failureaction); } i = authlist.size(); // stop checking authentication } } catch (Exception e) { /*-ERROR-*/ Lg.err( "Execution of authorization check of %s threw error", auth != null ? auth.get("AuthClass") : null, e); EEx.create( "AuthCheckErr", "Execution of authorization check of %s threw error", auth != null ? auth.get("AuthClass") : null, e); } } } return failureaction; }
/** * Process handles GET and POST requests to LiteServ's controller. This is typically invoke for * full-page or (yuck) HTML-Frames page requests. First it checks if the request requires * authentication based on the specified action. * * <p>If so, it invokes the global and handler-specific authenticators usually for credential * authentication such as:<br> * - cookie-based credentials <br> * - credentials in the request parameters l1=, l2=, etc. <br> * In general, authenticators should be capable of handling both types (the former is an existing * login entered, the latter is probably credentials in a shortcut, for REST compatibility) * * <p>If none is provided or the authentication fails, the ErrorAction action is invoked (either * global or authenticator-specific), along with pass-thru data to reprocess the current request * once the credentials have been obtained. * * <p>Once login has succeeded/authenticated, the action handler is looked up and invoked, as per * the usual MVC process. For documentum we will likely implement action handlers which perform * WDK-style scoping mechanisms. But the framework is intended for generic near-stateless web * clients in general. * * @param request the request send by the client to the server * @param response the response send by the server to the client * @throws ServletException if an error occurred * @throws IOException if an error occurred */ public String process(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { reloadConfig(); String responsediv = null; Map processingcontext = new HashMap(); ActionContext actioncontext = new ActionContext( getServletContext(), request, null /*argmap*/, processingcontext, null /*pluginconfig*/, WebConfig); request.setAttribute("ActionContext", actioncontext); /*-INFO-*/ Lg.inf("Process request"); // TODO: more in-depth trace logging on the request // threadlocal the request and response so they are accessible at all times by plugins, etc /*-trc-*/ Lg.trc("set threadlocal references"); RequestContext.setHttpObjects(request, response, getServletContext(), WebConfig, actioncontext); // get action /*-trc-*/ Lg.trc("get action from request"); String actionname = getActionFromRequest(request); // currently using extra path info /*-trc-*/ Lg.trc("get config for action: %s", actionname); Map actioncfg = (Map) CfgUtils.lookup(WebConfig, "[actions][" + actionname + ']'); // scoping...TBD // determine handler security /*-trc-*/ Lg.trc("check action security"); String authfailure = null; if (!"unsecured".equalsIgnoreCase((String) actioncfg.get("security"))) { // authenticate authfailure = authenticateAction(actionname, actioncfg); } if (authfailure == null) // no news is good news { // determine if there is controller processing, or we are simply forwarding to a jsp/vtl/html if (actioncfg.containsKey("Processing")) { // complicated // exec div generation action /*-trc-*/ Lg.trc("EXEC requested action %s", actionname); try { responsediv = executeAction(actionname, actioncfg, "", actioncontext); } catch (EEx lse) { // perform error action handling } } else { // simple/default processing: look for jsp, vtl or html in config map to exec (groovy? etc?) // get files map Map files = (Map) actioncfg.get("@Files"); Iterator i = files.keySet().iterator(); String jsp = null; String vtl = null; String html = null; while (i.hasNext()) { String key = (String) i.next(); if (key.length() > 4 && key.indexOf('.') != -1) { if (".jsp".equalsIgnoreCase(key.substring(key.length() - 4))) { jsp = key; } } if (key.length() > 4 && key.indexOf('.') != -1) { if (".vtl".equalsIgnoreCase(key.substring(key.length() - 4))) { vtl = key; } } if (key.length() > 4 && key.indexOf('.') != -1) { if (".htm".equalsIgnoreCase(key.substring(key.length() - 4))) { html = key; } } if (key.length() > 5 && key.indexOf('.') != -1) { if (".html".equalsIgnoreCase(key.substring(key.length() - 5))) { html = key; } } if (key.length() > 3 && key.indexOf('.') != -1) { if (".js".equalsIgnoreCase(key.substring(key.length() - 3))) { html = key; } } } if (jsp != null) { String resourcepath = (String) actioncfg.get("@Path") + jsp; responsediv = ResourceLoader.callActiveUrl(getServletContext(), request, response, resourcepath); } else if (vtl != null) { // output vtl responsediv = "Velocity support coming soon"; } else if (html != null) { String resourcepath = (String) actioncfg.get("@Path") + html; responsediv = ResourceLoader.loadWebResource(getServletContext(), resourcepath); // output html } } } else { /*-trc-*/ Lg.trc("EXEC authorization failure action %s", authfailure); } /*-trc-*/ Lg.trc("postprocess"); responsediv = postprocess(request, response, responsediv); /*-trc-*/ Lg.trc("done"); // send fully generated page return responsediv; }