Package org.jasig.portal.tools

Source Code of org.jasig.portal.tools.ChannelServlet$Worker

/**
* Licensed to Jasig under one or more contributor license
* agreements. See the NOTICE file distributed with this work
* for additional information regarding copyright ownership.
* Jasig licenses this file to you 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.jasig.portal.tools;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Enumeration;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.sax.TransformerHandler;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jasig.portal.BrowserInfo;
import org.jasig.portal.ChannelRuntimeData;
import org.jasig.portal.ChannelSAXStreamFilter;
import org.jasig.portal.ChannelStaticData;
import org.jasig.portal.IChannel;
import org.jasig.portal.IPrivileged;
import org.jasig.portal.MediaManager;
import org.jasig.portal.PortalControlStructures;
import org.jasig.portal.PortalException;
import org.jasig.portal.PortalSessionManager;
import org.jasig.portal.StylesheetSet;
import org.jasig.portal.UPFileSpec;
import org.jasig.portal.security.IPerson;
import org.jasig.portal.security.PersonFactory;
import org.jasig.portal.serialize.BaseMarkupSerializer;
import org.jasig.portal.utils.ResourceLoader;
import org.jasig.portal.utils.SAX2BufferImpl;
import org.jasig.portal.utils.XSLT;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;

/**
* A servlet that allows one to render an IChannel outside of the portal.
* @author Peter Kharchenko <pkharchenko@interactivebusiness.com>
* @version $Revision: 19776 $
*/
public class ChannelServlet extends HttpServlet {
  private static final Log LOG = LogFactory.getLog(ChannelServlet.class);
  public static String detachBaseStart = "detach_";
  StylesheetSet set;
  MediaManager mediaM;
  private boolean initialized = false;
  private IChannel channel;
  private String channelName;
  private long timeOut = 10000;                 // 10 seconds is the default timeout value
  private static final String relativeSSLLocation = "ChannelServlet/ChannelServlet.ssl";

  public void init() throws ServletException {
    ServletConfig sc = this.getServletConfig();
    if (sc != null) {
      // initialize stylesheet set
      // once JNDI DB access is in place the following line can be removed
      try {
  this.set = new StylesheetSet(ResourceLoader.getResourceAsURLString(this.getClass(), relativeSSLLocation));
        String mediaPropsUrl = ResourceLoader.getResourceAsURLString(this.getClass(), "/properties/media.properties");
        this.set.setMediaProps(mediaPropsUrl);
        this.mediaM = MediaManager.getMediaManager();
      } catch (PortalException pe) {
        throw new ServletException(pe);
      }
      // determine the channel with its parameters
      String className = sc.getInitParameter("className");
      channelName = sc.getInitParameter("channelName");
      String s_timeOut = sc.getInitParameter("timeOut");
      if (s_timeOut != null) {
          this.timeOut = Long.parseLong(s_timeOut);
      }
      // instantiate channel class
      try {
        channel = (org.jasig.portal.IChannel)Class.forName(className).newInstance();
        // construct a ChannelStaticData object
        ChannelStaticData sd = new ChannelStaticData();
        sd.setChannelSubscribeId("singlet");
        sd.setTimeout(timeOut);
        // determine the IPerson object
        IPerson person = PersonFactory.createGuestPerson();
        sd.setPerson(person);
        // todo: determine and pass channel publish/subscribe parameters.
        //        sd.setParameters (params);
        channel.setStaticData(sd);
        initialized = true;
      } catch (Exception e) {
          // some diagnostic state can be saved here
        LOG.error(e,e);
      }
    }
  }


  public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
    doGet(req, res);
  }


  public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
    if (initialized) {
      // construct runtime data object
      ChannelRuntimeData rd = new ChannelRuntimeData();
      rd.setBrowserInfo(new BrowserInfo(req));

      for (Enumeration en = req.getParameterNames(); en.hasMoreElements();) {
        String pName = (String)en.nextElement();
        if (!pName.startsWith("uP_")) {
          String[] val = (String[])req.getParameterValues(pName);
          rd.put(pName, val);
        }
      }

      try {
          rd.setUPFile(new UPFileSpec(UPFileSpec.RENDER_METHOD,"servletRoot","singlet",null));
      } catch (PortalException pe) {
        LOG.error("unable to construct a UPFile !",pe);
      }

      if (channel instanceof IPrivileged) {
        // provide as much of PCS as we can
        PortalControlStructures pcs = new PortalControlStructures(req, res);
        try {
          ((IPrivileged)channel).setPortalControlStructures(pcs);
        } catch (Exception e) {
          // channel failed to accept portal control structures
          LOG.error("channel failed to accept portal control structures.",e);
        }
      }
      // start rendering in a separate thread
      SAX2BufferImpl buffer = new SAX2BufferImpl();
      Worker worker = new Worker(channel, rd, buffer);
      Thread workerThread = new Thread(PortalSessionManager.getThreadGroup(), worker, "servlet renderer");
      workerThread.start();
      long startTime = System.currentTimeMillis();
      // set the mime type
      res.setContentType(mediaM.getReturnMimeType(req));
      // set up the serializer
      BaseMarkupSerializer ser = mediaM.getSerializer(mediaM.getMedia(req), res.getWriter());
      ser.asContentHandler();
      // get the framing stylesheet
      String xslURI = null;
      try
      {
        xslURI = set.getStylesheetURI(req);
      }
      catch(PortalException pe)
      {
        throw new ServletException(pe);
      }
      try {
          TransformerHandler th=XSLT.getTransformerHandler(xslURI);
          th.setResult(new SAXResult(ser));
          try {
              long wait = timeOut - System.currentTimeMillis() + startTime;
              if (wait > 0)
                  workerThread.join(wait);
          } catch (InterruptedException e) {
              // thread waiting on the worker has been interrupted
              LOG.error("thread waiting on the worker has been interrupted.",e);
          }
          // kill the working thread
          // yes, this is terribly crude and unsafe, but I don't see an alternative
          workerThread.stop();
          if (worker.done()) {
              if (worker.successful()) {
                  // unplug the buffer
                  try {
                      org.xml.sax.helpers.AttributesImpl atl = new org.xml.sax.helpers.AttributesImpl();
                      atl.addAttribute("","name","name", "CDATA", channelName);
                      // add other attributes: hasHelp, hasAbout, hasEdit
                      th.startDocument();
                      th.startElement("","channel","channel", atl);
                      ChannelSAXStreamFilter custodian = new ChannelSAXStreamFilter(th);
                      custodian.setParent(buffer);
                      buffer.stopBuffering(); buffer.outputBuffer();
                      th.endElement("","channel","channel");
                      th.endDocument();
                  } catch (SAXException e) {
                      // worst case scenario: partial content output :(
                      LOG.error("error during unbuffering",e);
                  }
              } else {
                  // rendering was not successful
                  Exception e;
                  if ((e = worker.getException()) != null) {
                      // channel generated an exception ... this should be handled
                      StringWriter sw = new StringWriter();
                      e.printStackTrace(new PrintWriter(sw));
                      sw.flush();
                      showErrorMessage("channel generated exception " + e.toString() + ". Stack trace: " + sw.toString(), res);
                  }
                  // should never get there, unless thread.stop() has seriously messed things up for the worker thread.
              }
          } else {
              // rendering has timed out
              showErrorMessage("channel rendering timed out", res);
          }
      } catch (Exception e) {
          // some exception occurred during processor initialization or framing transformation
          showErrorMessage("Exception occurred during the framing transformation or XSLT processor initialization", res);
      }
    } else
      showErrorMessage("failed to initialize", res);
  }


  private void showErrorMessage(String message, HttpServletResponse res) {
    res.setContentType("text/html");
    try {
      PrintWriter out = res.getWriter();
      out.println("<html>");
      out.println("<body>");
      if (channelName != null)
        out.println("<h1>" + channelName + "</h1>");
      else
        out.println("<h1>" + getServletConfig().getServletName() + "</h1>");
      out.println("<h3>Error !</h3>");
      out.println("<p>" + message + "<p>");
      out.println("</body></html>");
    } catch (Exception e) {
    // unable to get a writer from the HttpServletResponse object
    }
  }

  // the object that does the actual rendering
    protected class Worker
  implements Runnable {
  private boolean successful;
  private boolean done;
  private IChannel channel;
  private ChannelRuntimeData rd;
  private ContentHandler contentHandler;
  private Exception exc = null;


    public Worker(IChannel ch, ChannelRuntimeData runtimeData, ContentHandler dh) {
      this.channel = ch;
      this.contentHandler = dh;
      this.rd = runtimeData;
    }

    public void run() {
      successful = false;
      done = false;
      try {
        if (rd != null)
          channel.setRuntimeData(rd);
        channel.renderXML(contentHandler);
        successful = true;
      } catch (Exception e) {
        this.exc = e;
      }
      done = true;
    }

    public boolean successful() {
      return  this.successful;
    }

    public boolean done() {
      return  this.done;
    }

    public Exception getException() {
      return  exc;
    }
  }


  protected IPerson getPerson(HttpServletRequest req) {
    HttpSession session = req.getSession(false);
    IPerson person = (IPerson)session.getAttribute("up_person");
    return  person;
  }
}


TOP

Related Classes of org.jasig.portal.tools.ChannelServlet$Worker

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.