Reformatted according to Java code conventions.

Added Header comment with license and version info.
This commit is contained in:
hns 2003-04-10 17:16:25 +00:00
parent 33018c141c
commit d5c48918a0
131 changed files with 28602 additions and 18221 deletions

View file

@ -1,3 +1,19 @@
/*
* Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.doc; package helma.doc;
import helma.framework.IPathElement; import helma.framework.IPathElement;
@ -6,107 +22,161 @@ import helma.util.SystemProperties;
import java.io.*; import java.io.*;
import java.util.*; import java.util.*;
/**
*
*/
public class DocApplication extends DocDirElement { public class DocApplication extends DocDirElement {
HashSet excluded; HashSet excluded;
public static void main (String args[]) { /**
// DocApplication app; * Creates a new DocApplication object.
// app = new DocApplication (args[0], args[1]); *
// app.readApplication (); * @param name ...
* @param location ...
// DocPrototype el = DocPrototype.newInstance (new File(args[0])); *
// el.readFiles (); * @throws DocException ...
*/
// DocFunction func = DocFunction.newTemplate (new File(args[0]));
// DocFunction func = DocFunction.newAction (new File(args[0]));
DocFunction[] func = DocFunction.newFunctions (new File (args[0]));
// DocSkin skin = DocSkin.newInstance (new File (args[0]));
// System.out.println (func.getContent ());
// System.out.println ("\n\n\ncomment = " + func.getComment ());
}
public DocApplication(String name, File location) throws DocException { public DocApplication(String name, File location) throws DocException {
super(name, location, APPLICATION); super(name, location, APPLICATION);
readProps(); readProps();
} }
/**
* Creates a new DocApplication object.
*
* @param name ...
* @param appDir ...
*
* @throws DocException ...
*/
public DocApplication(String name, String appDir) throws DocException { public DocApplication(String name, String appDir) throws DocException {
super(name, new File(appDir), APPLICATION); super(name, new File(appDir), APPLICATION);
readProps(); readProps();
} }
/**
*
*
* @param args ...
*/
public static void main(String[] args) {
// DocApplication app;
// app = new DocApplication (args[0], args[1]);
// app.readApplication ();
// DocPrototype el = DocPrototype.newInstance (new File(args[0]));
// el.readFiles ();
// DocFunction func = DocFunction.newTemplate (new File(args[0]));
// DocFunction func = DocFunction.newAction (new File(args[0]));
DocFunction[] func = DocFunction.newFunctions(new File(args[0]));
// DocSkin skin = DocSkin.newInstance (new File (args[0]));
// System.out.println (func.getContent ());
// System.out.println ("\n\n\ncomment = " + func.getComment ());
}
/** /**
* reads the app.properties file and parses for helma.excludeDocs * reads the app.properties file and parses for helma.excludeDocs
*/ */
private void readProps() { private void readProps() {
File propsFile = new File(location, "app.properties"); File propsFile = new File(location, "app.properties");
SystemProperties serverProps = Server.getServer().getProperties(); SystemProperties serverProps = Server.getServer().getProperties();
SystemProperties appProps = new SystemProperties(propsFile.getAbsolutePath (), serverProps); SystemProperties appProps = new SystemProperties(propsFile.getAbsolutePath(),
serverProps);
excluded = new HashSet(); excluded = new HashSet();
addExclude("cvs"); addExclude("cvs");
addExclude(".docs"); addExclude(".docs");
String excludeProps = appProps.getProperty("helma.excludeDocs"); String excludeProps = appProps.getProperty("helma.excludeDocs");
if (excludeProps != null) { if (excludeProps != null) {
StringTokenizer tok = new StringTokenizer(excludeProps, ","); StringTokenizer tok = new StringTokenizer(excludeProps, ",");
while (tok.hasMoreTokens()) { while (tok.hasMoreTokens()) {
String str = tok.nextToken().trim(); String str = tok.nextToken().trim();
addExclude(str); addExclude(str);
} }
} }
} }
/**
*
*
* @param str ...
*/
public void addExclude(String str) { public void addExclude(String str) {
excluded.add(str.toLowerCase()); excluded.add(str.toLowerCase());
} }
/**
*
*
* @param str ...
*
* @return ...
*/
public boolean isExcluded(String str) { public boolean isExcluded(String str) {
return (excluded.contains(str.toLowerCase())); return (excluded.contains(str.toLowerCase()));
} }
/** /**
* reads all prototypes and files of the application * reads all prototypes and files of the application
*/ */
public void readApplication() { public void readApplication() {
readProps(); readProps();
String arr[] = location.list ();
String[] arr = location.list();
children.clear(); children.clear();
for (int i = 0; i < arr.length; i++) { for (int i = 0; i < arr.length; i++) {
if (isExcluded (arr[i])) if (isExcluded(arr[i])) {
continue; continue;
}
File f = new File(location.getAbsolutePath(), arr[i]); File f = new File(location.getAbsolutePath(), arr[i]);
if (!f.isDirectory ())
if (!f.isDirectory()) {
continue; continue;
}
try { try {
DocPrototype pt = DocPrototype.newInstance(f, this); DocPrototype pt = DocPrototype.newInstance(f, this);
addChild(pt); addChild(pt);
pt.readFiles(); pt.readFiles();
} catch (DocException e) { } catch (DocException e) {
debug("Couldn't read prototype " + arr[i] + ": " + e.getMessage()); debug("Couldn't read prototype " + arr[i] + ": " + e.getMessage());
} }
System.out.println(f); System.out.println(f);
} }
for (Iterator i = children.values().iterator(); i.hasNext();) { for (Iterator i = children.values().iterator(); i.hasNext();) {
((DocPrototype) i.next()).checkInheritance(); ((DocPrototype) i.next()).checkInheritance();
} }
} }
/**
*
*
* @return ...
*/
public DocElement[] listFunctions() { public DocElement[] listFunctions() {
Vector allFunctions = new Vector(); Vector allFunctions = new Vector();
for (Iterator i = children.values().iterator(); i.hasNext();) { for (Iterator i = children.values().iterator(); i.hasNext();) {
DocElement proto = (DocElement) i.next(); DocElement proto = (DocElement) i.next();
allFunctions.addAll(proto.children.values()); allFunctions.addAll(proto.children.values());
} }
Collections.sort(allFunctions, new DocComparator(DocComparator.BY_NAME, this)); Collections.sort(allFunctions, new DocComparator(DocComparator.BY_NAME, this));
return (DocElement[]) allFunctions.toArray(new DocElement[allFunctions.size()]); return (DocElement[]) allFunctions.toArray(new DocElement[allFunctions.size()]);
} }
/** /**
* from helma.framework.IPathElement, overridden with "api" * from helma.framework.IPathElement, overridden with "api"
* to work in manage-application * to work in manage-application
@ -115,19 +185,13 @@ public class DocApplication extends DocDirElement {
return "api"; return "api";
} }
/** /**
* from helma.framework.IPathElement, overridden with * from helma.framework.IPathElement, overridden with
* Server.getServer() to work in manage-application * Server.getServer() to work in manage-application
*/ */
public IPathElement getParentElement() { public IPathElement getParentElement() {
Server s = helma.main.Server.getServer(); Server s = helma.main.Server.getServer();
return s.getChildElement(this.name); return s.getChildElement(this.name);
} }
} }

View file

@ -1,44 +1,88 @@
/*
* Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.doc; package helma.doc;
import java.util.Comparator; import java.util.Comparator;
/**
*
*/
public class DocComparator implements Comparator { public class DocComparator implements Comparator {
public static final int BY_TYPE = 0; public static final int BY_TYPE = 0;
public static final int BY_NAME = 1; public static final int BY_NAME = 1;
int mode; int mode;
DocElement docEl; DocElement docEl;
/**
* Creates a new DocComparator object.
*
* @param mode ...
* @param docEl ...
*/
public DocComparator(int mode, DocElement docEl) { public DocComparator(int mode, DocElement docEl) {
this.mode = mode; this.mode = mode;
this.docEl = docEl; this.docEl = docEl;
} }
/**
* Creates a new DocComparator object.
*
* @param docEl ...
*/
public DocComparator(DocElement docEl) { public DocComparator(DocElement docEl) {
this.mode = 0; this.mode = 0;
this.docEl = docEl; this.docEl = docEl;
} }
/**
*
*
* @param obj1 ...
* @param obj2 ...
*
* @return ...
*/
public int compare(Object obj1, Object obj2) { public int compare(Object obj1, Object obj2) {
DocElement e1 = (DocElement) obj1; DocElement e1 = (DocElement) obj1;
DocElement e2 = (DocElement) obj2; DocElement e2 = (DocElement) obj2;
if (mode==BY_TYPE && e1.getType()>e2.getType())
if ((mode == BY_TYPE) && (e1.getType() > e2.getType())) {
return 1; return 1;
else if (mode==BY_TYPE && e1.getType()<e2.getType()) } else if ((mode == BY_TYPE) && (e1.getType() < e2.getType())) {
return -1; return -1;
else { } else {
return e1.name.compareTo(e2.name); return e1.name.compareTo(e2.name);
} }
} }
/**
*
*
* @param obj ...
*
* @return ...
*/
public boolean equals(Object obj) { public boolean equals(Object obj) {
DocElement el = (DocElement) obj; DocElement el = (DocElement) obj;
if (el.name.equals(docEl.name) && el.getType()==docEl.getType()) {
if (el.name.equals(docEl.name) && (el.getType() == docEl.getType())) {
return true; return true;
} else { } else {
return false; return false;
} }
} }
} }

View file

@ -1,19 +1,35 @@
/*
* Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.doc; package helma.doc;
import FESI.Parser.*;
import java.io.*; import java.io.*;
import java.util.*; import java.util.*;
import FESI.Parser.*; /**
*
*/
public abstract class DocDirElement extends DocElement { public abstract class DocDirElement extends DocElement {
// a default file that is read as comment for applications // a default file that is read as comment for applications
// and prototypes if found in their directories // and prototypes if found in their directories
public static final String[] DOCFILES = { public static final String[] DOCFILES = {
"doc.html", "doc.htm", "doc.html", "doc.htm", "app.html",
"app.html", "app.htm", "app.htm", "prototype.html",
"prototype.html", "prototype.htm", "prototype.htm", "index.html", "index.htm"
"index.html", "index.htm"
}; };
protected DocDirElement(String name, File location, int type) { protected DocDirElement(String name, File location, int type) {
@ -24,13 +40,14 @@ public abstract class DocDirElement extends DocElement {
private void checkCommentFiles() throws DocException { private void checkCommentFiles() throws DocException {
for (int i = 0; i < DOCFILES.length; i++) { for (int i = 0; i < DOCFILES.length; i++) {
File f = new File(location, DOCFILES[i]); File f = new File(location, DOCFILES[i]);
if (f.exists()) { if (f.exists()) {
String rawComment = readFile(f); String rawComment = readFile(f);
parseComment(rawComment); parseComment(rawComment);
return; return;
} }
} }
} }
} }

View file

@ -1,11 +1,44 @@
/*
* Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.doc; package helma.doc;
import helma.framework.IPathElement;
import java.io.*; import java.io.*;
import java.util.*; import java.util.*;
import helma.framework.IPathElement; /**
*
*/
public abstract class DocElement implements IPathElement { public abstract class DocElement implements IPathElement {
public static final int APPLICATION = 0;
public static final int PROTOTYPE = 1;
public static final int ACTION = 2;
public static final int TEMPLATE = 3;
public static final int FUNCTION = 4;
public static final int MACRO = 5;
public static final int SKIN = 6;
public static final int PROPERTIES = 7;
// above constants are used as array indices
public static final String[] typeNames = {
"Application", "Prototype", "Action",
"Template", "Function", "Macro", "Skin",
"Properties"
};
// identifiers of this element // identifiers of this element
String name; String name;
@ -20,34 +53,17 @@ public abstract class DocElement implements IPathElement {
List tags = new Vector(); List tags = new Vector();
List parameters = new Vector(); List parameters = new Vector();
public static final int APPLICATION = 0; protected DocElement(String name, String location, int type)
public static final int PROTOTYPE = 1; throws DocException {
public static final int ACTION = 2;
public static final int TEMPLATE = 3;
public static final int FUNCTION = 4;
public static final int MACRO = 5;
public static final int SKIN = 6;
public static final int PROPERTIES = 7;
// above constants are used as array indices
public static final String[] typeNames = {
"Application",
"Prototype",
"Action",
"Template",
"Function",
"Macro",
"Skin",
"Properties"
};
protected DocElement (String name, String location, int type) throws DocException {
this(name, new File(location), type); this(name, new File(location), type);
} }
protected DocElement (String name, File location, int type) throws DocException { protected DocElement(String name, File location, int type)
if (location.exists()==false) throws DocException {
if (location.exists() == false) {
throw new DocException(name + " not found in " + location.toString()); throw new DocException(name + " not found in " + location.toString());
}
this.name = name; this.name = name;
this.location = location; this.location = location;
this.type = type; this.type = type;
@ -69,15 +85,24 @@ public abstract class DocElement implements IPathElement {
return location; return location;
} }
/**
*
*
* @return ...
*/
public int getType() { public int getType() {
return type; return type;
} }
/**
*
*
* @return ...
*/
public String getTypeName() { public String getTypeName() {
return typeNames[type]; return typeNames[type];
} }
/** /**
* returns the comment string, empty string if no comment is set. * returns the comment string, empty string if no comment is set.
*/ */
@ -85,7 +110,6 @@ public abstract class DocElement implements IPathElement {
return comment; return comment;
} }
/** /**
* the actual content of the doc element (the function body, the properties * the actual content of the doc element (the function body, the properties
* list, the file list etc. * list, the file list etc.
@ -94,20 +118,25 @@ public abstract class DocElement implements IPathElement {
return content; return content;
} }
/**
*
*
* @param rawContent ...
*/
public void addTag(String rawContent) { public void addTag(String rawContent) {
if (tags == null) { if (tags == null) {
tags = new Vector(); tags = new Vector();
} }
try { try {
DocTag tag = DocTag.parse(rawContent); DocTag tag = DocTag.parse(rawContent);
tags.add(tag); tags.add(tag);
} catch (DocException doc) { } catch (DocException doc) {
debug(doc.toString()); debug(doc.toString());
} }
} }
/** /**
* list all tags * list all tags
*/ */
@ -115,20 +144,28 @@ public abstract class DocElement implements IPathElement {
return (DocTag[]) tags.toArray(new DocTag[0]); return (DocTag[]) tags.toArray(new DocTag[0]);
} }
/** /**
* filter the tags according to DocTag.TYPE * filter the tags according to DocTag.TYPE
*/ */
public DocTag[] listTags(int type) { public DocTag[] listTags(int type) {
Vector retval = new Vector(); Vector retval = new Vector();
for (int i = 0; i < tags.size(); i++) { for (int i = 0; i < tags.size(); i++) {
if ( ((DocTag) tags.get (i)).getType() == type) if (((DocTag) tags.get(i)).getType() == type) {
retval.add(tags.get(i)); retval.add(tags.get(i));
} }
}
return (DocTag[]) retval.toArray(); return (DocTag[]) retval.toArray();
} }
/**
*
*
* @param param ...
*
* @return ...
*/
public boolean hasParameter(String param) { public boolean hasParameter(String param) {
return parameters.contains(param); return parameters.contains(param);
} }
@ -140,7 +177,6 @@ public abstract class DocElement implements IPathElement {
return (String[]) parameters.toArray(new String[0]); return (String[]) parameters.toArray(new String[0]);
} }
/** /**
* add a string to the parameters-list * add a string to the parameters-list
*/ */
@ -148,7 +184,6 @@ public abstract class DocElement implements IPathElement {
parameters.add(param); parameters.add(param);
} }
/** /**
* parse rawComment, render DocTags * parse rawComment, render DocTags
*/ */
@ -161,39 +196,53 @@ public abstract class DocElement implements IPathElement {
boolean lastEmpty = false; boolean lastEmpty = false;
int mode = BLANK; int mode = BLANK;
StringBuffer buf = new StringBuffer(); StringBuffer buf = new StringBuffer();
while (tok.hasMoreTokens()) { while (tok.hasMoreTokens()) {
String line = Util.chopDelimiters(tok.nextToken().trim()); String line = Util.chopDelimiters(tok.nextToken().trim());
if ("".equals(line)) { if ("".equals(line)) {
// if we've already had text, store that this line was empty // if we've already had text, store that this line was empty
lastEmpty = (mode != BLANK) ? true : false; lastEmpty = (mode != BLANK) ? true : false;
continue; continue;
} }
// if we come here the first time, start with TEXT mode // if we come here the first time, start with TEXT mode
mode = (mode == BLANK) ? TEXT : mode; mode = (mode == BLANK) ? TEXT : mode;
// check if we have a new tag // check if we have a new tag
if (DocTag.isTagStart(line)) { if (DocTag.isTagStart(line)) {
// if we appended to comment text until now, store that ... // if we appended to comment text until now, store that ...
if (mode==TEXT) if (mode == TEXT) {
comment = buf.toString(); comment = buf.toString();
}
// if we appended to a tag, store that ... // if we appended to a tag, store that ...
if (mode==TAGS) if (mode == TAGS) {
addTag(buf.toString()); addTag(buf.toString());
}
// reset buffer // reset buffer
buf = new StringBuffer(); buf = new StringBuffer();
mode = TAGS; mode = TAGS;
} }
// append to current buffer // append to current buffer
if (lastEmpty==true) if (lastEmpty == true) {
buf.append("\n"); buf.append("\n");
}
buf.append(line); buf.append(line);
buf.append(" "); buf.append(" ");
lastEmpty = false; lastEmpty = false;
} }
// store the last element, if there was at least one element ... // store the last element, if there was at least one element ...
if (mode==TEXT) if (mode == TEXT) {
comment = buf.toString(); comment = buf.toString();
else if (mode==TAGS) } else if (mode == TAGS) {
addTag(buf.toString()); addTag(buf.toString());
}
} catch (RuntimeException rt) { } catch (RuntimeException rt) {
debug("parse error in " + location + ": " + rt.getMessage()); debug("parse error in " + location + ": " + rt.getMessage());
} }
@ -207,32 +256,56 @@ public abstract class DocElement implements IPathElement {
StringBuffer buf = new StringBuffer(); StringBuffer buf = new StringBuffer();
BufferedReader in = new BufferedReader(new FileReader(file)); BufferedReader in = new BufferedReader(new FileReader(file));
String line = in.readLine(); String line = in.readLine();
while (line != null) { while (line != null) {
buf.append(line + "\n"); buf.append(line + "\n");
line = in.readLine(); line = in.readLine();
} }
in.close(); in.close();
return buf.toString(); return buf.toString();
} catch (IOException e) { } catch (IOException e) {
return (""); return ("");
} }
} }
/**
*
*
* @param parent ...
*/
public void setParent(DocElement parent) { public void setParent(DocElement parent) {
this.parent = parent; this.parent = parent;
} }
/**
*
*
* @param child ...
*/
public void addChild(DocElement child) { public void addChild(DocElement child) {
if (child==null) if (child == null) {
return; return;
}
children.put(child.getElementName(), child); children.put(child.getElementName(), child);
} }
/**
*
*
* @return ...
*/
public int countChildren() { public int countChildren() {
return children.size(); return children.size();
} }
/**
*
*
* @return ...
*/
public Map getChildren() { public Map getChildren() {
return children; return children;
} }
@ -242,11 +315,15 @@ public abstract class DocElement implements IPathElement {
*/ */
public DocElement[] listChildren() { public DocElement[] listChildren() {
String[] keys = (String[]) children.keySet().toArray(new String[0]); String[] keys = (String[]) children.keySet().toArray(new String[0]);
Arrays.sort(keys); Arrays.sort(keys);
DocElement[] arr = new DocElement[keys.length]; DocElement[] arr = new DocElement[keys.length];
for (int i = 0; i < keys.length; i++) { for (int i = 0; i < keys.length; i++) {
arr[i] = (DocElement) children.get(keys[i]); arr[i] = (DocElement) children.get(keys[i]);
} }
return arr; return arr;
} }
@ -255,16 +332,18 @@ public abstract class DocElement implements IPathElement {
*/ */
public DocApplication getDocApplication() { public DocApplication getDocApplication() {
DocElement el = this; DocElement el = this;
while (el != null) { while (el != null) {
if (el instanceof DocApplication) { if (el instanceof DocApplication) {
return (DocApplication) el; return (DocApplication) el;
} }
el = (DocElement) el.getParentElement(); el = (DocElement) el.getParentElement();
} }
return null; return null;
} }
/** /**
* from helma.framework.IPathElement. Elements are named * from helma.framework.IPathElement. Elements are named
* like this: typename_name * like this: typename_name
@ -273,7 +352,6 @@ public abstract class DocElement implements IPathElement {
return typeNames[type].toLowerCase() + "_" + name; return typeNames[type].toLowerCase() + "_" + name;
} }
/** /**
* from helma.framework.IPathElement. Retrieves a child from the * from helma.framework.IPathElement. Retrieves a child from the
* children map. * children map.
@ -284,11 +362,11 @@ public abstract class DocElement implements IPathElement {
} catch (ClassCastException cce) { } catch (ClassCastException cce) {
debug(cce.toString()); debug(cce.toString());
cce.printStackTrace(); cce.printStackTrace();
return null; return null;
} }
} }
/** /**
* from helma.framework.IPathElement. Returns the parent object * from helma.framework.IPathElement. Returns the parent object
* of this instance if assigned. * of this instance if assigned.
@ -297,7 +375,6 @@ public abstract class DocElement implements IPathElement {
return parent; return parent;
} }
/** /**
* from helma.framework.IPathElement. Prototypes are assigned like * from helma.framework.IPathElement. Prototypes are assigned like
* this: "doc" + typename (e.g. docapplication, docprototype etc) * this: "doc" + typename (e.g. docapplication, docprototype etc)
@ -306,14 +383,21 @@ public abstract class DocElement implements IPathElement {
return "doc" + typeNames[type].toLowerCase(); return "doc" + typeNames[type].toLowerCase();
} }
/**
*
*
* @return ...
*/
public String toString() { public String toString() {
return "[" + typeNames[type] + " " + name + "]"; return "[" + typeNames[type] + " " + name + "]";
} }
/**
*
*
* @param msg ...
*/
public static void debug(String msg) { public static void debug(String msg) {
System.out.println(msg); System.out.println(msg);
} }
} }

View file

@ -1,16 +1,43 @@
/*
* Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.doc; package helma.doc;
/**
*
*/
public class DocException extends RuntimeException { public class DocException extends RuntimeException {
String str; String str;
/**
* Creates a new DocException object.
*
* @param str ...
*/
public DocException(String str) { public DocException(String str) {
super(str); super(str);
this.str = str; this.str = str;
} }
/**
*
*
* @return ...
*/
public String getMessage() { public String getMessage() {
return str; return str;
} }
} }

View file

@ -1,23 +1,48 @@
/*
* Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.doc; package helma.doc;
import FESI.Parser.*;
import java.io.*; import java.io.*;
import java.util.*; import java.util.*;
import FESI.Parser.*; /**
*
*/
public abstract class DocFileElement extends DocElement { public abstract class DocFileElement extends DocElement {
protected DocFileElement(String name, File location, int type) {
super(name, location, type);
}
/** /**
* extracts the function name from a file. basically chops the given suffix * extracts the function name from a file. basically chops the given suffix
* and throws an error if the file name doesn't fit. * and throws an error if the file name doesn't fit.
*/ */
static protected String nameFromFile (File f, String suffix) throws DocException { static protected String nameFromFile(File f, String suffix)
throws DocException {
String filename = f.getName(); String filename = f.getName();
if (!filename.endsWith (suffix))
throw new DocException ("file doesn't have suffix " + suffix + ": " + f.toString()); if (!filename.endsWith(suffix)) {
return filename.substring (0, filename.lastIndexOf(suffix)); throw new DocException("file doesn't have suffix " + suffix + ": " +
f.toString());
} }
return filename.substring(0, filename.lastIndexOf(suffix));
}
/** /**
* creates fesi token manager for a given file. * creates fesi token manager for a given file.
@ -26,6 +51,7 @@ public abstract class DocFileElement extends DocElement {
try { try {
ASCII_CharStream is = new ASCII_CharStream(new FileReader(f), 1, 1); ASCII_CharStream is = new ASCII_CharStream(new FileReader(f), 1, 1);
EcmaScriptTokenManager mgr = new EcmaScriptTokenManager(is, 0); EcmaScriptTokenManager mgr = new EcmaScriptTokenManager(is, 0);
return mgr; return mgr;
} catch (FileNotFoundException fnfe) { } catch (FileNotFoundException fnfe) {
fnfe.printStackTrace(); fnfe.printStackTrace();
@ -33,52 +59,54 @@ public abstract class DocFileElement extends DocElement {
} }
} }
protected DocFileElement (String name, File location, int type) {
super (name, location, type);
}
/** /**
* extracts a part of the source code, used to get the code for a * extracts a part of the source code, used to get the code for a
* single function from a function file. sets the field "content". * single function from a function file. sets the field "content".
*/ */
protected void parseSource (File sourceFile, int beginLine, int beginColumn, int endLine, int endColumn) { protected void parseSource(File sourceFile, int beginLine, int beginColumn,
int endLine, int endColumn) {
StringBuffer buf = new StringBuffer(); StringBuffer buf = new StringBuffer();
int ct = 0; int ct = 0;
try { try {
BufferedReader in = new BufferedReader(new FileReader(sourceFile)); BufferedReader in = new BufferedReader(new FileReader(sourceFile));
String line = ""; String line = "";
while (line != null) { while (line != null) {
line = in.readLine(); line = in.readLine();
if (line==null) break;
if (line == null) {
break;
}
ct++; ct++;
if (ct==beginLine)
if (ct == beginLine) {
buf.append(line.substring(beginColumn - 1, line.length()) + "\n"); buf.append(line.substring(beginColumn - 1, line.length()) + "\n");
else if ( ct>beginLine && ct<endLine ) } else if ((ct > beginLine) && (ct < endLine)) {
buf.append(line + "\n"); buf.append(line + "\n");
else if (ct==endLine) } else if (ct == endLine) {
buf.append(line.substring(0, endColumn)); buf.append(line.substring(0, endColumn));
} }
}
} catch (Exception e) { } catch (Exception e) {
debug(e.getMessage()); debug(e.getMessage());
} }
content = buf.toString(); content = buf.toString();
} }
/** /**
* connects all available specialTokens starting at the given token. * connects all available specialTokens starting at the given token.
*/ */
protected void parseCommentFromToken(Token tok) { protected void parseCommentFromToken(Token tok) {
StringBuffer buf = new StringBuffer(); StringBuffer buf = new StringBuffer();
while (tok.specialToken != null) { while (tok.specialToken != null) {
buf.append(tok.specialToken.toString()); buf.append(tok.specialToken.toString());
tok = tok.specialToken; tok = tok.specialToken;
} }
parseComment(buf.toString().trim()); parseComment(buf.toString().trim());
} }
} }

View file

@ -1,12 +1,34 @@
package helma.doc; /*
* Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
import java.io.*; package helma.doc;
import java.util.*;
import FESI.Parser.*; import FESI.Parser.*;
import helma.framework.IPathElement; import helma.framework.IPathElement;
import java.io.*;
import java.util.*;
/**
*
*/
public class DocFunction extends DocFileElement { public class DocFunction extends DocFileElement {
protected DocFunction(String name, File location, DocElement parent, int type) {
super(name, location, type);
this.parent = parent;
}
/** /**
* creates a new independent DocFunction object of type ACTION * creates a new independent DocFunction object of type ACTION
@ -15,14 +37,15 @@ public class DocFunction extends DocFileElement {
return newAction(location, null); return newAction(location, null);
} }
/** /**
* creates a new DocFunction object of type ACTION connected to another DocElement * creates a new DocFunction object of type ACTION connected to another DocElement
*/ */
public static DocFunction newAction(File location, DocElement parent) { public static DocFunction newAction(File location, DocElement parent) {
String name = nameFromFile(location, ".hac"); String name = nameFromFile(location, ".hac");
DocFunction func = new DocFunction(name, location, parent, ACTION); DocFunction func = new DocFunction(name, location, parent, ACTION);
func.parseActionFile(); func.parseActionFile();
return func; return func;
} }
@ -33,18 +56,18 @@ public class DocFunction extends DocFileElement {
return newTemplate(location, null); return newTemplate(location, null);
} }
/** /**
* creates a new DocFunction object of type TEMPLATE connected to another DocElement * creates a new DocFunction object of type TEMPLATE connected to another DocElement
*/ */
public static DocFunction newTemplate(File location, DocElement parent) { public static DocFunction newTemplate(File location, DocElement parent) {
String name = nameFromFile(location, ".hsp"); String name = nameFromFile(location, ".hsp");
DocFunction func = new DocFunction(name, location, parent, TEMPLATE); DocFunction func = new DocFunction(name, location, parent, TEMPLATE);
func.parseTemplateFile(); func.parseTemplateFile();
return func; return func;
} }
/** /**
* reads a function file and creates independent DocFunction objects of type FUNCTION * reads a function file and creates independent DocFunction objects of type FUNCTION
*/ */
@ -52,7 +75,6 @@ public class DocFunction extends DocFileElement {
return newFunctions(location, null); return newFunctions(location, null);
} }
/** /**
* reads a function file and creates DocFunction objects of type FUNCTION * reads a function file and creates DocFunction objects of type FUNCTION
* connected to another DocElement. * connected to another DocElement.
@ -61,60 +83,70 @@ public class DocFunction extends DocFileElement {
Vector vec = new Vector(); Vector vec = new Vector();
EcmaScriptTokenManager mgr = createTokenManager(location); EcmaScriptTokenManager mgr = createTokenManager(location);
Token tok = mgr.getNextToken(); Token tok = mgr.getNextToken();
while (tok.kind != 0) { while (tok.kind != 0) {
if (tok.kind == EcmaScriptConstants.FUNCTION) { if (tok.kind == EcmaScriptConstants.FUNCTION) {
// store the start position of the function: // store the start position of the function:
int beginLine = tok.beginLine; int beginLine = tok.beginLine;
int beginColumn = tok.beginColumn; int beginColumn = tok.beginColumn;
// the name is stored in the next token: // the name is stored in the next token:
String funcName = mgr.getNextToken().toString(); String funcName = mgr.getNextToken().toString();
// create the function object // create the function object
DocFunction func; DocFunction func;
if (funcName.endsWith("_action"))
if (funcName.endsWith("_action")) {
func = new DocFunction(funcName, location, parent, ACTION); func = new DocFunction(funcName, location, parent, ACTION);
else if (funcName.endsWith("_macro")) } else if (funcName.endsWith("_macro")) {
func = new DocFunction(funcName, location, parent, MACRO); func = new DocFunction(funcName, location, parent, MACRO);
else } else {
func = new DocFunction(funcName, location, parent, FUNCTION); func = new DocFunction(funcName, location, parent, FUNCTION);
}
// parse the comment from the special token(s) before this token: // parse the comment from the special token(s) before this token:
func.parseCommentFromToken(tok); func.parseCommentFromToken(tok);
// find the parameters of this function, but only if it's // find the parameters of this function, but only if it's
// neither macro nor action: // neither macro nor action:
if (func.type == FUNCTION) { if (func.type == FUNCTION) {
while (tok.kind!=0 && tok.kind!=EcmaScriptConstants.RPAREN) { while ((tok.kind != 0) && (tok.kind != EcmaScriptConstants.RPAREN)) {
if (tok.kind == EcmaScriptConstants.IDENTIFIER) { if (tok.kind == EcmaScriptConstants.IDENTIFIER) {
func.addParameter(tok.image); func.addParameter(tok.image);
} }
tok = mgr.getNextToken(); tok = mgr.getNextToken();
} }
} else { } else {
tok = mgr.getNextToken(); tok = mgr.getNextToken();
} }
// now find the end of the function: // now find the end of the function:
int endLine=0, endColumn=0; int endLine = 0;
while (tok.kind!=0 && tok.kind!=EcmaScriptConstants.FUNCTION) {
// now find the end of the function:
int endColumn = 0;
while ((tok.kind != 0) && (tok.kind != EcmaScriptConstants.FUNCTION)) {
endLine = tok.endLine; endLine = tok.endLine;
endColumn = tok.endColumn; endColumn = tok.endColumn;
tok = mgr.getNextToken(); tok = mgr.getNextToken();
} }
// now we know the exact position of the function in the file, // now we know the exact position of the function in the file,
// re-read it and extract the source code: // re-read it and extract the source code:
func.parseSource(location, beginLine, beginColumn, endLine, endColumn); func.parseSource(location, beginLine, beginColumn, endLine, endColumn);
vec.add(func); vec.add(func);
} }
if (tok.kind != EcmaScriptConstants.FUNCTION) { if (tok.kind != EcmaScriptConstants.FUNCTION) {
tok = mgr.getNextToken(); tok = mgr.getNextToken();
} }
} }
return (DocFunction[]) vec.toArray(new DocFunction[0]); return (DocFunction[]) vec.toArray(new DocFunction[0]);
} }
protected DocFunction (String name, File location, DocElement parent, int type) {
super (name, location, type);
this.parent = parent;
}
/** /**
* reads the content of a .hac file and parses the comment before the first * reads the content of a .hac file and parses the comment before the first
* javascript element * javascript element
@ -122,25 +154,27 @@ public class DocFunction extends DocFileElement {
private void parseActionFile() { private void parseActionFile() {
EcmaScriptTokenManager mgr = createTokenManager(location); EcmaScriptTokenManager mgr = createTokenManager(location);
Token tok = mgr.getNextToken(); Token tok = mgr.getNextToken();
parseCommentFromToken(tok); parseCommentFromToken(tok);
content = readFile(location); content = readFile(location);
} }
/** /**
* reads the content of a .hsp file and parses the comment before the first * reads the content of a .hsp file and parses the comment before the first
* javascript element (only if file starts with &gt;%-tag!). * javascript element (only if file starts with &gt;%-tag!).
*/ */
private void parseTemplateFile() { private void parseTemplateFile() {
content = readFile(location); content = readFile(location);
StringReader str = new StringReader (content.substring (content.indexOf("<%") + 2, content.indexOf ("%>")));
StringReader str = new StringReader(content.substring(content.indexOf("<%") + 2,
content.indexOf("%>")));
ASCII_CharStream ascii = new ASCII_CharStream(str, 1, 1); ASCII_CharStream ascii = new ASCII_CharStream(str, 1, 1);
EcmaScriptTokenManager mgr = new EcmaScriptTokenManager(ascii); EcmaScriptTokenManager mgr = new EcmaScriptTokenManager(ascii);
Token tok = mgr.getNextToken(); Token tok = mgr.getNextToken();
parseCommentFromToken(tok); parseCommentFromToken(tok);
} }
/** /**
* from helma.framework.IPathElement. All macros, templates, actions etc * from helma.framework.IPathElement. All macros, templates, actions etc
* have the same prototype. * have the same prototype.
@ -148,7 +182,4 @@ public class DocFunction extends DocFileElement {
public java.lang.String getPrototype() { public java.lang.String getPrototype() {
return "docfunction"; return "docfunction";
} }
} }

View file

@ -1,3 +1,19 @@
/*
* Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.doc; package helma.doc;
import helma.framework.IPathElement; import helma.framework.IPathElement;
@ -5,10 +21,28 @@ import helma.util.SystemProperties;
import java.io.*; import java.io.*;
import java.util.*; import java.util.*;
/**
*
*/
public class DocProperties extends DocFileElement { public class DocProperties extends DocFileElement {
Properties props = null; Properties props = null;
protected DocProperties(File location, DocElement parent)
throws DocException {
super(location.getName(), location, PROPERTIES);
this.parent = parent;
content = readFile(location);
props = new SystemProperties();
try {
props.load(new FileInputStream(location));
} catch (IOException e) {
debug("couldn't read file: " + e.toString());
} catch (Exception e) {
throw new DocException(e.toString());
}
}
/** /**
* creates a new independent DocProperties object * creates a new independent DocProperties object
*/ */
@ -27,37 +61,36 @@ public class DocProperties extends DocFileElement {
} }
} }
protected DocProperties (File location, DocElement parent) throws DocException { /**
super (location.getName (), location, PROPERTIES); *
this.parent = parent; *
content = readFile (location); * @return ...
props = new SystemProperties (); */
try {
props.load (new FileInputStream (location));
} catch (IOException e) {
debug ("couldn't read file: " + e.toString ());
} catch (Exception e) {
throw new DocException (e.toString ());
}
}
public Properties getProperties() { public Properties getProperties() {
return props; return props;
} }
/**
*
*
* @return ...
*/
public Properties getMappings() { public Properties getMappings() {
Properties childProps = new Properties(); Properties childProps = new Properties();
for (Enumeration e = props.keys(); e.hasMoreElements();) { for (Enumeration e = props.keys(); e.hasMoreElements();) {
String key = (String) e.nextElement(); String key = (String) e.nextElement();
String value = props.getProperty(key); String value = props.getProperty(key);
if (value.startsWith ("collection") || value.startsWith ("object") || value.startsWith ("mountpoint")) {
String prototype = value.substring (value.indexOf("(")+1, value.indexOf(")")).trim (); if (value.startsWith("collection") || value.startsWith("object") ||
value.startsWith("mountpoint")) {
String prototype = value.substring(value.indexOf("(") + 1,
value.indexOf(")")).trim();
childProps.setProperty(key, prototype); childProps.setProperty(key, prototype);
} }
} }
return childProps; return childProps;
} }
} }

View file

@ -1,16 +1,39 @@
/*
* Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.doc; package helma.doc;
import FESI.Parser.*;
import helma.framework.IPathElement; import helma.framework.IPathElement;
import java.io.*; import java.io.*;
import java.util.*; import java.util.*;
import FESI.Parser.*;
/**
*
*/
public class DocPrototype extends DocDirElement { public class DocPrototype extends DocDirElement {
private DocProperties typeProperties = null; private DocProperties typeProperties = null;
private DocPrototype parentPrototype = null; private DocPrototype parentPrototype = null;
private DocPrototype(String name, File location, DocElement parent) {
super(name, location, PROTOTYPE);
this.parent = parent;
typeProperties = DocProperties.newInstance(new File(location, "type.properties"));
}
/** /**
* creates a prototype that is independent of an * creates a prototype that is independent of an
* application object * application object
@ -28,16 +51,10 @@ public class DocPrototype extends DocDirElement {
*/ */
public static DocPrototype newInstance(File location, DocElement parent) { public static DocPrototype newInstance(File location, DocElement parent) {
DocPrototype pt = new DocPrototype(location.getName(), location, parent); DocPrototype pt = new DocPrototype(location.getName(), location, parent);
return pt; return pt;
} }
private DocPrototype (String name, File location, DocElement parent) {
super (name, location, PROTOTYPE);
this.parent = parent;
typeProperties = DocProperties.newInstance (new File (location, "type.properties"));
}
/** /**
* checks the type.properites for _extend values and connected a possible * checks the type.properites for _extend values and connected a possible
* parent prototype with this prototype. this can't be successfull at construction * parent prototype with this prototype. this can't be successfull at construction
@ -46,44 +63,64 @@ public class DocPrototype extends DocDirElement {
*/ */
public void checkInheritance() { public void checkInheritance() {
// hopobject is the top prototype: // hopobject is the top prototype:
if (name.equals("hopobject")) if (name.equals("hopobject")) {
return; return;
}
if (typeProperties != null) { if (typeProperties != null) {
// check for "_extends" in the the type.properties // check for "_extends" in the the type.properties
String ext = typeProperties.getProperties().getProperty("_extends"); String ext = typeProperties.getProperties().getProperty("_extends");
if (ext!=null && parent!=null) {
if ((ext != null) && (parent != null)) {
// try to get the prototype if available // try to get the prototype if available
parentPrototype = (DocPrototype) parent.getChildElement ("prototype_" + ext); parentPrototype = (DocPrototype) parent.getChildElement("prototype_" +
ext);
} }
} }
if (parentPrototype==null && parent!=null && !name.equals("global")) {
if ((parentPrototype == null) && (parent != null) && !name.equals("global")) {
// if no _extend was set, get the hopobject prototype // if no _extend was set, get the hopobject prototype
parentPrototype = (DocPrototype) parent.getChildElement("prototype_hopobject"); parentPrototype = (DocPrototype) parent.getChildElement("prototype_hopobject");
} }
} }
/**
*
*
* @return ...
*/
public DocPrototype getParentPrototype() { public DocPrototype getParentPrototype() {
return parentPrototype; return parentPrototype;
} }
/**
*
*
* @return ...
*/
public DocProperties getTypeProperties() { public DocProperties getTypeProperties() {
return typeProperties; return typeProperties;
} }
/** /**
* runs through the prototype directory and parses all helma files * runs through the prototype directory and parses all helma files
*/ */
public void readFiles() { public void readFiles() {
children.clear(); children.clear();
String arr[] = location.list ();
String[] arr = location.list();
for (int i = 0; i < arr.length; i++) { for (int i = 0; i < arr.length; i++) {
if (getDocApplication ().isExcluded (arr[i])) if (getDocApplication().isExcluded(arr[i])) {
continue; continue;
}
File f = new File(location.getAbsolutePath(), arr[i]); File f = new File(location.getAbsolutePath(), arr[i]);
if (f.isDirectory ())
if (f.isDirectory()) {
continue; continue;
}
try { try {
if (arr[i].endsWith(".skin")) { if (arr[i].endsWith(".skin")) {
addChild(DocSkin.newInstance(f, this)); addChild(DocSkin.newInstance(f, this));
@ -95,18 +132,19 @@ public class DocPrototype extends DocDirElement {
addChild(DocFunction.newTemplate(f, this)); addChild(DocFunction.newTemplate(f, this));
} else if (arr[i].endsWith(".js")) { } else if (arr[i].endsWith(".js")) {
DocElement[] elements = DocFunction.newFunctions(f, this); DocElement[] elements = DocFunction.newFunctions(f, this);
for (int j = 0; j < elements.length; j++) { for (int j = 0; j < elements.length; j++) {
addChild(elements[j]); addChild(elements[j]);
} }
} }
} catch (Exception ex) { } catch (Exception ex) {
System.out.println ("couldn't parse file " + f.getAbsolutePath () + ": " + ex.toString ()); System.out.println("couldn't parse file " + f.getAbsolutePath() + ": " +
ex.toString());
ex.printStackTrace(); ex.printStackTrace();
} catch (FESI.Parser.TokenMgrError err) { } catch (FESI.Parser.TokenMgrError err) {
System.out.println ("couldn't parse file " + f.getAbsolutePath () + ": " + err.toString ()); System.out.println("couldn't parse file " + f.getAbsolutePath() + ": " +
err.toString());
} }
} }
} }
} }

View file

@ -1,10 +1,35 @@
/*
* Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.doc; package helma.doc;
import helma.framework.IPathElement; import helma.framework.IPathElement;
import java.io.*; import java.io.*;
import java.util.*; import java.util.*;
/**
*
*/
public class DocSkin extends DocFileElement { public class DocSkin extends DocFileElement {
protected DocSkin(String name, File location, DocElement parent) {
super(name, location, SKIN);
this.parent = parent;
content = readFile(location);
parseHandlers();
}
/** /**
* creates a new independent DocSkin object * creates a new independent DocSkin object
@ -19,17 +44,10 @@ public class DocSkin extends DocFileElement {
public static DocSkin newInstance(File location, DocElement parent) { public static DocSkin newInstance(File location, DocElement parent) {
String skinname = nameFromFile(location, ".skin"); String skinname = nameFromFile(location, ".skin");
DocSkin skin = new DocSkin(skinname, location, parent); DocSkin skin = new DocSkin(skinname, location, parent);
return skin; return skin;
} }
protected DocSkin (String name, File location, DocElement parent) {
super (name, location, SKIN);
this.parent = parent;
content = readFile (location);
parseHandlers ();
}
/** /**
* parses the source code of the skin and * parses the source code of the skin and
* extracts all included macros. code taken * extracts all included macros. code taken
@ -41,39 +59,51 @@ public class DocSkin extends DocFileElement {
char[] source = content.toCharArray(); char[] source = content.toCharArray();
int sourceLength = source.length; int sourceLength = source.length;
int start = 0; int start = 0;
for (int i = 0; i < sourceLength-1; i++) {
if (source[i] == '<' && source[i+1] == '%') { for (int i = 0; i < (sourceLength - 1); i++) {
if ((source[i] == '<') && (source[i + 1] == '%')) {
// found macro start tag // found macro start tag
int j = i + 2; int j = i + 2;
// search macro end tag // search macro end tag
while (j < sourceLength-1 && (source[j] != '%' || source[j+1] != '>')) { while ((j < (sourceLength - 1)) &&
((source[j] != '%') || (source[j + 1] != '>'))) {
j++; j++;
} }
if (j > i+2) {
if (j > (i + 2)) {
String str = (new String(source, i + 2, j - i)).trim(); String str = (new String(source, i + 2, j - i)).trim();
if (str.endsWith("%>"))
if (str.endsWith("%>")) {
str = str.substring(0, str.length() - 2); str = str.substring(0, str.length() - 2);
}
if (str.startsWith("//")) { if (str.startsWith("//")) {
parseComment(str); parseComment(str);
} else { } else {
if (str.indexOf (" ")>-1) if (str.indexOf(" ") > -1) {
str = str.substring(0, str.indexOf(" ")); str = str.substring(0, str.indexOf(" "));
if (str.indexOf(".")>-1 && }
(str.startsWith ("param.")
|| str.startsWith ("response.") if ((str.indexOf(".") > -1) &&
|| str.startsWith("request.") (str.startsWith("param.") || str.startsWith("response.") ||
|| str.startsWith ("session.") str.startsWith("request.") || str.startsWith("session.")) &&
) && !partBuffer.contains(str)) { !partBuffer.contains(str)) {
partBuffer.add(str); partBuffer.add(str);
} }
} }
start = j + 2; start = j + 2;
} }
i = j + 1; i = j + 1;
} }
} }
String[] strArr = (String[]) partBuffer.toArray(new String[0]); String[] strArr = (String[]) partBuffer.toArray(new String[0]);
Arrays.sort(strArr); Arrays.sort(strArr);
for (int i = 0; i < strArr.length; i++) { for (int i = 0; i < strArr.length; i++) {
addParameter(strArr[i]); addParameter(strArr[i]);
} }
@ -85,7 +115,4 @@ public class DocSkin extends DocFileElement {
public java.lang.String getPrototype() { public java.lang.String getPrototype() {
return "docfunction"; return "docfunction";
} }
} }

View file

@ -1,9 +1,27 @@
/*
* Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.doc; package helma.doc;
import java.util.*; import java.util.*;
/**
*
*/
public final class DocTag { public final class DocTag {
// for public use we have less types than // for public use we have less types than
// internally. eg, we're combining "return" and "returns" // internally. eg, we're combining "return" and "returns"
// or "arg" and "param". // or "arg" and "param".
@ -16,7 +34,6 @@ public final class DocTag {
public static final int SEE = 6; public static final int SEE = 6;
public static final int DEPRECATED = 7; public static final int DEPRECATED = 7;
public static final int OVERRIDES = 8; public static final int OVERRIDES = 8;
public static final String[][] tags = { public static final String[][] tags = {
{ "@arg", "Argument" }, { "@arg", "Argument" },
{ "@param", "Parameter" }, { "@param", "Parameter" },
@ -28,33 +45,66 @@ public final class DocTag {
{ "@deprecated", "Deprecated" }, { "@deprecated", "Deprecated" },
{ "@overrides", "Overrides" } { "@overrides", "Overrides" }
}; };
private String name; private String name;
// "kind" is for internal use, "type" is external // "kind" is for internal use, "type" is external
private int kind; private int kind;
private String text; private String text;
public static boolean isTagStart (String rawTag) { private DocTag(int kind, String name, String text) {
if (getTagNumber(rawTag) > -1) this.kind = kind;
return true; this.name = (name != null) ? name : "";
else this.text = (text != null) ? text : "";
return false;
} }
/**
*
*
* @param rawTag ...
*
* @return ...
*/
public static boolean isTagStart(String rawTag) {
if (getTagNumber(rawTag) > -1) {
return true;
} else {
return false;
}
}
/**
*
*
* @param rawTag ...
*
* @return ...
*
* @throws DocException ...
*/
public static DocTag parse(String rawTag) throws DocException { public static DocTag parse(String rawTag) throws DocException {
int kind = getTagNumber(rawTag); int kind = getTagNumber(rawTag);
if (kind == -1)
if (kind == -1) {
throw new DocException("unsupported tag type: " + rawTag); throw new DocException("unsupported tag type: " + rawTag);
}
String content = rawTag.substring(tags[kind][0].length() + 1).trim(); String content = rawTag.substring(tags[kind][0].length() + 1).trim();
if (kind == 0 || kind==1) {
if ((kind == 0) || (kind == 1)) {
StringTokenizer tok = new StringTokenizer(content); StringTokenizer tok = new StringTokenizer(content);
String name = ""; String name = "";
if (tok.hasMoreTokens ())
if (tok.hasMoreTokens()) {
name = tok.nextToken(); name = tok.nextToken();
}
String comment = ""; String comment = "";
try { try {
comment = content.substring(name.length() + 1).trim(); comment = content.substring(name.length() + 1).trim();
} catch (StringIndexOutOfBoundsException e) { } } catch (StringIndexOutOfBoundsException e) {
}
return new DocTag(kind, name, comment); return new DocTag(kind, name, comment);
} else { } else {
return new DocTag(kind, "", content); return new DocTag(kind, "", content);
@ -63,46 +113,64 @@ public final class DocTag {
private static int getTagNumber(String rawTag) { private static int getTagNumber(String rawTag) {
rawTag = rawTag.trim().toLowerCase(); rawTag = rawTag.trim().toLowerCase();
for (int i = 0; i < tags.length; i++) { for (int i = 0; i < tags.length; i++) {
if (rawTag.startsWith(tags[i][0])) { if (rawTag.startsWith(tags[i][0])) {
return i; return i;
} }
} }
return -1; return -1;
} }
/**
private DocTag (int kind, String name, String text) { *
this.kind = kind; *
this.name = (name!=null) ? name : ""; * @return ...
this.text = (text!=null) ? text : ""; */
}
public String getName() { public String getName() {
return name; return name;
} }
/**
*
*
* @return ...
*/
public int getType() { public int getType() {
if (kind==0 || kind==1) if ((kind == 0) || (kind == 1)) {
return PARAMETER; return PARAMETER;
else if (kind==2 || kind==3) } else if ((kind == 2) || (kind == 3)) {
return RETURN; return RETURN;
else } else {
return kind; return kind;
} }
}
/**
*
*
* @return ...
*/
public String getTag() { public String getTag() {
return tags[kind][0]; return tags[kind][0];
} }
/**
*
*
* @return ...
*/
public String getText() { public String getText() {
return text; return text;
} }
/**
*
*
* @return ...
*/
public String toString() { public String toString() {
return tags[kind][1] + ": " + name + " " + text; return tags[kind][1] + ": " + name + " " + text;
} }
} }

View file

@ -1,26 +1,50 @@
/*
* Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.doc; package helma.doc;
import java.io.*; import java.io.*;
import java.util.*; import java.util.*;
/**
*
*/
public final class Util { public final class Util {
/**
*
*
* @param line ...
*
* @return ...
*/
public static String chopDelimiters(String line) { public static String chopDelimiters(String line) {
if (line==null) if (line == null) {
return null; return null;
else if (line.startsWith("/**")) } else if (line.startsWith("/**")) {
return line.substring(3).trim(); return line.substring(3).trim();
else if (line.startsWith("/*")) } else if (line.startsWith("/*")) {
return line.substring(2).trim(); return line.substring(2).trim();
else if (line.endsWith ("*/")) } else if (line.endsWith("*/")) {
return line.substring(0, line.length() - 2); return line.substring(0, line.length() - 2);
else if (line.startsWith("*")) } else if (line.startsWith("*")) {
return line.substring(1).trim(); return line.substring(1).trim();
else if (line.startsWith("//")) } else if (line.startsWith("//")) {
return line.substring(2).trim(); return line.substring(2).trim();
else } else {
return line; return line;
} }
}
} }

View file

@ -1,9 +1,31 @@
/*
* Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.extensions; package helma.extensions;
/**
*
*/
public class ConfigurationException extends RuntimeException { public class ConfigurationException extends RuntimeException {
/**
* Creates a new ConfigurationException object.
*
* @param msg ...
*/
public ConfigurationException(String msg) { public ConfigurationException(String msg) {
super(msg); super(msg);
} }
} }

View file

@ -1,19 +1,32 @@
package helma.extensions; /*
* Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
import java.util.HashMap; package helma.extensions;
import helma.framework.core.Application; import helma.framework.core.Application;
import helma.main.Server; import helma.main.Server;
import helma.scripting.ScriptingEngine; import helma.scripting.ScriptingEngine;
import java.util.HashMap;
/** /**
* Helma extensions have to subclass this. The extensions to be loaded are * Helma extensions have to subclass this. The extensions to be loaded are
* defined in <code>server.properties</code> by setting <code>extensions = * defined in <code>server.properties</code> by setting <code>extensions =
* packagename.classname, packagename.classname</code>. * packagename.classname, packagename.classname</code>.
*/ */
public abstract class HelmaExtension { public abstract class HelmaExtension {
/** /**
* called by the Server at startup time. should check wheter the needed classes * called by the Server at startup time. should check wheter the needed classes
* are present and throw a ConfigurationException if not. * are present and throw a ConfigurationException if not.
@ -24,7 +37,8 @@ public abstract class HelmaExtension {
* called when an Application is started. This should be <b>synchronized</b> when * called when an Application is started. This should be <b>synchronized</b> when
* any self-initialization is performed. * any self-initialization is performed.
*/ */
public abstract void applicationStarted (Application app) throws ConfigurationException; public abstract void applicationStarted(Application app)
throws ConfigurationException;
/** /**
* called when an Application is stopped. * called when an Application is stopped.
@ -45,9 +59,13 @@ public abstract class HelmaExtension {
* with pairs of varname and ESObjects. This method should be <b>synchronized</b>, if it * with pairs of varname and ESObjects. This method should be <b>synchronized</b>, if it
* performs any other self-initialization outside the scripting environment. * performs any other self-initialization outside the scripting environment.
*/ */
public abstract HashMap initScripting (Application app, ScriptingEngine engine) throws ConfigurationException; public abstract HashMap initScripting(Application app, ScriptingEngine engine)
throws ConfigurationException;
/**
*
*
* @return ...
*/
public abstract String getName(); public abstract String getName();
} }

View file

@ -1,12 +1,21 @@
/*
* Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.extensions.demo; package helma.extensions.demo;
import java.util.HashMap;
import helma.extensions.HelmaExtension;
import helma.extensions.ConfigurationException;
import helma.framework.core.Application;
import helma.main.Server;
import helma.scripting.ScriptingEngine;
// fesi-related stuff: // fesi-related stuff:
import FESI.Data.ESObject; import FESI.Data.ESObject;
@ -14,8 +23,13 @@ import FESI.Data.ESWrapper;
import FESI.Data.GlobalObject; import FESI.Data.GlobalObject;
import FESI.Exceptions.EcmaScriptException; import FESI.Exceptions.EcmaScriptException;
import FESI.Interpreter.Evaluator; import FESI.Interpreter.Evaluator;
import helma.extensions.ConfigurationException;
import helma.extensions.HelmaExtension;
import helma.framework.core.Application;
import helma.main.Server;
import helma.scripting.ScriptingEngine;
import helma.scripting.fesi.FesiEngine; import helma.scripting.fesi.FesiEngine;
import java.util.HashMap;
/** /**
* a demo extension implementation, to activate this add <code>extensions = * a demo extension implementation, to activate this add <code>extensions =
@ -23,9 +37,14 @@ import helma.scripting.fesi.FesiEngine;
* a new global object <code>demo</code> that wraps helma.main.Server * a new global object <code>demo</code> that wraps helma.main.Server
* will be added to the scripting environment. * will be added to the scripting environment.
*/ */
public class DemoExtension extends HelmaExtension { public class DemoExtension extends HelmaExtension {
/**
*
*
* @param server ...
*
* @throws ConfigurationException ...
*/
public void init(Server server) throws ConfigurationException { public void init(Server server) throws ConfigurationException {
try { try {
// just a demo with the server class itself (which is always there, obviously) // just a demo with the server class itself (which is always there, obviously)
@ -35,34 +54,73 @@ public class DemoExtension extends HelmaExtension {
} }
} }
/**
*
*
* @param app ...
*
* @throws ConfigurationException ...
*/
public void applicationStarted(Application app) throws ConfigurationException { public void applicationStarted(Application app) throws ConfigurationException {
app.logEvent("DemoExtension init with app " + app.getName()); app.logEvent("DemoExtension init with app " + app.getName());
} }
/**
*
*
* @param app ...
*/
public void applicationStopped(Application app) { public void applicationStopped(Application app) {
app.logEvent("DemoExtension stopped on app " + app.getName()); app.logEvent("DemoExtension stopped on app " + app.getName());
} }
/**
*
*
* @param app ...
*/
public void applicationUpdated(Application app) { public void applicationUpdated(Application app) {
app.logEvent("DemoExtension updated on app " + app.getName()); app.logEvent("DemoExtension updated on app " + app.getName());
} }
public HashMap initScripting (Application app, ScriptingEngine engine) throws ConfigurationException { /**
if (!(engine instanceof FesiEngine)) *
throw new ConfigurationException ("scripting engine " + engine.toString () + " not supported in DemoExtension"); *
app.logEvent("initScripting DemoExtension with " + app.getName () + " and " + engine.toString() ); * @param app ...
* @param engine ...
*
* @return ...
*
* @throws ConfigurationException ...
*/
public HashMap initScripting(Application app, ScriptingEngine engine)
throws ConfigurationException {
if (!(engine instanceof FesiEngine)) {
throw new ConfigurationException("scripting engine " + engine.toString() +
" not supported in DemoExtension");
}
app.logEvent("initScripting DemoExtension with " + app.getName() + " and " +
engine.toString());
// fesi-specific code: // fesi-specific code:
Evaluator evaluator = ((FesiEngine) engine).getEvaluator(); Evaluator evaluator = ((FesiEngine) engine).getEvaluator();
// initialize prototypes and global vars here, but don't add them to fesi's global object // initialize prototypes and global vars here, but don't add them to fesi's global object
ESWrapper demo = new ESWrapper(Server.getServer(), evaluator); ESWrapper demo = new ESWrapper(Server.getServer(), evaluator);
HashMap globals = new HashMap(); HashMap globals = new HashMap();
globals.put("demo", demo); globals.put("demo", demo);
return globals; return globals;
} }
/**
*
*
* @return ...
*/
public String getName() { public String getName() {
return "DemoExtension"; return "DemoExtension";
} }
} }

View file

@ -1,19 +1,31 @@
// ApplicationStoppedException.java /*
// Copyright (c) Hannes Wallnöfer 1998-2000 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.framework; package helma.framework;
/** /**
* This is thrown when a request is made to a stopped * This is thrown when a request is made to a stopped
* application * application
*/ */
public class ApplicationStoppedException extends RuntimeException { public class ApplicationStoppedException extends RuntimeException {
/**
* Creates a new ApplicationStoppedException object.
*/
public ApplicationStoppedException() { public ApplicationStoppedException() {
super("The application has been stopped"); super("The application has been stopped");
} }
} }

View file

@ -1,4 +1,18 @@
// CookieTrans.java /*
* Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.framework; package helma.framework;
@ -11,8 +25,10 @@ import javax.servlet.http.Cookie;
* of an HTTP cookie. * of an HTTP cookie.
*/ */
public final class CookieTrans implements Serializable { public final class CookieTrans implements Serializable {
String name;
String name, value, path, domain; String value;
String path;
String domain;
int days; int days;
CookieTrans(String name, String value) { CookieTrans(String name, String value) {
@ -36,39 +52,79 @@ public final class CookieTrans implements Serializable {
this.domain = domain; this.domain = domain;
} }
/**
*
*
* @return ...
*/
public String getName() { public String getName() {
return name; return name;
} }
/**
*
*
* @return ...
*/
public String getValue() { public String getValue() {
return value; return value;
} }
/**
*
*
* @return ...
*/
public int getDays() { public int getDays() {
return days; return days;
} }
/**
*
*
* @return ...
*/
public String getPath() { public String getPath() {
return path; return path;
} }
/**
*
*
* @return ...
*/
public String getDomain() { public String getDomain() {
return domain; return domain;
} }
/**
*
*
* @param defaultPath ...
* @param defaultDomain ...
*
* @return ...
*/
public Cookie getCookie(String defaultPath, String defaultDomain) { public Cookie getCookie(String defaultPath, String defaultDomain) {
Cookie c = new Cookie(name, value); Cookie c = new Cookie(name, value);
if (days > 0)
if (days > 0) {
// Cookie time to live, days -> seconds // Cookie time to live, days -> seconds
c.setMaxAge(days * 60 * 60 * 24); c.setMaxAge(days * 60 * 60 * 24);
if (path != null) }
if (path != null) {
c.setPath(path); c.setPath(path);
else if (defaultPath != null) } else if (defaultPath != null) {
c.setPath(defaultPath); c.setPath(defaultPath);
if (domain != null) }
if (domain != null) {
c.setDomain(domain); c.setDomain(domain);
else if (defaultDomain != null) } else if (defaultDomain != null) {
c.setDomain(defaultDomain); c.setDomain(defaultDomain);
}
return c; return c;
} }
} }

View file

@ -1,17 +1,33 @@
// FrameworkException.java /*
// Copyright (c) Hannes Wallnöfer 1998-2000 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.framework; package helma.framework;
/** /**
* The basic exception class used to tell when certain things go * The basic exception class used to tell when certain things go
* wrong in evaluation of requests. * wrong in evaluation of requests.
*/ */
public class FrameworkException extends RuntimeException { public class FrameworkException extends RuntimeException {
/**
* Creates a new FrameworkException object.
*
* @param msg ...
*/
public FrameworkException(String msg) { public FrameworkException(String msg) {
super(msg); super(msg);
} }
} }

View file

@ -1,5 +1,18 @@
// IPathElement.java /*
// Copyright (c) Hannes Wallnöfer 2001 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.framework; package helma.framework;
@ -14,9 +27,7 @@ package helma.framework;
* parent element. <p> * parent element. <p>
* *
*/ */
public interface IPathElement { public interface IPathElement {
/** /**
* Return the name to be used to get this element from its parent * Return the name to be used to get this element from its parent
*/ */
@ -32,16 +43,10 @@ public interface IPathElement {
*/ */
public IPathElement getParentElement(); public IPathElement getParentElement();
/** /**
* Get the name of the prototype to be used for this object. This will * Get the name of the prototype to be used for this object. This will
* determine which scripts, actions and skins can be called on it * determine which scripts, actions and skins can be called on it
* within the Helma scripting and rendering framework. * within the Helma scripting and rendering framework.
*/ */
public String getPrototype(); public String getPrototype();
} }

View file

@ -1,5 +1,18 @@
// IRemoteApp.java /*
// Copyright (c) Hannes Wallnöfer 1998-2000 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.framework; package helma.framework;
@ -9,11 +22,22 @@ import java.util.Vector;
/** /**
* RMI interface for an application. Currently only execute is used and supported. * RMI interface for an application. Currently only execute is used and supported.
*/ */
public interface IRemoteApp extends Remote { public interface IRemoteApp extends Remote {
/**
*
*
* @param param ...
*
* @return ...
*
* @throws RemoteException ...
*/
public ResponseTrans execute(RequestTrans param) throws RemoteException; public ResponseTrans execute(RequestTrans param) throws RemoteException;
/**
*
*
* @throws RemoteException ...
*/
public void ping() throws RemoteException; public void ping() throws RemoteException;
} }

View file

@ -1,5 +1,18 @@
// RedirectException.java /*
// Copyright (c) Hannes Wallnöfer 1998-2000 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.framework; package helma.framework;
@ -8,26 +21,43 @@ package helma.framework;
* RedirectException is thrown internally when a response is redirected to a * RedirectException is thrown internally when a response is redirected to a
* new URL. * new URL.
*/ */
public class RedirectException extends RuntimeException { public class RedirectException extends RuntimeException {
String url; String url;
/**
* Creates a new RedirectException object.
*
* @param url ...
*/
public RedirectException(String url) { public RedirectException(String url) {
super("Redirection Request to " + url); super("Redirection Request to " + url);
this.url = url; this.url = url;
} }
/**
*
*
* @return ...
*/
public String getMessage() { public String getMessage() {
return url; return url;
} }
/**
*
*
* @param s ...
*/
public void printStackTrace(java.io.PrintStream s) { public void printStackTrace(java.io.PrintStream s) {
// do nothing // do nothing
} }
/**
*
*
* @param w ...
*/
public void printStackTrace(java.io.PrintWriter w) { public void printStackTrace(java.io.PrintWriter w) {
// do nothing // do nothing
} }
} }

View file

@ -1,57 +1,125 @@
/*
* Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.framework; package helma.framework;
import helma.framework.core.Application;
import java.io.Serializable; import java.io.Serializable;
import java.util.Date;
import java.util.Map; import java.util.Map;
import helma.framework.core.Application; /**
import java.util.Date; *
*/
public class RequestBean implements Serializable { public class RequestBean implements Serializable {
RequestTrans req; RequestTrans req;
/**
* Creates a new RequestBean object.
*
* @param req ...
*/
public RequestBean(RequestTrans req) { public RequestBean(RequestTrans req) {
this.req = req; this.req = req;
} }
/**
*
*
* @param name ...
*
* @return ...
*/
public Object get(String name) { public Object get(String name) {
return req.get(name); return req.get(name);
} }
/**
*
*
* @return ...
*/
public boolean isGet() { public boolean isGet() {
return req.isGet(); return req.isGet();
} }
/**
*
*
* @return ...
*/
public boolean isPost() { public boolean isPost() {
return req.isPost(); return req.isPost();
} }
/**
*
*
* @return ...
*/
public String toString() { public String toString() {
return "[Request]"; return "[Request]";
} }
// property related methods: // property related methods:
public String getaction() { public String getaction() {
return req.action; return req.action;
} }
/**
*
*
* @return ...
*/
public Map getdata() { public Map getdata() {
return req.getRequestData(); return req.getRequestData();
} }
/**
*
*
* @return ...
*/
public long getruntime() { public long getruntime() {
return (System.currentTimeMillis() - req.startTime); return (System.currentTimeMillis() - req.startTime);
} }
/**
*
*
* @return ...
*/
public String getpassword() { public String getpassword() {
return req.getPassword(); return req.getPassword();
} }
/**
*
*
* @return ...
*/
public String getpath() { public String getpath() {
return req.path; return req.path;
} }
/**
*
*
* @return ...
*/
public String getusername() { public String getusername() {
return req.getUsername(); return req.getUsername();
} }
@ -63,12 +131,8 @@ public class RequestBean implements Serializable {
else else
return new Date (since); return new Date (since);
} }
public void setLastModified () { public void setLastModified () {
throw new RuntimeException ("The lastModified property of the Request object is read-only. "+ throw new RuntimeException ("The lastModified property of the Request object is read-only. "+
"Set lastModified on the Response object if you want to mark the last modification date of a resource."); "Set lastModified on the Response object if you want to mark the last modification date of a resource.");
} */ } */
} }

View file

@ -1,31 +1,48 @@
// RequestTrans.java /*
// Copyright (c) Hannes Wallnöfer 1998-2000 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.framework; package helma.framework;
import java.io.*;
import java.util.*;
import helma.objectmodel.*; import helma.objectmodel.*;
import helma.util.Base64; import helma.util.Base64;
import java.io.*;
import java.util.*;
/** /**
* A Transmitter for a request from the servlet client. Objects of this * A Transmitter for a request from the servlet client. Objects of this
* class are directly exposed to JavaScript as global property req. * class are directly exposed to JavaScript as global property req.
*/ */
public class RequestTrans implements Externalizable { public class RequestTrans implements Externalizable {
static final long serialVersionUID = 5398880083482000580L;
// the uri path of the request // the uri path of the request
public String path; public String path;
// the request's session id // the request's session id
public String session; public String session;
// the map of form and cookie data // the map of form and cookie data
private Map values; private Map values;
// the request method - 0 for GET, 1 for POST // the request method - 0 for GET, 1 for POST
private byte httpMethod = 0; private byte httpMethod = 0;
// timestamp of client-cached version, if present in request // timestamp of client-cached version, if present in request
private long ifModifiedSince = -1; private long ifModifiedSince = -1;
// set of ETags the client sent with If-None-Match header // set of ETags the client sent with If-None-Match header
private Set etags; private Set etags;
@ -34,12 +51,9 @@ public class RequestTrans implements Externalizable {
// the name of the action being invoked // the name of the action being invoked
public transient String action; public transient String action;
private transient String httpUsername; private transient String httpUsername;
private transient String httpPassword; private transient String httpPassword;
static final long serialVersionUID = 5398880083482000580L;
/** /**
* Create a new Request transmitter with an empty data map. * Create a new Request transmitter with an empty data map.
*/ */
@ -63,7 +77,6 @@ public class RequestTrans implements Externalizable {
values.put(name, value); values.put(name, value);
} }
/** /**
* Get a value from the requests map by key. * Get a value from the requests map by key.
*/ */
@ -87,10 +100,9 @@ public class RequestTrans implements Externalizable {
* detect multiple identic requests. * detect multiple identic requests.
*/ */
public int hashCode() { public int hashCode() {
return session == null ? super.hashCode () : session.hashCode (); return (session == null) ? super.hashCode() : session.hashCode();
} }
/** /**
* A request is considered equal to another one if it has the same user, path, * A request is considered equal to another one if it has the same user, path,
* and request data. This is used to evaluate multiple simultanous requests only once * and request data. This is used to evaluate multiple simultanous requests only once
@ -98,8 +110,8 @@ public class RequestTrans implements Externalizable {
public boolean equals(Object what) { public boolean equals(Object what) {
try { try {
RequestTrans other = (RequestTrans) what; RequestTrans other = (RequestTrans) what;
return (session.equals (other.session) &&
path.equalsIgnoreCase (other.path) && return (session.equals(other.session) && path.equalsIgnoreCase(other.path) &&
values.equals(other.getRequestData())); values.equals(other.getRequestData()));
} catch (Exception x) { } catch (Exception x) {
return false; return false;
@ -144,18 +156,35 @@ public class RequestTrans implements Externalizable {
s.writeObject(etags); s.writeObject(etags);
} }
/**
*
*
* @param since ...
*/
public void setIfModifiedSince(long since) { public void setIfModifiedSince(long since) {
ifModifiedSince = since; ifModifiedSince = since;
} }
/**
*
*
* @return ...
*/
public long getIfModifiedSince() { public long getIfModifiedSince() {
return ifModifiedSince; return ifModifiedSince;
} }
/**
*
*
* @param etagHeader ...
*/
public void setETags(String etagHeader) { public void setETags(String etagHeader) {
etags = new HashSet(); etags = new HashSet();
if (etagHeader.indexOf(",") > -1) { if (etagHeader.indexOf(",") > -1) {
StringTokenizer st = new StringTokenizer(etagHeader, ", \r\n"); StringTokenizer st = new StringTokenizer(etagHeader, ", \r\n");
while (st.hasMoreTokens()) while (st.hasMoreTokens())
etags.add(st.nextToken()); etags.add(st.nextToken());
} else { } else {
@ -163,56 +192,96 @@ public class RequestTrans implements Externalizable {
} }
} }
/**
*
*
* @return ...
*/
public Set getETags() { public Set getETags() {
return etags; return etags;
} }
/**
*
*
* @param etag ...
*
* @return ...
*/
public boolean hasETag(String etag) { public boolean hasETag(String etag) {
if (etags == null || etag == null) if ((etags == null) || (etag == null)) {
return false; return false;
}
return etags.contains(etag); return etags.contains(etag);
} }
/**
*
*
* @return ...
*/
public String getUsername() { public String getUsername() {
if ( httpUsername!=null ) if (httpUsername != null) {
return httpUsername;
String auth = (String)get("authorization");
if ( auth==null || "".equals(auth) ) {
return null;
}
decodeHttpAuth(auth);
return httpUsername; return httpUsername;
} }
public String getPassword() {
if ( httpPassword!=null )
return httpPassword;
String auth = (String) get("authorization"); String auth = (String) get("authorization");
if ( auth==null || "".equals(auth) ) {
if ((auth == null) || "".equals(auth)) {
return null; return null;
} }
decodeHttpAuth(auth); decodeHttpAuth(auth);
return httpUsername;
}
/**
*
*
* @return ...
*/
public String getPassword() {
if (httpPassword != null) {
return httpPassword;
}
String auth = (String) get("authorization");
if ((auth == null) || "".equals(auth)) {
return null;
}
decodeHttpAuth(auth);
return httpPassword; return httpPassword;
} }
private void decodeHttpAuth(String auth) { private void decodeHttpAuth(String auth) {
if ( auth==null ) if (auth == null) {
return; return;
}
StringTokenizer tok; StringTokenizer tok;
if( auth.startsWith("Basic ") )
tok = new StringTokenizer ( new String( Base64.decode((auth.substring(6)).toCharArray()) ), ":" ); if (auth.startsWith("Basic ")) {
else tok = new StringTokenizer(new String(Base64.decode((auth.substring(6)).toCharArray())),
":");
} else {
tok = new StringTokenizer(new String(Base64.decode(auth.toCharArray())), ":"); tok = new StringTokenizer(new String(Base64.decode(auth.toCharArray())), ":");
}
try { try {
httpUsername = tok.nextToken(); httpUsername = tok.nextToken();
} catch (NoSuchElementException e) { } catch (NoSuchElementException e) {
httpUsername = null; httpUsername = null;
} }
try { try {
httpPassword = tok.nextToken(); httpPassword = tok.nextToken();
} catch (NoSuchElementException e) { } catch (NoSuchElementException e) {
httpPassword = null; httpPassword = null;
} }
} }
} }

View file

@ -1,173 +1,384 @@
/*
* Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.framework; package helma.framework;
import helma.framework.core.Application;
import java.io.Serializable; import java.io.Serializable;
import java.util.Date;
import java.util.Map; import java.util.Map;
import helma.framework.core.Application; /**
import java.util.Date; *
*/
public class ResponseBean implements Serializable { public class ResponseBean implements Serializable {
ResponseTrans res; ResponseTrans res;
/**
* Creates a new ResponseBean object.
*
* @param res ...
*/
public ResponseBean(ResponseTrans res) { public ResponseBean(ResponseTrans res) {
this.res = res; this.res = res;
} }
/**
*
*
* @param what ...
*/
public void encode(Object what) { public void encode(Object what) {
res.encode(what); res.encode(what);
} }
/**
*
*
* @param what ...
*/
public void encodeXml(Object what) { public void encodeXml(Object what) {
res.encodeXml(what); res.encodeXml(what);
} }
/**
*
*
* @param what ...
*/
public void format(Object what) { public void format(Object what) {
res.format(what); res.format(what);
} }
/**
*
*
* @param url ...
*
* @throws RedirectException ...
*/
public void redirect(String url) throws RedirectException { public void redirect(String url) throws RedirectException {
res.redirect(url); res.redirect(url);
} }
/**
*
*/
public void reset() { public void reset() {
res.reset(); res.reset();
} }
/**
*
*
* @param key ...
* @param value ...
*/
public void setCookie(String key, String value) { public void setCookie(String key, String value) {
res.setCookie(key, value, -1, null, null); res.setCookie(key, value, -1, null, null);
} }
/**
*
*
* @param key ...
* @param value ...
* @param days ...
*/
public void setCookie(String key, String value, int days) { public void setCookie(String key, String value, int days) {
res.setCookie(key, value, days, null, null); res.setCookie(key, value, days, null, null);
} }
/**
*
*
* @param key ...
* @param value ...
* @param days ...
* @param path ...
*/
public void setCookie(String key, String value, int days, String path) { public void setCookie(String key, String value, int days, String path) {
res.setCookie(key, value, days, path, null); res.setCookie(key, value, days, path, null);
} }
/**
*
*
* @param key ...
* @param value ...
* @param days ...
* @param path ...
* @param domain ...
*/
public void setCookie(String key, String value, int days, String path, String domain) { public void setCookie(String key, String value, int days, String path, String domain) {
res.setCookie(key, value, days, path, domain); res.setCookie(key, value, days, path, domain);
} }
/**
*
*
* @param what ...
*/
public void write(Object what) { public void write(Object what) {
res.write(what); res.write(what);
} }
/**
*
*
* @param what ...
*/
public void writeln(Object what) { public void writeln(Object what) {
res.writeln(what); res.writeln(what);
} }
/**
*
*
* @param what ...
*/
public void writeBinary(byte[] what) { public void writeBinary(byte[] what) {
res.writeBinary(what); res.writeBinary(what);
} }
/**
*
*
* @param message ...
*/
public void debug(Object message) { public void debug(Object message) {
res.debug(message); res.debug(message);
} }
/**
*
*
* @return ...
*/
public String toString() { public String toString() {
return "[Response]"; return "[Response]";
} }
// property-related methods: // property-related methods:
public boolean getcache() { public boolean getcache() {
return res.cache; return res.cache;
} }
/**
*
*
* @param cache ...
*/
public void setcache(boolean cache) { public void setcache(boolean cache) {
res.cache = cache; res.cache = cache;
} }
/**
*
*
* @return ...
*/
public String getcharset() { public String getcharset() {
return res.charset; return res.charset;
} }
/**
*
*
* @param charset ...
*/
public void setcharset(String charset) { public void setcharset(String charset) {
res.charset = charset; res.charset = charset;
} }
/**
*
*
* @return ...
*/
public String getcontentType() { public String getcontentType() {
return res.contentType; return res.contentType;
} }
/**
*
*
* @param contentType ...
*/
public void setcontentType(String contentType) { public void setcontentType(String contentType) {
res.contentType = contentType; res.contentType = contentType;
} }
/**
*
*
* @return ...
*/
public Map getdata() { public Map getdata() {
return res.getResponseData(); return res.getResponseData();
} }
/**
*
*
* @return ...
*/
public Map gethandlers() { public Map gethandlers() {
return res.getMacroHandlers(); return res.getMacroHandlers();
} }
/**
*
*
* @return ...
*/
public String geterror() { public String geterror() {
return res.error; return res.error;
} }
/**
*
*
* @return ...
*/
public String getmessage() { public String getmessage() {
return res.message; return res.message;
} }
/**
*
*
* @param message ...
*/
public void setmessage(String message) { public void setmessage(String message) {
res.message = message; res.message = message;
} }
/**
*
*
* @return ...
*/
public String getrealm() { public String getrealm() {
return res.realm; return res.realm;
} }
/**
*
*
* @param realm ...
*/
public void setrealm(String realm) { public void setrealm(String realm) {
res.realm = realm; res.realm = realm;
} }
/**
*
*
* @param arr ...
*/
public void setskinpath(Object[] arr) { public void setskinpath(Object[] arr) {
res.setSkinpath(arr); res.setSkinpath(arr);
} }
/**
*
*
* @return ...
*/
public Object[] getskinpath() { public Object[] getskinpath() {
return res.getSkinpath(); return res.getSkinpath();
} }
/**
*
*
* @return ...
*/
public int getstatus() { public int getstatus() {
return res.status; return res.status;
} }
/**
*
*
* @param status ...
*/
public void setstatus(int status) { public void setstatus(int status) {
res.status = status; res.status = status;
} }
/**
*
*
* @return ...
*/
public Date getLastModified() { public Date getLastModified() {
long modified = res.getLastModified(); long modified = res.getLastModified();
if (modified > -1)
if (modified > -1) {
return new Date(modified); return new Date(modified);
else } else {
return null; return null;
} }
public void setLastModified (Date date) {
if (date == null)
res.setLastModified (-1);
else
res.setLastModified (date.getTime());
} }
/**
*
*
* @param date ...
*/
public void setLastModified(Date date) {
if (date == null) {
res.setLastModified(-1);
} else {
res.setLastModified(date.getTime());
}
}
/**
*
*
* @return ...
*/
public String getETag() { public String getETag() {
return res.getETag(); return res.getETag();
} }
/**
*
*
* @param etag ...
*/
public void setETag(String etag) { public void setETag(String etag) {
res.setETag(etag); res.setETag(etag);
} }
/**
*
*
* @param what ...
*/
public void dependsOn(Object what) { public void dependsOn(Object what) {
res.dependsOn(what); res.dependsOn(what);
} }
/**
*
*/
public void digest() { public void digest() {
res.digestDependencies(); res.digestDependencies();
} }
@ -177,14 +388,16 @@ public class ResponseBean implements Serializable {
// Helma templates (*.hsp files) and shouldn't // Helma templates (*.hsp files) and shouldn't
// be used otherwise. // be used otherwise.
//////////////////////////////////// ////////////////////////////////////
public void pushStringBuffer() { public void pushStringBuffer() {
res.pushStringBuffer(); res.pushStringBuffer();
} }
/**
*
*
* @return ...
*/
public String popStringBuffer() { public String popStringBuffer() {
return res.popStringBuffer(); return res.popStringBuffer();
} }
} }

View file

@ -1,21 +1,35 @@
// ResponseTrans.java /*
// Copyright (c) Hannes Wallnöfer 1998-2000 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.framework; package helma.framework;
import java.io.*;
import java.util.*;
import helma.framework.core.Skin; import helma.framework.core.Skin;
import helma.objectmodel.*; import helma.objectmodel.*;
import helma.util.*; import helma.util.*;
import java.io.*;
import java.security.*; import java.security.*;
import java.util.*;
/** /**
* A Transmitter for a response to the servlet client. Objects of this * A Transmitter for a response to the servlet client. Objects of this
* class are directly exposed to JavaScript as global property res. * class are directly exposed to JavaScript as global property res.
*/ */
public final class ResponseTrans implements Externalizable { public final class ResponseTrans implements Externalizable {
static final long serialVersionUID = -8627370766119740844L;
static final int INITIAL_BUFFER_SIZE = 2048;
/** /**
* Set the MIME content type of the response. * Set the MIME content type of the response.
@ -53,8 +67,10 @@ public final class ResponseTrans implements Externalizable {
// the last-modified date, if it should be set in the response // the last-modified date, if it should be set in the response
private long lastModified = -1; private long lastModified = -1;
// flag to signal that resource has not been modified // flag to signal that resource has not been modified
private boolean notModified = false; private boolean notModified = false;
// Entity Tag for this response, used for conditional GETs // Entity Tag for this response, used for conditional GETs
private String etag = null; private String etag = null;
@ -63,19 +79,19 @@ public final class ResponseTrans implements Externalizable {
// the buffer used to build the response // the buffer used to build the response
private transient StringBuffer buffer = null; private transient StringBuffer buffer = null;
// these are used to implement the _as_string variants for Hop templates. // these are used to implement the _as_string variants for Hop templates.
private transient Stack buffers; private transient Stack buffers;
// the path used to tell where to look for skins // the path used to tell where to look for skins
private transient Object[] skinpath = null; private transient Object[] skinpath = null;
// hashmap for skin caching // hashmap for skin caching
private transient HashMap skincache; private transient HashMap skincache;
// buffer for debug messages - will be automatically appended to response // buffer for debug messages - will be automatically appended to response
private transient StringBuffer debugBuffer; private transient StringBuffer debugBuffer;
static final long serialVersionUID = -8627370766119740844L;
/** /**
* string fields that hold a user message * string fields that hold a user message
*/ */
@ -86,8 +102,6 @@ public final class ResponseTrans implements Externalizable {
*/ */
public transient String error; public transient String error;
static final int INITIAL_BUFFER_SIZE = 2048;
// the map of form and cookie data // the map of form and cookie data
private transient Map values; private transient Map values;
@ -103,7 +117,9 @@ public final class ResponseTrans implements Externalizable {
// the appliciation checksum to make ETag headers sensitive to app changes // the appliciation checksum to make ETag headers sensitive to app changes
long applicationChecksum; long applicationChecksum;
/**
* Creates a new ResponseTrans object.
*/
public ResponseTrans() { public ResponseTrans() {
super(); super();
message = error = null; message = error = null;
@ -111,12 +127,16 @@ public final class ResponseTrans implements Externalizable {
handlers = new HashMap(); handlers = new HashMap();
} }
/**
* Creates a new ResponseTrans object.
*
* @param req ...
*/
public ResponseTrans(RequestTrans req) { public ResponseTrans(RequestTrans req) {
this(); this();
reqtrans = req; reqtrans = req;
} }
/** /**
* Get a value from the responses map by key. * Get a value from the responses map by key.
*/ */
@ -142,13 +162,14 @@ public final class ResponseTrans implements Externalizable {
return handlers; return handlers;
} }
/** /**
* Reset the response object to its initial empty state. * Reset the response object to its initial empty state.
*/ */
public void reset() { public void reset() {
if (buffer != null) if (buffer != null) {
buffer.setLength(0); buffer.setLength(0);
}
buffers = null; buffers = null;
response = null; response = null;
redir = null; redir = null;
@ -158,20 +179,25 @@ public final class ResponseTrans implements Externalizable {
lastModified = -1; lastModified = -1;
notModified = false; notModified = false;
etag = null; etag = null;
if (digest != null)
if (digest != null) {
digest.reset(); digest.reset();
} }
}
/** /**
* This is called before a skin is rendered as string (renderSkinAsString) to redirect the output * This is called before a skin is rendered as string (renderSkinAsString) to redirect the output
* to a new string buffer. * to a new string buffer.
*/ */
public void pushStringBuffer() { public void pushStringBuffer() {
if (buffers == null) if (buffers == null) {
buffers = new Stack(); buffers = new Stack();
if (buffer != null) }
if (buffer != null) {
buffers.push(buffer); buffers.push(buffer);
}
buffer = new StringBuffer(64); buffer = new StringBuffer(64);
} }
@ -180,7 +206,9 @@ public final class ResponseTrans implements Externalizable {
*/ */
public String popStringBuffer() { public String popStringBuffer() {
StringBuffer b = buffer; StringBuffer b = buffer;
buffer = buffers.empty() ? null : (StringBuffer) buffers.pop(); buffer = buffers.empty() ? null : (StringBuffer) buffers.pop();
return b.toString(); return b.toString();
} }
@ -188,11 +216,12 @@ public final class ResponseTrans implements Externalizable {
* Get the response buffer, creating it if it doesn't exist * Get the response buffer, creating it if it doesn't exist
*/ */
public StringBuffer getBuffer() { public StringBuffer getBuffer() {
if (buffer == null) if (buffer == null) {
buffer = new StringBuffer(INITIAL_BUFFER_SIZE); buffer = new StringBuffer(INITIAL_BUFFER_SIZE);
return buffer;
} }
return buffer;
}
/** /**
* Append a string to the response unchanged. This is often called * Append a string to the response unchanged. This is often called
@ -202,8 +231,11 @@ public final class ResponseTrans implements Externalizable {
public void write(Object what) { public void write(Object what) {
if (what != null) { if (what != null) {
String str = what.toString(); String str = what.toString();
if (buffer == null)
if (buffer == null) {
buffer = new StringBuffer(Math.max(str.length() + 100, INITIAL_BUFFER_SIZE)); buffer = new StringBuffer(Math.max(str.length() + 100, INITIAL_BUFFER_SIZE));
}
buffer.append(what.toString()); buffer.append(what.toString());
} }
} }
@ -212,10 +244,14 @@ public final class ResponseTrans implements Externalizable {
* Utility function that appends a <br> to whatever is written. * Utility function that appends a <br> to whatever is written.
*/ */
public void writeln(Object what) { public void writeln(Object what) {
if (buffer == null) if (buffer == null) {
buffer = new StringBuffer(INITIAL_BUFFER_SIZE); buffer = new StringBuffer(INITIAL_BUFFER_SIZE);
if (what != null) }
if (what != null) {
buffer.append(what.toString()); buffer.append(what.toString());
}
buffer.append("<br />\r\n"); buffer.append("<br />\r\n");
} }
@ -223,8 +259,10 @@ public final class ResponseTrans implements Externalizable {
* Append a part from a char array to the response buffer. * Append a part from a char array to the response buffer.
*/ */
public void writeCharArray(char[] c, int start, int length) { public void writeCharArray(char[] c, int start, int length) {
if (buffer == null) if (buffer == null) {
buffer = new StringBuffer(Math.max(length, INITIAL_BUFFER_SIZE)); buffer = new StringBuffer(Math.max(length, INITIAL_BUFFER_SIZE));
}
buffer.append(c, start, length); buffer.append(c, start, length);
} }
@ -234,9 +272,12 @@ public final class ResponseTrans implements Externalizable {
* case nothing happens. * case nothing happens.
*/ */
public void debug(Object message) { public void debug(Object message) {
if (debugBuffer == null) if (debugBuffer == null) {
debugBuffer = new StringBuffer(); debugBuffer = new StringBuffer();
String str = message == null ? "null" : message.toString (); }
String str = (message == null) ? "null" : message.toString();
debugBuffer.append("<p><span style=\"background: yellow; color: black\">"); debugBuffer.append("<p><span style=\"background: yellow; color: black\">");
debugBuffer.append(str); debugBuffer.append(str);
debugBuffer.append("</span></p>"); debugBuffer.append("</span></p>");
@ -249,8 +290,11 @@ public final class ResponseTrans implements Externalizable {
public void encode(Object what) { public void encode(Object what) {
if (what != null) { if (what != null) {
String str = what.toString(); String str = what.toString();
if (buffer == null)
if (buffer == null) {
buffer = new StringBuffer(Math.max(str.length() + 100, INITIAL_BUFFER_SIZE)); buffer = new StringBuffer(Math.max(str.length() + 100, INITIAL_BUFFER_SIZE));
}
HtmlEncoder.encodeAll(str, buffer); HtmlEncoder.encodeAll(str, buffer);
} }
} }
@ -261,13 +305,15 @@ public final class ResponseTrans implements Externalizable {
public void format(Object what) { public void format(Object what) {
if (what != null) { if (what != null) {
String str = what.toString(); String str = what.toString();
if (buffer == null)
if (buffer == null) {
buffer = new StringBuffer(Math.max(str.length() + 100, INITIAL_BUFFER_SIZE)); buffer = new StringBuffer(Math.max(str.length() + 100, INITIAL_BUFFER_SIZE));
}
HtmlEncoder.encode(str, buffer); HtmlEncoder.encode(str, buffer);
} }
} }
/** /**
* Replace special characters with entities, including <, > and ", thus allowing * Replace special characters with entities, including <, > and ", thus allowing
* no HTML tags. * no HTML tags.
@ -275,39 +321,62 @@ public final class ResponseTrans implements Externalizable {
public void encodeXml(Object what) { public void encodeXml(Object what) {
if (what != null) { if (what != null) {
String str = what.toString(); String str = what.toString();
if (buffer == null)
if (buffer == null) {
buffer = new StringBuffer(Math.max(str.length() + 100, INITIAL_BUFFER_SIZE)); buffer = new StringBuffer(Math.max(str.length() + 100, INITIAL_BUFFER_SIZE));
}
HtmlEncoder.encodeXml(str, buffer); HtmlEncoder.encodeXml(str, buffer);
} }
} }
/** /**
* Encode HTML entities, but leave newlines alone. This is for the content of textarea forms. * Encode HTML entities, but leave newlines alone. This is for the content of textarea forms.
*/ */
public void encodeForm(Object what) { public void encodeForm(Object what) {
if (what != null) { if (what != null) {
String str = what.toString(); String str = what.toString();
if (buffer == null)
if (buffer == null) {
buffer = new StringBuffer(Math.max(str.length() + 100, INITIAL_BUFFER_SIZE)); buffer = new StringBuffer(Math.max(str.length() + 100, INITIAL_BUFFER_SIZE));
}
HtmlEncoder.encodeAll(str, buffer, false); HtmlEncoder.encodeAll(str, buffer, false);
} }
} }
/**
*
*
* @param str ...
*/
public void append(String str) { public void append(String str) {
if (str != null) { if (str != null) {
if (buffer == null) if (buffer == null) {
buffer = new StringBuffer(Math.max(str.length(), INITIAL_BUFFER_SIZE)); buffer = new StringBuffer(Math.max(str.length(), INITIAL_BUFFER_SIZE));
}
buffer.append(str); buffer.append(str);
} }
} }
/**
*
*
* @param url ...
*
* @throws RedirectException ...
*/
public void redirect(String url) throws RedirectException { public void redirect(String url) throws RedirectException {
redir = url; redir = url;
throw new RedirectException(url); throw new RedirectException(url);
} }
/**
*
*
* @return ...
*/
public String getRedirect() { public String getRedirect() {
return redir; return redir;
} }
@ -321,28 +390,34 @@ public final class ResponseTrans implements Externalizable {
response = what; response = what;
} }
/** /**
* This has to be called after writing to this response has finished and before it is shipped back to the * This has to be called after writing to this response has finished and before it is shipped back to the
* web server. Transforms the string buffer into a char array to minimize size. * web server. Transforms the string buffer into a char array to minimize size.
*/ */
public synchronized void close(String cset) throws UnsupportedEncodingException { public synchronized void close(String cset) throws UnsupportedEncodingException {
// only use default charset if not explicitly set for this response. // only use default charset if not explicitly set for this response.
if (charset == null) if (charset == null) {
charset = cset; charset = cset;
}
// if charset is not set, use western encoding // if charset is not set, use western encoding
if (charset == null) if (charset == null) {
charset = "ISO-8859-1"; charset = "ISO-8859-1";
}
boolean encodingError = false; boolean encodingError = false;
// only close if the response hasn't been closed yet // only close if the response hasn't been closed yet
if (response == null) { if (response == null) {
// if debug buffer exists, append it to main buffer // if debug buffer exists, append it to main buffer
if (debugBuffer != null) { if (debugBuffer != null) {
if (buffer == null) if (buffer == null) {
buffer = debugBuffer; buffer = debugBuffer;
else } else {
buffer.append(debugBuffer); buffer.append(debugBuffer);
} }
}
// get the buffer's bytes in the specified encoding // get the buffer's bytes in the specified encoding
if (buffer != null) { if (buffer != null) {
try { try {
@ -351,31 +426,41 @@ public final class ResponseTrans implements Externalizable {
encodingError = true; encodingError = true;
response = buffer.toString().getBytes(); response = buffer.toString().getBytes();
} }
// make sure this is done only once, even with more requsts attached // make sure this is done only once, even with more requsts attached
buffer = null; buffer = null;
} else { } else {
response = new byte[0]; response = new byte[0];
} }
} }
// if etag is not set, calc MD5 digest and check it // if etag is not set, calc MD5 digest and check it
if (etag == null && lastModified == -1 && redir == null) try { if ((etag == null) && (lastModified == -1) && (redir == null)) {
try {
digest = MessageDigest.getInstance("MD5"); digest = MessageDigest.getInstance("MD5");
// if (contentType != null) // if (contentType != null)
// digest.update (contentType.getBytes()); // digest.update (contentType.getBytes());
byte[] b = digest.digest(response); byte[] b = digest.digest(response);
etag = "\"" + new String(Base64.encode(b)) + "\""; etag = "\"" + new String(Base64.encode(b)) + "\"";
if (reqtrans != null && reqtrans.hasETag (etag)) {
if ((reqtrans != null) && reqtrans.hasETag(etag)) {
response = new byte[0]; response = new byte[0];
notModified = true; notModified = true;
} }
} catch (Exception ignore) { } catch (Exception ignore) {
// Etag creation failed for some reason. Ignore. // Etag creation failed for some reason. Ignore.
} }
}
notifyAll(); notifyAll();
// if there was a problem with the encoding, let the app know // if there was a problem with the encoding, let the app know
if (encodingError) if (encodingError) {
throw new UnsupportedEncodingException(charset); throw new UnsupportedEncodingException(charset);
} }
}
/** /**
* If we just attached to evaluation we call this instead of close because only the primary thread * If we just attached to evaluation we call this instead of close because only the primary thread
@ -383,63 +468,118 @@ public final class ResponseTrans implements Externalizable {
*/ */
public synchronized void waitForClose() { public synchronized void waitForClose() {
try { try {
if (response == null) if (response == null) {
wait (10000l); wait(10000L);
} catch (InterruptedException ix) {} }
} catch (InterruptedException ix) {
}
} }
/**
*
*
* @return ...
*/
public byte[] getContent() { public byte[] getContent() {
return response == null ? new byte[0] : response; return (response == null) ? new byte[0] : response;
} }
/**
*
*
* @return ...
*/
public int getContentLength() { public int getContentLength() {
if (response != null) if (response != null) {
return response.length; return response.length;
}
return 0; return 0;
} }
/**
*
*
* @return ...
*/
public String getContentType() { public String getContentType() {
if (charset != null) if (charset != null) {
return contentType + "; charset=" + charset; return contentType + "; charset=" + charset;
}
return contentType; return contentType;
} }
/**
*
*
* @param modified ...
*/
public void setLastModified(long modified) { public void setLastModified(long modified) {
if (modified > -1 && reqtrans != null && if ((modified > -1) && (reqtrans != null) &&
reqtrans.getIfModifiedSince() >= modified) (reqtrans.getIfModifiedSince() >= modified)) {
{
notModified = true; notModified = true;
throw new RedirectException(null); throw new RedirectException(null);
} }
lastModified = modified; lastModified = modified;
} }
/**
*
*
* @return ...
*/
public long getLastModified() { public long getLastModified() {
return lastModified; return lastModified;
} }
/**
*
*
* @param value ...
*/
public void setETag(String value) { public void setETag(String value) {
etag = value == null ? null : "\""+value+"\""; etag = (value == null) ? null : ("\"" + value + "\"");
if (etag != null && reqtrans != null && reqtrans.hasETag (etag)) {
if ((etag != null) && (reqtrans != null) && reqtrans.hasETag(etag)) {
notModified = true; notModified = true;
throw new RedirectException(null); throw new RedirectException(null);
} }
} }
/**
*
*
* @return ...
*/
public String getETag() { public String getETag() {
return etag; return etag;
} }
/**
*
*
* @return ...
*/
public boolean getNotModified() { public boolean getNotModified() {
return notModified; return notModified;
} }
/**
*
*
* @param what ...
*/
public void dependsOn(Object what) { public void dependsOn(Object what) {
if (digest == null) try { if (digest == null) {
try {
digest = MessageDigest.getInstance("MD5"); digest = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException nsa) { } catch (NoSuchAlgorithmException nsa) {
// MD5 should always be available // MD5 should always be available
} }
}
if (what == null) { if (what == null) {
digest.update(new byte[0]); digest.update(new byte[0]);
} else if (what instanceof Date) { } else if (what instanceof Date) {
@ -448,17 +588,25 @@ public final class ResponseTrans implements Externalizable {
digest.update((byte[]) what); digest.update((byte[]) what);
} else { } else {
String str = what.toString(); String str = what.toString();
if (str != null)
if (str != null) {
digest.update(str.getBytes()); digest.update(str.getBytes());
else } else {
digest.update(new byte[0]); digest.update(new byte[0]);
} }
} }
}
/**
*
*/
public void digestDependencies() { public void digestDependencies() {
if (digest == null) if (digest == null) {
return; return;
}
byte[] b = digest.digest(MD5Encoder.toBytes(applicationChecksum)); byte[] b = digest.digest(MD5Encoder.toBytes(applicationChecksum));
/* StringBuffer buf = new StringBuffer(b.length*2); /* StringBuffer buf = new StringBuffer(b.length*2);
for ( int i=0; i<b.length; i++ ) { for ( int i=0; i<b.length; i++ ) {
int j = (b[i]<0) ? 256+b[i] : b[i]; int j = (b[i]<0) ? 256+b[i] : b[i];
@ -469,71 +617,144 @@ public final class ResponseTrans implements Externalizable {
setETag(new String(Base64.encode(b))); setETag(new String(Base64.encode(b)));
} }
/**
*
*
* @param n ...
*/
public void setApplicationChecksum(long n) { public void setApplicationChecksum(long n) {
applicationChecksum = n; applicationChecksum = n;
} }
/**
*
*
* @param arr ...
*/
public void setSkinpath(Object[] arr) { public void setSkinpath(Object[] arr) {
this.skinpath = arr; this.skinpath = arr;
skincache = null; skincache = null;
} }
/**
*
*
* @return ...
*/
public Object[] getSkinpath() { public Object[] getSkinpath() {
if (skinpath == null) if (skinpath == null) {
skinpath = new Object[0]; skinpath = new Object[0];
}
return skinpath; return skinpath;
} }
/**
*
*
* @param id ...
*
* @return ...
*/
public Skin getCachedSkin(String id) { public Skin getCachedSkin(String id) {
if (skincache == null) if (skincache == null) {
return null; return null;
}
return (Skin) skincache.get(id); return (Skin) skincache.get(id);
} }
/**
*
*
* @param id ...
* @param skin ...
*/
public void cacheSkin(String id, Skin skin) { public void cacheSkin(String id, Skin skin) {
if (skincache == null) if (skincache == null) {
skincache = new HashMap(); skincache = new HashMap();
}
skincache.put(id, skin); skincache.put(id, skin);
} }
/**
*
*
* @param key ...
* @param value ...
* @param days ...
* @param path ...
* @param domain ...
*/
public void setCookie(String key, String value, int days, String path, String domain) { public void setCookie(String key, String value, int days, String path, String domain) {
CookieTrans c = null; CookieTrans c = null;
if (cookies == null) { if (cookies == null) {
cookies = new HashMap(); cookies = new HashMap();
} else { } else {
c = (CookieTrans) cookies.get(key); c = (CookieTrans) cookies.get(key);
} }
if (c == null) { if (c == null) {
c = new CookieTrans(key, value); c = new CookieTrans(key, value);
cookies.put(key, c); cookies.put(key, c);
} else { } else {
c.setValue(value); c.setValue(value);
} }
c.setDays(days); c.setDays(days);
c.setPath(path); c.setPath(path);
c.setDomain(domain); c.setDomain(domain);
} }
/**
*
*/
public void resetCookies() { public void resetCookies() {
if (cookies != null) if (cookies != null) {
cookies.clear(); cookies.clear();
} }
}
/**
*
*
* @return ...
*/
public int countCookies() { public int countCookies() {
if (cookies != null) if (cookies != null) {
return cookies.size(); return cookies.size();
}
return 0; return 0;
} }
/**
*
*
* @return ...
*/
public CookieTrans[] getCookies() { public CookieTrans[] getCookies() {
if (cookies == null) if (cookies == null) {
return new CookieTrans[0]; return new CookieTrans[0];
}
CookieTrans[] c = new CookieTrans[cookies.size()]; CookieTrans[] c = new CookieTrans[cookies.size()];
cookies.values().toArray(c); cookies.values().toArray(c);
return c; return c;
} }
/**
*
*
* @param s ...
*
* @throws ClassNotFoundException ...
* @throws IOException ...
*/
public void readExternal(ObjectInput s) throws ClassNotFoundException, IOException { public void readExternal(ObjectInput s) throws ClassNotFoundException, IOException {
contentType = (String) s.readObject(); contentType = (String) s.readObject();
response = (byte[]) s.readObject(); response = (byte[]) s.readObject();
@ -548,6 +769,13 @@ public final class ResponseTrans implements Externalizable {
etag = (String) s.readObject(); etag = (String) s.readObject();
} }
/**
*
*
* @param s ...
*
* @throws IOException ...
*/
public void writeExternal(ObjectOutput s) throws IOException { public void writeExternal(ObjectOutput s) throws IOException {
s.writeObject(contentType); s.writeObject(contentType);
s.writeObject(response); s.writeObject(response);
@ -561,7 +789,4 @@ public final class ResponseTrans implements Externalizable {
s.writeObject(charset); s.writeObject(charset);
s.writeObject(etag); s.writeObject(etag);
} }
} }

View file

@ -1,18 +1,31 @@
// TimeoutException.java /*
// Copyright (c) Hannes Wallnöfer 1998-2000 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.framework; package helma.framework;
/** /**
* TimeoutException is thrown by the request evaluator when a request could * TimeoutException is thrown by the request evaluator when a request could
* not be serviced within the timeout period specified for an application. * not be serviced within the timeout period specified for an application.
*/ */
public class TimeoutException extends RuntimeException { public class TimeoutException extends RuntimeException {
/**
* Creates a new TimeoutException object.
*/
public TimeoutException() { public TimeoutException() {
super("Request timed out"); super("Request timed out");
} }
} }

View file

@ -1,21 +1,33 @@
// ApplicationClassLoader.java /*
* Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.framework.core; package helma.framework.core;
import java.net.URL; import java.net.URL;
import java.net.URLClassLoader; import java.net.URLClassLoader;
import java.util.Enumeration;
import java.security.CodeSource; import java.security.CodeSource;
import java.security.Permission; import java.security.Permission;
import java.security.PermissionCollection; import java.security.PermissionCollection;
import java.security.Permissions; import java.security.Permissions;
import java.util.Enumeration;
/** /**
* ClassLoader subclass with package accessible addURL method. * ClassLoader subclass with package accessible addURL method.
*/ */
public class AppClassLoader extends URLClassLoader { public class AppClassLoader extends URLClassLoader {
private final String appname; private final String appname;
/** /**
@ -30,8 +42,12 @@ public class AppClassLoader extends URLClassLoader {
super.addURL(url); super.addURL(url);
} }
/**
*
*
* @return ...
*/
public String getAppName() { public String getAppName() {
return appname; return appname;
} }
} }

File diff suppressed because it is too large Load diff

View file

@ -1,215 +1,448 @@
/*
* Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.framework.core; package helma.framework.core;
import java.io.Serializable; import helma.objectmodel.INode;
import java.io.File; import java.io.File;
import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map;
import java.util.List; import java.util.List;
import java.util.Map;
import helma.objectmodel.INode; /**
*
*/
public class ApplicationBean implements Serializable { public class ApplicationBean implements Serializable {
Application app; Application app;
/**
* Creates a new ApplicationBean object.
*
* @param app ...
*/
public ApplicationBean(Application app) { public ApplicationBean(Application app) {
this.app = app; this.app = app;
} }
/**
*
*/
public void clearCache() { public void clearCache() {
app.clearCache(); app.clearCache();
} }
/**
*
*
* @param msg ...
*/
public void log(Object msg) { public void log(Object msg) {
String str = msg == null ? "null" : msg.toString(); String str = (msg == null) ? "null" : msg.toString();
app.logEvent(str); app.logEvent(str);
} }
/**
*
*
* @param logname ...
* @param msg ...
*/
public void log(String logname, Object msg) { public void log(String logname, Object msg) {
String str = msg == null ? "null" : msg.toString(); String str = (msg == null) ? "null" : msg.toString();
app.getLogger(logname).log(str); app.getLogger(logname).log(str);
} }
/**
*
*
* @param msg ...
*/
public void debug(Object msg) { public void debug(Object msg) {
if (app.debug()) { if (app.debug()) {
String str = msg == null ? "null" : msg.toString(); String str = (msg == null) ? "null" : msg.toString();
app.logEvent(str); app.logEvent(str);
} }
} }
/**
*
*
* @param logname ...
* @param msg ...
*/
public void debug(String logname, Object msg) { public void debug(String logname, Object msg) {
if (app.debug()) { if (app.debug()) {
String str = msg == null ? "null" : msg.toString(); String str = (msg == null) ? "null" : msg.toString();
app.getLogger(logname).log(str); app.getLogger(logname).log(str);
} }
} }
/**
*
*
* @return ...
*/
public int countSessions() { public int countSessions() {
return app.sessions.size(); return app.sessions.size();
} }
/**
*
*
* @param sessionID ...
*
* @return ...
*/
public SessionBean getSession(String sessionID) { public SessionBean getSession(String sessionID) {
if (sessionID==null) if (sessionID == null) {
return null; return null;
}
Session session = app.getSession(sessionID.trim()); Session session = app.getSession(sessionID.trim());
if (session == null)
if (session == null) {
return null; return null;
}
return new SessionBean(session); return new SessionBean(session);
} }
/**
*
*
* @param sessionID ...
*
* @return ...
*/
public SessionBean createSession(String sessionID) { public SessionBean createSession(String sessionID) {
if (sessionID==null) if (sessionID == null) {
return null; return null;
}
Session session = session = app.checkSession(sessionID.trim()); Session session = session = app.checkSession(sessionID.trim());
if (session == null)
if (session == null) {
return null; return null;
}
return new SessionBean(session); return new SessionBean(session);
} }
/**
*
*
* @return ...
*/
public SessionBean[] getSessions() { public SessionBean[] getSessions() {
SessionBean[] theArray = new SessionBean[app.sessions.size()]; SessionBean[] theArray = new SessionBean[app.sessions.size()];
int i = 0; int i = 0;
for (Enumeration e = app.sessions.elements(); e.hasMoreElements();) { for (Enumeration e = app.sessions.elements(); e.hasMoreElements();) {
SessionBean sb = new SessionBean((Session) e.nextElement()); SessionBean sb = new SessionBean((Session) e.nextElement());
theArray[i++] = sb; theArray[i++] = sb;
} }
return theArray; return theArray;
} }
/**
*
*
* @param username ...
* @param password ...
*
* @return ...
*/
public INode registerUser(String username, String password) { public INode registerUser(String username, String password) {
if (username==null || password==null || "".equals (username.trim ()) || "".equals (password.trim ()) ) if ((username == null) || (password == null) || "".equals(username.trim()) ||
"".equals(password.trim())) {
return null; return null;
else } else {
return app.registerUser(username, password); return app.registerUser(username, password);
} }
}
/**
*
*
* @param username ...
*
* @return ...
*/
public INode getUser(String username) { public INode getUser(String username) {
if (username==null || "".equals (username.trim()) ) if ((username == null) || "".equals(username.trim())) {
return null; return null;
}
return app.getUserNode(username); return app.getUserNode(username);
} }
/**
*
*
* @return ...
*/
public INode[] getActiveUsers() { public INode[] getActiveUsers() {
List activeUsers = app.getActiveUsers(); List activeUsers = app.getActiveUsers();
return (INode[]) activeUsers.toArray(new INode[0]); return (INode[]) activeUsers.toArray(new INode[0]);
} }
/**
*
*
* @return ...
*/
public INode[] getRegisteredUsers() { public INode[] getRegisteredUsers() {
List registeredUsers = app.getRegisteredUsers(); List registeredUsers = app.getRegisteredUsers();
return (INode[]) registeredUsers.toArray(new INode[0]); return (INode[]) registeredUsers.toArray(new INode[0]);
} }
/**
*
*
* @param usernode ...
*
* @return ...
*/
public SessionBean[] getSessionsForUser(INode usernode) { public SessionBean[] getSessionsForUser(INode usernode) {
if (usernode==null) if (usernode == null) {
return new SessionBean[0]; return new SessionBean[0];
else } else {
return getSessionsForUser(usernode.getName()); return getSessionsForUser(usernode.getName());
} }
}
/**
*
*
* @param username ...
*
* @return ...
*/
public SessionBean[] getSessionsForUser(String username) { public SessionBean[] getSessionsForUser(String username) {
if (username==null || "".equals (username.trim ()) ) if ((username == null) || "".equals(username.trim())) {
return new SessionBean[0]; return new SessionBean[0];
}
List userSessions = app.getSessionsForUsername(username); List userSessions = app.getSessionsForUsername(username);
return (SessionBean[]) userSessions.toArray(new SessionBean[0]); return (SessionBean[]) userSessions.toArray(new SessionBean[0]);
} }
// getter methods for readonly properties of this application // getter methods for readonly properties of this application
public int getcacheusage() { public int getcacheusage() {
return app.getCacheUsage(); return app.getCacheUsage();
} }
/**
*
*
* @return ...
*/
public INode getdata() { public INode getdata() {
return app.getCacheNode(); return app.getCacheNode();
} }
/**
*
*
* @return ...
*/
public Map getmodules() { public Map getmodules() {
return app.modules; return app.modules;
} }
/**
*
*
* @return ...
*/
public String getdir() { public String getdir() {
return app.getAppDir().getAbsolutePath(); return app.getAppDir().getAbsolutePath();
} }
/**
*
*
* @return ...
*/
public Date getupSince() { public Date getupSince() {
return new Date(app.starttime); return new Date(app.starttime);
} }
/**
*
*
* @return ...
*/
public long getrequestCount() { public long getrequestCount() {
return app.getRequestCount(); return app.getRequestCount();
} }
/**
*
*
* @return ...
*/
public long getxmlrpcCount() { public long getxmlrpcCount() {
return app.getXmlrpcCount(); return app.getXmlrpcCount();
} }
/**
*
*
* @return ...
*/
public long geterrorCount() { public long geterrorCount() {
return app.getErrorCount(); return app.getErrorCount();
} }
/**
*
*
* @return ...
*/
public Application get__app__() { public Application get__app__() {
return app; return app;
} }
/**
*
*
* @return ...
*/
public Map getproperties() { public Map getproperties() {
return app.getProperties(); return app.getProperties();
} }
/**
*
*
* @return ...
*/
public int getfreeThreads() { public int getfreeThreads() {
return app.countFreeEvaluators(); return app.countFreeEvaluators();
} }
/**
*
*
* @return ...
*/
public int getactiveThreads() { public int getactiveThreads() {
return app.countActiveEvaluators(); return app.countActiveEvaluators();
} }
/**
*
*
* @return ...
*/
public int getmaxThreads() { public int getmaxThreads() {
return app.countEvaluators(); return app.countEvaluators();
} }
/**
*
*
* @param n ...
*/
public void setmaxThreads(int n) { public void setmaxThreads(int n) {
// add one to the number to compensate for the internal scheduler. // add one to the number to compensate for the internal scheduler.
app.setNumberOfEvaluators(n + 1); app.setNumberOfEvaluators(n + 1);
} }
/**
*
*
* @return ...
*/
public Map getSkinfiles() { public Map getSkinfiles() {
Map skinz = new HashMap(); Map skinz = new HashMap();
for (Iterator it = app.getPrototypes().iterator(); it.hasNext();) { for (Iterator it = app.getPrototypes().iterator(); it.hasNext();) {
Prototype p = (Prototype) it.next(); Prototype p = (Prototype) it.next();
skinz.put(p.getName(), p.getSkinMap()); skinz.put(p.getName(), p.getSkinMap());
} }
return skinz; return skinz;
} }
/**
*
*
* @param skinpath ...
*
* @return ...
*/
public Map getSkinfiles(Object[] skinpath) { public Map getSkinfiles(Object[] skinpath) {
Map skinz = new HashMap(); Map skinz = new HashMap();
for (Iterator it = app.getPrototypes().iterator(); it.hasNext();) { for (Iterator it = app.getPrototypes().iterator(); it.hasNext();) {
Prototype p = (Prototype) it.next(); Prototype p = (Prototype) it.next();
skinz.put(p.getName(), p.getSkinMap(skinpath)); skinz.put(p.getName(), p.getSkinMap(skinpath));
} }
return skinz; return skinz;
} }
/**
*
*
* @return ...
*/
public String getAppDir() { public String getAppDir() {
return app.getAppDir().getAbsolutePath(); return app.getAppDir().getAbsolutePath();
} }
/**
*
*
* @return ...
*/
public String getServerDir() { public String getServerDir() {
File f = app.getServerDir(); File f = app.getServerDir();
if (f == null)
if (f == null) {
f = app.getAppDir(); f = app.getAppDir();
}
return f.getAbsolutePath(); return f.getAbsolutePath();
} }
/**
*
*
* @return ...
*/
public String toString() { public String toString() {
return "[Application " + app.getName() + "]"; return "[Application " + app.getName() + "]";
} }
} }

View file

@ -1,16 +1,28 @@
// Prototype.java /*
// Copyright (c) Hannes Wallnöfer 1998-2000 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.framework.core; package helma.framework.core;
import java.util.*;
import java.io.*;
import helma.framework.*; import helma.framework.*;
import helma.scripting.*;
import helma.objectmodel.*; import helma.objectmodel.*;
import helma.objectmodel.db.DbMapping; import helma.objectmodel.db.DbMapping;
import helma.scripting.*;
import helma.util.Updatable; import helma.util.Updatable;
import java.io.*;
import java.util.*;
/** /**
* The Prototype class represents Script prototypes/type defined in a Helma * The Prototype class represents Script prototypes/type defined in a Helma
@ -18,40 +30,43 @@ import helma.util.Updatable;
* as well as optional information about the mapping of this type to a * as well as optional information about the mapping of this type to a
* relational database table. * relational database table.
*/ */
public final class Prototype { public final class Prototype {
String name; String name;
Application app; Application app;
File directory; File directory;
File[] files; File[] files;
long lastDirectoryListing; long lastDirectoryListing;
long checksum; long checksum;
HashMap code;
HashMap code, zippedCode; HashMap zippedCode;
HashMap skins, zippedSkins; HashMap skins;
HashMap zippedSkins;
HashMap updatables; HashMap updatables;
// a map of this prototype's skins as raw strings // a map of this prototype's skins as raw strings
// used for exposing skins to application (script) code (via app.skinfiles). // used for exposing skins to application (script) code (via app.skinfiles).
SkinMap skinMap; SkinMap skinMap;
DbMapping dbmap; DbMapping dbmap;
// lastCheck is the time the prototype's files were last checked // lastCheck is the time the prototype's files were last checked
private long lastChecksum; private long lastChecksum;
// lastUpdate is the time at which any of the prototype's files were // lastUpdate is the time at which any of the prototype's files were
// found updated the last time // found updated the last time
private long lastUpdate; private long lastUpdate;
private Prototype parent; private Prototype parent;
// Tells us whether this prototype is used to script a generic Java object, // Tells us whether this prototype is used to script a generic Java object,
// as opposed to a Helma objectmodel node object. // as opposed to a Helma objectmodel node object.
boolean isJavaPrototype; boolean isJavaPrototype;
/**
* Creates a new Prototype object.
*
* @param name ...
* @param dir ...
* @param app ...
*/
public Prototype(String name, File dir, Application app) { public Prototype(String name, File dir, Application app) {
// app.logEvent ("Constructing Prototype "+app.getName()+"/"+name); // app.logEvent ("Constructing Prototype "+app.getName()+"/"+name);
this.app = app; this.app = app;
@ -88,12 +103,15 @@ public final class Prototype {
* Get the list of files in this prototype's directory * Get the list of files in this prototype's directory
*/ */
public File[] getFiles() { public File[] getFiles() {
if (files == null || directory.lastModified() != lastDirectoryListing) { if ((files == null) || (directory.lastModified() != lastDirectoryListing)) {
lastDirectoryListing = directory.lastModified(); lastDirectoryListing = directory.lastModified();
files = directory.listFiles(); files = directory.listFiles();
if (files == null)
if (files == null) {
files = new File[0]; files = new File[0];
} }
}
return files; return files;
} }
@ -104,13 +122,21 @@ public final class Prototype {
// long start = System.currentTimeMillis(); // long start = System.currentTimeMillis();
File[] f = getFiles(); File[] f = getFiles();
long c = 0; long c = 0;
for (int i = 0; i < f.length; i++) for (int i = 0; i < f.length; i++)
c += f[i].lastModified(); c += f[i].lastModified();
checksum = c; checksum = c;
// System.err.println ("CHECKSUM "+name+": "+(System.currentTimeMillis()-start)); // System.err.println ("CHECKSUM "+name+": "+(System.currentTimeMillis()-start));
return checksum; return checksum;
} }
/**
*
*
* @return ...
*/
public boolean isUpToDate() { public boolean isUpToDate() {
return checksum == lastChecksum; return checksum == lastChecksum;
} }
@ -121,8 +147,10 @@ public final class Prototype {
*/ */
public void setParentPrototype(Prototype parent) { public void setParentPrototype(Prototype parent) {
// this is not allowed for the hopobject and global prototypes // this is not allowed for the hopobject and global prototypes
if ("hopobject".equalsIgnoreCase (name) || "global".equalsIgnoreCase (name)) if ("hopobject".equalsIgnoreCase(name) || "global".equalsIgnoreCase(name)) {
return; return;
}
this.parent = parent; this.parent = parent;
} }
@ -138,10 +166,14 @@ public final class Prototype {
* Check if the given prototype is within this prototype's parent chain. * Check if the given prototype is within this prototype's parent chain.
*/ */
public final boolean isInstanceOf(String pname) { public final boolean isInstanceOf(String pname) {
if (name.equals (pname)) if (name.equals(pname)) {
return true; return true;
if (parent != null && !"hopobject".equalsIgnoreCase (parent.getName())) }
if ((parent != null) && !"hopobject".equalsIgnoreCase(parent.getName())) {
return parent.isInstanceOf(pname); return parent.isInstanceOf(pname);
}
return false; return false;
} }
@ -149,20 +181,31 @@ public final class Prototype {
* Register an object as handler for this prototype and all our parent prototypes. * Register an object as handler for this prototype and all our parent prototypes.
*/ */
public final void addToHandlerMap(Map handlers, Object obj) { public final void addToHandlerMap(Map handlers, Object obj) {
if (parent != null && !"hopobject".equalsIgnoreCase (parent.getName())) if ((parent != null) && !"hopobject".equalsIgnoreCase(parent.getName())) {
parent.addToHandlerMap(handlers, obj); parent.addToHandlerMap(handlers, obj);
}
handlers.put(name, obj); handlers.put(name, obj);
} }
/**
*
*
* @param dbmap ...
*/
public void setDbMapping(DbMapping dbmap) { public void setDbMapping(DbMapping dbmap) {
this.dbmap = dbmap; this.dbmap = dbmap;
} }
/**
*
*
* @return ...
*/
public DbMapping getDbMapping() { public DbMapping getDbMapping() {
return dbmap; return dbmap;
} }
/** /**
* Get a Skinfile for this prototype. This only works for skins * Get a Skinfile for this prototype. This only works for skins
* residing in the prototype directory, not for skin files in * residing in the prototype directory, not for skin files in
@ -170,8 +213,11 @@ public final class Prototype {
*/ */
public SkinFile getSkinFile(String sfname) { public SkinFile getSkinFile(String sfname) {
SkinFile sf = (SkinFile) skins.get(sfname); SkinFile sf = (SkinFile) skins.get(sfname);
if (sf == null)
if (sf == null) {
sf = (SkinFile) zippedSkins.get(sfname); sf = (SkinFile) zippedSkins.get(sfname);
}
return sf; return sf;
} }
@ -182,18 +228,23 @@ public final class Prototype {
*/ */
public Skin getSkin(String sfname) { public Skin getSkin(String sfname) {
SkinFile sf = getSkinFile(sfname); SkinFile sf = getSkinFile(sfname);
if (sf != null)
if (sf != null) {
return sf.getSkin(); return sf.getSkin();
else } else {
return null; return null;
} }
}
/**
*
*
* @return ...
*/
public String getName() { public String getName() {
return name; return name;
} }
/** /**
* Get the last time any script has been re-read for this prototype. * Get the last time any script has been re-read for this prototype.
*/ */
@ -214,6 +265,7 @@ public final class Prototype {
* Get the time at which this prototype's scripts were checked * Get the time at which this prototype's scripts were checked
* for changes for the last time. * for changes for the last time.
*/ */
/* public long getLastCheck () { /* public long getLastCheck () {
return lastCheck; return lastCheck;
} */ } */
@ -227,7 +279,6 @@ public final class Prototype {
lastChecksum = checksum; lastChecksum = checksum;
} }
/** /**
* Return a clone of this prototype's actions container. Synchronized * Return a clone of this prototype's actions container. Synchronized
* to not return a map in a transient state where it is just being * to not return a map in a transient state where it is just being
@ -246,9 +297,14 @@ public final class Prototype {
return (Map) zippedCode.clone(); return (Map) zippedCode.clone();
} }
/**
*
*
* @param action ...
*/
public synchronized void addActionFile(ActionFile action) { public synchronized void addActionFile(ActionFile action) {
File f = action.getFile(); File f = action.getFile();
if (f != null) { if (f != null) {
code.put(action.getSourceName(), action); code.put(action.getSourceName(), action);
updatables.put(f.getName(), action); updatables.put(f.getName(), action);
@ -257,8 +313,14 @@ public final class Prototype {
} }
} }
/**
*
*
* @param template ...
*/
public synchronized void addTemplate(Template template) { public synchronized void addTemplate(Template template) {
File f = template.getFile(); File f = template.getFile();
if (f != null) { if (f != null) {
code.put(template.getSourceName(), template); code.put(template.getSourceName(), template);
updatables.put(f.getName(), template); updatables.put(f.getName(), template);
@ -267,8 +329,14 @@ public final class Prototype {
} }
} }
/**
*
*
* @param funcfile ...
*/
public synchronized void addFunctionFile(FunctionFile funcfile) { public synchronized void addFunctionFile(FunctionFile funcfile) {
File f = funcfile.getFile(); File f = funcfile.getFile();
if (f != null) { if (f != null) {
code.put(funcfile.getSourceName(), funcfile); code.put(funcfile.getSourceName(), funcfile);
updatables.put(f.getName(), funcfile); updatables.put(f.getName(), funcfile);
@ -277,8 +345,14 @@ public final class Prototype {
} }
} }
/**
*
*
* @param skinfile ...
*/
public synchronized void addSkinFile(SkinFile skinfile) { public synchronized void addSkinFile(SkinFile skinfile) {
File f = skinfile.getFile(); File f = skinfile.getFile();
if (f != null) { if (f != null) {
skins.put(skinfile.getName(), skinfile); skins.put(skinfile.getName(), skinfile);
updatables.put(f.getName(), skinfile); updatables.put(f.getName(), skinfile);
@ -287,9 +361,14 @@ public final class Prototype {
} }
} }
/**
*
*
* @param action ...
*/
public synchronized void removeActionFile(ActionFile action) { public synchronized void removeActionFile(ActionFile action) {
File f = action.getFile(); File f = action.getFile();
if (f != null) { if (f != null) {
code.remove(action.getSourceName()); code.remove(action.getSourceName());
updatables.remove(f.getName()); updatables.remove(f.getName());
@ -298,8 +377,14 @@ public final class Prototype {
} }
} }
/**
*
*
* @param funcfile ...
*/
public synchronized void removeFunctionFile(FunctionFile funcfile) { public synchronized void removeFunctionFile(FunctionFile funcfile) {
File f = funcfile.getFile(); File f = funcfile.getFile();
if (f != null) { if (f != null) {
code.remove(funcfile.getSourceName()); code.remove(funcfile.getSourceName());
updatables.remove(f.getName()); updatables.remove(f.getName());
@ -308,8 +393,14 @@ public final class Prototype {
} }
} }
/**
*
*
* @param template ...
*/
public synchronized void removeTemplate(Template template) { public synchronized void removeTemplate(Template template) {
File f = template.getFile(); File f = template.getFile();
if (f != null) { if (f != null) {
code.remove(template.getSourceName()); code.remove(template.getSourceName());
updatables.remove(f.getName()); updatables.remove(f.getName());
@ -318,8 +409,14 @@ public final class Prototype {
} }
} }
/**
*
*
* @param skinfile ...
*/
public synchronized void removeSkinFile(SkinFile skinfile) { public synchronized void removeSkinFile(SkinFile skinfile) {
File f = skinfile.getFile(); File f = skinfile.getFile();
if (f != null) { if (f != null) {
skins.remove(skinfile.getName()); skins.remove(skinfile.getName());
updatables.remove(f.getName()); updatables.remove(f.getName());
@ -328,7 +425,6 @@ public final class Prototype {
} }
} }
/** /**
* Return a string representing this prototype. * Return a string representing this prototype.
*/ */
@ -336,7 +432,11 @@ public final class Prototype {
return "[Prototype " + app.getName() + "/" + name + "]"; return "[Prototype " + app.getName() + "/" + name + "]";
} }
/**
*
*
* @return ...
*/
public SkinMap getSkinMap() { public SkinMap getSkinMap() {
return skinMap; return skinMap;
} }
@ -348,9 +448,7 @@ public final class Prototype {
// a map that dynamically expands to all skins in this prototype // a map that dynamically expands to all skins in this prototype
final class SkinMap extends HashMap { final class SkinMap extends HashMap {
long lastSkinmapLoad = 0; long lastSkinmapLoad = 0;
Object[] skinpath; Object[] skinpath;
SkinMap() { SkinMap() {
@ -365,46 +463,59 @@ public final class Prototype {
public boolean containsKey(Object key) { public boolean containsKey(Object key) {
checkForUpdates(); checkForUpdates();
return super.containsKey(key); return super.containsKey(key);
} }
public boolean containsValue(Object value) { public boolean containsValue(Object value) {
checkForUpdates(); checkForUpdates();
return super.containsValue(value); return super.containsValue(value);
} }
public Set entrySet() { public Set entrySet() {
checkForUpdates(); checkForUpdates();
return super.entrySet(); return super.entrySet();
} }
public boolean equals(Object obj) { public boolean equals(Object obj) {
checkForUpdates(); checkForUpdates();
return super.equals(obj); return super.equals(obj);
} }
public Object get(Object key) { public Object get(Object key) {
if (key == null) if (key == null) {
return null; return null;
}
checkForUpdates(); checkForUpdates();
SkinFile sf = (SkinFile) super.get(key); SkinFile sf = (SkinFile) super.get(key);
if (sf == null)
if (sf == null) {
return null; return null;
}
return sf.getSkin().getSource(); return sf.getSkin().getSource();
} }
public int hashCode() { public int hashCode() {
checkForUpdates(); checkForUpdates();
return super.hashCode(); return super.hashCode();
} }
public boolean isEmpty() { public boolean isEmpty() {
checkForUpdates(); checkForUpdates();
return super.isEmpty(); return super.isEmpty();
} }
public Set keySet() { public Set keySet() {
checkForUpdates(); checkForUpdates();
return super.keySet(); return super.keySet();
} }
@ -420,54 +531,66 @@ public final class Prototype {
public Object remove(Object key) { public Object remove(Object key) {
checkForUpdates(); checkForUpdates();
return super.remove(key); return super.remove(key);
} }
public int size() { public int size() {
checkForUpdates(); checkForUpdates();
return super.size(); return super.size();
} }
public Collection values() { public Collection values() {
checkForUpdates(); checkForUpdates();
return super.values(); return super.values();
} }
private void checkForUpdates() { private void checkForUpdates() {
if (/* lastCheck < System.currentTimeMillis()- 2000l*/ !isUpToDate()) if ( /* lastCheck < System.currentTimeMillis()- 2000l*/
!isUpToDate()) {
app.typemgr.updatePrototype(Prototype.this); app.typemgr.updatePrototype(Prototype.this);
if (lastUpdate > lastSkinmapLoad) }
if (lastUpdate > lastSkinmapLoad) {
load(); load();
} }
}
private synchronized void load() { private synchronized void load() {
if (lastUpdate == lastSkinmapLoad) if (lastUpdate == lastSkinmapLoad) {
return; return;
}
super.clear(); super.clear();
// System.err.println ("LOADING SKIN VALUES: "+Prototype.this); // System.err.println ("LOADING SKIN VALUES: "+Prototype.this);
for (Iterator i = skins.entrySet().iterator(); i.hasNext();) { for (Iterator i = skins.entrySet().iterator(); i.hasNext();) {
Map.Entry e = (Map.Entry) i.next(); Map.Entry e = (Map.Entry) i.next();
super.put(e.getKey(), e.getValue()); super.put(e.getKey(), e.getValue());
} }
// if skinpath is not null, overload/add skins from there // if skinpath is not null, overload/add skins from there
if (skinpath != null) { if (skinpath != null) {
for (int i = skinpath.length - 1; i >= 0; i--) { for (int i = skinpath.length - 1; i >= 0; i--) {
if (skinpath[i] != null && skinpath[i] instanceof String) { if ((skinpath[i] != null) && skinpath[i] instanceof String) {
Map m = app.skinmgr.getSkinFiles ((String) skinpath[i], Prototype.this); Map m = app.skinmgr.getSkinFiles((String) skinpath[i],
if (m != null) Prototype.this);
if (m != null) {
super.putAll(m); super.putAll(m);
} }
} }
} }
}
lastSkinmapLoad = lastUpdate; lastSkinmapLoad = lastUpdate;
} }
public String toString() { public String toString() {
return "[SkinMap " + name + "]"; return "[SkinMap " + name + "]";
} }
} }
} }

View file

@ -1,5 +1,18 @@
// RemoteApplication.java /*
// Copyright (c) Hannes Wallnöfer 2002 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.framework.core; package helma.framework.core;
@ -12,19 +25,21 @@ import java.util.Vector;
/** /**
* Proxy class for Aplication that listens to requests via RMI. * Proxy class for Aplication that listens to requests via RMI.
*/ */
public class RemoteApplication extends UnicastRemoteObject implements IRemoteApp,
public class RemoteApplication IReplicationListener {
extends UnicastRemoteObject
implements IRemoteApp, IReplicationListener {
Application app; Application app;
/**
* Creates a new RemoteApplication object.
*
* @param app ...
*
* @throws RemoteException ...
*/
public RemoteApplication(Application app) throws RemoteException { public RemoteApplication(Application app) throws RemoteException {
this.app = app; this.app = app;
} }
/** /**
* ping method to let clients know if the server is reachable * ping method to let clients know if the server is reachable
*/ */
@ -39,7 +54,6 @@ public class RemoteApplication
return app.execute(req); return app.execute(req);
} }
/** /**
* Update HopObjects in this application's cache. This is used to replicate * Update HopObjects in this application's cache. This is used to replicate
* application caches in a distributed app environment * application caches in a distributed app environment
@ -49,6 +63,7 @@ public class RemoteApplication
app.logEvent("Rejecting cache replication event: allowReplication property is not set to true"); app.logEvent("Rejecting cache replication event: allowReplication property is not set to true");
throw new RuntimeException("Replication event rejected: setup does not allow replication."); throw new RuntimeException("Replication event rejected: setup does not allow replication.");
} }
app.nmgr.replicateCache(add, delete); app.nmgr.replicateCache(add, delete);
} }
} }

View file

@ -1,15 +1,28 @@
// RequestEvaluator.java /*
// Copyright (c) Hannes Wallnöfer 1998-2000 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.framework.core; package helma.framework.core;
import helma.framework.*;
import helma.objectmodel.*; import helma.objectmodel.*;
import helma.objectmodel.db.*; import helma.objectmodel.db.*;
import helma.framework.*;
import helma.scripting.*; import helma.scripting.*;
import helma.util.*; import helma.util.*;
import java.util.*;
import java.lang.reflect.*; import java.lang.reflect.*;
import java.util.*;
/** /**
* This class does the work for incoming requests. It holds a transactor thread * This class does the work for incoming requests. It holds a transactor thread
@ -18,17 +31,15 @@ import java.lang.reflect.*;
* specified by the application has passed. In the latter case, the evaluator thread * specified by the application has passed. In the latter case, the evaluator thread
* is killed and an error message is returned. * is killed and an error message is returned.
*/ */
public final class RequestEvaluator implements Runnable { public final class RequestEvaluator implements Runnable {
static final int NONE = 0; // no request
static final int HTTP = 1; // via HTTP gateway
static final int XMLRPC = 2; // via XML-RPC
static final int INTERNAL = 3; // generic function call, e.g. by scheduler
public final Application app; public final Application app;
protected ScriptingEngine scriptingEngine; protected ScriptingEngine scriptingEngine;
public RequestTrans req; public RequestTrans req;
public ResponseTrans res; public ResponseTrans res;
volatile Transactor rtx; volatile Transactor rtx;
// the object on which to invoke a function, if specified // the object on which to invoke a function, if specified
@ -54,11 +65,6 @@ public final class RequestEvaluator implements Runnable {
// the type of request to be serviced // the type of request to be serviced
int reqtype; int reqtype;
static final int NONE = 0; // no request
static final int HTTP = 1; // via HTTP gateway
static final int XMLRPC = 2; // via XML-RPC
static final int INTERNAL = 3; // generic function call, e.g. by scheduler
protected int skinDepth; protected int skinDepth;
/** /**
@ -70,17 +76,21 @@ public final class RequestEvaluator implements Runnable {
protected void initScriptingEngine() { protected void initScriptingEngine() {
if (scriptingEngine == null) { if (scriptingEngine == null) {
String engineClassName = app.getProperty ( String engineClassName = app.getProperty("scriptingEngine",
"scriptingEngine",
"helma.scripting.fesi.PhantomEngine"); "helma.scripting.fesi.PhantomEngine");
try { try {
Class clazz = app.getClassLoader().loadClass(engineClassName); Class clazz = app.getClassLoader().loadClass(engineClassName);
scriptingEngine = (ScriptingEngine) clazz.newInstance(); scriptingEngine = (ScriptingEngine) clazz.newInstance();
scriptingEngine.init(app, this); scriptingEngine.init(app, this);
} catch (Exception x) { } catch (Exception x) {
Throwable t = x; Throwable t = x;
if (x instanceof InvocationTargetException)
if (x instanceof InvocationTargetException) {
t = ((InvocationTargetException) x).getTargetException(); t = ((InvocationTargetException) x).getTargetException();
}
app.logEvent("******************************************"); app.logEvent("******************************************");
app.logEvent("*** Error creating scripting engine: "); app.logEvent("*** Error creating scripting engine: ");
app.logEvent("*** " + t.toString()); app.logEvent("*** " + t.toString());
@ -89,43 +99,50 @@ public final class RequestEvaluator implements Runnable {
} }
} }
/**
*
*/
public void run() { public void run() {
int txcount = 0; int txcount = 0;
// first, set a local variable to the current transactor thread so we know // first, set a local variable to the current transactor thread so we know
// when it's time to quit because another thread took over. // when it's time to quit because another thread took over.
Transactor localrtx = (Transactor) Thread.currentThread(); Transactor localrtx = (Transactor) Thread.currentThread();
try { try {
do { do {
// long startCheck = System.currentTimeMillis (); // long startCheck = System.currentTimeMillis ();
app.typemgr.checkPrototypes(); app.typemgr.checkPrototypes();
initScriptingEngine(); initScriptingEngine();
scriptingEngine.updatePrototypes(); scriptingEngine.updatePrototypes();
// System.err.println ("Type check overhead: "+(System.currentTimeMillis ()-startCheck)+" millis");
// System.err.println ("Type check overhead: "+(System.currentTimeMillis ()-startCheck)+" millis");
// object refs to ressolve request path // object refs to ressolve request path
Object root, currentElement; Object root;
// System.err.println ("Type check overhead: "+(System.currentTimeMillis ()-startCheck)+" millis");
// object refs to ressolve request path
Object currentElement;
requestPath = new ArrayList(); requestPath = new ArrayList();
switch (reqtype) { switch (reqtype) {
case HTTP: case HTTP:
int tries = 0; int tries = 0;
boolean done = false; boolean done = false;
String error = null; String error = null;
while (!done) { while (!done) {
currentElement = null; currentElement = null;
try { try {
// used for logging // used for logging
StringBuffer txname = new StringBuffer(app.getName()); StringBuffer txname = new StringBuffer(app.getName());
txname.append("/"); txname.append("/");
txname.append (error == null ? req.path : "error"); txname.append((error == null) ? req.path : "error");
// begin transaction // begin transaction
localrtx.begin(txname.toString()); localrtx.begin(txname.toString());
@ -134,6 +151,7 @@ public final class RequestEvaluator implements Runnable {
root = app.getDataRoot(); root = app.getDataRoot();
HashMap globals = new HashMap(); HashMap globals = new HashMap();
globals.put("root", root); globals.put("root", root);
globals.put("session", new SessionBean(session)); globals.put("session", new SessionBean(session));
globals.put("req", new RequestBean(req)); globals.put("req", new RequestBean(req));
@ -141,44 +159,57 @@ public final class RequestEvaluator implements Runnable {
globals.put("app", new ApplicationBean(app)); globals.put("app", new ApplicationBean(app));
globals.put("path", requestPath); globals.put("path", requestPath);
req.startTime = System.currentTimeMillis(); req.startTime = System.currentTimeMillis();
if (error != null)
if (error != null) {
res.error = error; res.error = error;
}
if (session.message != null) { if (session.message != null) {
// bring over the message from a redirect // bring over the message from a redirect
res.message = session.message; res.message = session.message;
session.message = null; session.message = null;
} }
Map macroHandlers = res.getMacroHandlers(); Map macroHandlers = res.getMacroHandlers();
try { try {
if (error != null) { if (error != null) {
// there was an error in the previous loop, call error handler // there was an error in the previous loop, call error handler
currentElement = root; currentElement = root;
// do not reset the requestPath so error handler can use the original one // do not reset the requestPath so error handler can use the original one
// get error handler action // get error handler action
String errorAction = app.props.getProperty ("error", "error"); String errorAction = app.props.getProperty("error",
action = getAction (currentElement, errorAction); "error");
if (action == null)
throw new RuntimeException (error);
} else if (req.path == null || "".equals (req.path.trim ())) { action = getAction(currentElement, errorAction);
if (action == null) {
throw new RuntimeException(error);
}
} else if ((req.path == null) ||
"".equals(req.path.trim())) {
currentElement = root; currentElement = root;
requestPath.add(currentElement); requestPath.add(currentElement);
macroHandlers.put("root", root); macroHandlers.put("root", root);
action = getAction(currentElement, null); action = getAction(currentElement, null);
if (action == null)
if (action == null) {
throw new FrameworkException("Action not found"); throw new FrameworkException("Action not found");
}
} else { } else {
// march down request path... // march down request path...
StringTokenizer st = new StringTokenizer (req.path, "/"); StringTokenizer st = new StringTokenizer(req.path,
"/");
int ntokens = st.countTokens(); int ntokens = st.countTokens();
// limit path to < 50 tokens // limit path to < 50 tokens
if (ntokens > 50) if (ntokens > 50) {
throw new RuntimeException("Path too long"); throw new RuntimeException("Path too long");
}
String[] pathItems = new String[ntokens]; String[] pathItems = new String[ntokens];
for (int i = 0; i < ntokens; i++) for (int i = 0; i < ntokens; i++)
pathItems[i] = st.nextToken(); pathItems[i] = st.nextToken();
@ -187,66 +218,80 @@ public final class RequestEvaluator implements Runnable {
macroHandlers.put("root", root); macroHandlers.put("root", root);
for (int i = 0; i < ntokens; i++) { for (int i = 0; i < ntokens; i++) {
if (currentElement == null) {
if (currentElement == null)
throw new FrameworkException("Object not found."); throw new FrameworkException("Object not found.");
}
if (pathItems[i].length () == 0) if (pathItems[i].length() == 0) {
continue; continue;
}
// we used to do special processing for /user and /users // we used to do special processing for /user and /users
// here but with the framework cleanup, this stuff has to be // here but with the framework cleanup, this stuff has to be
// mounted manually. // mounted manually.
// if we're at the last element of the path, // if we're at the last element of the path,
// try to interpret it as action name. // try to interpret it as action name.
if (i == ntokens-1) { if (i == (ntokens - 1)) {
action = getAction (currentElement, pathItems[i]); action = getAction(currentElement,
pathItems[i]);
} }
if (action == null) { if (action == null) {
currentElement = app.getChildElement(currentElement,
currentElement = app.getChildElement (currentElement, pathItems[i]); pathItems[i]);
// add object to request path if suitable // add object to request path if suitable
if (currentElement != null) { if (currentElement != null) {
// add to requestPath array // add to requestPath array
requestPath.add(currentElement); requestPath.add(currentElement);
Prototype proto = app.getPrototype(currentElement); Prototype proto = app.getPrototype(currentElement);
if (proto != null)
proto.addToHandlerMap (macroHandlers, currentElement); if (proto != null) {
proto.addToHandlerMap(macroHandlers,
currentElement);
}
} }
} }
} }
if (currentElement == null) if (currentElement == null) {
throw new FrameworkException("Object not found."); throw new FrameworkException("Object not found.");
}
if (action == null) if (action == null) {
action = getAction(currentElement, null); action = getAction(currentElement, null);
}
if (action == null) if (action == null) {
throw new FrameworkException("Action not found"); throw new FrameworkException("Action not found");
} }
}
} catch (FrameworkException notfound) { } catch (FrameworkException notfound) {
if (error != null) if (error != null) {
// we already have an error and the error template wasn't found, // we already have an error and the error template wasn't found,
// display it instead of notfound message // display it instead of notfound message
throw new RuntimeException(); throw new RuntimeException();
}
// The path could not be resolved. Check if there is a "not found" action // The path could not be resolved. Check if there is a "not found" action
// specified in the property file. // specified in the property file.
res.status = 404; res.status = 404;
String notFoundAction = app.props.getProperty ("notFound", "notfound");
String notFoundAction = app.props.getProperty("notFound",
"notfound");
currentElement = root; currentElement = root;
action = getAction(currentElement, notFoundAction); action = getAction(currentElement, notFoundAction);
if (action == null)
if (action == null) {
throw new FrameworkException(notfound.getMessage()); throw new FrameworkException(notfound.getMessage());
} }
}
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// end of path resolution section // end of path resolution section
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// beginning of execution section // beginning of execution section
try { try {
@ -255,6 +300,7 @@ public final class RequestEvaluator implements Runnable {
// set the req.action property, cutting off the _action suffix // set the req.action property, cutting off the _action suffix
req.action = action.substring(0, action.length() - 7); req.action = action.substring(0, action.length() - 7);
// set the application checksum in response to make ETag // set the application checksum in response to make ETag
// generation sensitive to changes in the app // generation sensitive to changes in the app
res.setApplicationChecksum(app.getChecksum()); res.setApplicationChecksum(app.getChecksum());
@ -265,8 +311,12 @@ public final class RequestEvaluator implements Runnable {
// try calling onRequest() function on object before // try calling onRequest() function on object before
// calling the actual action // calling the actual action
try { try {
if (scriptingEngine.hasFunction (currentElement, "onRequest")) if (scriptingEngine.hasFunction(currentElement,
scriptingEngine.invoke (currentElement, "onRequest", new Object[0], false); "onRequest")) {
scriptingEngine.invoke(currentElement,
"onRequest",
new Object[0], false);
}
} catch (RedirectException redir) { } catch (RedirectException redir) {
throw redir; throw redir;
} }
@ -275,48 +325,57 @@ public final class RequestEvaluator implements Runnable {
skinDepth = 0; skinDepth = 0;
// do the actual action invocation // do the actual action invocation
scriptingEngine.invoke (currentElement, action, new Object[0], false); scriptingEngine.invoke(currentElement, action,
new Object[0], false);
} catch (RedirectException redirect) { } catch (RedirectException redirect) {
// res.redirect = redirect.getMessage (); // res.redirect = redirect.getMessage ();
// if there is a message set, save it on the user object for the next request // if there is a message set, save it on the user object for the next request
if (res.message != null) if (res.message != null) {
session.message = res.message; session.message = res.message;
}
done = true; done = true;
} }
// check if we're still the one and only or if the waiting thread has given up on us already // check if we're still the one and only or if the waiting thread has given up on us already
commitTransaction(); commitTransaction();
done = true; done = true;
} catch (ConcurrencyException x) { } catch (ConcurrencyException x) {
res.reset(); res.reset();
if (++tries < 8) { if (++tries < 8) {
// try again after waiting some period // try again after waiting some period
abortTransaction(true); abortTransaction(true);
try { try {
// wait a bit longer with each try // wait a bit longer with each try
int base = 800 * tries; int base = 800 * tries;
Thread.currentThread ().sleep ((long) (base + Math.random ()*base*2));
} catch (Exception ignore) {} Thread.currentThread().sleep((long) (base +
(Math.random() * base * 2)));
} catch (Exception ignore) {
}
continue; continue;
} else { } else {
abortTransaction(false); abortTransaction(false);
if (error == null) { if (error == null) {
app.errorCount += 1; app.errorCount += 1;
// set done to false so that the error will be processed // set done to false so that the error will be processed
done = false; done = false;
error = "Couldn't complete transaction due to heavy object traffic (tried "+tries+" times)"; error = "Couldn't complete transaction due to heavy object traffic (tried " +
tries + " times)";
} else { } else {
// error in error action. use traditional minimal error message // error in error action. use traditional minimal error message
res.write ("<b>Error in application '"+app.getName()+"':</b> <br><br><pre>"+error+"</pre>"); res.write("<b>Error in application '" +
app.getName() + "':</b> <br><br><pre>" +
error + "</pre>");
done = true; done = true;
} }
} }
} catch (Exception x) { } catch (Exception x) {
abortTransaction(false); abortTransaction(false);
// If the transactor thread has been killed by the invoker thread we don't have to // If the transactor thread has been killed by the invoker thread we don't have to
@ -330,30 +389,41 @@ public final class RequestEvaluator implements Runnable {
// check if we tried to process the error already // check if we tried to process the error already
if (error == null) { if (error == null) {
app.errorCount += 1; app.errorCount += 1;
app.logEvent ("Exception in "+Thread.currentThread()+": "+x); app.logEvent("Exception in " +
Thread.currentThread() + ": " + x);
// set done to false so that the error will be processed // set done to false so that the error will be processed
done = false; done = false;
error = x.getMessage(); error = x.getMessage();
if (error == null || error.length() == 0)
if ((error == null) || (error.length() == 0)) {
error = x.toString(); error = x.toString();
if (error == null)
error = "Unspecified error";
} else {
// error in error action. use traditional minimal error message
res.write ("<b>Error in application '"+app.getName()+"':</b> <br><br><pre>"+error+"</pre>");
done = true;
} }
if (error == null) {
error = "Unspecified error";
}
} else {
// error in error action. use traditional minimal error message
res.write("<b>Error in application '" +
app.getName() + "':</b> <br><br><pre>" +
error + "</pre>");
done = true;
} }
} }
}
break; break;
case XMLRPC: case XMLRPC:
try { try {
localrtx.begin(app.getName() + ":xmlrpc:" + method); localrtx.begin(app.getName() + ":xmlrpc:" + method);
root = app.getDataRoot(); root = app.getDataRoot();
HashMap globals = new HashMap(); HashMap globals = new HashMap();
globals.put("root", root); globals.put("root", root);
globals.put("res", new ResponseBean(res)); globals.put("res", new ResponseBean(res));
globals.put("app", new ApplicationBean(app)); globals.put("app", new ApplicationBean(app));
@ -365,30 +435,39 @@ public final class RequestEvaluator implements Runnable {
if (method.indexOf(".") > -1) { if (method.indexOf(".") > -1) {
StringTokenizer st = new StringTokenizer(method, "."); StringTokenizer st = new StringTokenizer(method, ".");
int cnt = st.countTokens(); int cnt = st.countTokens();
for (int i = 1; i < cnt; i++) { for (int i = 1; i < cnt; i++) {
String next = st.nextToken(); String next = st.nextToken();
currentElement = app.getChildElement (currentElement, next);
currentElement = app.getChildElement(currentElement,
next);
}
if (currentElement == null) {
throw new FrameworkException("Method name \"" +
method +
"\" could not be resolved.");
} }
if (currentElement == null)
throw new FrameworkException ("Method name \""+method+"\" could not be resolved.");
method = st.nextToken(); method = st.nextToken();
} }
// check XML-RPC access permissions // check XML-RPC access permissions
String proto = app.getPrototypeName(currentElement); String proto = app.getPrototypeName(currentElement);
app.checkXmlRpcAccess(proto, method); app.checkXmlRpcAccess(proto, method);
// reset skin recursion detection counter // reset skin recursion detection counter
skinDepth = 0; skinDepth = 0;
result = scriptingEngine.invoke (currentElement, method, args, true); result = scriptingEngine.invoke(currentElement, method, args,
true);
commitTransaction(); commitTransaction();
} catch (Exception x) { } catch (Exception x) {
abortTransaction(false); abortTransaction(false);
app.logEvent ("Exception in "+Thread.currentThread()+": "+x); app.logEvent("Exception in " + Thread.currentThread() + ": " +
x);
// If the transactor thread has been killed by the invoker thread we don't have to // If the transactor thread has been killed by the invoker thread we don't have to
// bother for the error message, just quit. // bother for the error message, just quit.
@ -400,49 +479,57 @@ public final class RequestEvaluator implements Runnable {
} }
break; break;
case INTERNAL: case INTERNAL:
// Just a human readable descriptor of this invocation // Just a human readable descriptor of this invocation
String funcdesc = app.getName() + ":internal:" + method; String funcdesc = app.getName() + ":internal:" + method;
// if thisObject is an instance of NodeHandle, get the node object itself. // if thisObject is an instance of NodeHandle, get the node object itself.
if (thisObject != null && thisObject instanceof NodeHandle) { if ((thisObject != null) && thisObject instanceof NodeHandle) {
thisObject = ((NodeHandle) thisObject).getNode(app.nmgr.safe); thisObject = ((NodeHandle) thisObject).getNode(app.nmgr.safe);
// see if a valid node was returned // see if a valid node was returned
if (thisObject == null) { if (thisObject == null) {
reqtype = NONE; reqtype = NONE;
break; break;
} }
} }
// avoid going into transaction if called function doesn't exist // avoid going into transaction if called function doesn't exist
boolean functionexists = true; boolean functionexists = true;
functionexists = scriptingEngine.hasFunction(thisObject, method); functionexists = scriptingEngine.hasFunction(thisObject, method);
if (!functionexists) { if (!functionexists) {
// function doesn't exist, nothing to do here. // function doesn't exist, nothing to do here.
reqtype = NONE; reqtype = NONE;
} else try { } else {
try {
localrtx.begin(funcdesc); localrtx.begin(funcdesc);
root = app.getDataRoot(); root = app.getDataRoot();
HashMap globals = new HashMap(); HashMap globals = new HashMap();
globals.put("root", root); globals.put("root", root);
globals.put("res", new ResponseBean(res)); globals.put("res", new ResponseBean(res));
globals.put("app", new ApplicationBean(app)); globals.put("app", new ApplicationBean(app));
scriptingEngine.enterContext(globals); scriptingEngine.enterContext(globals);
// reset skin recursion detection counter // reset skin recursion detection counter
skinDepth = 0; skinDepth = 0;
result = scriptingEngine.invoke (thisObject, method, args, false); result = scriptingEngine.invoke(thisObject, method, args,
false);
commitTransaction(); commitTransaction();
} catch (Exception x) { } catch (Exception x) {
abortTransaction(false); abortTransaction(false);
app.logEvent ("Exception in "+Thread.currentThread()+": "+x); app.logEvent("Exception in " + Thread.currentThread() +
": " + x);
// If the transactor thread has been killed by the invoker thread we don't have to // If the transactor thread has been killed by the invoker thread we don't have to
// bother for the error message, just quit. // bother for the error message, just quit.
@ -452,9 +539,9 @@ public final class RequestEvaluator implements Runnable {
this.exception = x; this.exception = x;
} }
}
break; break;
} }
// exit execution context // exit execution context
@ -464,13 +551,12 @@ public final class RequestEvaluator implements Runnable {
// if localrtx != rtx, the current thread has been aborted and there's no need to notify // if localrtx != rtx, the current thread has been aborted and there's no need to notify
if (localrtx != rtx) { if (localrtx != rtx) {
localrtx.closeConnections(); localrtx.closeConnections();
return; return;
} }
notifyAndWait(); notifyAndWait();
} while (localrtx == rtx); } while (localrtx == rtx);
} finally { } finally {
localrtx.closeConnections(); localrtx.closeConnections();
} }
@ -481,6 +567,7 @@ public final class RequestEvaluator implements Runnable {
*/ */
synchronized void commitTransaction() throws Exception { synchronized void commitTransaction() throws Exception {
Transactor localrtx = (Transactor) Thread.currentThread(); Transactor localrtx = (Transactor) Thread.currentThread();
if (localrtx == rtx) { if (localrtx == rtx) {
reqtype = NONE; reqtype = NONE;
localrtx.commit(); localrtx.commit();
@ -491,11 +578,15 @@ public final class RequestEvaluator implements Runnable {
synchronized void abortTransaction(boolean retry) { synchronized void abortTransaction(boolean retry) {
Transactor localrtx = (Transactor) Thread.currentThread(); Transactor localrtx = (Transactor) Thread.currentThread();
if (!retry && localrtx == rtx)
if (!retry && (localrtx == rtx)) {
reqtype = NONE; reqtype = NONE;
}
try { try {
localrtx.abort(); localrtx.abort();
} catch (Exception ignore) {} } catch (Exception ignore) {
}
} }
/** /**
@ -503,25 +594,41 @@ public final class RequestEvaluator implements Runnable {
*/ */
synchronized void notifyAndWait() { synchronized void notifyAndWait() {
Transactor localrtx = (Transactor) Thread.currentThread(); Transactor localrtx = (Transactor) Thread.currentThread();
if (reqtype != NONE)
if (reqtype != NONE) {
return; // is there a new request already? return; // is there a new request already?
}
notifyAll(); notifyAll();
try { try {
// wait for request, max 10 min // wait for request, max 10 min
wait(1000 * 60 * 10); wait(1000 * 60 * 10);
// if no request arrived, release ressources and thread // if no request arrived, release ressources and thread
if (reqtype == NONE && rtx == localrtx) { if ((reqtype == NONE) && (rtx == localrtx)) {
// comment this in to release not just the thread, but also the scripting engine. // comment this in to release not just the thread, but also the scripting engine.
// currently we don't do this because of the risk of memory leaks (objects from // currently we don't do this because of the risk of memory leaks (objects from
// framework referencing into the scripting engine) // framework referencing into the scripting engine)
// scriptingEngine = null; // scriptingEngine = null;
rtx = null; rtx = null;
} }
} catch (InterruptedException ir) {} } catch (InterruptedException ir) {
}
} }
public synchronized ResponseTrans invoke (RequestTrans req, Session session) throws Exception { /**
*
*
* @param req ...
* @param session ...
*
* @return ...
*
* @throws Exception ...
*/
public synchronized ResponseTrans invoke(RequestTrans req, Session session)
throws Exception {
this.reqtype = HTTP; this.reqtype = HTTP;
this.req = req; this.req = req;
this.session = session; this.session = session;
@ -531,14 +638,15 @@ public final class RequestEvaluator implements Runnable {
checkThread(); checkThread();
wait(app.requestTimeout); wait(app.requestTimeout);
if (reqtype != NONE) { if (reqtype != NONE) {
app.logEvent("Stopping Thread for Request " + app.getName() + "/" + req.path); app.logEvent("Stopping Thread for Request " + app.getName() + "/" + req.path);
stopThread(); stopThread();
res.reset(); res.reset();
res.write ("<b>Error in application '" + res.write("<b>Error in application '" + app.getName() +
app.getName() +
"':</b> <br><br><pre>Request timed out.</pre>"); "':</b> <br><br><pre>Request timed out.</pre>");
} }
return res; return res;
} }
@ -546,18 +654,34 @@ public final class RequestEvaluator implements Runnable {
* This checks if the Evaluator is already executing an equal request. If so, attach to it and * This checks if the Evaluator is already executing an equal request. If so, attach to it and
* wait for it to complete. Otherwise return null, so the application knows it has to run the request. * wait for it to complete. Otherwise return null, so the application knows it has to run the request.
*/ */
public synchronized ResponseTrans attachRequest (RequestTrans req) throws InterruptedException { public synchronized ResponseTrans attachRequest(RequestTrans req)
if (this.req == null || res == null || !this.req.equals (req)) throws InterruptedException {
if ((this.req == null) || (res == null) || !this.req.equals(req)) {
return null; return null;
}
// we already know our response object // we already know our response object
ResponseTrans r = res; ResponseTrans r = res;
if (reqtype != NONE)
if (reqtype != NONE) {
wait(app.requestTimeout); wait(app.requestTimeout);
}
return r; return r;
} }
/**
public synchronized Object invokeXmlRpc (String method, Object[] args) throws Exception { *
*
* @param method ...
* @param args ...
*
* @return ...
*
* @throws Exception ...
*/
public synchronized Object invokeXmlRpc(String method, Object[] args)
throws Exception {
this.reqtype = XMLRPC; this.reqtype = XMLRPC;
this.session = null; this.session = null;
this.method = method; this.method = method;
@ -568,22 +692,50 @@ public final class RequestEvaluator implements Runnable {
checkThread(); checkThread();
wait(app.requestTimeout); wait(app.requestTimeout);
if (reqtype != NONE) { if (reqtype != NONE) {
stopThread(); stopThread();
} }
// reset res for garbage collection (res.data may hold reference to evaluator) // reset res for garbage collection (res.data may hold reference to evaluator)
res = null; res = null;
if (exception != null)
if (exception != null) {
throw (exception); throw (exception);
}
return result; return result;
} }
public Object invokeDirectFunction (Object obj, String functionName, Object[] args) throws Exception { /**
*
*
* @param obj ...
* @param functionName ...
* @param args ...
*
* @return ...
*
* @throws Exception ...
*/
public Object invokeDirectFunction(Object obj, String functionName, Object[] args)
throws Exception {
return scriptingEngine.invoke(obj, functionName, args, false); return scriptingEngine.invoke(obj, functionName, args, false);
} }
public synchronized Object invokeFunction (Object object, String functionName, Object[] args) /**
*
*
* @param object ...
* @param functionName ...
* @param args ...
*
* @return ...
*
* @throws Exception ...
*/
public synchronized Object invokeFunction(Object object, String functionName,
Object[] args)
throws Exception { throws Exception {
reqtype = INTERNAL; reqtype = INTERNAL;
session = null; session = null;
@ -595,7 +747,7 @@ public final class RequestEvaluator implements Runnable {
exception = null; exception = null;
checkThread(); checkThread();
wait (60000l*15); // give internal call more time (15 minutes) to complete wait(60000L * 15); // give internal call more time (15 minutes) to complete
if (reqtype != NONE) { if (reqtype != NONE) {
stopThread(); stopThread();
@ -603,12 +755,27 @@ public final class RequestEvaluator implements Runnable {
// reset res for garbage collection (res.data may hold reference to evaluator) // reset res for garbage collection (res.data may hold reference to evaluator)
res = null; res = null;
if (exception != null)
if (exception != null) {
throw (exception); throw (exception);
}
return result; return result;
} }
public synchronized Object invokeFunction (Session session, String functionName, Object[] args) /**
*
*
* @param session ...
* @param functionName ...
* @param args ...
*
* @return ...
*
* @throws Exception ...
*/
public synchronized Object invokeFunction(Session session, String functionName,
Object[] args)
throws Exception { throws Exception {
reqtype = INTERNAL; reqtype = INTERNAL;
this.session = session; this.session = session;
@ -628,11 +795,13 @@ public final class RequestEvaluator implements Runnable {
// reset res for garbage collection (res.data may hold reference to evaluator) // reset res for garbage collection (res.data may hold reference to evaluator)
res = null; res = null;
if (exception != null)
if (exception != null) {
throw (exception); throw (exception);
return result;
} }
return result;
}
/** /**
* Stop this request evaluator's current thread. If currently active kill the request, otherwise just * Stop this request evaluator's current thread. If currently active kill the request, otherwise just
@ -640,32 +809,40 @@ public final class RequestEvaluator implements Runnable {
*/ */
public synchronized void stopThread() { public synchronized void stopThread() {
app.logEvent("Stopping Thread " + rtx); app.logEvent("Stopping Thread " + rtx);
Transactor t = rtx; Transactor t = rtx;
// let the scripting engine know that the // let the scripting engine know that the
// current transaction is being aborted. // current transaction is being aborted.
if (scriptingEngine != null) if (scriptingEngine != null) {
scriptingEngine.abort(); scriptingEngine.abort();
}
rtx = null; rtx = null;
if (t != null) { if (t != null) {
if (reqtype != NONE) { if (reqtype != NONE) {
reqtype = NONE; reqtype = NONE;
t.kill(); t.kill();
try { try {
t.abort(); t.abort();
} catch (Exception ignore) {} } catch (Exception ignore) {
}
} else { } else {
notifyAll(); notifyAll();
} }
t.closeConnections(); t.closeConnections();
} }
} }
private synchronized void checkThread() throws InterruptedException { private synchronized void checkThread() throws InterruptedException {
if (app.stopped) {
if (app.stopped)
throw new ApplicationStoppedException(); throw new ApplicationStoppedException();
}
if (rtx == null || !rtx.isAlive()) { if ((rtx == null) || !rtx.isAlive()) {
// app.logEvent ("Starting Thread"); // app.logEvent ("Starting Thread");
rtx = new Transactor(this, app.threadgroup, app.nmgr); rtx = new Transactor(this, app.threadgroup, app.nmgr);
rtx.setContextClassLoader(app.getClassLoader()); rtx.setContextClassLoader(app.getClassLoader());
@ -693,13 +870,16 @@ public final class RequestEvaluator implements Runnable {
* return the action's function name. Otherwise, return null. * return the action's function name. Otherwise, return null.
*/ */
public String getAction(Object obj, String action) { public String getAction(Object obj, String action) {
if (obj == null) if (obj == null) {
return null; return null;
String act = action == null ? "main_action" : action+"_action"; }
if (scriptingEngine.hasFunction (obj, act))
String act = (action == null) ? "main_action" : (action + "_action");
if (scriptingEngine.hasFunction(obj, act)) {
return act; return act;
}
return null; return null;
} }
} }

View file

@ -1,12 +1,26 @@
// Session.java /*
* Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.framework.core; package helma.framework.core;
import java.io.*;
import java.util.*;
import java.net.URLEncoder;
import helma.objectmodel.*; import helma.objectmodel.*;
import helma.objectmodel.db.*; import helma.objectmodel.db.*;
import java.io.*;
import java.net.URLEncoder;
import java.util.*;
/** /**
* This represents a session currently using the Hop application. * This represents a session currently using the Hop application.
@ -14,9 +28,7 @@ import helma.objectmodel.db.*;
* Depending on whether the user is logged in or not, the user object holds a * Depending on whether the user is logged in or not, the user object holds a
* persistent user node. * persistent user node.
*/ */
public class Session implements Serializable { public class Session implements Serializable {
transient Application app; transient Application app;
String sessionID; String sessionID;
@ -29,13 +41,20 @@ public class Session implements Serializable {
// the transient cache node that is exposed to javascript // the transient cache node that is exposed to javascript
// this stays the same across logins and logouts. // this stays the same across logins and logouts.
public TransientNode cacheNode; public TransientNode cacheNode;
long onSince;
long onSince, lastTouched, lastModified; long lastTouched;
long lastModified;
// used to remember messages to the user between requests - // used to remember messages to the user between requests -
// used for redirects. // used for redirects.
String message; String message;
/**
* Creates a new Session object.
*
* @param sessionID ...
* @param app ...
*/
public Session(String sessionID, Application app) { public Session(String sessionID, Application app) {
this.sessionID = sessionID; this.sessionID = sessionID;
this.app = app; this.app = app;
@ -57,6 +76,7 @@ public class Session implements Serializable {
userHandle = ((Node) usernode).getHandle(); userHandle = ((Node) usernode).getHandle();
uid = usernode.getElementName(); uid = usernode.getElementName();
} }
lastModified = System.currentTimeMillis(); lastModified = System.currentTimeMillis();
} }
@ -69,8 +89,13 @@ public class Session implements Serializable {
lastModified = System.currentTimeMillis(); lastModified = System.currentTimeMillis();
} }
/**
*
*
* @return ...
*/
public boolean isLoggedIn() { public boolean isLoggedIn() {
if (userHandle!=null && uid!=null) { if ((userHandle != null) && (uid != null)) {
return true; return true;
} else { } else {
return false; return false;
@ -81,11 +106,12 @@ public class Session implements Serializable {
* Gets the user Node from this Application's NodeManager. * Gets the user Node from this Application's NodeManager.
*/ */
public INode getUserNode() { public INode getUserNode() {
if (userHandle!=null) if (userHandle != null) {
return userHandle.getNode(app.getWrappedNodeManager()); return userHandle.getNode(app.getWrappedNodeManager());
else } else {
return null; return null;
} }
}
/** /**
* Gets the transient cache node. * Gets the transient cache node.
@ -94,45 +120,90 @@ public class Session implements Serializable {
return cacheNode; return cacheNode;
} }
/**
*
*
* @return ...
*/
public Application getApp() { public Application getApp() {
return app; return app;
} }
/**
*
*
* @param app ...
*/
public void setApp(Application app) { public void setApp(Application app) {
this.app = app; this.app = app;
} }
/**
*
*
* @return ...
*/
public String getSessionID() { public String getSessionID() {
return sessionID; return sessionID;
} }
/**
*
*/
public void touch() { public void touch() {
lastTouched = System.currentTimeMillis(); lastTouched = System.currentTimeMillis();
} }
/**
*
*
* @return ...
*/
public long lastTouched() { public long lastTouched() {
return lastTouched; return lastTouched;
} }
/**
*
*
* @return ...
*/
public long lastModified() { public long lastModified() {
return lastModified; return lastModified;
} }
/**
*
*
* @param date ...
*/
public void setLastModified(Date date) { public void setLastModified(Date date) {
if (date != null) if (date != null) {
lastModified = date.getTime(); lastModified = date.getTime();
} }
}
/**
*
*
* @return ...
*/
public long onSince() { public long onSince() {
return onSince; return onSince;
} }
/**
*
*
* @return ...
*/
public String toString() { public String toString() {
if ( uid!=null ) if (uid != null) {
return "[Session for user " + uid + "]"; return "[Session for user " + uid + "]";
else } else {
return "[Anonymous Session]"; return "[Anonymous Session]";
} }
}
/** /**
* Get the persistent user id of a registered user. This is usually the user name, or * Get the persistent user id of a registered user. This is usually the user name, or
@ -141,6 +212,4 @@ public class Session implements Serializable {
public String getUID() { public String getUID() {
return uid; return uid;
} }
} }

View file

@ -1,79 +1,163 @@
/*
* Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.framework.core; package helma.framework.core;
import helma.objectmodel.INode;
import helma.scripting.fesi.*;
import java.io.Serializable; import java.io.Serializable;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import helma.objectmodel.INode; /**
import helma.scripting.fesi.*; *
*/
public class SessionBean implements Serializable { public class SessionBean implements Serializable {
// the wrapped session object // the wrapped session object
Session session; Session session;
/**
* Creates a new SessionBean object.
*
* @param session ...
*/
public SessionBean(Session session) { public SessionBean(Session session) {
this.session = session; this.session = session;
} }
/**
*
*
* @return ...
*/
public String toString() { public String toString() {
return session.toString(); return session.toString();
} }
/**
*
*
* @param username ...
* @param password ...
*
* @return ...
*/
public boolean login(String username, String password) { public boolean login(String username, String password) {
boolean success = session.getApp().loginSession(username, password, session); boolean success = session.getApp().loginSession(username, password, session);
return success; return success;
} }
/**
*
*/
public void logout() { public void logout() {
session.getApp().logoutSession(session); session.getApp().logoutSession(session);
} }
/**
*
*/
public void touch() { public void touch() {
session.touch(); session.touch();
} }
/**
*
*
* @return ...
*/
public Date lastActive() { public Date lastActive() {
return new Date(session.lastTouched()); return new Date(session.lastTouched());
} }
/**
*
*
* @return ...
*/
public Date onSince() { public Date onSince() {
return new Date(session.onSince()); return new Date(session.onSince());
} }
// property-related methods: // property-related methods:
public INode getdata() { public INode getdata() {
return session.getCacheNode(); return session.getCacheNode();
} }
/**
*
*
* @return ...
*/
public INode getuser() { public INode getuser() {
return session.getUserNode(); return session.getUserNode();
} }
/**
*
*
* @return ...
*/
public String get_id() { public String get_id() {
return session.getSessionID(); return session.getSessionID();
} }
/**
*
*
* @return ...
*/
public String getcookie() { public String getcookie() {
return session.getSessionID(); return session.getSessionID();
} }
/**
*
*
* @return ...
*/
public Date getlastActive() { public Date getlastActive() {
return new Date(session.lastTouched()); return new Date(session.lastTouched());
} }
/**
*
*
* @return ...
*/
public Date getonSince() { public Date getonSince() {
return new Date(session.onSince()); return new Date(session.onSince());
} }
/**
*
*
* @return ...
*/
public Date getLastModified() { public Date getLastModified() {
return new Date(session.lastModified()); return new Date(session.lastModified());
} }
/**
*
*
* @param date ...
*/
public void setLastModified(Date date) { public void setLastModified(Date date) {
session.setLastModified(date); session.setLastModified(date);
} }
} }

View file

@ -1,15 +1,28 @@
// Skin.java /*
// Copyright (c) Hannes Wallnöfer 2001 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.framework.core; package helma.framework.core;
import helma.framework.*; import helma.framework.*;
import helma.scripting.*;
import helma.objectmodel.INode;
import helma.objectmodel.ConcurrencyException; import helma.objectmodel.ConcurrencyException;
import helma.objectmodel.INode;
import helma.scripting.*;
import helma.util.HtmlEncoder; import helma.util.HtmlEncoder;
import java.net.URLEncoder;
import java.io.*; import java.io.*;
import java.net.URLEncoder;
import java.util.*; import java.util.*;
/** /**
@ -17,16 +30,23 @@ import java.util.*;
* that will be dynamically evaluated.. It uses the request path array * that will be dynamically evaluated.. It uses the request path array
* from the RequestEvaluator object to resolve Macro handlers by type name. * from the RequestEvaluator object to resolve Macro handlers by type name.
*/ */
public final class Skin { public final class Skin {
static final int HANDLER = 0;
static final int MACRO = 1;
static final int PARAMNAME = 2;
static final int PARAMVALUE = 3;
static final int ENCODE_NONE = 0;
static final int ENCODE_HTML = 1;
static final int ENCODE_XML = 2;
static final int ENCODE_FORM = 3;
static final int ENCODE_URL = 4;
static final int ENCODE_ALL = 5;
private Macro[] macros; private Macro[] macros;
private Application app; private Application app;
private char[] source; private char[] source;
private int sourceLength; private int sourceLength;
private HashSet sandbox; private HashSet sandbox;
/** /**
* Create a skin without any restrictions on which macros are allowed to be called from it * Create a skin without any restrictions on which macros are allowed to be called from it
*/ */
@ -64,22 +84,26 @@ public final class Skin {
* Parse a skin object from source text * Parse a skin object from source text
*/ */
private void parse() { private void parse() {
ArrayList partBuffer = new ArrayList(); ArrayList partBuffer = new ArrayList();
int start = 0; int start = 0;
for (int i = 0; i < sourceLength-1; i++) {
if (source[i] == '<' && source[i+1] == '%') { for (int i = 0; i < (sourceLength - 1); i++) {
if ((source[i] == '<') && (source[i + 1] == '%')) {
// found macro start tag // found macro start tag
int j = i + 2; int j = i + 2;
// search macr end tag // search macr end tag
while (j < sourceLength-1 && (source[j] != '%' || source[j+1] != '>')) { while ((j < (sourceLength - 1)) &&
((source[j] != '%') || (source[j + 1] != '>'))) {
j++; j++;
} }
if (j > i+2) {
if (j > (i + 2)) {
partBuffer.add(new Macro(i, j + 2)); partBuffer.add(new Macro(i, j + 2));
start = j + 2; start = j + 2;
} }
i = j + 1; i = j + 1;
} }
} }
@ -98,32 +122,40 @@ public final class Skin {
/** /**
* Render this skin * Render this skin
*/ */
public void render (RequestEvaluator reval, Object thisObject, Map paramObject) throws RedirectException { public void render(RequestEvaluator reval, Object thisObject, Map paramObject)
throws RedirectException {
// check for endless skin recursion // check for endless skin recursion
if (++reval.skinDepth > 50) if (++reval.skinDepth > 50) {
throw new RuntimeException("Recursive skin invocation suspected"); throw new RuntimeException("Recursive skin invocation suspected");
}
if (macros == null) { if (macros == null) {
reval.res.writeCharArray(source, 0, sourceLength); reval.res.writeCharArray(source, 0, sourceLength);
reval.skinDepth--; reval.skinDepth--;
return; return;
} }
try { try {
int written = 0; int written = 0;
Map handlerCache = null; Map handlerCache = null;
if (macros.length > 3) { if (macros.length > 3) {
handlerCache = new HashMap(); handlerCache = new HashMap();
} }
for (int i = 0; i < macros.length; i++) { for (int i = 0; i < macros.length; i++) {
if (macros[i].start > written) if (macros[i].start > written) {
reval.res.writeCharArray(source, written, macros[i].start - written); reval.res.writeCharArray(source, written, macros[i].start - written);
}
macros[i].render(reval, thisObject, paramObject, handlerCache); macros[i].render(reval, thisObject, paramObject, handlerCache);
written = macros[i].end; written = macros[i].end;
} }
if (written < sourceLength)
if (written < sourceLength) {
reval.res.writeCharArray(source, written, sourceLength - written); reval.res.writeCharArray(source, written, sourceLength - written);
}
} finally { } finally {
reval.skinDepth--; reval.skinDepth--;
} }
@ -136,10 +168,13 @@ public final class Skin {
for (int i = 0; i < macros.length; i++) { for (int i = 0; i < macros.length; i++) {
if (macros[i] instanceof Macro) { if (macros[i] instanceof Macro) {
Macro m = (Macro) macros[i]; Macro m = (Macro) macros[i];
if (macroname.equals (m.fullName))
if (macroname.equals(m.fullName)) {
return true; return true;
} }
} }
}
return false; return false;
} }
@ -150,24 +185,13 @@ public final class Skin {
if (sandbox == null) { if (sandbox == null) {
sandbox = new HashSet(); sandbox = new HashSet();
} }
sandbox.add(macroname); sandbox.add(macroname);
} }
static final int HANDLER = 0;
static final int MACRO = 1;
static final int PARAMNAME = 2;
static final int PARAMVALUE = 3;
static final int ENCODE_NONE = 0;
static final int ENCODE_HTML = 1;
static final int ENCODE_XML = 2;
static final int ENCODE_FORM = 3;
static final int ENCODE_URL = 4;
static final int ENCODE_ALL = 5;
class Macro { class Macro {
final int start;
final int start, end; final int end;
String handler; String handler;
String name; String name;
String fullName; String fullName;
@ -178,37 +202,50 @@ public final class Skin {
Map parameters = null; Map parameters = null;
public Macro(int start, int end) { public Macro(int start, int end) {
this.start = start; this.start = start;
this.end = end; this.end = end;
int state = HANDLER; int state = HANDLER;
boolean escape = false; boolean escape = false;
char quotechar = '\u0000'; char quotechar = '\u0000';
String lastParamName = null; String lastParamName = null;
StringBuffer b = new StringBuffer(); StringBuffer b = new StringBuffer();
for (int i=start+2; i<end-2; i++) { for (int i = start + 2; i < (end - 2); i++) {
switch (source[i]) { switch (source[i]) {
case '.': case '.':
if (state == HANDLER) { if (state == HANDLER) {
handler = b.toString().trim(); handler = b.toString().trim();
b.setLength(0); b.setLength(0);
state = MACRO; state = MACRO;
} else } else {
b.append(source[i]); b.append(source[i]);
}
break; break;
case '\\': case '\\':
if (escape)
if (escape) {
b.append(source[i]); b.append(source[i]);
}
escape = !escape; escape = !escape;
break; break;
case '"': case '"':
case '\'': case '\'':
if (!escape && state == PARAMVALUE) {
if (!escape && (state == PARAMVALUE)) {
if (quotechar == source[i]) { if (quotechar == source[i]) {
String paramValue = b.toString(); String paramValue = b.toString();
if (!setSpecialParameter (lastParamName, paramValue))
if (!setSpecialParameter(lastParamName, paramValue)) {
addGenericParameter(lastParamName, paramValue); addGenericParameter(lastParamName, paramValue);
}
lastParamName = null; lastParamName = null;
b.setLength(0); b.setLength(0);
state = PARAMNAME; state = PARAMNAME;
@ -216,119 +253,152 @@ public final class Skin {
} else if (quotechar == '\u0000') { } else if (quotechar == '\u0000') {
quotechar = source[i]; quotechar = source[i];
b.setLength(0); b.setLength(0);
} else } else {
b.append(source[i]); b.append(source[i]);
} else }
} else {
b.append(source[i]); b.append(source[i]);
}
escape = false; escape = false;
break; break;
case ' ': case ' ':
case '\t': case '\t':
case '\n': case '\n':
case '\r': case '\r':
case '\f': case '\f':
if (state == MACRO || (state == HANDLER && b.length() > 0)) {
if ((state == MACRO) || ((state == HANDLER) && (b.length() > 0))) {
name = b.toString().trim(); name = b.toString().trim();
b.setLength(0); b.setLength(0);
state = PARAMNAME; state = PARAMNAME;
} else if (state == PARAMVALUE && quotechar == '\u0000') { } else if ((state == PARAMVALUE) && (quotechar == '\u0000')) {
String paramValue = b.toString(); String paramValue = b.toString();
if (!setSpecialParameter (lastParamName, paramValue))
if (!setSpecialParameter(lastParamName, paramValue)) {
addGenericParameter(lastParamName, paramValue); addGenericParameter(lastParamName, paramValue);
}
lastParamName = null; lastParamName = null;
b.setLength(0); b.setLength(0);
state = PARAMNAME; state = PARAMNAME;
} else if (state == PARAMVALUE) } else if (state == PARAMVALUE) {
b.append(source[i]); b.append(source[i]);
else } else {
b.setLength(0); b.setLength(0);
}
break; break;
case '=': case '=':
if (state == PARAMNAME) { if (state == PARAMNAME) {
lastParamName = b.toString().trim(); lastParamName = b.toString().trim();
b.setLength(0); b.setLength(0);
state = PARAMVALUE; state = PARAMVALUE;
} else } else {
b.append(source[i]); b.append(source[i]);
}
break; break;
default: default:
b.append(source[i]); b.append(source[i]);
escape = false; escape = false;
} }
} }
if (b.length() > 0) { if (b.length() > 0) {
if (lastParamName != null && b.length() > 0) { if ((lastParamName != null) && (b.length() > 0)) {
String paramValue = b.toString(); String paramValue = b.toString();
if (!setSpecialParameter (lastParamName, paramValue))
if (!setSpecialParameter(lastParamName, paramValue)) {
addGenericParameter(lastParamName, paramValue); addGenericParameter(lastParamName, paramValue);
} else if (state <= MACRO) }
} else if (state <= MACRO) {
name = b.toString().trim(); name = b.toString().trim();
} }
if (handler == null)
fullName = name;
else
fullName = handler+"."+name;
} }
if (handler == null) {
fullName = name;
} else {
fullName = handler + "." + name;
}
}
private boolean setSpecialParameter(String name, String value) { private boolean setSpecialParameter(String name, String value) {
if ("prefix".equals(name)) { if ("prefix".equals(name)) {
prefix = value; prefix = value;
return true; return true;
} else if ("suffix".equals(name)) { } else if ("suffix".equals(name)) {
suffix = value; suffix = value;
return true; return true;
} else if ("encoding".equals(name)) { } else if ("encoding".equals(name)) {
if ("html".equalsIgnoreCase (value)) if ("html".equalsIgnoreCase(value)) {
encoding = ENCODE_HTML; encoding = ENCODE_HTML;
else if ("xml".equalsIgnoreCase (value)) } else if ("xml".equalsIgnoreCase(value)) {
encoding = ENCODE_XML; encoding = ENCODE_XML;
else if ("form".equalsIgnoreCase (value)) } else if ("form".equalsIgnoreCase(value)) {
encoding = ENCODE_FORM; encoding = ENCODE_FORM;
else if ("url".equalsIgnoreCase (value)) } else if ("url".equalsIgnoreCase(value)) {
encoding = ENCODE_URL; encoding = ENCODE_URL;
else if ("all".equalsIgnoreCase (value)) } else if ("all".equalsIgnoreCase(value)) {
encoding = ENCODE_ALL; encoding = ENCODE_ALL;
}
return true; return true;
} else if ("default".equals(name)) { } else if ("default".equals(name)) {
defaultValue = value; defaultValue = value;
return true; return true;
} }
return false; return false;
} }
private void addGenericParameter(String name, String value) { private void addGenericParameter(String name, String value) {
if (parameters == null) if (parameters == null) {
parameters = new HashMap(); parameters = new HashMap();
}
parameters.put(name, value); parameters.put(name, value);
} }
/** /**
* Render the macro given a handler object * Render the macro given a handler object
*/ */
public void render (RequestEvaluator reval, Object thisObject, Map paramObject, Map handlerCache) throws RedirectException { public void render(RequestEvaluator reval, Object thisObject, Map paramObject,
Map handlerCache) throws RedirectException {
if ((sandbox != null) && !sandbox.contains(fullName)) {
String h = (handler == null) ? "global" : handler;
if (sandbox != null && !sandbox.contains (fullName)) {
String h = handler == null ? "global" : handler;
reval.res.write("[Macro " + fullName + " not allowed in sandbox]"); reval.res.write("[Macro " + fullName + " not allowed in sandbox]");
return; return;
} else if ("response".equalsIgnoreCase(handler)) { } else if ("response".equalsIgnoreCase(handler)) {
renderFromResponse(reval); renderFromResponse(reval);
return; return;
} else if ("request".equalsIgnoreCase(handler)) { } else if ("request".equalsIgnoreCase(handler)) {
renderFromRequest(reval); renderFromRequest(reval);
return; return;
} else if ("param".equalsIgnoreCase(handler)) { } else if ("param".equalsIgnoreCase(handler)) {
renderFromParam(reval, paramObject); renderFromParam(reval, paramObject);
return; return;
} else if ("session".equalsIgnoreCase(handler)) { } else if ("session".equalsIgnoreCase(handler)) {
renderFromSession(reval); renderFromSession(reval);
return; return;
} }
try { try {
Object handlerObject = null; Object handlerObject = null;
// flag to tell whether we found our invocation target object // flag to tell whether we found our invocation target object
@ -336,25 +406,30 @@ public final class Skin {
if (handler != null) { if (handler != null) {
// try to get handler from handlerCache first // try to get handler from handlerCache first
if (handlerCache != null) if (handlerCache != null) {
handlerObject = handlerCache.get(handler); handlerObject = handlerCache.get(handler);
}
if (handlerObject == null) { if (handlerObject == null) {
// if handler object wasn't found in cache retrieve it // if handler object wasn't found in cache retrieve it
if (handlerObject == null && thisObject != null) { if ((handlerObject == null) && (thisObject != null)) {
// not a global macro - need to find handler object // not a global macro - need to find handler object
// was called with this object - check it or its parents for matching prototype // was called with this object - check it or its parents for matching prototype
if (!handler.equals ("this") && !handler.equals (app.getPrototypeName (thisObject))) { if (!handler.equals("this") &&
!handler.equals(app.getPrototypeName(thisObject))) {
// the handler object is not what we want // the handler object is not what we want
Object n = thisObject; Object n = thisObject;
// walk down parent chain to find handler object // walk down parent chain to find handler object
while (n != null) { while (n != null) {
Prototype proto = app.getPrototype(n); Prototype proto = app.getPrototype(n);
if (proto != null && proto.isInstanceOf (handler)) {
if ((proto != null) && proto.isInstanceOf(handler)) {
handlerObject = n; handlerObject = n;
break; break;
} }
n = app.getParentElement(n); n = app.getParentElement(n);
} }
} else { } else {
@ -371,13 +446,14 @@ public final class Skin {
} }
// the macro handler object couldn't be found // the macro handler object couldn't be found
if (handlerObject == null) if (handlerObject == null) {
objectFound = false; objectFound = false;
}
// else put the found handler object into the cache so we don't have to look again // else put the found handler object into the cache so we don't have to look again
else if (handlerCache != null) else if (handlerCache != null) {
handlerCache.put(handler, handlerObject); handlerCache.put(handler, handlerObject);
} }
}
} else { } else {
// this is a global macro with no handler specified // this is a global macro with no handler specified
handlerObject = null; handlerObject = null;
@ -387,15 +463,17 @@ public final class Skin {
// check if a function called name_macro is defined. // check if a function called name_macro is defined.
// if so, the macro evaluates to the function. Otherwise, // if so, the macro evaluates to the function. Otherwise,
// a property/field with the name is used, if defined. // a property/field with the name is used, if defined.
String funcName = name + "_macro"; String funcName = name + "_macro";
if (reval.scriptingEngine.hasFunction (handlerObject, funcName)) {
if (reval.scriptingEngine.hasFunction(handlerObject, funcName)) {
StringBuffer buffer = reval.res.getBuffer(); StringBuffer buffer = reval.res.getBuffer();
// remember length of response buffer before calling macro // remember length of response buffer before calling macro
int bufLength = buffer.length(); int bufLength = buffer.length();
// remember length of buffer with prefix written out // remember length of buffer with prefix written out
int preLength = 0; int preLength = 0;
if (prefix != null) { if (prefix != null) {
buffer.append(prefix); buffer.append(prefix);
preLength = prefix.length(); preLength = prefix.length();
@ -406,41 +484,50 @@ public final class Skin {
// Map param = ; // Map param = ;
// if (parameters == null) // if (parameters == null)
// parameters = new HashMap (); // parameters = new HashMap ();
Object[] arguments = { parameters == null ? Object[] arguments = {
new HashMap () : (parameters == null) ? new HashMap()
new HashMap (parameters) : new HashMap(parameters)
}; };
Object value = reval.scriptingEngine.invoke (handlerObject, funcName, arguments, false); Object value = reval.scriptingEngine.invoke(handlerObject,
funcName, arguments,
false);
// check if macro wrote out to response buffer // check if macro wrote out to response buffer
if (buffer.length () == bufLength + preLength) { if (buffer.length() == (bufLength + preLength)) {
// function didn't write out anything itself. // function didn't write out anything itself.
// erase previously written prefix // erase previously written prefix
if (preLength > 0) if (preLength > 0) {
buffer.setLength(bufLength); buffer.setLength(bufLength);
}
// write out macro's return value // write out macro's return value
writeResponse(value, buffer, true); writeResponse(value, buffer, true);
} else { } else {
if (encoding != ENCODE_NONE) { if (encoding != ENCODE_NONE) {
// if an encoding is specified, re-encode the macro's output // if an encoding is specified, re-encode the macro's output
String output = buffer.substring(bufLength + preLength); String output = buffer.substring(bufLength + preLength);
buffer.setLength(bufLength); buffer.setLength(bufLength);
writeResponse(output, buffer, false); writeResponse(output, buffer, false);
} else { } else {
// no re-encoding needed, just append suffix // no re-encoding needed, just append suffix
if (suffix != null) if (suffix != null) {
buffer.append(suffix); buffer.append(suffix);
} }
}
writeResponse(value, buffer, false); writeResponse(value, buffer, false);
} }
} else { } else {
// System.err.println ("Getting macro from property"); // System.err.println ("Getting macro from property");
Object value = reval.scriptingEngine.get(handlerObject, name); Object value = reval.scriptingEngine.get(handlerObject, name);
writeResponse(value, reval.res.getBuffer(), true); writeResponse(value, reval.res.getBuffer(), true);
} }
} else { } else {
String msg = "[HopMacro unhandled: " + fullName + "]"; String msg = "[HopMacro unhandled: " + fullName + "]";
reval.res.write(" " + msg + " "); reval.res.write(" " + msg + " ");
app.logEvent(msg); app.logEvent(msg);
} }
@ -453,8 +540,11 @@ public final class Skin {
} catch (Exception x) { } catch (Exception x) {
// x.printStackTrace(); // x.printStackTrace();
String msg = x.getMessage(); String msg = x.getMessage();
if (msg == null || msg.length() < 10)
if ((msg == null) || (msg.length() < 10)) {
msg = x.toString(); msg = x.toString();
}
msg = "[HopMacro error in " + fullName + ": " + msg + "]"; msg = "[HopMacro error in " + fullName + ": " + msg + "]";
reval.res.write(" " + msg + " "); reval.res.write(" " + msg + " ");
app.logEvent(msg); app.logEvent(msg);
@ -463,34 +553,46 @@ public final class Skin {
private void renderFromResponse(RequestEvaluator reval) { private void renderFromResponse(RequestEvaluator reval) {
Object value = null; Object value = null;
if ("message".equals (name))
if ("message".equals(name)) {
value = reval.res.message; value = reval.res.message;
else if ("error".equals (name)) } else if ("error".equals(name)) {
value = reval.res.error; value = reval.res.error;
if (value == null) }
if (value == null) {
value = reval.res.get(name); value = reval.res.get(name);
}
writeResponse(value, reval.res.getBuffer(), true); writeResponse(value, reval.res.getBuffer(), true);
} }
private void renderFromRequest(RequestEvaluator reval) { private void renderFromRequest(RequestEvaluator reval) {
if (reval.req == null) if (reval.req == null) {
return; return;
}
Object value = reval.req.get(name); Object value = reval.req.get(name);
writeResponse(value, reval.res.getBuffer(), true); writeResponse(value, reval.res.getBuffer(), true);
} }
private void renderFromSession(RequestEvaluator reval) { private void renderFromSession(RequestEvaluator reval) {
if (reval.session == null) if (reval.session == null) {
return; return;
}
Object value = reval.session.getCacheNode().getString(name); Object value = reval.session.getCacheNode().getString(name);
writeResponse(value, reval.res.getBuffer(), true); writeResponse(value, reval.res.getBuffer(), true);
} }
private void renderFromParam(RequestEvaluator reval, Map paramObject) { private void renderFromParam(RequestEvaluator reval, Map paramObject) {
if (paramObject == null) if (paramObject == null) {
reval.res.write("[HopMacro error: Skin requires a parameter object]"); reval.res.write("[HopMacro error: Skin requires a parameter object]");
else { } else {
Object value = paramObject.get(name); Object value = paramObject.get(name);
writeResponse(value, reval.res.getBuffer(), true); writeResponse(value, reval.res.getBuffer(), true);
} }
} }
@ -500,57 +602,69 @@ public final class Skin {
*/ */
void writeResponse(Object value, StringBuffer buffer, boolean useDefault) { void writeResponse(Object value, StringBuffer buffer, boolean useDefault) {
String text; String text;
if (value == null) { if (value == null) {
if (useDefault) if (useDefault) {
text = defaultValue; text = defaultValue;
else } else {
return; return;
}
} else { } else {
text = value.toString(); text = value.toString();
} }
if (text != null && text.length() > 0) {
if (prefix != null) if ((text != null) && (text.length() > 0)) {
if (prefix != null) {
buffer.append(prefix); buffer.append(prefix);
}
switch (encoding) { switch (encoding) {
case ENCODE_NONE: case ENCODE_NONE:
buffer.append(text); buffer.append(text);
break; break;
case ENCODE_HTML: case ENCODE_HTML:
HtmlEncoder.encode(text, buffer); HtmlEncoder.encode(text, buffer);
break; break;
case ENCODE_XML: case ENCODE_XML:
HtmlEncoder.encodeXml(text, buffer); HtmlEncoder.encodeXml(text, buffer);
break; break;
case ENCODE_FORM: case ENCODE_FORM:
HtmlEncoder.encodeFormValue(text, buffer); HtmlEncoder.encodeFormValue(text, buffer);
break; break;
case ENCODE_URL: case ENCODE_URL:
buffer.append(URLEncoder.encode(text)); buffer.append(URLEncoder.encode(text));
break; break;
case ENCODE_ALL: case ENCODE_ALL:
HtmlEncoder.encodeAll(text, buffer); HtmlEncoder.encodeAll(text, buffer);
break; break;
} }
if (suffix != null)
if (suffix != null) {
buffer.append(suffix); buffer.append(suffix);
} }
} }
}
public String toString() { public String toString() {
return "[HopMacro: " + fullName + "]"; return "[HopMacro: " + fullName + "]";
} }
/** /**
* Return the full name of the macro in handler.name notation * Return the full name of the macro in handler.name notation
*/ */
public String getFullName() { public String getFullName() {
return fullName; return fullName;
} }
} }
} }

View file

@ -1,20 +1,29 @@
// SkinFile.java /*
// Copyright (c) Hannes Wallnöfer 2001 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.framework.core; package helma.framework.core;
import java.util.*;
import java.io.*;
import helma.util.Updatable; import helma.util.Updatable;
import java.io.*;
import java.util.*;
/** /**
* This represents a File containing a Hop skin * This represents a File containing a Hop skin
*/ */
public final class SkinFile implements Updatable { public final class SkinFile implements Updatable {
String name; String name;
Prototype prototype; Prototype prototype;
Application app; Application app;
@ -22,6 +31,13 @@ public final class SkinFile implements Updatable {
Skin skin; Skin skin;
long lastmod = 0; long lastmod = 0;
/**
* Creates a new SkinFile object.
*
* @param file ...
* @param name ...
* @param proto ...
*/
public SkinFile(File file, String name, Prototype proto) { public SkinFile(File file, String name, Prototype proto) {
this.prototype = proto; this.prototype = proto;
this.file = file; this.file = file;
@ -55,7 +71,6 @@ public final class SkinFile implements Updatable {
skin = null; skin = null;
} }
/** /**
* Tell the type manager whether we need an update. this is the case when * Tell the type manager whether we need an update. this is the case when
* the file has been modified or deleted. * the file has been modified or deleted.
@ -64,59 +79,85 @@ public final class SkinFile implements Updatable {
// if skin object is null we only need to call update if the file doesn't // if skin object is null we only need to call update if the file doesn't
// exist anymore, while if the skin is initialized, we'll catch both // exist anymore, while if the skin is initialized, we'll catch both
// cases (file deleted and file changed) by just calling lastModified(). // cases (file deleted and file changed) by just calling lastModified().
return skin != null ? lastmod != file.lastModified () : !file.exists (); return (skin != null) ? (lastmod != file.lastModified()) : (!file.exists());
} }
/**
*
*/
public void update() { public void update() {
if (!file.exists()) { if (!file.exists()) {
// remove skin from prototype // remove skin from prototype
remove(); remove();
} else { } else {
// we only need to update if the skin has already been initialized // we only need to update if the skin has already been initialized
if (skin != null) if (skin != null) {
read(); read();
} }
} }
}
private void read() { private void read() {
try { try {
FileReader reader = new FileReader(file); FileReader reader = new FileReader(file);
char c[] = new char[(int) file.length()]; char[] c = new char[(int) file.length()];
int length = reader.read(c); int length = reader.read(c);
reader.close(); reader.close();
skin = new Skin(c, length, app); skin = new Skin(c, length, app);
} catch (IOException x) { } catch (IOException x) {
app.logEvent("Error reading Skin " + file + ": " + x); app.logEvent("Error reading Skin " + file + ": " + x);
} }
lastmod = file.lastModified(); lastmod = file.lastModified();
} }
/**
*
*/
public void remove() { public void remove() {
if (prototype != null) { if (prototype != null) {
prototype.removeSkinFile(this); prototype.removeSkinFile(this);
} }
} }
/**
*
*
* @return ...
*/
public File getFile() { public File getFile() {
return file; return file;
} }
/**
*
*
* @return ...
*/
public Skin getSkin() { public Skin getSkin() {
if (skin == null) if (skin == null) {
read(); read();
}
return skin; return skin;
} }
/**
*
*
* @return ...
*/
public String getName() { public String getName() {
return name; return name;
} }
/**
*
*
* @return ...
*/
public String toString() { public String toString() {
return prototype.getName() + "/" + file.getName(); return prototype.getName() + "/" + file.getName();
} }
} }

View file

@ -1,67 +1,92 @@
// SkinManager.java /*
// Copyright (c) Hannes Wallnöfer 2002 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.framework.core; package helma.framework.core;
import java.util.*;
import helma.objectmodel.INode; import helma.objectmodel.INode;
import java.io.*; import java.io.*;
import java.util.*;
/** /**
* Manages skins for a Helma application * Manages skins for a Helma application
*/ */
public final class SkinManager implements FilenameFilter { public final class SkinManager implements FilenameFilter {
Application app; Application app;
/**
* Creates a new SkinManager object.
*
* @param app ...
*/
public SkinManager(Application app) { public SkinManager(Application app) {
this.app = app; this.app = app;
} }
protected Skin getSkin(Prototype proto, String skinname, Object[] skinpath) { protected Skin getSkin(Prototype proto, String skinname, Object[] skinpath) {
if (proto == null) if (proto == null) {
return null; return null;
}
Skin skin = null; Skin skin = null;
// First check if the skin has been already used within the execution of this request // First check if the skin has been already used within the execution of this request
// check for skinsets set via res.skinpath property // check for skinsets set via res.skinpath property
do { do {
if (skinpath != null) { if (skinpath != null) {
for (int i = 0; i < skinpath.length; i++) { for (int i = 0; i < skinpath.length; i++) {
skin = getSkinInternal(skinpath[i], proto.getName(), skinname); skin = getSkinInternal(skinpath[i], proto.getName(), skinname);
if (skin != null) { if (skin != null) {
return skin; return skin;
} }
} }
} }
// skin for this prototype wasn't found in the skinsets. // skin for this prototype wasn't found in the skinsets.
// the next step is to look if it is defined as skin file in the application directory // the next step is to look if it is defined as skin file in the application directory
skin = proto.getSkin(skinname); skin = proto.getSkin(skinname);
if (skin != null) { if (skin != null) {
return skin; return skin;
} }
// still not found. See if there is a parent prototype which might define the skin. // still not found. See if there is a parent prototype which might define the skin.
proto = proto.getParentPrototype(); proto = proto.getParentPrototype();
} while (proto != null); } while (proto != null);
// looked every where, nothing to be found // looked every where, nothing to be found
return null; return null;
} }
protected Skin getSkinInternal(Object skinset, String prototype, String skinname) { protected Skin getSkinInternal(Object skinset, String prototype, String skinname) {
if (prototype == null || skinset == null) if ((prototype == null) || (skinset == null)) {
return null; return null;
}
// check if the skinset object is a HopObject (db based skin) // check if the skinset object is a HopObject (db based skin)
// or a String (file based skin) // or a String (file based skin)
if (skinset instanceof INode) { if (skinset instanceof INode) {
INode n = ((INode) skinset).getNode(prototype); INode n = ((INode) skinset).getNode(prototype);
if (n != null) { if (n != null) {
n = n.getNode(skinname); n = n.getNode(skinname);
if (n != null) { if (n != null) {
String skin = n.getString("skin"); String skin = n.getString("skin");
if (skin != null) { if (skin != null) {
return new Skin(skin, app); return new Skin(skin, app);
} }
@ -71,29 +96,38 @@ public final class SkinManager implements FilenameFilter {
// Skinset is interpreted as directory name from which to // Skinset is interpreted as directory name from which to
// retrieve the skin // retrieve the skin
File f = new File(skinset.toString(), prototype); File f = new File(skinset.toString(), prototype);
f = new File(f, skinname + ".skin"); f = new File(f, skinname + ".skin");
if (f.exists() && f.canRead()) { if (f.exists() && f.canRead()) {
SkinFile sf = new SkinFile(f, skinname, app); SkinFile sf = new SkinFile(f, skinname, app);
return sf.getSkin(); return sf.getSkin();
} }
} }
// Inheritance is taken care of in the above getSkin method. // Inheritance is taken care of in the above getSkin method.
// the sequence is prototype.skin-from-db, prototype.skin-from-file, parent.from-db, parent.from-file etc. // the sequence is prototype.skin-from-db, prototype.skin-from-file, parent.from-db, parent.from-file etc.
return null; return null;
} }
protected Map getSkinFiles(String skinDir, Prototype proto) { protected Map getSkinFiles(String skinDir, Prototype proto) {
File dir = new File(skinDir.toString(), proto.getName()); File dir = new File(skinDir.toString(), proto.getName());
String[] skinNames = dir.list(this); String[] skinNames = dir.list(this);
if (skinNames == null || skinNames.length == 0)
if ((skinNames == null) || (skinNames.length == 0)) {
return null; return null;
}
HashMap map = new HashMap(); HashMap map = new HashMap();
for (int i = 0; i < skinNames.length; i++) { for (int i = 0; i < skinNames.length; i++) {
String name = skinNames[i].substring(0, skinNames[i].length() - 5); String name = skinNames[i].substring(0, skinNames[i].length() - 5);
File file = new File(dir, skinNames[i]); File file = new File(dir, skinNames[i]);
map.put(name, new SkinFile(file, name, proto)); map.put(name, new SkinFile(file, name, proto));
} }
return map; return map;
} }
@ -103,5 +137,4 @@ public final class SkinManager implements FilenameFilter {
public boolean accept(File d, String n) { public boolean accept(File d, String n) {
return n.endsWith(".skin"); return n.endsWith(".skin");
} }
} }

View file

@ -1,5 +1,18 @@
// TypeManager.java /*
// Copyright (c) Hannes Wallnöfer 1998-2000 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.framework.core; package helma.framework.core;
@ -7,19 +20,22 @@ import helma.objectmodel.*;
import helma.objectmodel.db.DbMapping; import helma.objectmodel.db.DbMapping;
import helma.scripting.*; import helma.scripting.*;
import helma.util.*; import helma.util.*;
import java.util.*;
import java.io.*; import java.io.*;
import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.net.URLClassLoader; import java.net.URLClassLoader;
import java.net.MalformedURLException; import java.util.*;
/** /**
* The type manager periodically checks the prototype definitions for its * The type manager periodically checks the prototype definitions for its
* applications and updates the evaluators if anything has changed. * applications and updates the evaluators if anything has changed.
*/ */
public final class TypeManager { public final class TypeManager {
final static String[] standardTypes = { "user", "global", "root", "hopobject" };
final static String templateExtension = ".hsp";
final static String scriptExtension = ".js";
final static String actionExtension = ".hac";
final static String skinExtension = ".skin";
Application app; Application app;
File appDir; File appDir;
HashMap prototypes; // map of prototypes HashMap prototypes; // map of prototypes
@ -27,54 +43,69 @@ public final class TypeManager {
HashSet jarfiles; // set of Java archives HashSet jarfiles; // set of Java archives
long lastCheck = 0; long lastCheck = 0;
long appDirMod = 0; long appDirMod = 0;
// a checksum that changes whenever something in the application files changes. // a checksum that changes whenever something in the application files changes.
long checksum; long checksum;
// the hopobject prototype // the hopobject prototype
Prototype hopobjectProto; Prototype hopobjectProto;
// the global prototype // the global prototype
Prototype globalProto; Prototype globalProto;
// app specific class loader, includes jar files in the app directory // app specific class loader, includes jar files in the app directory
AppClassLoader loader; AppClassLoader loader;
final static String[] standardTypes = {"user", "global", "root", "hopobject"}; /**
* Creates a new TypeManager object.
final static String templateExtension = ".hsp"; *
final static String scriptExtension = ".js"; * @param app ...
final static String actionExtension = ".hac"; *
final static String skinExtension = ".skin"; * @throws MalformedURLException ...
* @throws RuntimeException ...
*/
public TypeManager(Application app) throws MalformedURLException { public TypeManager(Application app) throws MalformedURLException {
this.app = app; this.app = app;
appDir = app.appDir; appDir = app.appDir;
// make sure the directories for the standard prototypes exist, and lament otherwise // make sure the directories for the standard prototypes exist, and lament otherwise
if (appDir.list().length == 0) { if (appDir.list().length == 0) {
for (int i = 0; i < standardTypes.length; i++) { for (int i = 0; i < standardTypes.length; i++) {
File f = new File(appDir, standardTypes[i]); File f = new File(appDir, standardTypes[i]);
if (!f.exists() && !f.mkdir ())
app.logEvent ("Warning: directory "+f.getAbsolutePath ()+" could not be created."); if (!f.exists() && !f.mkdir()) {
else if (!f.isDirectory ()) app.logEvent("Warning: directory " + f.getAbsolutePath() +
app.logEvent ("Warning: "+f.getAbsolutePath ()+" is not a directory."); " could not be created.");
} else if (!f.isDirectory()) {
app.logEvent("Warning: " + f.getAbsolutePath() +
" is not a directory.");
} }
} }
}
prototypes = new HashMap(); prototypes = new HashMap();
zipfiles = new HashMap(); zipfiles = new HashMap();
jarfiles = new HashSet(); jarfiles = new HashSet();
URL[] urls = ((URLClassLoader) TypeManager.class.getClassLoader()).getURLs(); URL[] urls = ((URLClassLoader) TypeManager.class.getClassLoader()).getURLs();
URL helmajar = null; URL helmajar = null;
for (int i = 0; i < urls.length; i++) { for (int i = 0; i < urls.length; i++) {
String url = urls[i].toString().toLowerCase(); String url = urls[i].toString().toLowerCase();
if (url.endsWith("helma.jar")) { if (url.endsWith("helma.jar")) {
helmajar = urls[i]; helmajar = urls[i];
break; break;
} }
} }
if (helmajar == null)
if (helmajar == null) {
throw new RuntimeException("helma.jar not found in embedding classpath"); throw new RuntimeException("helma.jar not found in embedding classpath");
loader = new AppClassLoader(app.getName(), new URL[] { helmajar });
} }
loader = new AppClassLoader(app.getName(), new URL[] { helmajar });
}
/** /**
* Run through application's prototype directories and create prototypes, but don't * Run through application's prototype directories and create prototypes, but don't
@ -84,25 +115,30 @@ public final class TypeManager {
// create standard prototypes. // create standard prototypes.
createPrototype("root"); createPrototype("root");
createPrototype("user"); createPrototype("user");
// get references to hopobject and global protos, // get references to hopobject and global protos,
// since we need it regularly when setting parent prototypes. // since we need it regularly when setting parent prototypes.
hopobjectProto = createPrototype("hopobject"); hopobjectProto = createPrototype("hopobject");
globalProto = createPrototype("global"); globalProto = createPrototype("global");
// loop through directories and create prototypes // loop through directories and create prototypes
checkFiles(); checkFiles();
} }
/** /**
* Run through application's prototype directories and check if anything has been updated. * Run through application's prototype directories and check if anything has been updated.
* If so, update prototypes and scripts. * If so, update prototypes and scripts.
*/ */
public synchronized void checkPrototypes() { public synchronized void checkPrototypes() {
if (System.currentTimeMillis () - lastCheck < 1000l) if ((System.currentTimeMillis() - lastCheck) < 1000L) {
return; return;
}
try { try {
checkFiles(); checkFiles();
} catch (Exception ignore) {} } catch (Exception ignore) {
}
lastCheck = System.currentTimeMillis(); lastCheck = System.currentTimeMillis();
} }
@ -115,37 +151,55 @@ public final class TypeManager {
// checked... // checked...
if (appDir.lastModified() > appDirMod) { if (appDir.lastModified() > appDirMod) {
appDirMod = appDir.lastModified(); appDirMod = appDir.lastModified();
String[] list = appDir.list(); String[] list = appDir.list();
if (list == null)
throw new RuntimeException ("Can't read app directory "+appDir+" - check permissions"); if (list == null) {
throw new RuntimeException("Can't read app directory " + appDir +
" - check permissions");
}
for (int i = 0; i < list.length; i++) { for (int i = 0; i < list.length; i++) {
if (list[i].endsWith(".zip")) { if (list[i].endsWith(".zip")) {
ZippedAppFile zipped = (ZippedAppFile) zipfiles.get(list[i]); ZippedAppFile zipped = (ZippedAppFile) zipfiles.get(list[i]);
if (zipped == null) { if (zipped == null) {
File f = new File(appDir, list[i]); File f = new File(appDir, list[i]);
if (!f.isDirectory()) { if (!f.isDirectory()) {
zipped = new ZippedAppFile(f, app); zipped = new ZippedAppFile(f, app);
zipfiles.put(list[i], zipped); zipfiles.put(list[i], zipped);
} }
} }
continue; continue;
} }
if (list[i].endsWith(".jar")) { if (list[i].endsWith(".jar")) {
if (!jarfiles.contains(list[i])) { if (!jarfiles.contains(list[i])) {
jarfiles.add(list[i]); jarfiles.add(list[i]);
File f = new File(appDir, list[i]); File f = new File(appDir, list[i]);
try { try {
loader.addURL(new URL("file:" + f.getAbsolutePath())); loader.addURL(new URL("file:" + f.getAbsolutePath()));
} catch (MalformedURLException ignore) {} } catch (MalformedURLException ignore) {
} }
}
continue; continue;
} }
if (list[i].indexOf ('.') > -1)
if (list[i].indexOf('.') > -1) {
continue; continue;
}
Prototype proto = getPrototype(list[i]); Prototype proto = getPrototype(list[i]);
// if prototype doesn't exist, create it // if prototype doesn't exist, create it
if (proto == null && isValidTypeName (list[i])) { if ((proto == null) && isValidTypeName(list[i])) {
File f = new File(appDir, list[i]); File f = new File(appDir, list[i]);
if (f.isDirectory()) { if (f.isDirectory()) {
// create new prototype // create new prototype
createPrototype(list[i], f); createPrototype(list[i], f);
@ -160,9 +214,11 @@ public final class TypeManager {
// loop through zip files to check for updates // loop through zip files to check for updates
for (Iterator it = zipfiles.values().iterator(); it.hasNext();) { for (Iterator it = zipfiles.values().iterator(); it.hasNext();) {
ZippedAppFile zipped = (ZippedAppFile) it.next(); ZippedAppFile zipped = (ZippedAppFile) it.next();
if (zipped.needsUpdate()) { if (zipped.needsUpdate()) {
zipped.update(); zipped.update();
} }
newChecksum += zipped.lastmod; newChecksum += zipped.lastmod;
} }
@ -171,44 +227,58 @@ public final class TypeManager {
// have been created in the previous loop. // have been created in the previous loop.
for (Iterator i = prototypes.values().iterator(); i.hasNext();) { for (Iterator i = prototypes.values().iterator(); i.hasNext();) {
Prototype proto = (Prototype) i.next(); Prototype proto = (Prototype) i.next();
// calculate this app's type checksum // calculate this app's type checksum
newChecksum += proto.getChecksum(); newChecksum += proto.getChecksum();
// update prototype's type mapping // update prototype's type mapping
DbMapping dbmap = proto.getDbMapping(); DbMapping dbmap = proto.getDbMapping();
if (dbmap != null && dbmap.needsUpdate ()) {
if ((dbmap != null) && dbmap.needsUpdate()) {
dbmap.update(); dbmap.update();
if (proto != hopobjectProto && proto != globalProto) {
if ((proto != hopobjectProto) && (proto != globalProto)) {
// set parent prototype, in case it has changed. // set parent prototype, in case it has changed.
String parentName = dbmap.getExtends(); String parentName = dbmap.getExtends();
if (parentName != null)
if (parentName != null) {
proto.setParentPrototype(getPrototype(parentName)); proto.setParentPrototype(getPrototype(parentName));
else if (!app.isJavaPrototype (proto.getName())) } else if (!app.isJavaPrototype(proto.getName())) {
proto.setParentPrototype(hopobjectProto); proto.setParentPrototype(hopobjectProto);
} }
} }
} }
}
checksum = newChecksum; checksum = newChecksum;
} }
protected void removeZipFile(String zipname) { protected void removeZipFile(String zipname) {
zipfiles.remove(zipname); zipfiles.remove(zipname);
for (Iterator i = prototypes.values().iterator(); i.hasNext();) { for (Iterator i = prototypes.values().iterator(); i.hasNext();) {
Prototype proto = (Prototype) i.next(); Prototype proto = (Prototype) i.next();
// update prototype's type mapping // update prototype's type mapping
DbMapping dbmap = proto.getDbMapping(); DbMapping dbmap = proto.getDbMapping();
SystemProperties props = dbmap.getProperties(); SystemProperties props = dbmap.getProperties();
props.removeProps(zipname); props.removeProps(zipname);
} }
} }
private boolean isValidTypeName(String str) { private boolean isValidTypeName(String str) {
if (str == null) if (str == null) {
return false; return false;
}
char[] c = str.toCharArray(); char[] c = str.toCharArray();
for (int i = 0; i < c.length; i++) for (int i = 0; i < c.length; i++)
if (!Character.isJavaIdentifierPart (c[i])) if (!Character.isJavaIdentifierPart(c[i])) {
return false; return false;
}
return true; return true;
} }
@ -236,32 +306,35 @@ public final class TypeManager {
return createPrototype(typename, new File(appDir, typename)); return createPrototype(typename, new File(appDir, typename));
} }
/** /**
* Create a prototype from a directory containing scripts and other stuff * Create a prototype from a directory containing scripts and other stuff
*/ */
public Prototype createPrototype(String typename, File dir) { public Prototype createPrototype(String typename, File dir) {
Prototype proto = new Prototype(typename, dir, app); Prototype proto = new Prototype(typename, dir, app);
// Create and register type properties file // Create and register type properties file
File propfile = new File(dir, "type.properties"); File propfile = new File(dir, "type.properties");
SystemProperties props = new SystemProperties(propfile.getAbsolutePath()); SystemProperties props = new SystemProperties(propfile.getAbsolutePath());
DbMapping dbmap = new DbMapping(app, typename, props); DbMapping dbmap = new DbMapping(app, typename, props);
// we don't need to put the DbMapping into proto.updatables, because // we don't need to put the DbMapping into proto.updatables, because
// dbmappings are checked separately in checkFiles for each request // dbmappings are checked separately in checkFiles for each request
// proto.updatables.put ("type.properties", dbmap); // proto.updatables.put ("type.properties", dbmap);
proto.setDbMapping(dbmap); proto.setDbMapping(dbmap);
// put the prototype into our map // put the prototype into our map
prototypes.put(typename, proto); prototypes.put(typename, proto);
return proto; return proto;
} }
/** /**
* Update a prototype to the files in the prototype directory. * Update a prototype to the files in the prototype directory.
*/ */
public void updatePrototype(String name) { public void updatePrototype(String name) {
// System.err.println ("UPDATE PROTO: "+app.getName()+"/"+name); // System.err.println ("UPDATE PROTO: "+app.getName()+"/"+name);
Prototype proto = getPrototype(name); Prototype proto = getPrototype(name);
updatePrototype(proto); updatePrototype(proto);
} }
@ -269,15 +342,16 @@ public final class TypeManager {
* Update a prototype to the files in the prototype directory. * Update a prototype to the files in the prototype directory.
*/ */
public void updatePrototype(Prototype proto) { public void updatePrototype(Prototype proto) {
if (proto == null || proto.isUpToDate()) if ((proto == null) || proto.isUpToDate()) {
return; return;
}
synchronized (proto) { synchronized (proto) {
// check again because another thread may have checked the // check again because another thread may have checked the
// prototype while we were waiting for access to the synchronized section // prototype while we were waiting for access to the synchronized section
/* if (System.currentTimeMillis() - proto.getLastCheck() < 1000) /* if (System.currentTimeMillis() - proto.getLastCheck() < 1000)
return; */ return; */
File dir = proto.getDirectory(); File dir = proto.getDirectory();
HashSet updateSet = null; HashSet updateSet = null;
HashSet createSet = null; HashSet createSet = null;
@ -286,9 +360,12 @@ public final class TypeManager {
// anything the prototype knows about has changed on disk // anything the prototype knows about has changed on disk
for (Iterator i = proto.updatables.values().iterator(); i.hasNext();) { for (Iterator i = proto.updatables.values().iterator(); i.hasNext();) {
Updatable upd = (Updatable) i.next(); Updatable upd = (Updatable) i.next();
if (upd.needsUpdate()) { if (upd.needsUpdate()) {
if (updateSet == null) if (updateSet == null) {
updateSet = new HashSet(); updateSet = new HashSet();
}
updateSet.add(upd); updateSet.add(upd);
} }
} }
@ -296,32 +373,35 @@ public final class TypeManager {
// next we check if files have been created or removed since last update // next we check if files have been created or removed since last update
// if (proto.getLastCheck() < dir.lastModified ()) { // if (proto.getLastCheck() < dir.lastModified ()) {
File[] list = proto.getFiles(); File[] list = proto.getFiles();
for (int i = 0; i < list.length; i++) { for (int i = 0; i < list.length; i++) {
String fn = list[i].getName(); String fn = list[i].getName();
if (!proto.updatables.containsKey(fn)) { if (!proto.updatables.containsKey(fn)) {
if (fn.endsWith (templateExtension) || if (fn.endsWith(templateExtension) || fn.endsWith(scriptExtension) ||
fn.endsWith (scriptExtension) || fn.endsWith(actionExtension) || fn.endsWith(skinExtension) ||
fn.endsWith (actionExtension) || "type.properties".equalsIgnoreCase(fn)) {
fn.endsWith (skinExtension) || if (createSet == null) {
"type.properties".equalsIgnoreCase (fn))
{
if (createSet == null)
createSet = new HashSet(); createSet = new HashSet();
}
createSet.add(list[i]); createSet.add(list[i]);
} }
} }
} }
// }
// }
// if nothing needs to be updated, mark prototype as checked and return // if nothing needs to be updated, mark prototype as checked and return
if (updateSet == null && createSet == null) { if ((updateSet == null) && (createSet == null)) {
proto.markChecked(); proto.markChecked();
return; return;
} }
// first go through new files and create new items // first go through new files and create new items
if (createSet != null) { if (createSet != null) {
Object[] newFiles = createSet.toArray(); Object[] newFiles = createSet.toArray();
for (int i = 0; i < newFiles.length; i++) { for (int i = 0; i < newFiles.length; i++) {
File file = (File) newFiles[i]; File file = (File) newFiles[i];
String filename = file.getName(); String filename = file.getName();
@ -331,6 +411,7 @@ public final class TypeManager {
if (filename.endsWith(templateExtension)) { if (filename.endsWith(templateExtension)) {
try { try {
Template t = new Template(file, tmpname, proto); Template t = new Template(file, tmpname, proto);
proto.addTemplate(t); proto.addTemplate(t);
} catch (Throwable x) { } catch (Throwable x) {
app.logEvent("Error updating prototype: " + x); app.logEvent("Error updating prototype: " + x);
@ -338,6 +419,7 @@ public final class TypeManager {
} else if (filename.endsWith(scriptExtension)) { } else if (filename.endsWith(scriptExtension)) {
try { try {
FunctionFile ff = new FunctionFile(file, proto); FunctionFile ff = new FunctionFile(file, proto);
proto.addFunctionFile(ff); proto.addFunctionFile(ff);
} catch (Throwable x) { } catch (Throwable x) {
app.logEvent("Error updating prototype: " + x); app.logEvent("Error updating prototype: " + x);
@ -345,12 +427,14 @@ public final class TypeManager {
} else if (filename.endsWith(actionExtension)) { } else if (filename.endsWith(actionExtension)) {
try { try {
ActionFile af = new ActionFile(file, tmpname, proto); ActionFile af = new ActionFile(file, tmpname, proto);
proto.addActionFile(af); proto.addActionFile(af);
} catch (Throwable x) { } catch (Throwable x) {
app.logEvent("Error updating prototype: " + x); app.logEvent("Error updating prototype: " + x);
} }
} else if (filename.endsWith(skinExtension)) { } else if (filename.endsWith(skinExtension)) {
SkinFile sf = new SkinFile(file, tmpname, proto); SkinFile sf = new SkinFile(file, tmpname, proto);
proto.addSkinFile(sf); proto.addSkinFile(sf);
} }
} }
@ -360,13 +444,17 @@ public final class TypeManager {
if (updateSet != null) { if (updateSet != null) {
for (Iterator i = updateSet.iterator(); i.hasNext();) { for (Iterator i = updateSet.iterator(); i.hasNext();) {
Updatable upd = (Updatable) i.next(); Updatable upd = (Updatable) i.next();
try { try {
upd.update(); upd.update();
} catch (Exception x) { } catch (Exception x) {
if (upd instanceof DbMapping) if (upd instanceof DbMapping) {
app.logEvent ("Error updating db mapping for type "+proto.getName()+": "+x); app.logEvent("Error updating db mapping for type " +
else proto.getName() + ": " + x);
app.logEvent ("Error updating "+upd+" of prototye type "+proto.getName()+": "+x); } else {
app.logEvent("Error updating " + upd + " of prototye type " +
proto.getName() + ": " + x);
}
} }
} }
} }
@ -374,10 +462,7 @@ public final class TypeManager {
// mark prototype as checked and updated. // mark prototype as checked and updated.
proto.markChecked(); proto.markChecked();
proto.markUpdated(); proto.markUpdated();
} // end of synchronized (proto)
} }
// end of synchronized (proto)
}
} }

View file

@ -1,119 +1,151 @@
// ZippedFile.java /*
// Copyright (c) Hannes Wallnöfer 2001 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.framework.core; package helma.framework.core;
import helma.framework.*;
import helma.objectmodel.db.DbMapping;
import helma.scripting.*;
import helma.util.SystemProperties;
import helma.util.Updatable;
import java.io.*;
import java.util.*; import java.util.*;
import java.util.zip.*; import java.util.zip.*;
import java.io.*;
import helma.framework.*;
import helma.scripting.*;
import helma.util.Updatable;
import helma.util.SystemProperties;
import helma.objectmodel.db.DbMapping;
/** /**
* This represents a Zip-File which may contain other Updatables for one or more prototypes. * This represents a Zip-File which may contain other Updatables for one or more prototypes.
*/ */
public class ZippedAppFile implements Updatable { public class ZippedAppFile implements Updatable {
Application app; Application app;
File file; File file;
long lastmod; long lastmod;
Set updatables; Set updatables;
/**
* Creates a new ZippedAppFile object.
*
* @param file ...
* @param app ...
*/
public ZippedAppFile(File file, Application app) { public ZippedAppFile(File file, Application app) {
this.app = app; this.app = app;
this.file = file; this.file = file;
// System.err.println ("CREATING ZIP FILE "+this); // System.err.println ("CREATING ZIP FILE "+this);
} }
/** /**
* Tell the type manager whether we need an update. this is the case when * Tell the type manager whether we need an update. this is the case when
* the file has been modified or deleted. * the file has been modified or deleted.
*/ */
public boolean needsUpdate() { public boolean needsUpdate() {
return !file.exists () || lastmod != file.lastModified (); return !file.exists() || (lastmod != file.lastModified());
} }
/**
*
*/
public void update() { public void update() {
if (!file.exists()) { if (!file.exists()) {
remove(); remove();
} else { } else {
ZipFile zip = null; ZipFile zip = null;
// collect created protos - we need this to check DbMappings for each created // collect created protos - we need this to check DbMappings for each created
// prototype afterwards // prototype afterwards
HashSet newPrototypes = new HashSet(); HashSet newPrototypes = new HashSet();
try { try {
lastmod = file.lastModified(); lastmod = file.lastModified();
// System.err.println ("UPDATING ZIP FILE "+this); // System.err.println ("UPDATING ZIP FILE "+this);
zip = new ZipFile(file); zip = new ZipFile(file);
updatables = new HashSet(); updatables = new HashSet();
for (Enumeration en = zip.entries(); en.hasMoreElements();) { for (Enumeration en = zip.entries(); en.hasMoreElements();) {
ZipEntry entry = (ZipEntry) en.nextElement(); ZipEntry entry = (ZipEntry) en.nextElement();
String ename = entry.getName(); String ename = entry.getName();
StringTokenizer st = new StringTokenizer(ename, "/"); StringTokenizer st = new StringTokenizer(ename, "/");
if (st.countTokens() == 2) { if (st.countTokens() == 2) {
String dir = st.nextToken(); String dir = st.nextToken();
String fname = st.nextToken(); String fname = st.nextToken();
// System.err.println ("ZIPENTRY: "+ dir +" ~ "+fname); // System.err.println ("ZIPENTRY: "+ dir +" ~ "+fname);
Prototype proto = app.typemgr.getPrototype(dir); Prototype proto = app.typemgr.getPrototype(dir);
if (proto == null) { if (proto == null) {
proto = app.typemgr.createPrototype(dir); proto = app.typemgr.createPrototype(dir);
newPrototypes.add(proto); newPrototypes.add(proto);
} }
if (fname.endsWith(".hac")) { if (fname.endsWith(".hac")) {
String name = fname.substring(0, fname.lastIndexOf(".")); String name = fname.substring(0, fname.lastIndexOf("."));
String sourceName = file.getName() + "/" + ename; String sourceName = file.getName() + "/" + ename;
String content = getZipEntryContent(zip, entry); String content = getZipEntryContent(zip, entry);
// System.err.println ("["+content+"]"); // System.err.println ("["+content+"]");
ActionFile act = new ActionFile (content, name, sourceName, proto); ActionFile act = new ActionFile(content, name, sourceName,
proto);
proto.addActionFile(act); proto.addActionFile(act);
updatables.add(act); updatables.add(act);
// mark prototype as updated // mark prototype as updated
proto.markUpdated(); proto.markUpdated();
} } else if (fname.endsWith(".hsp")) {
else if (fname.endsWith (".hsp")) {
String name = fname.substring(0, fname.lastIndexOf(".")); String name = fname.substring(0, fname.lastIndexOf("."));
String sourceName = file.getName() + "/" + ename; String sourceName = file.getName() + "/" + ename;
String content = getZipEntryContent(zip, entry); String content = getZipEntryContent(zip, entry);
// System.err.println ("["+content+"]"); // System.err.println ("["+content+"]");
Template tmp = new Template(content, name, sourceName, proto); Template tmp = new Template(content, name, sourceName, proto);
proto.addTemplate(tmp); proto.addTemplate(tmp);
updatables.add(tmp); updatables.add(tmp);
// mark prototype as updated // mark prototype as updated
proto.markUpdated(); proto.markUpdated();
} } else if (fname.endsWith(".skin")) {
else if (fname.endsWith (".skin")) {
String name = fname.substring(0, fname.lastIndexOf(".")); String name = fname.substring(0, fname.lastIndexOf("."));
String content = getZipEntryContent(zip, entry); String content = getZipEntryContent(zip, entry);
// System.err.println ("["+content+"]"); // System.err.println ("["+content+"]");
SkinFile skin = new SkinFile(content, name, proto); SkinFile skin = new SkinFile(content, name, proto);
proto.addSkinFile(skin); proto.addSkinFile(skin);
updatables.add(skin); updatables.add(skin);
} } else if (fname.endsWith(".js")) {
else if (fname.endsWith (".js")) {
String sourceName = file.getName() + "/" + ename; String sourceName = file.getName() + "/" + ename;
String content = getZipEntryContent(zip, entry); String content = getZipEntryContent(zip, entry);
// System.err.println ("["+content+"]"); // System.err.println ("["+content+"]");
FunctionFile ff = new FunctionFile(content, sourceName, proto); FunctionFile ff = new FunctionFile(content, sourceName, proto);
proto.addFunctionFile(ff); proto.addFunctionFile(ff);
updatables.add(ff); updatables.add(ff);
// mark prototype as updated // mark prototype as updated
proto.markUpdated(); proto.markUpdated();
} } else if ("type.properties".equalsIgnoreCase(fname)) {
else if ("type.properties".equalsIgnoreCase (fname)) {
DbMapping dbmap = proto.getDbMapping(); DbMapping dbmap = proto.getDbMapping();
SystemProperties props = dbmap.getProperties(); SystemProperties props = dbmap.getProperties();
props.addProps(file.getName(), zip.getInputStream(entry)); props.addProps(file.getName(), zip.getInputStream(entry));
// mark prototype as updated // mark prototype as updated
proto.markUpdated(); proto.markUpdated();
} }
@ -124,37 +156,53 @@ public class ZippedAppFile implements Updatable {
} finally { } finally {
try { try {
zip.close(); zip.close();
} catch (Exception ignore) {} } catch (Exception ignore) {
}
}
} }
} }
} /**
*
*/
public void remove() { public void remove() {
if (updatables != null) { if (updatables != null) {
for (Iterator it = updatables.iterator(); it.hasNext();) for (Iterator it = updatables.iterator(); it.hasNext();)
((Updatable) it.next()).remove(); ((Updatable) it.next()).remove();
} }
app.typemgr.removeZipFile(file.getName()); app.typemgr.removeZipFile(file.getName());
// System.err.println ("REMOVING ZIP FILE "+this); // System.err.println ("REMOVING ZIP FILE "+this);
} }
/**
public String getZipEntryContent (ZipFile zip, ZipEntry entry) throws IOException { *
*
* @param zip ...
* @param entry ...
*
* @return ...
*
* @throws IOException ...
*/
public String getZipEntryContent(ZipFile zip, ZipEntry entry)
throws IOException {
int size = (int) entry.getSize(); int size = (int) entry.getSize();
char[] c = new char[size]; char[] c = new char[size];
InputStreamReader reader = new InputStreamReader(zip.getInputStream(entry)); InputStreamReader reader = new InputStreamReader(zip.getInputStream(entry));
reader.read(c); reader.read(c);
return new String(c); return new String(c);
} }
/**
*
*
* @return ...
*/
public String toString() { public String toString() {
return file.getName(); return file.getName();
} }
} }

View file

@ -1,5 +1,18 @@
// SimplePathElement.java /*
// Copyright Hannes Wallnöfer 2001 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.framework.demo; package helma.framework.demo;
@ -9,9 +22,7 @@ import helma.framework.IPathElement;
* This is an example implementation for the helma.framework.IPathElement interface. * This is an example implementation for the helma.framework.IPathElement interface.
* It creates any child element which is requested on the fly without ever asking. * It creates any child element which is requested on the fly without ever asking.
*/ */
public class SimplePathElement implements IPathElement { public class SimplePathElement implements IPathElement {
String name; String name;
String prototype; String prototype;
IPathElement parent; IPathElement parent;
@ -69,6 +80,4 @@ public class SimplePathElement implements IPathElement {
public String toString() { public String toString() {
return "SimplePathElement " + name; return "SimplePathElement " + name;
} }
} }

View file

@ -1,126 +1,217 @@
// ImageGenerator.java /*
// Copyright (c) Hannes Wallnöfer 1999-2000 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.image; package helma.image;
import java.awt.*; import java.awt.*;
import java.awt.image.*; import java.awt.image.*;
import java.net.URL;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL;
/** /**
* Factory class for generating Image objects from various sources. * Factory class for generating Image objects from various sources.
* *
*/ */
public class ImageGenerator { public class ImageGenerator {
/**
* Creates a new ImageGenerator object.
*/
public ImageGenerator() { public ImageGenerator() {
// nothing to do // nothing to do
} }
/**
*
*
* @param w ...
* @param h ...
*
* @return ...
*/
public ImageWrapper createPaintableImage(int w, int h) { public ImageWrapper createPaintableImage(int w, int h) {
BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Graphics g = img.getGraphics(); Graphics g = img.getGraphics();
ImageWrapper rimg = new SunImageWrapper(img, g, w, h, this); ImageWrapper rimg = new SunImageWrapper(img, g, w, h, this);
return rimg; return rimg;
} }
public ImageWrapper createPaintableImage (byte src[]) { /**
*
*
* @param src ...
*
* @return ...
*/
public ImageWrapper createPaintableImage(byte[] src) {
ImageWrapper rimg = null; ImageWrapper rimg = null;
Image img1 = Toolkit.getDefaultToolkit().createImage(src); Image img1 = Toolkit.getDefaultToolkit().createImage(src);
ImageLoader loader = new ImageLoader(img1); ImageLoader loader = new ImageLoader(img1);
try { try {
loader.getDimensions(); loader.getDimensions();
int w = loader.getWidth(); int w = loader.getWidth();
int h = loader.getHeight(); int h = loader.getHeight();
Image img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); Image img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Graphics g = img.getGraphics(); Graphics g = img.getGraphics();
g.drawImage(img1, 0, 0, null); g.drawImage(img1, 0, 0, null);
rimg = new SunImageWrapper(img, g, w, h, this); rimg = new SunImageWrapper(img, g, w, h, this);
} finally { } finally {
loader.done(); loader.done();
} }
return rimg; return rimg;
} }
public ImageWrapper createImage (byte src[]) { /**
*
*
* @param src ...
*
* @return ...
*/
public ImageWrapper createImage(byte[] src) {
ImageWrapper rimg = null; ImageWrapper rimg = null;
Image img = Toolkit.getDefaultToolkit().createImage(src); Image img = Toolkit.getDefaultToolkit().createImage(src);
ImageLoader loader = new ImageLoader(img); ImageLoader loader = new ImageLoader(img);
try { try {
loader.getDimensions(); loader.getDimensions();
int w = loader.getWidth(); int w = loader.getWidth();
int h = loader.getHeight(); int h = loader.getHeight();
rimg = new SunImageWrapper(img, null, w, h, this); rimg = new SunImageWrapper(img, null, w, h, this);
} finally { } finally {
loader.done(); loader.done();
} }
return rimg; return rimg;
} }
/**
public ImageWrapper createPaintableImage (String urlstring) throws MalformedURLException { *
*
* @param urlstring ...
*
* @return ...
*
* @throws MalformedURLException ...
*/
public ImageWrapper createPaintableImage(String urlstring)
throws MalformedURLException {
ImageWrapper rimg = null; ImageWrapper rimg = null;
URL url = new URL(urlstring); URL url = new URL(urlstring);
Image img1 = Toolkit.getDefaultToolkit().createImage(url); Image img1 = Toolkit.getDefaultToolkit().createImage(url);
ImageLoader loader = new ImageLoader(img1); ImageLoader loader = new ImageLoader(img1);
try { try {
loader.getDimensions(); loader.getDimensions();
int w = loader.getWidth(); int w = loader.getWidth();
int h = loader.getHeight(); int h = loader.getHeight();
Image img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); Image img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Graphics g = img.getGraphics(); Graphics g = img.getGraphics();
g.drawImage(img1, 0, 0, null); g.drawImage(img1, 0, 0, null);
rimg = new SunImageWrapper(img, g, w, h, this); rimg = new SunImageWrapper(img, g, w, h, this);
} finally { } finally {
loader.done(); loader.done();
} }
return rimg; return rimg;
} }
/**
*
*
* @param iw ...
* @param filter ...
*
* @return ...
*/
public ImageWrapper createPaintableImage(ImageWrapper iw, ImageFilter filter) { public ImageWrapper createPaintableImage(ImageWrapper iw, ImageFilter filter) {
ImageWrapper rimg = null; ImageWrapper rimg = null;
FilteredImageSource fis = new FilteredImageSource(iw.getSource(), filter); FilteredImageSource fis = new FilteredImageSource(iw.getSource(), filter);
Image img1 = Toolkit.getDefaultToolkit().createImage(fis); Image img1 = Toolkit.getDefaultToolkit().createImage(fis);
ImageLoader loader = new ImageLoader(img1); ImageLoader loader = new ImageLoader(img1);
try { try {
loader.getDimensions(); loader.getDimensions();
int w = loader.getWidth(); int w = loader.getWidth();
int h = loader.getHeight(); int h = loader.getHeight();
Image img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); Image img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Graphics g = img.getGraphics(); Graphics g = img.getGraphics();
g.drawImage(img1, 0, 0, null); g.drawImage(img1, 0, 0, null);
rimg = new SunImageWrapper(img, g, w, h, this); rimg = new SunImageWrapper(img, g, w, h, this);
} finally { } finally {
loader.done(); loader.done();
} }
return rimg; return rimg;
} }
/**
*
*
* @param filename ...
*
* @return ...
*/
public Image createImage(String filename) { public Image createImage(String filename) {
Image img = null; Image img = null;
img = Toolkit.getDefaultToolkit().createImage(filename); img = Toolkit.getDefaultToolkit().createImage(filename);
ImageLoader loader = new ImageLoader(img); ImageLoader loader = new ImageLoader(img);
loader.getDimensions(); loader.getDimensions();
loader.done(); loader.done();
return img; return img;
} }
/**
*
*
* @param producer ...
*
* @return ...
*/
public Image createImage(ImageProducer producer) { public Image createImage(ImageProducer producer) {
Image img = null; Image img = null;
img = Toolkit.getDefaultToolkit().createImage(producer); img = Toolkit.getDefaultToolkit().createImage(producer);
ImageLoader loader = new ImageLoader(img); ImageLoader loader = new ImageLoader(img);
loader.getDimensions(); loader.getDimensions();
loader.done(); loader.done();
return img; return img;
} }
class ImageLoader implements ImageObserver { class ImageLoader implements ImageObserver {
Image img; Image img;
int w, h; int w;
int h;
boolean waiting; boolean waiting;
boolean firstFrameLoaded; boolean firstFrameLoaded;
@ -133,18 +224,21 @@ public class ImageGenerator {
synchronized void getDimensions() { synchronized void getDimensions() {
w = img.getWidth(this); w = img.getWidth(this);
h = img.getHeight(this); h = img.getHeight(this);
if (w == -1 || h == -1) {
if ((w == -1) || (h == -1)) {
try { try {
wait(45000); wait(45000);
} catch (InterruptedException x) { } catch (InterruptedException x) {
waiting = false; waiting = false;
return; return;
} finally { } finally {
waiting = false; waiting = false;
} }
} }
// if width and height haven't been set, throw tantrum // if width and height haven't been set, throw tantrum
if (w == -1 || h == -1) { if ((w == -1) || (h == -1)) {
throw new RuntimeException("Error loading image"); throw new RuntimeException("Error loading image");
} }
} }
@ -162,37 +256,40 @@ public class ImageGenerator {
return h; return h;
} }
public synchronized boolean imageUpdate(Image img, public synchronized boolean imageUpdate(Image img, int infoflags, int x, int y,
int infoflags, int width, int height) {
int x,
int y,
int width,
int height) {
// check if there was an error // check if there was an error
if (!waiting || (infoflags & ERROR) > 0 || (infoflags & ABORT) > 0) { if (!waiting || ((infoflags & ERROR) > 0) || ((infoflags & ABORT) > 0)) {
// we either timed out or there was an error. // we either timed out or there was an error.
notifyAll(); notifyAll();
return false; return false;
} }
if ((infoflags & WIDTH) > 0 || (infoflags & HEIGHT) > 0) {
if ((infoflags & WIDTH) > 0) if (((infoflags & WIDTH) > 0) || ((infoflags & HEIGHT) > 0)) {
if ((infoflags & WIDTH) > 0) {
w = width; w = width;
if ((infoflags & HEIGHT) > 0) }
if ((infoflags & HEIGHT) > 0) {
h = height; h = height;
if (w > -1 && h > -1 && firstFrameLoaded) { }
if ((w > -1) && (h > -1) && firstFrameLoaded) {
notifyAll(); notifyAll();
return false; return false;
} }
} }
if ((infoflags & ALLBITS) > 0 || (infoflags & FRAMEBITS) > 0) {
if (((infoflags & ALLBITS) > 0) || ((infoflags & FRAMEBITS) > 0)) {
firstFrameLoaded = true; firstFrameLoaded = true;
notifyAll(); notifyAll();
return false; return false;
} }
return true; return true;
} }
} }
} }

View file

@ -1,36 +1,61 @@
// ImageWrapper.java /*
// Copyright (c) Hannes Wallnöfer 1999-2000 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.image; package helma.image;
import java.awt.*; import java.awt.*;
import java.awt.image.*; import java.awt.image.*;
import java.util.*; import java.io.*;
import java.rmi.*; import java.rmi.*;
import java.rmi.server.*; import java.rmi.server.*;
import java.io.*; import java.util.*;
/** /**
* Abstract base class for Image Wrappers. * Abstract base class for Image Wrappers.
*/ */
public abstract class ImageWrapper { public abstract class ImageWrapper {
Image img; Image img;
Graphics g; Graphics g;
int width, height; int width;
int fontstyle, fontsize; int height;
int fontstyle;
int fontsize;
String fontname; String fontname;
ImageGenerator imggen; ImageGenerator imggen;
public ImageWrapper (Image img, Graphics g, int width, int height, ImageGenerator imggen) { /**
* Creates a new ImageWrapper object.
*
* @param img ...
* @param g ...
* @param width ...
* @param height ...
* @param imggen ...
*/
public ImageWrapper(Image img, Graphics g, int width, int height,
ImageGenerator imggen) {
this.img = img; this.img = img;
this.g = g; this.g = g;
this.width = width; this.width = width;
this.height = height; this.height = height;
this.imggen = imggen; this.imggen = imggen;
if (g != null) { if (g != null) {
Font f = g.getFont(); Font f = g.getFont();
fontname = f.getName(); fontname = f.getName();
fontstyle = f.getStyle(); fontstyle = f.getStyle();
fontsize = f.getSize(); fontsize = f.getSize();
@ -40,7 +65,6 @@ public abstract class ImageWrapper {
/** /**
* image manipulation methods * image manipulation methods
*/ */
public void setFont(String name, int style, int size) { public void setFont(String name, int style, int size) {
this.fontname = name; this.fontname = name;
this.fontstyle = style; this.fontstyle = style;
@ -48,65 +72,158 @@ public abstract class ImageWrapper {
g.setFont(new Font(name, style, size)); g.setFont(new Font(name, style, size));
} }
/**
*
*
* @param red ...
* @param green ...
* @param blue ...
*/
public void setColor(int red, int green, int blue) { public void setColor(int red, int green, int blue) {
g.setColor(new Color(red, green, blue)); g.setColor(new Color(red, green, blue));
} }
/**
*
*
* @param color ...
*/
public void setColor(int color) { public void setColor(int color) {
g.setColor(new Color(color)); g.setColor(new Color(color));
} }
/**
*
*
* @param str ...
* @param x ...
* @param y ...
*/
public void drawString(String str, int x, int y) { public void drawString(String str, int x, int y) {
g.drawString(str, x, y); g.drawString(str, x, y);
} }
/**
*
*
* @param x1 ...
* @param y1 ...
* @param x2 ...
* @param y2 ...
*/
public void drawLine(int x1, int y1, int x2, int y2) { public void drawLine(int x1, int y1, int x2, int y2) {
g.drawLine(x1, y1, x2, y2); g.drawLine(x1, y1, x2, y2);
} }
/**
*
*
* @param x ...
* @param y ...
* @param w ...
* @param h ...
*/
public void drawRect(int x, int y, int w, int h) { public void drawRect(int x, int y, int w, int h) {
g.drawRect(x, y, w, h); g.drawRect(x, y, w, h);
} }
/**
*
*
* @param filename ...
* @param x ...
* @param y ...
*/
public void drawImage(String filename, int x, int y) { public void drawImage(String filename, int x, int y) {
try { try {
Image i = imggen.createImage(filename); Image i = imggen.createImage(filename);
g.drawImage(i, x, y, null); g.drawImage(i, x, y, null);
} catch (Exception ignore) {} } catch (Exception ignore) {
}
} }
/**
*
*
* @param x ...
* @param y ...
* @param w ...
* @param h ...
*/
public void fillRect(int x, int y, int w, int h) { public void fillRect(int x, int y, int w, int h) {
g.fillRect(x, y, w, h); g.fillRect(x, y, w, h);
} }
/**
*
*
* @return ...
*/
public int getWidth() { public int getWidth() {
return width; return width;
} }
/**
*
*
* @return ...
*/
public int getHeight() { public int getHeight() {
return height; return height;
} }
/**
*
*
* @param x ...
* @param y ...
* @param w ...
* @param h ...
*/
public void crop(int x, int y, int w, int h) { public void crop(int x, int y, int w, int h) {
ImageFilter filter = new CropImageFilter(x, y, w, h); ImageFilter filter = new CropImageFilter(x, y, w, h);
img = Toolkit.getDefaultToolkit ().createImage(new FilteredImageSource(img.getSource(), filter));
img = Toolkit.getDefaultToolkit().createImage(new FilteredImageSource(img.getSource(),
filter));
} }
/**
*
*
* @param w ...
* @param h ...
*/
public void resize(int w, int h) { public void resize(int w, int h) {
img = img.getScaledInstance(w, h, Image.SCALE_SMOOTH); img = img.getScaledInstance(w, h, Image.SCALE_SMOOTH);
width = w; width = w;
height = h; height = h;
} }
/**
*
*
* @param w ...
* @param h ...
*/
public void resizeFast(int w, int h) { public void resizeFast(int w, int h) {
img = img.getScaledInstance(w, h, Image.SCALE_FAST); img = img.getScaledInstance(w, h, Image.SCALE_FAST);
width = w; width = w;
height = h; height = h;
} }
/**
*
*
* @param colors ...
*/
public abstract void reduceColors(int colors); public abstract void reduceColors(int colors);
/**
*
*
* @param filename ...
*/
public abstract void saveAs(String filename); public abstract void saveAs(String filename);
/** /**
@ -116,21 +233,40 @@ public abstract class ImageWrapper {
return img.getSource(); return img.getSource();
} }
/**
*
*
* @param str ...
*/
public void fillString(String str) { public void fillString(String str) {
Filler filler = new Filler(0, 0, width, height); Filler filler = new Filler(0, 0, width, height);
filler.layout(str); filler.layout(str);
} }
/**
*
*
* @param str ...
* @param x ...
* @param y ...
* @param w ...
* @param h ...
*/
public void fillString(String str, int x, int y, int w, int h) { public void fillString(String str, int x, int y, int w, int h) {
Filler filler = new Filler(x, y, w, h); Filler filler = new Filler(x, y, w, h);
filler.layout(str); filler.layout(str);
} }
class Filler { class Filler {
int x;
int x, y, w, h; int y;
int w;
int h;
int addedSpace = 0; int addedSpace = 0;
int xLeft, yLeft; int xLeft;
int yLeft;
int realHeight; int realHeight;
transient Vector lines; transient Vector lines;
@ -143,22 +279,28 @@ public abstract class ImageWrapper {
public void layout(String str) { public void layout(String str) {
int size = fontsize; int size = fontsize;
lines = new Vector(); lines = new Vector();
while (!splitMessage (str, size) && size > 10) {
while (!splitMessage(str, size) && (size > 10)) {
lines.setSize(0); lines.setSize(0);
size = Math.max(2, size - 1); size = Math.max(2, size - 1);
} }
Font oldfont = g.getFont(); Font oldfont = g.getFont();
g.setFont(new Font(fontname, fontstyle, size)); g.setFont(new Font(fontname, fontstyle, size));
int l = lines.size(); int l = lines.size();
for (int i = 0; i < l; i++) { for (int i = 0; i < l; i++) {
((Line) lines.elementAt (i)).paint (g, xLeft/2, yLeft/2 + y); ((Line) lines.elementAt(i)).paint(g, xLeft / 2, (yLeft / 2) + y);
} }
g.setFont(oldfont); g.setFont(oldfont);
} }
private boolean splitMessage(String string, int size) { private boolean splitMessage(String string, int size) {
Font font = new Font(fontname, fontstyle, size); Font font = new Font(fontname, fontstyle, size);
FontMetrics metrics = Toolkit.getDefaultToolkit().getFontMetrics(font); FontMetrics metrics = Toolkit.getDefaultToolkit().getFontMetrics(font);
int longestLine = 0; int longestLine = 0;
@ -169,54 +311,70 @@ public abstract class ImageWrapper {
int spaceWidth = metrics.stringWidth(" "); int spaceWidth = metrics.stringWidth(" ");
int currentLine = 0; int currentLine = 0;
int currentWidth = 0; int currentWidth = 0;
int maxWidth = w - 2, maxHeight = h + addedSpace - 2; int maxWidth = w - 2;
int maxHeight = (h + addedSpace) - 2;
while (tk.hasMoreTokens()) { while (tk.hasMoreTokens()) {
String nextToken = tk.nextToken(); String nextToken = tk.nextToken();
int nextWidth = metrics.stringWidth(nextToken); int nextWidth = metrics.stringWidth(nextToken);
if ((currentWidth + nextWidth >= maxWidth && currentWidth != 0)) {
if ((((currentWidth + nextWidth) >= maxWidth) && (currentWidth != 0))) {
Line line = new Line(buffer.toString(), x, heightSoFar, metrics); Line line = new Line(buffer.toString(), x, heightSoFar, metrics);
lines.addElement(line); lines.addElement(line);
if (line.textwidth > longestLine)
if (line.textwidth > longestLine) {
longestLine = line.textwidth; longestLine = line.textwidth;
}
buffer = new StringBuffer(); buffer = new StringBuffer();
currentWidth = 0; currentWidth = 0;
heightSoFar += heightIncrement; heightSoFar += heightIncrement;
} }
buffer.append(nextToken); buffer.append(nextToken);
buffer.append(" "); buffer.append(" ");
currentWidth += (nextWidth + spaceWidth); currentWidth += (nextWidth + spaceWidth);
if (1.18*heightSoFar > maxHeight && fontsize > 10)
if (((1.18 * heightSoFar) > maxHeight) && (fontsize > 10)) {
return false; return false;
} }
}
if (!"".equals(buffer.toString().trim())) { if (!"".equals(buffer.toString().trim())) {
Line line = new Line(buffer.toString(), x, heightSoFar, metrics); Line line = new Line(buffer.toString(), x, heightSoFar, metrics);
lines.addElement(line); lines.addElement(line);
if (line.textwidth > longestLine) if (line.textwidth > longestLine) {
longestLine = line.textwidth; longestLine = line.textwidth;
if (longestLine > maxWidth && fontsize > 10) }
if ((longestLine > maxWidth) && (fontsize > 10)) {
return false; return false;
}
heightSoFar += heightIncrement; heightSoFar += heightIncrement;
} }
xLeft = w - longestLine; xLeft = w - longestLine;
yLeft = addedSpace + h - heightSoFar; yLeft = (addedSpace + h) - heightSoFar;
realHeight = heightSoFar; realHeight = heightSoFar;
return (1.18*heightSoFar <= maxHeight);
}
return ((1.18 * heightSoFar) <= maxHeight);
}
} }
class Line implements Serializable { class Line implements Serializable {
String text; String text;
int xoff, yoff; int xoff;
int yoff;
FontMetrics fm; FontMetrics fm;
public int textwidth, len; public int textwidth;
public int len;
int ascent; int ascent;
public Line(String text, int xoff, int yoff, FontMetrics fm) { public Line(String text, int xoff, int yoff, FontMetrics fm) {
this.text = text.trim(); this.text = text.trim();
len = text.length(); len = text.length();
@ -231,17 +389,8 @@ public abstract class ImageWrapper {
g.drawString(text, xoff + xadd, yoff + ascent + yadd); g.drawString(text, xoff + xadd, yoff + ascent + yadd);
} }
public boolean contains(int y) { public boolean contains(int y) {
return (y < yoff+fm.getHeight()) ? true : false; return (y < (yoff + fm.getHeight())) ? true : false;
} }
} }
} }

View file

@ -1,42 +1,68 @@
// ActivatedImageWrapper.java /*
// Copyright (c) Hannes Wallnöfer 1999-2000 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.image; package helma.image;
import java.awt.*; import Acme.JPM.Encoders.GifEncoder;
import java.awt.image.*;
import com.sun.jimi.core.*; import com.sun.jimi.core.*;
import com.sun.jimi.core.util.*; import com.sun.jimi.core.util.*;
import Acme.JPM.Encoders.GifEncoder; import java.awt.*;
import java.io.IOException; import java.awt.image.*;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException;
/** /**
* A wrapper for an image that uses the Sun version of JIMI available at * A wrapper for an image that uses the Sun version of JIMI available at
* http://java.sun.com/products/jimi. * http://java.sun.com/products/jimi.
*/ */
public class SunImageWrapper extends ImageWrapper { public class SunImageWrapper extends ImageWrapper {
/**
* Creates a new SunImageWrapper object.
*
* @param img ...
* @param g ...
* @param width ...
* @param height ...
* @param imggen ...
*/
public SunImageWrapper(Image img, Graphics g, int width, int height, public SunImageWrapper(Image img, Graphics g, int width, int height,
ImageGenerator imggen) { ImageGenerator imggen) {
super(img, g, width, height, imggen); super(img, g, width, height, imggen);
} }
/**
*
*
* @param colors ...
*/
public void reduceColors(int colors) { public void reduceColors(int colors) {
try { try {
int pixels[][] = getPixels(); int[][] pixels = getPixels();
int palette[] = Quantize.quantizeImage(pixels, colors); int[] palette = Quantize.quantizeImage(pixels, colors);
int w = pixels.length; int w = pixels.length;
int h = pixels[0].length; int h = pixels[0].length;
int pix[] = new int[w * h]; int[] pix = new int[w * h];
// convert to RGB // convert to RGB
for (int x = w; x-- > 0;) { for (int x = w; x-- > 0;) {
for (int y = h; y-- > 0;) { for (int y = h; y-- > 0;) {
pix[y * w + x] = palette[pixels[x][y]]; pix[(y * w) + x] = palette[pixels[x][y]];
} }
} }
img = imggen.createImage(new MemoryImageSource(w, h, pix, 0, w)); img = imggen.createImage(new MemoryImageSource(w, h, pix, 0, w));
} catch (Exception x) { } catch (Exception x) {
// throw new RuntimeException (x.getMessage ()); // throw new RuntimeException (x.getMessage ());
@ -47,8 +73,9 @@ public class SunImageWrapper extends ImageWrapper {
* Snag the pixels from an image. * Snag the pixels from an image.
*/ */
int[][] getPixels() throws IOException { int[][] getPixels() throws IOException {
int pix[] = new int[width * height]; int[] pix = new int[width * height];
PixelGrabber grabber = new PixelGrabber(img, 0, 0, width, height, pix, 0, width); PixelGrabber grabber = new PixelGrabber(img, 0, 0, width, height, pix, 0, width);
try { try {
if (grabber.grabPixels() != true) { if (grabber.grabPixels() != true) {
throw new IOException("Grabber returned false: " + grabber.status()); throw new IOException("Grabber returned false: " + grabber.status());
@ -56,23 +83,32 @@ public class SunImageWrapper extends ImageWrapper {
} catch (InterruptedException e) { } catch (InterruptedException e) {
e.printStackTrace(); e.printStackTrace();
} }
int pixels[][] = new int[width][height];
int[][] pixels = new int[width][height];
for (int x = width; x-- > 0;) { for (int x = width; x-- > 0;) {
for (int y = height; y-- > 0;) { for (int y = height; y-- > 0;) {
pixels[x][y] = pix[y * width + x]; pixels[x][y] = pix[(y * width) + x];
} }
} }
return pixels; return pixels;
} }
/**
*
*
* @param filename ...
*/
public void saveAs(String filename) { public void saveAs(String filename) {
try { try {
if (filename.toLowerCase().endsWith(".gif")) { if (filename.toLowerCase().endsWith(".gif")) {
// sun's jimi package doesn't encode gifs, use Acme encoder // sun's jimi package doesn't encode gifs, use Acme encoder
FileOutputStream fout = new FileOutputStream(filename); FileOutputStream fout = new FileOutputStream(filename);
// Acme gif encoder // Acme gif encoder
GifEncoder enc = new GifEncoder(img, fout); GifEncoder enc = new GifEncoder(img, fout);
enc.encode(); enc.encode();
fout.close(); fout.close();
} else { } else {
@ -82,6 +118,4 @@ public class SunImageWrapper extends ImageWrapper {
throw new RuntimeException(x.getMessage()); throw new RuntimeException(x.getMessage());
} }
} }
} }

View file

@ -1,33 +1,43 @@
// ApplicationManager.java /*
// Copyright (c) Hannes Wallnöfer 1998-2000 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.main; package helma.main;
import java.util.*;
import java.io.*;
import java.lang.reflect.*;
import java.rmi.*;
import java.rmi.server.*;
import java.net.URLEncoder;
import helma.framework.*; import helma.framework.*;
import helma.framework.core.*; import helma.framework.core.*;
import helma.objectmodel.*; import helma.objectmodel.*;
import helma.servlet.*; import helma.servlet.*;
import helma.util.SystemProperties; import helma.util.SystemProperties;
import org.apache.xmlrpc.XmlRpcHandler;
import org.mortbay.http.*; import org.mortbay.http.*;
import org.mortbay.http.handler.*; import org.mortbay.http.handler.*;
import org.mortbay.jetty.servlet.*; import org.mortbay.jetty.servlet.*;
import org.mortbay.util.*; import org.mortbay.util.*;
import java.io.*;
import java.lang.reflect.*;
import java.net.URLEncoder;
import java.rmi.*;
import java.rmi.server.*;
import java.util.*;
import javax.servlet.Servlet; import javax.servlet.Servlet;
import org.apache.xmlrpc.XmlRpcHandler;
/** /**
* This class is responsible for starting and stopping Helma applications. * This class is responsible for starting and stopping Helma applications.
*/ */
public class ApplicationManager implements XmlRpcHandler { public class ApplicationManager implements XmlRpcHandler {
private Hashtable applications; private Hashtable applications;
private Hashtable xmlrpcHandlers; private Hashtable xmlrpcHandlers;
private Properties mountpoints; private Properties mountpoints;
@ -37,7 +47,16 @@ public class ApplicationManager implements XmlRpcHandler {
private Server server; private Server server;
private long lastModified; private long lastModified;
public ApplicationManager (int port, File hopHome, SystemProperties props, Server server) { /**
* Creates a new ApplicationManager object.
*
* @param port ...
* @param hopHome ...
* @param props ...
* @param server ...
*/
public ApplicationManager(int port, File hopHome, SystemProperties props,
Server server) {
this.port = port; this.port = port;
this.hopHome = hopHome; this.hopHome = hopHome;
this.props = props; this.props = props;
@ -48,21 +67,24 @@ public class ApplicationManager implements XmlRpcHandler {
lastModified = 0; lastModified = 0;
} }
// regularely check applications property file to create and start new applications // regularely check applications property file to create and start new applications
protected void checkForChanges() { protected void checkForChanges() {
if (props.lastModified() > lastModified) { if (props.lastModified() > lastModified) {
try { try {
for (Enumeration e = props.keys(); e.hasMoreElements();) { for (Enumeration e = props.keys(); e.hasMoreElements();) {
String appName = (String) e.nextElement(); String appName = (String) e.nextElement();
if (appName.indexOf (".") == -1 && applications.get (appName) == null) {
if ((appName.indexOf(".") == -1) &&
(applications.get(appName) == null)) {
start(appName); start(appName);
register(appName); register(appName);
} }
} }
// then stop deleted ones // then stop deleted ones
for (Enumeration e = applications.keys(); e.hasMoreElements();) { for (Enumeration e = applications.keys(); e.hasMoreElements();) {
String appName = (String) e.nextElement(); String appName = (String) e.nextElement();
// check if application has been removed and should be stopped // check if application has been removed and should be stopped
if (!props.containsKey(appName)) { if (!props.containsKey(appName)) {
stop(appName); stop(appName);
@ -72,31 +94,57 @@ public class ApplicationManager implements XmlRpcHandler {
String oldMountpoint = mountpoints.getProperty(appName); String oldMountpoint = mountpoints.getProperty(appName);
String mountpoint = getMountpoint(appName); String mountpoint = getMountpoint(appName);
String pattern = getPathPattern(mountpoint); String pattern = getPathPattern(mountpoint);
if (!pattern.equals(oldMountpoint)) { if (!pattern.equals(oldMountpoint)) {
Server.getLogger().log("Moving application "+appName+" from "+oldMountpoint+" to "+pattern); Server.getLogger().log("Moving application " + appName +
HttpContext oldContext = server.http.getContext (null, oldMountpoint); " from " + oldMountpoint + " to " +
pattern);
HttpContext oldContext = server.http.getContext(null,
oldMountpoint);
if (oldContext != null) { if (oldContext != null) {
// oldContext.setContextPath(pattern); // oldContext.setContextPath(pattern);
oldContext.stop(); oldContext.stop();
oldContext.destroy(); oldContext.destroy();
} }
Application app = (Application) applications.get(appName); Application app = (Application) applications.get(appName);
if (!app.hasExplicitBaseURI())
if (!app.hasExplicitBaseURI()) {
app.setBaseURI(mountpoint); app.setBaseURI(mountpoint);
}
ServletHttpContext context = new ServletHttpContext(); ServletHttpContext context = new ServletHttpContext();
context.setContextPath(pattern); context.setContextPath(pattern);
server.http.addContext(context); server.http.addContext(context);
ServletHolder holder = context.addServlet (appName, "/*", "helma.servlet.EmbeddedServletClient");
ServletHolder holder = context.addServlet(appName, "/*",
"helma.servlet.EmbeddedServletClient");
holder.setInitParameter("application", appName); holder.setInitParameter("application", appName);
holder.setInitParameter("mountpoint", mountpoint); holder.setInitParameter("mountpoint", mountpoint);
if ("true".equalsIgnoreCase (props.getProperty (appName+".responseEncoding")))
if ("true".equalsIgnoreCase(props.getProperty(appName +
".responseEncoding"))) {
context.addHandler(new ContentEncodingHandler()); context.addHandler(new ContentEncodingHandler());
String cookieDomain = props.getProperty (appName+".cookieDomain"); }
if (cookieDomain != null)
String cookieDomain = props.getProperty(appName +
".cookieDomain");
if (cookieDomain != null) {
holder.setInitParameter("cookieDomain", cookieDomain); holder.setInitParameter("cookieDomain", cookieDomain);
String uploadLimit = props.getProperty (appName+".uploadLimit"); }
if (uploadLimit != null)
String uploadLimit = props.getProperty(appName +
".uploadLimit");
if (uploadLimit != null) {
holder.setInitParameter("uploadLimit", uploadLimit); holder.setInitParameter("uploadLimit", uploadLimit);
}
// holder.start (); // holder.start ();
context.start(); context.start();
mountpoints.setProperty(appName, pattern); mountpoints.setProperty(appName, pattern);
@ -113,16 +161,20 @@ public class ApplicationManager implements XmlRpcHandler {
void start(String appName) { void start(String appName) {
Server.getLogger().log("Building application " + appName); Server.getLogger().log("Building application " + appName);
try { try {
// check if application and db dirs are set, otherwise go with // check if application and db dirs are set, otherwise go with
// the defaults, passing null dirs to the constructor. // the defaults, passing null dirs to the constructor.
String appDirName = props.getProperty(appName + ".appdir"); String appDirName = props.getProperty(appName + ".appdir");
File appDir = appDirName == null ? null : new File (appDirName); File appDir = (appDirName == null) ? null : new File(appDirName);
String dbDirName = props.getProperty(appName + ".dbdir"); String dbDirName = props.getProperty(appName + ".dbdir");
File dbDir = dbDirName == null ? null : new File (dbDirName); File dbDir = (dbDirName == null) ? null : new File(dbDirName);
// create the application instance // create the application instance
Application app = new Application(appName, server, appDir, dbDir); Application app = new Application(appName, server, appDir, dbDir);
applications.put(appName, app); applications.put(appName, app);
// the application is started later in the register method, when it's bound // the application is started later in the register method, when it's bound
app.init(); app.init();
} catch (Exception x) { } catch (Exception x) {
@ -133,21 +185,26 @@ public class ApplicationManager implements XmlRpcHandler {
void stop(String appName) { void stop(String appName) {
Server.getLogger().log("Stopping application " + appName); Server.getLogger().log("Stopping application " + appName);
try { try {
Application app = (Application) applications.get(appName); Application app = (Application) applications.get(appName);
// unbind from RMI server // unbind from RMI server
if (port > 0) { if (port > 0) {
Naming.unbind("//:" + port + "/" + appName); Naming.unbind("//:" + port + "/" + appName);
} }
// unbind from Jetty HTTP server // unbind from Jetty HTTP server
if (server.http != null) { if (server.http != null) {
String mountpoint = mountpoints.getProperty(appName); String mountpoint = mountpoints.getProperty(appName);
HttpContext context = server.http.getContext(null, mountpoint); HttpContext context = server.http.getContext(null, mountpoint);
if (context != null) { if (context != null) {
context.stop(); context.stop();
context.destroy(); context.destroy();
} }
} }
// unregister as XML-RPC handler // unregister as XML-RPC handler
xmlrpcHandlers.remove(app.getXmlRpcHandlerName()); xmlrpcHandlers.remove(app.getXmlRpcHandlerName());
app.stop(); app.stop();
@ -155,45 +212,70 @@ public class ApplicationManager implements XmlRpcHandler {
} catch (Exception x) { } catch (Exception x) {
Server.getLogger().log("Couldn't unregister app: " + x); Server.getLogger().log("Couldn't unregister app: " + x);
} }
applications.remove(appName); applications.remove(appName);
} }
void register(String appName) { void register(String appName) {
try { try {
Server.getLogger().log("Binding application " + appName); Server.getLogger().log("Binding application " + appName);
Application app = (Application) applications.get(appName); Application app = (Application) applications.get(appName);
// bind to RMI server // bind to RMI server
if (port > 0) { if (port > 0) {
Naming.rebind("//:" + port + "/" + appName, new RemoteApplication(app)); Naming.rebind("//:" + port + "/" + appName, new RemoteApplication(app));
} }
// bind to Jetty HTTP server // bind to Jetty HTTP server
if (server.http != null) { if (server.http != null) {
String mountpoint = getMountpoint(appName); String mountpoint = getMountpoint(appName);
// if using embedded webserver (not AJP) set application URL prefix // if using embedded webserver (not AJP) set application URL prefix
if (!app.hasExplicitBaseURI ()) if (!app.hasExplicitBaseURI()) {
app.setBaseURI(mountpoint); app.setBaseURI(mountpoint);
}
String pattern = getPathPattern(mountpoint); String pattern = getPathPattern(mountpoint);
ServletHttpContext context = new ServletHttpContext(); ServletHttpContext context = new ServletHttpContext();
context.setContextPath(pattern); context.setContextPath(pattern);
server.http.addContext(context); server.http.addContext(context);
ServletHolder holder = context.addServlet (appName, "/*", "helma.servlet.EmbeddedServletClient");
ServletHolder holder = context.addServlet(appName, "/*",
"helma.servlet.EmbeddedServletClient");
holder.setInitParameter("application", appName); holder.setInitParameter("application", appName);
holder.setInitParameter("mountpoint", mountpoint); holder.setInitParameter("mountpoint", mountpoint);
if ("true".equalsIgnoreCase (props.getProperty (appName+".responseEncoding")))
if ("true".equalsIgnoreCase(props.getProperty(appName +
".responseEncoding"))) {
context.addHandler(new ContentEncodingHandler()); context.addHandler(new ContentEncodingHandler());
}
String cookieDomain = props.getProperty(appName + ".cookieDomain"); String cookieDomain = props.getProperty(appName + ".cookieDomain");
if (cookieDomain != null)
if (cookieDomain != null) {
holder.setInitParameter("cookieDomain", cookieDomain); holder.setInitParameter("cookieDomain", cookieDomain);
}
String uploadLimit = props.getProperty(appName + ".uploadLimit"); String uploadLimit = props.getProperty(appName + ".uploadLimit");
if (uploadLimit != null)
if (uploadLimit != null) {
holder.setInitParameter("uploadLimit", uploadLimit); holder.setInitParameter("uploadLimit", uploadLimit);
}
String debug = props.getProperty(appName + ".debug"); String debug = props.getProperty(appName + ".debug");
if (debug != null)
if (debug != null) {
holder.setInitParameter("debug", debug); holder.setInitParameter("debug", debug);
}
// holder.start (); // holder.start ();
context.start(); context.start();
mountpoints.setProperty(appName, pattern); mountpoints.setProperty(appName, pattern);
} }
// register as XML-RPC handler // register as XML-RPC handler
xmlrpcHandlers.put(app.getXmlRpcHandlerName(), app); xmlrpcHandlers.put(app.getXmlRpcHandlerName(), app);
app.start(); app.start();
@ -203,28 +285,44 @@ public class ApplicationManager implements XmlRpcHandler {
} }
} }
/**
*
*/
public void startAll() { public void startAll() {
try { try {
for (Enumeration e = props.keys(); e.hasMoreElements();) { for (Enumeration e = props.keys(); e.hasMoreElements();) {
String appName = (String) e.nextElement(); String appName = (String) e.nextElement();
if (appName.indexOf (".") == -1)
if (appName.indexOf(".") == -1) {
start(appName); start(appName);
} }
}
for (Enumeration e = props.keys(); e.hasMoreElements();) { for (Enumeration e = props.keys(); e.hasMoreElements();) {
String appName = (String) e.nextElement(); String appName = (String) e.nextElement();
if (appName.indexOf (".") == -1)
if (appName.indexOf(".") == -1) {
register(appName); register(appName);
} }
}
if (server.http != null) { if (server.http != null) {
// add handler for static files. // add handler for static files.
File staticContent = new File(server.getHopHome(), "static"); File staticContent = new File(server.getHopHome(), "static");
Server.getLogger().log("Serving static content from "+staticContent.getAbsolutePath());
Server.getLogger().log("Serving static content from " +
staticContent.getAbsolutePath());
HttpContext context = server.http.addContext("/static/*"); HttpContext context = server.http.addContext("/static/*");
context.setResourceBase(staticContent.getAbsolutePath()); context.setResourceBase(staticContent.getAbsolutePath());
ResourceHandler handler = new ResourceHandler(); ResourceHandler handler = new ResourceHandler();
context.addHandler(handler); context.addHandler(handler);
context.start(); context.start();
} }
lastModified = System.currentTimeMillis(); lastModified = System.currentTimeMillis();
} catch (Exception mx) { } catch (Exception mx) {
Server.getLogger().log("Error starting applications: " + mx); Server.getLogger().log("Error starting applications: " + mx);
@ -232,9 +330,13 @@ public class ApplicationManager implements XmlRpcHandler {
} }
} }
/**
*
*/
public void stopAll() { public void stopAll() {
for (Enumeration en = applications.keys(); en.hasMoreElements();) { for (Enumeration en = applications.keys(); en.hasMoreElements();) {
String appName = (String) en.nextElement(); String appName = (String) en.nextElement();
stop(appName); stop(appName);
} }
} }
@ -256,39 +358,57 @@ public class ApplicationManager implements XmlRpcHandler {
/** /**
* Implements org.apache.xmlrpc.XmlRpcHandler.execute() * Implements org.apache.xmlrpc.XmlRpcHandler.execute()
*/ */
public Object execute (String method, Vector params) throws Exception { public Object execute(String method, Vector params)
throws Exception {
int dot = method.indexOf("."); int dot = method.indexOf(".");
if (dot == -1)
throw new Exception ("Method name \""+method+"\" does not specify a handler application"); if (dot == -1) {
if (dot == 0 || dot == method.length()-1) throw new Exception("Method name \"" + method +
"\" does not specify a handler application");
}
if ((dot == 0) || (dot == (method.length() - 1))) {
throw new Exception("\"" + method + "\" is not a valid XML-RPC method name"); throw new Exception("\"" + method + "\" is not a valid XML-RPC method name");
}
String handler = method.substring(0, dot); String handler = method.substring(0, dot);
String method2 = method.substring(dot + 1); String method2 = method.substring(dot + 1);
Application app = (Application) xmlrpcHandlers.get(handler); Application app = (Application) xmlrpcHandlers.get(handler);
if (app == null)
if (app == null) {
throw new Exception("Handler \"" + handler + "\" not found for " + method); throw new Exception("Handler \"" + handler + "\" not found for " + method);
}
return app.executeXmlRpc(method2, params); return app.executeXmlRpc(method2, params);
} }
private String getMountpoint(String appName) { private String getMountpoint(String appName) {
String mountpoint = props.getProperty(appName + ".mountpoint"); String mountpoint = props.getProperty(appName + ".mountpoint");
if (mountpoint == null)
if (mountpoint == null) {
return "/" + URLEncoder.encode(appName); return "/" + URLEncoder.encode(appName);
}
mountpoint = mountpoint.trim(); mountpoint = mountpoint.trim();
if ("".equals (mountpoint))
if ("".equals(mountpoint)) {
return "/"; return "/";
else if (!mountpoint.startsWith ("/")) } else if (!mountpoint.startsWith("/")) {
return "/" + mountpoint; return "/" + mountpoint;
}
return mountpoint; return mountpoint;
} }
private String getPathPattern(String mountpoint) { private String getPathPattern(String mountpoint) {
if ("/".equals (mountpoint)) if ("/".equals(mountpoint)) {
return "/"; return "/";
if (!mountpoint.endsWith ("/"))
return mountpoint+"/*";
return mountpoint+"*";
} }
if (!mountpoint.endsWith("/")) {
return mountpoint + "/*";
}
return mountpoint + "*";
}
} }

View file

@ -1,12 +1,26 @@
// HelmaSecurityManager.java /*
* Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.main; package helma.main;
import java.security.Permission; import helma.framework.core.AppClassLoader;
import java.io.FileDescriptor; import java.io.FileDescriptor;
import java.net.InetAddress; import java.net.InetAddress;
import java.security.Permission;
import java.util.HashSet; import java.util.HashSet;
import helma.framework.core.AppClassLoader;
/** /**
* Liberal security manager for Helma system that makes sure application code * Liberal security manager for Helma system that makes sure application code
@ -17,64 +31,281 @@ import helma.framework.core.AppClassLoader;
* the name of the application trying to execute the action in question, if any. * the name of the application trying to execute the action in question, if any.
*/ */
public class HelmaSecurityManager extends SecurityManager { public class HelmaSecurityManager extends SecurityManager {
// The set of actions forbidden to application code. // The set of actions forbidden to application code.
// We are pretty permissive, forbidding only System.exit() // We are pretty permissive, forbidding only System.exit()
// and setting the security manager. // and setting the security manager.
private final static HashSet forbidden = new HashSet(); private final static HashSet forbidden = new HashSet();
static { static {
forbidden.add("exitVM"); forbidden.add("exitVM");
forbidden.add("setSecurityManager"); forbidden.add("setSecurityManager");
} }
/**
*
*
* @param p ...
*/
public void checkPermission(Permission p) { public void checkPermission(Permission p) {
if (p instanceof RuntimePermission) { if (p instanceof RuntimePermission) {
if (forbidden.contains(p.getName())) { if (forbidden.contains(p.getName())) {
Class[] classes = getClassContext(); Class[] classes = getClassContext();
for (int i = 0; i < classes.length; i++) { for (int i = 0; i < classes.length; i++) {
if (classes[i].getClassLoader() instanceof AppClassLoader) if (classes[i].getClassLoader() instanceof AppClassLoader) {
throw new SecurityException (p.getName()+" not allowed for application code"); throw new SecurityException(p.getName() +
" not allowed for application code");
} }
} }
} }
} }
}
/**
*
*
* @param p ...
* @param context ...
*/
public void checkPermission(Permission p, Object context) { public void checkPermission(Permission p, Object context) {
} }
public void checkCreateClassLoader() {}
public void checkAccess(Thread thread) {} /**
public void checkAccess(ThreadGroup group) {} *
*/
public void checkCreateClassLoader() {
}
/**
*
*
* @param thread ...
*/
public void checkAccess(Thread thread) {
}
/**
*
*
* @param group ...
*/
public void checkAccess(ThreadGroup group) {
}
/**
*
*
* @param status ...
*/
public void checkExit(int status) { public void checkExit(int status) {
Class[] classes = getClassContext(); Class[] classes = getClassContext();
for (int i = 0; i < classes.length; i++) { for (int i = 0; i < classes.length; i++) {
if (classes[i].getClassLoader() instanceof AppClassLoader) if (classes[i].getClassLoader() instanceof AppClassLoader) {
throw new SecurityException("operation not allowed for application code"); throw new SecurityException("operation not allowed for application code");
} }
} }
public void checkExec(String cmd) {} }
public void checkLink(String lib) {}
public void checkRead(FileDescriptor fdesc) {} /**
public void checkRead(String file) {} *
public void checkRead(String file, Object context) {} *
public void checkWrite(FileDescriptor fdesc) {} * @param cmd ...
public void checkWrite(String file) {} */
public void checkDelete(String file) {} public void checkExec(String cmd) {
public void checkConnect(String host, int port) {} }
public void checkConnect(String host, int port, Object context) {}
public void checkListen(int port) {} /**
public void checkAccept(String host, int port) {} *
public void checkMulticast(InetAddress addr) {} *
public void checkMulticast(InetAddress addr, byte ttl) {} * @param lib ...
public void checkPropertiesAccess() {} */
public void checkPropertyAccess(String key) {} public void checkLink(String lib) {
public boolean checkTopLevelWindow(Object window) { return true; } }
public void checkPrintJobAccess() {}
public void checkSystemClipboardAccess() {} /**
public void checkAwtEventQueueAccess() {} *
public void checkPackageAccess(String pkg) {} *
public void checkPackageDefinition(String pkg) {} * @param fdesc ...
public void checkSetFactory() {} */
public void checkMemberAccess(Class clazz, int which) {} public void checkRead(FileDescriptor fdesc) {
public void checkSecurityAccess(String target) {} }
/**
*
*
* @param file ...
*/
public void checkRead(String file) {
}
/**
*
*
* @param file ...
* @param context ...
*/
public void checkRead(String file, Object context) {
}
/**
*
*
* @param fdesc ...
*/
public void checkWrite(FileDescriptor fdesc) {
}
/**
*
*
* @param file ...
*/
public void checkWrite(String file) {
}
/**
*
*
* @param file ...
*/
public void checkDelete(String file) {
}
/**
*
*
* @param host ...
* @param port ...
*/
public void checkConnect(String host, int port) {
}
/**
*
*
* @param host ...
* @param port ...
* @param context ...
*/
public void checkConnect(String host, int port, Object context) {
}
/**
*
*
* @param port ...
*/
public void checkListen(int port) {
}
/**
*
*
* @param host ...
* @param port ...
*/
public void checkAccept(String host, int port) {
}
/**
*
*
* @param addr ...
*/
public void checkMulticast(InetAddress addr) {
}
/**
*
*
* @param addr ...
* @param ttl ...
*/
public void checkMulticast(InetAddress addr, byte ttl) {
}
/**
*
*/
public void checkPropertiesAccess() {
}
/**
*
*
* @param key ...
*/
public void checkPropertyAccess(String key) {
}
/**
*
*
* @param window ...
*
* @return ...
*/
public boolean checkTopLevelWindow(Object window) {
return true;
}
/**
*
*/
public void checkPrintJobAccess() {
}
/**
*
*/
public void checkSystemClipboardAccess() {
}
/**
*
*/
public void checkAwtEventQueueAccess() {
}
/**
*
*
* @param pkg ...
*/
public void checkPackageAccess(String pkg) {
}
/**
*
*
* @param pkg ...
*/
public void checkPackageDefinition(String pkg) {
}
/**
*
*/
public void checkSetFactory() {
}
/**
*
*
* @param clazz ...
* @param which ...
*/
public void checkMemberAccess(Class clazz, int which) {
}
/**
*
*
* @param target ...
*/
public void checkSecurityAccess(String target) {
}
/** /**
* Utility method that returns the name of the application trying * Utility method that returns the name of the application trying
@ -83,12 +314,14 @@ public class HelmaSecurityManager extends SecurityManager {
*/ */
protected String getApplication() { protected String getApplication() {
Class[] classes = getClassContext(); Class[] classes = getClassContext();
for (int i = 0; i < classes.length; i++) { for (int i = 0; i < classes.length; i++) {
if (classes[i].getClassLoader() instanceof AppClassLoader) if (classes[i].getClassLoader() instanceof AppClassLoader) {
return ((AppClassLoader) classes[i].getClassLoader()).getAppName(); return ((AppClassLoader) classes[i].getClassLoader()).getAppName();
} }
}
// no application class loader found in stack - return null // no application class loader found in stack - return null
return null; return null;
} }
} }

View file

@ -1,4 +1,19 @@
// HelmaShutdownHook.java /*
* Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.main; package helma.main;
import helma.util.Logger; import helma.util.Logger;
@ -8,23 +23,35 @@ import java.util.List;
* ShutdownHook that shuts down all running Helma applications on exit. * ShutdownHook that shuts down all running Helma applications on exit.
*/ */
public class HelmaShutdownHook extends Thread { public class HelmaShutdownHook extends Thread {
ApplicationManager appmgr; ApplicationManager appmgr;
/**
* Creates a new HelmaShutdownHook object.
*
* @param appmgr ...
*/
public HelmaShutdownHook(ApplicationManager appmgr) { public HelmaShutdownHook(ApplicationManager appmgr) {
this.appmgr = appmgr; this.appmgr = appmgr;
} }
/**
*
*/
public void run() { public void run() {
Logger logger = Server.getLogger(); Logger logger = Server.getLogger();
if (logger != null)
if (logger != null) {
logger.log("Shutting down Helma"); logger.log("Shutting down Helma");
appmgr.stopAll ();
List loggers = Logger.getLoggers();
int l = loggers.size();
for (int i=0; i<l; i++)
((Logger) loggers.get(i)).close();
Logger.wakeup();
} }
appmgr.stopAll();
List loggers = Logger.getLoggers();
int l = loggers.size();
for (int i = 0; i < l; i++)
((Logger) loggers.get(i)).close();
Logger.wakeup();
}
} }

View file

@ -1,42 +1,79 @@
// HopSocketFactory.java /*
// Copyright (c) Hannes Wallnöfer 1999-2000 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.main; package helma.main;
import helma.util.*; import helma.util.*;
import java.io.IOException;
import java.net.*; import java.net.*;
import java.rmi.server.*; import java.rmi.server.*;
import java.io.IOException;
/** /**
* An RMI socket factory that has a "paranoid" option to filter clients. * An RMI socket factory that has a "paranoid" option to filter clients.
* We only do direct connections, no HTTP proxy stuff, since this is * We only do direct connections, no HTTP proxy stuff, since this is
* server-to-server. * server-to-server.
*/ */
public class HelmaSocketFactory extends RMISocketFactory { public class HelmaSocketFactory extends RMISocketFactory {
private InetAddressFilter filter; private InetAddressFilter filter;
/**
* Creates a new HelmaSocketFactory object.
*/
public HelmaSocketFactory() { public HelmaSocketFactory() {
filter = new InetAddressFilter(); filter = new InetAddressFilter();
} }
/**
*
*
* @param address ...
*/
public void addAddress(String address) { public void addAddress(String address) {
try { try {
filter.addAddress(address); filter.addAddress(address);
} catch (IOException x) { } catch (IOException x) {
Server.getLogger().log ("Could not add "+address+" to Socket Filter: invalid address."); Server.getLogger().log("Could not add " + address +
" to Socket Filter: invalid address.");
} }
} }
/**
*
*
* @param host ...
* @param port ...
*
* @return ...
*
* @throws IOException ...
*/
public Socket createSocket(String host, int port) throws IOException { public Socket createSocket(String host, int port) throws IOException {
return new Socket(host, port); return new Socket(host, port);
} }
/**
*
*
* @param port ...
*
* @return ...
*
* @throws IOException ...
*/
public ServerSocket createServerSocket(int port) throws IOException { public ServerSocket createServerSocket(int port) throws IOException {
return new ParanoidServerSocket(port, filter); return new ParanoidServerSocket(port, filter);
} }
} }

View file

@ -1,48 +1,63 @@
// Server.java /*
// Copyright (c) Hannes Wallnöfer 1998-2000 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.main; package helma.main;
import java.io.*;
import java.rmi.*;
import java.rmi.server.*;
import java.rmi.registry.*;
import java.net.*;
import java.util.*;
import helma.extensions.HelmaExtension; import helma.extensions.HelmaExtension;
import helma.objectmodel.db.DbSource;
import helma.framework.*; import helma.framework.*;
import helma.framework.core.*; import helma.framework.core.*;
import helma.objectmodel.db.DbSource;
import helma.util.*; import helma.util.*;
import org.mortbay.http.*;
import org.mortbay.util.*;
import org.mortbay.http.ajp.*;
import org.apache.xmlrpc.*; import org.apache.xmlrpc.*;
import org.mortbay.http.*;
import org.mortbay.http.ajp.*;
import org.mortbay.util.*;
import java.io.*;
import java.net.*;
import java.rmi.*;
import java.rmi.registry.*;
import java.rmi.server.*;
import java.util.*;
/** /**
* Helma server main class. * Helma server main class.
*/ */
public class Server implements IPathElement, Runnable { public class Server implements IPathElement, Runnable {
public static final String version = "1.2.3 (2003/03/07)"; public static final String version = "1.2.3 (2003/03/07)";
public final long starttime;
// if true we only accept RMI and XML-RPC connections from
// explicitly listed hosts.
public boolean paranoid;
private ApplicationManager appManager;
private Vector extensions;
private Thread mainThread;
// server-wide properties // server-wide properties
static SystemProperties appsProps; static SystemProperties appsProps;
static SystemProperties dbProps; static SystemProperties dbProps;
static SystemProperties sysProps; static SystemProperties sysProps;
// static server instance
private static Server server;
protected static File hopHome = null;
// our logger
private static Logger logger;
public final long starttime;
// if true we only accept RMI and XML-RPC connections from
// explicitly listed hosts.
public boolean paranoid;
private ApplicationManager appManager;
private Vector extensions;
private Thread mainThread;
// server ports // server ports
int rmiPort = 0; int rmiPort = 0;
int xmlrpcPort = 0; int xmlrpcPort = 0;
@ -52,14 +67,6 @@ import org.apache.xmlrpc.*;
// map of server-wide database sources // map of server-wide database sources
Hashtable dbSources; Hashtable dbSources;
// static server instance
private static Server server;
protected static File hopHome = null;
// our logger
private static Logger logger;
// the embedded web server // the embedded web server
// protected Serve websrv; // protected Serve websrv;
protected HttpServer http; protected HttpServer http;
@ -70,37 +77,12 @@ import org.apache.xmlrpc.*;
// the XML-RPC server // the XML-RPC server
protected WebServer xmlrpc; protected WebServer xmlrpc;
/**
* static main entry point.
*/
public static void main (String args[]) throws IOException {
// check if we are running on a Java 2 VM - otherwise exit with an error message
String javaVersion = System.getProperty ("java.version");
if (javaVersion == null || javaVersion.startsWith ("1.1") || javaVersion.startsWith ("1.0")) {
System.err.println ("This version of Helma requires Java 1.2 or greater.");
if (javaVersion == null) // don't think this will ever happen, but you never know
System.err.println ("Your Java Runtime did not provide a version number. Please update to a more recent version.");
else
System.err.println ("Your Java Runtime is version "+javaVersion+". Please update to a more recent version.");
System.exit (1);
}
// create new server instance
server = new Server (args);
// start the server main thread
server.start ();
}
/** /**
* Constructs a new Server instance with an array of command line options. * Constructs a new Server instance with an array of command line options.
*/ */
public Server(String[] args) { public Server(String[] args) {
starttime = System.currentTimeMillis(); starttime = System.currentTimeMillis();
String homeDir = null; String homeDir = null;
boolean usageError = false; boolean usageError = false;
@ -112,35 +94,35 @@ import org.apache.xmlrpc.*;
// parse arguments // parse arguments
for (int i = 0; i < args.length; i++) { for (int i = 0; i < args.length; i++) {
if (args[i].equals ("-h") && i+1<args.length) if (args[i].equals("-h") && ((i + 1) < args.length)) {
homeDir = args[++i]; homeDir = args[++i];
else if (args[i].equals ("-f") && i+1<args.length) } else if (args[i].equals("-f") && ((i + 1) < args.length)) {
propfile = args[++i]; propfile = args[++i];
else if (args[i].equals ("-p") && i+1<args.length) { } else if (args[i].equals("-p") && ((i + 1) < args.length)) {
try { try {
rmiPort = Integer.parseInt(args[++i]); rmiPort = Integer.parseInt(args[++i]);
} catch (Exception portx) { } catch (Exception portx) {
usageError = true; usageError = true;
} }
} else if (args[i].equals ("-x") && i+1<args.length) { } else if (args[i].equals("-x") && ((i + 1) < args.length)) {
try { try {
xmlrpcPort = Integer.parseInt(args[++i]); xmlrpcPort = Integer.parseInt(args[++i]);
} catch (Exception portx) { } catch (Exception portx) {
usageError = true; usageError = true;
} }
} else if (args[i].equals ("-w") && i+1<args.length) { } else if (args[i].equals("-w") && ((i + 1) < args.length)) {
try { try {
websrvPort = Integer.parseInt(args[++i]); websrvPort = Integer.parseInt(args[++i]);
} catch (Exception portx) { } catch (Exception portx) {
usageError = true; usageError = true;
} }
} else if (args[i].equals ("-jk") && i+1<args.length) { } else if (args[i].equals("-jk") && ((i + 1) < args.length)) {
try { try {
ajp13Port = Integer.parseInt(args[++i]); ajp13Port = Integer.parseInt(args[++i]);
} catch (Exception portx) { } catch (Exception portx) {
usageError = true; usageError = true;
} }
} else if (args[i].equals ("-i") && i+1<args.length) { } else if (args[i].equals("-i") && ((i + 1) < args.length)) {
// eat away the -i parameter which is meant for helma.main.launcher.Main // eat away the -i parameter which is meant for helma.main.launcher.Main
i++; i++;
} else { } else {
@ -152,38 +134,51 @@ import org.apache.xmlrpc.*;
// get main property file from home dir or vice versa, depending on what we have. // get main property file from home dir or vice versa, depending on what we have.
// get property file from hopHome // get property file from hopHome
if (propfile == null) { if (propfile == null) {
if (homeDir != null) if (homeDir != null) {
propfile = new File(homeDir, "server.properties").getAbsolutePath(); propfile = new File(homeDir, "server.properties").getAbsolutePath();
else } else {
propfile = new File("server.properties").getAbsolutePath(); propfile = new File("server.properties").getAbsolutePath();
} }
}
// create system properties // create system properties
sysProps = new SystemProperties(propfile); sysProps = new SystemProperties(propfile);
// check if there's a property setting for those ports not specified via command line // check if there's a property setting for those ports not specified via command line
if (websrvPort == 0 && sysProps.getProperty ("webPort") != null) try { if ((websrvPort == 0) && (sysProps.getProperty("webPort") != null)) {
try {
websrvPort = Integer.parseInt(sysProps.getProperty("webPort")); websrvPort = Integer.parseInt(sysProps.getProperty("webPort"));
} catch (NumberFormatException fmt) { } catch (NumberFormatException fmt) {
System.err.println("Error parsing web server port property: " + fmt); System.err.println("Error parsing web server port property: " + fmt);
} }
if (ajp13Port == 0 && sysProps.getProperty ("ajp13Port") != null) try { }
if ((ajp13Port == 0) && (sysProps.getProperty("ajp13Port") != null)) {
try {
ajp13Port = Integer.parseInt(sysProps.getProperty("ajp13Port")); ajp13Port = Integer.parseInt(sysProps.getProperty("ajp13Port"));
} catch (NumberFormatException fmt) { } catch (NumberFormatException fmt) {
System.err.println("Error parsing AJP1.3 server port property: " + fmt); System.err.println("Error parsing AJP1.3 server port property: " + fmt);
} }
if (rmiPort == 0 && sysProps.getProperty ("rmiPort") != null) try { }
if ((rmiPort == 0) && (sysProps.getProperty("rmiPort") != null)) {
try {
rmiPort = Integer.parseInt(sysProps.getProperty("rmiPort")); rmiPort = Integer.parseInt(sysProps.getProperty("rmiPort"));
} catch (NumberFormatException fmt) { } catch (NumberFormatException fmt) {
System.err.println("Error parsing RMI server port property: " + fmt); System.err.println("Error parsing RMI server port property: " + fmt);
} }
if (xmlrpcPort == 0 && sysProps.getProperty ("xmlrpcPort") != null) try { }
if ((xmlrpcPort == 0) && (sysProps.getProperty("xmlrpcPort") != null)) {
try {
xmlrpcPort = Integer.parseInt(sysProps.getProperty("xmlrpcPort")); xmlrpcPort = Integer.parseInt(sysProps.getProperty("xmlrpcPort"));
} catch (NumberFormatException fmt) { } catch (NumberFormatException fmt) {
System.err.println("Error parsing XML-RPC server port property: " + fmt); System.err.println("Error parsing XML-RPC server port property: " + fmt);
} }
}
// check server ports. If no port is set, issue a warning and exit. // check server ports. If no port is set, issue a warning and exit.
if (!usageError && (websrvPort | ajp13Port | rmiPort | xmlrpcPort) == 0) { if (!usageError && ((websrvPort | ajp13Port | rmiPort | xmlrpcPort) == 0)) {
System.out.println(" Error: No server port specified."); System.out.println(" Error: No server port specified.");
usageError = true; usageError = true;
} }
@ -203,27 +198,38 @@ import org.apache.xmlrpc.*;
// check if any of the specified server ports is in use already // check if any of the specified server ports is in use already
try { try {
if (websrvPort > 0) if (websrvPort > 0) {
checkRunning(websrvPort); checkRunning(websrvPort);
if (rmiPort > 0) }
if (rmiPort > 0) {
checkRunning(rmiPort); checkRunning(rmiPort);
if (xmlrpcPort > 0) }
if (xmlrpcPort > 0) {
checkRunning(xmlrpcPort); checkRunning(xmlrpcPort);
if (ajp13Port > 0) }
if (ajp13Port > 0) {
checkRunning(ajp13Port); checkRunning(ajp13Port);
}
} catch (Exception running) { } catch (Exception running) {
System.out.println(running.getMessage()); System.out.println(running.getMessage());
System.exit(1); System.exit(1);
} }
// get hopHome from property file // get hopHome from property file
if (homeDir == null) if (homeDir == null) {
homeDir = sysProps.getProperty("hophome"); homeDir = sysProps.getProperty("hophome");
if (homeDir == null) }
if (homeDir == null) {
homeDir = new File(propfile).getParent(); homeDir = new File(propfile).getParent();
}
// create hopHome File object // create hopHome File object
hopHome = new File(homeDir); hopHome = new File(homeDir);
// try to transform hopHome directory to its cononical representation // try to transform hopHome directory to its cononical representation
try { try {
hopHome = hopHome.getCanonicalFile(); hopHome = hopHome.getCanonicalFile();
@ -239,28 +245,32 @@ import org.apache.xmlrpc.*;
System.setProperty("user.dir", hopHome.getPath()); System.setProperty("user.dir", hopHome.getPath());
// from now on it's safe to call getLogger() because hopHome is set up // from now on it's safe to call getLogger() because hopHome is set up
String startMessage = "Starting Helma " + version + " on Java " +
System.getProperty("java.version");
String startMessage = "Starting Helma "+version+
" on Java "+System.getProperty ("java.version");
getLogger().log(startMessage); getLogger().log(startMessage);
// also print a msg to System.out // also print a msg to System.out
System.out.println(startMessage); System.out.println(startMessage);
getLogger().log("propfile = " + propfile); getLogger().log("propfile = " + propfile);
getLogger().log("hopHome = " + hopHome); getLogger().log("hopHome = " + hopHome);
File helper = new File(hopHome, "db.properties"); File helper = new File(hopHome, "db.properties");
dbPropfile = helper.getAbsolutePath(); dbPropfile = helper.getAbsolutePath();
dbProps = new SystemProperties(dbPropfile); dbProps = new SystemProperties(dbPropfile);
DbSource.setDefaultProps(dbProps); DbSource.setDefaultProps(dbProps);
getLogger().log("dbPropfile = " + dbPropfile); getLogger().log("dbPropfile = " + dbPropfile);
appsPropfile = sysProps.getProperty("appsPropFile"); appsPropfile = sysProps.getProperty("appsPropFile");
if (appsPropfile != null && !"".equals (appsPropfile.trim()))
if ((appsPropfile != null) && !"".equals(appsPropfile.trim())) {
helper = new File(appsPropfile); helper = new File(appsPropfile);
else } else {
helper = new File(hopHome, "apps.properties"); helper = new File(hopHome, "apps.properties");
}
appsPropfile = helper.getAbsolutePath(); appsPropfile = helper.getAbsolutePath();
appsProps = new SystemProperties(appsPropfile); appsProps = new SystemProperties(appsPropfile);
getLogger().log("appsPropfile = " + appsPropfile); getLogger().log("appsPropfile = " + appsPropfile);
@ -271,34 +281,71 @@ import org.apache.xmlrpc.*;
String country = sysProps.getProperty("country"); String country = sysProps.getProperty("country");
String timezone = sysProps.getProperty("timezone"); String timezone = sysProps.getProperty("timezone");
if (language != null && country != null) if ((language != null) && (country != null)) {
Locale.setDefault(new Locale(language, country)); Locale.setDefault(new Locale(language, country));
if (timezone != null) }
if (timezone != null) {
TimeZone.setDefault(TimeZone.getTimeZone(timezone)); TimeZone.setDefault(TimeZone.getTimeZone(timezone));
}
getLogger().log("Locale = " + Locale.getDefault()); getLogger().log("Locale = " + Locale.getDefault());
getLogger().log ("TimeZone = "+TimeZone.getDefault().getDisplayName (Locale.getDefault ())); getLogger().log("TimeZone = " +
TimeZone.getDefault().getDisplayName(Locale.getDefault()));
dbSources = new Hashtable(); dbSources = new Hashtable();
// try to load the extensions // try to load the extensions
extensions = new Vector(); extensions = new Vector();
if (sysProps.getProperty("extensions") != null) { if (sysProps.getProperty("extensions") != null) {
StringTokenizer tok=new StringTokenizer (sysProps.getProperty ("extensions"),","); StringTokenizer tok = new StringTokenizer(sysProps.getProperty("extensions"),
",");
while (tok.hasMoreTokens()) { while (tok.hasMoreTokens()) {
String extClassName = tok.nextToken().trim(); String extClassName = tok.nextToken().trim();
try { try {
Class extClass = Class.forName(extClassName); Class extClass = Class.forName(extClassName);
HelmaExtension ext = (HelmaExtension) extClass.newInstance(); HelmaExtension ext = (HelmaExtension) extClass.newInstance();
ext.init(this); ext.init(this);
extensions.add(ext); extensions.add(ext);
getLogger().log("loaded: " + extClassName); getLogger().log("loaded: " + extClassName);
} catch (Exception e) { } catch (Exception e) {
getLogger ().log ("error: " + extClassName + " (" + e.toString () + ")"); getLogger().log("error: " + extClassName + " (" + e.toString() +
")");
}
} }
} }
} }
/**
* static main entry point.
*/
public static void main(String[] args) throws IOException {
// check if we are running on a Java 2 VM - otherwise exit with an error message
String javaVersion = System.getProperty("java.version");
if ((javaVersion == null) || javaVersion.startsWith("1.1") ||
javaVersion.startsWith("1.0")) {
System.err.println("This version of Helma requires Java 1.2 or greater.");
if (javaVersion == null) { // don't think this will ever happen, but you never know
System.err.println("Your Java Runtime did not provide a version number. Please update to a more recent version.");
} else {
System.err.println("Your Java Runtime is version " + javaVersion +
". Please update to a more recent version.");
}
System.exit(1);
}
// create new server instance
server = new Server(args);
// start the server main thread
server.start();
} }
protected void start() { protected void start() {
@ -318,25 +365,37 @@ import org.apache.xmlrpc.*;
* apps or starting new ones. * apps or starting new ones.
*/ */
public void run() { public void run() {
try { try {
if ((websrvPort > 0) || (ajp13Port > 0)) {
if (websrvPort > 0 || ajp13Port > 0) {
http = new HttpServer(); http = new HttpServer();
// disable Jetty logging FIXME: seems to be a jetty bug; as soon // disable Jetty logging FIXME: seems to be a jetty bug; as soon
// as the logging is disabled, the more is logged // as the logging is disabled, the more is logged
Log.instance().disableLog(); Log.instance().disableLog();
Log.instance().add (new LogSink () Log.instance().add(new LogSink() {
{ public String getOptions() {
public String getOptions () { return null; } return null;
public void log (String formattedLog) {}
public void log (String tag, Object msg, Frame frame, long time) {}
public void setOptions (String options) {}
public boolean isStarted () { return true; }
public void start () {}
public void stop () {}
} }
);
public void log(String formattedLog) {
}
public void log(String tag, Object msg, Frame frame, long time) {
}
public void setOptions(String options) {
}
public boolean isStarted() {
return true;
}
public void start() {
}
public void stop() {
}
});
} }
// start embedded web server if port is specified // start embedded web server if port is specified
@ -349,66 +408,84 @@ import org.apache.xmlrpc.*;
// create AJP13Listener // create AJP13Listener
ajp13 = new AJP13Listener(new InetAddrPort(ajp13Port)); ajp13 = new AJP13Listener(new InetAddrPort(ajp13Port));
ajp13.setHttpServer(http); ajp13.setHttpServer(http);
String jkallow = sysProps.getProperty("allowAJP13"); String jkallow = sysProps.getProperty("allowAJP13");
// by default the AJP13-connection just accepts requests from 127.0.0.1 // by default the AJP13-connection just accepts requests from 127.0.0.1
if (jkallow == null) if (jkallow == null) {
jkallow = "127.0.0.1"; jkallow = "127.0.0.1";
}
StringTokenizer st = new StringTokenizer(jkallow, " ,;"); StringTokenizer st = new StringTokenizer(jkallow, " ,;");
String[] jkallowarr = new String[st.countTokens()]; String[] jkallowarr = new String[st.countTokens()];
int cnt = 0; int cnt = 0;
while (st.hasMoreTokens()) { while (st.hasMoreTokens()) {
jkallowarr[cnt] = st.nextToken(); jkallowarr[cnt] = st.nextToken();
cnt++; cnt++;
} }
ajp13.setRemoteServers(jkallowarr); ajp13.setRemoteServers(jkallowarr);
getLogger().log("Starting AJP13-Listener on port " + (ajp13Port)); getLogger().log("Starting AJP13-Listener on port " + (ajp13Port));
} }
if (xmlrpcPort > 0) { if (xmlrpcPort > 0) {
String xmlparser = sysProps.getProperty("xmlparser"); String xmlparser = sysProps.getProperty("xmlparser");
if (xmlparser != null)
if (xmlparser != null) {
XmlRpc.setDriver(xmlparser); XmlRpc.setDriver(xmlparser);
}
xmlrpc = new WebServer(xmlrpcPort); xmlrpc = new WebServer(xmlrpcPort);
if (paranoid) { if (paranoid) {
xmlrpc.setParanoid(true); xmlrpc.setParanoid(true);
String xallow = sysProps.getProperty("allowXmlRpc"); String xallow = sysProps.getProperty("allowXmlRpc");
if (xallow != null) { if (xallow != null) {
StringTokenizer st = new StringTokenizer(xallow, " ,;"); StringTokenizer st = new StringTokenizer(xallow, " ,;");
while (st.hasMoreTokens()) while (st.hasMoreTokens())
xmlrpc.acceptClient(st.nextToken()); xmlrpc.acceptClient(st.nextToken());
} }
} }
getLogger().log("Starting XML-RPC server on port " + (xmlrpcPort)); getLogger().log("Starting XML-RPC server on port " + (xmlrpcPort));
} }
if (rmiPort > 0) { if (rmiPort > 0) {
if (paranoid) { if (paranoid) {
HelmaSocketFactory factory = new HelmaSocketFactory(); HelmaSocketFactory factory = new HelmaSocketFactory();
String rallow = sysProps.getProperty("allowWeb"); String rallow = sysProps.getProperty("allowWeb");
if (rallow != null) { if (rallow != null) {
StringTokenizer st = new StringTokenizer(rallow, " ,;"); StringTokenizer st = new StringTokenizer(rallow, " ,;");
while (st.hasMoreTokens()) while (st.hasMoreTokens())
factory.addAddress(st.nextToken()); factory.addAddress(st.nextToken());
} }
RMISocketFactory.setSocketFactory(factory); RMISocketFactory.setSocketFactory(factory);
} }
getLogger().log("Starting RMI server on port " + rmiPort); getLogger().log("Starting RMI server on port " + rmiPort);
LocateRegistry.createRegistry(rmiPort); LocateRegistry.createRegistry(rmiPort);
} }
// create application manager // create application manager
appManager = new ApplicationManager(rmiPort, hopHome, appsProps, this); appManager = new ApplicationManager(rmiPort, hopHome, appsProps, this);
if (xmlrpc != null)
if (xmlrpc != null) {
xmlrpc.addHandler("$default", appManager); xmlrpc.addHandler("$default", appManager);
}
// add shutdown hook to close running apps and servers on exit // add shutdown hook to close running apps and servers on exit
Runtime.getRuntime().addShutdownHook(new HelmaShutdownHook(appManager)); Runtime.getRuntime().addShutdownHook(new HelmaShutdownHook(appManager));
} catch (Exception gx) { } catch (Exception gx) {
getLogger().log("Error initializing embedded database: " + gx); getLogger().log("Error initializing embedded database: " + gx);
gx.printStackTrace(); gx.printStackTrace();
return; return;
} }
@ -416,8 +493,11 @@ import org.apache.xmlrpc.*;
// the default implementation is helma.main.HelmaSecurityManager. // the default implementation is helma.main.HelmaSecurityManager.
try { try {
String secManClass = sysProps.getProperty("securityManager"); String secManClass = sysProps.getProperty("securityManager");
if (secManClass != null) { if (secManClass != null) {
SecurityManager secMan = (SecurityManager) Class.forName(secManClass).newInstance (); SecurityManager secMan = (SecurityManager) Class.forName(secManClass)
.newInstance();
System.setSecurityManager(secMan); System.setSecurityManager(secMan);
getLogger().log("Setting security manager to " + secManClass); getLogger().log("Setting security manager to " + secManClass);
} }
@ -429,23 +509,30 @@ import org.apache.xmlrpc.*;
appManager.startAll(); appManager.startAll();
// start embedded web server // start embedded web server
if (http != null) try { if (http != null) {
try {
http.start(); http.start();
} catch (MultiException m) { } catch (MultiException m) {
getLogger().log("Error starting embedded web server: " + m); getLogger().log("Error starting embedded web server: " + m);
} }
}
if (ajp13 != null) try { if (ajp13 != null) {
try {
ajp13.start(); ajp13.start();
} catch (Exception m) { } catch (Exception m) {
getLogger().log("Error starting AJP13 listener: " + m); getLogger().log("Error starting AJP13 listener: " + m);
} }
}
int count = 0; int count = 0;
while (Thread.currentThread() == mainThread) { while (Thread.currentThread() == mainThread) {
try { try {
mainThread.sleep (3000l); mainThread.sleep(3000L);
} catch (InterruptedException ie) {} } catch (InterruptedException ie) {
}
try { try {
appManager.checkForChanges(); appManager.checkForChanges();
} catch (Exception x) { } catch (Exception x) {
@ -474,16 +561,21 @@ import org.apache.xmlrpc.*;
public static Logger getLogger() { public static Logger getLogger() {
if (logger == null) { if (logger == null) {
String logDir = sysProps.getProperty("logdir", "log"); String logDir = sysProps.getProperty("logdir", "log");
if ("console".equalsIgnoreCase(logDir)) { if ("console".equalsIgnoreCase(logDir)) {
logger = new Logger(System.out); logger = new Logger(System.out);
} else { } else {
File helper = new File(logDir); File helper = new File(logDir);
if (hopHome != null && !helper.isAbsolute ())
if ((hopHome != null) && !helper.isAbsolute()) {
helper = new File(hopHome, logDir); helper = new File(hopHome, logDir);
}
logDir = helper.getAbsolutePath(); logDir = helper.getAbsolutePath();
logger = Logger.getLogger(logDir, "hop"); logger = Logger.getLogger(logDir, "hop");
} }
} }
return logger; return logger;
} }
@ -517,39 +609,79 @@ import org.apache.xmlrpc.*;
} catch (Exception x) { } catch (Exception x) {
return; return;
} }
// if we got so far, another server is already running on this port and db // if we got so far, another server is already running on this port and db
throw new Exception("Error: Server already running on this port: " + portNumber); throw new Exception("Error: Server already running on this port: " + portNumber);
} }
/**
*
*
* @param key ...
*
* @return ...
*/
public String getProperty(String key) { public String getProperty(String key) {
return (String) sysProps.get(key); return (String) sysProps.get(key);
} }
/**
*
*
* @return ...
*/
public SystemProperties getProperties() { public SystemProperties getProperties() {
return sysProps; return sysProps;
} }
/**
*
*
* @return ...
*/
public SystemProperties getDbProperties() { public SystemProperties getDbProperties() {
return dbProps; return dbProps;
} }
/**
*
*
* @return ...
*/
public File getAppsHome() { public File getAppsHome() {
String appHome = sysProps.getProperty("appHome"); String appHome = sysProps.getProperty("appHome");
if (appHome != null && !"".equals (appHome.trim()))
if ((appHome != null) && !"".equals(appHome.trim())) {
return new File(appHome); return new File(appHome);
else } else {
return new File(hopHome, "apps"); return new File(hopHome, "apps");
} }
}
/**
*
*
* @return ...
*/
public Vector getExtensions() { public Vector getExtensions() {
return extensions; return extensions;
} }
/**
*
*
* @param name ...
*/
public void startApplication(String name) { public void startApplication(String name) {
appManager.start(name); appManager.start(name);
appManager.register(name); appManager.register(name);
} }
/**
*
*
* @param name ...
*/
public void stopApplication(String name) { public void stopApplication(String name) {
appManager.stop(name); appManager.stop(name);
} }
@ -582,6 +714,4 @@ import org.apache.xmlrpc.*;
public String getPrototype() { public String getPrototype() {
return "root"; return "root";
} }
} }

View file

@ -1,20 +1,33 @@
// FilteredClassLoader.java /*
* Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.main.launcher; package helma.main.launcher;
import java.net.URL; import java.net.URL;
import java.net.URLClassLoader; import java.net.URLClassLoader;
import java.util.Hashtable; import java.security.CodeSource;
import java.security.PermissionCollection; import java.security.PermissionCollection;
import java.security.Permissions; import java.security.Permissions;
import java.security.Policy; import java.security.Policy;
import java.security.CodeSource; import java.util.Hashtable;
/** /**
* ClassLoader that is able to exclude certain packages from loading. * ClassLoader that is able to exclude certain packages from loading.
*/ */
public class FilteredClassLoader extends URLClassLoader { public class FilteredClassLoader extends URLClassLoader {
/** /**
* Create a server wide class loader that doesn't see the scripting engine(s) * Create a server wide class loader that doesn't see the scripting engine(s)
* embedded in helma.jar. These files should be loaded by the per-application * embedded in helma.jar. These files should be loaded by the per-application
@ -29,8 +42,10 @@ public class FilteredClassLoader extends URLClassLoader {
* Mask classes that implement the scripting engine(s) contained in helma.jar * Mask classes that implement the scripting engine(s) contained in helma.jar
*/ */
protected Class findClass(String name) throws ClassNotFoundException { protected Class findClass(String name) throws ClassNotFoundException {
if (name != null && "helma.scripting.fesi.PhantomEngine".equals (name)) if ((name != null) && "helma.scripting.fesi.PhantomEngine".equals(name)) {
throw new ClassNotFoundException(name); throw new ClassNotFoundException(name);
}
return super.findClass(name); return super.findClass(name);
} }
} }

View file

@ -1,65 +1,84 @@
// helma.main.Main /*
* Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.main.launcher; package helma.main.launcher;
import java.net.URLClassLoader;
import java.net.URL;
import java.net.URLDecoder;
import java.io.File; import java.io.File;
import java.io.FilenameFilter; import java.io.FilenameFilter;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList; import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLDecoder;
import java.security.Policy; import java.security.Policy;
import java.util.ArrayList;
/** /**
* Helma bootstrap class. Figures out Helma home directory, sets up class path and * Helma bootstrap class. Figures out Helma home directory, sets up class path and
* lauchnes main class. * lauchnes main class.
*/ */
public class Main { public class Main {
public static final String[] jars = { public static final String[] jars = {
"helma.jar", "helma.jar", "jetty.jar", "crimson.jar",
"jetty.jar", "xmlrpc.jar", "servlet.jar", "regexp.jar",
"crimson.jar", "mail.jar", "activation.jar",
"xmlrpc.jar", "netcomponents.jar", "jimi.jar",
"servlet.jar", "apache-dom.jar", "jdom.jar"
"regexp.jar",
"mail.jar",
"activation.jar",
"netcomponents.jar",
"jimi.jar",
"apache-dom.jar",
"jdom.jar"
}; };
/**
*
*
* @param args ...
*
* @throws Exception ...
*/
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
// check if home directory is set via command line arg. If not, // check if home directory is set via command line arg. If not,
// we'll get it from the location of the jar file this class // we'll get it from the location of the jar file this class
// has been loaded from. // has been loaded from.
String installDir = null; String installDir = null;
// first, try to get helma home dir from command line options // first, try to get helma home dir from command line options
for (int i = 0; i < args.length; i++) { for (int i = 0; i < args.length; i++) {
if (args[i].equals ("-i") && i+1<args.length) { if (args[i].equals("-i") && ((i + 1) < args.length)) {
installDir = args[i + 1]; installDir = args[i + 1];
} }
} }
URLClassLoader apploader = (URLClassLoader) ClassLoader.getSystemClassLoader(); URLClassLoader apploader = (URLClassLoader) ClassLoader.getSystemClassLoader();
// try to get Helma installation directory // try to get Helma installation directory
if (installDir == null) { if (installDir == null) {
try { try {
URL launcherUrl = apploader.findResource("helma/main/launcher/Main.class"); URL launcherUrl = apploader.findResource("helma/main/launcher/Main.class");
// this is a JAR URL of the form // this is a JAR URL of the form
// jar:<url>!/{entry} // jar:<url>!/{entry}
// we strip away the jar: prefix and the !/{entry} suffix // we strip away the jar: prefix and the !/{entry} suffix
// to get the original jar file URL // to get the original jar file URL
installDir = launcherUrl.toString().substring(4); installDir = launcherUrl.toString().substring(4);
int excl = installDir.indexOf("!"); int excl = installDir.indexOf("!");
if (excl > -1) { if (excl > -1) {
installDir = installDir.substring(0, excl); installDir = installDir.substring(0, excl);
launcherUrl = new URL(installDir); launcherUrl = new URL(installDir);
File f = new File(launcherUrl.getPath()); File f = new File(launcherUrl.getPath());
installDir = f.getParentFile().getCanonicalPath(); installDir = f.getParentFile().getCanonicalPath();
} }
} catch (Exception x) { } catch (Exception x) {
@ -75,40 +94,52 @@ public class Main {
// set up the class path // set up the class path
File libdir = new File(installDir, "lib"); File libdir = new File(installDir, "lib");
ArrayList jarlist = new ArrayList(); ArrayList jarlist = new ArrayList();
for (int i = 0; i < jars.length; i++) { for (int i = 0; i < jars.length; i++) {
File jar = new File(libdir, jars[i]); File jar = new File(libdir, jars[i]);
jarlist.add(new URL("file:" + jar.getAbsolutePath())); jarlist.add(new URL("file:" + jar.getAbsolutePath()));
} }
// add all jar files from the lib/ext directory // add all jar files from the lib/ext directory
File extdir = new File(libdir, "ext"); File extdir = new File(libdir, "ext");
File[] files = extdir.listFiles(new FilenameFilter() { File[] files = extdir.listFiles(new FilenameFilter() {
public boolean accept(File dir, String name) { public boolean accept(File dir, String name) {
String n = name.toLowerCase(); String n = name.toLowerCase();
return n.endsWith(".jar") || n.endsWith(".zip"); return n.endsWith(".jar") || n.endsWith(".zip");
} }
}); });
if (files != null)
if (files != null) {
for (int i = 0; i < files.length; i++) { for (int i = 0; i < files.length; i++) {
// WORKAROUND: add the files in lib/ext before // WORKAROUND: add the files in lib/ext before
// lib/apache-dom.jar, since otherwise putting a full version // lib/apache-dom.jar, since otherwise putting a full version
// of Xerces in lib/ext would cause a version conflict with the // of Xerces in lib/ext would cause a version conflict with the
// xerces classes in lib/apache-dom.jar. Generally, having some pieces // xerces classes in lib/apache-dom.jar. Generally, having some pieces
// of Xerces in lib/apache-dom.jar is kind of problematic. // of Xerces in lib/apache-dom.jar is kind of problematic.
jarlist.add (jars.length-3, new URL ("file:" + files[i].getAbsolutePath())); jarlist.add(jars.length - 3, new URL("file:" +
files[i].getAbsolutePath()));
System.err.println("Adding to classpath: " + files[i].getAbsolutePath()); System.err.println("Adding to classpath: " + files[i].getAbsolutePath());
} }
}
URL[] urls = new URL[jarlist.size()]; URL[] urls = new URL[jarlist.size()];
jarlist.toArray(urls); jarlist.toArray(urls);
FilteredClassLoader loader = new FilteredClassLoader(urls); FilteredClassLoader loader = new FilteredClassLoader(urls);
// set the new class loader as context class loader // set the new class loader as context class loader
Thread.currentThread().setContextClassLoader(loader); Thread.currentThread().setContextClassLoader(loader);
// get the main server class // get the main server class
Class clazz = loader.loadClass("helma.main.Server"); Class clazz = loader.loadClass("helma.main.Server");
Class[] cargs = new Class[] { args.getClass() }; Class[] cargs = new Class[] { args.getClass() };
Method main = clazz.getMethod("main", cargs); Method main = clazz.getMethod("main", cargs);
Object[] nargs = new Object[] { args }; Object[] nargs = new Object[] { args };
// run // run
main.invoke(null, nargs); main.invoke(null, nargs);
} }
} }

View file

@ -1,5 +1,18 @@
// ConcurrencyException.java /*
// Copyright (c) Hannes Wallnöfer 1998-2000 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.objectmodel; package helma.objectmodel;
@ -8,44 +21,13 @@ package helma.objectmodel;
* Thrown when more than one thrad tries to modify a Node. The evaluator * Thrown when more than one thrad tries to modify a Node. The evaluator
* will normally catch this and try again after a period of time. * will normally catch this and try again after a period of time.
*/ */
public class ConcurrencyException extends RuntimeException { public class ConcurrencyException extends RuntimeException {
/**
* Creates a new ConcurrencyException object.
*
* @param msg ...
*/
public ConcurrencyException(String msg) { public ConcurrencyException(String msg) {
super(msg); super(msg);
} }
} }

View file

@ -1,4 +1,18 @@
// DatabaseException.java /*
* Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.objectmodel; package helma.objectmodel;
@ -6,44 +20,13 @@ package helma.objectmodel;
/** /**
* Thrown on any kind of Database-Error * Thrown on any kind of Database-Error
*/ */
public class DatabaseException extends RuntimeException { public class DatabaseException extends RuntimeException {
/**
* Creates a new DatabaseException object.
*
* @param msg ...
*/
public DatabaseException(String msg) { public DatabaseException(String msg) {
super(msg); super(msg);
} }
} }

View file

@ -1,35 +1,104 @@
// IDatabase.java /*
* Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.objectmodel; package helma.objectmodel;
import helma.objectmodel.db.IDGenerator;
import helma.objectmodel.INode; import helma.objectmodel.INode;
import helma.objectmodel.db.IDGenerator;
/** /**
* Interface that is implemented by Database wrappers * Interface that is implemented by Database wrappers
*/ */
public interface IDatabase { public interface IDatabase {
// db-related // db-related
public void shutdown(); public void shutdown();
// id-related // id-related
public String nextID() throws ObjectNotFoundException; public String nextID() throws ObjectNotFoundException;
public IDGenerator getIDGenerator (ITransaction transaction) throws Exception;
public void saveIDGenerator (ITransaction transaction, IDGenerator idgen) throws Exception; /**
*
*
* @param transaction ...
*
* @return ...
*
* @throws Exception ...
*/
public IDGenerator getIDGenerator(ITransaction transaction)
throws Exception;
/**
*
*
* @param transaction ...
* @param idgen ...
*
* @throws Exception ...
*/
public void saveIDGenerator(ITransaction transaction, IDGenerator idgen)
throws Exception;
// node-related // node-related
public INode getNode (ITransaction transaction, String key) throws Exception; public INode getNode(ITransaction transaction, String key)
public void saveNode (ITransaction transaction, String key, INode node) throws Exception; throws Exception;
public void deleteNode (ITransaction transaction, String key) throws Exception;
/**
*
*
* @param transaction ...
* @param key ...
* @param node ...
*
* @throws Exception ...
*/
public void saveNode(ITransaction transaction, String key, INode node)
throws Exception;
/**
*
*
* @param transaction ...
* @param key ...
*
* @throws Exception ...
*/
public void deleteNode(ITransaction transaction, String key)
throws Exception;
// transaction-related // transaction-related
public ITransaction beginTransaction(); public ITransaction beginTransaction();
public void commitTransaction (ITransaction transaction) throws DatabaseException;
public void abortTransaction (ITransaction transaction) throws DatabaseException;
/**
*
*
* @param transaction ...
*
* @throws DatabaseException ...
*/
public void commitTransaction(ITransaction transaction)
throws DatabaseException;
/**
*
*
* @param transaction ...
*
* @throws DatabaseException ...
*/
public void abortTransaction(ITransaction transaction)
throws DatabaseException;
} }

View file

@ -1,88 +1,391 @@
// INode.java /*
// Copyright (c) Hannes Wallnöfer 1998-2000 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.objectmodel; package helma.objectmodel;
import java.util.*;
import java.io.*;
import helma.framework.IPathElement; import helma.framework.IPathElement;
import helma.objectmodel.db.DbMapping; import helma.objectmodel.db.DbMapping;
import java.io.*;
import java.util.*;
/** /**
* Interface that all Nodes implement. Currently, there are two implementations: * Interface that all Nodes implement. Currently, there are two implementations:
* Transient nodes which only exist in memory, and persistent Nodes, which are * Transient nodes which only exist in memory, and persistent Nodes, which are
* stored in a database (either the internal Object DB or an external relational DB). * stored in a database (either the internal Object DB or an external relational DB).
*/ */
public interface INode extends INodeState, IPathElement { public interface INode extends INodeState, IPathElement {
/** /**
* id-related methods * id-related methods
*/ */
public String getID(); public String getID();
/**
*
*
* @return ...
*/
public String getName(); public String getName();
/**
*
*
* @param dbmap ...
*/
public void setDbMapping(DbMapping dbmap); public void setDbMapping(DbMapping dbmap);
/**
*
*
* @return ...
*/
public DbMapping getDbMapping(); public DbMapping getDbMapping();
/**
*
*
* @return ...
*/
public int getState(); public int getState();
/**
*
*
* @param s ...
*/
public void setState(int s); public void setState(int s);
/**
*
*
* @param name ...
*/
public void setName(String name); public void setName(String name);
/**
*
*
* @return ...
*/
public long lastModified(); public long lastModified();
/**
*
*
* @return ...
*/
public long created(); public long created();
/**
*
*
* @return ...
*/
public boolean isAnonymous(); // is this a named node, or an anonymous node in a collection? public boolean isAnonymous(); // is this a named node, or an anonymous node in a collection?
/**
*
*
* @return ...
*/
public String getPrototype(); public String getPrototype();
/**
*
*
* @param prototype ...
*/
public void setPrototype(String prototype); public void setPrototype(String prototype);
/**
*
*
* @return ...
*/
public INode getCacheNode(); public INode getCacheNode();
/**
*
*/
public void clearCacheNode(); public void clearCacheNode();
/**
*
*
* @return ...
*/
public String getFullName(); public String getFullName();
/**
*
*
* @param root ...
*
* @return ...
*/
public String getFullName(INode root); public String getFullName(INode root);
/** /**
* node-related methods * node-related methods
*/ */
public INode getParent(); public INode getParent();
/**
*
*
* @param rel ...
*/
public void setSubnodeRelation(String rel); public void setSubnodeRelation(String rel);
/**
*
*
* @return ...
*/
public String getSubnodeRelation(); public String getSubnodeRelation();
/**
*
*
* @return ...
*/
public int numberOfNodes(); public int numberOfNodes();
/**
*
*
* @param node ...
*
* @return ...
*/
public INode addNode(INode node); public INode addNode(INode node);
/**
*
*
* @param node ...
* @param where ...
*
* @return ...
*/
public INode addNode(INode node, int where); public INode addNode(INode node, int where);
/**
*
*
* @param name ...
*
* @return ...
*/
public INode createNode(String name); public INode createNode(String name);
/**
*
*
* @param name ...
* @param where ...
*
* @return ...
*/
public INode createNode(String name, int where); public INode createNode(String name, int where);
/**
*
*
* @return ...
*/
public Enumeration getSubnodes(); public Enumeration getSubnodes();
/**
*
*
* @param name ...
*
* @return ...
*/
public INode getSubnode(String name); public INode getSubnode(String name);
/**
*
*
* @param index ...
*
* @return ...
*/
public INode getSubnodeAt(int index); public INode getSubnodeAt(int index);
/**
*
*
* @param node ...
*
* @return ...
*/
public int contains(INode node); public int contains(INode node);
/**
*
*
* @return ...
*/
public boolean remove(); public boolean remove();
/**
*
*
* @param node ...
*/
public void removeNode(INode node); public void removeNode(INode node);
/** /**
* property-related methods * property-related methods
*/ */
public Enumeration properties(); public Enumeration properties();
/**
*
*
* @param name ...
*
* @return ...
*/
public IProperty get(String name); public IProperty get(String name);
/**
*
*
* @param name ...
*
* @return ...
*/
public String getString(String name); public String getString(String name);
/**
*
*
* @param name ...
*
* @return ...
*/
public boolean getBoolean(String name); public boolean getBoolean(String name);
/**
*
*
* @param name ...
*
* @return ...
*/
public Date getDate(String name); public Date getDate(String name);
/**
*
*
* @param name ...
*
* @return ...
*/
public long getInteger(String name); public long getInteger(String name);
/**
*
*
* @param name ...
*
* @return ...
*/
public double getFloat(String name); public double getFloat(String name);
/**
*
*
* @param name ...
*
* @return ...
*/
public INode getNode(String name); public INode getNode(String name);
/**
*
*
* @param name ...
*
* @return ...
*/
public Object getJavaObject(String name); public Object getJavaObject(String name);
/**
*
*
* @param name ...
* @param value ...
*/
public void setString(String name, String value); public void setString(String name, String value);
/**
*
*
* @param name ...
* @param value ...
*/
public void setBoolean(String name, boolean value); public void setBoolean(String name, boolean value);
/**
*
*
* @param name ...
* @param value ...
*/
public void setDate(String name, Date value); public void setDate(String name, Date value);
/**
*
*
* @param name ...
* @param value ...
*/
public void setInteger(String name, long value); public void setInteger(String name, long value);
/**
*
*
* @param name ...
* @param value ...
*/
public void setFloat(String name, double value); public void setFloat(String name, double value);
/**
*
*
* @param name ...
* @param value ...
*/
public void setNode(String name, INode value); public void setNode(String name, INode value);
/**
*
*
* @param name ...
* @param value ...
*/
public void setJavaObject(String name, Object value); public void setJavaObject(String name, Object value);
/**
*
*
* @param name ...
*/
public void unset(String name); public void unset(String name);
} }

View file

@ -1,17 +1,28 @@
// INodeState.java /*
// Copyright (c) Hannes Wallnöfer 2001 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.objectmodel; package helma.objectmodel;
import java.util.*;
import java.io.*; import java.io.*;
import java.util.*;
/** /**
* Interface that defines states of nodes * Interface that defines states of nodes
*/ */
public interface INodeState { public interface INodeState {
public final static int TRANSIENT = -3; public final static int TRANSIENT = -3;
public final static int VIRTUAL = -2; public final static int VIRTUAL = -2;
public final static int INVALID = -1; public final static int INVALID = -1;
@ -19,9 +30,4 @@ public interface INodeState {
public final static int NEW = 1; public final static int NEW = 1;
public final static int MODIFIED = 2; public final static int MODIFIED = 2;
public final static int DELETED = 3; public final static int DELETED = 3;
} }

View file

@ -1,5 +1,18 @@
// IProperty.java /*
// Copyright (c) Hannes Wallnöfer 1997-2000 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.objectmodel; package helma.objectmodel;
@ -8,9 +21,7 @@ import java.util.Date;
/** /**
* Interface that is implemented by node properties. * Interface that is implemented by node properties.
*/ */
public interface IProperty { public interface IProperty {
public static final int STRING = 1; public static final int STRING = 1;
public static final int BOOLEAN = 2; public static final int BOOLEAN = 2;
public static final int DATE = 3; public static final int DATE = 3;
@ -19,16 +30,73 @@ public interface IProperty {
public static final int NODE = 6; public static final int NODE = 6;
public static final int JAVAOBJECT = 7; public static final int JAVAOBJECT = 7;
/**
*
*
* @return ...
*/
public String getName(); public String getName();
/**
*
*
* @return ...
*/
public int getType(); public int getType();
/**
*
*
* @return ...
*/
public Object getValue(); public Object getValue();
/**
*
*
* @return ...
*/
public INode getNodeValue(); public INode getNodeValue();
public String getStringValue ();
public boolean getBooleanValue ();
public long getIntegerValue ();
public double getFloatValue ();
public Date getDateValue ();
public Object getJavaObjectValue ();
/**
*
*
* @return ...
*/
public String getStringValue();
/**
*
*
* @return ...
*/
public boolean getBooleanValue();
/**
*
*
* @return ...
*/
public long getIntegerValue();
/**
*
*
* @return ...
*/
public double getFloatValue();
/**
*
*
* @return ...
*/
public Date getDateValue();
/**
*
*
* @return ...
*/
public Object getJavaObjectValue();
} }

View file

@ -1,18 +1,27 @@
// ITransaction.java /*
* Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.objectmodel; package helma.objectmodel;
/** /**
* This interface is kept for databases that are able * This interface is kept for databases that are able
* to run transactions. Transactions were used for the * to run transactions. Transactions were used for the
* Berkeley database and might be used in other future * Berkeley database and might be used in other future
* databases, so we leave transactions in. * databases, so we leave transactions in.
*/ */
public interface ITransaction { public interface ITransaction {
} }

View file

@ -1,5 +1,18 @@
// NodeEvent.java /*
// Copyright (c) Hannes Wallnöfer 1998-2000 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.objectmodel; package helma.objectmodel;
@ -8,21 +21,24 @@ import java.io.*;
/** /**
* This is passed to NodeListeners when a node is modified. * This is passed to NodeListeners when a node is modified.
*/ */
public class NodeEvent implements Serializable { public class NodeEvent implements Serializable {
public static final int CONTENT_CHANGED = 0; public static final int CONTENT_CHANGED = 0;
public static final int PROPERTIES_CHANGED = 1; public static final int PROPERTIES_CHANGED = 1;
public static final int NODE_REMOVED = 2; public static final int NODE_REMOVED = 2;
public static final int NODE_RENAMED = 3; public static final int NODE_RENAMED = 3;
public static final int SUBNODE_ADDED = 4; public static final int SUBNODE_ADDED = 4;
public static final int SUBNODE_REMOVED = 5; public static final int SUBNODE_REMOVED = 5;
public int type; public int type;
public String id; public String id;
public transient INode node; public transient INode node;
public transient Object arg; public transient Object arg;
/**
* Creates a new NodeEvent object.
*
* @param node ...
* @param type ...
*/
public NodeEvent(INode node, int type) { public NodeEvent(INode node, int type) {
super(); super();
this.node = node; this.node = node;
@ -30,6 +46,13 @@ public class NodeEvent implements Serializable {
this.type = type; this.type = type;
} }
/**
* Creates a new NodeEvent object.
*
* @param node ...
* @param type ...
* @param arg ...
*/
public NodeEvent(INode node, int type, Object arg) { public NodeEvent(INode node, int type, Object arg) {
super(); super();
this.node = node; this.node = node;
@ -38,22 +61,32 @@ public class NodeEvent implements Serializable {
this.arg = arg; this.arg = arg;
} }
/**
*
*
* @return ...
*/
public String toString() { public String toString() {
switch (type) { switch (type) {
case CONTENT_CHANGED: case CONTENT_CHANGED:
return "NodeEvent: content changed"; return "NodeEvent: content changed";
case PROPERTIES_CHANGED: case PROPERTIES_CHANGED:
return "NodeEvent: properties changed"; return "NodeEvent: properties changed";
case NODE_REMOVED: case NODE_REMOVED:
return "NodeEvent: node removed"; return "NodeEvent: node removed";
case NODE_RENAMED: case NODE_RENAMED:
return "NodeEvent: node moved"; return "NodeEvent: node moved";
case SUBNODE_ADDED: case SUBNODE_ADDED:
return "NodeEvent: subnode added"; return "NodeEvent: subnode added";
case SUBNODE_REMOVED: case SUBNODE_REMOVED:
return "NodeEvent: subnode removed"; return "NodeEvent: subnode removed";
} }
return "NodeEvent: invalid type"; return "NodeEvent: invalid type";
} }
} }

View file

@ -1,5 +1,18 @@
// ObjectNotFoundException.java /*
// Copyright (c) Hannes Wallnöfer 1998-2000 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.objectmodel; package helma.objectmodel;
@ -8,42 +21,13 @@ package helma.objectmodel;
* Thrown when an object could not found in the database where * Thrown when an object could not found in the database where
* it was expected. * it was expected.
*/ */
public class ObjectNotFoundException extends Exception { public class ObjectNotFoundException extends Exception {
/**
* Creates a new ObjectNotFoundException object.
*
* @param msg ...
*/
public ObjectNotFoundException(String msg) { public ObjectNotFoundException(String msg) {
super(msg); super(msg);
} }
} }

View file

@ -1,195 +1,350 @@
// Property.java /*
// Copyright (c) Hannes Wallnöfer 1997-2000 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.objectmodel; package helma.objectmodel;
import helma.util.*; import helma.util.*;
import java.util.Vector;
import java.util.Hashtable;
import java.util.Date;
import java.util.Enumeration;
import java.io.*; import java.io.*;
import java.text.*; import java.text.*;
import java.util.Date;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
/** /**
* A property implementation for Nodes stored inside a database. * A property implementation for Nodes stored inside a database.
*/ */
public final class Property implements IProperty, Serializable { public final class Property implements IProperty, Serializable {
protected String propname; protected String propname;
protected TransientNode node; protected TransientNode node;
public String svalue; public String svalue;
public boolean bvalue; public boolean bvalue;
public long lvalue; public long lvalue;
public double dvalue; public double dvalue;
public INode nvalue; public INode nvalue;
public Object jvalue; public Object jvalue;
public int type; public int type;
/**
* Creates a new Property object.
*
* @param node ...
*/
public Property(TransientNode node) { public Property(TransientNode node) {
this.node = node; this.node = node;
} }
/**
* Creates a new Property object.
*
* @param propname ...
* @param node ...
*/
public Property(String propname, TransientNode node) { public Property(String propname, TransientNode node) {
this.propname = propname; this.propname = propname;
this.node = node; this.node = node;
} }
/**
*
*
* @return ...
*/
public String getName() { public String getName() {
return propname; return propname;
} }
/**
*
*
* @return ...
*/
public Object getValue() { public Object getValue() {
switch (type) { switch (type) {
case STRING: case STRING:
return svalue; return svalue;
case BOOLEAN: case BOOLEAN:
return new Boolean(bvalue); return new Boolean(bvalue);
case INTEGER: case INTEGER:
return new Long(lvalue); return new Long(lvalue);
case FLOAT: case FLOAT:
return new Double(dvalue); return new Double(dvalue);
case DATE: case DATE:
return new Date(lvalue); return new Date(lvalue);
case NODE: case NODE:
return nvalue; return nvalue;
case JAVAOBJECT: case JAVAOBJECT:
return jvalue; return jvalue;
} }
return null; return null;
} }
/**
*
*
* @param value ...
*/
public void setStringValue(String value) { public void setStringValue(String value) {
if (type == NODE) if (type == NODE) {
this.nvalue = null; this.nvalue = null;
if (type == JAVAOBJECT) }
if (type == JAVAOBJECT) {
this.jvalue = null; this.jvalue = null;
}
type = STRING; type = STRING;
this.svalue = value; this.svalue = value;
} }
/**
*
*
* @param value ...
*/
public void setIntegerValue(long value) { public void setIntegerValue(long value) {
if (type == NODE) if (type == NODE) {
this.nvalue = null; this.nvalue = null;
if (type == JAVAOBJECT) }
if (type == JAVAOBJECT) {
this.jvalue = null; this.jvalue = null;
}
type = INTEGER; type = INTEGER;
this.lvalue = value; this.lvalue = value;
} }
/**
*
*
* @param value ...
*/
public void setFloatValue(double value) { public void setFloatValue(double value) {
if (type == NODE) if (type == NODE) {
this.nvalue = null; this.nvalue = null;
if (type == JAVAOBJECT) }
if (type == JAVAOBJECT) {
this.jvalue = null; this.jvalue = null;
}
type = FLOAT; type = FLOAT;
this.dvalue = value; this.dvalue = value;
} }
/**
*
*
* @param value ...
*/
public void setDateValue(Date value) { public void setDateValue(Date value) {
if (type == NODE) if (type == NODE) {
this.nvalue = null; this.nvalue = null;
if (type == JAVAOBJECT) }
if (type == JAVAOBJECT) {
this.jvalue = null; this.jvalue = null;
}
type = DATE; type = DATE;
this.lvalue = value.getTime(); this.lvalue = value.getTime();
} }
/**
*
*
* @param value ...
*/
public void setBooleanValue(boolean value) { public void setBooleanValue(boolean value) {
if (type == NODE) if (type == NODE) {
this.nvalue = null; this.nvalue = null;
if (type == JAVAOBJECT) }
if (type == JAVAOBJECT) {
this.jvalue = null; this.jvalue = null;
}
type = BOOLEAN; type = BOOLEAN;
this.bvalue = value; this.bvalue = value;
} }
/**
*
*
* @param value ...
*/
public void setNodeValue(INode value) { public void setNodeValue(INode value) {
if (type == JAVAOBJECT) if (type == JAVAOBJECT) {
this.jvalue = null; this.jvalue = null;
}
type = NODE; type = NODE;
this.nvalue = value; this.nvalue = value;
} }
/**
*
*
* @param value ...
*/
public void setJavaObjectValue(Object value) { public void setJavaObjectValue(Object value) {
if (type == NODE) if (type == NODE) {
this.nvalue = null; this.nvalue = null;
}
type = JAVAOBJECT; type = JAVAOBJECT;
this.jvalue = value; this.jvalue = value;
} }
/**
*
*
* @return ...
*/
public String getStringValue() { public String getStringValue() {
switch (type) { switch (type) {
case STRING: case STRING:
return svalue; return svalue;
case BOOLEAN: case BOOLEAN:
return "" + bvalue; return "" + bvalue;
case DATE: case DATE:
SimpleDateFormat format = new SimpleDateFormat("dd.MM.yy HH:mm"); SimpleDateFormat format = new SimpleDateFormat("dd.MM.yy HH:mm");
return format.format(new Date(lvalue)); return format.format(new Date(lvalue));
case INTEGER: case INTEGER:
return Long.toString(lvalue); return Long.toString(lvalue);
case FLOAT: case FLOAT:
return Double.toString(dvalue); return Double.toString(dvalue);
case NODE: case NODE:
return nvalue.getName(); return nvalue.getName();
case JAVAOBJECT: case JAVAOBJECT:
return jvalue == null ? null : jvalue.toString (); return (jvalue == null) ? null : jvalue.toString();
} }
return ""; return "";
} }
/**
*
*
* @return ...
*/
public String toString() { public String toString() {
return getStringValue(); return getStringValue();
} }
/**
*
*
* @return ...
*/
public long getIntegerValue() { public long getIntegerValue() {
if (type == INTEGER) if (type == INTEGER) {
return lvalue; return lvalue;
}
return 0; return 0;
} }
/**
*
*
* @return ...
*/
public double getFloatValue() { public double getFloatValue() {
if (type == FLOAT) if (type == FLOAT) {
return dvalue; return dvalue;
}
return 0.0; return 0.0;
} }
/**
*
*
* @return ...
*/
public Date getDateValue() { public Date getDateValue() {
if (type == DATE) if (type == DATE) {
return new Date(lvalue); return new Date(lvalue);
}
return null; return null;
} }
/**
*
*
* @return ...
*/
public boolean getBooleanValue() { public boolean getBooleanValue() {
if (type == BOOLEAN) if (type == BOOLEAN) {
return bvalue; return bvalue;
}
return false; return false;
} }
/**
*
*
* @return ...
*/
public INode getNodeValue() { public INode getNodeValue() {
if (type == NODE) if (type == NODE) {
return nvalue; return nvalue;
}
return null; return null;
} }
/**
*
*
* @return ...
*/
public Object getJavaObjectValue() { public Object getJavaObjectValue() {
if (type == JAVAOBJECT) if (type == JAVAOBJECT) {
return jvalue; return jvalue;
}
return null; return null;
} }
/**
*
*
* @return ...
*/
public int getType() { public int getType() {
return type; return type;
} }
} }

File diff suppressed because it is too large Load diff

View file

@ -1,14 +1,27 @@
// DbColumn.java /*
// Copyright 2002 Hannes Wallnoefer, Helma.org * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.objectmodel.db; package helma.objectmodel.db;
/** /**
* A class that encapsulates the Column name and data type of a * A class that encapsulates the Column name and data type of a
* column in a relational table. * column in a relational table.
*/ */
public final class DbColumn { public final class DbColumn {
private final String name; private final String name;
private final int type; private final int type;
private final Relation relation; private final Relation relation;
@ -20,9 +33,11 @@ public final class DbColumn {
this.name = name; this.name = name;
this.type = type; this.type = type;
this.relation = rel; this.relation = rel;
if (relation != null)
if (relation != null) {
relation.setColumnType(type); relation.setColumnType(type);
} }
}
/** /**
* Get the column name. * Get the column name.
@ -44,5 +59,4 @@ public final class DbColumn {
public Relation getRelation() { public Relation getRelation() {
return relation; return relation;
} }
} }

View file

@ -1,22 +1,34 @@
// DbKey.java /*
// Copyright (c) Hannes Wallnöfer 1998-2000 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.objectmodel.db; package helma.objectmodel.db;
import java.io.Serializable; import java.io.Serializable;
/** /**
* This is the internal representation of a database key. It is constructed * This is the internal representation of a database key. It is constructed
* from the logical table (type) name and the object's primary key * from the logical table (type) name and the object's primary key
* within the table. Currently only single keys are supported. * within the table. Currently only single keys are supported.
*/ */
public final class DbKey implements Key, Serializable { public final class DbKey implements Key, Serializable {
// the name of the prototype which defines the storage of this object. // the name of the prototype which defines the storage of this object.
// this is the name of the object's prototype, or one of its ancestors. // this is the name of the object's prototype, or one of its ancestors.
// If null, the object is stored in the embedded db. // If null, the object is stored in the embedded db.
private final String storageName; private final String storageName;
// the id that defines this key's object within the above storage space // the id that defines this key's object within the above storage space
private final String id; private final String id;
@ -28,48 +40,80 @@ public final class DbKey implements Key, Serializable {
*/ */
public DbKey(DbMapping dbmap, String id) { public DbKey(DbMapping dbmap, String id) {
this.id = id; this.id = id;
this.storageName = dbmap == null ? null : dbmap.getStorageTypeName (); this.storageName = (dbmap == null) ? null : dbmap.getStorageTypeName();
} }
/**
*
*
* @param what ...
*
* @return ...
*/
public boolean equals(Object what) { public boolean equals(Object what) {
if (what == this) if (what == this) {
return true; return true;
if (!(what instanceof DbKey)) }
if (!(what instanceof DbKey)) {
return false; return false;
}
DbKey k = (DbKey) what; DbKey k = (DbKey) what;
// storageName is an interned string (by DbMapping, from where we got it) // storageName is an interned string (by DbMapping, from where we got it)
// so we can compare by using == instead of the equals method. // so we can compare by using == instead of the equals method.
return storageName == k.storageName && (id == k.id || id.equals (k.id)); return (storageName == k.storageName) && ((id == k.id) || id.equals(k.id));
} }
/**
*
*
* @return ...
*/
public int hashCode() { public int hashCode() {
if (hashcode == 0) { if (hashcode == 0) {
hashcode = storageName == null ? hashcode = (storageName == null) ? (17 + (37 * id.hashCode()))
17 + 37*id.hashCode () : : (17 + (37 * storageName.hashCode()) +
17 + 37*storageName.hashCode() + +37*id.hashCode (); (+37 * id.hashCode()));
} }
return hashcode; return hashcode;
} }
/**
*
*
* @return ...
*/
public Key getParentKey() { public Key getParentKey() {
return null; return null;
} }
/**
*
*
* @return ...
*/
public String getStorageName() { public String getStorageName() {
return storageName; return storageName;
} }
/**
*
*
* @return ...
*/
public String getID() { public String getID() {
return id; return id;
} }
/**
*
*
* @return ...
*/
public String toString() { public String toString() {
return storageName == null ? "["+id+"]" : storageName+"["+id+"]"; return (storageName == null) ? ("[" + id + "]") : (storageName + "[" + id + "]");
} }
} }

File diff suppressed because it is too large Load diff

View file

@ -1,49 +1,82 @@
// DbSource.java /*
// Copyright (c) Hannes Wallnöfer 1999-2000 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.objectmodel.db; package helma.objectmodel.db;
import helma.util.SystemProperties;
import java.sql.*; import java.sql.*;
import java.util.Hashtable; import java.util.Hashtable;
import helma.util.SystemProperties;
/** /**
* This class describes a releational data source (URL, driver, user and password). * This class describes a releational data source (URL, driver, user and password).
*/ */
public class DbSource { public class DbSource {
private static SystemProperties defaultProps = null;
private String name; private String name;
private SystemProperties props; private SystemProperties props;
private static SystemProperties defaultProps = null;
protected String url; protected String url;
private String driver; private String driver;
protected String user; protected String user;
private String password; private String password;
private long lastRead = 0L;
private long lastRead = 0l; /**
* Creates a new DbSource object.
public DbSource (String name, SystemProperties props) throws ClassNotFoundException { *
* @param name ...
* @param props ...
*
* @throws ClassNotFoundException ...
*/
public DbSource(String name, SystemProperties props)
throws ClassNotFoundException {
this.name = name; this.name = name;
this.props = props; this.props = props;
init(); init();
} }
/**
*
*
* @return ...
*
* @throws ClassNotFoundException ...
* @throws SQLException ...
*/
public Connection getConnection() throws ClassNotFoundException, SQLException { public Connection getConnection() throws ClassNotFoundException, SQLException {
Transactor tx = (Transactor) Thread.currentThread(); Transactor tx = (Transactor) Thread.currentThread();
Connection con = tx.getConnection(this); Connection con = tx.getConnection(this);
boolean fileUpdated = props.lastModified() > lastRead; boolean fileUpdated = props.lastModified() > lastRead;
if (!fileUpdated && defaultProps != null)
if (!fileUpdated && (defaultProps != null)) {
fileUpdated = defaultProps.lastModified() > lastRead; fileUpdated = defaultProps.lastModified() > lastRead;
if (con == null || con.isClosed () || fileUpdated) { }
if ((con == null) || con.isClosed() || fileUpdated) {
init(); init();
Class.forName(driver); Class.forName(driver);
con = DriverManager.getConnection(url, user, password); con = DriverManager.getConnection(url, user, password);
// If we wanted to use SQL transactions, we'd set autoCommit to // If we wanted to use SQL transactions, we'd set autoCommit to
// false here and make commit/rollback invocations in Transactor methods; // false here and make commit/rollback invocations in Transactor methods;
// System.err.println ("Created new Connection to "+url); // System.err.println ("Created new Connection to "+url);
tx.registerConnection(this, con); tx.registerConnection(this, con);
////////////////////////////////////////////// //////////////////////////////////////////////
/* DatabaseMetaData meta = con.getMetaData (); /* DatabaseMetaData meta = con.getMetaData ();
ResultSet tables = meta.getCatalogs (); ResultSet tables = meta.getCatalogs ();
while (tables.next()) while (tables.next())
@ -53,11 +86,14 @@ public class DbSource {
System.err.println ("******* TYPE: "+types.getObject(1) +" - "+types.getObject(2)+" - "+types.getObject(6)); System.err.println ("******* TYPE: "+types.getObject(1) +" - "+types.getObject(2)+" - "+types.getObject(6));
*/ */
} }
return con; return con;
} }
private void init() throws ClassNotFoundException { private void init() throws ClassNotFoundException {
lastRead = defaultProps == null ? props.lastModified () : Math.max (props.lastModified (), defaultProps.lastModified ()); lastRead = (defaultProps == null) ? props.lastModified()
: Math.max(props.lastModified(),
defaultProps.lastModified());
url = props.getProperty(name + ".url"); url = props.getProperty(name + ".url");
driver = props.getProperty(name + ".driver"); driver = props.getProperty(name + ".driver");
Class.forName(driver); Class.forName(driver);
@ -65,56 +101,30 @@ public class DbSource {
password = props.getProperty(name + ".password"); password = props.getProperty(name + ".password");
} }
/**
*
*
* @return ...
*/
public String getDriverName() { public String getDriverName() {
return driver; return driver;
} }
/**
*
*
* @return ...
*/
public String getName() { public String getName() {
return name; return name;
} }
/**
*
*
* @param props ...
*/
public static void setDefaultProps(SystemProperties props) { public static void setDefaultProps(SystemProperties props) {
defaultProps = props; defaultProps = props;
} }
} }

View file

@ -1,5 +1,18 @@
// ExternalizableVector.java /*
// Copyright (c) Hannes Wallnöfer 1999-2000 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.objectmodel.db; package helma.objectmodel.db;
@ -10,14 +23,21 @@ import java.util.ArrayList;
* A subclass of Vector that implements the Externalizable interface in order * A subclass of Vector that implements the Externalizable interface in order
* to be able to control how it is serialized and deserialized. * to be able to control how it is serialized and deserialized.
*/ */
public class ExternalizableVector extends ArrayList implements Externalizable { public class ExternalizableVector extends ArrayList implements Externalizable {
static final long serialVersionUID = 2316243615310540423L; static final long serialVersionUID = 2316243615310540423L;
public synchronized void readExternal (ObjectInput in) throws IOException { /**
*
*
* @param in ...
*
* @throws IOException ...
*/
public synchronized void readExternal(ObjectInput in)
throws IOException {
try { try {
int size = in.readInt(); int size = in.readInt();
for (int i = 0; i < size; i++) for (int i = 0; i < size; i++)
add(in.readObject()); add(in.readObject());
} catch (ClassNotFoundException x) { } catch (ClassNotFoundException x) {
@ -25,15 +45,20 @@ public class ExternalizableVector extends ArrayList implements Externalizable {
} }
} }
public synchronized void writeExternal (ObjectOutput out) throws IOException { /**
*
*
* @param out ...
*
* @throws IOException ...
*/
public synchronized void writeExternal(ObjectOutput out)
throws IOException {
int size = size(); int size = size();
out.writeInt(size); out.writeInt(size);
for (int i = 0; i < size; i++) for (int i = 0; i < size; i++)
out.writeObject(get(i)); out.writeObject(get(i));
} }
} }

View file

@ -1,5 +1,18 @@
// IDGenerator.java /*
// Copyright (c) Hannes Wallnöfer 1997-2000 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.objectmodel.db; package helma.objectmodel.db;
@ -13,20 +26,16 @@ import java.io.Serializable;
* in Oracle are supported, while auto-IDs are not, since the HOP has to know * in Oracle are supported, while auto-IDs are not, since the HOP has to know
* the keys of new objects.) * the keys of new objects.)
*/ */
public final class IDGenerator implements Serializable { public final class IDGenerator implements Serializable {
static final long serialVersionUID = 753408631669789263L;
private long counter; private long counter;
transient volatile boolean dirty; transient volatile boolean dirty;
static final long serialVersionUID = 753408631669789263L;
/** /**
* Builds a new IDGenerator starting with 0. * Builds a new IDGenerator starting with 0.
*/ */
public IDGenerator() { public IDGenerator() {
this.counter = 0l; this.counter = 0L;
dirty = false; dirty = false;
} }
@ -42,8 +51,9 @@ public final class IDGenerator implements Serializable {
* Delivers a unique id and increases counter by 1. * Delivers a unique id and increases counter by 1.
*/ */
public synchronized String newID() { public synchronized String newID() {
counter += 1l; counter += 1L;
dirty = true; dirty = true;
return Long.toString(counter); return Long.toString(counter);
} }
@ -62,12 +72,13 @@ public final class IDGenerator implements Serializable {
return counter; return counter;
} }
/**
*
*
* @return ...
*/
public String toString() { public String toString() {
return "helma.objectmodel.db.IDGenerator[counter="+counter+",dirty="+dirty+"]"; return "helma.objectmodel.db.IDGenerator[counter=" + counter + ",dirty=" + dirty +
"]";
} }
} }

View file

@ -1,5 +1,18 @@
// IReplicationListener.java /*
// Copyright (c) Hannes Wallnöfer 2002 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.objectmodel.db; package helma.objectmodel.db;
@ -9,13 +22,11 @@ import java.util.Vector;
/** /**
* RMI interface for an application. Currently only execute is used and supported. * RMI interface for an application. Currently only execute is used and supported.
*/ */
public interface IReplicationListener extends Remote { public interface IReplicationListener extends Remote {
/** /**
* Update HopObjects in this application's cache. This is used to replicate * Update HopObjects in this application's cache. This is used to replicate
* application caches in a distributed app environment * application caches in a distributed app environment
*/ */
public void replicateCache (Vector add, Vector delete) throws RemoteException; public void replicateCache(Vector add, Vector delete)
throws RemoteException;
} }

View file

@ -1,5 +1,18 @@
// Key.java /*
// Copyright (c) Hannes Wallnöfer 1998-2000 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.objectmodel.db; package helma.objectmodel.db;
@ -9,66 +22,24 @@ package helma.objectmodel.db;
* *
*/ */
public interface Key { public interface Key {
/**
*
*
* @return ...
*/
public Key getParentKey(); public Key getParentKey();
/**
*
*
* @return ...
*/
public String getID(); public String getID();
/**
*
*
* @return ...
*/
public String getStorageName(); public String getStorageName();
} }

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,18 @@
// NodeHandle.java /*
// Copyright (c) Hannes Wallnöfer 1998-2000 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.objectmodel.db; package helma.objectmodel.db;
@ -16,8 +29,8 @@ import java.io.Serializable;
* and reinstanciated since being set, NodeHandle will always return an up-to-date * and reinstanciated since being set, NodeHandle will always return an up-to-date
* instance of its node. * instance of its node.
*/ */
public final class NodeHandle implements INodeState, Serializable { public final class NodeHandle implements INodeState, Serializable {
static final long serialVersionUID = 3067763116576910931L;
// direct reference to the node // direct reference to the node
private Node node; private Node node;
@ -25,13 +38,12 @@ public final class NodeHandle implements INodeState, Serializable {
// the node's key // the node's key
private Key key; private Key key;
static final long serialVersionUID = 3067763116576910931L;
/** /**
* Builds a handle for a node * Builds a handle for a node
*/ */
public NodeHandle(Node node) { public NodeHandle(Node node) {
int state = node.getState(); int state = node.getState();
if (state == TRANSIENT) { if (state == TRANSIENT) {
this.node = node; this.node = node;
key = null; key = null;
@ -55,8 +67,10 @@ public final class NodeHandle implements INodeState, Serializable {
* Get the node described by this node handle * Get the node described by this node handle
*/ */
public Node getNode(WrappedNodeManager nodemgr) { public Node getNode(WrappedNodeManager nodemgr) {
if (node != null) if (node != null) {
return node; return node;
}
return nodemgr.getNode(key); return nodemgr.getNode(key);
} }
@ -65,8 +79,10 @@ public final class NodeHandle implements INodeState, Serializable {
* This may only be called on persistent Nodes. * This may only be called on persistent Nodes.
*/ */
public Key getKey() { public Key getKey() {
if (key == null) if (key == null) {
throw new RuntimeException("getKey called on transient Node"); throw new RuntimeException("getKey called on transient Node");
}
return key; return key;
} }
@ -75,18 +91,28 @@ public final class NodeHandle implements INodeState, Serializable {
* This may only be called on persistent Nodes. * This may only be called on persistent Nodes.
*/ */
public String getID() { public String getID() {
if (key == null) if (key == null) {
return node.getID(); return node.getID();
}
return key.getID(); return key.getID();
} }
private Object getObject() { private Object getObject() {
if (node != null) if (node != null) {
return node; return node;
else } else {
return key; return key;
} }
}
/**
*
*
* @param other ...
*
* @return ...
*/
public boolean equals(Object other) { public boolean equals(Object other) {
try { try {
return getObject().equals(((NodeHandle) other).getObject()); return getObject().equals(((NodeHandle) other).getObject());
@ -106,13 +132,16 @@ public final class NodeHandle implements INodeState, Serializable {
} }
} }
/**
*
*
* @return ...
*/
public String toString() { public String toString() {
if (node != null) if (node != null) {
return "NodeHandle[transient:" + node + "]"; return "NodeHandle[transient:" + node + "]";
else } else {
return "NodeHandle[" + key + "]"; return "NodeHandle[" + key + "]";
} }
} }
}

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,18 @@
// ParentInfo.java /*
// Copyright (c) Hannes Wallnöfer 1999-2000 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.objectmodel.db; package helma.objectmodel.db;
@ -7,21 +20,26 @@ package helma.objectmodel.db;
/** /**
* This class describes a parent relation between releational nodes. * This class describes a parent relation between releational nodes.
*/ */
public class ParentInfo { public class ParentInfo {
public final String propname; public final String propname;
public final String virtualname; public final String virtualname;
public final boolean named; public final boolean named;
public final boolean isroot; public final boolean isroot;
/**
* Creates a new ParentInfo object.
*
* @param desc ...
*/
public ParentInfo(String desc) { public ParentInfo(String desc) {
int n = desc.indexOf("[named]"); int n = desc.indexOf("[named]");
named = n > -1; named = n > -1;
String d = named ? desc.substring(0, n) : desc; String d = named ? desc.substring(0, n) : desc;
int dot = d.indexOf("."); int dot = d.indexOf(".");
if (dot > -1) { if (dot > -1) {
propname = d.substring(0, dot).trim(); propname = d.substring(0, dot).trim();
virtualname = d.substring(dot + 1).trim(); virtualname = d.substring(dot + 1).trim();
@ -31,11 +49,16 @@ public class ParentInfo {
} }
isroot = "root".equals(propname); isroot = "root".equals(propname);
// System.err.println ("created "+this); // System.err.println ("created "+this);
} }
/**
*
*
* @return ...
*/
public String toString() { public String toString() {
return "ParentInfo[" + propname + "," + virtualname + "," + named + "]"; return "ParentInfo[" + propname + "," + virtualname + "," + named + "]";
} }
} }

View file

@ -1,67 +1,128 @@
// Property.java /*
// Copyright (c) Hannes Wallnöfer 1997-2000 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.objectmodel.db; package helma.objectmodel.db;
import helma.util.*;
import java.util.*;
import java.io.*;
import java.text.*;
import helma.objectmodel.*; import helma.objectmodel.*;
import helma.util.*;
import java.io.*;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.text.*;
import java.util.*;
/** /**
* A property implementation for Nodes stored inside a database. Basically * A property implementation for Nodes stored inside a database. Basically
* the same as for transient nodes, with a few hooks added. * the same as for transient nodes, with a few hooks added.
*/ */
public final class Property implements IProperty, Serializable, Cloneable { public final class Property implements IProperty, Serializable, Cloneable {
static final long serialVersionUID = -1022221688349192379L;
private String propname; private String propname;
private Node node; private Node node;
private Object value; private Object value;
private int type; private int type;
transient boolean dirty; transient boolean dirty;
static final long serialVersionUID = -1022221688349192379L; /**
* Creates a new Property object.
*
* @param node ...
*/
public Property(Node node) {
this.node = node;
dirty = true;
}
/**
* Creates a new Property object.
*
* @param propname ...
* @param node ...
*/
public Property(String propname, Node node) {
this.propname = propname;
this.node = node;
dirty = true;
}
/**
* Creates a new Property object.
*
* @param propname ...
* @param node ...
* @param valueNode ...
*/
public Property(String propname, Node node, Node valueNode) {
this(propname, node);
type = NODE;
value = (valueNode == null) ? null : valueNode.getHandle();
dirty = true;
}
private void readObject(ObjectInputStream in) throws IOException { private void readObject(ObjectInputStream in) throws IOException {
try { try {
propname = in.readUTF(); propname = in.readUTF();
node = (Node) in.readObject(); node = (Node) in.readObject();
type = in.readInt(); type = in.readInt();
switch (type) { switch (type) {
case STRING: case STRING:
// try to convert from old format // try to convert from old format
if (node.version < 7) if (node.version < 7) {
value = in.readUTF(); value = in.readUTF();
else } else {
value = in.readObject(); value = in.readObject();
}
break; break;
case BOOLEAN: case BOOLEAN:
value = in.readBoolean() ? Boolean.TRUE : Boolean.FALSE; value = in.readBoolean() ? Boolean.TRUE : Boolean.FALSE;
break; break;
case INTEGER: case INTEGER:
value = new Long(in.readLong()); value = new Long(in.readLong());
break; break;
case DATE: case DATE:
value = new Date(in.readLong()); value = new Date(in.readLong());
break; break;
case FLOAT: case FLOAT:
value = new Double(in.readDouble()); value = new Double(in.readDouble());
break; break;
case NODE: case NODE:
// try to convert from old format // try to convert from old format
if (node.version > 4) if (node.version > 4) {
value = (NodeHandle) in.readObject(); value = (NodeHandle) in.readObject();
else } else {
value = new NodeHandle(new DbKey(null, in.readUTF())); value = new NodeHandle(new DbKey(null, in.readUTF()));
}
break; break;
case JAVAOBJECT: case JAVAOBJECT:
value = in.readObject(); value = in.readObject();
break; break;
} }
} catch (ClassNotFoundException x) { } catch (ClassNotFoundException x) {
@ -73,189 +134,281 @@ public final class Property implements IProperty, Serializable, Cloneable {
out.writeUTF(propname); out.writeUTF(propname);
out.writeObject(node); out.writeObject(node);
out.writeInt(type); out.writeInt(type);
switch (type) { switch (type) {
case STRING: case STRING:
out.writeObject(value); out.writeObject(value);
break; break;
case BOOLEAN: case BOOLEAN:
out.writeBoolean(((Boolean) value).booleanValue()); out.writeBoolean(((Boolean) value).booleanValue());
break; break;
case INTEGER: case INTEGER:
out.writeLong(((Long) value).longValue()); out.writeLong(((Long) value).longValue());
break; break;
case DATE: case DATE:
out.writeLong(((Date) value).getTime()); out.writeLong(((Date) value).getTime());
break; break;
case FLOAT: case FLOAT:
out.writeDouble(((Double) value).doubleValue()); out.writeDouble(((Double) value).doubleValue());
break; break;
case NODE: case NODE:
out.writeObject(value); out.writeObject(value);
break; break;
case JAVAOBJECT: case JAVAOBJECT:
if (value != null && !(value instanceof Serializable))
if ((value != null) && !(value instanceof Serializable)) {
out.writeObject(null); out.writeObject(null);
else } else {
out.writeObject(value); out.writeObject(value);
}
break; break;
} }
} }
/**
public Property (Node node) { *
this.node = node; *
dirty = true; * @return ...
} */
public Property (String propname, Node node) {
this.propname = propname;
this.node = node;
dirty = true;
}
public Property (String propname, Node node, Node valueNode) {
this (propname, node);
type = NODE;
value = valueNode == null ? null : valueNode.getHandle ();
dirty = true;
}
public String getName() { public String getName() {
return propname; return propname;
} }
/**
*
*
* @return ...
*/
public Object getValue() { public Object getValue() {
return value; return value;
} }
/**
*
*
* @return ...
*/
public int getType() { public int getType() {
return type; return type;
} }
/**
*
*
* @param str ...
*/
public void setStringValue(String str) { public void setStringValue(String str) {
if (type == NODE) if (type == NODE) {
unregisterNode(); unregisterNode();
}
type = STRING; type = STRING;
value = str; value = str;
dirty = true; dirty = true;
} }
/**
*
*
* @param l ...
*/
public void setIntegerValue(long l) { public void setIntegerValue(long l) {
if (type == NODE) if (type == NODE) {
unregisterNode(); unregisterNode();
}
type = INTEGER; type = INTEGER;
value = new Long(l); value = new Long(l);
dirty = true; dirty = true;
} }
/**
*
*
* @param d ...
*/
public void setFloatValue(double d) { public void setFloatValue(double d) {
if (type == NODE) if (type == NODE) {
unregisterNode(); unregisterNode();
}
type = FLOAT; type = FLOAT;
value = new Double(d); value = new Double(d);
dirty = true; dirty = true;
} }
/**
*
*
* @param date ...
*/
public void setDateValue(Date date) { public void setDateValue(Date date) {
if (type == NODE) if (type == NODE) {
unregisterNode(); unregisterNode();
}
type = DATE; type = DATE;
value = date; value = date;
dirty = true; dirty = true;
} }
/**
*
*
* @param bool ...
*/
public void setBooleanValue(boolean bool) { public void setBooleanValue(boolean bool) {
if (type == NODE) if (type == NODE) {
unregisterNode(); unregisterNode();
}
type = BOOLEAN; type = BOOLEAN;
value = bool ? Boolean.TRUE : Boolean.FALSE; value = bool ? Boolean.TRUE : Boolean.FALSE;
dirty = true; dirty = true;
} }
/**
*
*
* @param node ...
*/
public void setNodeValue(Node node) { public void setNodeValue(Node node) {
// value.checkWriteLock (); // value.checkWriteLock ();
if (type == NODE) if (type == NODE) {
unregisterNode(); unregisterNode();
}
// registerNode (value); // registerNode (value);
type = NODE; type = NODE;
value = node == null ? null : node.getHandle (); value = (node == null) ? null : node.getHandle();
dirty = true; dirty = true;
} }
/**
*
*
* @param handle ...
*/
public void setNodeHandle(NodeHandle handle) { public void setNodeHandle(NodeHandle handle) {
if (type == NODE) if (type == NODE) {
unregisterNode(); unregisterNode();
}
// registerNode (value); // registerNode (value);
type = NODE; type = NODE;
value = handle; value = handle;
dirty = true; dirty = true;
} }
/**
*
*
* @return ...
*/
public NodeHandle getNodeHandle() { public NodeHandle getNodeHandle() {
if (type == NODE) if (type == NODE) {
return (NodeHandle) value; return (NodeHandle) value;
}
return null; return null;
} }
/**
*
*
* @param dbm ...
*/
public void convertToNodeReference(DbMapping dbm) { public void convertToNodeReference(DbMapping dbm) {
if (value != null && !(value instanceof NodeHandle)) if ((value != null) && !(value instanceof NodeHandle)) {
value = new NodeHandle(new DbKey(dbm, value.toString())); value = new NodeHandle(new DbKey(dbm, value.toString()));
}
type = NODE; type = NODE;
} }
/**
*
*
* @param obj ...
*/
public void setJavaObjectValue(Object obj) { public void setJavaObjectValue(Object obj) {
if (type == NODE) if (type == NODE) {
unregisterNode(); unregisterNode();
}
type = JAVAOBJECT; type = JAVAOBJECT;
value = obj; value = obj;
} }
/** /**
* tell a the value node that it is no longer used as a property. * tell a the value node that it is no longer used as a property.
* If this was the "main" property for the node, also remove all other references. * If this was the "main" property for the node, also remove all other references.
*/ */
protected void unregisterNode() { protected void unregisterNode() {
if (value == null || !(value instanceof NodeHandle)) if ((value == null) || !(value instanceof NodeHandle)) {
return; return;
}
NodeHandle nhandle = (NodeHandle) value; NodeHandle nhandle = (NodeHandle) value;
Node nvalue = nhandle.getNode(node.nmgr); Node nvalue = nhandle.getNode(node.nmgr);
DbMapping nvmap = null; DbMapping nvmap = null;
Relation nvrel = null; Relation nvrel = null;
if (node.dbmap != null) { if (node.dbmap != null) {
nvmap = node.dbmap.getPropertyMapping(propname); nvmap = node.dbmap.getPropertyMapping(propname);
nvrel = node.dbmap.getPropertyRelation(propname); nvrel = node.dbmap.getPropertyRelation(propname);
} }
if (nvalue == null) if (nvalue == null) {
return; return;
}
nvalue.checkWriteLock(); nvalue.checkWriteLock();
// check if the property node is also a subnode // check if the property node is also a subnode
// BUG: this doesn't work because properties for subnode/properties are never stored and therefore // BUG: this doesn't work because properties for subnode/properties are never stored and therefore
// never reused. // never reused.
if (nvrel != null && nvrel.hasAccessName()) { if ((nvrel != null) && nvrel.hasAccessName()) {
node.removeNode(nvalue); node.removeNode(nvalue);
} }
// only need to call unregisterPropLink if the value node is not stored in a relational db // only need to call unregisterPropLink if the value node is not stored in a relational db
// also, getParent is heuristical/implicit for relational nodes, so we don't do deepRemoveNode // also, getParent is heuristical/implicit for relational nodes, so we don't do deepRemoveNode
// based on that for relational nodes. // based on that for relational nodes.
if (nvmap == null || !nvmap.isRelational()) { if ((nvmap == null) || !nvmap.isRelational()) {
if (!nvalue.isAnonymous() && propname.equals (nvalue.getName()) && this.node == nvalue.getParent()) { if (!nvalue.isAnonymous() && propname.equals(nvalue.getName()) &&
(this.node == nvalue.getParent())) {
// this is the "main" property of a named node, so handle this as a cascading delete. // this is the "main" property of a named node, so handle this as a cascading delete.
nvalue.deepRemoveNode(); nvalue.deepRemoveNode();
} }
} }
} }
/**
*
*
* @return ...
*/
public String getStringValue() { public String getStringValue() {
if (value == null) if (value == null) {
return null; return null;
}
switch (type) { switch (type) {
case STRING: case STRING:
case BOOLEAN: case BOOLEAN:
@ -263,26 +416,47 @@ public final class Property implements IProperty, Serializable, Cloneable {
case FLOAT: case FLOAT:
case JAVAOBJECT: case JAVAOBJECT:
return value.toString(); return value.toString();
case DATE: case DATE:
SimpleDateFormat format = new SimpleDateFormat("dd.MM.yy hh:mm:ss"); SimpleDateFormat format = new SimpleDateFormat("dd.MM.yy hh:mm:ss");
return format.format((Date) value); return format.format((Date) value);
case NODE: case NODE:
return ((NodeHandle) value).getID(); return ((NodeHandle) value).getID();
} }
return ""; return "";
} }
/**
*
*
* @return ...
*/
public String toString() { public String toString() {
return getStringValue(); return getStringValue();
} }
/**
*
*
* @return ...
*/
public long getIntegerValue() { public long getIntegerValue() {
if (type == INTEGER) if (type == INTEGER) {
return ((Long) value).longValue(); return ((Long) value).longValue();
if (type == FLOAT) }
if (type == FLOAT) {
return ((Double) value).longValue(); return ((Double) value).longValue();
if (type == BOOLEAN) }
if (type == BOOLEAN) {
return ((Boolean) value).booleanValue() ? 1 : 0; return ((Boolean) value).booleanValue() ? 1 : 0;
}
try { try {
return Long.parseLong(getStringValue()); return Long.parseLong(getStringValue());
} catch (Exception x) { } catch (Exception x) {
@ -290,11 +464,20 @@ public final class Property implements IProperty, Serializable, Cloneable {
} }
} }
/**
*
*
* @return ...
*/
public double getFloatValue() { public double getFloatValue() {
if (type == FLOAT) if (type == FLOAT) {
return ((Double) value).doubleValue(); return ((Double) value).doubleValue();
if (type == INTEGER) }
if (type == INTEGER) {
return ((Long) value).doubleValue(); return ((Long) value).doubleValue();
}
try { try {
return Double.parseDouble(getStringValue()); return Double.parseDouble(getStringValue());
} catch (Exception x) { } catch (Exception x) {
@ -302,41 +485,74 @@ public final class Property implements IProperty, Serializable, Cloneable {
} }
} }
/**
*
*
* @return ...
*/
public Date getDateValue() { public Date getDateValue() {
if (type == DATE) if (type == DATE) {
return (Date) value; return (Date) value;
}
return null; return null;
} }
/**
*
*
* @return ...
*/
public Timestamp getTimestampValue() { public Timestamp getTimestampValue() {
if (type == DATE && value != null) if ((type == DATE) && (value != null)) {
return new Timestamp(((Date) value).getTime()); return new Timestamp(((Date) value).getTime());
}
return null; return null;
} }
/**
*
*
* @return ...
*/
public boolean getBooleanValue() { public boolean getBooleanValue() {
if (type == BOOLEAN) if (type == BOOLEAN) {
return ((Boolean) value).booleanValue(); return ((Boolean) value).booleanValue();
if (type == INTEGER) }
if (type == INTEGER) {
return !(0 == getIntegerValue()); return !(0 == getIntegerValue());
}
return false; return false;
} }
/**
*
*
* @return ...
*/
public INode getNodeValue() { public INode getNodeValue() {
if (type == NODE && value != null) { if ((type == NODE) && (value != null)) {
NodeHandle nhandle = (NodeHandle) value; NodeHandle nhandle = (NodeHandle) value;
return nhandle.getNode(node.nmgr); return nhandle.getNode(node.nmgr);
} }
return null; return null;
} }
/**
*
*
* @return ...
*/
public Object getJavaObjectValue() { public Object getJavaObjectValue() {
if (type == JAVAOBJECT) if (type == JAVAOBJECT) {
return value; return value;
}
return null; return null;
} }
} }

View file

@ -1,13 +1,26 @@
// Relation.java /*
// Copyright (c) Hannes Wallnöfer 1997-2000 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.objectmodel.db; package helma.objectmodel.db;
import helma.objectmodel.*;
import helma.framework.core.Application; import helma.framework.core.Application;
import helma.objectmodel.*;
import java.sql.SQLException;
import java.util.Properties; import java.util.Properties;
import java.util.Vector; import java.util.Vector;
import java.sql.SQLException;
/** /**
* This describes how a property of a persistent Object is stored in a * This describes how a property of a persistent Object is stored in a
@ -15,23 +28,25 @@ import java.sql.SQLException;
* or a reference to one or more other objects. * or a reference to one or more other objects.
*/ */
public final class Relation { public final class Relation {
// these constants define different type of property-to-db-mappings // these constants define different type of property-to-db-mappings
// there is an error in the description of this relation // there is an error in the description of this relation
public final static int INVALID = -1; public final static int INVALID = -1;
// a mapping of a non-object, scalar type // a mapping of a non-object, scalar type
public final static int PRIMITIVE = 0; public final static int PRIMITIVE = 0;
// a 1-to-1 relation, i.e. a field in the table is a foreign key to another object // a 1-to-1 relation, i.e. a field in the table is a foreign key to another object
public final static int REFERENCE = 1; public final static int REFERENCE = 1;
// a 1-to-many relation, a field in another table points to objects of this type // a 1-to-many relation, a field in another table points to objects of this type
public final static int COLLECTION = 2; public final static int COLLECTION = 2;
// direct mapping is a very powerful feature: objects of some types can be directly accessed // direct mapping is a very powerful feature: objects of some types can be directly accessed
// by one of their properties/db fields. // by one of their properties/db fields.
// public final static int DIRECT = 3; // public final static int DIRECT = 3;
// the DbMapping of the type we come from // the DbMapping of the type we come from
DbMapping ownType; DbMapping ownType;
// the DbMapping of the prototype we link to, unless this is a "primitive" (non-object) relation // the DbMapping of the prototype we link to, unless this is a "primitive" (non-object) relation
DbMapping otherType; DbMapping otherType;
@ -40,20 +55,15 @@ public final class Relation {
// if this relation defines a virtual node, we need to provide a DbMapping for these virtual nodes // if this relation defines a virtual node, we need to provide a DbMapping for these virtual nodes
DbMapping virtualMapping; DbMapping virtualMapping;
String propName; String propName;
String columnName; String columnName;
int reftype; int reftype;
Constraint[] constraints; Constraint[] constraints;
boolean virtual; boolean virtual;
boolean readonly; boolean readonly;
boolean aggressiveLoading; boolean aggressiveLoading;
boolean aggressiveCaching; boolean aggressiveCaching;
boolean isPrivate; boolean isPrivate;
String accessName; // db column used to access objects through this relation String accessName; // db column used to access objects through this relation
String order; String order;
String groupbyOrder; String groupbyOrder;
@ -63,7 +73,6 @@ public final class Relation {
String filter; String filter;
int maxSize = 0; int maxSize = 0;
/** /**
* This constructor makes a copy of an existing relation. Not all fields are copied, just those * This constructor makes a copy of an existing relation. Not all fields are copied, just those
* which are needed in groupby- and virtual nodes defined by this relation. * which are needed in groupby- and virtual nodes defined by this relation.
@ -88,14 +97,13 @@ public final class Relation {
otherType = null; otherType = null;
} }
//////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////
// parse methods for new file format // parse methods for new file format
//////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////
public void update(String desc, Properties props) { public void update(String desc, Properties props) {
Application app = ownType.getApplication(); Application app = ownType.getApplication();
if (desc == null || "".equals (desc.trim ())) {
if ((desc == null) || "".equals(desc.trim())) {
if (propName != null) { if (propName != null) {
reftype = PRIMITIVE; reftype = PRIMITIVE;
columnName = propName; columnName = propName;
@ -105,11 +113,14 @@ public final class Relation {
} }
} else { } else {
desc = desc.trim(); desc = desc.trim();
int open = desc.indexOf("("); int open = desc.indexOf("(");
int close = desc.indexOf(")"); int close = desc.indexOf(")");
if (open > -1 && close > open) {
if ((open > -1) && (close > open)) {
String ref = desc.substring(0, open).trim(); String ref = desc.substring(0, open).trim();
String proto = desc.substring(open + 1, close).trim(); String proto = desc.substring(open + 1, close).trim();
if ("collection".equalsIgnoreCase(ref)) { if ("collection".equalsIgnoreCase(ref)) {
virtual = !"_children".equalsIgnoreCase(propName); virtual = !"_children".equalsIgnoreCase(propName);
reftype = COLLECTION; reftype = COLLECTION;
@ -123,31 +134,39 @@ public final class Relation {
} else { } else {
throw new RuntimeException("Invalid property Mapping: " + desc); throw new RuntimeException("Invalid property Mapping: " + desc);
} }
otherType = app.getDbMapping(proto); otherType = app.getDbMapping(proto);
if (otherType == null)
throw new RuntimeException ("DbMapping for "+proto+" not found from "+ownType.typename); if (otherType == null) {
throw new RuntimeException("DbMapping for " + proto +
" not found from " + ownType.typename);
}
} else { } else {
virtual = false; virtual = false;
columnName = desc; columnName = desc;
reftype = PRIMITIVE; reftype = PRIMITIVE;
} }
} }
String rdonly = props.getProperty(propName + ".readonly"); String rdonly = props.getProperty(propName + ".readonly");
if (rdonly != null && "true".equalsIgnoreCase (rdonly)) {
if ((rdonly != null) && "true".equalsIgnoreCase(rdonly)) {
readonly = true; readonly = true;
} else { } else {
readonly = false; readonly = false;
} }
isPrivate = "true".equalsIgnoreCase(props.getProperty(propName + ".private")); isPrivate = "true".equalsIgnoreCase(props.getProperty(propName + ".private"));
// the following options only apply to object and collection relations // the following options only apply to object and collection relations
if (reftype != PRIMITIVE && reftype != INVALID) { if ((reftype != PRIMITIVE) && (reftype != INVALID)) {
Vector newConstraints = new Vector(); Vector newConstraints = new Vector();
parseOptions(newConstraints, props); parseOptions(newConstraints, props);
constraints = new Constraint[newConstraints.size()]; constraints = new Constraint[newConstraints.size()];
newConstraints.copyInto(constraints); newConstraints.copyInto(constraints);
// if DbMapping for virtual nodes has already been created, // if DbMapping for virtual nodes has already been created,
// update its subnode relation. // update its subnode relation.
// FIXME: needs to be synchronized? // FIXME: needs to be synchronized?
@ -159,55 +178,81 @@ public final class Relation {
} }
} }
protected void parseOptions(Vector cnst, Properties props) { protected void parseOptions(Vector cnst, Properties props) {
String loading = props.getProperty(propName + ".loadmode"); String loading = props.getProperty(propName + ".loadmode");
aggressiveLoading = loading != null && "aggressive".equalsIgnoreCase (loading.trim());
aggressiveLoading = (loading != null) &&
"aggressive".equalsIgnoreCase(loading.trim());
String caching = props.getProperty(propName + ".cachemode"); String caching = props.getProperty(propName + ".cachemode");
aggressiveCaching = caching != null && "aggressive".equalsIgnoreCase (caching.trim());
aggressiveCaching = (caching != null) &&
"aggressive".equalsIgnoreCase(caching.trim());
// get order property // get order property
order = props.getProperty(propName + ".order"); order = props.getProperty(propName + ".order");
if (order != null && order.trim().length() == 0)
if ((order != null) && (order.trim().length() == 0)) {
order = null; order = null;
}
// get additional filter property // get additional filter property
filter = props.getProperty(propName + ".filter"); filter = props.getProperty(propName + ".filter");
if (filter != null && filter.trim().length() == 0)
if ((filter != null) && (filter.trim().length() == 0)) {
filter = null; filter = null;
}
// get max size of collection // get max size of collection
String max = props.getProperty(propName + ".maxSize"); String max = props.getProperty(propName + ".maxSize");
if (max != null) try {
if (max != null) {
try {
maxSize = Integer.parseInt(max); maxSize = Integer.parseInt(max);
} catch (NumberFormatException nfe) { } catch (NumberFormatException nfe) {
maxSize = 0; maxSize = 0;
}
} else { } else {
maxSize = 0; maxSize = 0;
} }
// get group by property // get group by property
groupby = props.getProperty(propName + ".group"); groupby = props.getProperty(propName + ".group");
if (groupby != null && groupby.trim().length() == 0)
if ((groupby != null) && (groupby.trim().length() == 0)) {
groupby = null; groupby = null;
}
if (groupby != null) { if (groupby != null) {
groupbyOrder = props.getProperty(propName + ".group.order"); groupbyOrder = props.getProperty(propName + ".group.order");
if (groupbyOrder != null && groupbyOrder.trim().length() == 0)
if ((groupbyOrder != null) && (groupbyOrder.trim().length() == 0)) {
groupbyOrder = null; groupbyOrder = null;
}
groupbyPrototype = props.getProperty(propName + ".group.prototype"); groupbyPrototype = props.getProperty(propName + ".group.prototype");
if (groupbyPrototype != null && groupbyPrototype.trim().length() == 0)
if ((groupbyPrototype != null) && (groupbyPrototype.trim().length() == 0)) {
groupbyPrototype = null; groupbyPrototype = null;
}
// aggressive loading and caching is not supported for groupby-nodes // aggressive loading and caching is not supported for groupby-nodes
aggressiveLoading = aggressiveCaching = false; aggressiveLoading = aggressiveCaching = false;
} }
// check if subnode condition should be applied for property relations // check if subnode condition should be applied for property relations
accessName = props.getProperty(propName + ".accessname"); accessName = props.getProperty(propName + ".accessname");
// parse contstraints // parse contstraints
String local = props.getProperty(propName + ".local"); String local = props.getProperty(propName + ".local");
String foreign = props.getProperty(propName + ".foreign"); String foreign = props.getProperty(propName + ".foreign");
if (local != null && foreign != null) {
if ((local != null) && (foreign != null)) {
cnst.addElement(new Constraint(local, otherType.getTableName(), foreign, false)); cnst.addElement(new Constraint(local, otherType.getTableName(), foreign, false));
columnName = local; columnName = local;
} }
} }
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
/** /**
@ -253,7 +298,7 @@ public final class Relation {
* and never stored to a persistent storage. * and never stored to a persistent storage.
*/ */
public boolean createPropertyOnDemand() { public boolean createPropertyOnDemand() {
return virtual || accessName != null || groupby != null; return virtual || (accessName != null) || (groupby != null);
} }
/** /**
@ -265,12 +310,17 @@ public final class Relation {
* its content after restarts. * its content after restarts.
*/ */
public boolean needsPersistence() { public boolean needsPersistence() {
if (!virtual) if (!virtual) {
return false; return false;
if (prototype == null) }
if (prototype == null) {
return !otherType.isRelational(); return !otherType.isRelational();
}
DbMapping sub = otherType.getSubnodeMapping(); DbMapping sub = otherType.getSubnodeMapping();
return sub != null && !sub.isRelational ();
return (sub != null) && !sub.isRelational();
} }
/** /**
@ -287,15 +337,24 @@ public final class Relation {
return propName; return propName;
} }
/**
*
*
* @param ct ...
*/
public void setColumnType(int ct) { public void setColumnType(int ct) {
columnType = ct; columnType = ct;
} }
/**
*
*
* @return ...
*/
public int getColumnType() { public int getColumnType() {
return columnType; return columnType;
} }
/** /**
* Add a constraint to the current list of constraints * Add a constraint to the current list of constraints
*/ */
@ -305,37 +364,61 @@ public final class Relation {
constraints[0] = c; constraints[0] = c;
} else { } else {
Constraint[] nc = new Constraint[constraints.length + 1]; Constraint[] nc = new Constraint[constraints.length + 1];
System.arraycopy(constraints, 0, nc, 0, constraints.length); System.arraycopy(constraints, 0, nc, 0, constraints.length);
nc[nc.length - 1] = c; nc[nc.length - 1] = c;
constraints = nc; constraints = nc;
} }
} }
/**
*
*
* @return ...
*/
public boolean usesPrimaryKey() { public boolean usesPrimaryKey() {
if (otherType != null) { if (otherType != null) {
if (reftype == REFERENCE) if (reftype == REFERENCE) {
return constraints.length == 1 && constraints[0].foreignKeyIsPrimary (); return (constraints.length == 1) && constraints[0].foreignKeyIsPrimary();
if (reftype == COLLECTION)
return accessName == null || accessName.equalsIgnoreCase (otherType.getIDField ());
} }
if (reftype == COLLECTION) {
return (accessName == null) ||
accessName.equalsIgnoreCase(otherType.getIDField());
}
}
return false; return false;
} }
/**
*
*
* @return ...
*/
public boolean hasAccessName() { public boolean hasAccessName() {
return accessName != null; return accessName != null;
} }
/**
*
*
* @return ...
*/
public String getAccessName() { public String getAccessName() {
return accessName; return accessName;
} }
/**
*
*
* @return ...
*/
public Relation getSubnodeRelation() { public Relation getSubnodeRelation() {
// return subnoderelation; // return subnoderelation;
return null; return null;
} }
/** /**
* Return the local field name for updates. * Return the local field name for updates.
*/ */
@ -343,19 +426,21 @@ public final class Relation {
return columnName; return columnName;
} }
/** /**
* get a DbMapping to use for virtual aka collection nodes. * get a DbMapping to use for virtual aka collection nodes.
*/ */
public DbMapping getVirtualMapping() { public DbMapping getVirtualMapping() {
// return null unless this relation describes a virtual/collection node. // return null unless this relation describes a virtual/collection node.
if (!virtual) if (!virtual) {
return null; return null;
}
// if the collection node is prototyped, return the app's DbMapping // if the collection node is prototyped, return the app's DbMapping
// for that prototype // for that prototype
if (prototype != null) { if (prototype != null) {
return otherType; return otherType;
} }
// create a synthetic DbMapping that describes how to fetch the // create a synthetic DbMapping that describes how to fetch the
// collection's child objects. // collection's child objects.
if (virtualMapping == null) { if (virtualMapping == null) {
@ -363,17 +448,20 @@ public final class Relation {
virtualMapping.subRelation = getVirtualSubnodeRelation(); virtualMapping.subRelation = getVirtualSubnodeRelation();
virtualMapping.propRelation = getVirtualPropertyRelation(); virtualMapping.propRelation = getVirtualPropertyRelation();
} }
return virtualMapping; return virtualMapping;
} }
/** /**
* Return a Relation that defines the subnodes of a virtual node. * Return a Relation that defines the subnodes of a virtual node.
*/ */
Relation getVirtualSubnodeRelation() { Relation getVirtualSubnodeRelation() {
if (!virtual) if (!virtual) {
throw new RuntimeException("getVirtualSubnodeRelation called on non-virtual relation"); throw new RuntimeException("getVirtualSubnodeRelation called on non-virtual relation");
}
Relation vr = new Relation(this); Relation vr = new Relation(this);
vr.groupby = groupby; vr.groupby = groupby;
vr.groupbyOrder = groupbyOrder; vr.groupbyOrder = groupbyOrder;
vr.groupbyPrototype = groupbyPrototype; vr.groupbyPrototype = groupbyPrototype;
@ -383,6 +471,7 @@ public final class Relation {
vr.constraints = constraints; vr.constraints = constraints;
vr.aggressiveLoading = aggressiveLoading; vr.aggressiveLoading = aggressiveLoading;
vr.aggressiveCaching = aggressiveCaching; vr.aggressiveCaching = aggressiveCaching;
return vr; return vr;
} }
@ -390,9 +479,12 @@ public final class Relation {
* Return a Relation that defines the properties of a virtual node. * Return a Relation that defines the properties of a virtual node.
*/ */
Relation getVirtualPropertyRelation() { Relation getVirtualPropertyRelation() {
if (!virtual) if (!virtual) {
throw new RuntimeException("getVirtualPropertyRelation called on non-virtual relation"); throw new RuntimeException("getVirtualPropertyRelation called on non-virtual relation");
}
Relation vr = new Relation(this); Relation vr = new Relation(this);
vr.groupby = groupby; vr.groupby = groupby;
vr.groupbyOrder = groupbyOrder; vr.groupbyOrder = groupbyOrder;
vr.groupbyPrototype = groupbyPrototype; vr.groupbyPrototype = groupbyPrototype;
@ -400,6 +492,7 @@ public final class Relation {
vr.filter = filter; vr.filter = filter;
vr.maxSize = maxSize; vr.maxSize = maxSize;
vr.constraints = constraints; vr.constraints = constraints;
return vr; return vr;
} }
@ -407,9 +500,12 @@ public final class Relation {
* Return a Relation that defines the subnodes of a group-by node. * Return a Relation that defines the subnodes of a group-by node.
*/ */
Relation getGroupbySubnodeRelation() { Relation getGroupbySubnodeRelation() {
if (groupby == null) if (groupby == null) {
throw new RuntimeException("getGroupbySubnodeRelation called on non-group-by relation"); throw new RuntimeException("getGroupbySubnodeRelation called on non-group-by relation");
}
Relation vr = new Relation(this); Relation vr = new Relation(this);
vr.order = order; vr.order = order;
vr.prototype = groupbyPrototype; vr.prototype = groupbyPrototype;
vr.filter = filter; vr.filter = filter;
@ -417,6 +513,7 @@ public final class Relation {
vr.addConstraint(new Constraint(null, null, groupby, true)); vr.addConstraint(new Constraint(null, null, groupby, true));
vr.aggressiveLoading = aggressiveLoading; vr.aggressiveLoading = aggressiveLoading;
vr.aggressiveCaching = aggressiveCaching; vr.aggressiveCaching = aggressiveCaching;
return vr; return vr;
} }
@ -424,39 +521,50 @@ public final class Relation {
* Return a Relation that defines the properties of a group-by node. * Return a Relation that defines the properties of a group-by node.
*/ */
Relation getGroupbyPropertyRelation() { Relation getGroupbyPropertyRelation() {
if (groupby == null) if (groupby == null) {
throw new RuntimeException("getGroupbyPropertyRelation called on non-group-by relation"); throw new RuntimeException("getGroupbyPropertyRelation called on non-group-by relation");
}
Relation vr = new Relation(this); Relation vr = new Relation(this);
vr.order = order; vr.order = order;
vr.prototype = groupbyPrototype; vr.prototype = groupbyPrototype;
vr.filter = filter; vr.filter = filter;
vr.constraints = constraints; vr.constraints = constraints;
vr.addConstraint(new Constraint(null, null, groupby, true)); vr.addConstraint(new Constraint(null, null, groupby, true));
return vr; return vr;
} }
/** /**
* Build the second half of an SQL select statement according to this relation * Build the second half of an SQL select statement according to this relation
* and a local object. * and a local object.
*/ */
public String buildQuery (INode home, INode nonvirtual, String kstr, String pre, boolean useOrder) throws SQLException { public String buildQuery(INode home, INode nonvirtual, String kstr, String pre,
boolean useOrder) throws SQLException {
StringBuffer q = new StringBuffer(); StringBuffer q = new StringBuffer();
String prefix = pre; String prefix = pre;
if (kstr != null) { if (kstr != null) {
q.append(prefix); q.append(prefix);
String accessColumn = accessName == null ? otherType.getIDField () : accessName;
String accessColumn = (accessName == null) ? otherType.getIDField() : accessName;
q.append(accessColumn); q.append(accessColumn);
q.append(" = "); q.append(" = ");
// check if column is string type and value needs to be quoted // check if column is string type and value needs to be quoted
if (otherType.needsQuotes(accessColumn)) { if (otherType.needsQuotes(accessColumn)) {
q.append("'"); q.append("'");
q.append(escape(kstr)); q.append(escape(kstr));
q.append("'"); q.append("'");
} else } else {
q.append(escape(kstr)); q.append(escape(kstr));
}
prefix = " AND "; prefix = " AND ";
} }
for (int i = 0; i < constraints.length; i++) { for (int i = 0; i < constraints.length; i++) {
q.append(prefix); q.append(prefix);
constraints[i].addToQuery(q, home, nonvirtual); constraints[i].addToQuery(q, home, nonvirtual);
@ -467,39 +575,58 @@ public final class Relation {
q.append(prefix); q.append(prefix);
q.append(filter); q.append(filter);
} }
if (groupby != null) { if (groupby != null) {
q.append(" GROUP BY " + groupby); q.append(" GROUP BY " + groupby);
if (useOrder && groupbyOrder != null)
if (useOrder && (groupbyOrder != null)) {
q.append(" ORDER BY " + groupbyOrder); q.append(" ORDER BY " + groupbyOrder);
} else if (useOrder && order != null) }
} else if (useOrder && (order != null)) {
q.append(" ORDER BY " + order); q.append(" ORDER BY " + order);
}
return q.toString(); return q.toString();
} }
public String renderConstraints (INode home, INode nonvirtual) throws SQLException { /**
*
*
* @param home ...
* @param nonvirtual ...
*
* @return ...
*
* @throws SQLException ...
*/
public String renderConstraints(INode home, INode nonvirtual)
throws SQLException {
StringBuffer q = new StringBuffer(); StringBuffer q = new StringBuffer();
String suffix = " AND "; String suffix = " AND ";
for (int i = 0; i < constraints.length; i++) { for (int i = 0; i < constraints.length; i++) {
constraints[i].addToQuery(q, home, nonvirtual); constraints[i].addToQuery(q, home, nonvirtual);
q.append(suffix); q.append(suffix);
} }
if (filter != null) { if (filter != null) {
q.append(filter); q.append(filter);
q.append(suffix); q.append(suffix);
} }
return q.toString(); return q.toString();
} }
/** /**
* Get the order section to use for this relation * Get the order section to use for this relation
*/ */
public String getOrder() { public String getOrder() {
if (groupby != null) if (groupby != null) {
return groupbyOrder; return groupbyOrder;
else } else {
return order; return order;
} }
}
/** /**
* Tell wether the property described by this relation is to be handled * Tell wether the property described by this relation is to be handled
@ -509,7 +636,6 @@ public final class Relation {
return readonly; return readonly;
} }
/** /**
* Check if the child node fullfills the constraints defined by this relation. * Check if the child node fullfills the constraints defined by this relation.
*/ */
@ -520,28 +646,36 @@ public final class Relation {
// is defined, we return false as soon as the modified-time is greater // is defined, we return false as soon as the modified-time is greater
// than the create-time of the child, i.e. if the child node has been // than the create-time of the child, i.e. if the child node has been
// modified since it was first fetched from the db. // modified since it was first fetched from the db.
if (filter != null && child.lastModified() > child.created()) if ((filter != null) && (child.lastModified() > child.created())) {
return false; return false;
for (int i=0; i<constraints.length; i++) {
String propname = constraints[i].foreignProperty ();
if (propname != null) {
INode home = constraints[i].isGroupby ? parent : parent.getNonVirtualParent ();
String localName = constraints[i].localName;
String value = null;
if (localName == null || localName.equalsIgnoreCase (ownType.getIDField ()))
value = home.getID ();
else if (ownType.isRelational ())
value = home.getString (ownType.columnNameToProperty (localName));
else
value = home.getString (localName);
if (value != null && !value.equals (child.getString (propname))) {
return false;
}
}
}
return true;
} }
for (int i = 0; i < constraints.length; i++) {
String propname = constraints[i].foreignProperty();
if (propname != null) {
INode home = constraints[i].isGroupby ? parent
: parent.getNonVirtualParent();
String localName = constraints[i].localName;
String value = null;
if ((localName == null) ||
localName.equalsIgnoreCase(ownType.getIDField())) {
value = home.getID();
} else if (ownType.isRelational()) {
value = home.getString(ownType.columnNameToProperty(localName));
} else {
value = home.getString(localName);
}
if ((value != null) && !value.equals(child.getString(propname))) {
return false;
}
}
}
return true;
}
/** /**
* Make sure that the child node fullfills the constraints defined by this relation by setting the * Make sure that the child node fullfills the constraints defined by this relation by setting the
@ -549,37 +683,48 @@ public final class Relation {
*/ */
public void setConstraints(Node parent, Node child) { public void setConstraints(Node parent, Node child) {
INode home = parent.getNonVirtualParent(); INode home = parent.getNonVirtualParent();
for (int i = 0; i < constraints.length; i++) { for (int i = 0; i < constraints.length; i++) {
// don't set groupby constraints since we don't know if the // don't set groupby constraints since we don't know if the
// parent node is the base node or a group node // parent node is the base node or a group node
if (constraints[i].isGroupby) if (constraints[i].isGroupby) {
continue; continue;
}
Relation crel = otherType.columnNameToRelation(constraints[i].foreignName); Relation crel = otherType.columnNameToRelation(constraints[i].foreignName);
if (crel != null) { if (crel != null) {
// INode home = constraints[i].isGroupby ? parent : nonVirtual; // INode home = constraints[i].isGroupby ? parent : nonVirtual;
String localName = constraints[i].localName; String localName = constraints[i].localName;
if (localName == null || localName.equalsIgnoreCase (ownType.getIDField ())) {
if ((localName == null) ||
localName.equalsIgnoreCase(ownType.getIDField())) {
// only set node if property in child object is defined as reference. // only set node if property in child object is defined as reference.
if (crel.reftype == REFERENCE) { if (crel.reftype == REFERENCE) {
INode currentValue = child.getNode(crel.propName); INode currentValue = child.getNode(crel.propName);
// we set the backwards reference iff the reference is currently unset, if // we set the backwards reference iff the reference is currently unset, if
// is set to a transient object, or if the new target is not transient. This // is set to a transient object, or if the new target is not transient. This
// prevents us from overwriting a persistent refererence with a transient one, // prevents us from overwriting a persistent refererence with a transient one,
// which would most probably not be what we want. // which would most probably not be what we want.
if (currentValue == null || if ((currentValue == null) ||
(currentValue != home && ((currentValue != home) &&
(currentValue.getState() == Node.TRANSIENT || ((currentValue.getState() == Node.TRANSIENT) ||
home.getState() != Node.TRANSIENT))) (home.getState() != Node.TRANSIENT)))) {
child.setNode(crel.propName, home); child.setNode(crel.propName, home);
}
} else if (crel.reftype == PRIMITIVE) { } else if (crel.reftype == PRIMITIVE) {
child.setString(crel.propName, home.getID()); child.setString(crel.propName, home.getID());
} }
} else if (crel.reftype == PRIMITIVE) { } else if (crel.reftype == PRIMITIVE) {
String value = null; String value = null;
if (ownType.isRelational ())
if (ownType.isRelational()) {
value = home.getString(ownType.columnNameToProperty(localName)); value = home.getString(ownType.columnNameToProperty(localName));
else } else {
value = home.getString(localName); value = home.getString(localName);
}
if (value != null) { if (value != null) {
child.setString(crel.propName, value); child.setString(crel.propName, value);
} }
@ -588,30 +733,45 @@ public final class Relation {
} }
} }
// a utility method to escape single quotes // a utility method to escape single quotes
String escape(String str) { String escape(String str) {
if (str == null) if (str == null) {
return null; return null;
if (str.indexOf ("'") < 0) }
if (str.indexOf("'") < 0) {
return str; return str;
}
int l = str.length(); int l = str.length();
StringBuffer sbuf = new StringBuffer(l + 10); StringBuffer sbuf = new StringBuffer(l + 10);
for (int i = 0; i < l; i++) { for (int i = 0; i < l; i++) {
char c = str.charAt(i); char c = str.charAt(i);
if (c == '\'')
if (c == '\'') {
sbuf.append('\''); sbuf.append('\'');
}
sbuf.append(c); sbuf.append(c);
} }
return sbuf.toString(); return sbuf.toString();
} }
/**
*
*
* @return ...
*/
public String toString() { public String toString() {
String c = ""; String c = "";
if (constraints != null) { if (constraints != null) {
for (int i = 0; i < constraints.length; i++) for (int i = 0; i < constraints.length; i++)
c += constraints[i].toString(); c += constraints[i].toString();
} }
return "Relation[" + ownType + "." + propName + ">" + otherType + "]" + c; return "Relation[" + ownType + "." + propName + ">" + otherType + "]" + c;
} }
@ -620,7 +780,6 @@ public final class Relation {
* establish a relation between database mapped objects. * establish a relation between database mapped objects.
*/ */
class Constraint { class Constraint {
String localName; String localName;
String tableName; String tableName;
String foreignName; String foreignName;
@ -633,27 +792,35 @@ public final class Relation {
isGroupby = groupby; isGroupby = groupby;
} }
public void addToQuery (StringBuffer q, INode home, INode nonvirtual) throws SQLException { public void addToQuery(StringBuffer q, INode home, INode nonvirtual)
throws SQLException {
String local = null; String local = null;
INode ref = isGroupby ? home : nonvirtual; INode ref = isGroupby ? home : nonvirtual;
if (localName == null || localName.equalsIgnoreCase (ref.getDbMapping ().getIDField ()))
if ((localName == null) ||
localName.equalsIgnoreCase(ref.getDbMapping().getIDField())) {
local = ref.getID(); local = ref.getID();
else { } else {
String homeprop = ownType.columnNameToProperty(localName); String homeprop = ownType.columnNameToProperty(localName);
local = ref.getString(homeprop); local = ref.getString(homeprop);
} }
q.append(foreignName); q.append(foreignName);
q.append(" = "); q.append(" = ");
if (otherType.needsQuotes(foreignName)) { if (otherType.needsQuotes(foreignName)) {
q.append("'"); q.append("'");
q.append(escape(local)); q.append(escape(local));
q.append("'"); q.append("'");
} else } else {
q.append(escape(local)); q.append(escape(local));
} }
}
public boolean foreignKeyIsPrimary() { public boolean foreignKeyIsPrimary() {
return foreignName == null || foreignName.equalsIgnoreCase (otherType.getIDField ()); return (foreignName == null) ||
foreignName.equalsIgnoreCase(otherType.getIDField());
} }
public String foreignProperty() { public String foreignProperty() {
@ -668,7 +835,4 @@ public final class Relation {
return ownType + "." + localName + "=" + tableName + "." + foreignName; return ownType + "." + localName + "=" + tableName + "." + foreignName;
} }
} }
} }

View file

@ -1,5 +1,18 @@
// Replicator.java /*
// Copyright (c) Hannes Wallnöfer 2001 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.objectmodel.db; package helma.objectmodel.db;
@ -9,14 +22,20 @@ import java.util.*;
/** /**
* This class replicates the updates of transactions to other applications via RMI * This class replicates the updates of transactions to other applications via RMI
*/ */
public class Replicator implements Runnable { public class Replicator implements Runnable {
Vector urls; Vector urls;
Vector add, delete, currentAdd, currentDelete; Vector add;
Vector delete;
Vector currentAdd;
Vector currentDelete;
Thread runner; Thread runner;
NodeManager nmgr; NodeManager nmgr;
/**
* Creates a new Replicator object.
*
* @param nmgr ...
*/
public Replicator(NodeManager nmgr) { public Replicator(NodeManager nmgr) {
urls = new Vector(); urls = new Vector();
add = new Vector(); add = new Vector();
@ -26,12 +45,22 @@ public class Replicator implements Runnable {
runner.start(); runner.start();
} }
/**
*
*
* @param url ...
*/
public void addUrl(String url) { public void addUrl(String url) {
urls.addElement(url); urls.addElement(url);
if (nmgr.logReplication)
if (nmgr.logReplication) {
nmgr.app.logEvent("Adding replication listener: " + url); nmgr.app.logEvent("Adding replication listener: " + url);
} }
}
/**
*
*/
public void run() { public void run() {
while (Thread.currentThread() == runner) { while (Thread.currentThread() == runner) {
if (prepareReplication()) { if (prepareReplication()) {
@ -39,9 +68,14 @@ public class Replicator implements Runnable {
try { try {
String url = (String) urls.elementAt(i); String url = (String) urls.elementAt(i);
IReplicationListener listener = (IReplicationListener) Naming.lookup(url); IReplicationListener listener = (IReplicationListener) Naming.lookup(url);
listener.replicateCache(currentAdd, currentDelete); listener.replicateCache(currentAdd, currentDelete);
if (nmgr.logReplication)
nmgr.app.logEvent ("Sent cache replication event: "+add.size()+" added, "+delete.size()+" deleted"); if (nmgr.logReplication) {
nmgr.app.logEvent("Sent cache replication event: " +
add.size() + " added, " + delete.size() +
" deleted");
}
} catch (Exception x) { } catch (Exception x) {
nmgr.app.logEvent("Error sending cache replication event: " + x); nmgr.app.logEvent("Error sending cache replication event: " + x);
} }
@ -49,36 +83,52 @@ public class Replicator implements Runnable {
} }
try { try {
if (runner != null) if (runner != null) {
runner.sleep (1000l); runner.sleep(1000L);
}
} catch (InterruptedException ir) { } catch (InterruptedException ir) {
runner = null; runner = null;
} }
} }
} }
/**
*
*
* @param n ...
*/
public synchronized void addNewNode(Node n) { public synchronized void addNewNode(Node n) {
add.addElement(n); add.addElement(n);
} }
/**
*
*
* @param n ...
*/
public synchronized void addModifiedNode(Node n) { public synchronized void addModifiedNode(Node n) {
add.addElement(n); add.addElement(n);
} }
/**
*
*
* @param n ...
*/
public synchronized void addDeletedNode(Node n) { public synchronized void addDeletedNode(Node n) {
delete.addElement(n); delete.addElement(n);
} }
private synchronized boolean prepareReplication() { private synchronized boolean prepareReplication() {
if (add.size() == 0 && delete.size() == 0) if ((add.size() == 0) && (delete.size() == 0)) {
return false; return false;
}
currentAdd = add; currentAdd = add;
currentDelete = delete; currentDelete = delete;
add = new Vector(); add = new Vector();
delete = new Vector(); delete = new Vector();
return true; return true;
} }
} }

View file

@ -1,5 +1,18 @@
// Server.java /*
// Copyright (c) Hannes Wallnöfer 1998-2000 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.objectmodel.db; package helma.objectmodel.db;
@ -9,16 +22,12 @@ import java.io.IOException;
* Helma server main class. This moved to the helma.main package but a * Helma server main class. This moved to the helma.main package but a
* simple redirector is kept here for backwards compatibility. * simple redirector is kept here for backwards compatibility.
*/ */
public class Server { public class Server {
/** /**
* Just invoke the main method in the new Server class. * Just invoke the main method in the new Server class.
*/ */
public static void main (String args[]) throws IOException { public static void main(String[] args) throws IOException {
System.err.println("The Helma main class is now in helma.main.Server. Please update your start script accordingly."); System.err.println("The Helma main class is now in helma.main.Server. Please update your start script accordingly.");
helma.main.Server.main(args); helma.main.Server.main(args);
} }
} }

View file

@ -1,5 +1,18 @@
// SyntheticKey.java /*
// Copyright (c) Hannes Wallnöfer 1998-2000 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.objectmodel.db; package helma.objectmodel.db;
@ -12,14 +25,12 @@ import java.io.Serializable;
* virtual nodes and groupby nodes. * virtual nodes and groupby nodes.
*/ */
public final class SyntheticKey implements Key, Serializable { public final class SyntheticKey implements Key, Serializable {
private final Key parentKey; private final Key parentKey;
private final String name; private final String name;
// lazily initialized hashcode // lazily initialized hashcode
private transient int hashcode = 0; private transient int hashcode = 0;
/** /**
* make a key for a persistent Object, describing its datasource and id. * make a key for a persistent Object, describing its datasource and id.
*/ */
@ -28,40 +39,74 @@ public final class SyntheticKey implements Key, Serializable {
this.name = name; this.name = name;
} }
/**
*
*
* @param what ...
*
* @return ...
*/
public boolean equals(Object what) { public boolean equals(Object what) {
if (what == this) if (what == this) {
return true; return true;
if (!(what instanceof SyntheticKey))
return false;
SyntheticKey k = (SyntheticKey) what;
return parentKey.equals (k.parentKey) &&
(name == k.name || name.equals (k.name));
} }
if (!(what instanceof SyntheticKey)) {
return false;
}
SyntheticKey k = (SyntheticKey) what;
return parentKey.equals(k.parentKey) &&
((name == k.name) || name.equals(k.name));
}
/**
*
*
* @return ...
*/
public int hashCode() { public int hashCode() {
if (hashcode == 0) if (hashcode == 0) {
hashcode = 17 + 37*name.hashCode () + 37*parentKey.hashCode (); hashcode = 17 + (37 * name.hashCode()) + (37 * parentKey.hashCode());
}
return hashcode; return hashcode;
} }
/**
*
*
* @return ...
*/
public Key getParentKey() { public Key getParentKey() {
return parentKey; return parentKey;
} }
/**
*
*
* @return ...
*/
public String getID() { public String getID() {
return name; return name;
} }
/**
*
*
* @return ...
*/
public String getStorageName() { public String getStorageName() {
return null; return null;
} }
/**
*
*
* @return ...
*/
public String toString() { public String toString() {
return parentKey + "/" + name; return parentKey + "/" + name;
} }
} }

View file

@ -1,45 +1,66 @@
// Transactor.java /*
// Copyright (c) Hannes Wallnöfer 1998-2000 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.objectmodel.db; package helma.objectmodel.db;
import java.io.*; import helma.framework.TimeoutException;
import java.util.*;
import java.sql.*;
import helma.objectmodel.*; import helma.objectmodel.*;
import helma.util.Timer; import helma.util.Timer;
import helma.framework.TimeoutException; import java.io.*;
import java.sql.*;
import java.util.*;
/** /**
* A subclass of thread that keeps track of changed nodes and triggers * A subclass of thread that keeps track of changed nodes and triggers
* changes in the database when a transaction is commited. * changes in the database when a transaction is commited.
*/ */
public class Transactor extends Thread { public class Transactor extends Thread {
NodeManager nmgr; NodeManager nmgr;
// List of nodes to be updated // List of nodes to be updated
private HashMap nodes; private HashMap nodes;
private ArrayList nodesArray; private ArrayList nodesArray;
// List of visited clean nodes // List of visited clean nodes
private HashMap cleannodes; private HashMap cleannodes;
// Is a transaction in progress? // Is a transaction in progress?
private volatile boolean active; private volatile boolean active;
private volatile boolean killed; private volatile boolean killed;
// Transaction for the embedded database // Transaction for the embedded database
protected ITransaction txn; protected ITransaction txn;
// Transactions for SQL data sources // Transactions for SQL data sources
protected HashMap sqlCon; protected HashMap sqlCon;
public Timer timer; public Timer timer;
// when did the current transaction start? // when did the current transaction start?
private long tstart; private long tstart;
// a name to log the transaction. For HTTP transactions this is the rerquest path // a name to log the transaction. For HTTP transactions this is the rerquest path
private String tname; private String tname;
/**
* Creates a new Transactor object.
*
* @param runnable ...
* @param group ...
* @param nmgr ...
*/
public Transactor(Runnable runnable, ThreadGroup group, NodeManager nmgr) { public Transactor(Runnable runnable, ThreadGroup group, NodeManager nmgr) {
super(group, runnable, group.getName()); super(group, runnable, group.getName());
this.nmgr = nmgr; this.nmgr = nmgr;
@ -52,9 +73,15 @@ public class Transactor extends Thread {
timer = new Timer(); timer = new Timer();
} }
/**
*
*
* @param node ...
*/
public void visitNode(Node node) { public void visitNode(Node node) {
if (node != null) { if (node != null) {
Key key = node.getKey(); Key key = node.getKey();
if (!nodes.containsKey(key)) { if (!nodes.containsKey(key)) {
nodes.put(key, node); nodes.put(key, node);
nodesArray.add(node); nodesArray.add(node);
@ -62,23 +89,41 @@ public class Transactor extends Thread {
} }
} }
/**
*
*
* @param node ...
*/
public void dropNode(Node node) { public void dropNode(Node node) {
if (node != null) { if (node != null) {
Key key = node.getKey(); Key key = node.getKey();
nodes.remove(key); nodes.remove(key);
nodesArray.remove(node); nodesArray.remove(node);
} }
} }
/**
*
*
* @param node ...
*/
public void visitCleanNode(Node node) { public void visitCleanNode(Node node) {
if (node != null) { if (node != null) {
Key key = node.getKey(); Key key = node.getKey();
if (!cleannodes.containsKey(key)) { if (!cleannodes.containsKey(key)) {
cleannodes.put(key, node); cleannodes.put(key, node);
} }
} }
} }
/**
*
*
* @param key ...
* @param node ...
*/
public void visitCleanNode(Key key, Node node) { public void visitCleanNode(Key key, Node node) {
if (node != null) { if (node != null) {
if (!cleannodes.containsKey(key)) { if (!cleannodes.containsKey(key)) {
@ -87,30 +132,63 @@ public class Transactor extends Thread {
} }
} }
/**
*
*
* @param key ...
*
* @return ...
*/
public Node getVisitedNode(Object key) { public Node getVisitedNode(Object key) {
return key == null ? null : (Node) cleannodes.get (key); return (key == null) ? null : (Node) cleannodes.get(key);
} }
/**
*
*
* @return ...
*/
public boolean isActive() { public boolean isActive() {
return active; return active;
} }
/**
*
*
* @param src ...
* @param con ...
*/
public void registerConnection(DbSource src, Connection con) { public void registerConnection(DbSource src, Connection con) {
sqlCon.put(src, con); sqlCon.put(src, con);
} }
/**
*
*
* @param src ...
*
* @return ...
*/
public Connection getConnection(DbSource src) { public Connection getConnection(DbSource src) {
return (Connection) sqlCon.get(src); return (Connection) sqlCon.get(src);
} }
/**
*
*
* @param tnm ...
*
* @throws Exception ...
* @throws DatabaseException ...
*/
public synchronized void begin(String tnm) throws Exception { public synchronized void begin(String tnm) throws Exception {
if (killed) {
if (killed)
throw new DatabaseException("Transaction started on killed thread"); throw new DatabaseException("Transaction started on killed thread");
}
if (active) if (active) {
abort(); abort();
}
nodes.clear(); nodes.clear();
nodesArray.clear(); nodesArray.clear();
@ -121,47 +199,68 @@ public class Transactor extends Thread {
tname = tnm; tname = tnm;
} }
/**
*
*
* @throws Exception ...
*/
public synchronized void commit() throws Exception { public synchronized void commit() throws Exception {
if (killed) { if (killed) {
abort(); abort();
return; return;
} }
int ins = 0, upd = 0, dlt = 0; int ins = 0;
int upd = 0;
int dlt = 0;
int l = nodesArray.size(); int l = nodesArray.size();
Replicator replicator = nmgr.getReplicator(); Replicator replicator = nmgr.getReplicator();
for (int i = 0; i < l; i++) { for (int i = 0; i < l; i++) {
Node node = (Node) nodesArray.get(i); Node node = (Node) nodesArray.get(i);
// update nodes in db // update nodes in db
int nstate = node.getState(); int nstate = node.getState();
if (nstate == Node.NEW) { if (nstate == Node.NEW) {
nmgr.registerNode(node); // register node with nodemanager cache nmgr.registerNode(node); // register node with nodemanager cache
nmgr.insertNode(nmgr.db, txn, node); nmgr.insertNode(nmgr.db, txn, node);
node.setState(Node.CLEAN); node.setState(Node.CLEAN);
if (replicator != null)
if (replicator != null) {
replicator.addNewNode(node); replicator.addNewNode(node);
}
ins++; ins++;
nmgr.app.logEvent ("inserted: Node "+node.getPrototype ()+"/"+node.getID ()); nmgr.app.logEvent("inserted: Node " + node.getPrototype() + "/" +
node.getID());
} else if (nstate == Node.MODIFIED) { } else if (nstate == Node.MODIFIED) {
nmgr.updateNode(nmgr.db, txn, node); nmgr.updateNode(nmgr.db, txn, node);
node.setState(Node.CLEAN); node.setState(Node.CLEAN);
if (replicator != null)
if (replicator != null) {
replicator.addModifiedNode(node); replicator.addModifiedNode(node);
}
upd++; upd++;
nmgr.app.logEvent ("updated: Node "+node.getPrototype ()+"/"+node.getID ()); nmgr.app.logEvent("updated: Node " + node.getPrototype() + "/" +
node.getID());
} else if (nstate == Node.DELETED) { } else if (nstate == Node.DELETED) {
// nmgr.app.logEvent ("deleted: "+node.getFullName ()+" ("+node.getName ()+")"); // nmgr.app.logEvent ("deleted: "+node.getFullName ()+" ("+node.getName ()+")");
nmgr.deleteNode(nmgr.db, txn, node); nmgr.deleteNode(nmgr.db, txn, node);
nmgr.evictNode(node); nmgr.evictNode(node);
if (replicator != null)
if (replicator != null) {
replicator.addDeletedNode(node); replicator.addDeletedNode(node);
}
dlt++; dlt++;
} else { } else {
// nmgr.app.logEvent ("noop: "+node.getFullName ()); // nmgr.app.logEvent ("noop: "+node.getFullName ());
} }
node.clearWriteLock(); node.clearWriteLock();
} }
@ -180,72 +279,99 @@ public class Transactor extends Thread {
txn = null; txn = null;
} }
nmgr.app.logAccess (tname+" "+l+" marked, "+ins+" inserted, "+upd+" updated, "+dlt+" deleted in "+(System.currentTimeMillis()-tstart)+" millis"); nmgr.app.logAccess(tname + " " + l + " marked, " + ins + " inserted, " + upd +
" updated, " + dlt + " deleted in " +
(System.currentTimeMillis() - tstart) + " millis");
} }
/**
*
*
* @throws Exception ...
*/
public synchronized void abort() throws Exception { public synchronized void abort() throws Exception {
int l = nodesArray.size(); int l = nodesArray.size();
for (int i = 0; i < l; i++) { for (int i = 0; i < l; i++) {
Node node = (Node) nodesArray.get(i); Node node = (Node) nodesArray.get(i);
// Declare node as invalid, so it won't be used by other threads that want to // Declare node as invalid, so it won't be used by other threads that want to
// write on it and remove it from cache // write on it and remove it from cache
nmgr.evictNode(node); nmgr.evictNode(node);
node.clearWriteLock(); node.clearWriteLock();
} }
nodes.clear(); nodes.clear();
nodesArray.clear(); nodesArray.clear();
cleannodes.clear(); cleannodes.clear();
// close any JDBC connections associated with this transactor thread // close any JDBC connections associated with this transactor thread
closeConnections(); closeConnections();
if (active) { if (active) {
active = false; active = false;
if (txn != null) { if (txn != null) {
nmgr.db.abortTransaction(txn); nmgr.db.abortTransaction(txn);
txn = null; txn = null;
} }
nmgr.app.logAccess (tname+" aborted after "+(System.currentTimeMillis()-tstart)+" millis");
nmgr.app.logAccess(tname + " aborted after " +
(System.currentTimeMillis() - tstart) + " millis");
} }
} }
/**
*
*/
public synchronized void kill() { public synchronized void kill() {
killed = true; killed = true;
// The thread is told to stop by setting the thread flag in the EcmaScript // The thread is told to stop by setting the thread flag in the EcmaScript
// evaluator, so we can hope that it stops without doing anything else. // evaluator, so we can hope that it stops without doing anything else.
try { try {
join(500); join(500);
} catch (InterruptedException ir) {} } catch (InterruptedException ir) {
}
// Interrupt the thread if it has not noticed the flag (e.g. because it is busy // Interrupt the thread if it has not noticed the flag (e.g. because it is busy
// reading from a network socket). // reading from a network socket).
if (isAlive()) { if (isAlive()) {
interrupt(); interrupt();
try { try {
join(1000); join(1000);
} catch (InterruptedException ir) {} } catch (InterruptedException ir) {
}
} }
} }
/**
*
*/
public void closeConnections() { public void closeConnections() {
// nmgr.app.logEvent("Cleaning up Transactor thread"); // nmgr.app.logEvent("Cleaning up Transactor thread");
if (sqlCon != null) { if (sqlCon != null) {
for (Iterator i = sqlCon.values().iterator(); i.hasNext();) { for (Iterator i = sqlCon.values().iterator(); i.hasNext();) {
try { try {
Connection con = (Connection) i.next(); Connection con = (Connection) i.next();
con.close(); con.close();
nmgr.app.logEvent("Closing DB connection: " + con); nmgr.app.logEvent("Closing DB connection: " + con);
} catch (Exception ignore) {} } catch (Exception ignore) {
} }
}
sqlCon.clear(); sqlCon.clear();
} }
} }
/**
*
*
* @return ...
*/
public String toString() { public String toString() {
return "Transactor[" + tname + "]"; return "Transactor[" + tname + "]";
} }
} }

View file

@ -1,5 +1,18 @@
// WrappedNodeManager.java /*
// Copyright (c) Hannes Wallnöfer 1998-2000 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.objectmodel.db; package helma.objectmodel.db;
@ -7,25 +20,42 @@ import helma.objectmodel.*;
import java.util.List; import java.util.List;
import java.util.Vector; import java.util.Vector;
/** /**
* A wrapper around NodeManager that catches most Exceptions, or rethrows them as RuntimeExceptions. * A wrapper around NodeManager that catches most Exceptions, or rethrows them as RuntimeExceptions.
* The idea behind this is that we don't care a lot about Exception classes, since Hop programming is done * The idea behind this is that we don't care a lot about Exception classes, since Hop programming is done
* in JavaScript which doesn't know about them (except for the exception message). * in JavaScript which doesn't know about them (except for the exception message).
*/ */
public final class WrappedNodeManager { public final class WrappedNodeManager {
NodeManager nmgr; NodeManager nmgr;
/**
* Creates a new WrappedNodeManager object.
*
* @param nmgr ...
*/
public WrappedNodeManager(NodeManager nmgr) { public WrappedNodeManager(NodeManager nmgr) {
this.nmgr = nmgr; this.nmgr = nmgr;
} }
/**
*
*
* @param id ...
* @param dbmap ...
*
* @return ...
*/
public Node getNode(String id, DbMapping dbmap) { public Node getNode(String id, DbMapping dbmap) {
return getNode(new DbKey(dbmap, id)); return getNode(new DbKey(dbmap, id));
} }
/**
*
*
* @param key ...
*
* @return ...
*/
public Node getNode(Key key) { public Node getNode(Key key) {
try { try {
return nmgr.getNode(key); return nmgr.getNode(key);
@ -33,124 +63,241 @@ import java.util.Vector;
return null; return null;
} catch (Exception x) { } catch (Exception x) {
nmgr.app.logEvent("Error retrieving Node via DbMapping: " + x); nmgr.app.logEvent("Error retrieving Node via DbMapping: " + x);
if (nmgr.app.debug ())
if (nmgr.app.debug()) {
x.printStackTrace(); x.printStackTrace();
}
throw new RuntimeException("Error retrieving Node: " + x); throw new RuntimeException("Error retrieving Node: " + x);
} }
} }
/**
*
*
* @param home ...
* @param id ...
* @param rel ...
*
* @return ...
*/
public Node getNode(Node home, String id, Relation rel) { public Node getNode(Node home, String id, Relation rel) {
try { try {
return nmgr.getNode(home, id, rel); return nmgr.getNode(home, id, rel);
} catch (ObjectNotFoundException x) { } catch (ObjectNotFoundException x) {
return null; return null;
} catch (Exception x) { } catch (Exception x) {
nmgr.app.logEvent ("Error retrieving Node \""+id+"\" from "+home+": "+x); nmgr.app.logEvent("Error retrieving Node \"" + id + "\" from " + home + ": " +
if (nmgr.app.debug ()) x);
if (nmgr.app.debug()) {
x.printStackTrace(); x.printStackTrace();
}
throw new RuntimeException("Error retrieving Node: " + x); throw new RuntimeException("Error retrieving Node: " + x);
} }
} }
/**
*
*
* @param home ...
* @param rel ...
*
* @return ...
*/
public List getNodes(Node home, Relation rel) { public List getNodes(Node home, Relation rel) {
try { try {
return nmgr.getNodes(home, rel); return nmgr.getNodes(home, rel);
} catch (Exception x) { } catch (Exception x) {
if (nmgr.app.debug ()) if (nmgr.app.debug()) {
x.printStackTrace(); x.printStackTrace();
}
throw new RuntimeException("Error retrieving Nodes: " + x); throw new RuntimeException("Error retrieving Nodes: " + x);
} }
} }
/**
*
*
* @param home ...
* @param rel ...
*
* @return ...
*/
public List getNodeIDs(Node home, Relation rel) { public List getNodeIDs(Node home, Relation rel) {
try { try {
return nmgr.getNodeIDs(home, rel); return nmgr.getNodeIDs(home, rel);
} catch (Exception x) { } catch (Exception x) {
if (nmgr.app.debug ()) if (nmgr.app.debug()) {
x.printStackTrace(); x.printStackTrace();
}
throw new RuntimeException("Error retrieving NodeIDs: " + x); throw new RuntimeException("Error retrieving NodeIDs: " + x);
} }
} }
/**
*
*
* @param home ...
* @param rel ...
*
* @return ...
*/
public int countNodes(Node home, Relation rel) { public int countNodes(Node home, Relation rel) {
try { try {
return nmgr.countNodes(home, rel); return nmgr.countNodes(home, rel);
} catch (Exception x) { } catch (Exception x) {
if (nmgr.app.debug ()) if (nmgr.app.debug()) {
x.printStackTrace(); x.printStackTrace();
}
throw new RuntimeException("Error counting Node: " + x); throw new RuntimeException("Error counting Node: " + x);
} }
} }
/**
*
*
* @param node ...
*/
public void deleteNode(Node node) { public void deleteNode(Node node) {
try { try {
nmgr.deleteNode(node); nmgr.deleteNode(node);
} catch (Exception x) { } catch (Exception x) {
if (nmgr.app.debug ()) if (nmgr.app.debug()) {
x.printStackTrace(); x.printStackTrace();
}
throw new RuntimeException("Error deleting Node: " + x); throw new RuntimeException("Error deleting Node: " + x);
} }
} }
/**
*
*
* @param home ...
* @param rel ...
*
* @return ...
*/
public Vector getPropertyNames(Node home, Relation rel) { public Vector getPropertyNames(Node home, Relation rel) {
try { try {
return nmgr.getPropertyNames(home, rel); return nmgr.getPropertyNames(home, rel);
} catch (Exception x) { } catch (Exception x) {
if (nmgr.app.debug ()) if (nmgr.app.debug()) {
x.printStackTrace(); x.printStackTrace();
}
throw new RuntimeException("Error retrieving property names: " + x); throw new RuntimeException("Error retrieving property names: " + x);
} }
} }
/**
*
*
* @param node ...
*/
public void registerNode(Node node) { public void registerNode(Node node) {
nmgr.registerNode(node); nmgr.registerNode(node);
} }
/**
*
*
* @param node ...
*/
public void evictNode(Node node) { public void evictNode(Node node) {
nmgr.evictNode(node); nmgr.evictNode(node);
} }
/**
*
*
* @param key ...
*/
public void evictNodeByKey(Key key) { public void evictNodeByKey(Key key) {
nmgr.evictNodeByKey(key); nmgr.evictNodeByKey(key);
} }
/**
*
*
* @param key ...
*/
public void evictKey(Key key) { public void evictKey(Key key) {
nmgr.evictKey(key); nmgr.evictKey(key);
} }
/**
*
*
* @return ...
*/
public String generateID() { public String generateID() {
return nmgr.idgen.newID(); return nmgr.idgen.newID();
} }
/**
*
*
* @param map ...
*
* @return ...
*/
public String generateID(DbMapping map) { public String generateID(DbMapping map) {
try { try {
// check if we use internal id generator // check if we use internal id generator
if (map == null || !map.isRelational () || "[hop]".equalsIgnoreCase (map.getIDgen())) if ((map == null) || !map.isRelational() ||
"[hop]".equalsIgnoreCase(map.getIDgen())) {
return nmgr.idgen.newID(); return nmgr.idgen.newID();
}
// or if we query max key value // or if we query max key value
else if (map.getIDgen() == null || "[max]".equalsIgnoreCase (map.getIDgen())) else if ((map.getIDgen() == null) ||
"[max]".equalsIgnoreCase(map.getIDgen())) {
return nmgr.generateMaxID(map); return nmgr.generateMaxID(map);
else } else {
return nmgr.generateID(map); return nmgr.generateID(map);
}
// otherwise, we use an oracle sequence // otherwise, we use an oracle sequence
} catch (Exception x) { } catch (Exception x) {
if (nmgr.app.debug ()) if (nmgr.app.debug()) {
x.printStackTrace(); x.printStackTrace();
}
throw new RuntimeException(x.toString()); throw new RuntimeException(x.toString());
} }
} }
/**
*
*
* @return ...
*/
public Object[] getCacheEntries() { public Object[] getCacheEntries() {
return nmgr.getCacheEntries(); return nmgr.getCacheEntries();
} }
/**
*
*
* @param msg ...
*/
public void logEvent(String msg) { public void logEvent(String msg) {
nmgr.app.logEvent(msg); nmgr.app.logEvent(msg);
} }
/**
*
*
* @param name ...
*
* @return ...
*/
public DbMapping getDbMapping(String name) { public DbMapping getDbMapping(String name) {
return nmgr.app.getDbMapping(name); return nmgr.app.getDbMapping(name);
} }
} }

View file

@ -1,68 +1,173 @@
package helma.objectmodel.db; /*
* Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
import java.io.*; package helma.objectmodel.db;
import java.util.Date;
import org.w3c.dom.Element;
import org.w3c.dom.Document;
import helma.objectmodel.*; import helma.objectmodel.*;
import helma.objectmodel.dom.*; import helma.objectmodel.dom.*;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import java.io.*;
import java.util.Date;
/** /**
* A simple XML-database * A simple XML-database
*/ */
public final class XmlDatabase implements IDatabase { public final class XmlDatabase implements IDatabase {
private String dbHome; private String dbHome;
private File dbBaseDir; private File dbBaseDir;
private NodeManager nmgr; private NodeManager nmgr;
private IDGenerator idgen; private IDGenerator idgen;
// character encoding to use when writing files. // character encoding to use when writing files.
// use standard encoding by default. // use standard encoding by default.
private String encoding = null; private String encoding = null;
/**
public XmlDatabase (String dbHome, String dbFilename, NodeManager nmgr) throws DatabaseException { * Creates a new XmlDatabase object.
*
* @param dbHome ...
* @param dbFilename ...
* @param nmgr ...
*
* @throws DatabaseException ...
* @throws RuntimeException ...
*/
public XmlDatabase(String dbHome, String dbFilename, NodeManager nmgr)
throws DatabaseException {
this.dbHome = dbHome; this.dbHome = dbHome;
this.nmgr = nmgr; this.nmgr = nmgr;
dbBaseDir = new File(dbHome); dbBaseDir = new File(dbHome);
if (!dbBaseDir.exists() && !dbBaseDir.mkdirs() )
if (!dbBaseDir.exists() && !dbBaseDir.mkdirs()) {
throw new RuntimeException("Couldn't create DB-directory"); throw new RuntimeException("Couldn't create DB-directory");
}
this.encoding = nmgr.app.getCharset(); this.encoding = nmgr.app.getCharset();
} }
public void shutdown () { } /**
public ITransaction beginTransaction () throws DatabaseException { return null; } *
public void commitTransaction (ITransaction txn) throws DatabaseException { } */
public void abortTransaction (ITransaction txn) throws DatabaseException { } public void shutdown() {
}
/**
*
*
* @return ...
*
* @throws DatabaseException ...
*/
public ITransaction beginTransaction() throws DatabaseException {
return null;
}
/**
*
*
* @param txn ...
*
* @throws DatabaseException ...
*/
public void commitTransaction(ITransaction txn) throws DatabaseException {
}
/**
*
*
* @param txn ...
*
* @throws DatabaseException ...
*/
public void abortTransaction(ITransaction txn) throws DatabaseException {
}
/**
*
*
* @return ...
*
* @throws ObjectNotFoundException ...
*/
public String nextID() throws ObjectNotFoundException { public String nextID() throws ObjectNotFoundException {
if (idgen == null) { if (idgen == null) {
getIDGenerator(null); getIDGenerator(null);
} }
return idgen.newID(); return idgen.newID();
} }
public IDGenerator getIDGenerator (ITransaction txn) throws ObjectNotFoundException { /**
*
*
* @param txn ...
*
* @return ...
*
* @throws ObjectNotFoundException ...
*/
public IDGenerator getIDGenerator(ITransaction txn)
throws ObjectNotFoundException {
File file = new File(dbBaseDir, "idgen.xml"); File file = new File(dbBaseDir, "idgen.xml");
this.idgen = IDGenParser.getIDGenerator(file); this.idgen = IDGenParser.getIDGenerator(file);
return idgen; return idgen;
} }
public void saveIDGenerator (ITransaction txn, IDGenerator idgen) throws Exception { /**
*
*
* @param txn ...
* @param idgen ...
*
* @throws Exception ...
*/
public void saveIDGenerator(ITransaction txn, IDGenerator idgen)
throws Exception {
File file = new File(dbBaseDir, "idgen.xml"); File file = new File(dbBaseDir, "idgen.xml");
IDGenParser.saveIDGenerator(idgen, file); IDGenParser.saveIDGenerator(idgen, file);
this.idgen = idgen; this.idgen = idgen;
} }
public INode getNode (ITransaction txn, String kstr) throws Exception { /**
*
*
* @param txn ...
* @param kstr ...
*
* @return ...
*
* @throws Exception ...
* @throws ObjectNotFoundException ...
*/
public INode getNode(ITransaction txn, String kstr)
throws Exception {
File f = new File(dbBaseDir, kstr + ".xml"); File f = new File(dbBaseDir, kstr + ".xml");
if ( ! f.exists() )
if (!f.exists()) {
throw new ObjectNotFoundException("Object not found for key " + kstr + "."); throw new ObjectNotFoundException("Object not found for key " + kstr + ".");
}
try { try {
XmlDatabaseReader reader = new XmlDatabaseReader(nmgr); XmlDatabaseReader reader = new XmlDatabaseReader(nmgr);
Node node = reader.read(f); Node node = reader.read(f);
return node; return node;
} catch (RuntimeException x) { } catch (RuntimeException x) {
nmgr.app.logEvent("error reading node from XmlDatbase: " + x.toString()); nmgr.app.logEvent("error reading node from XmlDatbase: " + x.toString());
@ -70,27 +175,62 @@ public final class XmlDatabase implements IDatabase {
} }
} }
public void saveNode (ITransaction txn, String kstr, INode node) throws Exception { /**
*
*
* @param txn ...
* @param kstr ...
* @param node ...
*
* @throws Exception ...
*/
public void saveNode(ITransaction txn, String kstr, INode node)
throws Exception {
XmlWriter writer = null; XmlWriter writer = null;
File file = new File(dbBaseDir, kstr + ".xml"); File file = new File(dbBaseDir, kstr + ".xml");
if (encoding != null)
if (encoding != null) {
writer = new XmlWriter(file, encoding); writer = new XmlWriter(file, encoding);
else } else {
writer = new XmlWriter(file); writer = new XmlWriter(file);
}
writer.setMaxLevels(1); writer.setMaxLevels(1);
boolean result = writer.write((Node) node); boolean result = writer.write((Node) node);
writer.close(); writer.close();
} }
public void deleteNode (ITransaction txn, String kstr) throws Exception { /**
*
*
* @param txn ...
* @param kstr ...
*
* @throws Exception ...
*/
public void deleteNode(ITransaction txn, String kstr)
throws Exception {
File f = new File(dbBaseDir, kstr + ".xml"); File f = new File(dbBaseDir, kstr + ".xml");
f.delete(); f.delete();
} }
/**
*
*
* @param enc ...
*/
public void setEncoding(String enc) { public void setEncoding(String enc) {
this.encoding = encoding; this.encoding = encoding;
} }
/**
*
*
* @return ...
*/
public String getEncoding() { public String getEncoding() {
return encoding; return encoding;
} }

View file

@ -1,28 +1,72 @@
package helma.objectmodel.dom; /*
* Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
import java.io.*; package helma.objectmodel.dom;
import java.util.Date;
import org.w3c.dom.*;
import helma.objectmodel.ObjectNotFoundException; import helma.objectmodel.ObjectNotFoundException;
import helma.objectmodel.db.IDGenerator; import helma.objectmodel.db.IDGenerator;
import org.w3c.dom.*;
import java.io.*;
import java.util.Date;
/**
*
*/
public class IDGenParser { public class IDGenParser {
/**
public static IDGenerator getIDGenerator (File file) throws ObjectNotFoundException { *
if ( ! file.exists() ) *
* @param file ...
*
* @return ...
*
* @throws ObjectNotFoundException ...
*/
public static IDGenerator getIDGenerator(File file)
throws ObjectNotFoundException {
if (!file.exists()) {
throw new ObjectNotFoundException("IDGenerator not found in idgen.xml"); throw new ObjectNotFoundException("IDGenerator not found in idgen.xml");
}
try { try {
Document document = XmlUtil.parse(new FileInputStream(file)); Document document = XmlUtil.parse(new FileInputStream(file));
org.w3c.dom.Element tmp = (Element)document.getDocumentElement().getElementsByTagName("counter").item(0); org.w3c.dom.Element tmp = (Element) document.getDocumentElement()
.getElementsByTagName("counter")
.item(0);
return new IDGenerator(Long.parseLong(XmlUtil.getTextContent(tmp))); return new IDGenerator(Long.parseLong(XmlUtil.getTextContent(tmp)));
} catch (Exception e) { } catch (Exception e) {
throw new ObjectNotFoundException(e.toString()); throw new ObjectNotFoundException(e.toString());
} }
} }
public static IDGenerator saveIDGenerator (IDGenerator idgen, File file) throws Exception { /**
*
*
* @param idgen ...
* @param file ...
*
* @return ...
*
* @throws Exception ...
*/
public static IDGenerator saveIDGenerator(IDGenerator idgen, File file)
throws Exception {
OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(file)); OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(file));
out.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); out.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
out.write("<!-- printed by helma object publisher -->\n"); out.write("<!-- printed by helma object publisher -->\n");
out.write("<!-- created " + (new Date()).toString() + " -->\n"); out.write("<!-- created " + (new Date()).toString() + " -->\n");
@ -30,8 +74,7 @@ public class IDGenParser {
out.write(" <counter>" + idgen.getValue() + "</counter>\n"); out.write(" <counter>" + idgen.getValue() + "</counter>\n");
out.write("</xmlroot>\n"); out.write("</xmlroot>\n");
out.close(); out.close();
return idgen; return idgen;
} }
} }

View file

@ -1,8 +1,25 @@
/*
* Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.objectmodel.dom; package helma.objectmodel.dom;
/**
*
*/
public interface XmlConstants { public interface XmlConstants {
public final String NAMESPACE = "http://www.helma.org/docs/guide/features/database"; public final String NAMESPACE = "http://www.helma.org/docs/guide/features/database";
public final String DATEFORMAT = "dd.MM.yyyy HH:mm:ss z"; public final String DATEFORMAT = "dd.MM.yyyy HH:mm:ss z";
} }

View file

@ -1,51 +1,99 @@
/*
* Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.objectmodel.dom; package helma.objectmodel.dom;
import java.io.*;
import java.net.*;
import java.util.*;
import javax.xml.parsers.*;
import org.w3c.dom.*;
import org.xml.sax.InputSource;
import helma.objectmodel.*; import helma.objectmodel.*;
import helma.util.SystemProperties; import helma.util.SystemProperties;
import org.w3c.dom.*;
import org.xml.sax.InputSource;
import java.io.*;
import java.net.*;
import java.util.*;
import javax.xml.parsers.*;
/**
*
*/
public class XmlConverter implements XmlConstants { public class XmlConverter implements XmlConstants {
private boolean DEBUG = false; private boolean DEBUG = false;
private boolean sparse = false; private boolean sparse = false;
private Properties props; private Properties props;
private char defaultSeparator = '_'; private char defaultSeparator = '_';
private int offset = 0; private int offset = 0;
/**
* Creates a new XmlConverter object.
*/
public XmlConverter() { public XmlConverter() {
props = new SystemProperties(); props = new SystemProperties();
} }
/**
* Creates a new XmlConverter object.
*
* @param propFile ...
*/
public XmlConverter(String propFile) { public XmlConverter(String propFile) {
props = new SystemProperties(propFile); props = new SystemProperties(propFile);
extractProperties(props); extractProperties(props);
} }
/**
* Creates a new XmlConverter object.
*
* @param propFile ...
*/
public XmlConverter(File propFile) { public XmlConverter(File propFile) {
this(propFile.getAbsolutePath()); this(propFile.getAbsolutePath());
} }
/**
* Creates a new XmlConverter object.
*
* @param props ...
*/
public XmlConverter(Properties props) { public XmlConverter(Properties props) {
this.props = props; this.props = props;
extractProperties(props); extractProperties(props);
} }
/**
*
*
* @param desc ...
*
* @return ...
*/
public INode convert(String desc) { public INode convert(String desc) {
return convert(desc, new TransientNode()); return convert(desc, new TransientNode());
} }
public INode convert( String desc, INode helmaNode ) throws RuntimeException { /**
*
*
* @param desc ...
* @param helmaNode ...
*
* @return ...
*
* @throws RuntimeException ...
*/
public INode convert(String desc, INode helmaNode)
throws RuntimeException {
try { try {
return convert(new URL(desc), helmaNode); return convert(new URL(desc), helmaNode);
} catch (MalformedURLException notanurl) { } catch (MalformedURLException notanurl) {
@ -59,42 +107,107 @@ public class XmlConverter implements XmlConstants {
} }
} }
public INode convert( File file, INode helmaNode ) throws RuntimeException, FileNotFoundException { /**
*
*
* @param file ...
* @param helmaNode ...
*
* @return ...
*
* @throws RuntimeException ...
* @throws FileNotFoundException ...
*/
public INode convert(File file, INode helmaNode)
throws RuntimeException, FileNotFoundException {
return convert(new FileInputStream(file), helmaNode); return convert(new FileInputStream(file), helmaNode);
} }
public INode convert( URL url, INode helmaNode ) throws RuntimeException, IOException, MalformedURLException { /**
*
*
* @param url ...
* @param helmaNode ...
*
* @return ...
*
* @throws RuntimeException ...
* @throws IOException ...
* @throws MalformedURLException ...
*/
public INode convert(URL url, INode helmaNode)
throws RuntimeException, IOException, MalformedURLException {
return convert(url.openConnection().getInputStream(), helmaNode); return convert(url.openConnection().getInputStream(), helmaNode);
} }
public INode convert( InputStream in, INode helmaNode ) throws RuntimeException { /**
*
*
* @param in ...
* @param helmaNode ...
*
* @return ...
*
* @throws RuntimeException ...
*/
public INode convert(InputStream in, INode helmaNode)
throws RuntimeException {
Document document = XmlUtil.parse(in); Document document = XmlUtil.parse(in);
if ( document!=null && document.getDocumentElement()!=null ) {
if ((document != null) && (document.getDocumentElement() != null)) {
return convert(document.getDocumentElement(), helmaNode, new HashMap()); return convert(document.getDocumentElement(), helmaNode, new HashMap());
} else { } else {
return helmaNode; return helmaNode;
} }
} }
public INode convertFromString( String xml, INode helmaNode ) throws RuntimeException { /**
*
*
* @param xml ...
* @param helmaNode ...
*
* @return ...
*
* @throws RuntimeException ...
*/
public INode convertFromString(String xml, INode helmaNode)
throws RuntimeException {
Document document = XmlUtil.parse(new InputSource(new StringReader(xml))); Document document = XmlUtil.parse(new InputSource(new StringReader(xml)));
if ( document!=null && document.getDocumentElement()!=null ) {
if ((document != null) && (document.getDocumentElement() != null)) {
return convert(document.getDocumentElement(), helmaNode, new HashMap()); return convert(document.getDocumentElement(), helmaNode, new HashMap());
} else { } else {
return helmaNode; return helmaNode;
} }
} }
/**
*
*
* @param element ...
* @param helmaNode ...
* @param nodeCache ...
*
* @return ...
*/
public INode convert(Element element, INode helmaNode, Map nodeCache) { public INode convert(Element element, INode helmaNode, Map nodeCache) {
offset++; offset++;
// previousNode is used to cache previous nodes with the same prototype // previousNode is used to cache previous nodes with the same prototype
// so we can reset it in the nodeCache after we've run // so we can reset it in the nodeCache after we've run
Object previousNode = null; Object previousNode = null;
if (DEBUG)
if (DEBUG) {
debug("reading " + element.getNodeName()); debug("reading " + element.getNodeName());
}
String prototype = props.getProperty(element.getNodeName() + "._prototype"); String prototype = props.getProperty(element.getNodeName() + "._prototype");
if ( prototype == null && !sparse )
if ((prototype == null) && !sparse) {
prototype = "HopObject"; prototype = "HopObject";
}
// if we have a prototype (either explicit or implicit "hopobject"), // if we have a prototype (either explicit or implicit "hopobject"),
// set it on the Helma node and store it in the node cache. // set it on the Helma node and store it in the node cache.
if (prototype != null) { if (prototype != null) {
@ -102,31 +215,38 @@ public class XmlConverter implements XmlConstants {
helmaNode.setPrototype(prototype); helmaNode.setPrototype(prototype);
previousNode = nodeCache.put(prototype, helmaNode); previousNode = nodeCache.put(prototype, helmaNode);
} }
// check attributes of the current element // check attributes of the current element
attributes(element, helmaNode, nodeCache); attributes(element, helmaNode, nodeCache);
// check child nodes of the current element // check child nodes of the current element
if ( element.hasChildNodes() ) if (element.hasChildNodes()) {
children(element, helmaNode, nodeCache); children(element, helmaNode, nodeCache);
}
// if it exists, restore the previous node we've replaced in the node cache. // if it exists, restore the previous node we've replaced in the node cache.
if (previousNode != null) if (previousNode != null) {
nodeCache.put(prototype, previousNode); nodeCache.put(prototype, previousNode);
}
offset--; offset--;
return helmaNode; return helmaNode;
} }
/** /**
* parse xml children and create hopobject-children * parse xml children and create hopobject-children
*/ */
private INode children( Element element, helma.objectmodel.INode helmaNode, Map nodeCache ) { private INode children(Element element, helma.objectmodel.INode helmaNode,
Map nodeCache) {
NodeList list = element.getChildNodes(); NodeList list = element.getChildNodes();
int len = list.getLength(); int len = list.getLength();
boolean nodeIsInitialized = !nodeCache.isEmpty(); boolean nodeIsInitialized = !nodeCache.isEmpty();
StringBuffer textcontent = new StringBuffer(); StringBuffer textcontent = new StringBuffer();
String domKey, helmaKey; String domKey;
for ( int i=0; i<len; i++ ) { String helmaKey;
for (int i = 0; i < len; i++) {
// loop through the list of children // loop through the list of children
org.w3c.dom.Node childNode = list.item(i); org.w3c.dom.Node childNode = list.item(i);
@ -135,104 +255,146 @@ public class XmlConverter implements XmlConstants {
if (!nodeIsInitialized) { if (!nodeIsInitialized) {
if (childNode.getNodeType() == Node.ELEMENT_NODE) { if (childNode.getNodeType() == Node.ELEMENT_NODE) {
convert((Element) childNode, helmaNode, nodeCache); convert((Element) childNode, helmaNode, nodeCache);
if (helmaNode.getPrototype() != null)
if (helmaNode.getPrototype() != null) {
return helmaNode; return helmaNode;
} }
}
continue; continue;
} }
// if it's text content of this element -> append to StringBuffer // if it's text content of this element -> append to StringBuffer
if ( childNode.getNodeType() == Node.TEXT_NODE || if ((childNode.getNodeType() == Node.TEXT_NODE) ||
childNode.getNodeType() == Node.CDATA_SECTION_NODE ) { (childNode.getNodeType() == Node.CDATA_SECTION_NODE)) {
textcontent.append(childNode.getNodeValue().trim()); textcontent.append(childNode.getNodeValue().trim());
continue; continue;
} }
// it's some kind of element (property or child) // it's some kind of element (property or child)
if (childNode.getNodeType() == Node.ELEMENT_NODE) { if (childNode.getNodeType() == Node.ELEMENT_NODE) {
Element childElement = (Element) childNode; Element childElement = (Element) childNode;
// get the basic key we have to look for in the properties-table // get the basic key we have to look for in the properties-table
domKey = element.getNodeName() + "." + childElement.getNodeName(); domKey = element.getNodeName() + "." + childElement.getNodeName();
// is there a childtext-2-property mapping? // is there a childtext-2-property mapping?
if ( props!=null && props.containsKey(domKey+"._text") ) { if ((props != null) && props.containsKey(domKey + "._text")) {
helmaKey = props.getProperty(domKey + "._text"); helmaKey = props.getProperty(domKey + "._text");
if( helmaKey.equals("") )
if (helmaKey.equals("")) {
// if property is set but without value, read elementname for this mapping // if property is set but without value, read elementname for this mapping
helmaKey = childElement.getNodeName().replace(':',defaultSeparator); helmaKey = childElement.getNodeName().replace(':',
if (DEBUG) defaultSeparator);
debug("childtext-2-property mapping, helmaKey " + helmaKey + " for domKey " + domKey ); }
if (DEBUG) {
debug("childtext-2-property mapping, helmaKey " + helmaKey +
" for domKey " + domKey);
}
// check if helmaKey contains an explicit prototype name in which to // check if helmaKey contains an explicit prototype name in which to
// set the property. // set the property.
int dot = helmaKey.indexOf("."); int dot = helmaKey.indexOf(".");
if (dot > -1) { if (dot > -1) {
String prototype = helmaKey.substring(0, dot); String prototype = helmaKey.substring(0, dot);
INode node = (INode) nodeCache.get(prototype); INode node = (INode) nodeCache.get(prototype);
helmaKey = helmaKey.substring(dot + 1); helmaKey = helmaKey.substring(dot + 1);
if (node != null && node.getString(helmaKey)==null) {
if ((node != null) && (node.getString(helmaKey) == null)) {
node.setString(helmaKey, XmlUtil.getTextContent(childNode)); node.setString(helmaKey, XmlUtil.getTextContent(childNode));
} }
} else if (helmaNode.getString(helmaKey) == null) { } else if (helmaNode.getString(helmaKey) == null) {
helmaNode.setString(helmaKey, XmlUtil.getTextContent(childNode)); helmaNode.setString(helmaKey, XmlUtil.getTextContent(childNode));
if (DEBUG)
debug("childtext-2-property mapping, setting " + helmaKey + " as string" ); if (DEBUG) {
debug("childtext-2-property mapping, setting " + helmaKey +
" as string");
} }
}
continue; continue;
} }
// is there a simple child-2-property mapping? // is there a simple child-2-property mapping?
// (lets the user define to use only one element and make this a property // (lets the user define to use only one element and make this a property
// and simply ignore other elements of the same name) // and simply ignore other elements of the same name)
if ( props!=null && props.containsKey(domKey+"._property") ) { if ((props != null) && props.containsKey(domKey + "._property")) {
helmaKey = props.getProperty(domKey + "._property"); helmaKey = props.getProperty(domKey + "._property");
// if property is set but without value, read elementname for this mapping: // if property is set but without value, read elementname for this mapping:
if ( helmaKey.equals("") ) if (helmaKey.equals("")) {
helmaKey = childElement.getNodeName().replace(':',defaultSeparator); helmaKey = childElement.getNodeName().replace(':',
if (DEBUG) defaultSeparator);
debug("child-2-property mapping, helmaKey " + helmaKey + " for domKey " + domKey); }
if (DEBUG) {
debug("child-2-property mapping, helmaKey " + helmaKey +
" for domKey " + domKey);
}
// get the node on which to opererate, depending on the helmaKey // get the node on which to opererate, depending on the helmaKey
// value from the properties file. // value from the properties file.
INode node = helmaNode; INode node = helmaNode;
int dot = helmaKey.indexOf("."); int dot = helmaKey.indexOf(".");
if (dot > -1) { if (dot > -1) {
String prototype = helmaKey.substring(0, dot); String prototype = helmaKey.substring(0, dot);
if (!prototype.equalsIgnoreCase (node.getPrototype()))
if (!prototype.equalsIgnoreCase(node.getPrototype())) {
node = (INode) nodeCache.get(prototype); node = (INode) nodeCache.get(prototype);
}
helmaKey = helmaKey.substring(dot + 1); helmaKey = helmaKey.substring(dot + 1);
} }
if (node == null)
if (node == null) {
continue; continue;
}
if (node.getNode(helmaKey) == null) { if (node.getNode(helmaKey) == null) {
convert(childElement, node.createNode(helmaKey), nodeCache); convert(childElement, node.createNode(helmaKey), nodeCache);
if (DEBUG)
debug( "read " + childElement.toString() + node.getNode(helmaKey).toString() ); if (DEBUG) {
debug("read " + childElement.toString() +
node.getNode(helmaKey).toString());
} }
}
continue; continue;
} }
// map it to one of the children-lists // map it to one of the children-lists
helma.objectmodel.INode newHelmaNode = null; helma.objectmodel.INode newHelmaNode = null;
String childrenMapping = props.getProperty(element.getNodeName()+"._children"); String childrenMapping = props.getProperty(element.getNodeName() +
"._children");
// do we need a mapping directly among _children of helmaNode? // do we need a mapping directly among _children of helmaNode?
// can either be through property elname._children=_all or elname._children=childname // can either be through property elname._children=_all or elname._children=childname
if( childrenMapping!=null && ( childrenMapping.equals("_all") || childrenMapping.equals(childElement.getNodeName()) ) ) { if ((childrenMapping != null) &&
newHelmaNode = convert(childElement, helmaNode.createNode(null), nodeCache ); (childrenMapping.equals("_all") ||
childrenMapping.equals(childElement.getNodeName()))) {
newHelmaNode = convert(childElement, helmaNode.createNode(null),
nodeCache);
} }
// in which virtual subnode collection should objects of this type be stored? // in which virtual subnode collection should objects of this type be stored?
helmaKey = props.getProperty(domKey); helmaKey = props.getProperty(domKey);
if ( helmaKey==null && !sparse ) {
if ((helmaKey == null) && !sparse) {
helmaKey = childElement.getNodeName().replace(':', defaultSeparator); helmaKey = childElement.getNodeName().replace(':', defaultSeparator);
} }
if (helmaKey == null) { if (helmaKey == null) {
// we don't map this child element itself since we do // we don't map this child element itself since we do
// sparse parsing, but there may be something of interest // sparse parsing, but there may be something of interest
// in the child's attributes and child elements. // in the child's attributes and child elements.
attributes(childElement, helmaNode, nodeCache); attributes(childElement, helmaNode, nodeCache);
children(childElement, helmaNode, nodeCache); children(childElement, helmaNode, nodeCache);
continue; continue;
} }
@ -240,28 +402,40 @@ public class XmlConverter implements XmlConstants {
// value from the properties file. // value from the properties file.
INode node = helmaNode; INode node = helmaNode;
int dot = helmaKey.indexOf("."); int dot = helmaKey.indexOf(".");
if (dot > -1) { if (dot > -1) {
String prototype = helmaKey.substring(0, dot); String prototype = helmaKey.substring(0, dot);
if (!prototype.equalsIgnoreCase (node.getPrototype()))
if (!prototype.equalsIgnoreCase(node.getPrototype())) {
node = (INode) nodeCache.get(prototype); node = (INode) nodeCache.get(prototype);
}
helmaKey = helmaKey.substring(dot + 1); helmaKey = helmaKey.substring(dot + 1);
} }
if (node == null)
if (node == null) {
continue; continue;
}
// try to get the virtual node // try to get the virtual node
INode worknode = null; INode worknode = null;
if ("_children".equals(helmaKey)) { if ("_children".equals(helmaKey)) {
worknode = node; worknode = node;
} else { } else {
worknode = node.getNode(helmaKey); worknode = node.getNode(helmaKey);
if (worknode == null) { if (worknode == null) {
// if virtual node doesn't exist, create it // if virtual node doesn't exist, create it
worknode = helmaNode.createNode(helmaKey); worknode = helmaNode.createNode(helmaKey);
} }
} }
if (DEBUG)
debug( "mounting child "+ childElement.getNodeName() + " at worknode " + worknode.toString() ); if (DEBUG) {
debug("mounting child " + childElement.getNodeName() +
" at worknode " + worknode.toString());
}
// now mount it, possibly re-using the helmaNode that's been created before // now mount it, possibly re-using the helmaNode that's been created before
if (newHelmaNode != null) { if (newHelmaNode != null) {
worknode.addNode(newHelmaNode); worknode.addNode(newHelmaNode);
@ -269,17 +443,24 @@ public class XmlConverter implements XmlConstants {
convert(childElement, worknode.createNode(null), nodeCache); convert(childElement, worknode.createNode(null), nodeCache);
} }
} }
// forget about other types (comments etc) // forget about other types (comments etc)
continue; continue;
} }
// if there's some text content for this element, map it: // if there's some text content for this element, map it:
if ( textcontent.length()>0 && !sparse ) { if ((textcontent.length() > 0) && !sparse) {
helmaKey = props.getProperty(element.getNodeName() + "._text"); helmaKey = props.getProperty(element.getNodeName() + "._text");
if ( helmaKey==null )
if (helmaKey == null) {
helmaKey = "text"; helmaKey = "text";
if (DEBUG) }
debug ("setting text "+textcontent+" to property "+helmaKey+" of object "+helmaNode);
if (DEBUG) {
debug("setting text " + textcontent + " to property " + helmaKey +
" of object " + helmaNode);
}
helmaNode.setString(helmaKey, textcontent.toString().trim()); helmaNode.setString(helmaKey, textcontent.toString().trim());
} }
@ -292,20 +473,27 @@ public class XmlConverter implements XmlConstants {
private INode attributes(Element element, INode helmaNode, Map nodeCache) { private INode attributes(Element element, INode helmaNode, Map nodeCache) {
NamedNodeMap nnm = element.getAttributes(); NamedNodeMap nnm = element.getAttributes();
int len = nnm.getLength(); int len = nnm.getLength();
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
org.w3c.dom.Node attr = nnm.item(i); org.w3c.dom.Node attr = nnm.item(i);
String helmaKey = props.getProperty(element.getNodeName()+"._attribute."+attr.getNodeName()); String helmaKey = props.getProperty(element.getNodeName() + "._attribute." +
attr.getNodeName());
// unless we only map explicit attributes, use attribute name as property name // unless we only map explicit attributes, use attribute name as property name
// in case no property name was defined. // in case no property name was defined.
if ( helmaKey==null && !sparse) if ((helmaKey == null) && !sparse) {
helmaKey = attr.getNodeName().replace(':', defaultSeparator); helmaKey = attr.getNodeName().replace(':', defaultSeparator);
}
if (helmaKey != null) { if (helmaKey != null) {
// check if the mapping contains the prototype to which // check if the mapping contains the prototype to which
// the property should be applied // the property should be applied
int dot = helmaKey.indexOf("."); int dot = helmaKey.indexOf(".");
if (dot > -1) { if (dot > -1) {
String prototype = helmaKey.substring(0, dot); String prototype = helmaKey.substring(0, dot);
INode node = (INode) nodeCache.get(prototype); INode node = (INode) nodeCache.get(prototype);
if (node != null) { if (node != null) {
node.setString(helmaKey.substring(dot + 1), attr.getNodeValue()); node.setString(helmaKey.substring(dot + 1), attr.getNodeValue());
} }
@ -314,6 +502,7 @@ public class XmlConverter implements XmlConstants {
} }
} }
} }
return helmaNode; return helmaNode;
} }
@ -324,22 +513,24 @@ public class XmlConverter implements XmlConstants {
if (props.containsKey("separator")) { if (props.containsKey("separator")) {
defaultSeparator = props.getProperty("separator").charAt(0); defaultSeparator = props.getProperty("separator").charAt(0);
} }
sparse = "sparse".equalsIgnoreCase(props.getProperty("_mode")); sparse = "sparse".equalsIgnoreCase(props.getProperty("_mode"));
} }
/** for testing */ /** for testing */
void debug(Object msg) { void debug(Object msg) {
for (int i = 0; i < offset; i++) { for (int i = 0; i < offset; i++) {
System.out.print(" "); System.out.print(" ");
} }
System.out.println(msg.toString()); System.out.println(msg.toString());
} }
/**
public static void main ( String args[] ) { *
*
* @param args ...
*/
public static void main(String[] args) {
} }
} }

View file

@ -1,100 +1,136 @@
/*
* Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.objectmodel.dom; package helma.objectmodel.dom;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.text.ParseException;
import java.util.Date;
// import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import javax.xml.parsers.*;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import helma.objectmodel.INode; import helma.objectmodel.INode;
import helma.objectmodel.db.DbKey; import helma.objectmodel.db.DbKey;
import helma.objectmodel.db.DbMapping;
import helma.objectmodel.db.ExternalizableVector; import helma.objectmodel.db.ExternalizableVector;
import helma.objectmodel.db.Node; import helma.objectmodel.db.Node;
import helma.objectmodel.db.NodeHandle; import helma.objectmodel.db.NodeHandle;
import helma.objectmodel.db.NodeManager; import helma.objectmodel.db.NodeManager;
import helma.objectmodel.db.Property; import helma.objectmodel.db.Property;
import helma.objectmodel.db.DbMapping; import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
// import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import javax.xml.parsers.*;
/**
*
*/
public final class XmlDatabaseReader extends DefaultHandler implements XmlConstants { public final class XmlDatabaseReader extends DefaultHandler implements XmlConstants {
static SAXParserFactory factory = SAXParserFactory.newInstance();
private NodeManager nmgr = null; private NodeManager nmgr = null;
private Node currentNode; private Node currentNode;
private String elementType = null; private String elementType = null;
private String elementName = null; private String elementName = null;
private StringBuffer charBuffer = null; private StringBuffer charBuffer = null;
Hashtable propMap = null; Hashtable propMap = null;
List subnodes = null; List subnodes = null;
static SAXParserFactory factory = SAXParserFactory.newInstance (); /**
* Creates a new XmlDatabaseReader object.
*
* @param nmgr ...
*/
public XmlDatabaseReader(NodeManager nmgr) { public XmlDatabaseReader(NodeManager nmgr) {
this.nmgr = nmgr; this.nmgr = nmgr;
} }
/** /**
* read an InputSource with xml-content. * read an InputSource with xml-content.
*/ */
public Node read(File file) public Node read(File file)
throws ParserConfigurationException, SAXException, IOException { throws ParserConfigurationException, SAXException, IOException {
if (nmgr==null) if (nmgr == null) {
throw new RuntimeException("can't create a new Node without a NodeManager"); throw new RuntimeException("can't create a new Node without a NodeManager");
}
SAXParser parser = factory.newSAXParser(); SAXParser parser = factory.newSAXParser();
currentNode = null; currentNode = null;
parser.parse(file, this); parser.parse(file, this);
return currentNode; return currentNode;
} }
/**
public void startElement(String namespaceURI, String localName, String qName, Attributes atts) { *
*
* @param namespaceURI ...
* @param localName ...
* @param qName ...
* @param atts ...
*/
public void startElement(String namespaceURI, String localName, String qName,
Attributes atts) {
// System.err.println ("XML-READ: startElement "+namespaceURI+", "+localName+", "+qName+", "+atts.getValue("id")); // System.err.println ("XML-READ: startElement "+namespaceURI+", "+localName+", "+qName+", "+atts.getValue("id"));
// discard the first element called xmlroot // discard the first element called xmlroot
if ("xmlroot".equals (qName) && currentNode == null) if ("xmlroot".equals(qName) && (currentNode == null)) {
return; return;
}
// if currentNode is null, this must be the hopobject node // if currentNode is null, this must be the hopobject node
if ("hopobject".equals (qName) && currentNode == null) { if ("hopobject".equals(qName) && (currentNode == null)) {
String id = atts.getValue("id"); String id = atts.getValue("id");
String name = atts.getValue("name"); String name = atts.getValue("name");
String prototype = atts.getValue("prototype"); String prototype = atts.getValue("prototype");
if ( "".equals(prototype) )
if ("".equals(prototype)) {
prototype = "hopobject"; prototype = "hopobject";
}
try { try {
long created = Long.parseLong(atts.getValue("created")); long created = Long.parseLong(atts.getValue("created"));
long lastmodified = Long.parseLong(atts.getValue("lastModified")); long lastmodified = Long.parseLong(atts.getValue("lastModified"));
currentNode = new Node (name,id,prototype,nmgr.safe,created,lastmodified);
currentNode = new Node(name, id, prototype, nmgr.safe, created,
lastmodified);
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
currentNode = new Node(name, id, prototype, nmgr.safe); currentNode = new Node(name, id, prototype, nmgr.safe);
} }
return; return;
} }
// find out what kind of element this is by looking at // find out what kind of element this is by looking at
// the number and names of attributes. // the number and names of attributes.
String idref = atts.getValue("idref"); String idref = atts.getValue("idref");
if (idref != null) { if (idref != null) {
// a hopobject reference. // a hopobject reference.
NodeHandle handle = makeNodeHandle(atts); NodeHandle handle = makeNodeHandle(atts);
if ("hop:child".equals(qName)) { if ("hop:child".equals(qName)) {
if (subnodes == null) { if (subnodes == null) {
subnodes = new ExternalizableVector(); subnodes = new ExternalizableVector();
currentNode.setSubnodes(subnodes); currentNode.setSubnodes(subnodes);
} }
subnodes.add(handle); subnodes.add(handle);
} else if ("hop:parent".equals(qName)) { } else if ("hop:parent".equals(qName)) {
currentNode.setParentHandle(handle); currentNode.setParentHandle(handle);
@ -102,46 +138,80 @@ public final class XmlDatabaseReader extends DefaultHandler implements XmlConsta
// property name may be encoded as "propertyname" attribute, // property name may be encoded as "propertyname" attribute,
// otherwise it is the element name // otherwise it is the element name
String propName = atts.getValue("propertyname"); String propName = atts.getValue("propertyname");
if (propName == null)
if (propName == null) {
propName = qName; propName = qName;
}
Property prop = new Property(propName, currentNode); Property prop = new Property(propName, currentNode);
prop.setNodeHandle(handle); prop.setNodeHandle(handle);
if (propMap == null) { if (propMap == null) {
propMap = new Hashtable(); propMap = new Hashtable();
currentNode.setPropMap(propMap); currentNode.setPropMap(propMap);
} }
propMap.put(propName.toLowerCase(), prop); propMap.put(propName.toLowerCase(), prop);
} }
} else { } else {
// a primitive property // a primitive property
elementType = atts.getValue("type"); elementType = atts.getValue("type");
if (elementType == null)
if (elementType == null) {
elementType = "string"; elementType = "string";
}
// property name may be encoded as "propertyname" attribute, // property name may be encoded as "propertyname" attribute,
// otherwise it is the element name // otherwise it is the element name
elementName = atts.getValue("propertyname"); elementName = atts.getValue("propertyname");
if (elementName == null)
if (elementName == null) {
elementName = qName; elementName = qName;
if (charBuffer == null) }
if (charBuffer == null) {
charBuffer = new StringBuffer(); charBuffer = new StringBuffer();
else } else {
charBuffer.setLength(0); charBuffer.setLength(0);
} }
} }
}
/**
*
*
* @param ch ...
* @param start ...
* @param length ...
*
* @throws SAXException ...
*/
public void characters(char[] ch, int start, int length) public void characters(char[] ch, int start, int length)
throws SAXException { throws SAXException {
// append chars to char buffer // append chars to char buffer
if (elementType != null) if (elementType != null) {
charBuffer.append(ch, start, length); charBuffer.append(ch, start, length);
} }
}
/**
*
*
* @param namespaceURI ...
* @param localName ...
* @param qName ...
*
* @throws SAXException ...
*/
public void endElement(String namespaceURI, String localName, String qName) public void endElement(String namespaceURI, String localName, String qName)
throws SAXException { throws SAXException {
if (elementType != null) { if (elementType != null) {
Property prop = new Property(elementName, currentNode); Property prop = new Property(elementName, currentNode);
String charValue = charBuffer.toString(); String charValue = charBuffer.toString();
charBuffer.setLength(0); charBuffer.setLength(0);
if ("boolean".equals(elementType)) { if ("boolean".equals(elementType)) {
if ("true".equals(charValue)) { if ("true".equals(charValue)) {
prop.setBooleanValue(true); prop.setBooleanValue(true);
@ -150,8 +220,10 @@ public final class XmlDatabaseReader extends DefaultHandler implements XmlConsta
} }
} else if ("date".equals(elementType)) { } else if ("date".equals(elementType)) {
SimpleDateFormat format = new SimpleDateFormat(DATEFORMAT); SimpleDateFormat format = new SimpleDateFormat(DATEFORMAT);
try { try {
Date date = format.parse(charValue); Date date = format.parse(charValue);
prop.setDateValue(date); prop.setDateValue(date);
} catch (ParseException e) { } catch (ParseException e) {
prop.setStringValue(charValue); prop.setStringValue(charValue);
@ -163,10 +235,12 @@ public final class XmlDatabaseReader extends DefaultHandler implements XmlConsta
} else { } else {
prop.setStringValue(charValue); prop.setStringValue(charValue);
} }
if (propMap == null) { if (propMap == null) {
propMap = new Hashtable(); propMap = new Hashtable();
currentNode.setPropMap(propMap); currentNode.setPropMap(propMap);
} }
propMap.put(elementName.toLowerCase(), prop); propMap.put(elementName.toLowerCase(), prop);
elementName = null; elementName = null;
elementType = null; elementType = null;
@ -174,16 +248,16 @@ public final class XmlDatabaseReader extends DefaultHandler implements XmlConsta
} }
} }
// create a node handle from a node reference DOM element // create a node handle from a node reference DOM element
private NodeHandle makeNodeHandle(Attributes atts) { private NodeHandle makeNodeHandle(Attributes atts) {
String idref = atts.getValue("idref"); String idref = atts.getValue("idref");
String protoref = atts.getValue("prototyperef"); String protoref = atts.getValue("prototyperef");
DbMapping dbmap = null; DbMapping dbmap = null;
if (protoref != null)
if (protoref != null) {
dbmap = nmgr.getDbMapping(protoref); dbmap = nmgr.getDbMapping(protoref);
}
return new NodeHandle(new DbKey(dbmap, idref)); return new NodeHandle(new DbKey(dbmap, idref));
} }
} }

View file

@ -1,43 +1,57 @@
/*
* Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.objectmodel.dom; package helma.objectmodel.dom;
import helma.objectmodel.INode;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.Reader; import java.io.Reader;
import java.text.SimpleDateFormat;
import java.text.ParseException; import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.Stack; import java.util.Stack;
import javax.xml.parsers.*; import javax.xml.parsers.*;
import org.xml.sax.*; /**
import org.xml.sax.helpers.DefaultHandler; *
*/
import helma.objectmodel.INode;
public final class XmlReader extends DefaultHandler implements XmlConstants { public final class XmlReader extends DefaultHandler implements XmlConstants {
static SAXParserFactory factory = SAXParserFactory.newInstance();
private INode rootNode, currentNode; private INode rootNode;
private INode currentNode;
private Stack nodeStack; private Stack nodeStack;
private HashMap convertedNodes; private HashMap convertedNodes;
private String elementType = null; private String elementType = null;
private String elementName = null; private String elementName = null;
private StringBuffer charBuffer = null; private StringBuffer charBuffer = null;
static SAXParserFactory factory = SAXParserFactory.newInstance ();
boolean parsingHopObject; boolean parsingHopObject;
/**
* Creates a new XmlReader object.
*/
public XmlReader() { public XmlReader() {
} }
/** /**
* main entry to read an xml-file. * main entry to read an xml-file.
*/ */
@ -47,6 +61,7 @@ public final class XmlReader extends DefaultHandler implements XmlConstants {
return read(new FileInputStream(file), helmaNode); return read(new FileInputStream(file), helmaNode);
} catch (FileNotFoundException notfound) { } catch (FileNotFoundException notfound) {
System.err.println("couldn't find xml-file: " + file.getAbsolutePath()); System.err.println("couldn't find xml-file: " + file.getAbsolutePath());
return helmaNode; return helmaNode;
} }
} }
@ -72,8 +87,9 @@ public final class XmlReader extends DefaultHandler implements XmlConstants {
*/ */
public INode read(InputSource in, INode helmaNode) public INode read(InputSource in, INode helmaNode)
throws ParserConfigurationException, SAXException, IOException { throws ParserConfigurationException, SAXException, IOException {
if (helmaNode==null) if (helmaNode == null) {
throw new RuntimeException("Can't create a new Node without a root Node"); throw new RuntimeException("Can't create a new Node without a root Node");
}
SAXParser parser = factory.newSAXParser(); SAXParser parser = factory.newSAXParser();
@ -84,18 +100,31 @@ public final class XmlReader extends DefaultHandler implements XmlConstants {
parsingHopObject = true; parsingHopObject = true;
parser.parse(in, this); parser.parse(in, this);
return rootNode; return rootNode;
} }
/**
public void startElement(String namespaceURI, String localName, String qName, Attributes atts) *
throws SAXException { *
* @param namespaceURI ...
* @param localName ...
* @param qName ...
* @param atts ...
*
* @throws SAXException ...
*/
public void startElement(String namespaceURI, String localName, String qName,
Attributes atts) throws SAXException {
// System.err.println ("XML-READ: startElement "+namespaceURI+", "+localName+", "+qName+", "+atts.getValue("id")); // System.err.println ("XML-READ: startElement "+namespaceURI+", "+localName+", "+qName+", "+atts.getValue("id"));
// discard the first element called xmlroot // discard the first element called xmlroot
if ("xmlroot".equals (qName) && currentNode == null) if ("xmlroot".equals(qName) && (currentNode == null)) {
return; return;
}
// if currentNode is null, this must be the hopobject node // if currentNode is null, this must be the hopobject node
String id = atts.getValue("id"); String id = atts.getValue("id");
if (id != null) { if (id != null) {
// check if there is a current node. // check if there is a current node.
if (currentNode == null) { if (currentNode == null) {
@ -108,30 +137,43 @@ public final class XmlReader extends DefaultHandler implements XmlConstants {
} else { } else {
// it's a named node property // it's a named node property
nodeStack.push(currentNode); nodeStack.push(currentNode);
// property name may be encoded as "propertyname" attribute, // property name may be encoded as "propertyname" attribute,
// otherwise it is the element name // otherwise it is the element name
String propName = atts.getValue("propertyname"); String propName = atts.getValue("propertyname");
if (propName == null)
if (propName == null) {
propName = qName; propName = qName;
}
currentNode = currentNode.createNode(propName); currentNode = currentNode.createNode(propName);
} }
// set the prototype on the current node and // set the prototype on the current node and
// add it to the map of parsed nodes. // add it to the map of parsed nodes.
String prototype = atts.getValue("prototype"); String prototype = atts.getValue("prototype");
if ( !"".equals(prototype) && !"hopobject".equals(prototype) )
if (!"".equals(prototype) && !"hopobject".equals(prototype)) {
currentNode.setPrototype(prototype); currentNode.setPrototype(prototype);
}
String key = id + "-" + prototype; String key = id + "-" + prototype;
convertedNodes.put(key, currentNode); convertedNodes.put(key, currentNode);
return; return;
} }
// check if we have a currentNode to set properties on, // check if we have a currentNode to set properties on,
// otherwise throw exception. // otherwise throw exception.
if (currentNode == null) if (currentNode == null) {
throw new SAXException("Invalid XML: No valid root HopObject found"); throw new SAXException("Invalid XML: No valid root HopObject found");
}
// check if we are inside a HopObject - otherwise throw an exception // check if we are inside a HopObject - otherwise throw an exception
if (!parsingHopObject) if (!parsingHopObject) {
throw new SAXException("Invalid XML: Found nested non-HobObject elements"); throw new SAXException("Invalid XML: Found nested non-HobObject elements");
}
// if we got so far, the element is not a hopobject. Set flag to prevent // if we got so far, the element is not a hopobject. Set flag to prevent
// the hopobject stack to be popped when the element // the hopobject stack to be popped when the element
@ -140,12 +182,14 @@ public final class XmlReader extends DefaultHandler implements XmlConstants {
// Is it a reference to an already parsed node? // Is it a reference to an already parsed node?
String idref = atts.getValue("idref"); String idref = atts.getValue("idref");
if (idref != null) { if (idref != null) {
// a reference to a node that should have been parsed // a reference to a node that should have been parsed
// and lying in our cache of parsed nodes. // and lying in our cache of parsed nodes.
String prototyperef = atts.getValue("prototyperef"); String prototyperef = atts.getValue("prototyperef");
String key = idref + "-" + prototyperef; String key = idref + "-" + prototyperef;
INode n = (INode) convertedNodes.get(key); INode n = (INode) convertedNodes.get(key);
if (n != null) { if (n != null) {
if ("hop:child".equals(qName)) { if ("hop:child".equals(qName)) {
// add an already parsed node as child to current node // add an already parsed node as child to current node
@ -155,8 +199,11 @@ public final class XmlReader extends DefaultHandler implements XmlConstants {
// property name may be encoded as "propertyname" attribute, // property name may be encoded as "propertyname" attribute,
// otherwise it is the element name // otherwise it is the element name
String propName = atts.getValue("propertyname"); String propName = atts.getValue("propertyname");
if (propName == null)
if (propName == null) {
propName = qName; propName = qName;
}
currentNode.setNode(propName, n); currentNode.setNode(propName, n);
} }
} }
@ -165,32 +212,61 @@ public final class XmlReader extends DefaultHandler implements XmlConstants {
// so we can properly parse/interpret the character data when we // so we can properly parse/interpret the character data when we
// get it later on. // get it later on.
elementType = atts.getValue("type"); elementType = atts.getValue("type");
if (elementType == null)
if (elementType == null) {
elementType = "string"; elementType = "string";
}
// property name may be encoded as "propertyname" attribute, // property name may be encoded as "propertyname" attribute,
// otherwise it is the element name // otherwise it is the element name
elementName = atts.getValue("propertyname"); elementName = atts.getValue("propertyname");
if (elementName == null)
if (elementName == null) {
elementName = qName; elementName = qName;
if (charBuffer == null) }
if (charBuffer == null) {
charBuffer = new StringBuffer(); charBuffer = new StringBuffer();
else } else {
charBuffer.setLength(0); charBuffer.setLength(0);
} }
} }
public void characters (char[] ch, int start, int length) throws SAXException {
// System.err.println ("CHARACTERS: "+new String (ch, start, length));
// append chars to char buffer
if (elementType != null)
charBuffer.append (ch, start, length);
} }
/**
*
*
* @param ch ...
* @param start ...
* @param length ...
*
* @throws SAXException ...
*/
public void characters(char[] ch, int start, int length)
throws SAXException {
// System.err.println ("CHARACTERS: "+new String (ch, start, length));
// append chars to char buffer
if (elementType != null) {
charBuffer.append(ch, start, length);
}
}
/**
*
*
* @param namespaceURI ...
* @param localName ...
* @param qName ...
*
* @throws SAXException ...
*/
public void endElement(String namespaceURI, String localName, String qName) public void endElement(String namespaceURI, String localName, String qName)
throws SAXException { throws SAXException {
if (elementType != null) { if (elementType != null) {
String charValue = charBuffer.toString(); String charValue = charBuffer.toString();
charBuffer.setLength(0); charBuffer.setLength(0);
if ("boolean".equals(elementType)) { if ("boolean".equals(elementType)) {
if ("true".equals(charValue)) { if ("true".equals(charValue)) {
currentNode.setBoolean(elementName, true); currentNode.setBoolean(elementName, true);
@ -199,8 +275,10 @@ public final class XmlReader extends DefaultHandler implements XmlConstants {
} }
} else if ("date".equals(elementType)) { } else if ("date".equals(elementType)) {
SimpleDateFormat format = new SimpleDateFormat(DATEFORMAT); SimpleDateFormat format = new SimpleDateFormat(DATEFORMAT);
try { try {
Date date = format.parse(charValue); Date date = format.parse(charValue);
currentNode.setDate(elementName, date); currentNode.setDate(elementName, date);
} catch (ParseException e) { } catch (ParseException e) {
currentNode.setString(elementName, charValue); currentNode.setString(elementName, charValue);
@ -212,15 +290,16 @@ public final class XmlReader extends DefaultHandler implements XmlConstants {
} else { } else {
currentNode.setString(elementName, charValue); currentNode.setString(elementName, charValue);
} }
elementName = null; elementName = null;
elementType = null; elementType = null;
charValue = null; charValue = null;
} }
if (parsingHopObject && !nodeStack.isEmpty ())
if (parsingHopObject && !nodeStack.isEmpty()) {
currentNode = (INode) nodeStack.pop(); currentNode = (INode) nodeStack.pop();
else } else {
parsingHopObject = true; // the next element end tag closes a hopobject again parsingHopObject = true; // the next element end tag closes a hopobject again
} }
} }
}

View file

@ -1,37 +1,53 @@
/*
* Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.objectmodel.dom; package helma.objectmodel.dom;
import java.io.InputStream; import helma.objectmodel.INode;
import java.io.IOException; import helma.objectmodel.TransientNode;
import java.util.WeakHashMap;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.w3c.dom.Element; import org.w3c.dom.Element;
import org.w3c.dom.Node; import org.w3c.dom.Node;
import org.w3c.dom.NodeList; import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import org.xml.sax.InputSource; import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import java.io.IOException;
import java.io.InputStream;
import java.util.WeakHashMap;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import helma.objectmodel.INode; /**
import helma.objectmodel.TransientNode; *
*/
public class XmlUtil { public class XmlUtil {
private static final DocumentBuilderFactory domBuilderFactory = javax.xml.parsers.DocumentBuilderFactory.newInstance(); private static final DocumentBuilderFactory domBuilderFactory = javax.xml.parsers.DocumentBuilderFactory.newInstance();
private static final WeakHashMap domBuilders = new WeakHashMap(); private static final WeakHashMap domBuilders = new WeakHashMap();
private static synchronized DocumentBuilder getDocumentBuilder() { private static synchronized DocumentBuilder getDocumentBuilder() {
DocumentBuilder domBuilder = (DocumentBuilder) domBuilders.get(Thread.currentThread()); DocumentBuilder domBuilder = (DocumentBuilder) domBuilders.get(Thread.currentThread());
if (domBuilder != null) { if (domBuilder != null) {
return domBuilder; return domBuilder;
} else { } else {
try { try {
domBuilder = domBuilderFactory.newDocumentBuilder(); domBuilder = domBuilderFactory.newDocumentBuilder();
domBuilders.put(Thread.currentThread(), domBuilder); domBuilders.put(Thread.currentThread(), domBuilder);
return domBuilder; return domBuilder;
} catch (ParserConfigurationException e) { } catch (ParserConfigurationException e) {
throw new RuntimeException("Cannot build parser: " + e.toString()); throw new RuntimeException("Cannot build parser: " + e.toString());
@ -39,16 +55,34 @@ public class XmlUtil {
} }
} }
/**
*
*
* @return ...
*/
public static Document newDocument() { public static Document newDocument() {
DocumentBuilder d = getDocumentBuilder(); DocumentBuilder d = getDocumentBuilder();
return d.newDocument(); return d.newDocument();
} }
/**
*
*
* @param in ...
*
* @return ...
*
* @throws RuntimeException ...
*/
public static Document parse(InputStream in) throws RuntimeException { public static Document parse(InputStream in) throws RuntimeException {
DocumentBuilder d = getDocumentBuilder(); DocumentBuilder d = getDocumentBuilder();
try { try {
Document doc = d.parse(in); Document doc = d.parse(in);
doc.normalize(); doc.normalize();
return doc; return doc;
} catch (SAXException e) { } catch (SAXException e) {
throw new RuntimeException("Bad xml-code: " + e.toString()); throw new RuntimeException("Bad xml-code: " + e.toString());
@ -57,11 +91,23 @@ public class XmlUtil {
} }
} }
/**
*
*
* @param in ...
*
* @return ...
*
* @throws RuntimeException ...
*/
public static Document parse(InputSource in) throws RuntimeException { public static Document parse(InputSource in) throws RuntimeException {
DocumentBuilder d = getDocumentBuilder(); DocumentBuilder d = getDocumentBuilder();
try { try {
Document doc = d.parse(in); Document doc = d.parse(in);
doc.normalize(); doc.normalize();
return doc; return doc;
} catch (SAXException e) { } catch (SAXException e) {
throw new RuntimeException("Bad xml-code: " + e.toString()); throw new RuntimeException("Bad xml-code: " + e.toString());
@ -75,16 +121,21 @@ public class XmlUtil {
*/ */
public static Element getFirstElement(Document document) { public static Element getFirstElement(Document document) {
Element workelement = null; Element workelement = null;
if (document.getDocumentElement() != null) { if (document.getDocumentElement() != null) {
org.w3c.dom.Node tmp = document.getDocumentElement().getFirstChild(); org.w3c.dom.Node tmp = document.getDocumentElement().getFirstChild();
while (tmp != null) { while (tmp != null) {
tmp = tmp.getNextSibling(); tmp = tmp.getNextSibling();
if (tmp.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) { if (tmp.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
workelement = (Element) tmp; workelement = (Element) tmp;
break; break;
} }
} }
} }
return workelement; return workelement;
} }
@ -95,15 +146,16 @@ public class XmlUtil {
StringBuffer childtext = new StringBuffer(); StringBuffer childtext = new StringBuffer();
NodeList childlist = element.getChildNodes(); NodeList childlist = element.getChildNodes();
int ct = childlist.getLength(); int ct = childlist.getLength();
for (int j = 0; j < ct; j++) { for (int j = 0; j < ct; j++) {
org.w3c.dom.Node childNode = childlist.item(j); org.w3c.dom.Node childNode = childlist.item(j);
if ( childNode.getNodeType() == Node.TEXT_NODE ||
childNode.getNodeType() == Node.CDATA_SECTION_NODE) { if ((childNode.getNodeType() == Node.TEXT_NODE) ||
(childNode.getNodeType() == Node.CDATA_SECTION_NODE)) {
childtext.append(childNode.getNodeValue().trim()); childtext.append(childNode.getNodeValue().trim());
} }
} }
return childtext.toString(); return childtext.toString();
} }
} }

View file

@ -1,5 +1,30 @@
/*
* Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.objectmodel.dom; package helma.objectmodel.dom;
// import java.util.Set;
import helma.objectmodel.*;
import helma.objectmodel.INode;
import helma.objectmodel.IProperty;
import helma.objectmodel.TransientNode;
import helma.objectmodel.db.DbMapping;
import helma.objectmodel.db.Node;
import helma.util.HtmlEncoder;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.FileOutputStream; import java.io.FileOutputStream;
@ -12,35 +37,105 @@ import java.util.Date;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.Vector; import java.util.Vector;
// import java.util.Set;
import helma.objectmodel.*;
import helma.objectmodel.INode;
import helma.objectmodel.IProperty;
import helma.objectmodel.TransientNode;
import helma.objectmodel.db.Node;
import helma.objectmodel.db.DbMapping;
import helma.util.HtmlEncoder;
/**
*
*/
public class XmlWriter extends OutputStreamWriter implements XmlConstants { public class XmlWriter extends OutputStreamWriter implements XmlConstants {
private final static String LINESEPARATOR = System.getProperty("line.separator"); private final static String LINESEPARATOR = System.getProperty("line.separator");
private static int fileid;
private Vector convertedNodes; private Vector convertedNodes;
private int maxLevels = 3; private int maxLevels = 3;
private String indent = " "; private String indent = " ";
private StringBuffer prefix = new StringBuffer(); private StringBuffer prefix = new StringBuffer();
private static int fileid;
private SimpleDateFormat format = new SimpleDateFormat(DATEFORMAT); private SimpleDateFormat format = new SimpleDateFormat(DATEFORMAT);
private boolean dbmode = true; private boolean dbmode = true;
// Only add encoding to XML declaration if it was explicitly set, not when we're using // Only add encoding to XML declaration if it was explicitly set, not when we're using
// the platform's standard encoding. // the platform's standard encoding.
private String explicitEncoding; private String explicitEncoding;
/**
* empty constructor, will use System.out as outputstream.
*/
public XmlWriter() {
super(System.out);
}
/**
* Creates a new XmlWriter object.
*
* @param out ...
*/
public XmlWriter(OutputStream out) {
super(out);
}
/**
* Creates a new XmlWriter object.
*
* @param out ...
* @param enc ...
*
* @throws UnsupportedEncodingException ...
*/
public XmlWriter(OutputStream out, String enc) throws UnsupportedEncodingException {
super(out, enc);
explicitEncoding = enc;
}
/**
* Creates a new XmlWriter object.
*
* @param desc ...
*
* @throws FileNotFoundException ...
*/
public XmlWriter(String desc) throws FileNotFoundException {
super(new FileOutputStream(desc));
}
/**
* Creates a new XmlWriter object.
*
* @param desc ...
* @param enc ...
*
* @throws FileNotFoundException ...
* @throws UnsupportedEncodingException ...
*/
public XmlWriter(String desc, String enc)
throws FileNotFoundException, UnsupportedEncodingException {
super(new FileOutputStream(desc), enc);
explicitEncoding = enc;
}
/**
* Creates a new XmlWriter object.
*
* @param file ...
*
* @throws FileNotFoundException ...
*/
public XmlWriter(File file) throws FileNotFoundException {
super(new FileOutputStream(file));
}
/**
* Creates a new XmlWriter object.
*
* @param file ...
* @param enc ...
*
* @throws FileNotFoundException ...
* @throws UnsupportedEncodingException ...
*/
public XmlWriter(File file, String enc)
throws FileNotFoundException, UnsupportedEncodingException {
super(new FileOutputStream(file), enc);
explicitEncoding = enc;
}
// Set of prototypes at which to stop writing. // Set of prototypes at which to stop writing.
// private Set stopTypes = null; // private Set stopTypes = null;
@ -51,40 +146,6 @@ public class XmlWriter extends OutputStreamWriter implements XmlConstants {
return fileid++; return fileid++;
} }
/**
* empty constructor, will use System.out as outputstream.
*/
public XmlWriter () {
super(System.out);
}
public XmlWriter (OutputStream out) {
super(out);
}
public XmlWriter (OutputStream out, String enc) throws UnsupportedEncodingException {
super(out, enc);
explicitEncoding = enc;
}
public XmlWriter (String desc) throws FileNotFoundException {
super (new FileOutputStream (desc));
}
public XmlWriter (String desc, String enc) throws FileNotFoundException, UnsupportedEncodingException {
super (new FileOutputStream (desc), enc);
explicitEncoding = enc;
}
public XmlWriter (File file) throws FileNotFoundException {
super (new FileOutputStream (file));
}
public XmlWriter (File file, String enc) throws FileNotFoundException, UnsupportedEncodingException {
super (new FileOutputStream (file), enc);
explicitEncoding = enc;
}
/** /**
* by default writing only descends 50 levels into the node tree to prevent * by default writing only descends 50 levels into the node tree to prevent
* infite loops. number can be changed here. * infite loops. number can be changed here.
@ -93,6 +154,11 @@ public class XmlWriter extends OutputStreamWriter implements XmlConstants {
maxLevels = levels; maxLevels = levels;
} }
/**
*
*
* @param dbmode ...
*/
public void setDatabaseMode(boolean dbmode) { public void setDatabaseMode(boolean dbmode) {
this.dbmode = dbmode; this.dbmode = dbmode;
} }
@ -100,6 +166,7 @@ public class XmlWriter extends OutputStreamWriter implements XmlConstants {
/** /**
* Set a group of prototypes at which to stop XML serialization. * Set a group of prototypes at which to stop XML serialization.
*/ */
/* public void setStopTypes (Set set) { /* public void setStopTypes (Set set) {
this.stopTypes = set; this.stopTypes = set;
} */ } */
@ -109,9 +176,11 @@ public class XmlWriter extends OutputStreamWriter implements XmlConstants {
*/ */
public void setIndent(int ct) { public void setIndent(int ct) {
StringBuffer tmp = new StringBuffer(); StringBuffer tmp = new StringBuffer();
for (int i = 0; i < ct; i++) { for (int i = 0; i < ct; i++) {
tmp.append(" "); tmp.append(" ");
} }
indent = tmp.toString(); indent = tmp.toString();
} }
@ -122,10 +191,13 @@ public class XmlWriter extends OutputStreamWriter implements XmlConstants {
*/ */
public boolean write(INode node) throws IOException { public boolean write(INode node) throws IOException {
convertedNodes = new Vector(); convertedNodes = new Vector();
if (explicitEncoding == null)
if (explicitEncoding == null) {
writeln("<?xml version=\"1.0\"?>"); writeln("<?xml version=\"1.0\"?>");
else } else {
writeln("<?xml version=\"1.0\" encoding=\"" + explicitEncoding + "\"?>"); writeln("<?xml version=\"1.0\" encoding=\"" + explicitEncoding + "\"?>");
}
// writeln ("<!-- printed by helma object publisher -->"); // writeln ("<!-- printed by helma object publisher -->");
// writeln ("<!-- created " + (new Date()).toString() + " -->" ); // writeln ("<!-- created " + (new Date()).toString() + " -->" );
write("<xmlroot xmlns:hop=\""); write("<xmlroot xmlns:hop=\"");
@ -134,6 +206,7 @@ public class XmlWriter extends OutputStreamWriter implements XmlConstants {
write(node, null, null, 0); write(node, null, null, 0);
writeln("</xmlroot>"); writeln("</xmlroot>");
convertedNodes = null; convertedNodes = null;
return true; return true;
} }
@ -142,58 +215,76 @@ public class XmlWriter extends OutputStreamWriter implements XmlConstants {
* references are made here if a node already has been fully printed * references are made here if a node already has been fully printed
* or if this is the last level that's going to be dumped * or if this is the last level that's going to be dumped
*/ */
public void write (INode node, String elementName, String propName, int level) throws IOException { public void write(INode node, String elementName, String propName, int level)
if (node==null) throws IOException {
if (node == null) {
return; return;
}
// if (stopTypes != null && stopTypes.contains (node.getPrototype())) // if (stopTypes != null && stopTypes.contains (node.getPrototype()))
// return; // return;
int previousLength = prefix.length(); int previousLength = prefix.length();
prefix.append(indent); prefix.append(indent);
if (++level > maxLevels) { if (++level > maxLevels) {
writeReferenceTag(node, elementName, propName); writeReferenceTag(node, elementName, propName);
prefix.setLength(previousLength); prefix.setLength(previousLength);
return; return;
} }
if (convertedNodes.contains(node)) { if (convertedNodes.contains(node)) {
writeReferenceTag(node, elementName, propName); writeReferenceTag(node, elementName, propName);
} else { } else {
convertedNodes.addElement(node); convertedNodes.addElement(node);
writeTagOpen(node, elementName, propName); writeTagOpen(node, elementName, propName);
INode parent = node.getParent(); INode parent = node.getParent();
if (parent != null) { if (parent != null) {
writeReferenceTag(parent, "hop:parent", null); writeReferenceTag(parent, "hop:parent", null);
} }
writeProperties(node, level); writeProperties(node, level);
writeChildren(node, level); writeChildren(node, level);
writeTagClose(elementName); writeTagClose(elementName);
} }
prefix.setLength(previousLength); prefix.setLength(previousLength);
} }
/** /**
* loop through properties and print them with their property-name * loop through properties and print them with their property-name
* as elementname * as elementname
*/ */
private void writeProperties (INode node, int level) throws IOException { private void writeProperties(INode node, int level)
throws IOException {
Enumeration e = null; Enumeration e = null;
if ( dbmode==true && node instanceof helma.objectmodel.db.Node ) {
if ((dbmode == true) && node instanceof helma.objectmodel.db.Node) {
// a newly constructed db.Node doesn't have a propMap, // a newly constructed db.Node doesn't have a propMap,
// but returns an enumeration of all it's db-mapped properties // but returns an enumeration of all it's db-mapped properties
Hashtable props = ((Node) node).getPropMap(); Hashtable props = ((Node) node).getPropMap();
if (props==null)
if (props == null) {
return; return;
}
e = props.keys(); e = props.keys();
} else { } else {
e = node.properties(); e = node.properties();
} }
while (e.hasMoreElements()) { while (e.hasMoreElements()) {
String key = (String) e.nextElement(); String key = (String) e.nextElement();
IProperty prop = node.get(key); IProperty prop = node.get(key);
if (prop != null) { if (prop != null) {
boolean validName = isValidElementName(key); boolean validName = isValidElementName(key);
String elementName, propName; String elementName;
String propName;
if (validName) { if (validName) {
elementName = key; elementName = key;
propName = null; propName = null;
@ -201,7 +292,9 @@ public class XmlWriter extends OutputStreamWriter implements XmlConstants {
elementName = "property"; elementName = "property";
propName = key; propName = key;
} }
int type = prop.getType(); int type = prop.getType();
if (type == IProperty.NODE) { if (type == IProperty.NODE) {
write(prop.getNodeValue(), elementName, propName, level); write(prop.getNodeValue(), elementName, propName, level);
} else { } else {
@ -224,43 +317,61 @@ public class XmlWriter extends OutputStreamWriter implements XmlConstants {
* write a single property, set attribute type according to type, * write a single property, set attribute type according to type,
* apply xml-encoding. * apply xml-encoding.
*/ */
public void writeProperty (IProperty property, String elementName, String propName) throws IOException { public void writeProperty(IProperty property, String elementName, String propName)
throws IOException {
int propType = property.getType(); int propType = property.getType();
// we can't encode java objects in XML // we can't encode java objects in XML
if (propType == IProperty.JAVAOBJECT) if (propType == IProperty.JAVAOBJECT) {
return; return;
}
write(prefix.toString()); write(prefix.toString());
write(indent); write(indent);
write("<"); write("<");
write(elementName); write(elementName);
if (propName != null) { if (propName != null) {
write(" propertyname=\""); write(" propertyname=\"");
write(HtmlEncoder.encodeXml(propName)); write(HtmlEncoder.encodeXml(propName));
write("\""); write("\"");
} }
switch (propType) { switch (propType) {
case IProperty.BOOLEAN: case IProperty.BOOLEAN:
write(" type=\"boolean\">"); write(" type=\"boolean\">");
write(property.getStringValue()); write(property.getStringValue());
break; break;
case IProperty.FLOAT: case IProperty.FLOAT:
write(" type=\"float\">"); write(" type=\"float\">");
write(property.getStringValue()); write(property.getStringValue());
break; break;
case IProperty.INTEGER: case IProperty.INTEGER:
write(" type=\"integer\">"); write(" type=\"integer\">");
write(property.getStringValue()); write(property.getStringValue());
break; break;
case IProperty.DATE: case IProperty.DATE:
write(" type=\"date\">"); write(" type=\"date\">");
write(format.format(property.getDateValue())); write(format.format(property.getDateValue()));
break; break;
case IProperty.STRING: case IProperty.STRING:
write(">"); write(">");
String str = HtmlEncoder.encodeXml(property.getStringValue()); String str = HtmlEncoder.encodeXml(property.getStringValue());
if (str != null)
if (str != null) {
write(str); write(str);
} }
}
write("</"); write("</");
write(elementName); write(elementName);
write(">"); write(">");
@ -271,15 +382,22 @@ public class XmlWriter extends OutputStreamWriter implements XmlConstants {
* loop through the children-array and print them as <hop:child> * loop through the children-array and print them as <hop:child>
*/ */
private void writeChildren(INode node, int level) throws IOException { private void writeChildren(INode node, int level) throws IOException {
if ( dbmode==true && node instanceof helma.objectmodel.db.Node ) { if ((dbmode == true) && node instanceof helma.objectmodel.db.Node) {
Node dbNode = (Node) node; Node dbNode = (Node) node;
DbMapping smap = dbNode.getDbMapping() == null ? null : dbNode.getDbMapping().getSubnodeMapping (); DbMapping smap = (dbNode.getDbMapping() == null) ? null
if (smap != null && smap.isRelational ()) : dbNode.getDbMapping()
.getSubnodeMapping();
if ((smap != null) && smap.isRelational()) {
return; return;
} }
}
Enumeration e = node.getSubnodes(); Enumeration e = node.getSubnodes();
while (e.hasMoreElements()) { while (e.hasMoreElements()) {
INode nextNode = (INode) e.nextElement(); INode nextNode = (INode) e.nextElement();
write(nextNode, "hop:child", null, level); write(nextNode, "hop:child", null, level);
} }
} }
@ -288,16 +406,19 @@ public class XmlWriter extends OutputStreamWriter implements XmlConstants {
* write an opening tag for a node. Include id and prototype, use a * write an opening tag for a node. Include id and prototype, use a
* name if parameter is non-empty. * name if parameter is non-empty.
*/ */
public void writeTagOpen (INode node, String name, String propName) throws IOException { public void writeTagOpen(INode node, String name, String propName)
throws IOException {
write(prefix.toString()); write(prefix.toString());
write("<"); write("<");
write((name == null) ? "hopobject" : name); write((name == null) ? "hopobject" : name);
write(" id=\""); write(" id=\"");
write(getNodeIdentifier(node)); write(getNodeIdentifier(node));
if (propName != null) { if (propName != null) {
write("\" propertyname=\""); write("\" propertyname=\"");
write(HtmlEncoder.encodeXml(propName)); write(HtmlEncoder.encodeXml(propName));
} }
write("\" name=\""); write("\" name=\"");
write(node.getName()); write(node.getName());
write("\" prototype=\""); write("\" prototype=\"");
@ -306,6 +427,7 @@ public class XmlWriter extends OutputStreamWriter implements XmlConstants {
write(Long.toString(node.created())); write(Long.toString(node.created()));
write("\" lastModified=\""); write("\" lastModified=\"");
write(Long.toString(node.lastModified())); write(Long.toString(node.lastModified()));
//FIXME: do we need anonymous-property? //FIXME: do we need anonymous-property?
write("\">"); write("\">");
write(LINESEPARATOR); write(LINESEPARATOR);
@ -328,16 +450,19 @@ public class XmlWriter extends OutputStreamWriter implements XmlConstants {
* been written out before. * been written out before.
* e.g. <parent idref="35" prototyperef="hopobject"/> * e.g. <parent idref="35" prototyperef="hopobject"/>
*/ */
public void writeReferenceTag (INode node, String name, String propName) throws IOException { public void writeReferenceTag(INode node, String name, String propName)
throws IOException {
write(prefix.toString()); write(prefix.toString());
write("<"); write("<");
write((name == null) ? "hopobject" : name); write((name == null) ? "hopobject" : name);
write(" idref=\""); write(" idref=\"");
write(getNodeIdentifier(node)); write(getNodeIdentifier(node));
if (propName != null) { if (propName != null) {
write("\" propertyname=\""); write("\" propertyname=\"");
write(HtmlEncoder.encodeXml(propName)); write(HtmlEncoder.encodeXml(propName));
} }
write("\" prototyperef=\""); write("\" prototyperef=\"");
write(getNodePrototype(node)); write(getNodePrototype(node));
write("\"/>"); write("\"/>");
@ -348,7 +473,7 @@ public class XmlWriter extends OutputStreamWriter implements XmlConstants {
* retrieve prototype-string of a node, defaults to "hopobject" * retrieve prototype-string of a node, defaults to "hopobject"
*/ */
private String getNodePrototype(INode node) { private String getNodePrototype(INode node) {
if ( node.getPrototype()==null || "".equals(node.getPrototype()) ) { if ((node.getPrototype() == null) || "".equals(node.getPrototype())) {
return "hopobject"; return "hopobject";
} else { } else {
return node.getPrototype(); return node.getPrototype();
@ -362,18 +487,25 @@ public class XmlWriter extends OutputStreamWriter implements XmlConstants {
private String getNodeIdentifier(INode node) { private String getNodeIdentifier(INode node) {
try { try {
TransientNode tmp = (TransientNode) node; TransientNode tmp = (TransientNode) node;
return Integer.toString(tmp.hashCode()); return Integer.toString(tmp.hashCode());
} catch (ClassCastException e) { } catch (ClassCastException e) {
return node.getID(); return node.getID();
} }
} }
/**
*
*
* @param str ...
*
* @throws IOException ...
*/
public void writeln(String str) throws IOException { public void writeln(String str) throws IOException {
write(str); write(str);
write(LINESEPARATOR); write(LINESEPARATOR);
} }
/** /**
* Check if a string is usable as XML element name. If not, the name * Check if a string is usable as XML element name. If not, the name
* will be appended as attribute to the XML element. We are * will be appended as attribute to the XML element. We are
@ -382,15 +514,21 @@ public class XmlWriter extends OutputStreamWriter implements XmlConstants {
*/ */
private boolean isValidElementName(String str) { private boolean isValidElementName(String str) {
char c = str.charAt(0); char c = str.charAt(0);
if (!Character.isLetter(c))
return false; if (!Character.isLetter(c)) {
int l = str.length();
for (int i=1; i<l; i++) {
c = str.charAt (i);
if (!Character.isLetterOrDigit(c) && c != '-' && c != '_')
return false; return false;
} }
return true;
int l = str.length();
for (int i = 1; i < l; i++) {
c = str.charAt(i);
if (!Character.isLetterOrDigit(c) && (c != '-') && (c != '_')) {
return false;
} }
} }
return true;
}
}

View file

@ -1,15 +1,27 @@
// ActionFile.java /*
// Copyright (c) Helma.org 1998-2002 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.scripting; package helma.scripting;
import java.util.Vector;
import java.util.Iterator;
import java.io.*;
import helma.framework.*; import helma.framework.*;
import helma.framework.core.*; import helma.framework.core.*;
import helma.util.Updatable; import helma.util.Updatable;
import java.io.*;
import java.util.Iterator;
import java.util.Vector;
/** /**
* An ActionFile is a file containing function code that is exposed as a URI * An ActionFile is a file containing function code that is exposed as a URI
@ -17,18 +29,22 @@ import helma.util.Updatable;
* usually represented by a file with extension .hac (hop action file) * usually represented by a file with extension .hac (hop action file)
* that contains the raw body of the function. * that contains the raw body of the function.
*/ */
public class ActionFile implements Updatable { public class ActionFile implements Updatable {
String name;
String name, sourceName; String sourceName;
Prototype prototype; Prototype prototype;
Application app; Application app;
File file; File file;
String content; String content;
long lastmod; long lastmod;
/**
* Creates a new ActionFile object.
*
* @param file ...
* @param name ...
* @param proto ...
*/
public ActionFile(File file, String name, Prototype proto) { public ActionFile(File file, String name, Prototype proto) {
this.prototype = proto; this.prototype = proto;
this.app = proto.getApplication(); this.app = proto.getApplication();
@ -39,6 +55,14 @@ public class ActionFile implements Updatable {
this.content = null; this.content = null;
} }
/**
* Creates a new ActionFile object.
*
* @param content ...
* @param name ...
* @param sourceName ...
* @param proto ...
*/
public ActionFile(String content, String name, String sourceName, Prototype proto) { public ActionFile(String content, String name, String sourceName, Prototype proto) {
this.prototype = proto; this.prototype = proto;
this.app = proto.getApplication(); this.app = proto.getApplication();
@ -48,7 +72,6 @@ public class ActionFile implements Updatable {
this.content = content; this.content = content;
} }
/** /**
* Tell the type manager whether we need an update. this is the case when * Tell the type manager whether we need an update. this is the case when
* the file has been modified or deleted. * the file has been modified or deleted.
@ -57,7 +80,9 @@ public class ActionFile implements Updatable {
return lastmod != file.lastModified(); return lastmod != file.lastModified();
} }
/**
*
*/
public void update() { public void update() {
if (!file.exists()) { if (!file.exists()) {
// remove functions declared by this from all object prototypes // remove functions declared by this from all object prototypes
@ -67,64 +92,115 @@ public class ActionFile implements Updatable {
} }
} }
/**
*
*/
public void remove() { public void remove() {
prototype.removeActionFile(this); prototype.removeActionFile(this);
} }
/**
*
*
* @return ...
*/
public File getFile() { public File getFile() {
return file; return file;
} }
/**
*
*
* @return ...
*/
public String getName() { public String getName() {
return name; return name;
} }
/**
*
*
* @return ...
*/
public String getSourceName() { public String getSourceName() {
return sourceName; return sourceName;
} }
/**
*
*
* @return ...
*
* @throws FileNotFoundException ...
*/
public Reader getReader() throws FileNotFoundException { public Reader getReader() throws FileNotFoundException {
if (content != null) if (content != null) {
return new StringReader(content); return new StringReader(content);
else if (file.length() == 0) } else if (file.length() == 0) {
return new StringReader(";"); return new StringReader(";");
else } else {
return new FileReader(file); return new FileReader(file);
} }
}
/**
*
*
* @return ...
*/
public String getContent() { public String getContent() {
if (content != null) if (content != null) {
return content; return content;
else { } else {
try { try {
FileReader reader = new FileReader(file); FileReader reader = new FileReader(file);
char cbuf[] = new char[(int) file.length ()]; char[] cbuf = new char[(int) file.length()];
reader.read(cbuf); reader.read(cbuf);
reader.close(); reader.close();
return new String(cbuf); return new String(cbuf);
} catch (Exception filex) { } catch (Exception filex) {
app.logEvent("Error reading " + this + ": " + filex); app.logEvent("Error reading " + this + ": " + filex);
return null; return null;
} }
} }
} }
/**
*
*
* @return ...
*/
public String getFunctionName() { public String getFunctionName() {
return name + "_action"; return name + "_action";
} }
/**
*
*
* @return ...
*/
public Prototype getPrototype() { public Prototype getPrototype() {
return prototype; return prototype;
} }
/**
*
*
* @return ...
*/
public Application getApplication() { public Application getApplication() {
return app; return app;
} }
/**
*
*
* @return ...
*/
public String toString() { public String toString() {
return "ActionFile[" + sourceName + "]"; return "ActionFile[" + sourceName + "]";
} }
} }

View file

@ -1,25 +1,34 @@
// FunctionFile.java /*
// Copyright (c) Hannes Wallnöfer 1998-2000 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.scripting; package helma.scripting;
import java.util.HashMap;
import java.util.Iterator;
import java.util.HashSet;
import java.util.Enumeration;
import java.io.*;
import helma.framework.*; import helma.framework.*;
import helma.framework.core.*; import helma.framework.core.*;
import helma.util.Updatable; import helma.util.Updatable;
import java.io.*;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
/** /**
* This represents a File containing script functions for a given class/prototype. * This represents a File containing script functions for a given class/prototype.
*/ */
public class FunctionFile implements Updatable { public class FunctionFile implements Updatable {
Prototype prototype; Prototype prototype;
Application app; Application app;
File file; File file;
@ -27,7 +36,12 @@ public class FunctionFile implements Updatable {
String content; String content;
long lastmod; long lastmod;
/**
* Creates a new FunctionFile object.
*
* @param file ...
* @param proto ...
*/
public FunctionFile(File file, Prototype proto) { public FunctionFile(File file, Prototype proto) {
this.prototype = proto; this.prototype = proto;
this.app = proto.getApplication(); this.app = proto.getApplication();
@ -54,10 +68,12 @@ public class FunctionFile implements Updatable {
* the file has been modified or deleted. * the file has been modified or deleted.
*/ */
public boolean needsUpdate() { public boolean needsUpdate() {
return file != null && lastmod != file.lastModified (); return (file != null) && (lastmod != file.lastModified());
} }
/**
*
*/
public void update() { public void update() {
if (file != null) { if (file != null) {
if (!file.exists()) { if (!file.exists()) {
@ -68,28 +84,46 @@ public class FunctionFile implements Updatable {
} }
} }
/**
*
*
* @return ...
*/
public File getFile() { public File getFile() {
return file; return file;
} }
/**
*
*
* @return ...
*/
public String getContent() { public String getContent() {
return content; return content;
} }
/**
*
*
* @return ...
*/
public String getSourceName() { public String getSourceName() {
return sourceName; return sourceName;
} }
/**
*
*/
public void remove() { public void remove() {
prototype.removeFunctionFile(this); prototype.removeFunctionFile(this);
} }
/**
*
*
* @return ...
*/
public String toString() { public String toString() {
return sourceName; return sourceName;
} }
} }

View file

@ -1,5 +1,18 @@
// ScriptingEngine.java /*
// Copyright (c) Hannes Wallnöfer 1998-2001 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.scripting; package helma.scripting;
@ -7,8 +20,8 @@ import helma.framework.IPathElement;
import helma.framework.core.Application; import helma.framework.core.Application;
import helma.framework.core.Prototype; import helma.framework.core.Prototype;
import helma.framework.core.RequestEvaluator; import helma.framework.core.RequestEvaluator;
import java.util.*;
import java.io.File; import java.io.File;
import java.util.*;
/** /**
* This is the interface that must be implemented to make a scripting environment * This is the interface that must be implemented to make a scripting environment
@ -18,7 +31,6 @@ import java.io.File;
* to be usable by the Helma framework. * to be usable by the Helma framework.
*/ */
public interface ScriptingEngine { public interface ScriptingEngine {
/** /**
* Init the scripting engine with an application and a request evaluator * Init the scripting engine with an application and a request evaluator
*/ */
@ -44,13 +56,12 @@ public interface ScriptingEngine {
*/ */
public void exitContext(); public void exitContext();
/** /**
* Invoke a function on some object, using the given arguments and global vars. * Invoke a function on some object, using the given arguments and global vars.
* XML-RPC calls require special input and output parameter conversion. * XML-RPC calls require special input and output parameter conversion.
*/ */
public Object invoke (Object thisObject, String functionName, Object[] args, boolean xmlrpc) public Object invoke(Object thisObject, String functionName, Object[] args,
throws ScriptingException; boolean xmlrpc) throws ScriptingException;
/** /**
* Let the evaluator know that the current evaluation has been aborted. * Let the evaluator know that the current evaluation has been aborted.
@ -74,6 +85,4 @@ public interface ScriptingEngine {
* class should be compatible with helma.doc.DocApplication. * class should be compatible with helma.doc.DocApplication.
*/ */
public IPathElement getIntrospector(); public IPathElement getIntrospector();
} }

View file

@ -1,17 +1,28 @@
// ScriptingException.java /*
// Copyright (c) Hannes Wallnöfer 1998-2001 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.scripting; package helma.scripting;
import java.io.PrintWriter;
import java.io.PrintStream; import java.io.PrintStream;
import java.io.PrintWriter;
/** /**
* The base class for exceptions thrown by Helma scripting package * The base class for exceptions thrown by Helma scripting package
*/ */
public class ScriptingException extends Exception { public class ScriptingException extends Exception {
Exception wrapped; Exception wrapped;
/** /**
@ -29,39 +40,66 @@ public class ScriptingException extends Exception {
wrapped = w; wrapped = w;
} }
/**
*
*
* @return ...
*/
public String toString() { public String toString() {
if (wrapped == null) if (wrapped == null) {
return super.toString(); return super.toString();
else } else {
return wrapped.toString(); return wrapped.toString();
} }
}
/**
*
*
* @return ...
*/
public String getMessage() { public String getMessage() {
if (wrapped == null) if (wrapped == null) {
return super.getMessage(); return super.getMessage();
else } else {
return wrapped.getMessage(); return wrapped.getMessage();
} }
}
/**
*
*/
public void printStackTrace() { public void printStackTrace() {
if (wrapped == null) if (wrapped == null) {
super.printStackTrace(); super.printStackTrace();
else } else {
wrapped.printStackTrace(); wrapped.printStackTrace();
} }
}
/**
*
*
* @param stream ...
*/
public void printStackTrace(PrintStream stream) { public void printStackTrace(PrintStream stream) {
if (wrapped == null) if (wrapped == null) {
super.printStackTrace(stream); super.printStackTrace(stream);
else } else {
wrapped.printStackTrace(stream); wrapped.printStackTrace(stream);
} }
}
/**
*
*
* @param writer ...
*/
public void printStackTrace(PrintWriter writer) { public void printStackTrace(PrintWriter writer) {
if (wrapped == null) if (wrapped == null) {
super.printStackTrace(writer); super.printStackTrace(writer);
else } else {
wrapped.printStackTrace(writer); wrapped.printStackTrace(writer);
} }
}
} }

View file

@ -1,15 +1,27 @@
// Template.java /*
// Copyright (c) Hannes Wallnöfer 1998-2000 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.scripting; package helma.scripting;
import java.io.*;
import java.util.Vector;
import java.util.Iterator;
import java.util.StringTokenizer;
import helma.framework.*; import helma.framework.*;
import helma.framework.core.*; import helma.framework.core.*;
import java.io.*;
import java.util.Iterator;
import java.util.StringTokenizer;
import java.util.Vector;
/** /**
* This represents a Helma template, i.e. a file with the extension .hsp * This represents a Helma template, i.e. a file with the extension .hsp
@ -21,58 +33,99 @@ import helma.framework.core.*;
* now is to have a .hac file with all the logic which in turn calls one or more * now is to have a .hac file with all the logic which in turn calls one or more
* template files to do the formatting. * template files to do the formatting.
*/ */
public class Template extends ActionFile { public class Template extends ActionFile {
/**
* Creates a new Template object.
*
* @param file ...
* @param name ...
* @param proto ...
*/
public Template(File file, String name, Prototype proto) { public Template(File file, String name, Prototype proto) {
super(file, name, proto); super(file, name, proto);
} }
/**
* Creates a new Template object.
*
* @param content ...
* @param name ...
* @param sourceName ...
* @param proto ...
*/
public Template(String content, String name, String sourceName, Prototype proto) { public Template(String content, String name, String sourceName, Prototype proto) {
super(content, name, sourceName, proto); super(content, name, sourceName, proto);
} }
/**
*
*
* @return ...
*/
public String getFunctionName() { public String getFunctionName() {
return name; return name;
} }
/**
*
*
* @return ...
*/
public Reader getReader() { public Reader getReader() {
return new StringReader(getContent()); return new StringReader(getContent());
} }
/**
*
*
* @return ...
*/
public String getContent() { public String getContent() {
Vector partBuffer = new Vector(); Vector partBuffer = new Vector();
String cstring = super.getContent(); String cstring = super.getContent();
char[] cnt = cstring.toCharArray(); char[] cnt = cstring.toCharArray();
int l = cnt.length; int l = cnt.length;
if (l == 0)
if (l == 0) {
return ""; return "";
}
// if last charackter is whitespace, swallow it. this is necessary for some inner templates to look ok. // if last charackter is whitespace, swallow it. this is necessary for some inner templates to look ok.
if (Character.isWhitespace (cnt[l-1])) if (Character.isWhitespace(cnt[l - 1])) {
l -= 1; l -= 1;
}
int lastIdx = 0; int lastIdx = 0;
for (int i = 0; i < l-1; i++) {
if (cnt[i] == '<' && cnt[i+1] == '%') { for (int i = 0; i < (l - 1); i++) {
if ((cnt[i] == '<') && (cnt[i + 1] == '%')) {
int j = i + 2; int j = i + 2;
while (j < l-1 && (cnt[j] != '%' || cnt[j+1] != '>')) {
while ((j < (l - 1)) && ((cnt[j] != '%') || (cnt[j + 1] != '>'))) {
j++; j++;
} }
if (j > i+2) {
if (i - lastIdx > 0) if (j > (i + 2)) {
partBuffer.addElement (new Part (this, new String (cnt, lastIdx, i - lastIdx), true)); if ((i - lastIdx) > 0) {
partBuffer.addElement(new Part(this,
new String(cnt, lastIdx,
i - lastIdx), true));
}
String script = new String(cnt, i + 2, (j - i) - 2); String script = new String(cnt, i + 2, (j - i) - 2);
partBuffer.addElement(new Part(this, script, false)); partBuffer.addElement(new Part(this, script, false));
lastIdx = j + 2; lastIdx = j + 2;
} }
i = j + 1; i = j + 1;
} }
} }
if (lastIdx < l)
partBuffer.addElement (new Part (this, new String (cnt, lastIdx, l - lastIdx), true)); if (lastIdx < l) {
partBuffer.addElement(new Part(this, new String(cnt, lastIdx, l - lastIdx),
true));
}
StringBuffer templateBody = new StringBuffer(); StringBuffer templateBody = new StringBuffer();
int nparts = partBuffer.size(); int nparts = partBuffer.size();
@ -84,9 +137,12 @@ public class Template extends ActionFile {
// check for <%= ... %> statements // check for <%= ... %> statements
if (!nextPart.isStatic) { if (!nextPart.isStatic) {
nextPart.content = nextPart.content.trim().substring(1).trim(); nextPart.content = nextPart.content.trim().substring(1).trim();
// cut trailing ";" // cut trailing ";"
while (nextPart.content.endsWith(";")) while (nextPart.content.endsWith(";"))
nextPart.content = nextPart.content.substring (0, nextPart.content.length()-1); nextPart.content = nextPart.content.substring(0,
nextPart.content.length() -
1);
} }
StringTokenizer st = new StringTokenizer(nextPart.content, "\r\n", true); StringTokenizer st = new StringTokenizer(nextPart.content, "\r\n", true);
@ -96,30 +152,35 @@ public class Template extends ActionFile {
int newLineCount = 0; int newLineCount = 0;
templateBody.append("res.write ("); templateBody.append("res.write (");
if (nextPart.isStatic) { if (nextPart.isStatic) {
templateBody.append("\""); templateBody.append("\"");
} }
while (nextLine != null) { while (nextLine != null) {
if ("\n".equals(nextLine)) { if ("\n".equals(nextLine)) {
// append a CRLF // append a CRLF
newLineCount++; newLineCount++;
templateBody.append("\\r\\n"); templateBody.append("\\r\\n");
} else if (!"\r".equals (nextLine)) try { } else if (!"\r".equals(nextLine)) {
try {
StringReader lineReader = new StringReader(nextLine); StringReader lineReader = new StringReader(nextLine);
int c = lineReader.read(); int c = lineReader.read();
while (c > -1) { while (c > -1) {
if (nextPart.isStatic && ((char)c == '"' || (char)c == '\\')) { if (nextPart.isStatic &&
(((char) c == '"') || ((char) c == '\\'))) {
templateBody.append('\\'); templateBody.append('\\');
} }
templateBody.append((char) c); templateBody.append((char) c);
c = lineReader.read(); c = lineReader.read();
} }
} catch (IOException srx) {} } catch (IOException srx) {
}
}
nextLine = st.hasMoreTokens() ? st.nextToken() : null; nextLine = st.hasMoreTokens() ? st.nextToken() : null;
} }
if (nextPart.isStatic) { if (nextPart.isStatic) {
@ -134,33 +195,32 @@ public class Template extends ActionFile {
for (int i = 0; i < newLineCount; i++) { for (int i = 0; i < newLineCount; i++) {
templateBody.append("\r\n"); templateBody.append("\r\n");
} }
} else { } else {
templateBody.append(nextPart.content); templateBody.append(nextPart.content);
if (!nextPart.content.trim().endsWith(";")) { if (!nextPart.content.trim().endsWith(";")) {
templateBody.append(";"); templateBody.append(";");
} }
} }
} }
// templateBody.append ("\r\nreturn null;\r\n");
// templateBody.append ("\r\nreturn null;\r\n");
return templateBody.toString(); return templateBody.toString();
} }
/**
*
*/
public void remove() { public void remove() {
prototype.removeTemplate(this); prototype.removeTemplate(this);
} }
class Part { class Part {
String content; String content;
Template parent; Template parent;
boolean isPart; boolean isPart;
boolean isStatic; boolean isStatic;
public Part(Template parent, String content, boolean isStatic) { public Part(Template parent, String content, boolean isStatic) {
isPart = false; isPart = false;
this.parent = parent; this.parent = parent;
@ -172,16 +232,8 @@ public class Template extends ActionFile {
return isStatic ? null : content; return isStatic ? null : content;
} }
public String toString() { public String toString() {
return "Template.Part [" + content + "," + isStatic + "]"; return "Template.Part [" + content + "," + isStatic + "]";
} }
} }
} }

View file

@ -1,25 +1,43 @@
/*
* Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.scripting.fesi; package helma.scripting.fesi;
import java.util.Map;
import helma.framework.core.ApplicationBean;
import helma.objectmodel.INode;
import helma.util.SystemProperties;
import FESI.Interpreter.Evaluator;
import FESI.Exceptions.EcmaScriptException;
import FESI.Data.ESNull; import FESI.Data.ESNull;
import FESI.Data.ESValue; import FESI.Data.ESValue;
import FESI.Data.ESWrapper; import FESI.Data.ESWrapper;
import FESI.Exceptions.EcmaScriptException;
import FESI.Interpreter.Evaluator;
import helma.framework.core.ApplicationBean;
import helma.objectmodel.INode;
import helma.util.SystemProperties;
import java.util.Map;
/** /**
* Wrap a Java Bean for use in EcmaScript. * Wrap a Java Bean for use in EcmaScript.
*/ */
public class ESBeanWrapper extends ESWrapper { public class ESBeanWrapper extends ESWrapper {
FesiEngine engine; FesiEngine engine;
/**
* Creates a new ESBeanWrapper object.
*
* @param object ...
* @param engine ...
*/
public ESBeanWrapper(Object object, FesiEngine engine) { public ESBeanWrapper(Object object, FesiEngine engine) {
super(object, engine.getEvaluator(), true); super(object, engine.getEvaluator(), true);
this.engine = engine; this.engine = engine;
@ -29,37 +47,52 @@ public class ESBeanWrapper extends ESWrapper {
* Wrap getProperty, return ESNode if INode would be returned, * Wrap getProperty, return ESNode if INode would be returned,
* ESMapWrapper if Map would be returned. * ESMapWrapper if Map would be returned.
*/ */
public ESValue getProperty(String propertyName, int hash) throws EcmaScriptException { public ESValue getProperty(String propertyName, int hash)
throws EcmaScriptException {
try { try {
ESValue val = super.getProperty(propertyName, hash); ESValue val = super.getProperty(propertyName, hash);
if (val instanceof ESWrapper) { if (val instanceof ESWrapper) {
Object theObject = ((ESWrapper) val).getJavaObject(); Object theObject = ((ESWrapper) val).getJavaObject();
if (val instanceof ESWrapper && theObject instanceof INode) { if (val instanceof ESWrapper && theObject instanceof INode) {
return engine.getNodeWrapper((INode) theObject); return engine.getNodeWrapper((INode) theObject);
} else if (val instanceof ESWrapper && theObject instanceof Map) { } else if (val instanceof ESWrapper && theObject instanceof Map) {
ESMapWrapper wrapper = new ESMapWrapper(engine, (Map) theObject); ESMapWrapper wrapper = new ESMapWrapper(engine, (Map) theObject);
if (theObject instanceof SystemProperties && super.getJavaObject () instanceof ApplicationBean)
if (theObject instanceof SystemProperties &&
super.getJavaObject() instanceof ApplicationBean) {
wrapper.setReadonly(true); wrapper.setReadonly(true);
}
return wrapper; return wrapper;
} }
} }
return val; return val;
} catch (Exception rte) { } catch (Exception rte) {
return ESNull.theNull; return ESNull.theNull;
} }
} }
public void putProperty(String propertyName, ESValue propertyValue, int hash) throws EcmaScriptException { /**
*
*
* @param propertyName ...
* @param propertyValue ...
* @param hash ...
*
* @throws EcmaScriptException ...
*/
public void putProperty(String propertyName, ESValue propertyValue, int hash)
throws EcmaScriptException {
try { try {
super.putProperty(propertyName, propertyValue, hash); super.putProperty(propertyName, propertyValue, hash);
} catch (Exception rte) { } catch (Exception rte) {
// create a nice error message // create a nice error message
throw new EcmaScriptException("can't set property " + propertyName + throw new EcmaScriptException("can't set property " + propertyName +
" to this value on " + getJavaObject().toString() ); " to this value on " +
getJavaObject().toString());
} }
} }
} }

View file

@ -1,89 +1,213 @@
// ESGenericObject.java /*
// Copyright (c) Hannes Wallnöfer 1998-2000 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.scripting.fesi; package helma.scripting.fesi;
import helma.framework.core.*;
import helma.framework.IPathElement;
import FESI.Interpreter.*;
import FESI.Exceptions.*;
import FESI.Data.*; import FESI.Data.*;
import FESI.Exceptions.*;
import FESI.Interpreter.*;
import helma.framework.IPathElement;
import helma.framework.core.*;
import java.util.*; import java.util.*;
/** /**
* A wrapper for a Java object that may or may not implement the IPathElement interface. * A wrapper for a Java object that may or may not implement the IPathElement interface.
*/ */
public class ESGenericObject extends ObjectPrototype { public class ESGenericObject extends ObjectPrototype {
ESWrapper wrapper; ESWrapper wrapper;
Object wrappedObject; Object wrappedObject;
/**
* Creates a new ESGenericObject object.
*
* @param prototype ...
* @param evaluator ...
* @param obj ...
*/
public ESGenericObject(ESObject prototype, Evaluator evaluator, Object obj) { public ESGenericObject(ESObject prototype, Evaluator evaluator, Object obj) {
super(prototype, evaluator); super(prototype, evaluator);
wrappedObject = obj; wrappedObject = obj;
wrapper = new ESWrapper(obj, evaluator); wrapper = new ESWrapper(obj, evaluator);
} }
/**
*
*
* @return ...
*/
public String getESClassName() { public String getESClassName() {
return "GenericObject"; return "GenericObject";
} }
/**
*
*
* @return ...
*/
public String toString() { public String toString() {
return wrappedObject.toString(); return wrappedObject.toString();
} }
/**
*
*
* @return ...
*/
public String toDetailString() { public String toDetailString() {
return wrapper.toDetailString(); return wrapper.toDetailString();
} }
/**
public void putProperty(String propertyName, ESValue propertyValue, int hash) throws EcmaScriptException { *
*
* @param propertyName ...
* @param propertyValue ...
* @param hash ...
*
* @throws EcmaScriptException ...
*/
public void putProperty(String propertyName, ESValue propertyValue, int hash)
throws EcmaScriptException {
wrapper.putProperty(propertyName, propertyValue, hash); wrapper.putProperty(propertyName, propertyValue, hash);
} }
public boolean hasProperty(String propertyName, int hash) throws EcmaScriptException { /**
return super.hasProperty (propertyName, hash) || wrapper.hasProperty (propertyName, hash); *
*
* @param propertyName ...
* @param hash ...
*
* @return ...
*
* @throws EcmaScriptException ...
*/
public boolean hasProperty(String propertyName, int hash)
throws EcmaScriptException {
return super.hasProperty(propertyName, hash) ||
wrapper.hasProperty(propertyName, hash);
} }
public boolean deleteProperty(String propertyName, int hash) throws EcmaScriptException { /**
*
*
* @param propertyName ...
* @param hash ...
*
* @return ...
*
* @throws EcmaScriptException ...
*/
public boolean deleteProperty(String propertyName, int hash)
throws EcmaScriptException {
return wrapper.deleteProperty(propertyName, hash); return wrapper.deleteProperty(propertyName, hash);
} }
/**
*
*
* @param i ...
*
* @return ...
*
* @throws EcmaScriptException ...
*/
public ESValue getProperty(int i) throws EcmaScriptException { public ESValue getProperty(int i) throws EcmaScriptException {
return wrapper.getProperty(i); return wrapper.getProperty(i);
} }
public void putProperty(int index, ESValue propertyValue) throws EcmaScriptException { /**
*
*
* @param index ...
* @param propertyValue ...
*
* @throws EcmaScriptException ...
*/
public void putProperty(int index, ESValue propertyValue)
throws EcmaScriptException {
wrapper.putProperty(index, propertyValue); wrapper.putProperty(index, propertyValue);
} }
/**
public ESValue getProperty(String propertyName, int hash) throws EcmaScriptException { *
*
* @param propertyName ...
* @param hash ...
*
* @return ...
*
* @throws EcmaScriptException ...
*/
public ESValue getProperty(String propertyName, int hash)
throws EcmaScriptException {
ESValue val = super.getProperty(propertyName, hash); ESValue val = super.getProperty(propertyName, hash);
if (val == null || val == ESUndefined.theUndefined)
if ((val == null) || (val == ESUndefined.theUndefined)) {
val = wrapper.getProperty(propertyName, hash); val = wrapper.getProperty(propertyName, hash);
}
return val; return val;
} }
public ESValue doIndirectCall(Evaluator evaluator, ESObject thisObject, String functionName, ESValue[] arguments) /**
*
*
* @param evaluator ...
* @param thisObject ...
* @param functionName ...
* @param arguments ...
*
* @return ...
*
* @throws EcmaScriptException ...
* @throws NoSuchMethodException ...
*/
public ESValue doIndirectCall(Evaluator evaluator, ESObject thisObject,
String functionName, ESValue[] arguments)
throws EcmaScriptException, NoSuchMethodException { throws EcmaScriptException, NoSuchMethodException {
if (super.hasProperty (functionName, functionName.hashCode())) if (super.hasProperty(functionName, functionName.hashCode())) {
return super.doIndirectCall(evaluator, thisObject, functionName, arguments); return super.doIndirectCall(evaluator, thisObject, functionName, arguments);
}
return wrapper.doIndirectCall(evaluator, thisObject, functionName, arguments); return wrapper.doIndirectCall(evaluator, thisObject, functionName, arguments);
} }
/**
*
*
* @return ...
*/
public Enumeration getAllProperties() { public Enumeration getAllProperties() {
return wrapper.getProperties(); return wrapper.getProperties();
} }
/**
*
*
* @return ...
*/
public Enumeration getProperties() { public Enumeration getProperties() {
return wrapper.getProperties(); return wrapper.getProperties();
} }
/**
*
*
* @return ...
*/
public Object toJavaObject() { public Object toJavaObject() {
return wrappedObject; return wrappedObject;
} }
@ -93,17 +217,20 @@ public class ESGenericObject extends ObjectPrototype {
* or the wrapped INode itself. FIXME: doesen't check dbmapping/type! * or the wrapped INode itself. FIXME: doesen't check dbmapping/type!
*/ */
public boolean equals(Object what) { public boolean equals(Object what) {
if (what == null) if (what == null) {
return false; return false;
if (what == this) }
if (what == this) {
return true; return true;
}
if (what instanceof ESGenericObject) { if (what instanceof ESGenericObject) {
ESGenericObject other = (ESGenericObject) what; ESGenericObject other = (ESGenericObject) what;
return (wrappedObject.equals(other.wrappedObject)); return (wrappedObject.equals(other.wrappedObject));
} }
return false; return false;
} }
} }

View file

@ -1,43 +1,72 @@
// ESMapWrapper.java /*
// Copyright (c) Hannes Wallnöfer 1998-2000 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.scripting.fesi; package helma.scripting.fesi;
import helma.framework.core.*;
import helma.objectmodel.INode;
import FESI.Data.*; import FESI.Data.*;
import FESI.Exceptions.*; import FESI.Exceptions.*;
import FESI.Interpreter.Evaluator; import FESI.Interpreter.Evaluator;
import helma.framework.core.*;
import helma.objectmodel.INode;
import java.util.*; import java.util.*;
/** /**
* An EcmaScript object that makes stuff in a hashtable accessible as its properties * An EcmaScript object that makes stuff in a hashtable accessible as its properties
*/ */
public class ESMapWrapper extends ESWrapper { public class ESMapWrapper extends ESWrapper {
private Map data; private Map data;
private FesiEngine engine; private FesiEngine engine;
private boolean readonly = false; private boolean readonly = false;
/**
* Creates a new ESMapWrapper object.
*
* @param engine ...
*/
public ESMapWrapper(FesiEngine engine) { public ESMapWrapper(FesiEngine engine) {
super(new Object(), engine.getEvaluator()); super(new Object(), engine.getEvaluator());
this.engine = engine; this.engine = engine;
} }
/**
* Creates a new ESMapWrapper object.
*
* @param engine ...
* @param data ...
*/
public ESMapWrapper(FesiEngine engine, Map data) { public ESMapWrapper(FesiEngine engine, Map data) {
super(new Object(), engine.getEvaluator()); super(new Object(), engine.getEvaluator());
this.engine = engine; this.engine = engine;
this.data = data; this.data = data;
} }
/**
*
*
* @param readonly ...
*/
public void setReadonly(boolean readonly) { public void setReadonly(boolean readonly) {
this.readonly = readonly; this.readonly = readonly;
} }
/**
*
*
* @param data ...
*/
public void setData(Map data) { public void setData(Map data) {
this.data = data; this.data = data;
} }
@ -45,58 +74,98 @@ public class ESMapWrapper extends ESWrapper {
/** /**
* Overridden to make the object read-only * Overridden to make the object read-only
*/ */
public void putProperty(String propertyName, ESValue propertyValue, int hash) throws EcmaScriptException { public void putProperty(String propertyName, ESValue propertyValue, int hash)
if (data == null) throws EcmaScriptException {
if (data == null) {
data = new HashMap(); data = new HashMap();
if (propertyValue == ESNull.theNull) }
if (propertyValue == ESNull.theNull) {
deleteProperty(propertyName, hash); deleteProperty(propertyName, hash);
else if (readonly==false) } else if (readonly == false) {
data.put(propertyName, propertyValue.toJavaObject()); data.put(propertyName, propertyValue.toJavaObject());
else } else {
throw new EcmaScriptException("object is readonly"); throw new EcmaScriptException("object is readonly");
} }
public boolean deleteProperty(String propertyName, int hash) throws EcmaScriptException {
if (readonly==false) {
data.remove (propertyName);
return true;
} else
return false;
} }
public ESValue getProperty(String propertyName, int hash) throws EcmaScriptException { /**
if (data == null) *
*
* @param propertyName ...
* @param hash ...
*
* @return ...
*
* @throws EcmaScriptException ...
*/
public boolean deleteProperty(String propertyName, int hash)
throws EcmaScriptException {
if (readonly == false) {
data.remove(propertyName);
return true;
} else {
return false;
}
}
/**
*
*
* @param propertyName ...
* @param hash ...
*
* @return ...
*
* @throws EcmaScriptException ...
*/
public ESValue getProperty(String propertyName, int hash)
throws EcmaScriptException {
if (data == null) {
return ESNull.theNull; return ESNull.theNull;
}
Object val = data.get(propertyName); Object val = data.get(propertyName);
if (val == null) if (val == null) {
return ESNull.theNull; return ESNull.theNull;
}
if (val instanceof String) if (val instanceof String) {
return new ESString((String) val); return new ESString((String) val);
else if (val instanceof INode) } else if (val instanceof INode) {
return engine.getNodeWrapper((INode) val); return engine.getNodeWrapper((INode) val);
else if (val instanceof Map) } else if (val instanceof Map) {
return new ESMapWrapper(engine, (Map) val); return new ESMapWrapper(engine, (Map) val);
else if (val instanceof ESValue) } else if (val instanceof ESValue) {
return (ESValue) val; return (ESValue) val;
}
return ESLoader.normalizeValue(val, evaluator); return ESLoader.normalizeValue(val, evaluator);
} }
/**
*
*
* @return ...
*/
public Enumeration getAllProperties() { public Enumeration getAllProperties() {
return getProperties(); return getProperties();
} }
/**
*
*
* @return ...
*/
public Enumeration getProperties() { public Enumeration getProperties() {
Object[] keys = data == null ? null : data.keySet().toArray (); Object[] keys = (data == null) ? null : data.keySet().toArray();
return new Enum(keys); return new Enum(keys);
} }
class Enum implements Enumeration { class Enum implements Enumeration {
Object[] elements; Object[] elements;
int pos; int pos;
@ -106,66 +175,15 @@ public class ESMapWrapper extends ESWrapper {
} }
public boolean hasMoreElements() { public boolean hasMoreElements() {
return elements != null && pos < elements.length; return (elements != null) && (pos < elements.length);
} }
public Object nextElement() { public Object nextElement() {
if (elements == null || pos >= elements.length) if ((elements == null) || (pos >= elements.length)) {
throw new NoSuchElementException(); throw new NoSuchElementException();
}
return elements[pos++]; return elements[pos++];
} }
} }
} }

View file

@ -1,33 +1,43 @@
// ESNode.java /*
// Copyright (c) Hannes Wallnöfer 1998-2000 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.scripting.fesi; package helma.scripting.fesi;
import FESI.Data.*;
import FESI.Exceptions.*;
import FESI.Interpreter.*;
import helma.framework.core.*;
import helma.objectmodel.*; import helma.objectmodel.*;
import helma.objectmodel.db.*; import helma.objectmodel.db.*;
import helma.framework.core.*;
import helma.util.*; import helma.util.*;
import FESI.Interpreter.*;
import FESI.Exceptions.*;
import FESI.Data.*;
import java.io.*; import java.io.*;
import java.util.*; import java.util.*;
/** /**
* An EcmaScript wrapper around a Node object. This is the basic * An EcmaScript wrapper around a Node object. This is the basic
* HopObject that can be stored in the internal or external databases. * HopObject that can be stored in the internal or external databases.
*/ */
public class ESNode extends ObjectPrototype { public class ESNode extends ObjectPrototype {
// the INode object wrapped by this ESObject // the INode object wrapped by this ESObject
INode node; INode node;
// the cache node - persistent nodes have a transient property as a commodity to // the cache node - persistent nodes have a transient property as a commodity to
// store temporary stuff. // store temporary stuff.
INode cache; INode cache;
// the ecmascript wrapper for the cache. // the ecmascript wrapper for the cache.
ESNode cacheWrapper; ESNode cacheWrapper;
@ -51,23 +61,36 @@ public class ESNode extends ObjectPrototype {
handle = null; handle = null;
} }
/**
* Creates a new ESNode object.
*
* @param prototype ...
* @param evaluator ...
* @param obj ...
* @param engine ...
*/
public ESNode(ESObject prototype, Evaluator evaluator, Object obj, FesiEngine engine) { public ESNode(ESObject prototype, Evaluator evaluator, Object obj, FesiEngine engine) {
super(prototype, evaluator); super(prototype, evaluator);
// eval.app.logEvent ("in ESNode constructor: "+o.getClass ()); // eval.app.logEvent ("in ESNode constructor: "+o.getClass ());
this.engine = engine; this.engine = engine;
if (obj == null)
if (obj == null) {
node = new TransientNode(null); node = new TransientNode(null);
else if (obj instanceof ESWrapper) } else if (obj instanceof ESWrapper) {
node = (INode) ((ESWrapper) obj).getJavaObject(); node = (INode) ((ESWrapper) obj).getJavaObject();
else if (obj instanceof INode) } else if (obj instanceof INode) {
node = (INode) obj; node = (INode) obj;
else } else {
node = new TransientNode(obj.toString()); node = new TransientNode(obj.toString());
}
// set node handle to wrapped node // set node handle to wrapped node
if (node instanceof Node) if (node instanceof Node) {
handle = ((Node) node).getHandle(); handle = ((Node) node).getHandle();
else } else {
handle = null; handle = null;
}
// cache Node is initialized on demend when it is needed // cache Node is initialized on demend when it is needed
cache = null; cache = null;
@ -79,35 +102,71 @@ public class ESNode extends ObjectPrototype {
* from the db via the app's node manager. * from the db via the app's node manager.
*/ */
protected void checkNode() { protected void checkNode() {
if (node.getState () == INode.INVALID) try { if (node.getState() == INode.INVALID) {
try {
node = handle.getNode(engine.app.getWrappedNodeManager()); node = handle.getNode(engine.app.getWrappedNodeManager());
} catch (Exception nx) {} } catch (Exception nx) {
}
}
} }
/**
*
*
* @return ...
*/
public INode getNode() { public INode getNode() {
checkNode(); checkNode();
return node; return node;
} }
/**
*
*
* @param protoName ...
*/
public void setPrototype(String protoName) { public void setPrototype(String protoName) {
checkNode(); checkNode();
node.setPrototype(protoName); node.setPrototype(protoName);
} }
/**
*
*
* @return ...
*/
public String getPrototypeName() { public String getPrototypeName() {
return node.getPrototype(); return node.getPrototype();
} }
/**
*
*
* @return ...
*/
public String getESClassName() { public String getESClassName() {
return "HopObject"; return "HopObject";
} }
/**
*
*
* @return ...
*/
public String toString() { public String toString() {
if (node == null) if (node == null) {
return "<null>"; return "<null>";
}
return node.toString(); return node.toString();
} }
/**
*
*
* @return ...
*/
public String toDetailString() { public String toDetailString() {
return "ES:[Object: builtin " + this.getClass().getName() + ":" + return "ES:[Object: builtin " + this.getClass().getName() + ":" +
((node == null) ? "null" : node.toString()) + "]"; ((node == null) ? "null" : node.toString()) + "]";
@ -117,51 +176,83 @@ public class ESNode extends ObjectPrototype {
lastError = e; lastError = e;
} }
/**
public boolean add (ESValue what[]) { *
*
* @param what ...
*
* @return ...
*/
public boolean add(ESValue[] what) {
checkNode(); checkNode();
for (int i = 0; i < what.length; i++) for (int i = 0; i < what.length; i++)
if (what[i] instanceof ESNode) { if (what[i] instanceof ESNode) {
ESNode esn = (ESNode) what[i]; ESNode esn = (ESNode) what[i];
INode added = node.addNode(esn.getNode()); INode added = node.addNode(esn.getNode());
} }
return true; return true;
} }
/**
*
*
* @return ...
*/
public ESValue list() { public ESValue list() {
checkNode(); checkNode();
int l = node.numberOfNodes(); int l = node.numberOfNodes();
Enumeration e = node.getSubnodes(); Enumeration e = node.getSubnodes();
ESObject ap = evaluator.getArrayPrototype(); ESObject ap = evaluator.getArrayPrototype();
ArrayPrototype theArray = new ArrayPrototype(ap, evaluator); ArrayPrototype theArray = new ArrayPrototype(ap, evaluator);
if (e != null) { if (e != null) {
theArray.setSize(l); theArray.setSize(l);
for (int i = 0; i < l; i++) { for (int i = 0; i < l; i++) {
theArray.setElementAt(engine.getNodeWrapper((INode) e.nextElement()), i); theArray.setElementAt(engine.getNodeWrapper((INode) e.nextElement()), i);
} }
} else { } else {
theArray.setSize(0); theArray.setSize(0);
} }
return theArray; return theArray;
} }
public boolean addAt (ESValue what[]) throws EcmaScriptException { /**
*
*
* @param what ...
*
* @return ...
*
* @throws EcmaScriptException ...
*/
public boolean addAt(ESValue[] what) throws EcmaScriptException {
checkNode(); checkNode();
if (what.length < 2)
if (what.length < 2) {
throw new EcmaScriptException("Wrong number of arguments"); throw new EcmaScriptException("Wrong number of arguments");
if (! (what[1] instanceof ESNode))
throw new EcmaScriptException ("Can ony add Node objects as subnodes");
ESNode esn = (ESNode) what[1];
INode added = node.addNode (esn.getNode (), (int) what[0].toInt32 ());
return true;
} }
if (!(what[1] instanceof ESNode)) {
throw new EcmaScriptException("Can ony add Node objects as subnodes");
}
ESNode esn = (ESNode) what[1];
INode added = node.addNode(esn.getNode(), (int) what[0].toInt32());
return true;
}
/** /**
* Remove node itself or one or more subnodes. * Remove node itself or one or more subnodes.
*/ */
public boolean remove (ESValue args[]) { public boolean remove(ESValue[] args) {
checkNode(); checkNode();
// semantics: if called without arguments, remove self. // semantics: if called without arguments, remove self.
// otherwise, remove given subnodes. // otherwise, remove given subnodes.
if (args.length == 0) { if (args.length == 0) {
@ -170,17 +261,19 @@ public class ESNode extends ObjectPrototype {
for (int i = 0; i < args.length; i++) { for (int i = 0; i < args.length; i++) {
if (args[i] instanceof ESNode) { if (args[i] instanceof ESNode) {
ESNode esn = (ESNode) args[i]; ESNode esn = (ESNode) args[i];
node.removeNode(esn.getNode()); node.removeNode(esn.getNode());
} }
} }
} }
return true; return true;
} }
/** /**
* Invalidate the node itself or a subnode * Invalidate the node itself or a subnode
*/ */
public boolean invalidate (ESValue args[]) { public boolean invalidate(ESValue[] args) {
if (node instanceof helma.objectmodel.db.Node) { if (node instanceof helma.objectmodel.db.Node) {
if (args.length == 0) { if (args.length == 0) {
((helma.objectmodel.db.Node) node).invalidate(); ((helma.objectmodel.db.Node) node).invalidate();
@ -188,49 +281,63 @@ public class ESNode extends ObjectPrototype {
((helma.objectmodel.db.Node) node).invalidateNode(args[0].toString()); ((helma.objectmodel.db.Node) node).invalidateNode(args[0].toString());
} }
} }
return true; return true;
} }
/** /**
* Check if node is contained in subnodes * Check if node is contained in subnodes
*/ */
public int contains (ESValue args[]) { public int contains(ESValue[] args) {
checkNode(); checkNode();
if (args.length == 1 && args[0] instanceof ESNode) {
if ((args.length == 1) && args[0] instanceof ESNode) {
ESNode esn = (ESNode) args[0]; ESNode esn = (ESNode) args[0];
return node.contains(esn.getNode()); return node.contains(esn.getNode());
} }
return -1; return -1;
} }
/** /**
* Prefetch child objects from (relational) database. * Prefetch child objects from (relational) database.
*/ */
public void prefetchChildren (ESValue args[]) throws Exception { public void prefetchChildren(ESValue[] args) throws Exception {
checkNode(); checkNode();
if (!(node instanceof Node))
if (!(node instanceof Node)) {
return; return;
int start = 0, length = 0; }
int start = 0;
int length = 0;
try { try {
if (args.length == 0) { if (args.length == 0) {
start = 0; start = 0;
length = 1000; length = 1000;
} else if (args.length == 2) { } else if (args.length == 2) {
if (args[0].isNumberValue ()) if (args[0].isNumberValue()) {
start = args[0].toInt32(); start = args[0].toInt32();
else } else {
throw new RuntimeException ("Illegal argument in prefetchChildren: "+args[0]); throw new RuntimeException("Illegal argument in prefetchChildren: " +
if (args[1].isNumberValue ()) args[0]);
}
if (args[1].isNumberValue()) {
length = args[1].toInt32(); length = args[1].toInt32();
else } else {
throw new RuntimeException ("Illegal argument in prefetchChildren: "+args[1]); throw new RuntimeException("Illegal argument in prefetchChildren: " +
args[1]);
}
} else { } else {
throw new RuntimeException("Wrong number of arguments in prefetchChildren"); throw new RuntimeException("Wrong number of arguments in prefetchChildren");
} }
} catch (Exception x) { } catch (Exception x) {
throw new IllegalArgumentException(x.getMessage()); throw new IllegalArgumentException(x.getMessage());
} }
((Node) node).prefetchChildren(start, length); ((Node) node).prefetchChildren(start, length);
} }
@ -238,74 +345,116 @@ public class ESNode extends ObjectPrototype {
* This used to be different from add(), it isn't anymore. It's left here for * This used to be different from add(), it isn't anymore. It's left here for
* compatibility. * compatibility.
*/ */
public boolean link (ESValue args[]) { public boolean link(ESValue[] args) {
checkNode(); checkNode();
for (int i = 0; i < args.length; i++) { for (int i = 0; i < args.length; i++) {
if (args[i] instanceof ESNode) { if (args[i] instanceof ESNode) {
ESNode esn = (ESNode) args[i]; ESNode esn = (ESNode) args[i];
node.addNode(esn.getNode()); node.addNode(esn.getNode());
} }
} }
return true; return true;
} }
/**
*
*
* @param pval ...
*
* @return ...
*/
public boolean setParent(ESValue[] pval) { public boolean setParent(ESValue[] pval) {
// do a couple of checks: both nodes need to be persistent in order for setParent to make sense. // do a couple of checks: both nodes need to be persistent in order for setParent to make sense.
if (!(node instanceof helma.objectmodel.db.Node)) if (!(node instanceof helma.objectmodel.db.Node)) {
return false; return false;
if (pval == null || pval.length < 1 || pval.length > 2) }
if ((pval == null) || (pval.length < 1) || (pval.length > 2)) {
return false; return false;
if (!(pval[0] instanceof ESNode)) }
if (!(pval[0] instanceof ESNode)) {
return false; return false;
}
ESNode esn = (ESNode) pval[0]; ESNode esn = (ESNode) pval[0];
INode pn = esn.getNode(); INode pn = esn.getNode();
if (!(pn instanceof helma.objectmodel.db.Node))
if (!(pn instanceof helma.objectmodel.db.Node)) {
return false; return false;
}
// check if there is an additional string element - if so, it's the property name by which the node is // check if there is an additional string element - if so, it's the property name by which the node is
// accessed, otherwise it will be accessed as anonymous subnode via its id // accessed, otherwise it will be accessed as anonymous subnode via its id
String propname = null; String propname = null;
if (pval.length == 2 && pval[1] != null && !(pval[1] instanceof ESNull))
if ((pval.length == 2) && (pval[1] != null) && !(pval[1] instanceof ESNull)) {
propname = pval[1].toString(); propname = pval[1].toString();
}
helma.objectmodel.db.Node n = (helma.objectmodel.db.Node) node; helma.objectmodel.db.Node n = (helma.objectmodel.db.Node) node;
n.setParent((helma.objectmodel.db.Node) pn, propname); n.setParent((helma.objectmodel.db.Node) pn, propname);
return true; return true;
} }
/**
public void putProperty(String propertyName, ESValue propertyValue, int hash) throws EcmaScriptException { *
*
* @param propertyName ...
* @param propertyValue ...
* @param hash ...
*
* @throws EcmaScriptException ...
*/
public void putProperty(String propertyName, ESValue propertyValue, int hash)
throws EcmaScriptException {
checkNode(); checkNode();
// engine.app.logEvent ("put property called: "+propertyName+", "+propertyValue.getClass()); // engine.app.logEvent ("put property called: "+propertyName+", "+propertyValue.getClass());
if ("cache".equalsIgnoreCase (propertyName)) if ("cache".equalsIgnoreCase(propertyName)) {
throw new EcmaScriptException ("Can't modify read-only property \""+propertyName+"\"."); throw new EcmaScriptException("Can't modify read-only property \"" +
propertyName + "\".");
}
if ("subnodeRelation".equalsIgnoreCase(propertyName)) { if ("subnodeRelation".equalsIgnoreCase(propertyName)) {
node.setSubnodeRelation (propertyValue instanceof ESNull ? null : propertyValue.toString ()); node.setSubnodeRelation((propertyValue instanceof ESNull) ? null
: propertyValue.toString());
return; return;
} }
// check if the property is write protected, i.e. the type.property file describes it as [readonly] // check if the property is write protected, i.e. the type.property file describes it as [readonly]
DbMapping dbm = node.getDbMapping(); DbMapping dbm = node.getDbMapping();
if (dbm != null) { if (dbm != null) {
Relation rel = dbm.getPropertyRelation(propertyName); Relation rel = dbm.getPropertyRelation(propertyName);
if (rel != null && rel.isReadonly ())
if ((rel != null) && rel.isReadonly()) {
return; return;
} }
}
if (propertyValue instanceof ESNull || propertyValue instanceof ESUndefined) if (propertyValue instanceof ESNull || propertyValue instanceof ESUndefined) {
node.unset(propertyName); node.unset(propertyName);
else if (propertyValue instanceof ESString) } else if (propertyValue instanceof ESString) {
node.setString(propertyName, propertyValue.toString()); node.setString(propertyName, propertyValue.toString());
else if (propertyValue instanceof ESBoolean) } else if (propertyValue instanceof ESBoolean) {
node.setBoolean(propertyName, propertyValue.booleanValue()); node.setBoolean(propertyName, propertyValue.booleanValue());
else if (propertyValue instanceof ESNumber) } else if (propertyValue instanceof ESNumber) {
node.setFloat(propertyName, propertyValue.doubleValue()); node.setFloat(propertyName, propertyValue.doubleValue());
else if (propertyValue instanceof DatePrototype) } else if (propertyValue instanceof DatePrototype) {
node.setDate(propertyName, (Date) propertyValue.toJavaObject()); node.setDate(propertyName, (Date) propertyValue.toJavaObject());
else if (propertyValue instanceof ESNode) { } else if (propertyValue instanceof ESNode) {
// long now = System.currentTimeMillis (); // long now = System.currentTimeMillis ();
ESNode esn = (ESNode) propertyValue; ESNode esn = (ESNode) propertyValue;
node.setNode(propertyName, esn.getNode()); node.setNode(propertyName, esn.getNode());
// engine.app.logEvent ("*** spent "+(System.currentTimeMillis () - now)+" ms to set property "+propertyName); // engine.app.logEvent ("*** spent "+(System.currentTimeMillis () - now)+" ms to set property "+propertyName);
} else { } else {
// engine.app.logEvent ("got "+propertyValue.getClass ()); // engine.app.logEvent ("got "+propertyValue.getClass ());
@ -315,33 +464,71 @@ public class ESNode extends ObjectPrototype {
} }
} }
public boolean deleteProperty(String propertyName, int hash) throws EcmaScriptException { /**
*
*
* @param propertyName ...
* @param hash ...
*
* @return ...
*
* @throws EcmaScriptException ...
*/
public boolean deleteProperty(String propertyName, int hash)
throws EcmaScriptException {
checkNode(); checkNode();
// engine.app.logEvent ("delete property called: "+propertyName); // engine.app.logEvent ("delete property called: "+propertyName);
if (node.get(propertyName) != null) { if (node.get(propertyName) != null) {
node.unset(propertyName); node.unset(propertyName);
return true; return true;
} }
return super.deleteProperty(propertyName, hash); return super.deleteProperty(propertyName, hash);
} }
/**
*
*
* @param i ...
*
* @return ...
*
* @throws EcmaScriptException ...
*/
public ESValue getProperty(int i) throws EcmaScriptException { public ESValue getProperty(int i) throws EcmaScriptException {
checkNode(); checkNode();
INode n = node.getSubnodeAt(i); INode n = node.getSubnodeAt(i);
if (n == null)
if (n == null) {
return ESNull.theNull; return ESNull.theNull;
}
return engine.getNodeWrapper(n); return engine.getNodeWrapper(n);
} }
public void putProperty(int index, ESValue propertyValue) throws EcmaScriptException { /**
*
*
* @param index ...
* @param propertyValue ...
*
* @throws EcmaScriptException ...
*/
public void putProperty(int index, ESValue propertyValue)
throws EcmaScriptException {
checkNode(); checkNode();
if (propertyValue instanceof ESNode) { if (propertyValue instanceof ESNode) {
ESNode n = (ESNode) propertyValue; ESNode n = (ESNode) propertyValue;
node.addNode(n.getNode(), index); node.addNode(n.getNode(), index);
} else } else {
throw new EcmaScriptException("Can only add Nodes to Node arrays"); throw new EcmaScriptException("Can only add Nodes to Node arrays");
} }
}
/** /**
* Retrieve a property from the node object or the underlying EcmaScript prototype. * Retrieve a property from the node object or the underlying EcmaScript prototype.
@ -351,12 +538,17 @@ public class ESNode extends ObjectPrototype {
* because generally things are divided cleanly between prototype and object - the * because generally things are divided cleanly between prototype and object - the
* first holds the functions, the latter the mapped data properties. * first holds the functions, the latter the mapped data properties.
*/ */
public ESValue getProperty(String propertyName, int hash) throws EcmaScriptException { public ESValue getProperty(String propertyName, int hash)
throws EcmaScriptException {
checkNode(); checkNode();
// engine.app.logEvent ("get property called: "+propertyName); // engine.app.logEvent ("get property called: "+propertyName);
ESValue retval = super.getProperty(propertyName, hash); ESValue retval = super.getProperty(propertyName, hash);
if (! (retval instanceof ESUndefined))
if (!(retval instanceof ESUndefined)) {
return retval; return retval;
}
return getNodeProperty(propertyName); return getNodeProperty(propertyName);
} }
@ -365,62 +557,89 @@ public class ESNode extends ObjectPrototype {
* This is called directly when we call get(x) on a hopobject, since we don't want to return * This is called directly when we call get(x) on a hopobject, since we don't want to return
* the prototype functions in that case. * the prototype functions in that case.
*/ */
public ESValue getNodeProperty (String propertyName) throws EcmaScriptException { public ESValue getNodeProperty(String propertyName)
throws EcmaScriptException {
// check for null // check for null
if (propertyName == null) if (propertyName == null) {
return ESNull.theNull; return ESNull.theNull;
}
// persistent or persistent capable nodes have a cache property that's a transient node. // persistent or persistent capable nodes have a cache property that's a transient node.
// it it hasn't requested before, initialize it now // it it hasn't requested before, initialize it now
if ("cache".equalsIgnoreCase(propertyName) && node instanceof Node) { if ("cache".equalsIgnoreCase(propertyName) && node instanceof Node) {
cache = node.getCacheNode(); cache = node.getCacheNode();
if (cacheWrapper == null)
if (cacheWrapper == null) {
cacheWrapper = new ESNode(cache, engine); cacheWrapper = new ESNode(cache, engine);
else } else {
cacheWrapper.node = cache; cacheWrapper.node = cache;
}
return cacheWrapper; return cacheWrapper;
} }
if ("subnodeRelation".equalsIgnoreCase(propertyName)) { if ("subnodeRelation".equalsIgnoreCase(propertyName)) {
String rel = node.getSubnodeRelation(); String rel = node.getSubnodeRelation();
return rel == null ? (ESValue) ESNull.theNull : new ESString (rel);
return (rel == null) ? (ESValue) ESNull.theNull : new ESString(rel);
} }
// Everything starting with an underscore is interpreted as internal property // Everything starting with an underscore is interpreted as internal property
if (propertyName.startsWith ("_")) if (propertyName.startsWith("_")) {
return getInternalProperty(propertyName); return getInternalProperty(propertyName);
}
// this _may_ do a relational query if properties are mapped to a relational type. // this _may_ do a relational query if properties are mapped to a relational type.
IProperty p = node.get(propertyName); IProperty p = node.get(propertyName);
if (p != null) { if (p != null) {
if (p.getType() == IProperty.STRING) { if (p.getType() == IProperty.STRING) {
String str = p.getStringValue(); String str = p.getStringValue();
if (str == null)
if (str == null) {
return ESNull.theNull; return ESNull.theNull;
else } else {
return new ESString(str); return new ESString(str);
} }
if (p.getType () == IProperty.BOOLEAN) }
if (p.getType() == IProperty.BOOLEAN) {
return ESBoolean.makeBoolean(p.getBooleanValue()); return ESBoolean.makeBoolean(p.getBooleanValue());
if (p.getType () == IProperty.DATE) }
if (p.getType() == IProperty.DATE) {
return new DatePrototype(evaluator, p.getDateValue()); return new DatePrototype(evaluator, p.getDateValue());
if (p.getType () == IProperty.INTEGER) }
if (p.getType() == IProperty.INTEGER) {
return new ESNumber((double) p.getIntegerValue()); return new ESNumber((double) p.getIntegerValue());
if (p.getType () == IProperty.FLOAT) }
if (p.getType() == IProperty.FLOAT) {
return new ESNumber(p.getFloatValue()); return new ESNumber(p.getFloatValue());
}
if (p.getType() == IProperty.NODE) { if (p.getType() == IProperty.NODE) {
INode nd = p.getNodeValue(); INode nd = p.getNodeValue();
if (nd == null)
if (nd == null) {
return ESNull.theNull; return ESNull.theNull;
else } else {
return engine.getNodeWrapper(nd); return engine.getNodeWrapper(nd);
} }
if (p.getType () == IProperty.JAVAOBJECT) }
if (p.getType() == IProperty.JAVAOBJECT) {
return ESLoader.normalizeObject(p.getJavaObjectValue(), evaluator); return ESLoader.normalizeObject(p.getJavaObjectValue(), evaluator);
} }
}
// as last resort, try to get property as anonymous subnode // as last resort, try to get property as anonymous subnode
INode anon = (INode) node.getChildElement(propertyName); INode anon = (INode) node.getChildElement(propertyName);
if (anon != null)
if (anon != null) {
return engine.getNodeWrapper(anon); return engine.getNodeWrapper(anon);
}
return ESNull.theNull; return ESNull.theNull;
} }
@ -429,72 +648,124 @@ public class ESNode extends ObjectPrototype {
* Some internal properties defined for every Node object. These are most commonly * Some internal properties defined for every Node object. These are most commonly
* used for debugging Helma applications. * used for debugging Helma applications.
*/ */
private ESValue getInternalProperty (String propertyName) throws EcmaScriptException { private ESValue getInternalProperty(String propertyName)
throws EcmaScriptException {
if ("__id__".equals(propertyName) || "_id".equals(propertyName)) { if ("__id__".equals(propertyName) || "_id".equals(propertyName)) {
return new ESString(node.getID()); return new ESString(node.getID());
} }
if ("__prototype__".equals(propertyName) || "_prototype".equals(propertyName)) { if ("__prototype__".equals(propertyName) || "_prototype".equals(propertyName)) {
String p = node.getPrototype(); String p = node.getPrototype();
if (p == null)
if (p == null) {
return ESNull.theNull; return ESNull.theNull;
else } else {
return new ESString(node.getPrototype()); return new ESString(node.getPrototype());
} }
}
if ("__parent__".equals(propertyName) || "_parent".equals(propertyName)) { if ("__parent__".equals(propertyName) || "_parent".equals(propertyName)) {
INode n = node.getParent(); INode n = node.getParent();
if (n == null)
if (n == null) {
return ESNull.theNull; return ESNull.theNull;
else } else {
return engine.getNodeWrapper(n); return engine.getNodeWrapper(n);
} }
}
// some more internal properties // some more internal properties
if ("__name__".equals (propertyName)) if ("__name__".equals(propertyName)) {
return new ESString(node.getName()); return new ESString(node.getName());
if ("__fullname__".equals (propertyName)) }
if ("__fullname__".equals(propertyName)) {
return new ESString(node.getFullName()); return new ESString(node.getFullName());
if ("__hash__".equals (propertyName)) }
if ("__hash__".equals(propertyName)) {
return new ESString("" + node.hashCode()); return new ESString("" + node.hashCode());
if ("__node__".equals (propertyName)) }
if ("__node__".equals(propertyName)) {
return new ESWrapper(node, evaluator); return new ESWrapper(node, evaluator);
if ("__created__".equalsIgnoreCase (propertyName)) }
if ("__created__".equalsIgnoreCase(propertyName)) {
return new DatePrototype(evaluator, node.created()); return new DatePrototype(evaluator, node.created());
if ("__lastmodified__".equalsIgnoreCase (propertyName)) }
if ("__lastmodified__".equalsIgnoreCase(propertyName)) {
return new DatePrototype(evaluator, node.lastModified()); return new DatePrototype(evaluator, node.lastModified());
}
return ESNull.theNull; return ESNull.theNull;
} }
/**
*
*
* @return ...
*/
public boolean clearCache() { public boolean clearCache() {
checkNode(); checkNode();
node.clearCacheNode(); node.clearCacheNode();
return true; return true;
} }
/**
*
*
* @return ...
*/
public Enumeration getAllProperties() { public Enumeration getAllProperties() {
return getProperties(); return getProperties();
} }
/**
*
*
* @return ...
*/
public Enumeration getProperties() { public Enumeration getProperties() {
checkNode(); checkNode();
return node.properties(); return node.properties();
} }
/**
*
*
* @return ...
*/
public String error() { public String error() {
if (lastError == null) { if (lastError == null) {
return ""; return "";
} else { } else {
String exceptionName = lastError.getClass().getName(); String exceptionName = lastError.getClass().getName();
int l = exceptionName.lastIndexOf("."); int l = exceptionName.lastIndexOf(".");
if (l>0) exceptionName = exceptionName.substring(l+1);
if (l > 0) {
exceptionName = exceptionName.substring(l + 1);
}
return exceptionName + ": " + lastError.getMessage(); return exceptionName + ": " + lastError.getMessage();
} }
} }
/**
*
*/
public void clearError() { public void clearError() {
lastError = null; lastError = null;
} }
/**
*
*
* @return ...
*/
public Object toJavaObject() { public Object toJavaObject() {
return getNode(); return getNode();
} }
@ -504,25 +775,38 @@ public class ESNode extends ObjectPrototype {
* or the wrapped INode itself. FIXME: doesen't check dbmapping/type! * or the wrapped INode itself. FIXME: doesen't check dbmapping/type!
*/ */
public boolean equals(Object what) { public boolean equals(Object what) {
if (what == null) if (what == null) {
return false;
if (what == this)
return true;
if (what instanceof ESNode) {
ESNode other = (ESNode) what;
if (handle != null)
return handle.equals (other.handle);
else
return (node == other.node);
}
return false; return false;
} }
if (what == this) {
return true;
}
if (what instanceof ESNode) {
ESNode other = (ESNode) what;
if (handle != null) {
return handle.equals(other.handle);
} else {
return (node == other.node);
}
}
return false;
}
/**
*
*
* @param hint ...
*
* @return ...
*
* @throws EcmaScriptException ...
*/
public ESValue getDefaultValue(int hint) throws EcmaScriptException { public ESValue getDefaultValue(int hint) throws EcmaScriptException {
return new ESString(this.toString()); return new ESString(this.toString());
} }
}
} // class ESNode // class ESNode

View file

@ -1,71 +1,93 @@
// ActionFile.java /*
// Copyright (c) Hannes Wallnöfer 1998-2000 * Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.scripting.fesi; package helma.scripting.fesi;
import helma.scripting.*;
import java.util.Vector;
import java.util.Iterator;
import java.io.*;
import helma.framework.*;
import helma.framework.core.*;
import helma.util.Updatable;
import FESI.Data.*;
import FESI.Parser.*;
import FESI.AST.ASTFormalParameterList; import FESI.AST.ASTFormalParameterList;
import FESI.AST.ASTStatementList; import FESI.AST.ASTStatementList;
import FESI.AST.EcmaScriptTreeConstants; import FESI.AST.EcmaScriptTreeConstants;
import FESI.Interpreter.*; import FESI.Data.*;
import FESI.Exceptions.*; import FESI.Exceptions.*;
import FESI.Interpreter.*;
import FESI.Parser.*;
import helma.framework.*;
import helma.framework.core.*;
import helma.scripting.*;
import helma.util.Updatable;
import java.io.*;
import java.util.Iterator;
import java.util.Vector;
/** /**
* An class that updates fesi interpreters with actionfiles and templates. * An class that updates fesi interpreters with actionfiles and templates.
*/ */
public class FesiActionAdapter { public class FesiActionAdapter {
Prototype prototype; Prototype prototype;
Application app; Application app;
String functionName; String functionName;
String sourceName; String sourceName;
// this is the parsed function which can be easily applied to FesiEngine objects
TypeUpdater pfunc, pfuncAsString;
// this is the parsed function which can be easily applied to FesiEngine objects
TypeUpdater pfunc;
// this is the parsed function which can be easily applied to FesiEngine objects
TypeUpdater pfuncAsString;
/**
* Creates a new FesiActionAdapter object.
*
* @param action ...
*/
public FesiActionAdapter(ActionFile action) { public FesiActionAdapter(ActionFile action) {
prototype = action.getPrototype(); prototype = action.getPrototype();
app = action.getApplication(); app = action.getApplication();
Reader reader = null; Reader reader = null;
functionName = action.getFunctionName(); functionName = action.getFunctionName();
sourceName = action.getSourceName(); sourceName = action.getSourceName();
try { try {
reader = action.getReader(); reader = action.getReader();
pfunc = parseFunction(functionName, pfunc = parseFunction(functionName,
"arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10", "arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10",
reader, reader, sourceName);
sourceName);
} catch (Throwable x) { } catch (Throwable x) {
String message = x.getMessage(); String message = x.getMessage();
pfunc = new ErrorFeedback(functionName, message); pfunc = new ErrorFeedback(functionName, message);
} finally { } finally {
try { try {
reader.close(); reader.close();
} catch (Exception ignore) {} } catch (Exception ignore) {
} }
}
// check if this is a template and we need to generate an "_as_string" variant // check if this is a template and we need to generate an "_as_string" variant
if (action instanceof Template) { if (action instanceof Template) {
String content = "res.pushStringBuffer(); " + String content = "res.pushStringBuffer(); " + action.getContent() +
action.getContent () +
"\r\nreturn res.popStringBuffer();\r\n"; "\r\nreturn res.popStringBuffer();\r\n";
try { try {
pfuncAsString = parseFunction(functionName + "_as_string", pfuncAsString = parseFunction(functionName + "_as_string",
"arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10", "arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10",
new StringReader(content), new StringReader(content), sourceName);
sourceName);
} catch (Throwable x) { } catch (Throwable x) {
String message = x.getMessage(); String message = x.getMessage();
pfunc = new ErrorFeedback(functionName + "_as_string", message); pfunc = new ErrorFeedback(functionName + "_as_string", message);
} }
} else { } else {
@ -73,16 +95,27 @@ public class FesiActionAdapter {
} }
} }
/**
public synchronized void updateEvaluator (FesiEngine engine) throws EcmaScriptException { *
if (pfunc != null) *
* @param engine ...
*
* @throws EcmaScriptException ...
*/
public synchronized void updateEvaluator(FesiEngine engine)
throws EcmaScriptException {
if (pfunc != null) {
pfunc.updateEvaluator(engine); pfunc.updateEvaluator(engine);
if (pfuncAsString != null)
pfuncAsString.updateEvaluator (engine);
} }
protected TypeUpdater parseFunction (String funcName, String params, Reader body, String sourceName) throws EcmaScriptException { if (pfuncAsString != null) {
pfuncAsString.updateEvaluator(engine);
}
}
protected TypeUpdater parseFunction(String funcName, String params, Reader body,
String sourceName)
throws EcmaScriptException {
// ESObject fp = app.eval.evaluator.getFunctionPrototype(); // ESObject fp = app.eval.evaluator.getFunctionPrototype();
// ConstructedFunctionObject function = null; // ConstructedFunctionObject function = null;
ASTFormalParameterList fpl = null; ASTFormalParameterList fpl = null;
@ -93,8 +126,11 @@ public class FesiActionAdapter {
body = ";\r\n"; body = ";\r\n";
else else
body = body + "\r\n"; */ body = body + "\r\n"; */
if (params == null) params = ""; if (params == null) {
else params = params.trim (); params = "";
} else {
params = params.trim();
}
EcmaScript parser; EcmaScript parser;
StringReader is; StringReader is;
@ -105,13 +141,17 @@ public class FesiActionAdapter {
} else { } else {
is = new java.io.StringReader(params); is = new java.io.StringReader(params);
parser = new EcmaScript(is); parser = new EcmaScript(is);
try { try {
fpl = (ASTFormalParameterList) parser.FormalParameterList(); fpl = (ASTFormalParameterList) parser.FormalParameterList();
is.close(); is.close();
} catch (ParseException x) { } catch (ParseException x) {
throw new EcmaScriptParseException (x, new FileEvaluationSource(sourceName, null)); throw new EcmaScriptParseException(x,
new FileEvaluationSource(sourceName,
null));
} }
} }
// this is very very very strange: without the toString, lots of obscure exceptions // this is very very very strange: without the toString, lots of obscure exceptions
// deep inside the parser... // deep inside the parser...
// is = new java.io.StringReader(body.toString ()); // is = new java.io.StringReader(body.toString ());
@ -120,27 +160,37 @@ public class FesiActionAdapter {
sl = (ASTStatementList) parser.StatementList(); sl = (ASTStatementList) parser.StatementList();
body.close(); body.close();
} catch (ParseException x) { } catch (ParseException x) {
app.logEvent ("Error parsing file "+app.getName()+":"+sourceName+": "+x); app.logEvent("Error parsing file " + app.getName() + ":" + sourceName + ": " +
throw new EcmaScriptParseException (x, new FileEvaluationSource(sourceName, null)); x);
throw new EcmaScriptParseException(x,
new FileEvaluationSource(sourceName, null));
} catch (Exception x) { } catch (Exception x) {
app.logEvent ("Error parsing file "+app.getName()+":"+sourceName+": "+x); app.logEvent("Error parsing file " + app.getName() + ":" + sourceName + ": " +
x);
throw new RuntimeException(x.getMessage()); throw new RuntimeException(x.getMessage());
} }
fes = new FunctionEvaluationSource (new FileEvaluationSource(sourceName, null), funcName); fes = new FunctionEvaluationSource(new FileEvaluationSource(sourceName, null),
funcName);
return new ParsedFunction(fpl, sl, fes, null, funcName); return new ParsedFunction(fpl, sl, fes, null, funcName);
} }
class ParsedFunction implements TypeUpdater { interface TypeUpdater {
public void updateEvaluator(FesiEngine engine)
throws EcmaScriptException;
}
class ParsedFunction implements TypeUpdater {
ASTFormalParameterList fpl = null; ASTFormalParameterList fpl = null;
ASTStatementList sl = null; ASTStatementList sl = null;
FunctionEvaluationSource fes = null; FunctionEvaluationSource fes = null;
String fullFunctionText = null; String fullFunctionText = null;
String functionName; String functionName;
public ParsedFunction (ASTFormalParameterList fpl, ASTStatementList sl, FunctionEvaluationSource fes, public ParsedFunction(ASTFormalParameterList fpl, ASTStatementList sl,
String fullFunctionText, String functionName) { FunctionEvaluationSource fes, String fullFunctionText,
String functionName) {
this.fpl = fpl; this.fpl = fpl;
this.sl = sl; this.sl = sl;
this.fes = fes; this.fes = fes;
@ -148,58 +198,63 @@ public class FesiActionAdapter {
this.functionName = functionName; this.functionName = functionName;
} }
public void updateEvaluator (FesiEngine engine) throws EcmaScriptException { public void updateEvaluator(FesiEngine engine)
throws EcmaScriptException {
ObjectPrototype op = engine.getPrototype(prototype.getName()); ObjectPrototype op = engine.getPrototype(prototype.getName());
EcmaScriptVariableVisitor vdvisitor = engine.evaluator.getVarDeclarationVisitor(); EcmaScriptVariableVisitor vdvisitor = engine.evaluator.getVarDeclarationVisitor();
Vector vnames = vdvisitor.processVariableDeclarations(sl, fes); Vector vnames = vdvisitor.processVariableDeclarations(sl, fes);
FunctionPrototype fp = ConstructedFunctionObject.makeNewConstructedFunction ( FunctionPrototype fp = ConstructedFunctionObject.makeNewConstructedFunction(engine.evaluator,
engine.evaluator, functionName, fes, functionName,
fullFunctionText, fpl.getArguments(), vnames, sl); fes,
fullFunctionText,
fpl.getArguments(),
vnames,
sl);
op.putHiddenProperty(functionName, fp); op.putHiddenProperty(functionName, fp);
} }
} }
class ErrorFeedback implements TypeUpdater { class ErrorFeedback implements TypeUpdater {
String functionName;
String functionName, errorMessage; String errorMessage;
public ErrorFeedback(String fname, String msg) { public ErrorFeedback(String fname, String msg) {
functionName = fname; functionName = fname;
errorMessage = msg; errorMessage = msg;
} }
public void updateEvaluator (FesiEngine engine) throws EcmaScriptException { public void updateEvaluator(FesiEngine engine)
throws EcmaScriptException {
ObjectPrototype op = engine.getPrototype(prototype.getName()); ObjectPrototype op = engine.getPrototype(prototype.getName());
FunctionPrototype fp = (FunctionPrototype) engine.evaluator.getFunctionPrototype(); FunctionPrototype fp = (FunctionPrototype) engine.evaluator.getFunctionPrototype();
FunctionPrototype func = new ThrowException (functionName, engine.evaluator, fp, errorMessage); FunctionPrototype func = new ThrowException(functionName, engine.evaluator,
op.putHiddenProperty (functionName, func); fp, errorMessage);
op.putHiddenProperty(functionName, func);
} }
} }
class ThrowException extends BuiltinFunctionObject { class ThrowException extends BuiltinFunctionObject {
String message; String message;
ThrowException (String name, Evaluator evaluator, FunctionPrototype fp, String message) {
ThrowException(String name, Evaluator evaluator, FunctionPrototype fp,
String message) {
super(fp, evaluator, name, 1); super(fp, evaluator, name, 1);
this.message = message == null ? "No error message available" : message; this.message = (message == null) ? "No error message available" : message;
} }
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
public ESValue callFunction(ESObject thisObject, ESValue[] arguments)
throws EcmaScriptException {
throw new EcmaScriptException(message); throw new EcmaScriptException(message);
} }
public ESObject doConstruct (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
public ESObject doConstruct(ESObject thisObject, ESValue[] arguments)
throws EcmaScriptException {
throw new EcmaScriptException(message); throw new EcmaScriptException(message);
} }
} }
interface TypeUpdater {
public void updateEvaluator (FesiEngine engine) throws EcmaScriptException;
} }
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

Some files were not shown because too many files have changed in this diff Show more