Show ThinkCap.java syntax highlighted
package org.integratedmodelling.thinkcap;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Properties;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.integratedmodelling.thinkcap.basecommands.StreamResource;
import org.integratedmodelling.thinkcap.basecommands.StreamTemplate;
import org.integratedmodelling.thinkcap.basecommands.ThinkcapMain;
import org.integratedmodelling.thinkcap.exceptions.ThinkcapException;
import org.integratedmodelling.thinkcap.widget.ThinkcapWidgetManager;
import org.integratedmodelling.thinklab.command.CommandDeclaration;
import org.integratedmodelling.thinklab.exception.ThinklabException;
import org.integratedmodelling.thinklab.exception.ThinklabIOException;
import org.integratedmodelling.thinklab.impl.Session;
import org.integratedmodelling.thinklab.impl.protege.FileKnowledgeRepository;
import org.integratedmodelling.thinklab.interfaces.IConcept;
import org.integratedmodelling.thinklab.interfaces.IKnowledgeInterface;
import org.integratedmodelling.thinklab.interfaces.IPlugin;
import org.integratedmodelling.thinklab.interfaces.ISession;
import org.integratedmodelling.thinklab.interfaces.IValue;
import org.integratedmodelling.utils.CopyURL;
import org.integratedmodelling.thinklab.configuration.LocalConfiguration;
import org.integratedmodelling.utils.MiscUtilities;
import org.integratedmodelling.utils.Pair;
/**
* Servlet implementation class for Servlet: ThinkCap
*
* TODO reimplement as a Knowledge Interface and use in a KnowledgeManager. KI has command loop based
* on get/post callbacks and translation to Command. Its INIT is the entry point and creates the KM and all.
* KM initializes and caches the search engine. Use within all servlets.
*
*/
public class ThinkCap extends org.zkoss.zk.ui.http.DHtmlLayoutServlet implements javax.servlet.Servlet, IKnowledgeInterface {
/**
* Plugins can register names and entry points for Thinklab applications, so we have a catalog of them.
* @author Ferdinando Villa
*
*/
public class ApplicationDescriptor {
String appName;
String entryPoint;
String image;
String description;
public ApplicationDescriptor(String name, String entry, String desc, String icon) {
appName = name;
entryPoint = entry;
description = desc;
image = icon;
}
}
private static final long serialVersionUID = 2125035537141697393L;
public final int STATUS_OK = 0;
public final int STATUS_ERROR = 1;
/* change version number and release date here */
public final String thinkcapVersion = "0.0 alpha";
public final String thinkcapReleaseDate = "October 2006";
public int status;
/* servlet-wide parameters that must not be known by templates */
public String uploadPath;
public String tcInterface;
ThinkcapManager TKM;
private Properties velocityProperties;
private String mainCommand = null;
private Hashtable<String, String> templateStyles = new Hashtable<String, String>();
private String macroFiles = null;
/**
* @deprecated should go into visual package
*/
private Hashtable<String, String> typeIcons = new Hashtable<String, String>();
private boolean initialized = false;
private ArrayList<ApplicationDescriptor> applications = new ArrayList<ApplicationDescriptor>();
/**
* Make sure that passed path is in Velocity template path
* @param path
* @throws ThinkcapException
*/
public void checkTemplatePath(String path) throws ThinkcapException {
String s = velocityProperties.getProperty( Velocity.FILE_RESOURCE_LOADER_PATH);
if (!s.contains(path)) {
s = path + "," + s;
velocityProperties.setProperty(Velocity.FILE_RESOURCE_LOADER_PATH, s);
}
}
public String getMainCommand() {
return mainCommand;
}
/**
* To be used in XUL scripts and actions to retrieve everything about the current Thinkcap session
* @param zSession
* @return
*/
static public ThinkcapSession getTkSession(org.zkoss.zk.ui.Session zSession) {
HttpSession hSession = (HttpSession) zSession.getNativeSession();
return hSession == null ? null : (ThinkcapSession)hSession.getAttribute("thinkcap.session.IMTSession");
}
public void registerApplication(String name, String entry, String desc, String icon) {
applications.add(new ApplicationDescriptor(name, entry, desc, icon));
}
public File getWebFilePath() throws ThinkcapException {
String path = getServletContext().getRealPath("/");
if (path == null) {
throw new ThinkcapException("thinkcap: web path not defined (not using tomcat?)");
}
return new File(path.substring(0, path.length() - 1));
}
/**
* Check if specified resource file is in web path.
* @param resource
* @return
* @throws ThinkcapException
*/
public boolean resourceExists(String resource) throws ThinkcapException {
File f = new File(getWebFilePath() + "/" + resource);
return f.exists();
}
public void init() throws ServletException
{
if (initialized)
return;
super.init();
/* set up paths so we can access templates from the servlet
fs space. */
String path = getServletContext().getRealPath("/");
if (path == null) {
/* should not happen unless we're not running Tomcat */
path = "/";
}
System.out.println("web path is" + path);
/* set status to OK - shouldn't be necessary */
status = STATUS_OK;
/* initial set up of template system. Plugins loaded by KM.initialize() may add
* search paths. */
velocityProperties = new Properties();
try {
/* initialize main parameters */
uploadPath = (String)getServletContext().
getInitParameter("thinkcap.UploadPath");
/* find out which interface we want */
tcInterface =
(String)getServletContext().
getInitParameter("thinkcap.Interface");
/* default to, ehm, default. TBC on tomcat4/linux an absent
parameter does not turn to null, but generates an exception,
so this must be avoided and its presence must be checked.\
FIXME this stuff is largely obsolete.
*/
if (tcInterface == null)
tcInterface = "default";
/* template and log path */
velocityProperties.setProperty( Velocity.FILE_RESOURCE_LOADER_PATH,
path + "interface/" + tcInterface);
velocityProperties.setProperty( "runtime.log", path + "velocity.log" );
/* TBC we may want to define class and params of the KR to use in
* init somehow, or use policies.
*/
if (TKM == null) {
TKM = new ThinkcapManager(new FileKnowledgeRepository(), this);
/*
* Initialize the plugin directory
*/
TKM.addPluginDirectory(LocalConfiguration.getSystemDirectory("Thinkcap/Plugins"));
getServletContext().log("Thinkcap plugins directory: " + LocalConfiguration.getSystemDirectory("Thinkcap/Plugins"));
/*
* direct plugins to write their goodies in the area that tomcat's
* classloader will look into.
*/
TKM.setPluginClasspaths(
new File(path + "/WEB-INF/classes"),
new File(path + "/WEB-INF/lib"));
// initalize the sucker, read plugins, unpack everything
TKM.initialize();
// FIXME remove
TKM.printBanner();
/* bind KM to context */
getServletContext().
setAttribute("thinkcap.OntologyRepository", TKM.getKnowledgeRepository());
/* add custom directive through properties */
if (macroFiles != null) {
velocityProperties.setProperty(
"velocimacro.library",
macroFiles);
}
/* initialize Velocity now that plugins had a chance to change the template
* path.
*/
Velocity.init(velocityProperties);
/* create common Velocity context with configuration params */
VelocityContext ctx = new VelocityContext();
/* tbi init it with public parameters, statistics etc */
ctx.put("thinkcapInterface", tcInterface);
ctx.put("thinkcapReleaseDate", thinkcapReleaseDate);
ctx.put("thinkcapVersion", thinkcapVersion);
/* set it into servlet context */
getServletContext().setAttribute("thinkcap.VelocityContext", ctx);
initialized = true;
// not really doing what we think
TKM.run();
}
} catch (Exception e) {
/* log exception */
getServletContext().log("Error during initialization: " +
e.getMessage(), e);
status = STATUS_ERROR;
}
}
/**
* Output a string of text as HTML, without templates, so we don't risk a template exception.
* Fairly basic.
*
* @param text
* @param response
* @throws ThinkcapException
*/
public void outputText(String text, HttpServletResponse response) throws ThinkcapException {
response.setContentType("text/html");
PrintWriter writer;
try {
writer = response.getWriter();
} catch (IOException e) {
throw new ThinkcapException(e);
}
writer.println("<html>");
writer.println("<head>");
writer.println("<title>Thinkcap: notification</title>");
writer.println("</head>");
writer.println("<body bgcolor=white>");
writer.println("<table border=\"0\">");
writer.println("<tr>");
writer.println("<td>");
writer.println("</td>");
writer.println("<td>");
writer.println("<p>" + text + "</p>");
writer.println("</td>");
writer.println("</tr>");
writer.println("</table>");
writer.println("</body>");
writer.println("</html>");
}
public void outputTemplate(String template,
VelocityContext ctx,
HttpServletResponse response,
Writer writer)
throws ThinkcapException
{
try {
Template t = Velocity.getTemplate(template + ".vm");
t.merge(ctx, writer);
} catch (Exception e) {
printException(e, response);
}
}
public void handleCommand(String mode, VelocityContext ctx,
HttpServletRequest request, HttpServletResponse response)
throws ThinklabException {
/*
* obtain a local context so that we keep changes local. Merge in the
* global context.
*/
VelocityContext lctx = new VelocityContext(ctx);
/* make mode available to template */
lctx.put("thinkcapMode", mode);
if (mode.equals("error")) {
String errorcode = (String) request.getSession().getAttribute(
"thinkcap.session.error");
handleError(errorcode, lctx, request, response);
} else {
// instantiate stuff
HashMap<String, String> args = new HashMap<String, String>();
Enumeration pnames = request.getParameterNames();
ArrayList<Pair<String, String>> signatures = new ArrayList<Pair<String,String>>();
while (pnames.hasMoreElements()) {
String pname = pnames.nextElement().toString();
if (pname.startsWith("widget_signature_")) {
signatures.add(
new Pair<String, String>(request.getParameter(pname), pname.substring(17)));
} else {
args.put(pname, request.getParameter(pname));
}
for (Pair<String, String> sig : signatures) {
ThinkcapWidgetManager.processWidgetResponse(args,
lctx,
sig.getFirst(),
sig.getSecond());
}
}
if (TKM.hasCommand(mode)) {
ThinkcapCommand cmd = new ThinkcapCommand(mode, args, request,
response);
cmd.context = lctx;
cmd.servletContext = getServletContext();
cmd.session = (ThinkcapSession) lctx.get("thinkcapSession");
// call command action
IValue result = TKM.submitCommand(cmd);
if (result != null && result.getClass() == ThinkcapAnswer.class) {
// parse answer, output template if requested
ThinkcapAnswer ta = (ThinkcapAnswer) result;
if (ta.template != null) {
PageSpecs pSp = (PageSpecs)ctx.get("pageSpecs");
/* add any styles set through the API */
if (ta.style != null) {
pSp.requestStyle(ta.style);
} else {
/* only add default style if no style requested explicitly */
String tstyle = templateStyles.get(mode);
if (tstyle != null) {
pSp.requestStyle(tstyle);
}
}
// output page in proper rendering order
outputPage(ta.template, lctx, response, cmd.getPrintWriter());
}
}
} else {
ThinkcapCommand cmd = new ThinkcapCommand(args, request, response, lctx);
cmd.context = lctx;
cmd.servletContext = getServletContext();
cmd.session = (ThinkcapSession)ctx.get("thinkcapSession");
// dummy call to ensure that WidgetManager is defined
cmd.getWidgetManager();
// see if plugin contained a default style for template
PageSpecs pSp = (PageSpecs) ctx.get("pageSpecs");
String tstyle = templateStyles.get(mode);
if (tstyle != null)
pSp.requestStyle(tstyle);
/* translate all argument into parameters. */
for ( String attr : args.keySet()) {
lctx.put(attr, args.get(attr));
}
// output page in proper rendering order
outputPage(mode, lctx, response, cmd.getPrintWriter());
}
}
}
/*
* Render the page in a twisted way: first process any embedded code in the main
* template. Then render the body to a string: in the process, embedded velocimacros
* may influence the page manager (e.g. add a style, a widget, or any js code that
* must appear in the header). Then render the header, output the body, and render the footer.
*/
public void outputPage(String template, VelocityContext ctx, HttpServletResponse response, PrintWriter writer) throws ThinklabException {
/* process any embedded code */
TemplateProcessor.get().processTemplate(template, ctx);
/* render template first */
StringWriter swriter = new StringWriter();
outputTemplate(template, ctx, response, swriter);
/*
* page macros may have changed the type of the page from HTML to
* something else.
*/
PageSpecs pSp = (PageSpecs)ctx.get("pageSpecs");
/* if HTML page, render header, output rendered template, render footer */
if (pSp.getPageType().equals("text/html")) {
outputTemplate("stdhead", ctx, response, writer);
writer.print(swriter.getBuffer());
outputTemplate("stdfoot", ctx, response, writer);
} else {
/* if not HTML, just output template and set to whatever type we have (TBI should
* this be simply text?) */
response.setContentType(pSp.getPageType());
writer.print(swriter.getBuffer());
}
/* reset page specifications */
pSp.reset();
}
public void handleError(String errorcode,
VelocityContext ctx,
HttpServletRequest request,
HttpServletResponse response)
throws ThinkcapException
{
outputText("An error has occurred: <b>" + errorcode + "</b>", response);
// ctx.put("errorMessage", errorcode);
// outputTemplate("error", ctx, writer, response);
}
/**
* Handle POST or GET request.
* @param request
* @param response
* @param isGet
* @throws ServletException
* @throws IOException
*/
private void handleHttpRequest(HttpServletRequest request, HttpServletResponse response, boolean isGet) throws ServletException, IOException {
if (!initialized) {
init();
}
/* velocity context, initially null */
VelocityContext ctx;
/* retrieve session */
HttpSession session = request.getSession(true);
ctx = (VelocityContext)
session.getAttribute("thinkcap.session.VelocityContext");
/* extract mode. It should be either the main application name (ThinkCap for now) or
* a command indicated by extension .cmd. Whatever is sent that is not a command is
* turned into ThinkCap anyway, although it should not be necessary.
*/
String mode = "ThinkCap";
if (request.getRequestURI().endsWith(".cmd")) {
mode = request.getRequestURI();
if (mode.indexOf("/") > -1)
mode = mode.substring(request.getRequestURI().lastIndexOf("/") + 1);
mode = mode.substring(0, mode.indexOf("."));
}
if (status != STATUS_OK) {
session.setAttribute("thinkcap.session.error", "102 - internal error");
mode = "error";
} else if (mode.equals("ThinkCap") && mainCommand != null) {
mode = mainCommand;
}
/* fill context with request-specific variables */
ctx.put("servletPath", request.getServletPath());
ctx.put("requestURL", request.getRequestURL());
/* pass context, writer and request to request handler */
try {
handleCommand(mode, ctx, request, response);
} catch (Exception e) {
try {
e.printStackTrace();
printException(e, response);
} catch (ThinkcapException e1) {
// TODO Auto-generated catch block
throw new ServletException(e1);
}
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
if (request.getRequestURI().endsWith(".zul") || request.getRequestURI().endsWith(".zhtml")) {
/* transfer to ZK. TODO Check if we should prepare any context */
super.doPost(request, response);
} else {
handleHttpRequest(request, response, false);
}
}
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
if (request.getRequestURI().endsWith(".zul") || request.getRequestURI().endsWith(".zhtml")) {
/* transfer to ZK. TODO Check if we should prepare any context */
super.doGet(request, response);
} else {
handleHttpRequest(request, response, false);
}
}
void printException(Exception e, HttpServletResponse response)
throws ThinkcapException {
StringWriter stringWriter = new StringWriter();
PrintWriter printWriter = new PrintWriter(stringWriter);
e.printStackTrace(printWriter);
StringBuffer error = stringWriter.getBuffer();
outputText("<p>An exception (" + e.getClass() + ") has occurred. Message is <b>" +
e + "</b>." + "</p><p>" + error + "</p>", response);
}
public void start() {
// we use this one to install hard-coded commands
try {
new ThinkcapMain().install(TKM);
new StreamResource().install(TKM);
new StreamTemplate().install(TKM);
} catch (ThinklabException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void initialize(String[] args) {
// subsumed in init()
}
public void importPreferences() {
// TODO Auto-generated method stub
}
public void savePreferences() {
// TODO Auto-generated method stub
}
public ISession createNewSession() throws ThinklabException {
// TODO set creation time and stats
return new ThinkcapSession();
}
public void notifySessionDeletion(Session session) {
// TODO Auto-generated method stub
}
public ISession getCurrentSession() throws ThinklabException {
// TODO Auto-generated method stub
return null;
}
public void registerCommand(CommandDeclaration arg0) throws ThinklabException {
// TODO Auto-generated method stub
}
public void setTemplateStyle(String name, String style) {
String tname = name;
if (tname.contains("/"))
tname = tname.substring(tname.lastIndexOf("/") + 1);
if (tname.contains("."))
tname = tname.substring(0, tname.lastIndexOf("."));
this.templateStyles.put(tname, style);
}
public void addMacroFile(String name) {
if (name.contains("/"))
name = name.substring(name.lastIndexOf("/") + 1);
if (this.macroFiles == null)
macroFiles = name;
else
macroFiles += "," + name;
}
/**
* @deprecated
* @param concept
* @param isLarge
* @return
*/
public String getTypeIcon(IConcept concept, boolean isLarge) {
/* FIXME this should recurse type hierarchy and return the closest available */
String ret = isLarge ? "type_icons/owl_large.png" : "type_icons/owl_large.png";
/* try setting to concept space icon first */
String icon =
concept.getConceptSpace() +
"_" +
(isLarge ? "large" : "small");
if (typeIcons.containsKey(icon))
ret = typeIcons.get(icon);
icon =
concept.getConceptSpace() +
"_" +
concept.getLocalName() +
"_" +
(isLarge ? "large" : "small");
if (typeIcons.containsKey(icon))
ret = typeIcons.get(icon);
return ret;
}
/**
* @deprecated
*/
public void addTypeIcon(String newf) {
String tname = newf.toString();
if (tname.contains("/"))
tname = tname.substring(tname.lastIndexOf("/") + 1);
if (tname.contains("."))
tname = tname.substring(0, tname.lastIndexOf("."));
this.typeIcons.put(tname, newf);
}
public void notifySessionDeletion(ISession session) {
// TODO Auto-generated method stub
}
public Collection<ApplicationDescriptor> getApplications() {
return applications;
}
/**
* Return the path to the classloader-visible directory that is specific of this web application.
* FIXME probably depends on container. This should only be assumed to work on Tomcat (like other
* things here).
* @return
*/
public File getLoadPath() {
return new File(getServletContext().getRealPath("/") + "WEB-INF/lib");
}
/**
* Copy a specific jar to classpath.
* NOTE: this will trigger a reload of the servlet context. We condition it to a new jar, but if the
* application needs to do this at every load, measures should be taken to prevent context reload.
* FIXME reload behavior should be addressed for generality.
*
* @param jarFile
* @throws ThinklabIOException
*/
public void copyJarToClasspath(File jarFile) throws ThinklabIOException {
File outfile = new File(getLoadPath() + "/" + MiscUtilities.getFileName(jarFile.toString()));
if (outfile.exists() && outfile.lastModified() >= jarFile.lastModified())
return;
CopyURL.copyChanneled(jarFile, outfile);
}
}
See more files for this project here