Package org.olat.core.gui.control.winmgr

Source Code of org.olat.core.gui.control.winmgr.AjaxController

/**
* OLAT - Online Learning and Training<br>
* http://www.olat.org
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Copyright (c) 1999-2006 at Multimedia- & E-Learning Services (MELS),<br>
* University of Zurich, Switzerland.
* <p>
*/

package org.olat.core.gui.control.winmgr;

import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringEscapeUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.olat.core.defaults.dispatcher.StaticMediaDispatcher;
import org.olat.core.dispatcher.mapper.Mapper;
import org.olat.core.dispatcher.mapper.MapperRegistry;
import org.olat.core.gui.UserRequest;
import org.olat.core.gui.components.Component;
import org.olat.core.gui.components.Window;
import org.olat.core.gui.components.panel.Panel;
import org.olat.core.gui.components.velocity.VelocityContainer;
import org.olat.core.gui.control.DefaultController;
import org.olat.core.gui.control.Event;
import org.olat.core.gui.control.WindowBackOffice;
import org.olat.core.gui.control.pushpoll.WindowCommand;
import org.olat.core.gui.media.MediaResource;
import org.olat.core.gui.media.StringMediaResource;
import org.olat.core.helpers.Settings;
import org.olat.core.logging.AssertException;
import org.olat.core.logging.OLog;
import org.olat.core.logging.Tracing;
import org.olat.core.util.Util;

/**
* Description:<br> - to be used by the windowmanager only! - this controller
* manages the state of all browser windows on the client side (javascript) and
* communicates changes to the server side (java)
* <P>
* Initial Date: 17.03.2006 <br>
*
* @author Felix Jost
*/
public class AjaxController extends DefaultController {
  private static final String VELOCITY_ROOT = Util.getPackageVelocityRoot(AjaxController.class);
  private OLog log = Tracing.createLoggerFor(AjaxController.class);
  private VelocityContainer myContent;
  private VelocityContainer pollPeriodContent;
  private Panel mainP;
  private Panel pollperiodPanel;
  // protected only for performance improvement
  protected List<WindowCommand> windowcommands = new ArrayList<WindowCommand>(3);
  private MapperRegistry mreg;
  private Mapper m;
  private boolean showJSON = false;
  protected final WindowBackOfficeImpl wboImpl;
 
  private static final int DEFAULT_POLLPERIOD = 30000;//reasonable default value
  private int pollperiod = DEFAULT_POLLPERIOD;//reasonable default value
  private int pollCount = 0;
  private long creationTime = System.currentTimeMillis();
  private boolean ajaxEnabled;

  AjaxController(UserRequest ureq, final WindowBackOfficeImpl wboImpl, boolean ajaxEnabled, String iframeName) {
    super(null);
    this.wboImpl = wboImpl;
    this.ajaxEnabled = ajaxEnabled;
    pollPeriodContent = new VelocityContainer("jsserverpartpoll", VELOCITY_ROOT + "/pollperiod.html", null, this);
    pollPeriodContent.contextPut("pollperiod", new Integer(pollperiod));
   
    myContent = new VelocityContainer("jsserverpart", VELOCITY_ROOT + "/serverpart.html", null, this);
    myContent.contextPut("highlight", Boolean.FALSE);
    myContent.contextPut("pollperiod", new Integer(pollperiod));
   
    //more debug information: OLAT-3529
    if (ajaxEnabled) myContent.contextPut("isAdmin", Boolean.valueOf(ureq.getUserSession().getRoles().isOLATAdmin()));
   
    // create a mapper to not block main traffic when polling (or vica versa)
    final Window window = wboImpl.getWindow();
    m = new Mapper() {
      public MediaResource handle(String relPath, HttpServletRequest request) {
        pollCount++;
        // check for dirty components now.
        wboImpl.fireCycleEvent(Window.BEFORE_INLINE_RENDERING);
        Command updateDirtyCom = window.handleDirties();
        wboImpl.fireCycleEvent(Window.AFTER_INLINE_RENDERING);
        if (updateDirtyCom != null) {
          synchronized (windowcommands) { //o_clusterOK by:fj
            windowcommands.add(new WindowCommand(wboImpl, updateDirtyCom));
          }
        }
        MediaResource mr = extractMediaResource(false);
        return mr;
      }
    };

    mreg = MapperRegistry.getInstanceFor(ureq.getUserSession());
    String uri = mreg.register(m);
    myContent.contextPut("mapuri", uri);
    myContent.contextPut("iframeName", iframeName);
    myContent.contextPut("showJSON", Boolean.valueOf(showJSON));
   
    mainP = new Panel("ajaxMainPanel");
    mainP.setContent(myContent);
   
    pollperiodPanel = new Panel("pollperiodP");
    pollperiodPanel.setContent(pollPeriodContent);
    myContent.put("pollperiodPanel", pollperiodPanel);

    setInitialComponent(mainP);
   
    // either turn ajax on or off
    setAjaxEnabled(ajaxEnabled);
  }

  /**
   * @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest,
   *      org.olat.core.gui.components.Component, org.olat.core.gui.control.Event)
   */
  public void event(UserRequest ureq, Component source, Event event) {
  //
  }
 
  public void setHighLightingEnabled(boolean enabled) {
    myContent.contextPut("highlight", Boolean.valueOf(enabled));
  }

  public MediaResource extractMediaResource(boolean wrapHTML) {
    JSONObject json = getAndClearJSON();
    String res;
    String jsonText = json.toString();
    //System.out.println("jsontext:"+jsonText);
    if (wrapHTML) {
      // most ajax responses are a lot smaller than 16k
      StringBuffer sb = new StringBuffer(16384);
      sb.append("<html><head><script type=\"text/javascript\">\n/* <![CDATA[ */\nfunction invoke(){var r=")
        .append(jsonText).append("; ")
        .append("if (parent!=self&&parent.window.o_info){")
        .append("parent.window.o_ainvoke(r);")
          // normal case: ajax result can be delivered into the hidden iframe.
          // else: no parent frame or parent frame is not olat -> reasons:
          // a) mouse-right-click to open in new tab/window
          // b) fast double-click when target causes a 302 and browser's window's document has been updated, but old link was still clickable
          // c) ...
          // -> in all cases, do not show the json command, but reload the window which contained the link clicked (= window id of url)
         
        .append("} else {")
          // inform user that ajax-request cannot be opened in a new window,
          // todo felix: maybe send back request to bookmark-launch current url? -> new window?
          // we could then come near to what the user probably wanted when he/she opened a link in a new window
        .append("this.document.location=\"")
        .append(StaticMediaDispatcher.createStaticURIFor("msg/json/en/info.html"))
        .append("\";")
          //.append("window.open(self.location+\"?o_win_jsontop=1\"); this.close();")
          //.append("this.document.location=self.location+\"?o_win_jsontop=1\";")
        .append("}}")
        .append("\n/* ]]> */\n</script></head><body onLoad=\"invoke()\">");
          if (showJSON) {
            try {
              sb.append("<pre style=\"font-size:12px;\">len:").append(jsonText.length()).append(":\n").append(StringEscapeUtils.escapeHtml(json.toString(2))).append("</pre>");
            } catch (JSONException e) {
              sb.append("error while prettyprinting json for debug mode: ").append(e.getMessage());
            }
          }
          sb.append("</body></html>");
          res = sb.toString();
    } else {
      res = jsonText;
    }

    StringMediaResource smr = new StringMediaResource();
    smr.setContentType("text/html;charset=utf-8");
    // TODO: check if it worked also with text/javascript
    smr.setEncoding("utf-8");
    smr.setData(res);
    return smr;
  }

  private JSONObject createJSON(WindowCommand wc) {
    Command c = wc.getCommand();
    WindowBackOffice wbo = wc.getWindowBackOffice();
    long winId = wbo.getWindow().getDispatchID();
    JSONObject jo = new JSONObject();
    try {
      jo.put("cmd", c.getCommand());
      jo.put("w", winId);
      jo.put("cda", c.getSubJSON());
      return jo;
    } catch (JSONException e) {
      throw new AssertException("json exception:", e);
    }
  }

  /**
   * @param moreCmds a List of WindowCommand objects
   * @return
   */
  private JSONObject getAndClearJSON() {
    JSONObject root = new JSONObject();
   

    try {
      if (Settings.isDebuging()) {
        long time = System.currentTimeMillis();
        root.put("time", time);
      }
      synchronized (windowcommands) { //o_clusterOK by:fj
        // handle all windowcommands now, create json
        int sum = windowcommands.size();
        root.put("cmdcnt", sum); // number of commands: 0..n
        if (sum > 0) {
          JSONArray ja = new JSONArray();
          root.put("cmds", ja);
          // treat commands waiting for the poll
          for (int i = 0; i < sum; i++) {
            WindowCommand wc = windowcommands.get(i);
            JSONObject jo = createJSON(wc);
            ja.put(jo);
          }
          windowcommands.clear();
        }
       
      }
      return root;
    } catch (JSONException e) {
      throw new AssertException("wrong data put into json object", e);
    }
  }

  /**
   * @see org.olat.core.gui.control.DefaultController#doDispose(boolean)
   */
  protected void doDispose() {
    mreg.deregister(m);
    if (ajaxEnabled && pollCount == 0) {
      //the controller should be older than 40s otherwise poll may not started yet
      if ((System.currentTimeMillis() - creationTime) > 40000) log.warn("Client did not send a single polling request though ajax is enabled!");
    }
  }

  /**
   * @param wco
   */
  public void sendCommandTo(WindowCommand wco) {
    synchronized (windowcommands) { //o_clusterOK by:fj
      windowcommands.add(wco);
    }
  }

  /**
   * @param enabled
   */
  public void setAjaxEnabled(boolean enabled) {
    if (enabled) {
      mainP.setContent(myContent);
    } else {
      mainP.setContent(null);
    }

  }

  /**
   * @param showJSON The showJSON to set.
   */
  public void setShowJSON(boolean showJSON) {
    this.showJSON = showJSON;
    myContent.contextPut("showJSON", Boolean.valueOf(showJSON));
  }
 
  /**
   *
   * @param pollperiod time in ms between two polls
   */
  public void setPollPeriod(int pollperiod) {
    if (pollperiod != this.pollperiod) {
      if (pollperiod == -1) pollperiod = DEFAULT_POLLPERIOD;
      this.pollperiod = pollperiod;
      pollPeriodContent.contextPut("pollperiod", new Integer(pollperiod));
    } // else no need to change anything
  }

}
TOP

Related Classes of org.olat.core.gui.control.winmgr.AjaxController

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.