Package de.innovationgate.wgpublisher.webtml

Source Code of de.innovationgate.wgpublisher.webtml.Root

/*******************************************************************************
* Copyright 2009, 2010 Innovation Gate GmbH. All Rights Reserved.
*
* This file is part of the OpenWGA server platform.
*
* OpenWGA is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* In addition, a special exception is granted by the copyright holders
* of OpenWGA called "OpenWGA plugin exception". You should have received
* a copy of this exception along with OpenWGA in file COPYING.
* If not, see <http://www.openwga.com/gpl-plugin-exception>.
*
* OpenWGA is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenWGA in file COPYING.
* If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package de.innovationgate.wgpublisher.webtml;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.commons.fileupload.DiskFileUpload;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUpload;
import org.apache.commons.fileupload.FileUploadException;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import de.innovationgate.utils.Base64;
import de.innovationgate.utils.WGUtils;
import de.innovationgate.utils.XStreamUtils;
import de.innovationgate.utils.Zipper;
import de.innovationgate.webgate.api.WGAPIException;
import de.innovationgate.webgate.api.WGContent;
import de.innovationgate.wgpublisher.WGACore;
import de.innovationgate.wgpublisher.WGPDispatcher;
import de.innovationgate.wgpublisher.WGPRequestPath;
import de.innovationgate.wgpublisher.expressions.ExpressionResult;
import de.innovationgate.wgpublisher.webtml.utils.AjaxInfo;
import de.innovationgate.wgpublisher.webtml.utils.FormInfo;
import de.innovationgate.wgpublisher.webtml.utils.RootTagReceptor;
import de.innovationgate.wgpublisher.webtml.utils.TMLAction;
import de.innovationgate.wgpublisher.webtml.utils.TMLActionException;
import de.innovationgate.wgpublisher.webtml.utils.TMLActionLink;
import de.innovationgate.wgpublisher.webtml.utils.TMLContext;
import de.innovationgate.wgpublisher.webtml.utils.TMLException;
import de.innovationgate.wgpublisher.webtml.utils.TMLForm;
import de.innovationgate.wgpublisher.webtml.utils.TMLInvalidActionLinkException;
import de.innovationgate.wgpublisher.webtml.utils.TMLOption;
import de.innovationgate.wgpublisher.webtml.utils.TMLPortlet;
import de.innovationgate.wgpublisher.webtml.utils.TMLOptionPreserver;
import de.innovationgate.wgpublisher.webtml.utils.URLBuilder;
import de.innovationgate.wgpublisher.webtml.utils.VarParamsMap;

public class Root extends Base {
 
  public static final String URLPARAM_ACTION = "$action";

    public static final String REQUEST_ATTRIB_IS_AJAX_SUBFORM = "de.innovationgate.request.attrib.isAjaxSubForm";
   
    // Collects all options that should not be recovered in AJAX requests
    private static final Set UNRECOVERABLE_OPTIONS = new HashSet();

    public static final String URLPARAM_VARS = "$vars";
    static {
        UNRECOVERABLE_OPTIONS.add(Base.OPTION_PORTLET_EVENT_STARTINDEX);
        UNRECOVERABLE_OPTIONS.add(Base.OPTION_DESIGNDB);
        UNRECOVERABLE_OPTIONS.add(Base.OPTION_TMLMODULE_NAME);
        UNRECOVERABLE_OPTIONS.add(Base.OPTION_TMLMODULE_MEDIAKEY);
    }
   
 
  /**
   * @see Base#tmlStartTag()
   */
 
  private String resource = null;
  private String ref = null;
  private String modulename = null;
    private String modulemediakey = null;
 

   
    public static class Status extends BaseTagStatus {
        private Boolean _tagPoolingEnabled = null;
        private boolean _ajax;
        private AjaxInfo _ajaxInfo;
        private boolean _isAjaxNoRefreshCall = false;
        private RootTagReceptor receptorTag = null;
        public String resource;
        private String _upperTml;
    }
   
    @Override
    public BaseTagStatus createTagStatus() {
        return new Status();
    }
 
  public void tmlStartTag() throws TMLException, WGAPIException {

    Status status = (Status) getStatus();
    status.resource = getResource();
     
    status.keepResult = true;
   
    // Set module info

        status.setOption(OPTION_TMLMODULE_NAME, getModulename(), null);
        status.setOption(OPTION_TMLMODULE_MEDIAKEY, getModulemediakey(), null);
    status.receptorTag = (RootTagReceptor) this.getParentTag();
   
   
    HttpServletRequest request = (HttpServletRequest) this.pageContext.getRequest();
           
        storeCurrentTMLAttributes(request);               
       
    // Root tag was included by another tag
    if (status.receptorTag != null) {
      processIncludedRoot();           
    }
   
    // Root tag is absolute root tag of this request - do basic functionalities
    else {           
            processAbsoluteRoot(request);
    }
       
  }

    private void processIncludedRoot() throws TMLException {
       
        Status status = (Status) getStatus();
       
        this.setTMLContext(status.receptorTag.getChildTagContext());
        this.setChildTagContext(status.receptorTag.getChildTagContext());
        status.receptorTag.setRootTagStatus((Status) getStatus());
       
        // Test for inclusion depth. Evaluation will stop, if level 32 reached for stability reasons (stack overflow)
        Integer includeLevel = (Integer) getTMLContext().option(WGACore.ATTRIB_INCLUDELEVEL);
        if (includeLevel.intValue() >= 32) {
          throw new TMLException("Maximum tml:include level of 32 reached. No further inclusions allowed.", true);
        }
        else {
          status.setOption(WGACore.ATTRIB_INCLUDELEVEL, new Integer(includeLevel.intValue() + 1), null);
        }
       
        // Filter out local options
        if (status.receptorTag instanceof Include.Status) {
            Include.Status includeTag = (Include.Status) status.receptorTag;
            filterOptions(includeTag.getOptionsToFilter());
        }
    }

    private void processAbsoluteRoot(HttpServletRequest request) throws WGAPIException {
       
        Status status = (Status) getStatus();
       
        // check if appserver has enabled tag pooling
        // if not the property _tagPoolingEnabled must be everytime null
        if (status._tagPoolingEnabled == null) {
            status._tagPoolingEnabled = new Boolean(true);
        } else {
           if (status._tagPoolingEnabled.booleanValue()) {
               // appserver has enabled tagpooling
               String message = "Your appserver has enabled JSP-Tag-Pooling. Good so!.";
               this.addWarning(message);
               log.warn(message);
           }
        }           
       
        // check for ajaxCall
        status._ajax = false;
        status._ajaxInfo = (AjaxInfo) request.getAttribute(WGACore.ATTRIB_AJAXINFO);
        if ( status._ajaxInfo != null) {
            status._ajax = true;
            // restore ajax environment
            this.restoreEnvironmentFromAjaxCall(status._ajaxInfo, request);                       
        }           
       
        // set currentMediakey to MainMediaKey
        status.setOption(OPTION_CURRENT_MEDIAKEY, getStatus().getMainMediaKey(), null);
       
        // Set basic request attributes
        status.parentTag = status;
        setBasicRequestAttributes(request);
       
        // Eventually enable TML Debug
        HttpSession session = this.pageContext.getSession();
        Boolean tmlDebug = (Boolean) session.getAttribute(WGACore.ATTRIB_TMLDEBUG);
        if (tmlDebug != null && tmlDebug.booleanValue() == true) {
          enableDebug(session);
        }
       
        // Determine, which (if any) document can be edited in this request
        if (status.isBrowserInterface()) {
          WGContent content = this.getTMLContext().content();       
                 
          List userNamesList = new ArrayList();
          userNamesList.add(content.getAuthor());
          
          if ( content.getStatus().equals(WGContent.STATUS_DRAFT)
            && (!content.hasCompleteRelationships() || content.getStructEntry().mayEditEntryAndContent() == null)
            && content.getLanguage().mayCreateContent()
            && content.getDatabase().isMemberOfUserList( userNamesList )
            && !content.hasItem("remote_info")
            ) {     
           
            pageContext.getRequest().setAttribute(WGACore.ATTRIB_EDITDOCUMENT, content.getContentKey().toString());
          }
        }

       
        // process multipartformdata
        List data = null;
        // first try to retrieve formdata from ajax call
        String ajaxFormdataSessionKey = request.getParameter("$ajaxformkey");
        if (ajaxFormdataSessionKey != null && !ajaxFormdataSessionKey.trim().equals("")) {
            data = (List) request.getSession().getAttribute(ajaxFormdataSessionKey);               
            if (data == null) {
                this.getTMLContext().addwarning("Could not restore ajaxformdata. FormKey found but nothing in session.", true);                   
            } else {
                // remove session attribute
                request.getSession().removeAttribute(ajaxFormdataSessionKey);
            }
        } else {
            // try to retrieve from current post-request
            data = retrieveMultipartFormData(request);
        }           
        // create TMLForm if data is available
        TMLForm form = null;
        if (data != null) {
          // F00004936
          // check if this request contains a tmlform ($forminfo is present)
          // otherwise this is an standard multipart request and multipartData will be transported
          // as raw data within the tmlvar "multipartData"
          boolean isTMLForm = false;
          Iterator multipartItems = data.iterator();
          while (multipartItems.hasNext()) {
            FileItem fi = (FileItem) multipartItems.next();
            if (fi.getFieldName().equals("$forminfo")) {
              isTMLForm = true;
            }
          }
         
          if (isTMLForm) {
                //create a tml form object
                form = processTMLForm(request, data)
          } else {
            // put multipartdata in request for custom processing
            // used by CM for multi file uploads
            getTMLContext().setvar("multipartData", data);
          }
        }
       
       
       
        // Process WebTML var parameters
        String varParam = request.getParameter(URLPARAM_VARS);
        if (varParam != null) {
            try {
                processVarParams(varParam);
            }
            catch (Exception e) {
                log.error("Exception processing var params", e);
                addWarning("Unable to process var params: " + e.getMessage());         
            }      
        }

        // eventually execute action
        boolean actioncalled = false;
        try {
          actioncalled = processAction(request, form, status._ajax);
        }
        catch (Exception e) {
          log.error("Exception processing WebTML action", e);
          addWarning("Unable to process WebTML action: " + e.getMessage());         
        }
                   
        // if an action was called
        if (actioncalled) {
            // if keepOnValidate is true and form was validated once and form was not validated
            // in this request
            if (form != null) {
                FormInfo formInfo = form.getforminfo();
                if (formInfo.isValidated() && formInfo.keepOnValidate() && !form.wasValidatedInThisRequest()) {
                    form.validate();
                }
            }
        }
       
        if (status._ajax) {
            // if session is new throw corresponding system event
            if (getTMLContext().getrequest().getSession().isNew()) {
                fireSessionIsNewPortletEvent();
            } else {
                // check if session was new - this might happen on ajax calls with form data
                // this session attribute is set in Dispatcher on ajax form call
                String ajaxSessionWasNewFlagSessionKey = request.getParameter("$ajaxformkey") + ".event.SessionWasNew";
                Boolean sessionWasNew = (Boolean) request.getSession().getAttribute(ajaxSessionWasNewFlagSessionKey);
                if (sessionWasNew != null && sessionWasNew.booleanValue()) {
                    // remove attribute
                    request.getSession().removeAttribute(ajaxSessionWasNewFlagSessionKey);
                   
                    // fire session is new event
                    fireSessionIsNewPortletEvent();
                }               
            }
           
            if (getTMLContext().getportlet() != null) {
                String portletKey = status._ajaxInfo.getId();
                // register portlet on client side - this must be done here to ensure registration is also done after an ajaxcall
                String javaScriptPRegistration = null;
                if (status._isAjaxNoRefreshCall) {
                  // this is an no refresh ajax call - portlet registration is not necessary
                    //javaScriptPRegistration = getTMLContext().createJavaScriptPortletRegistration(portletKey, true);
                } else {
                    javaScriptPRegistration = getTMLContext().createJavaScriptPortletRegistration(portletKey, false);
                }
                if (javaScriptPRegistration != null) {
                    this.setPrefix(this.getPrefix() + javaScriptPRegistration);
                }
               
                // Prepare for serverside portlet event processing inside the currently rendered portlet
                getTMLContext().getportlet().prepareEventProcessing(this);
            }
        }
    }

    private void processVarParams(String varParam) throws WGAPIException, UnsupportedEncodingException, IOException {
       
        VarParamsMap varParams = URLBuilder.extractVarParameters(varParam, getTMLContext().getwgacore().getDesEncrypter());
       
        // Wrong session? Discard var params
        if (!varParams.isValidSession(getPageContext().getSession())) {
            getTMLContext().getlog().warn("Var params for wrong session used by client " + getPageContext().getRequest().getRemoteAddr() + ". Not used.");
            return;
        }
       
        getTMLContext().getrequest().setAttribute(WGACore.ATTRIB_VAR_PARAMETERS, varParams);       
        for (Map.Entry<String,Object> param : varParams.entrySet()) {
            getTMLContext().setvar(param.getKey(), param.getValue());
        }
        
    }

    private void fireSessionIsNewPortletEvent() throws WGAPIException {       
        TMLPortlet portlet = getTMLContext().getportlet();
        if (portlet != null) {
            portlet.fireevent(de.innovationgate.wgpublisher.webtml.utils.PortletEvent.SESSION_IS_NEW_EVENT);
        } else {
            String sessionIsNewEvent = de.innovationgate.wgpublisher.webtml.utils.PortletEvent.SESSION_IS_NEW_EVENT.toJavaScriptObject();
            String encodedEvent = Base64.encodeWeb(sessionIsNewEvent.getBytes());
            try {
                getTMLContext().redirectto(getTMLContext().getrequest().getContextPath() + "/fireSystemEvent.jsp?event="  + encodedEvent);
            }
            catch (IOException e) {
                getTMLContext().addwarning("Unable to fire portlet event 'session is new'. Redirect to 'fireSystemEvent.jsp' failed bc. of exception '" + e.getMessage() + "'");          
            }
        }
           
    }
   
    private void enableDebug(HttpSession session) {
    Document doc = DocumentHelper.createDocument();
    Element rootElement = doc.addElement("tmldebugdocument");
    rootElement.addAttribute("url", WGUtils.reduce(getStatus().getRequestURL(), 100));
    rootElement.addAttribute("started", DEBUG_TIMESTAMP_FORMAT.format(new Date()));
    rootElement.addAttribute("traceresults", String.valueOf(session.getAttribute(WGACore.ATTRIB_TMLDEBUG_TRACE_RESULTS)));
        rootElement.addAttribute("traceoptions", String.valueOf(session.getAttribute(WGACore.ATTRIB_TMLDEBUG_TRACE_OPTIONS)));
    List debugDocuments = WGACore.getDebugDocumentsList(session);
    debugDocuments.add(doc);
    createDebugNode(rootElement);
    try {
            debugNode.addAttribute("context", getTMLContext().getpath());
        }
        catch (WGAPIException e) {
            debugNode.addAttribute("context", "Unable to retrieve contextpath bc. of exception: " + e.getClass().getName() + " message: " + e.getMessage());
        }
  }



  private void setBasicRequestAttributes(HttpServletRequest request) {

      Status status = (Status) getStatus();
     
      request.setAttribute(WGACore.ATTRIB_ROOT_TAG, status);
    request.setAttribute(WGACore.ATTRIB_REQUESTTIME, new Long(System.currentTimeMillis()));
    status.setOption(WGACore.ATTRIB_INCLUDELEVEL, new Integer(0), null);
    status.setOption(WGACore.ATTRIB_ITEM_MAPPINGS, new java.util.HashMap(), null);
    status.setOption(WGACore.ATTRIB_META_MAPPINGS, new java.util.HashMap(), null);
   
    if (status._ajaxInfo == null) {
      // if this is an static tml request we use a dummy designdbkey
      String requestType = (String) request.getAttribute(WGACore.ATTRIB_REQUESTTYPE);
        if(requestType != null && requestType.equals(WGPDispatcher.REQUESTTYPE_STATICTML)) {
          status.setOption(OPTION_DESIGNDB, WGACore.STATICTML_DESIGNDBKEY, null);
        }
        else {
            status.setOption(OPTION_DESIGNDB, getTMLContext().db().getDbReference(), null);
        }
    }
       
        // Set DefaultURLBuilder if no other is already set
        getTMLContext().getwgacore().retrieveURLBuilder(request, getTMLContext().db());
  }



    private List retrieveMultipartFormData(HttpServletRequest request) {
        if (FileUpload.isMultipartContent(request) && request.getContentLength() != -1) {
            DiskFileUpload dfu = new DiskFileUpload();
            //F000037B2
            if (getCore().getCharacterEncoding() != null) {
                dfu.setHeaderEncoding(getCore().getCharacterEncoding());
            }
            try {
                List fileItems = dfu.parseRequest(request);
                return fileItems;
            } catch (FileUploadException e) {
                getCore().getLog().error("Error parsing multipart form", e);
                return null;
            }
        } else {
            return null;
        }
    }
   
    private TMLForm processTMLForm(HttpServletRequest request, List multipartData) {
       
        Status status = (Status) getStatus();
       
        TMLForm form = null;
        try {
            form = new TMLForm(multipartData, this.getTMLContext(), this.getCore().getLog(), request);
        } catch (TMLException e) {
            this.getTMLContext().addwarning("Error creating TMLForm object bc. of exception: " + e.getClass().getName() + " message: " + e.getMessage(), true);
            return null;
        } catch (WGAPIException e) {
            this.getTMLContext().addwarning("Error creating TMLForm object bc. of exception: " + e.getClass().getName() + " message: " + e.getMessage(), true);
            return null;
        } catch (UnsupportedEncodingException e) {
            this.getTMLContext().addwarning("Error creating TMLForm object bc. of exception: " + e.getClass().getName() + " message: " + e.getMessage() + " - ensure that you have configured a valid 'characterEncoding'", true);
            return null;
        }
       
        // Eventually merge with persistent form
        TMLForm persistentForm = (TMLForm) getTMLContext().getPersistentForms().get(form.getformid());
        if (persistentForm != null) {
            persistentForm.importForm(form);
            form = persistentForm;             
        }
        else {
            getTMLContext().registerForm(form, false);         
        }
        request.setAttribute(WGACore.ATTRIB_LASTFORM, form);       

        if (form != null) {
            // reset validated in this request flag
            form.setWasValidatedInThisRequest(false);
        }
       
        // Look if the form is our "superform". If so we switch to AJAX subform mode.
        if (status._ajaxInfo != null && status._ajaxInfo.getSuperform() != null && status._ajaxInfo.getSuperform().equals(form.getformid())) {
            getPageContext().getRequest().setAttribute(Root.REQUEST_ATTRIB_IS_AJAX_SUBFORM, Boolean.TRUE);
        }
       
       
        return form;
    }


  private boolean processAction(HttpServletRequest request, TMLForm form, boolean ajax) {
     
      Status status = (Status) getStatus();
    boolean actioncalled = false;
    // Location of Actionkey depends. When form available, then is located in form, else is URL parameter
    String actionKey = null;
    if (form != null) {
      actionKey = form.getformaction();
    }
    else {
      actionKey = request.getParameter(URLPARAM_ACTION);
    }
       
    // Parse the action link and call the action
    TMLActionLink actionLink;
    if (actionKey != null && !actionKey.trim().equals("")) {
      //  actions
     
           
           
      try {
        actionLink = new TMLActionLink(URLDecoder.decode(actionKey, "UTF-8"),getCore());
               
                long starttime = System.currentTimeMillis();
        TMLAction action = callAction(actionLink, ajax);
                long endtime = System.currentTimeMillis();
               
                // We rebuild the session on the current context if the action was a master action
                // to be able to pick up modifications done there (F00004096)
                if (action != null && action.isMaster()) {
                    getTMLContext().db().reopenSession();
                }
               
                //F00004242
                if (actionLink.getMode() != null && actionLink.getMode().equals(TMLActionLink.MODE_AJAX_NO_PORTLET_REFRESH)) {
                    // this is an ajax action call do not render content result but portletEvents
                    status._isAjaxNoRefreshCall = true;
                    appendResult("");
                    setEvalBody(false);
                }
               
                actioncalled = true;                               
               
                if (debugNode != null) {
                    debugNode.addAttribute("actiontime", new Long(endtime - starttime).toString());
                }
      }
      catch (TMLInvalidActionLinkException e) {
          // Not logging these
      }
            catch (TMLActionException e) {
                addWarning("Error calling TML action: " + e.getMessage());
            }
            catch (IOException e) {
        addWarning("Error decoding action link: " + e.getMessage());
      }
            catch (WGAPIException e) {
                addWarning("Error calling TML action: " + e.getMessage());
            }
    }
   
    // Conditionally execute special action changeLanguage
        WGPRequestPath path = (WGPRequestPath) request.getAttribute(WGACore.ATTRIB_REQUESTPATH);
    if (path.getPreferredLanguageChange() != null) {
      actionLink = new TMLActionLink(request.getSession());
      actionLink.setDefaultAction(TMLAction.DEFAULTACTION_CHANGELANGUAGE);
           
            try {
                if (path.getPreferredLanguageChange().equals(WGPRequestPath.PREFERREDLANGUAGECHANGE_USECONTENT)) {
                    actionLink.setParam1((String) getTMLContext().meta("language"));
                }
                else {
                    actionLink.setParam1(path.getPreferredLanguageChange());
                }
               
          actionLink.setContextPath(getTMLContext().getpath());
                             
                TMLAction calledAction = callAction(actionLink, ajax);
                               
                // In case of a called master action we rebuild the session of the current db
                // To let the following WebTML request reflect eventually done changes in the action
                if (calledAction != null && calledAction.isMaster()) {
                    getTMLContext().db().reopenSession();
                }
               
            }
            catch (TMLActionException e) {
                addWarning("Error changing preferred language to '" + path.getPreferredLanguageChange() + "' bc of exception: " + e.getClass().getName() + " message: " + e.getMessage());
                log.error("Error changing preferred language to '" + path.getPreferredLanguageChange() + "'", e);
            }
            catch (WGAPIException e) {
                addWarning("Error changing preferred language to '" + path.getPreferredLanguageChange() + "' bc of exception: " + e.getClass().getName() + " message: " + e.getMessage());
                log.error("Error changing preferred language to '" + path.getPreferredLanguageChange() + "'", e);
            }
            actioncalled = true;
           

    }
      
        try {
      if (getTMLContext().getportlet() != null && getTMLContext().getportlet().getcontext() != null) {
        setChildTagContext(getTMLContext().getportlet().getcontext());
      }
    } catch (WGAPIException e) {
      addWarning("Error setting portlet context bc of exception: " + e.getClass().getName() + " message: " + e.getMessage());
            log.error("Error setting portlet context", e);
    }   
   
        return actioncalled;
       
  }



  /**
   * @throws WGAPIException
   * @see Base#tmlEndTag()
   */
  public void tmlEndTag() throws TMLException, WGAPIException {
     
      Status status = (Status) getStatus();
 
      // check for portlet events that were issued inside the AJAX call and render if present
        // this must be done here to ensure these events are executed as javascript by the ajaxcall-function
        if (status._ajax == true) {
            String javaScriptPEvents = null;
            if (status._isAjaxNoRefreshCall) {
                javaScriptPEvents = getTMLContext().createJavaScriptPortletEvents(status._ajaxInfo.getId(), true);
            } else {
                javaScriptPEvents = getTMLContext().createJavaScriptPortletEvents(status._ajaxInfo.getId(), false);
            }
            if (javaScriptPEvents != null) {
                this.setSuffix(this.getSuffix() + javaScriptPEvents);
            }
           
            if (getPageContext().getRequest().getAttribute(REQUEST_ATTRIB_IS_AJAX_SUBFORM) != null &&
                (Boolean)getPageContext().getRequest().getAttribute(REQUEST_ATTRIB_IS_AJAX_SUBFORM)) {
              String formId = status.getRelevantForm();
              if (formId != null) {
                TMLForm form = getTMLContext().tmlformbyid(formId);
                if (form != null) {
                  try {
              String serializedInfo = FormBase.serializeFormInfo(form.getforminfo(), getTMLContext());
                    StringBuffer javaScript = new StringBuffer();
                    if (!status._isAjaxNoRefreshCall) {
                        javaScript.append("<script type=\"text/javascript\">");
                    }
                javaScript.append("var form = document.forms['" + form.getformid() + "'];");
                javaScript.append("if( form ) {");
                javaScript.append("form.$forminfo.value = \"" + serializedInfo +"\";");
                javaScript.append("form.removeAttribute('target');");
                javaScript.append("form.removeAttribute('action');");
                javaScript.append("}");
                javaScript.append("else { alert('Oops, there is no form!'); };");
                if (!status._isAjaxNoRefreshCall) {
                    javaScript.append("</script>");
                }
              this.setSuffix(getSuffix() + javaScript.toString());
            } catch (UnsupportedEncodingException e) {
              throw new TMLException("Unable to serialize form data.", e, false);
            }
                }
              }
            }
           
            String redirectURL = (String) getPageContext().getRequest().getAttribute(WGACore.ATTRIB_REDIRECT);
            if (redirectURL != null) {
                StringBuffer javaScript = new StringBuffer();
                if (!status._isAjaxNoRefreshCall) {
                    javaScript.append("<script type=\"text/javascript\">");
                }
               
                javaScript.append("location.href=\"" + WGUtils.encodeJS(redirectURL) + "\";");
               
                if (!status._isAjaxNoRefreshCall) {
                    javaScript.append("</script>");
                }
                this.setSuffix(getSuffix() + javaScript.toString());
            }
        }
       
    if (debugNode != null) {
      debugNode.addAttribute("ended", (new Date()).toString());
            debugNode.addAttribute("backenddocs", String.valueOf(getMainContext().db().getSessionContext().getTotalFetchedCores()));
      Element rootElement = debugNode.getDocument().getRootElement();
            rootElement.addAttribute("ended", DEBUG_TIMESTAMP_FORMAT.format(new Date()));
            rootElement.addAttribute("tags", new Integer(getStatus().subtags).toString());
            rootElement.addAttribute("backenddocs", String.valueOf(getMainContext().db().getSessionContext().getTotalFetchedCores()));
           
    }

    if (status.receptorTag != null) {
      this.setResultOutput(false);
    }
    else {
      this.pageContext.getRequest().setAttribute(WGACore.ATTRIB_TAGIDS, null);
    }
   
    recoverCurrentTMLAttributes((HttpServletRequest) pageContext.getRequest());
       
    /* I think this is bogus now
        // If parent tag, set it to current TMLContext, bc. tags in this TML module
        // may have no complete pageContext objects any more after it was left
        BaseTagStatus parentTag = getParentTag();
        if (parentTag != null) {
            getTMLContext().settag(parentTag);
        }*/
       

  }

  /**
   * Gets the resource
   * @return Returns a String
   */
  public String getResource() {
    return resource;
  }
  /**
   * Sets the resource
   * @param resource The resource to set
   */
  public void setResource(String resource) {
    this.resource = resource;
  }

  /**
   * Returns the db.
   * @return String
   */
  public String getRef() {
    return ref;
  }

  /**
   * Sets the db.
   * @param db The db to set
   */
  public void setRef(String db) {
    this.ref = db;
  }

  /**
     * @param request
     */
    protected void storeCurrentTMLAttributes(HttpServletRequest request) {
       
        Status status = (Status) getStatus();
        Root.Status root;
        if (status instanceof Root.Status) {
            root = (Root.Status) status;
        }
        else {
            root = status.getRootTag();
        }
       
        status._upperTml = (String) request.getAttribute(WGACore.ATTRIB_CURRENTTML);
       
        request.setAttribute(WGACore.ATTRIB_CURRENTTML, root.resource);
    }
   
    protected void recoverCurrentTMLAttributes(HttpServletRequest request) {
       
        Status status = (Status) getStatus();
        request.setAttribute(WGACore.ATTRIB_CURRENTTML, status._upperTml);
       
    }
   
    /**
     * restores the given ajaxInformation (options and context)
     * @param ajaxInfo
     */
    public void restoreEnvironmentFromAjaxCall(AjaxInfo ajaxInfo, HttpServletRequest request) {
       
        Status status = (Status) getStatus();
       
        // restore options
        Map options = ajaxInfo.getOptions();
        Iterator itOptions = options.values().iterator();
        while (itOptions.hasNext()) {
            TMLOption option = (TMLOption) itOptions.next();
            if (!UNRECOVERABLE_OPTIONS.contains(option.getName())) {
                status.setOption(option.getName(), option.getValue(), option.getScope());
            }
        }
       
        // Restore design db option - must be here so following context change can use it
        status.setOption(OPTION_DESIGNDB, status._ajaxInfo.getDesignDB(), null);
       
        // restore context
        // B00004832
        TMLContext context = getTMLContext().context(ajaxInfo.getContextPath());
        this.setTMLContext(context);
        this.setChildTagContext(context);
       
        // Restore profile store on end flag
        if (getTMLContext().getprofile() != null) {
            getTMLContext().getprofile().setSavedOnEnd(ajaxInfo.isSaveProfileOnEnd());
        }
    }

    /**
     * @return Returns the modulename.
     */
    public String getModulename() {
        return modulename;
    }

    /**
     * @param modulename The modulename to set.
     */
    public void setModulename(String modulename) {
        this.modulename = modulename;
    }

    /**
     * @return Returns the modulemediakey.
     */
    public String getModulemediakey() {
        return modulemediakey;
    }

    /**
     * @param modulemediakey The modulemediakey to set.
     */
    public void setModulemediakey(String modulemediakey) {
        this.modulemediakey = modulemediakey;
    }
   
    /*
    public void restoreTMLOptions(HttpServletRequest request) {
        // restore options
        String encryptedOptions = request.getParameter("$options");
        if (encryptedOptions != null) {
            try {
                if (encryptedOptions.trim().equals("")) {
                    log.error("$OPTIONS parameter was posted with empty value. Cannon restore tml:options.");
                    return;
                }
                // decrypt
                byte[] serOptions = this.getTMLContext().getCore().getDesEncrypter().decrypt(encryptedOptions);
                // unzip
                String unzipped = Zipper.unzip(serOptions);
                // deserialize
                HashMap options = (HashMap) new XStream().fromXML(unzipped);
                // restore options
                Iterator itKeys = options.keySet().iterator();
                while (itKeys.hasNext()) {
                    String optionKey = (String) itKeys.next();                   
                    Object optionValue = options.get(optionKey);
                    this.setOption(optionKey, optionValue);
                }
            } catch (Exception e) {
                String errMsg = "Error restoring tml:options from posted request.";                   
                log.error(errMsg, e);
            }           
        }
       
        // restore context
        String currentMediaKey = (String) this.getOption(OPTION_CURRENT_MEDIAKEY);
        if (currentMediaKey != null) {
            this.setContext()
        }
    }*/
   
    private void filterOptions(Set optionsToFilter) {
       
        Iterator options = getStatus().getTagOptions().values().iterator();
        TMLOption option;
        while (options.hasNext()) {
            option = (TMLOption) options.next();
            if (optionsToFilter.contains(option.getName()) && option.isLocalScope()) {
                options.remove();
            }
        }
       
    }

    public TMLAction callAction(TMLActionLink actionLink, boolean ajax) throws TMLActionException, WGAPIException {
   
      // Set params
      ArrayList params = new ArrayList();
      params.add(actionLink.getParam1());
      params.add(actionLink.getParam2());
      params.add(actionLink.getParam3());
      params.add(actionLink.getParam4());
      params.add(actionLink.getParam5());
   
      // Look for correct sequence number to prevent action execution by page reload. Fail silently
      HttpSession session = getTMLContext().gethttpsession();
        if (!isCurrentSequenceNumber(actionLink, session, ajax)) {
            return null;
        }
       
        // Look if action was rendered in this session - if not do not execute
        if (!actionLink.getSessionID().equals(session.getId())) {
            throw new TMLInvalidActionLinkException("The action was registered for a different session ID");
        }
   
      // Try to retrieve action context - defaults to context of this tag
      TMLContext actionContext = getTMLContext();
      if (!actionLink.getContextPath().equals(TMLActionLink.EMPTY_PARAM)) {
        actionContext = actionContext.context(actionLink.getContextPath(), false);
           
            // Could not retrieve context. Too dangerous to execute action under the wrong context.
            if (actionContext == null) {
                throw new TMLActionException("Unable to retrieve action context: " + actionLink.getContextPath());
            }           
      } else {
        //B00004602
       
        // no context path - switch to dummy context of the given db 
        actionContext = getTMLContext().context("db:" + actionLink.getDbKey(), false);
       
        // Could not retrieve dummy context. Too dangerous to execute action under the wrong context.
        if (actionContext == null) {
          throw new TMLActionException("Unable to retrieve action context: db:" + actionLink.getDbKey());
        }
      }
     
      // Temporarily set portlet namespace, WebTML scope
      BaseTagStatus tag = getTMLContext().getDesignContext().getTag();
      TMLOptionPreserver preserver = new TMLOptionPreserver(tag);
       preserver.preserve(Base.OPTION_PORTLET_NAMESPACE, actionLink.getPortletKey());
        preserver.preserve(Base.OPTION_WEBTML_SCOPE, actionLink.getWebtmlScope());
     
        try {
        // Inner call, depends, if this a default action or not
        if (actionLink.isDefaultAction()) {
          actionContext.callDefaultAction(actionLink.getDefaultAction(), params);
          if (actionLink.getPortletmode() != null && actionContext.getportlet() != null) {
            actionContext.getportlet().setmode(actionLink.getPortletmode());
          }
          applyPortletContext(actionLink, actionContext);
          return null;
        }
        else {
          TMLAction tmlAction = (TMLAction) getTMLContext().getActionRegistration().get(actionLink.getActionKeyInteger());
          if (tmlAction == null) {
            throw new TMLActionException("Could not find action for key " + actionLink.getActionKey());
          }
          actionContext.callCustomAction(tmlAction, params);
          if (actionLink.getPortletmode() != null && actionContext.getportlet() != null) {
              if (getTMLContext().isdefined("actionresult")) {
                      ExpressionResult expressionResult = (ExpressionResult) getTMLContext().item("actionresult");
                      if (!expressionResult.isError() && (expressionResult.getResult() == null || expressionResult.getResult() instanceof String || !expressionResult.isFalse())) {
                          actionContext.getportlet().setmode(actionLink.getPortletmode());         
                      }
                  }
          }
                applyPortletContext(actionLink, actionContext);
          return tmlAction;
        }
       
       
        }
        finally {       
            preserver.restore();
        }
   
    }
   
    private void applyPortletContext(TMLActionLink actionLink, TMLContext actionContext) throws WGAPIException {
        String pContextPath = actionLink.getPortletContextPath();
        if (pContextPath != null && actionContext.getportlet() != null) {
            if (pContextPath.trim().equalsIgnoreCase(TMLPortlet.PORTLETCONTEXT_NONE)) {
                actionContext.getportlet().setcontext(null);   
            }
            else {
                actionContext.getportlet().getSessionContext().setContextPath(pContextPath);
            }
        }
    }

    private boolean isCurrentSequenceNumber(TMLActionLink actionLink, HttpSession session, boolean ajax) {
       
        boolean correctSequence = true;
       
        if (actionLink.isDefaultAction()) {
           
            TMLAction.DefaultAction defaultAction = TMLAction.getDefaultAction(actionLink.getDefaultAction());
           
            // When default action is unknown return true,
            // so the action execution runs and issues warning "unknown default action"
            if (defaultAction == null) {
                return true;
            }
           
            if (!defaultAction.isDebounced()) {
                return true;
            }
           
            if (!getCore().defaultActionSequenceIdAlreadyUsed(actionLink.getSequenceId())) {
                getCore().defaultActionCalledWithSequenceId(actionLink.getSequenceId());
            }
            else {
                correctSequence = false;
            }
        }
        else {
            TMLAction action = (TMLAction) getTMLContext().getActionRegistration().get(actionLink.getActionKeyInteger());
            if (action == null) {
                // Will fail later when action will be called. More speaking error message can be put out there.
                return true;
            }
           
            // if debouncing is disabled we do not care about sequencenumber
            if (!action.isDebounce() || (actionLink.getMode() != null && actionLink.getMode().equals(TMLActionLink.MODE_AJAX_NO_PORTLET_REFRESH))) {
                return true;
            }
           
            if (!action.sequenceIdAlreadyUsed(actionLink.getSequenceId())) {
                // action was not called with this sequenceId
                action.calledWithSequenceId(actionLink.getSequenceId());
            } else {
                correctSequence = false;
            }
        }
        return correctSequence;
    }

}
TOP

Related Classes of de.innovationgate.wgpublisher.webtml.Root

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.