Package org.butor.web.servlet

Source Code of org.butor.web.servlet.DefaultAjaxComponent

/*******************************************************************************
* Copyright 2013 butor.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package org.butor.web.servlet;

import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.butor.json.JsonHelper;
import org.butor.json.JsonRequest;
import org.butor.json.service.ResponseHandler;
import org.butor.utils.Message;
import org.butor.utils.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class DefaultAjaxComponent extends BaseAjaxComponent {
  protected Logger _logger = LoggerFactory.getLogger(getClass());
  private JsonHelper _jsh = new JsonHelper();
  private static final int MAX_ROWS_PER_NOTIF = 40;
  public DefaultAjaxComponent(Object targetCmp) {
    super(targetCmp);
  }
  @Override
  public void process(final HttpServletRequest req_, final HttpServletResponse resp_)
      throws ServletException, IOException {

    OutputStream os = null;
    ResponseHandler<Object> streamer = null;
    String serviceName = null;
    final List<Message> fmsgs = new ArrayList<Message>();
    final List<Object> frows = new ArrayList<Object>();
    ScriptStreamer notif = null;
    JsonRequest jr = null;
    try {
      jr = findJsonRequest(req_);
      List<?> params = _jsh.deserialize(jr.getServiceArgsJson(), List.class);
      int nbArgs = params.size();
      final JsonRequest fjr = jr;

      serviceName = jr.getService();
      if (StringUtil.isEmpty(serviceName))
        throw new IllegalArgumentException("Missing serviceName");

      Method m = findService(serviceName, nbArgs);
      if (m == null)
        throw new UnsupportedOperationException(
          String.format("Service=%s with %d args doesn't exists",
            serviceName, nbArgs +1));

      if (!fjr.isStreaming()) {
        resp_.setContentType("application/json");
      } else {
        resp_.setContentType("text/html");
      }

      os = resp_.getOutputStream();
      final OutputStream fos = os;

      notif = fjr.isStreaming() ? new ScriptStreamer() : null;
      final ScriptStreamer fnotif = notif;

      final String reqId = jr.getReqId();

      streamer = new ResponseHandler<Object>() {
        int rowsPerNotif = 2;
        long rowCount = 0;
        boolean startedResp = false;
        @Override
        public void end() {
          if (!startedResp)
            try {
              //startResp(os, fjr.isStreaming(), reqId, notif.funcDef());
              startedResp = true;
              if (fjr.isStreaming()) {
                fos.write(fnotif.funcDef());
                fos.flush();
              } else {
                fos.write(String.format("{\"reqId\":\"%s\",\"data\":[", reqId).getBytes());
                fos.flush();
              }
            } catch (IOException e1) {
              _logger.warn("Failed to write beginnig of response", e1);
            }
        }
        @Override
        public boolean addRow(Object row_) {
          if (row_ == null)
            return false;

          if (!startedResp)
            try {
              //startResp(os, fjr.isStreaming(), reqId, notif.funcDef());
              startedResp = true;
              if (fjr.isStreaming()) {
                fos.write(fnotif.funcDef());
                fos.flush();
              } else {
                fos.write(String.format("{\"reqId\":\"%s\",\"data\":[", reqId).getBytes());
                fos.flush();
              }
            } catch (IOException e1) {
              _logger.warn("Failed to addRow", e1);
              return false;
            }

          rowCount++;
          try {
            if (fjr.isStreaming()) {
              // send small size notif first, then grows slowly
              // to reach a max. This way, results will hit the browser
              // very soon.
              if (rowsPerNotif < MAX_ROWS_PER_NOTIF)
                rowsPerNotif+=2;
              frows.add(row_);
              //if (frows.size() >= rowsPerNotif) {
                String json = _jsh.serialize(frows);
                frows.clear();
                fos.write(fnotif.buildNotif(fjr.getReqId(), "row", json, false));
              //}
            } else {
              if (rowCount>1)
                fos.write(',');
              String json = _jsh.serialize(row_);
              fos.write(json.getBytes());
            }
            fos.flush();
            return true;
          } catch (IOException e) {
            _logger.warn("Failed to addRow", e);
          }
          return false;
        }

        @Override
        public boolean addMessage(Message message_) {
          if (message_ == null)
            return false;

          if (!startedResp)
            try {
              //startResp(os, fjr.isStreaming(), reqId, notif.funcDef());
              startedResp = true;
              if (fjr.isStreaming()) {
                fos.write(fnotif.funcDef());
                fos.flush();
              } else {
                fos.write(String.format("{\"reqId\":\"%s\",\"data\":[", reqId).getBytes());
                fos.flush();
              }
            } catch (IOException e1) {
              _logger.warn("Failed to addRow", e1);
              return false;
            }

          fmsgs.add(message_);
          try {
            if (fjr.isStreaming()) {
              if (frows.size() > 0) {
                String json = _jsh.serialize(frows);
                frows.clear();
                fos.write(fnotif.buildNotif(fjr.getReqId(), "row", json, false));
              }

              String json = _jsh.serialize(fmsgs);
              fmsgs.clear();
              fos.write(fnotif.buildNotif(fjr.getReqId(), "msg", json, false));
              fos.flush();
            }
            return true;
          } catch (IOException e) {
            _logger.warn("Failed to write row or message", e);
          }
          return false;
        }
      };

      final ResponseHandler<Object> fStreamer = streamer;
      AjaxContext ctx = new AjaxContext() {
        @Override
        public ResponseHandler<Object> getResponseHandler() {
          return fStreamer;
        }
        @Override
        public HttpServletResponse getHttpServletResponse() {
          return resp_;
        }
        @Override
        public HttpServletRequest getHttpServletRequest() {
          return req_;
        }
        @Override
        public JsonRequest getRequest() {
          return fjr;
        }
      };
      Class<?>[] pts = m.getParameterTypes();
      Object[] args = new Object[pts.length];
      args[0] = ctx;
      for (int ii=1; ii<pts.length; ii++) {
        Object par = params.get(ii-1);
        String so = _jsh.serialize(par);
        args[ii] = _jsh.deserialize(so, pts[ii]);
      }
      m.invoke(getTargetCmp(), args);

    } catch (InvocationTargetException e) {
      if (streamer != null)
        handleException(streamer, serviceName, e.getTargetException());
    } catch (Throwable e) {
      if (streamer != null)
        handleException(streamer, serviceName, e);
    } finally {
      if (streamer != null) {
        try {
          streamer.end();
 
          if (jr.isStreaming()) {
            if (frows.size() > 0) {
              String json = _jsh.serialize(frows);
              frows.clear();
              os.write(notif.buildNotif(jr.getReqId(), "row", json, false));
            }
            os.write(notif.buildNotif(jr.getReqId(), "row", null, true));
          } else {
            os.write("],\"messages\":".getBytes());
            os.write(_jsh.serialize(fmsgs).getBytes());
            os.write('}');
          }
          os.flush();
        } catch (Exception e) {
          _logger.warn("Oh shit! Failed in finally.", e);
          //never mind
        }
      }
    }
  }
}
TOP

Related Classes of org.butor.web.servlet.DefaultAjaxComponent

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.