TclHandler.java :  » Web-Server » Brazil » sunlabs » brazil » tcl » Java Open Source

Java Open Source » Web Server » Brazil 
Brazil » sunlabs » brazil » tcl » TclHandler.java
/*
 * TclHandler.java
 *
 * Brazil project web application Framework,
 * export version: 1.1 
 * Copyright (c) 1999-2000 Sun Microsystems, Inc.
 *
 * Sun Public License Notice
 *
 * The contents of this file are subject to the Sun Public License Version 
 * 1.0 (the "License"). You may not use this file except in compliance with 
 * the License. A copy of the License is included as the file "license.terms",
 * and also available at http://www.sun.com/
 * 
 * The Original Code is from:
 *    Brazil project web application Framework release 1.1.
 * The Initial Developer of the Original Code is: suhler.
 * Portions created by suhler are Copyright (C) Sun Microsystems, Inc.
 * All Rights Reserved.
 * 
 * Contributor(s): cstevens, suhler.
 *
 * Version:  1.16
 * Created by suhler on 99/04/04
 * Last modified by suhler on 00/12/11 13:33:06
 */

package sunlabs.brazil.tcl;

import sunlabs.brazil.server.FileHandler;
import sunlabs.brazil.server.Handler;
import sunlabs.brazil.server.Request;
import sunlabs.brazil.server.Server;
import sunlabs.brazil.session.SessionManager;

import tcl.lang.Interp;
import tcl.lang.ReflectObject;
import tcl.lang.TCL;
import tcl.lang.TclException;
import tcl.lang.TclUtil;

import java.io.File;
import java.io.IOException;

/**
 * Handler for writing handlers in tcl.
 * Anytime a request is made, call the <b>respond</b> callback
 * in the tcl code, which is provided with the
 * {@link sunlabs.brazil.server.Request} object as an argument.
 * <p>
 * This provides a bare-bones tcl interface.  The startup script, which is
 * sourced once upon startup, 
 * should provide a friendlier interface.
 * <p>
 * One Tcl interpreter is started for each session.
 * The SessionID property of the request is used to choose the session.
 * if no Session ID is available, a single interpreter is used for each
 * request.
 * The interpreter is Initialized the first time it is referenced for a
 * session, or if the "SessionID" variable is NOT set.
 * <p>
 * This handler requires that <code>tcljava.jar</code> and
 * <code>jacl.jar</code> jar files (both available
 * <a href="http://www.scriptics.com/software/java1.0.html">)here</a>.
 * <p>
 * The following server properties are used:
 * <dl class=props>
 * <dt>callback  <dd>The name of the TCL script to call at each request.
 *    Defaults to <code>respond</code>.
 * <dt>prefix  <dd> The URL prefix to match (defaults to "/").
 * <dt>script  <dd> The name of the TCL file sourced on startup.
 *    The {@link #init} parameters a make available as the global
 *    variables <code>prefix</code> and <code>server</code>.
 * <dt>suffix  <dd> The URL suffix to match, if any.
 * </dl>
 *
 * @author    Stephen Uhler
 * @version    1.16, 00/12/11
 */

public class TclHandler implements Handler {
    Server server;
    String propsPrefix;
    String scriptName;
    String urlPrefix;
    String urlSuffix;
    String callback;

    static final String SCRIPT = "script";
    static final String PREFIX = "prefix";
    static final String SUFFIX = "suffix";
    static final String CALLBACK = "callback";

    /**
     * Create a tcl interp, extract the properties, and run the init script
     */

    public boolean
    init(Server server, String prefix) {
      this.server = server;
      propsPrefix = prefix;
  scriptName = server.props.getProperty(prefix + SCRIPT,prefix + "tcl");
  urlPrefix = server.props.getProperty(prefix + PREFIX,"/");
  urlSuffix = server.props.getProperty(prefix + SUFFIX,"");
  callback = server.props.getProperty(prefix + CALLBACK,"respond");
  File scriptFile = new File(scriptName);
  if (!scriptFile.isAbsolute()) {
      scriptFile = new File(server.props.getProperty(FileHandler.ROOT,"."), scriptName);
  }
  scriptName = scriptFile.getAbsolutePath();
  server.log(Server.LOG_DIAGNOSTIC, prefix, "Using: " + scriptName);
  return true;
    }

    /*
     * Find (or create) the interpreter.
     * Call the tcl callback script.
     * The <code>request</code> object reference is appended to the
     * <code>callback</code> parameter.
     * @return  true, if the callback script returns "true" or "1".
     */

    public boolean
    respond(Request request) throws IOException {

        if (!request.url.startsWith(urlPrefix))  {
            return false;
  }
        if (!request.url.endsWith(urlSuffix))  {
            return false;
  }

  /*
   * Find the proper interp, creating it if needed.  If newly created
   * (or if no SessionID variable was found) - initialize the interp
   */

  // request.props.list(System.out);
  String sessionId = request.props.getProperty("SessionID","common");
  request.log(Server.LOG_DIAGNOSTIC, "  Using session: " + sessionId);
  Interp interp = (Interp) SessionManager.getSession(sessionId, "TCL",
    Interp.class);
  setupInterp(interp, sessionId);

      int code = 0;
  String result = interp.getResult().toString();
      synchronized (interp) {
      try {
    interp.eval(callback + " " +
      ReflectObject.newInstance(interp, Request.class, request));
      } catch (TclException e) {
    code = e.getCompletionCode();
    String trace = e.toString();
    System.out.println("Tcl Oops: "  + code + " " + e);
    if (code == 1) {
        try {
      trace = interp.getVar("errorInfo", TCL.GLOBAL_ONLY).toString();
        } catch (Exception e1) {}
    }
    request.log(Server.LOG_WARNING, propsPrefix + trace);
      }
      result = interp.getResult().toString();
  }  // end sync block
  if ((code==0 || code==2) && (result.equalsIgnoreCase("true") ||
    result.equals("1"))) {
      return true;
  } else {
      return false;
  }
    }

    /**
     * Setup a tcl interpreter for this session
     */

    private void
    setupInterp(Interp newInterp, String id) {
  try {
      newInterp.getVar("SessionID", TCL.GLOBAL_ONLY);
      return;
  } catch (TclException e) {
      System.out.println("New interp: " + e);
  }
  try {
      TclUtil.setVar(newInterp, "tcl_interactive", "0", TCL.GLOBAL_ONLY);
      TclUtil.setVar(newInterp, "argv0", scriptName, TCL.GLOBAL_ONLY);
      TclUtil.setVar(newInterp, "prefix", propsPrefix, TCL.GLOBAL_ONLY);
      TclUtil.setVar(newInterp, "SessionID", id, TCL.GLOBAL_ONLY);
      TclUtil.setVar(newInterp, "server",
        ReflectObject.newInstance(newInterp, Server.class, server), 
        TCL.GLOBAL_ONLY);
      newInterp.evalFile(scriptName);
  } catch (TclException e) {
      int code = e.getCompletionCode();
      String trace = e.toString();
      if (code == 1) {
    try {
        trace = newInterp.getVar("errorInfo",
          TCL.GLOBAL_ONLY).toString();
    } catch (Exception e1) {}
      }
      server.log(Server.LOG_WARNING, null, trace);
  }
    return;
    }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.