0001: /*
0002: * This file is part of PFIXCORE.
0003: *
0004: * PFIXCORE is free software; you can redistribute it and/or modify
0005: * it under the terms of the GNU Lesser General Public License as published by
0006: * the Free Software Foundation; either version 2 of the License, or
0007: * (at your option) any later version.
0008: *
0009: * PFIXCORE is distributed in the hope that it will be useful,
0010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
0012: * GNU Lesser General Public License for more details.
0013: *
0014: * You should have received a copy of the GNU Lesser General Public License
0015: * along with PFIXCORE; if not, write to the Free Software
0016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0017: */
0018:
0019: package de.schlund.pfixcore.workflow.context;
0020:
0021: import java.util.ArrayList;
0022: import java.util.Iterator;
0023: import java.util.LinkedHashSet;
0024: import java.util.List;
0025: import java.util.Properties;
0026: import java.util.Set;
0027:
0028: import javax.servlet.http.Cookie;
0029: import javax.servlet.http.HttpServletResponse;
0030:
0031: import org.apache.log4j.Logger;
0032: import org.w3c.dom.Document;
0033: import org.w3c.dom.Element;
0034: import org.w3c.dom.Node;
0035:
0036: import de.schlund.pfixcore.auth.AuthConstraint;
0037: import de.schlund.pfixcore.auth.AuthConstraintViolation;
0038: import de.schlund.pfixcore.auth.Authentication;
0039: import de.schlund.pfixcore.auth.AuthorizationException;
0040: import de.schlund.pfixcore.auth.AuthorizationInterceptor;
0041: import de.schlund.pfixcore.auth.NotAuthenticatedException;
0042: import de.schlund.pfixcore.auth.Role;
0043: import de.schlund.pfixcore.exception.PustefixApplicationException;
0044: import de.schlund.pfixcore.exception.PustefixCoreException;
0045: import de.schlund.pfixcore.exception.PustefixRuntimeException;
0046: import de.schlund.pfixcore.generator.StatusCodeInfo;
0047: import de.schlund.pfixcore.workflow.ContextImpl;
0048: import de.schlund.pfixcore.workflow.ContextInterceptor;
0049: import de.schlund.pfixcore.workflow.FlowStep;
0050: import de.schlund.pfixcore.workflow.PageMap;
0051: import de.schlund.pfixcore.workflow.PageRequest;
0052: import de.schlund.pfixcore.workflow.PageRequestStatus;
0053: import de.schlund.pfixcore.workflow.State;
0054: import de.schlund.pfixcore.workflow.VariantManager;
0055: import de.schlund.pfixcore.workflow.app.DefaultIWrapperState;
0056: import de.schlund.pfixxml.ContextXMLServlet;
0057: import de.schlund.pfixxml.PfixServletRequest;
0058: import de.schlund.pfixxml.RequestParam;
0059: import de.schlund.pfixxml.ResultDocument;
0060: import de.schlund.pfixxml.SPDocument;
0061: import de.schlund.pfixxml.ServletManager;
0062: import de.schlund.pfixxml.Variant;
0063: import de.schlund.pfixxml.config.PageRequestConfig;
0064: import de.schlund.pfixxml.perflogging.PerfEvent;
0065: import de.schlund.pfixxml.perflogging.PerfEventType;
0066: import de.schlund.util.statuscodes.StatusCode;
0067:
0068: /**
0069: * Implementation of the request part of the context used by ContextXMLServlet,
0070: * DirectOutputServlet and WebServiceServlet. This class should never be directly
0071: * used by application developers.
0072: *
0073: * @author Sebastian Marsching <sebastian.marsching@1und1.de>
0074: */
0075: public class RequestContextImpl implements Cloneable,
0076: AuthorizationInterceptor {
0077:
0078: private final static Logger LOG = Logger
0079: .getLogger(ContextImpl.class);
0080: private final static String PARAM_JUMPPAGE = "__jumptopage";
0081: private final static String PARAM_JUMPPAGEFLOW = "__jumptopageflow";
0082: private final static String PARAM_FLOW = "__pageflow";
0083: private final static String PARAM_LASTFLOW = "__lf";
0084: private final static String PARAM_STARTWITHFLOW = "__startwithflow";
0085: private final static String PARAM_FORCESTOP = "__forcestop";
0086: private final static String PARAM_ROLEAUTH = "__roleauth";
0087: private final static String PARAM_ROLEAUTHTARGET = "__roleauthtarget";
0088:
0089: private ContextImpl parentcontext;
0090: private ServerContextImpl servercontext;
0091: private PageFlowManager pageflowmanager;
0092: private VariantManager variantmanager;
0093: private PageMap pagemap;
0094:
0095: private Variant variant = null;
0096: private String language = null;
0097:
0098: private PageRequest currentpagerequest = null;
0099: private PageFlow currentpageflow = null;
0100: private PfixServletRequest currentpservreq = null;
0101:
0102: private String jumptopage = null;
0103: private String jumptopageflow = null;
0104:
0105: private boolean roleAuth;
0106: private String roleAuthTarget;
0107: private Set<String> roleAuthDeps;
0108:
0109: private PageRequest authpage = null;
0110: private boolean prohibitcontinue = false;
0111: private boolean stopnextforcurrentrequest = false;
0112: private boolean on_jumptopage = false;
0113: private boolean pageflow_requested_by_user = false;
0114: private boolean startwithflow = false;
0115:
0116: private List<StatusCodeInfo> messages = new ArrayList<StatusCodeInfo>();
0117: private List<Cookie> cookielist = new ArrayList<Cookie>();
0118:
0119: public RequestContextImpl(ServerContextImpl servercontext,
0120: ContextImpl context) {
0121: this .parentcontext = context;
0122: this .servercontext = servercontext;
0123: this .pageflowmanager = servercontext.getPageFlowManager();
0124: this .variantmanager = servercontext.getVariantManager();
0125: this .pagemap = servercontext.getPageMap();
0126:
0127: this .variant = parentcontext.getSessionVariant();
0128: this .language = parentcontext.getSessionLanguage();
0129:
0130: // Initialize with default values, will be overwritten by
0131: // request parameters
0132: currentpageflow = pageflowmanager.getPageFlowByName(
0133: servercontext.getContextConfig().getDefaultFlow(),
0134: getVariant());
0135: currentpagerequest = createPageRequest(currentpageflow
0136: .getFirstStep().getPageName());
0137:
0138: checkForAuthenticationMode();
0139: }
0140:
0141: public ServerContextImpl getServerContext() {
0142: return servercontext;
0143: }
0144:
0145: public Properties getPropertiesForCurrentPageRequest() {
0146: if (currentpagerequest != null) {
0147: PageRequestConfig conf = servercontext.getContextConfig()
0148: .getPageRequestConfig(currentpagerequest.getName());
0149: if (conf != null) {
0150: return conf.getProperties();
0151: }
0152: }
0153: return null;
0154: }
0155:
0156: public PageRequest getCurrentPageRequest() {
0157: if (currentpagerequest == null) {
0158: throw new IllegalStateException(
0159: "PageRequest is only available witihin request handling");
0160: }
0161: return currentpagerequest;
0162: }
0163:
0164: public PageFlow getCurrentPageFlow() {
0165: if (currentpservreq == null) {
0166: throw new IllegalStateException(
0167: "PageFlow is only available witihin request handling");
0168: }
0169: return currentpageflow;
0170: }
0171:
0172: public void setCurrentPageFlow(String pageflow) {
0173: if (currentpservreq == null) {
0174: throw new IllegalStateException(
0175: "PageFlow is only available witihin request handling");
0176: }
0177:
0178: PageFlow tmp = pageflowmanager.getPageFlowByName(pageflow,
0179: getVariant());
0180: if (tmp != null) {
0181: LOG
0182: .debug("===> Setting currentpageflow to user-requested flow "
0183: + pageflow);
0184: currentpageflow = tmp;
0185: pageflow_requested_by_user = true;
0186: } else {
0187: LOG.warn("*** Trying to set currentpageflow to " + pageflow
0188: + ", but it's not defined ***");
0189: }
0190: }
0191:
0192: public String getJumpToPage() {
0193: if (currentpservreq == null) {
0194: throw new IllegalStateException(
0195: "JumpToPage is only available witihin request handling");
0196: }
0197: return jumptopage;
0198: }
0199:
0200: public void setJumpToPage(String pagename) {
0201: if (currentpservreq == null) {
0202: throw new IllegalStateException(
0203: "JumpToPage is only available witihin request handling");
0204: }
0205:
0206: PageRequest page = createPageRequest(pagename);
0207: if (pagemap.getState(page) != null) {
0208: jumptopage = pagename;
0209: } else {
0210: LOG.warn("*** Trying to set jumppage " + pagename
0211: + ", but it's not defined ***");
0212: jumptopage = null;
0213: }
0214: }
0215:
0216: public boolean isJumpToPageSet() {
0217: return getJumpToPage() != null;
0218: }
0219:
0220: public String getJumpToPageFlow() {
0221: if (currentpservreq == null) {
0222: throw new IllegalStateException(
0223: "JumpToPageFlow is only available witihin request handling");
0224: }
0225: return jumptopageflow;
0226: }
0227:
0228: public void setJumpToPageFlow(String pageflow) {
0229: if (currentpservreq == null) {
0230: throw new IllegalStateException(
0231: "JumpToPageFlow is only available witihin request handling");
0232: }
0233:
0234: if (jumptopage != null) {
0235: PageFlow tmp = pageflowmanager.getPageFlowByName(pageflow,
0236: null);
0237: if (tmp != null) {
0238: jumptopageflow = pageflow;
0239: } else {
0240: LOG.warn("*** Trying to set jumptopageflow " + pageflow
0241: + ", but it's not defined ***");
0242: jumptopageflow = null;
0243: }
0244: } else {
0245: jumptopageflow = null;
0246: }
0247: }
0248:
0249: public boolean isJumpToPageFlowSet() {
0250: return getJumpToPageFlow() != null;
0251: }
0252:
0253: public void prohibitContinue() {
0254: if (currentpservreq == null) {
0255: throw new IllegalStateException(
0256: "PageFlow handling is only available witihin request handling");
0257: }
0258: prohibitcontinue = true;
0259: }
0260:
0261: public boolean isProhibitContinue() {
0262: if (currentpservreq == null) {
0263: throw new IllegalStateException(
0264: "PageFlow handling is only available witihin request handling");
0265: }
0266: return prohibitcontinue;
0267: }
0268:
0269: public boolean isProhibitContinueSet() {
0270: return isProhibitContinue();
0271: }
0272:
0273: public boolean precedingFlowNeedsData()
0274: throws PustefixApplicationException {
0275: if (currentpservreq == null) {
0276: throw new IllegalStateException(
0277: "PageFlow information is only availabe during request handling");
0278: }
0279:
0280: if (!currentpageflow.containsPage(currentpagerequest
0281: .getRootName())) {
0282: throw new RuntimeException("*** current pageflow "
0283: + currentpageflow.getName()
0284: + " does not contain current pagerequest "
0285: + currentpagerequest);
0286: }
0287:
0288: PageRequest current = currentpagerequest;
0289: FlowStep[] workflow = currentpageflow.getAllSteps();
0290:
0291: for (int i = 0; i < workflow.length; i++) {
0292: FlowStep step = workflow[i];
0293: String pagename = step.getPageName();
0294: PageRequest page = createPageRequest(pagename);
0295: if (pagename.equals(current.getRootName())) {
0296: return false;
0297: }
0298: if (checkIsAccessible(page, current.getStatus())
0299: && checkNeedsData(page, current.getStatus())) {
0300: return true;
0301: }
0302: }
0303: return false;
0304: }
0305:
0306: public boolean finalPageIsRunning() {
0307: if (currentpservreq == null) {
0308: throw new IllegalStateException(
0309: "PageFlow information is only availabe during request handling");
0310: }
0311: return (currentpagerequest.getStatus() == PageRequestStatus.FINAL);
0312: }
0313:
0314: public boolean jumpToPageIsRunning() {
0315: if (currentpservreq == null) {
0316: throw new IllegalStateException(
0317: "PageFlow information is only availabe during request handling");
0318: }
0319: return on_jumptopage;
0320: }
0321:
0322: public boolean flowIsRunning() {
0323: if (currentpservreq == null) {
0324: throw new IllegalStateException(
0325: "PageFlow information is only availabe during request handling");
0326: }
0327:
0328: if (currentpagerequest.getStatus() == PageRequestStatus.WORKFLOW) {
0329: return true;
0330: } else {
0331: return false;
0332: }
0333: }
0334:
0335: public boolean isCurrentPageRequestInCurrentFlow() {
0336: if (currentpservreq == null) {
0337: throw new IllegalStateException(
0338: "PageFlow information is only availabe during request handling");
0339: }
0340: return (currentpageflow != null && currentpageflow
0341: .containsPage(currentpagerequest.getRootName()));
0342: }
0343:
0344: public boolean isCurrentPageFlowRequestedByUser() {
0345: if (currentpservreq == null) {
0346: throw new IllegalStateException(
0347: "PageFlow information is only availabe during request handling");
0348: }
0349: return pageflow_requested_by_user;
0350: }
0351:
0352: public String getLanguage() {
0353: return language;
0354: }
0355:
0356: public void setLanguage(String lang) {
0357: language = lang;
0358: }
0359:
0360: public Variant getVariant() {
0361: return variant;
0362: }
0363:
0364: public void setVariantForThisRequestOnly(Variant variant) {
0365: if (currentpservreq == null) {
0366: throw new IllegalStateException(
0367: "This feature is only available during request handling");
0368: }
0369: this .variant = variant;
0370: }
0371:
0372: public boolean stateMustSupplyFullDocument() {
0373: if (currentpservreq == null) {
0374: throw new IllegalStateException(
0375: "PageFlow information is only availabe during request handling");
0376: }
0377:
0378: if (prohibitcontinue) {
0379: // We will use the returned document no matter what else happens.
0380: return true;
0381: }
0382: if (currentFlowStepWantsPostProcess()) {
0383: // We need the full doc for the post processing no matter what else happens.
0384: return true;
0385: }
0386: if (getJumpToPageFlow() != null) {
0387: // We will jump to some page and not use the returned document for creating the UI.
0388: return false;
0389: }
0390: if (isCurrentPageRequestInCurrentFlow()
0391: || isCurrentPageFlowRequestedByUser()) {
0392: // The next page to display is determined from the pageflow
0393: return false;
0394: }
0395:
0396: // better create the document one time too much...
0397: return true;
0398: }
0399:
0400: private boolean currentFlowStepWantsPostProcess() {
0401: if (currentpageflow != null
0402: && currentpageflow.containsPage(currentpagerequest
0403: .getRootName())) {
0404: if (currentpageflow.getFlowStepForPage(
0405: currentpagerequest.getRootName())
0406: .hasOnContinueAction()) {
0407: return true;
0408: }
0409: }
0410: return false;
0411: }
0412:
0413: public void addPageMessage(StatusCode scode) {
0414: addPageMessage(scode, null, null);
0415: }
0416:
0417: public void addPageMessage(StatusCode scode, String level) {
0418: addPageMessage(scode, null, level);
0419: }
0420:
0421: public void addPageMessage(StatusCode scode, String[] args) {
0422: addPageMessage(scode, args, null);
0423: }
0424:
0425: public void addPageMessage(StatusCode scode, String[] args,
0426: String level) {
0427: if (currentpservreq == null) {
0428: throw new IllegalStateException(
0429: "PageMessages are only availabe during request handling");
0430: }
0431: if (scode == null)
0432: return;
0433: messages.add(new StatusCodeInfo(scode, args, level));
0434: }
0435:
0436: public SPDocument handleRequest(PfixServletRequest preq)
0437: throws PustefixApplicationException, PustefixCoreException {
0438: SPDocument spdoc;
0439:
0440: spdoc = handleRequestWorker(preq);
0441:
0442: boolean forceSSL = false;
0443: if (getConfigForCurrentPageRequest() != null
0444: && getConfigForCurrentPageRequest().isSSL()
0445: && !preq.getOriginalScheme().equals("https")) {
0446: forceSSL = true;
0447: }
0448:
0449: if (spdoc != null && forceSSL) {
0450: // Make sure connection is switched to SSL if current page is marked
0451: // as "secure"
0452: String scheme = "https";
0453: String port = getServerContext().getProperties()
0454: .getProperty(
0455: ServletManager.PROP_SSL_REDIRECT_PORT
0456: + String.valueOf(preq
0457: .getOriginalServerPort()));
0458: if (port == null) {
0459: port = "443";
0460: }
0461:
0462: String redirectURL = scheme + "://"
0463: + ServletManager.getServerName(preq.getRequest())
0464: + ":" + port + preq.getContextPath()
0465: + preq.getServletPath() + "/" + spdoc.getPagename()
0466: + ";jsessionid=" + preq.getSession(false).getId()
0467: + "?__reuse=" + spdoc.getTimestamp();
0468:
0469: RequestParam rp = preq.getRequestParam("__frame");
0470: if (rp != null) {
0471: redirectURL += "&__frame=" + rp.getValue();
0472: }
0473: spdoc.setRedirect(redirectURL);
0474:
0475: }
0476:
0477: // Reset stored variant so the session variant is being used
0478: // to check the visibility of other pages when rendering the output
0479: this .variant = parentcontext.getSessionVariant();
0480:
0481: return spdoc;
0482: }
0483:
0484: private SPDocument handleRequestWorker(PfixServletRequest preq)
0485: throws PustefixApplicationException, PustefixCoreException {
0486: currentpservreq = preq;
0487: prohibitcontinue = false;
0488: stopnextforcurrentrequest = false;
0489: jumptopage = null;
0490: jumptopageflow = null;
0491: on_jumptopage = false;
0492: pageflow_requested_by_user = false;
0493: startwithflow = false;
0494: roleAuthDeps = null;
0495:
0496: RequestParam fstop = currentpservreq
0497: .getRequestParam(PARAM_FORCESTOP);
0498: if (fstop != null && fstop.getValue().equals("true")) {
0499: // We already decide here to stay on the page, what ever the state wants...
0500: prohibitContinue();
0501: }
0502: if (fstop != null && fstop.getValue().equals("step")) {
0503: // We want to behave the current pageflow as if it would have the stopnext attribute set to true
0504: stopnextforcurrentrequest = true;
0505: }
0506:
0507: RequestParam swflow = currentpservreq
0508: .getRequestParam(PARAM_STARTWITHFLOW);
0509: if (swflow != null && swflow.getValue().equals("true")) {
0510: startwithflow = true;
0511: }
0512:
0513: // This helps to reset the state between different requests from different windows
0514: // representing different locations in the same application. The page will be set a bit
0515: // below in trySettingPageRequestAndFlow, where the "real" pageflow to use is also deduced.
0516: // At least, the currentpageflow is updated to be the currently valid variant.
0517: RequestParam lastflow = currentpservreq
0518: .getRequestParam(PARAM_LASTFLOW);
0519:
0520: processIC(servercontext.getStartInterceptors());
0521:
0522: if (lastflow != null && !lastflow.getValue().equals("")) {
0523: PageFlow tmp = pageflowmanager.getPageFlowByName(lastflow
0524: .getValue(), getVariant());
0525: if (tmp != null) {
0526: LOG.debug("* Got last pageflow state from request as ["
0527: + tmp.getName() + "]");
0528: currentpageflow = tmp;
0529: }
0530: } else if (currentpageflow != null) {
0531: // HttpServletRequest req = currentpservreq.getRequest();
0532: // LOG.warn("LASTFLOWNOTSET:" + currentpservreq.getServerName() + "|"
0533: // + currentpservreq.getRequest().getHeader("Referer") + "|"
0534: // + currentpservreq.getRequestURI() + "|" + currentpageflow.getName());
0535: currentpageflow = pageflowmanager.getPageFlowByName(
0536: currentpageflow.getRootName(), getVariant());
0537: }
0538: // Update currentpagerequest to currently valid variant
0539: if (currentpagerequest != null) {
0540: currentpagerequest = createPageRequest(currentpagerequest
0541: .getRootName());
0542: }
0543:
0544: trySettingPageRequestAndFlow();
0545:
0546: SPDocument spdoc = documentFromFlow();
0547:
0548: processIC(servercontext.getEndInterceptors());
0549:
0550: if (spdoc != null) {
0551: if (spdoc.getPagename() == null) {
0552: spdoc.setPagename(currentpagerequest.getRootName());
0553: }
0554:
0555: if (currentpageflow != null) {
0556: spdoc.setProperty("pageflow", currentpageflow
0557: .getRootName());
0558: addPageFlowInfo(currentpageflow, spdoc);
0559: }
0560:
0561: Variant var = getVariant();
0562: if (var != null) {
0563: spdoc.setVariant(var);
0564: spdoc.getDocument().getDocumentElement().setAttribute(
0565: "requested-variant", var.getVariantId());
0566: if (currentpagerequest != null)
0567: spdoc.getDocument().getDocumentElement()
0568: .setAttribute("used-pr",
0569: currentpagerequest.getName());
0570: if (currentpageflow != null)
0571: spdoc.getDocument().getDocumentElement()
0572: .setAttribute("used-pf",
0573: currentpageflow.getName());
0574: }
0575:
0576: if (spdoc.getResponseError() == 0) {
0577: parentcontext.addVisitedPage(spdoc.getPagename());
0578: // if (!getConfigForCurrentPageRequest().isStoreXML()) {
0579: // spdoc.setNostore(true);
0580: // }
0581: }
0582:
0583: LOG.debug("\n");
0584: insertPageMessages(spdoc);
0585: storeCookies(spdoc);
0586: spdoc.setProperty(
0587: ContextXMLServlet.XSLPARAM_REQUESTCONTEXT, this );
0588: }
0589:
0590: return spdoc;
0591: }
0592:
0593: private void insertPageMessages(SPDocument spdoc) {
0594: if (spdoc == null)
0595: return;
0596:
0597: LOG.debug("Adding " + messages.size()
0598: + " PageMessages to result document");
0599:
0600: if (!messages.isEmpty()) {
0601: Document doc = spdoc.getDocument();
0602: Element formresult = doc.getDocumentElement();
0603:
0604: if (formresult != null) {
0605: Element messagesElem = doc
0606: .createElement("pagemessages");
0607: formresult.appendChild(messagesElem);
0608:
0609: Iterator<StatusCodeInfo> iter = messages.iterator();
0610: while (iter.hasNext()) {
0611: StatusCodeInfo sci = iter.next();
0612: Element msg = doc.createElement("message");
0613: Element inc = ResultDocument
0614: .createIncludeFromStatusCode(doc,
0615: servercontext.getContextConfig()
0616: .getProperties(), sci
0617: .getStatusCode(), sci
0618: .getArgs());
0619: msg.appendChild(inc);
0620: if (sci.getLevel() != null) {
0621: msg.setAttribute("level", sci.getLevel());
0622: }
0623: messagesElem.appendChild(msg);
0624:
0625: LOG.debug("Added PageMessage for level "
0626: + sci.getLevel() + " with args "
0627: + sci.getArgs());
0628: }
0629: }
0630: }
0631: }
0632:
0633: private void storeCookies(SPDocument spdoc) {
0634: for (Iterator<Cookie> i = cookielist.iterator(); i.hasNext();) {
0635: spdoc.addCookie(i.next());
0636: }
0637: }
0638:
0639: private void addPageFlowInfo(PageFlow flow, SPDocument spdoc) {
0640: Document doc = spdoc.getDocument();
0641: Element root = doc.createElement("pageflow");
0642: doc.getDocumentElement().appendChild(root);
0643: root.setAttribute("name", flow.getRootName());
0644: FlowStep[] steps = flow.getAllSteps();
0645: for (int i = 0; i < steps.length; i++) {
0646: String step = steps[i].getPageName();
0647: Element stepelem = doc.createElement("step");
0648: root.appendChild(stepelem);
0649: stepelem.setAttribute("name", step);
0650: }
0651: }
0652:
0653: private void processIC(ContextInterceptor[] icarr) {
0654: if (icarr != null) {
0655: for (int i = 0; i < icarr.length; i++) {
0656: icarr[i].process(parentcontext, currentpservreq);
0657: }
0658: }
0659: }
0660:
0661: private PageRequest createPageRequest(String pagename) {
0662: Variant var = getVariant();
0663: if (var != null && var.getVariantFallbackArray() != null
0664: && variantmanager != null) {
0665: return new PageRequest(variantmanager
0666: .getVariantMatchingPageRequestName(pagename, var));
0667: } else {
0668: return new PageRequest(pagename);
0669: }
0670: }
0671:
0672: public PageRequestConfig getConfigForCurrentPageRequest() {
0673: if (currentpagerequest == null) {
0674: throw new IllegalStateException(
0675: "PageRequest is only available witihin request handling");
0676: }
0677: return servercontext.getContextConfig().getPageRequestConfig(
0678: currentpagerequest.getName());
0679: }
0680:
0681: private SPDocument documentFromFlow()
0682: throws PustefixApplicationException, PustefixCoreException {
0683: SPDocument document = null;
0684:
0685: // First, check if the requested page is defined at all
0686: // We do this only if the current pagerequest is not the special STARTWITHFLOW_PAGE
0687: // because then we don't know yet which page to use.
0688:
0689: if (!startwithflow) {
0690: ResultDocument resdoc;
0691:
0692: State state = pagemap.getState(currentpagerequest);
0693: if (state == null) {
0694: LOG.warn("* Can't get a handling state for page "
0695: + currentpagerequest);
0696: resdoc = new ResultDocument();
0697: Node commentNode = resdoc
0698: .getRootElement()
0699: .getOwnerDocument()
0700: .createComment(
0701: " This XML tree contains no page specific data as no page configuration could be found! ");
0702: if (resdoc.getRootElement().getFirstChild() != null) {
0703: resdoc.getRootElement().insertBefore(commentNode,
0704: resdoc.getRootElement().getFirstChild());
0705: } else {
0706: resdoc.getRootElement().appendChild(commentNode);
0707: }
0708: document = resdoc.getSPDocument();
0709: document
0710: .setResponseError(HttpServletResponse.SC_NOT_FOUND);
0711: return document;
0712: }
0713:
0714: // Now, check for possibly needed authorization
0715: RequestParam sdreq = currentpservreq
0716: .getRequestParam(State.SENDAUTHDATA);
0717: boolean forceauth = (sdreq != null && sdreq.isTrue());
0718:
0719: document = checkAuthorization(forceauth);
0720: if (document != null) {
0721: return document;
0722: }
0723:
0724: // Now we need to make sure that the current page is accessible, and take the right measures if not.
0725: if (!checkIsAccessible(currentpagerequest,
0726: PageRequestStatus.DIRECT)) {
0727: LOG
0728: .warn("["
0729: + currentpagerequest
0730: + "]: not accessible! Trying first page of default flow.");
0731: currentpageflow = pageflowmanager.getPageFlowByName(
0732: servercontext.getContextConfig()
0733: .getDefaultFlow(), getVariant());
0734: PageRequest defpage = createPageRequest(currentpageflow
0735: .getFirstStep().getPageName());
0736: currentpagerequest = defpage;
0737: if (!checkIsAccessible(defpage,
0738: PageRequestStatus.DIRECT)) {
0739: throw new PustefixCoreException(
0740: "Even first page ["
0741: + defpage
0742: + "] of default flow was not accessible! Bailing out.");
0743: }
0744: }
0745:
0746: resdoc = documentFromCurrentStep();
0747: if (currentpageflow != null
0748: && currentpageflow.containsPage(currentpagerequest
0749: .getRootName())) {
0750: FlowStep step = currentpageflow
0751: .getFlowStepForPage(currentpagerequest
0752: .getRootName());
0753: step.applyActionsOnContinue(parentcontext, resdoc);
0754: }
0755:
0756: if (currentpageflow != null) {
0757: currentpageflow = pageflowmanager.getPageFlowByName(
0758: currentpageflow.getRootName(), getVariant());
0759: }
0760:
0761: if (prohibitcontinue) {
0762: LOG
0763: .debug("* ["
0764: + currentpagerequest
0765: + "] returned document to show, skipping page flow.");
0766: document = resdoc.getSPDocument();
0767: } else if (jumptopage != null) {
0768: LOG.debug("* [" + currentpagerequest
0769: + "] signalled success, jumptopage is set as ["
0770: + jumptopage + "].");
0771: currentpagerequest = createPageRequest(jumptopage);
0772: if (jumptopageflow != null) {
0773: setCurrentPageFlow(jumptopageflow);
0774: } else {
0775: currentpageflow = pageflowmanager
0776: .pageFlowToPageRequest(currentpageflow,
0777: currentpagerequest, getVariant());
0778: }
0779: jumptopage = null; // we don't want to recurse infinitely
0780: jumptopageflow = null; // we don't want to recurse infinitely
0781: on_jumptopage = true; // we need this information to supress the interpretation of
0782: // the request as one that submits data. See StateImpl,
0783: // methods isSubmitTrigger & isDirectTrigger
0784:
0785: LOG.debug("******* JUMPING to [" + currentpagerequest
0786: + "] *******\n");
0787: document = documentFromFlow();
0788: } else if (currentpageflow != null) {
0789: if (pageflow_requested_by_user
0790: || currentpageflow
0791: .containsPage(currentpagerequest
0792: .getRootName())) {
0793: LOG
0794: .debug("* ["
0795: + currentpagerequest
0796: + "] signalled success, starting page flow process");
0797: document = runPageFlow(false);
0798: } else {
0799: LOG
0800: .debug("* ["
0801: + currentpagerequest
0802: + "] signalled success, but is neither member of flow ["
0803: + currentpageflow
0804: + "] nor is this flow explicitely requested, skipping page flow.");
0805: document = resdoc.getSPDocument();
0806: }
0807: } else {
0808: // throw new XMLException("*** ERROR! *** [" + currentpagerequest + "] signalled success, but current page flow == null!");
0809: LOG
0810: .debug("* ["
0811: + currentpagerequest
0812: + "] signalled success, but page flow == null, skipping page flow.");
0813: document = resdoc.getSPDocument();
0814: }
0815: } else {
0816: LOG
0817: .debug("* Page is determined from flow ["
0818: + currentpageflow
0819: + "], starting page flow process");
0820: LOG.debug("* Current page: [" + currentpagerequest + "]");
0821: document = runPageFlow(true);
0822: }
0823: return document;
0824: }
0825:
0826: private SPDocument runPageFlow(boolean startwithflow)
0827: throws PustefixApplicationException, PustefixCoreException {
0828: ResultDocument resdoc = null;
0829: // We need to re-check the authorisation because the just handled submit could have changed the authorisation status.
0830: SPDocument document = checkAuthorization(false);
0831: if (document != null) {
0832: return document;
0833: }
0834: FlowStep[] workflow = currentpageflow.getAllSteps();
0835: PageRequest saved = currentpagerequest;
0836: boolean after_current = false;
0837: boolean on_current = false;
0838:
0839: for (int i = 0; i < workflow.length; i++) {
0840: if (on_current)
0841: after_current = true;
0842: FlowStep step = workflow[i];
0843: PageRequest page = createPageRequest(step.getPageName());
0844: if (page.equals(saved)) {
0845: on_current = true;
0846: if (startwithflow
0847: && checkIsAccessible(page,
0848: PageRequestStatus.WORKFLOW)) {
0849: LOG
0850: .debug("=> ["
0851: + page
0852: + "]: STARTWITHFLOW: Pageflow must stop here at last.");
0853: currentpagerequest = page;
0854: currentpagerequest
0855: .setStatus(PageRequestStatus.WORKFLOW);
0856: document = documentFromCurrentStep()
0857: .getSPDocument();
0858: if (document == null) {
0859: throw new PustefixCoreException("*** FATAL: ["
0860: + page
0861: + "] returns a 'null' SPDocument! ***");
0862: }
0863: LOG.debug("* [" + page
0864: + "] returned document => show it.");
0865: break;
0866: } else {
0867: // TODO: This whole "else" branch will be removed as soon as the new behavior for pageflows is implemented
0868: // together with the new IWrapperContainer (IWrapperContainerImpl) and we don't need to implement the old behavior anymore.
0869: String containerclazz = servercontext
0870: .getContextConfig()
0871: .getProperties()
0872: .getProperty(
0873: DefaultIWrapperState.PROP_CONTAINER);
0874: if (containerclazz == null
0875: || containerclazz
0876: .equals(DefaultIWrapperState.DEF_WRP_CONTAINER)) {
0877: LOG
0878: .debug("* Skipping step ["
0879: + page
0880: + "] in page flow (been there already...)");
0881: LOG
0882: .debug(" Please IGNORE the next needsData() check, this is only for logging purposes!!! We will skip regardless of the outcome!");
0883: if (checkIsAccessible(page,
0884: PageRequestStatus.WORKFLOW)
0885: && checkNeedsData(page,
0886: PageRequestStatus.WORKFLOW)) {
0887: LOG.warn("SKIPPEDWOULDSTOP:"
0888: + currentpservreq.getServerName()
0889: + "|" + page.getName() + "|"
0890: + currentpageflow.getName());
0891: }
0892: continue;
0893: }
0894: }
0895: }
0896:
0897: if (!checkIsAccessible(page, PageRequestStatus.WORKFLOW)) {
0898: LOG
0899: .debug("* Skipping step ["
0900: + page
0901: + "] in page flow (state is not accessible...)");
0902: // break;
0903: } else {
0904: LOG.debug("* Page flow is at step " + i + ": [" + page
0905: + "]");
0906: if (after_current
0907: && (step.wantsToStopHere() || stopnextforcurrentrequest)) {
0908: if (stopnextforcurrentrequest)
0909: LOG
0910: .debug("=> Request specifies to act like stophere='true'");
0911: LOG
0912: .debug("=> ["
0913: + page
0914: + "]: Page flow wants to stop, getting document now.");
0915: currentpagerequest = page;
0916: currentpagerequest
0917: .setStatus(PageRequestStatus.WORKFLOW);
0918: resdoc = documentFromCurrentStep();
0919: document = resdoc.getSPDocument();
0920: if (document == null) {
0921: throw new PustefixCoreException("*** FATAL: ["
0922: + page
0923: + "] returns a 'null' SPDocument! ***");
0924: }
0925: LOG.debug("* [" + page
0926: + "] returned document => show it.");
0927: break;
0928: } else if (checkNeedsData(page,
0929: PageRequestStatus.WORKFLOW)) {
0930: LOG
0931: .debug("=> ["
0932: + page
0933: + "]: needsData() returned TRUE, leaving page flow and getting document now.");
0934: currentpagerequest = page;
0935: currentpagerequest
0936: .setStatus(PageRequestStatus.WORKFLOW);
0937: resdoc = documentFromCurrentStep();
0938: document = resdoc.getSPDocument();
0939: if (document == null) {
0940: throw new PustefixCoreException("*** FATAL: ["
0941: + page
0942: + "] returns a 'null' SPDocument! ***");
0943: }
0944: LOG.debug("* [" + page
0945: + "] returned document => show it.");
0946: break;
0947: } else {
0948: LOG
0949: .debug("=> ["
0950: + page
0951: + "]: Page flow doesn't want to stop and needsData() returned FALSE");
0952: LOG.debug("=> [" + page
0953: + "]: going to next step in page flow.");
0954: }
0955: }
0956: }
0957: if (document == null) {
0958: PageRequest finalpage = null;
0959: if (startwithflow) {
0960: finalpage = saved;
0961: LOG
0962: .debug("=> STARTWITHFLOW is active, using original target page ["
0963: + saved + "] as final page");
0964: } else if (currentpageflow.getFinalPage() != null) {
0965: finalpage = createPageRequest(currentpageflow
0966: .getFinalPage());
0967: LOG.debug("=> Pageflow [" + currentpageflow
0968: + "] defines page [" + finalpage
0969: + "] as final page");
0970: }
0971: if (finalpage == null) {
0972: throw new PustefixCoreException(
0973: "*** Reached end of page flow '"
0974: + currentpageflow.getName()
0975: + "' "
0976: + "with neither getting a non-null SPDocument or having a FINAL page defined ***");
0977: } else if (!checkIsAccessible(finalpage,
0978: PageRequestStatus.FINAL)) {
0979: throw new PustefixCoreException(
0980: "*** Reached end of page flow '"
0981: + currentpageflow.getName() + "' "
0982: + "but FINAL page [" + finalpage
0983: + "] is inaccessible ***");
0984: } else {
0985: currentpagerequest = finalpage;
0986: currentpageflow = pageflowmanager
0987: .pageFlowToPageRequest(currentpageflow,
0988: finalpage, getVariant());
0989: finalpage.setStatus(PageRequestStatus.FINAL);
0990: resdoc = documentFromCurrentStep();
0991: document = resdoc.getSPDocument();
0992: if (document == null) {
0993: throw new PustefixCoreException("*** FATAL: "
0994: + finalpage
0995: + " returns a 'null' SPDocument! ***");
0996: }
0997: }
0998: }
0999: return document;
1000: }
1001:
1002: public SPDocument checkAuthorization(boolean forceauth)
1003: throws PustefixApplicationException, PustefixCoreException {
1004: return checkAuthorization(forceauth, true);
1005: }
1006:
1007: public SPDocument checkAuthorization(boolean forceauth,
1008: boolean needDocument) throws PustefixApplicationException,
1009: PustefixCoreException {
1010: // The needDocument flag is a hack that should only be used internally:
1011: // It is needed, when this method is called only to see, whether
1012: // the context is authenticated, but the creation of SPDocument
1013: // for the login page would lead to an exception being thrown.
1014: if (authpage != null) {
1015: ResultDocument resdoc = null;
1016: LOG
1017: .debug("===> [" + authpage
1018: + "]: Checking authorisation");
1019: if (!checkIsAccessible(authpage, PageRequestStatus.AUTH)) {
1020: throw new PustefixCoreException(
1021: "*** Authorisation page [" + authpage
1022: + "] is not accessible! ***");
1023: }
1024: if (forceauth) {
1025: LOG.debug("* [" + currentpagerequest
1026: + "] forceauth is TRUE ***");
1027: }
1028: PageRequest saved = currentpagerequest;
1029: if (checkNeedsData(authpage, PageRequestStatus.AUTH)
1030: || forceauth) {
1031: if (!needDocument) {
1032: // Return an empty SPDocument that is just used to
1033: // signal the context is not authenticated yet.
1034: return new SPDocument();
1035: }
1036: LOG.debug("===> [" + authpage
1037: + "]: Need authorisation data");
1038: currentpagerequest = authpage;
1039: resdoc = documentFromCurrentStep();
1040: currentpagerequest = saved;
1041: if (!prohibitcontinue) {
1042: LOG.debug("===> [" + authpage
1043: + "]: Authorisation granted");
1044: } else {
1045: LOG.debug("===> [" + authpage
1046: + "]: Authorisation failed");
1047: }
1048: } else {
1049: LOG
1050: .debug("===> [" + authpage
1051: + "]: Already authorised");
1052: }
1053: if (resdoc != null && prohibitcontinue) {
1054: // getting a document here means we need to show the authpage
1055: if (resdoc.getSPDocument() == null) {
1056: throw new PustefixCoreException("*** FATAL: "
1057: + authpage
1058: + " returns a 'null' SPDocument! ***");
1059: }
1060: resdoc.getSPDocument().getDocument()
1061: .getDocumentElement()
1062: .setAttribute("authoriginalpage",
1063: saved.getRootName());
1064: resdoc.getSPDocument().setPagename(authpage.getName());
1065: return resdoc.getSPDocument();
1066: }
1067: }
1068: return null;
1069: }
1070:
1071: private ResultDocument documentFromCurrentStep()
1072: throws PustefixApplicationException, PustefixCoreException {
1073:
1074: ResultDocument document = null;
1075: document = checkPageAuthorization();
1076: if (document != null)
1077: return document;
1078:
1079: State state = pagemap.getState(currentpagerequest);
1080: if (state == null) {
1081: throw new PustefixRuntimeException(
1082: "* Can't get a state in documentFromCurrentStep() for page "
1083: + currentpagerequest.getName());
1084: }
1085:
1086: LOG.debug("** [" + currentpagerequest + "]: associated state: "
1087: + state.getClass().getName());
1088: LOG.debug("=> [" + currentpagerequest
1089: + "]: Calling getDocument()");
1090:
1091: try {
1092: ResultDocument resdoc = state.getDocument(parentcontext,
1093: currentpservreq);
1094: //TODO: find better place and only insert if authorization failed
1095: if (resdoc != null && roleAuth) {
1096: addAuthenticationData(resdoc);
1097: }
1098: return resdoc;
1099: } catch (Exception e) {
1100: throw new PustefixApplicationException(
1101: "Exception while running getDocument() for page "
1102: + currentpagerequest.getName(), e);
1103: }
1104: }
1105:
1106: public void checkAuthorization(Authentication authentication) {
1107: if (parentcontext.getContextConfig().hasRoles()) {
1108: String pageName = currentpagerequest.getRootName();
1109: if (authentication == null) {
1110: if (LOG.isDebugEnabled())
1111: LOG.debug("Not yet authenticated.");
1112: throw new NotAuthenticatedException(
1113: "Not yet authenticated.", "pageaccess",
1114: pageName);
1115: }
1116: PageRequestConfig pageConfig = this
1117: .getConfigForCurrentPageRequest();
1118: AuthConstraint authConstraint = pageConfig
1119: .getAuthConstraint();
1120: if (authConstraint == null)
1121: authConstraint = parentcontext.getContextConfig()
1122: .getDefaultAuthConstraint();
1123: if (authConstraint != null) {
1124: if (!authConstraint.isAuthorized(authentication)) {
1125: if (LOG.isDebugEnabled())
1126: LOG.debug("Not authorized to access page '"
1127: + pageName + "'");
1128: throw new AuthConstraintViolation(
1129: "Not authorized to access page '"
1130: + pageName + "'.", "pageaccess",
1131: pageName, authConstraint);
1132: }
1133: }
1134: }
1135: }
1136:
1137: private ResultDocument checkPageAuthorization()
1138: throws PustefixApplicationException, PustefixCoreException {
1139: if (!parentcontext.getContextConfig().hasRoles())
1140: return null;
1141: try {
1142: checkAuthorization(parentcontext.getAuthentication());
1143: } catch (AuthorizationException authEx) {
1144: String targetPage = authEx.getTarget();
1145: if (roleAuthDeps != null
1146: && roleAuthDeps.contains(targetPage)) {
1147: StringBuilder sb = new StringBuilder();
1148: for (String s : roleAuthDeps)
1149: sb.append(s + " -> ");
1150: sb.append(targetPage);
1151: throw new PustefixCoreException(
1152: "Authorization page has circular dependencies: "
1153: + sb.toString());
1154: }
1155: if (roleAuthDeps == null)
1156: roleAuthDeps = new LinkedHashSet<String>();
1157: roleAuthDeps.add(authEx.getTarget());
1158: PageRequest localAuthPage = null;
1159: PageRequestConfig pageConfig = this
1160: .getConfigForCurrentPageRequest();
1161: AuthConstraint authConstraint = pageConfig
1162: .getAuthConstraint();
1163: if (authConstraint == null)
1164: authConstraint = parentcontext.getContextConfig()
1165: .getDefaultAuthConstraint();
1166: if (authConstraint != null) {
1167: String authPageName = authConstraint.getAuthPage();
1168: if (authPageName != null)
1169: localAuthPage = createPageRequest(authPageName);
1170: }
1171: if (localAuthPage == null)
1172: throw authEx;
1173: if (localAuthPage.equals(authpage))
1174: throw new PustefixCoreException(
1175: "Authconstraint authpage isn't "
1176: + "allowed to be equal to context authpage: "
1177: + authpage);
1178: PageRequest saved = currentpagerequest;
1179: if (LOG.isDebugEnabled())
1180: LOG.debug("===> [" + localAuthPage
1181: + "]: Checking authorisation");
1182: if (!checkIsAccessible(localAuthPage,
1183: PageRequestStatus.AUTH)) {
1184: throw new PustefixCoreException(
1185: "*** Authorisation page [" + localAuthPage
1186: + "] is not accessible! ***");
1187: }
1188: if (LOG.isDebugEnabled())
1189: LOG.debug("===> [" + localAuthPage
1190: + "]: Need authorisation data");
1191: currentpagerequest = localAuthPage;
1192: ResultDocument resdoc = documentFromCurrentStep();
1193: currentpagerequest = saved;
1194: prohibitcontinue = true;
1195: if (resdoc != null && prohibitcontinue) {
1196: if (resdoc.getSPDocument() == null) {
1197: throw new PustefixCoreException("*** FATAL: "
1198: + localAuthPage
1199: + " returns a 'null' SPDocument! ***");
1200: }
1201: resdoc.getSPDocument().getDocument()
1202: .getDocumentElement()
1203: .setAttribute("authoriginalpage",
1204: saved.getRootName());
1205: resdoc.getSPDocument().setPagename(
1206: localAuthPage.getName());
1207: Element authElem = addAuthenticationData(resdoc);
1208: if (authElem != null) {
1209: authElem.setAttribute("targetpage", authEx
1210: .getTarget());
1211: Element misElem = resdoc.createSubNode(authElem,
1212: "authorizationfailure");
1213: if (authEx.getType() != null)
1214: misElem.setAttribute("type", authEx.getType());
1215: if (authEx.getAuthorization() != null)
1216: misElem.setAttribute("authorization", authEx
1217: .getAuthorization());
1218: if (authEx.getTarget() != null)
1219: misElem.setAttribute("target", authEx
1220: .getTarget());
1221: if (authEx instanceof AuthConstraintViolation) {
1222: AuthConstraintViolation authVio = (AuthConstraintViolation) authEx;
1223: AuthConstraint authCon = authVio
1224: .getViolatedConstraint();
1225: if (authCon != null) {
1226: Element constraintElem = authCon
1227: .toXML(misElem.getOwnerDocument());
1228: misElem.appendChild(constraintElem);
1229: }
1230: }
1231: }
1232: return resdoc;
1233: }
1234: }
1235: return null;
1236: }
1237:
1238: private Element addAuthenticationData(ResultDocument resDoc) {
1239: if (parentcontext.getAuthentication() != null) {
1240: Element root = resDoc.getRootElement();
1241: Element authElem = resDoc.createNode("authentication");
1242: if (root.getFirstChild() != null)
1243: root.insertBefore(authElem, root.getFirstChild());
1244: else
1245: root.appendChild(authElem);
1246: if (roleAuthTarget != null)
1247: authElem.setAttribute("targetpage", roleAuthTarget);
1248: Role[] roles = parentcontext.getAuthentication().getRoles();
1249: Element rolesElem = resDoc.createSubNode(authElem, "roles");
1250: if (roles != null)
1251: for (Role role : roles) {
1252: Element roleElem = resDoc.createSubNode(rolesElem,
1253: "role");
1254: roleElem.setAttribute("name", role.getName());
1255: }
1256: return authElem;
1257: }
1258: return null;
1259: }
1260:
1261: private void trySettingPageRequestAndFlow() {
1262: PageRequest tmp = null;
1263: String tmppagename = currentpservreq.getPageName();
1264: if (tmppagename != null) {
1265: tmp = createPageRequest(tmppagename);
1266: }
1267: RequestParam reqParam = currentpservreq
1268: .getRequestParam(PARAM_ROLEAUTH);
1269: roleAuth = (reqParam != null && reqParam.isTrue());
1270: if (roleAuth) {
1271: roleAuthTarget = null;
1272: reqParam = currentpservreq
1273: .getRequestParam(PARAM_ROLEAUTHTARGET);
1274: if (reqParam != null)
1275: roleAuthTarget = reqParam.getValue();
1276: else if (tmp != null) {
1277: roleAuthTarget = tmp.getName();
1278: tmp = null;
1279: } else
1280: throw new RuntimeException("No target page specified!");
1281: PageRequestConfig targetPageConf = servercontext
1282: .getContextConfig().getPageRequestConfig(
1283: roleAuthTarget);
1284: if (targetPageConf != null) {
1285: AuthConstraint authConst = targetPageConf
1286: .getAuthConstraint();
1287: if (authConst == null)
1288: authConst = getParentContext().getContextConfig()
1289: .getDefaultAuthConstraint();
1290: if (authConst != null) {
1291: String authPageName = authConst.getAuthPage();
1292: if (authPageName != null) {
1293: if (tmp != null
1294: && !authPageName.equals(tmp.getName()))
1295: throw new RuntimeException(
1296: "Requested page and required authpage "
1297: + "don't match: "
1298: + authPageName + " -> "
1299: + tmp.getName());
1300: if (tmp == null)
1301: tmp = createPageRequest(authPageName);
1302: setJumpToPage(roleAuthTarget);
1303: } else
1304: throw new RuntimeException(
1305: "No authpage defined for authconstraint "
1306: + "of page: " + roleAuthTarget);
1307: } else
1308: throw new RuntimeException(
1309: "No authconstraint defined for page: "
1310: + roleAuthTarget);
1311: } else
1312: throw new RuntimeException(
1313: "Target page not configured: " + roleAuthTarget);
1314: }
1315: if (tmp != null && (authpage == null || !tmp.equals(authpage))) {
1316: currentpagerequest = tmp;
1317: currentpagerequest.setStatus(PageRequestStatus.DIRECT);
1318:
1319: PageFlow flow = null;
1320: RequestParam flowname = currentpservreq
1321: .getRequestParam(PARAM_FLOW);
1322: if (flowname != null && !flowname.getValue().equals("")) {
1323: LOG.debug("===> User requesting to switch to flow '"
1324: + flowname.getValue() + "'");
1325: flow = pageflowmanager.getPageFlowByName(flowname
1326: .getValue(), getVariant());
1327: if (flow != null) {
1328: LOG.debug("===> Flow '" + flowname.getValue()
1329: + "' exists...");
1330: pageflow_requested_by_user = true;
1331: if (flow.containsPage(currentpagerequest
1332: .getRootName())) {
1333: LOG.debug("===> and it contains page '"
1334: + currentpagerequest.getName() + "'");
1335: } else {
1336: LOG
1337: .debug("===> CAUTION: it doesn't contain page '"
1338: + currentpagerequest.getName()
1339: + "'! Make sure this is what you want...");
1340: }
1341: } else {
1342: LOG
1343: .error("\n\n!!!! CAUTION !!!! Flow '"
1344: + flowname
1345: + "' is not defined! I'll continue as if no flow was given\n\n");
1346: flow = pageflowmanager.pageFlowToPageRequest(
1347: currentpageflow, currentpagerequest,
1348: getVariant());
1349: pageflow_requested_by_user = false;
1350: }
1351: } else {
1352: flow = pageflowmanager.pageFlowToPageRequest(
1353: currentpageflow, currentpagerequest,
1354: getVariant());
1355: pageflow_requested_by_user = false;
1356: }
1357: currentpageflow = flow;
1358: LOG.debug("* Setting currentpagerequest to ["
1359: + currentpagerequest.getName() + "]");
1360: LOG.debug("* Setting currentpageflow to ["
1361: + currentpageflow.getName() + "]");
1362: } else {
1363: if (currentpagerequest != null) {
1364: currentpagerequest = createPageRequest(currentpagerequest
1365: .getRootName());
1366: currentpagerequest.setStatus(PageRequestStatus.DIRECT);
1367: LOG
1368: .debug("* Reusing page [" + currentpagerequest
1369: + "]");
1370: LOG.debug("* Reusing flow ["
1371: + currentpageflow.getName() + "]");
1372: } else {
1373: throw new RuntimeException(
1374: "Don't have a current page to use as output target");
1375: }
1376: }
1377: RequestParam jump = currentpservreq
1378: .getRequestParam(PARAM_JUMPPAGE);
1379: if (jump != null && !jump.getValue().equals("")) {
1380: setJumpToPage(jump.getValue());
1381: // We only search for a special jumpflow when also a jumppage is set
1382: RequestParam jumpflow = currentpservreq
1383: .getRequestParam(PARAM_JUMPPAGEFLOW);
1384: if (jumpflow != null && !jumpflow.getValue().equals("")) {
1385: setJumpToPageFlow(jumpflow.getValue());
1386: }
1387: }
1388: }
1389:
1390: public void forceStopAtNextStep(boolean forcestop) {
1391: this .stopnextforcurrentrequest = forcestop;
1392: }
1393:
1394: private boolean checkNeedsData(PageRequest page,
1395: PageRequestStatus status)
1396: throws PustefixApplicationException {
1397: PageRequest saved = currentpagerequest;
1398: currentpagerequest = page;
1399: State state = pagemap.getState(page);
1400: if (state == null) {
1401: throw new PustefixRuntimeException(
1402: "*** Can't get a state to check needsData() for page "
1403: + page.getName() + " ***");
1404: }
1405: page.setStatus(status);
1406:
1407: PerfEvent pe = new PerfEvent(PerfEventType.PAGE_NEEDSDATA, page
1408: .getName());
1409: pe.start();
1410: boolean retval;
1411: try {
1412: retval = state.needsData(parentcontext, currentpservreq);
1413: } catch (Exception e) {
1414: throw new PustefixApplicationException(
1415: "Exception while running needsData() for page "
1416: + page.getName(), e);
1417: }
1418: pe.save();
1419:
1420: currentpagerequest = saved;
1421: return retval;
1422: }
1423:
1424: private boolean checkIsAccessible(PageRequest page,
1425: PageRequestStatus status)
1426: throws PustefixApplicationException {
1427: PageRequest saved = currentpagerequest;
1428: try {
1429: currentpagerequest = page;
1430: State state = pagemap.getState(page);
1431: if (state == null) {
1432: throw new PustefixRuntimeException(
1433: "Can't get a state to check isAccessible() for page "
1434: + page.getName());
1435: }
1436: page.setStatus(status);
1437:
1438: PerfEvent pe = new PerfEvent(
1439: PerfEventType.PAGE_ISACCESSIBLE, page.getName());
1440: pe.start();
1441: boolean retval;
1442: try {
1443: retval = state.isAccessible(parentcontext,
1444: currentpservreq);
1445: } catch (Exception e) {
1446: throw new PustefixApplicationException(
1447: "Got exception from state for page "
1448: + page.getName()
1449: + " while calling isAccessible()", e);
1450: }
1451: pe.save();
1452:
1453: return retval;
1454: } finally {
1455: currentpagerequest = saved;
1456: }
1457: }
1458:
1459: private void checkForAuthenticationMode() {
1460: String authpagename = servercontext.getContextConfig()
1461: .getAuthPage();
1462: if (authpagename != null) {
1463: authpage = createPageRequest(authpagename);
1464: } else {
1465: authpage = null;
1466: }
1467: }
1468:
1469: public boolean isPageAccessible(String pagename) throws Exception {
1470: PageRequest page = createPageRequest(pagename);
1471: Variant currentvariant = getVariant();
1472: setVariantForThisRequestOnly(parentcontext.getSessionVariant());
1473: boolean retval = checkIsAccessible(page,
1474: PageRequestStatus.NAVIGATION);
1475: setVariantForThisRequestOnly(currentvariant);
1476: return retval;
1477: }
1478:
1479: public Cookie[] getRequestCookies() {
1480: if (currentpservreq == null) {
1481: throw new IllegalStateException(
1482: "Cookies are only available witihin request handling");
1483: }
1484: return currentpservreq.getCookies();
1485: }
1486:
1487: public void addCookie(Cookie cookie) {
1488: if (currentpservreq == null) {
1489: throw new IllegalStateException(
1490: "Cookies are only available witihin request handling");
1491: }
1492: cookielist.add(cookie);
1493: }
1494:
1495: public Throwable getLastException() {
1496: if (currentpservreq == null) {
1497: throw new IllegalStateException(
1498: "This method is only available during request processing");
1499: }
1500: return currentpservreq.getLastException();
1501: }
1502:
1503: public String toString() {
1504: StringBuffer contextbuf = new StringBuffer("\n");
1505:
1506: contextbuf.append(" pageflow: " + currentpageflow
1507: + "\n");
1508: contextbuf.append(" PageRequest: " + currentpagerequest
1509: + "\n");
1510: if (currentpagerequest != null) {
1511: contextbuf.append(" -> State: "
1512: + pagemap.getState(currentpagerequest) + "\n");
1513: contextbuf.append(" -> Status: "
1514: + currentpagerequest.getStatus() + "\n");
1515: }
1516:
1517: return contextbuf.toString();
1518: }
1519:
1520: public Object clone() throws CloneNotSupportedException {
1521: RequestContextImpl copy = (RequestContextImpl) super .clone();
1522: if (currentpagerequest != null) {
1523: copy.currentpagerequest = new PageRequest(
1524: currentpagerequest.getName());
1525: copy.currentpagerequest.setStatus(currentpagerequest
1526: .getStatus());
1527: }
1528: if (authpage != null) {
1529: copy.authpage = new PageRequest(authpage.getName());
1530: copy.authpage.setStatus(authpage.getStatus());
1531: }
1532: copy.cookielist = new ArrayList<Cookie>(cookielist);
1533: copy.messages = new ArrayList<StatusCodeInfo>(messages);
1534: return copy;
1535: }
1536:
1537: public void setPfixServletRequest(PfixServletRequest pservreq) {
1538: // Usually the PfixServletRequest is supplied when
1539: // calling handleSubmittedData(), however there might
1540: // be situations when though there is no request to
1541: // handle a PfixServletRequest is needed.
1542: this .currentpservreq = pservreq;
1543: }
1544:
1545: public ContextImpl getParentContext() {
1546: return this.parentcontext;
1547: }
1548: }
|