Merge from helma_1_2_4

This commit is contained in:
hns 2003-04-16 16:28:04 +00:00
parent df40e73b63
commit 66663c8b20
177 changed files with 28899 additions and 18112 deletions

View file

@ -1,98 +1,197 @@
/*
* 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;
import helma.framework.IPathElement;
import helma.main.Server;
import helma.util.SystemProperties;
import java.io.*;
import java.util.*;
public class DocApplication extends DocDirElement {
/**
*
*/
public class DocApplication extends DocDirElement {
HashSet excluded;
public static void main (String args[]) {
// DocApplication app;
// app = new DocApplication (args[0], args[1]);
// app.readApplication ();
/**
* Creates a new DocApplication object.
*
* @param name ...
* @param location ...
*
* @throws DocException ...
*/
public DocApplication(String name, File location) throws DocException {
super(name, location, APPLICATION);
readProps();
}
// DocPrototype el = DocPrototype.newInstance (new File(args[0]));
// el.readFiles ();
/**
* Creates a new DocApplication object.
*
* @param name ...
* @param appDir ...
*
* @throws DocException ...
*/
public DocApplication(String name, String appDir) throws DocException {
super(name, new File(appDir), APPLICATION);
readProps();
}
// DocFunction func = DocFunction.newTemplate (new File(args[0]));
// DocFunction func = DocFunction.newAction (new File(args[0]));
/**
*
*
* @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]));
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 ());
}
// 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
*/
private void readProps() {
File propsFile = new File(location, "app.properties");
SystemProperties serverProps = Server.getServer().getProperties();
SystemProperties appProps = new SystemProperties(propsFile.getAbsolutePath(),
serverProps);
excluded = new HashSet();
addExclude("cvs");
addExclude(".docs");
public DocApplication (String name, File location) throws DocException {
super (name, location, APPLICATION);
}
String excludeProps = appProps.getProperty("helma.excludeDocs");
public DocApplication (String name, String appDir) throws DocException {
super (name, new File (appDir), APPLICATION);
}
if (excludeProps != null) {
StringTokenizer tok = new StringTokenizer(excludeProps, ",");
while (tok.hasMoreTokens()) {
String str = tok.nextToken().trim();
/**
* reads all prototypes and files of the application
*/
public void readApplication () {
String arr[] = location.list ();
children.clear ();
for (int i=0; i<arr.length; i++) {
if (Util.isExcluded (arr[i]))
continue;
File f = new File (location.getAbsolutePath (), arr[i]);
if (!f.isDirectory ())
continue;
try {
DocPrototype pt = DocPrototype.newInstance (f, this);
addChild (pt);
pt.readFiles ();
} catch (DocException e) {
debug ("Couldn't read prototype " + arr[i] + ": " + e.getMessage ());
}
System.out.println (f);
}
for (Iterator i=children.values ().iterator (); i.hasNext ();) {
((DocPrototype) i.next ()).checkInheritance ();
}
}
addExclude(str);
}
}
}
public DocElement[] listFunctions () {
Vector allFunctions = new Vector ();
for (Iterator i = children.values ().iterator (); i.hasNext ();) {
DocElement proto = (DocElement) i.next ();
allFunctions.addAll (proto.children.values ());
}
Collections.sort (allFunctions, new DocComparator (DocComparator.BY_NAME, this));
return (DocElement[]) allFunctions.toArray (new DocElement[allFunctions.size ()]);
}
/**
*
*
* @param str ...
*/
public void addExclude(String str) {
excluded.add(str.toLowerCase());
}
/**
*
*
* @param str ...
*
* @return ...
*/
public boolean isExcluded(String str) {
return (excluded.contains(str.toLowerCase()));
}
/**
* from helma.framework.IPathElement, overridden with "api"
* to work in manage-application
*/
public String getElementName() {
return "api";
}
/**
* reads all prototypes and files of the application
*/
public void readApplication() {
readProps();
String[] arr = location.list();
/**
* from helma.framework.IPathElement, overridden with
* Server.getServer() to work in manage-application
*/
public IPathElement getParentElement() {
Server s = helma.main.Server.getServer();
return s.getChildElement(this.name);
}
children.clear();
for (int i = 0; i < arr.length; i++) {
if (isExcluded(arr[i])) {
continue;
}
File f = new File(location.getAbsolutePath(), arr[i]);
if (!f.isDirectory()) {
continue;
}
try {
DocPrototype pt = DocPrototype.newInstance(f, this);
addChild(pt);
pt.readFiles();
} catch (DocException e) {
debug("Couldn't read prototype " + arr[i] + ": " + e.getMessage());
}
System.out.println(f);
}
for (Iterator i = children.values().iterator(); i.hasNext();) {
((DocPrototype) i.next()).checkInheritance();
}
}
/**
*
*
* @return ...
*/
public DocElement[] listFunctions() {
Vector allFunctions = new Vector();
for (Iterator i = children.values().iterator(); i.hasNext();) {
DocElement proto = (DocElement) i.next();
allFunctions.addAll(proto.children.values());
}
Collections.sort(allFunctions, new DocComparator(DocComparator.BY_NAME, this));
return (DocElement[]) allFunctions.toArray(new DocElement[allFunctions.size()]);
}
/**
* from helma.framework.IPathElement, overridden with "api"
* to work in manage-application
*/
public String getElementName() {
return "api";
}
/**
* from helma.framework.IPathElement, overridden with
* Server.getServer() to work in manage-application
*/
public IPathElement getParentElement() {
Server s = helma.main.Server.getServer();
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;
import java.util.Comparator;
/**
*
*/
public class DocComparator implements Comparator {
public static final int BY_TYPE = 0;
public static final int BY_NAME = 1;
int mode;
DocElement docEl;
public static final int BY_TYPE = 0;
public static final int BY_NAME = 1;
/**
* Creates a new DocComparator object.
*
* @param mode ...
* @param docEl ...
*/
public DocComparator(int mode, DocElement docEl) {
this.mode = mode;
this.docEl = docEl;
}
int mode;
DocElement docEl;
/**
* Creates a new DocComparator object.
*
* @param docEl ...
*/
public DocComparator(DocElement docEl) {
this.mode = 0;
this.docEl = docEl;
}
public DocComparator(int mode, DocElement docEl) {
this.mode = mode;
this.docEl = docEl;
}
/**
*
*
* @param obj1 ...
* @param obj2 ...
*
* @return ...
*/
public int compare(Object obj1, Object obj2) {
DocElement e1 = (DocElement) obj1;
DocElement e2 = (DocElement) obj2;
public DocComparator(DocElement docEl) {
this.mode = 0;
this.docEl = docEl;
}
if ((mode == BY_TYPE) && (e1.getType() > e2.getType())) {
return 1;
} else if ((mode == BY_TYPE) && (e1.getType() < e2.getType())) {
return -1;
} else {
return e1.name.compareTo(e2.name);
}
}
public int compare(Object obj1, Object obj2) {
DocElement e1 = (DocElement)obj1;
DocElement e2 = (DocElement)obj2;
if (mode==BY_TYPE && e1.getType()>e2.getType())
return 1;
else if (mode==BY_TYPE && e1.getType()<e2.getType())
return -1;
else {
return e1.name.compareTo(e2.name);
}
}
public boolean equals(Object obj) {
DocElement el = (DocElement) obj;
if (el.name.equals(docEl.name) && el.getType()==docEl.getType()) {
return true;
} else {
return false;
}
}
/**
*
*
* @param obj ...
*
* @return ...
*/
public boolean equals(Object obj) {
DocElement el = (DocElement) obj;
if (el.name.equals(docEl.name) && (el.getType() == docEl.getType())) {
return true;
} else {
return false;
}
}
}

View file

@ -1,36 +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.doc;
import FESI.Parser.*;
import java.io.*;
import java.util.*;
import FESI.Parser.*;
/**
*
*/
public abstract class DocDirElement extends DocElement {
// a default file that is read as comment for applications
// and prototypes if found in their directories
public static final String[] DOCFILES = {
"doc.html", "doc.htm", "app.html",
"app.htm", "prototype.html",
"prototype.htm", "index.html", "index.htm"
};
// a default file that is read as comment for applications
// and prototypes if found in their directories
public static final String[] DOCFILES = {
"doc.html", "doc.htm",
"app.html", "app.htm",
"prototype.html", "prototype.htm",
"index.html", "index.htm"
};
protected DocDirElement(String name, File location, int type) {
super(name, location, type);
checkCommentFiles();
}
protected DocDirElement (String name, File location, int type) {
super (name, location, type);
checkCommentFiles ();
}
private void checkCommentFiles() throws DocException {
for (int i = 0; i < DOCFILES.length; i++) {
File f = new File(location, DOCFILES[i]);
private void checkCommentFiles () throws DocException {
for (int i=0; i<DOCFILES.length; i++) {
File f = new File (location, DOCFILES[i]);
if (f.exists ()) {
String rawComment = readFile (f);
parseComment (rawComment);
return;
}
}
}
if (f.exists()) {
String rawComment = readFile(f);
parseComment(rawComment);
return;
}
}
}
}

View file

@ -1,304 +1,403 @@
/*
* 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;
import helma.framework.IPathElement;
import java.io.*;
import java.util.*;
import helma.framework.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;
public abstract class DocElement implements IPathElement {
// above constants are used as array indices
public static final String[] typeNames = {
"Application", "Prototype", "Action",
"Template", "Function", "Macro", "Skin",
"Properties"
};
// identifiers of this element
String name;
int type;
File location;
DocElement parent = null;
Map children = new HashMap ();
// identifiers of this element
String name;
int type;
File location;
DocElement parent = null;
Map children = new HashMap();
// content
String content = "";
String comment = "";
List tags = new Vector ();
List parameters = new Vector ();
// content
String content = "";
String comment = "";
List tags = new Vector();
List parameters = new Vector();
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;
protected DocElement(String name, String location, int type)
throws DocException {
this(name, new File(location), type);
}
// above constants are used as array indices
public static final String[] typeNames = {
"Application",
"Prototype",
"Action",
"Template",
"Function",
"Macro",
"Skin",
"Properties"
};
protected DocElement(String name, File location, int type)
throws DocException {
if (location.exists() == false) {
throw new DocException(name + " not found in " + location.toString());
}
protected DocElement (String name, String location, int type) throws DocException {
this (name, new File (location), type);
}
this.name = name;
this.location = location;
this.type = type;
}
protected DocElement (String name, File location, int type) throws DocException {
if (location.exists()==false)
throw new DocException( name + " not found in " + location.toString ());
this.name = name;
this.location = location;
this.type = type;
}
/**
* the simple name of the element
*/
public String getName() {
return name;
}
/**
* the simple name of the element
*/
public String getName() {
return name;
}
/**
* @return absolute path to location of element
* (directory for apps and prototypes, file for
* methods and properties files)
*/
public File getLocation() {
return location;
}
/**
* @return absolute path to location of element
* (directory for apps and prototypes, file for
* methods and properties files)
*/
public File getLocation() {
return location;
}
/**
*
*
* @return ...
*/
public int getType() {
return type;
}
public int getType() {
return type;
}
/**
*
*
* @return ...
*/
public String getTypeName() {
return typeNames[type];
}
public String getTypeName () {
return typeNames [type];
}
/**
* returns the comment string, empty string if no comment is set.
*/
public String getComment() {
return comment;
}
/**
* the actual content of the doc element (the function body, the properties
* list, the file list etc.
*/
public String getContent() {
return content;
}
/**
* returns the comment string, empty string if no comment is set.
*/
public String getComment () {
return comment;
}
/**
*
*
* @param rawContent ...
*/
public void addTag(String rawContent) {
if (tags == null) {
tags = new Vector();
}
try {
DocTag tag = DocTag.parse(rawContent);
/**
* the actual content of the doc element (the function body, the properties
* list, the file list etc.
*/
public String getContent () {
return content;
}
tags.add(tag);
} catch (DocException doc) {
debug(doc.toString());
}
}
/**
* list all tags
*/
public DocTag[] listTags() {
return (DocTag[]) tags.toArray(new DocTag[0]);
}
public void addTag (String rawContent) {
if (tags==null) {
tags = new Vector ();
}
try {
DocTag tag = DocTag.parse (rawContent);
tags.add (tag);
} catch (DocException doc) {
debug (doc.toString ());
}
}
/**
* filter the tags according to DocTag.TYPE
*/
public DocTag[] listTags(int type) {
Vector retval = new Vector();
for (int i = 0; i < tags.size(); i++) {
if (((DocTag) tags.get(i)).getType() == type) {
retval.add(tags.get(i));
}
}
/**
* list all tags
*/
public DocTag[] listTags () {
return (DocTag[]) tags.toArray (new DocTag[0]);
}
return (DocTag[]) retval.toArray();
}
/**
*
*
* @param param ...
*
* @return ...
*/
public boolean hasParameter(String param) {
return parameters.contains(param);
}
/**
* filter the tags according to DocTag.TYPE
*/
public DocTag[] listTags (int type) {
Vector retval = new Vector ();
for (int i=0; i<tags.size (); i++) {
if ( ((DocTag) tags.get (i)).getType() == type)
retval.add (tags.get (i));
}
return (DocTag[]) retval.toArray ();
}
/**
* the list of parameters
*/
public String[] listParameters() {
return (String[]) parameters.toArray(new String[0]);
}
/**
* add a string to the parameters-list
*/
protected void addParameter(String param) {
parameters.add(param);
}
public boolean hasParameter (String param) {
return parameters.contains (param);
}
/**
* parse rawComment, render DocTags
*/
void parseComment(String rawComment) {
try {
StringTokenizer tok = new StringTokenizer(rawComment, "\n", true);
int BLANK = 0;
int TEXT = 1;
int TAGS = 2;
boolean lastEmpty = false;
int mode = BLANK;
StringBuffer buf = new StringBuffer();
/**
* the list of parameters
*/
public String[] listParameters () {
return (String[]) parameters.toArray (new String[0]);
}
while (tok.hasMoreTokens()) {
String line = Util.chopDelimiters(tok.nextToken().trim());
if ("".equals(line)) {
// if we've already had text, store that this line was empty
lastEmpty = (mode != BLANK) ? true : false;
/**
* add a string to the parameters-list
*/
protected void addParameter (String param) {
parameters.add (param);
}
continue;
}
// if we come here the first time, start with TEXT mode
mode = (mode == BLANK) ? TEXT : mode;
/**
* parse rawComment, render DocTags
*/
void parseComment (String rawComment) {
try {
StringTokenizer tok = new StringTokenizer (rawComment, "\n", true);
int BLANK = 0;
int TEXT = 1;
int TAGS = 2;
boolean lastEmpty = false;
int mode = BLANK;
StringBuffer buf = new StringBuffer ();
while (tok.hasMoreTokens ()) {
String line = Util.chopDelimiters (tok.nextToken ().trim ());
if ("".equals(line)) {
// if we've already had text, store that this line was empty
lastEmpty = (mode!=BLANK) ? true : false;
continue;
}
// if we come here the first time, start with TEXT mode
mode = (mode==BLANK) ? TEXT : mode;
// check if we have a new tag
if (DocTag.isTagStart (line)) {
// if we appended to comment text until now, store that ...
if (mode==TEXT)
comment = buf.toString ();
// if we appended to a tag, store that ...
if (mode==TAGS)
addTag (buf.toString ());
// reset buffer
buf = new StringBuffer ();
mode = TAGS;
}
// append to current buffer
if (lastEmpty==true)
buf.append ("\n");
buf.append (line);
buf.append (" ");
lastEmpty = false;
}
// store the last element, if there was at least one element ...
if (mode==TEXT)
comment = buf.toString ();
else if (mode==TAGS)
addTag (buf.toString ());
} catch (RuntimeException rt) {
debug ("parse error in " + location + ": " + rt.getMessage());
}
}
// check if we have a new tag
if (DocTag.isTagStart(line)) {
// if we appended to comment text until now, store that ...
if (mode == TEXT) {
comment = buf.toString();
}
/**
* utility: read a complete file into a string
*/
protected static String readFile (File file) {
try {
StringBuffer buf = new StringBuffer ();
BufferedReader in = new BufferedReader (new FileReader (file));
String line = in.readLine ();
while(line!=null) {
buf.append (line+"\n");
line = in.readLine ();
}
in.close ();
return buf.toString();
} catch (IOException e) {
return ("");
}
}
// if we appended to a tag, store that ...
if (mode == TAGS) {
addTag(buf.toString());
}
// reset buffer
buf = new StringBuffer();
mode = TAGS;
}
public void setParent (DocElement parent) {
this.parent = parent;
}
// append to current buffer
if (lastEmpty == true) {
buf.append("\n");
}
public void addChild (DocElement child) {
if (child==null)
return;
children.put (child.getElementName (), child);
}
buf.append(line);
buf.append(" ");
lastEmpty = false;
}
public int countChildren () {
return children.size ();
}
// store the last element, if there was at least one element ...
if (mode == TEXT) {
comment = buf.toString();
} else if (mode == TAGS) {
addTag(buf.toString());
}
} catch (RuntimeException rt) {
debug("parse error in " + location + ": " + rt.getMessage());
}
}
public Map getChildren () {
return children;
}
/**
* utility: read a complete file into a string
*/
protected static String readFile(File file) {
try {
StringBuffer buf = new StringBuffer();
BufferedReader in = new BufferedReader(new FileReader(file));
String line = in.readLine();
/**
* returns an array of doc elements, sorted by their name
*/
public DocElement[] listChildren () {
String[] keys = (String[]) children.keySet ().toArray (new String[0]);
Arrays.sort (keys);
DocElement[] arr = new DocElement [keys.length];
for (int i=0; i<keys.length; i++) {
arr [i] = (DocElement) children.get (keys[i]);
}
return arr;
}
while (line != null) {
buf.append(line + "\n");
line = in.readLine();
}
/**
* from helma.framework.IPathElement. Elements are named
* like this: typename_name
*/
public String getElementName() {
return typeNames[type].toLowerCase() + "_" + name;
}
in.close();
return buf.toString();
} catch (IOException e) {
return ("");
}
}
/**
* from helma.framework.IPathElement. Retrieves a child from the
* children map.
*/
public IPathElement getChildElement (String name) {
try {
return (IPathElement) children.get (name);
} catch (ClassCastException cce) {
debug (cce.toString ());
cce.printStackTrace ();
return null;
}
}
/**
*
*
* @param parent ...
*/
public void setParent(DocElement parent) {
this.parent = parent;
}
/**
*
*
* @param child ...
*/
public void addChild(DocElement child) {
if (child == null) {
return;
}
/**
* from helma.framework.IPathElement. Returns the parent object
* of this instance if assigned.
*/
public IPathElement getParentElement () {
return parent;
}
children.put(child.getElementName(), child);
}
/**
*
*
* @return ...
*/
public int countChildren() {
return children.size();
}
/**
* from helma.framework.IPathElement. Prototypes are assigned like
* this: "doc" + typename (e.g. docapplication, docprototype etc)
*/
public java.lang.String getPrototype () {
return "doc" + typeNames[type].toLowerCase ();
}
/**
*
*
* @return ...
*/
public Map getChildren() {
return children;
}
/**
* returns an array of doc elements, sorted by their name
*/
public DocElement[] listChildren() {
String[] keys = (String[]) children.keySet().toArray(new String[0]);
public String toString () {
return "[" + typeNames [type] + " " + name + "]";
}
Arrays.sort(keys);
public static void debug (String msg) {
System.out.println(msg);
}
DocElement[] arr = new DocElement[keys.length];
for (int i = 0; i < keys.length; i++) {
arr[i] = (DocElement) children.get(keys[i]);
}
return arr;
}
/**
* walks up the tree and tries to find a DocApplication object
*/
public DocApplication getDocApplication() {
DocElement el = this;
while (el != null) {
if (el instanceof DocApplication) {
return (DocApplication) el;
}
el = (DocElement) el.getParentElement();
}
return null;
}
/**
* from helma.framework.IPathElement. Elements are named
* like this: typename_name
*/
public String getElementName() {
return typeNames[type].toLowerCase() + "_" + name;
}
/**
* from helma.framework.IPathElement. Retrieves a child from the
* children map.
*/
public IPathElement getChildElement(String name) {
try {
return (IPathElement) children.get(name);
} catch (ClassCastException cce) {
debug(cce.toString());
cce.printStackTrace();
return null;
}
}
/**
* from helma.framework.IPathElement. Returns the parent object
* of this instance if assigned.
*/
public IPathElement getParentElement() {
return parent;
}
/**
* from helma.framework.IPathElement. Prototypes are assigned like
* this: "doc" + typename (e.g. docapplication, docprototype etc)
*/
public java.lang.String getPrototype() {
return "doc" + typeNames[type].toLowerCase();
}
/**
*
*
* @return ...
*/
public String toString() {
return "[" + typeNames[type] + " " + name + "]";
}
/**
*
*
* @param msg ...
*/
public static void debug(String 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;
/**
*
*/
public class DocException extends RuntimeException {
String str;
public DocException (String str) {
super (str);
this.str = str;
/**
* Creates a new DocException object.
*
* @param str ...
*/
public DocException(String str) {
super(str);
this.str = str;
}
/**
*
*
* @return ...
*/
public String getMessage() {
return str;
return str;
}
}

View file

@ -1,84 +1,112 @@
/*
* 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;
import FESI.Parser.*;
import java.io.*;
import java.util.*;
import FESI.Parser.*;
/**
*
*/
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
* and throws an error if the file name doesn't fit.
*/
static protected String nameFromFile (File f, String suffix) throws DocException {
String filename = f.getName ();
if (!filename.endsWith (suffix))
throw new DocException ("file doesn't have suffix " + suffix + ": " + f.toString());
return filename.substring (0, filename.lastIndexOf(suffix));
}
/**
* extracts the function name from a file. basically chops the given suffix
* and throws an error if the file name doesn't fit.
*/
static protected String nameFromFile(File f, String suffix)
throws DocException {
String filename = f.getName();
if (!filename.endsWith(suffix)) {
throw new DocException("file doesn't have suffix " + suffix + ": " +
f.toString());
}
/**
* creates fesi token manager for a given file.
*/
static protected EcmaScriptTokenManager createTokenManager (File f) {
try {
ASCII_CharStream is = new ASCII_CharStream(new FileReader(f), 1, 1);
EcmaScriptTokenManager mgr = new EcmaScriptTokenManager(is,0);
return mgr;
} catch (FileNotFoundException fnfe) {
fnfe.printStackTrace ();
throw new DocException (fnfe.toString ());
}
}
return filename.substring(0, filename.lastIndexOf(suffix));
}
/**
* creates fesi token manager for a given file.
*/
static protected EcmaScriptTokenManager createTokenManager(File f) {
try {
ASCII_CharStream is = new ASCII_CharStream(new FileReader(f), 1, 1);
EcmaScriptTokenManager mgr = new EcmaScriptTokenManager(is, 0);
protected DocFileElement (String name, File location, int type) {
super (name, location, type);
}
return mgr;
} catch (FileNotFoundException fnfe) {
fnfe.printStackTrace();
throw new DocException(fnfe.toString());
}
}
/**
* extracts a part of the source code, used to get the code for a
* single function from a function file. sets the field "content".
*/
protected void parseSource(File sourceFile, int beginLine, int beginColumn,
int endLine, int endColumn) {
StringBuffer buf = new StringBuffer();
int ct = 0;
/**
* extracts a part of the source code, used to get the code for a
* single function from a function file. sets the field "content".
*/
protected void parseSource (File sourceFile, int beginLine, int beginColumn, int endLine, int endColumn) {
StringBuffer buf = new StringBuffer ();
int ct=0;
try {
BufferedReader in = new BufferedReader (new FileReader (sourceFile));
String line="";
while (line!=null) {
line = in.readLine();
if (line==null) break;
ct++;
if (ct==beginLine)
buf.append (line.substring(beginColumn-1, line.length())+"\n");
else if ( ct>beginLine && ct<endLine )
buf.append (line+"\n");
else if (ct==endLine)
buf.append (line.substring(0,endColumn));
}
} catch (Exception e) {
debug (e.getMessage ());
}
content = buf.toString ();
}
try {
BufferedReader in = new BufferedReader(new FileReader(sourceFile));
String line = "";
while (line != null) {
line = in.readLine();
/**
* connects all available specialTokens starting at the given token.
*/
protected void parseCommentFromToken (Token tok) {
StringBuffer buf = new StringBuffer();
while (tok.specialToken!=null) {
buf.append (tok.specialToken.toString() );
tok = tok.specialToken;
}
parseComment (buf.toString().trim());
}
if (line == null) {
break;
}
ct++;
if (ct == beginLine) {
buf.append(line.substring(beginColumn - 1, line.length()) + "\n");
} else if ((ct > beginLine) && (ct < endLine)) {
buf.append(line + "\n");
} else if (ct == endLine) {
buf.append(line.substring(0, endColumn));
}
}
} catch (Exception e) {
debug(e.getMessage());
}
content = buf.toString();
}
/**
* connects all available specialTokens starting at the given token.
*/
protected void parseCommentFromToken(Token tok) {
StringBuffer buf = new StringBuffer();
while (tok.specialToken != null) {
buf.append(tok.specialToken.toString());
tok = tok.specialToken;
}
parseComment(buf.toString().trim());
}
}

View file

@ -1,154 +1,185 @@
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.*;
import java.util.*;
package helma.doc;
import FESI.Parser.*;
import helma.framework.IPathElement;
import java.io.*;
import java.util.*;
/**
*
*/
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
*/
public static DocFunction newAction (File location) {
return newAction (location, null);
}
/**
* creates a new independent DocFunction object of type ACTION
*/
public static DocFunction newAction(File location) {
return newAction(location, null);
}
/**
* creates a new DocFunction object of type ACTION connected to another DocElement
*/
public static DocFunction newAction(File location, DocElement parent) {
String name = nameFromFile(location, ".hac");
DocFunction func = new DocFunction(name, location, parent, ACTION);
/**
* creates a new DocFunction object of type ACTION connected to another DocElement
*/
public static DocFunction newAction (File location, DocElement parent) {
String name = nameFromFile (location, ".hac");
DocFunction func = new DocFunction (name, location, parent, ACTION);
func.parseActionFile ();
return func;
}
func.parseActionFile();
/**
* creates a new independent DocFunction object of type TEMPLATE
*/
public static DocFunction newTemplate (File location) {
return newTemplate (location, null);
}
return func;
}
/**
* creates a new independent DocFunction object of type TEMPLATE
*/
public static DocFunction newTemplate(File location) {
return newTemplate(location, null);
}
/**
* creates a new DocFunction object of type TEMPLATE connected to another DocElement
*/
public static DocFunction newTemplate (File location, DocElement parent) {
String name = nameFromFile (location, ".hsp");
DocFunction func = new DocFunction (name, location, parent, TEMPLATE);
func.parseTemplateFile ();
return func;
}
/**
* creates a new DocFunction object of type TEMPLATE connected to another DocElement
*/
public static DocFunction newTemplate(File location, DocElement parent) {
String name = nameFromFile(location, ".hsp");
DocFunction func = new DocFunction(name, location, parent, TEMPLATE);
func.parseTemplateFile();
/**
* reads a function file and creates independent DocFunction objects of type FUNCTION
*/
public static DocFunction[] newFunctions (File location) {
return newFunctions (location, null);
}
return func;
}
/**
* reads a function file and creates independent DocFunction objects of type FUNCTION
*/
public static DocFunction[] newFunctions(File location) {
return newFunctions(location, null);
}
/**
* reads a function file and creates DocFunction objects of type FUNCTION
* connected to another DocElement.
*/
public static DocFunction[] newFunctions (File location, DocElement parent) {
Vector vec = new Vector ();
EcmaScriptTokenManager mgr = createTokenManager(location);
Token tok = mgr.getNextToken();
while (tok.kind!=0) {
if (tok.kind == EcmaScriptConstants.FUNCTION) {
// store the start position of the function:
int beginLine = tok.beginLine;
int beginColumn = tok.beginColumn;
// the name is stored in the next token:
String funcName = mgr.getNextToken().toString();
// create the function object
DocFunction func;
if (funcName.endsWith("_action"))
func = new DocFunction (funcName, location, parent, ACTION);
else if (funcName.endsWith("_macro"))
func = new DocFunction (funcName, location, parent, MACRO);
else
func = new DocFunction (funcName, location, parent, FUNCTION);
// parse the comment from the special token(s) before this token:
func.parseCommentFromToken (tok);
// find the parameters of this function, but only if it's
// neither macro nor action:
if (func.type==FUNCTION) {
while (tok.kind!=0 && tok.kind!=EcmaScriptConstants.RPAREN) {
if (tok.kind==EcmaScriptConstants.IDENTIFIER) {
func.addParameter (tok.image);
}
tok = mgr.getNextToken ();
}
} else {
tok = mgr.getNextToken ();
}
// now find the end of the function:
int endLine=0, endColumn=0;
while (tok.kind!=0 && tok.kind!=EcmaScriptConstants.FUNCTION) {
endLine = tok.endLine;
endColumn = tok.endColumn;
tok = mgr.getNextToken ();
}
// now we know the exact position of the function in the file,
// re-read it and extract the source code:
func.parseSource (location, beginLine, beginColumn, endLine, endColumn);
vec.add (func);
}
if (tok.kind != EcmaScriptConstants.FUNCTION) {
tok = mgr.getNextToken();
}
}
return (DocFunction[]) vec.toArray (new DocFunction[0]);
}
/**
* reads a function file and creates DocFunction objects of type FUNCTION
* connected to another DocElement.
*/
public static DocFunction[] newFunctions(File location, DocElement parent) {
Vector vec = new Vector();
EcmaScriptTokenManager mgr = createTokenManager(location);
Token tok = mgr.getNextToken();
protected DocFunction (String name, File location, DocElement parent, int type) {
super (name, location, type);
this.parent = parent;
}
while (tok.kind != 0) {
if (tok.kind == EcmaScriptConstants.FUNCTION) {
// store the start position of the function:
int beginLine = tok.beginLine;
int beginColumn = tok.beginColumn;
// the name is stored in the next token:
String funcName = mgr.getNextToken().toString();
/**
* reads the content of a .hac file and parses the comment before the first
* javascript element
*/
private void parseActionFile () {
EcmaScriptTokenManager mgr = createTokenManager(location);
Token tok = mgr.getNextToken();
parseCommentFromToken (tok);
content = readFile (location);
}
// create the function object
DocFunction func;
if (funcName.endsWith("_action")) {
func = new DocFunction(funcName, location, parent, ACTION);
} else if (funcName.endsWith("_macro")) {
func = new DocFunction(funcName, location, parent, MACRO);
} else {
func = new DocFunction(funcName, location, parent, FUNCTION);
}
/**
* reads the content of a .hsp file and parses the comment before the first
* javascript element (only if file starts with &gt;%-tag!).
*/
private void parseTemplateFile () {
content = readFile (location);
StringReader str = new StringReader (content.substring (content.indexOf("<%") + 2, content.indexOf ("%>")));
ASCII_CharStream ascii = new ASCII_CharStream (str,1,1);
EcmaScriptTokenManager mgr = new EcmaScriptTokenManager (ascii);
Token tok = mgr.getNextToken();
parseCommentFromToken (tok);
}
// parse the comment from the special token(s) before this token:
func.parseCommentFromToken(tok);
// find the parameters of this function, but only if it's
// neither macro nor action:
if (func.type == FUNCTION) {
while ((tok.kind != 0) && (tok.kind != EcmaScriptConstants.RPAREN)) {
if (tok.kind == EcmaScriptConstants.IDENTIFIER) {
func.addParameter(tok.image);
}
/**
* from helma.framework.IPathElement. All macros, templates, actions etc
* have the same prototype.
*/
public java.lang.String getPrototype () {
return "docfunction";
}
tok = mgr.getNextToken();
}
} else {
tok = mgr.getNextToken();
}
// now find the end of the function:
int endLine = 0;
// now find the end of the function:
int endColumn = 0;
while ((tok.kind != 0) && (tok.kind != EcmaScriptConstants.FUNCTION)) {
endLine = tok.endLine;
endColumn = tok.endColumn;
tok = mgr.getNextToken();
}
// now we know the exact position of the function in the file,
// re-read it and extract the source code:
func.parseSource(location, beginLine, beginColumn, endLine, endColumn);
vec.add(func);
}
if (tok.kind != EcmaScriptConstants.FUNCTION) {
tok = mgr.getNextToken();
}
}
return (DocFunction[]) vec.toArray(new DocFunction[0]);
}
/**
* reads the content of a .hac file and parses the comment before the first
* javascript element
*/
private void parseActionFile() {
EcmaScriptTokenManager mgr = createTokenManager(location);
Token tok = mgr.getNextToken();
parseCommentFromToken(tok);
content = readFile(location);
}
/**
* reads the content of a .hsp file and parses the comment before the first
* javascript element (only if file starts with &gt;%-tag!).
*/
private void parseTemplateFile() {
content = readFile(location);
StringReader str = new StringReader(content.substring(content.indexOf("<%") + 2,
content.indexOf("%>")));
ASCII_CharStream ascii = new ASCII_CharStream(str, 1, 1);
EcmaScriptTokenManager mgr = new EcmaScriptTokenManager(ascii);
Token tok = mgr.getNextToken();
parseCommentFromToken(tok);
}
/**
* from helma.framework.IPathElement. All macros, templates, actions etc
* have the same prototype.
*/
public java.lang.String getPrototype() {
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;
import helma.framework.IPathElement;
@ -5,59 +21,76 @@ import helma.util.SystemProperties;
import java.io.*;
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();
/**
* creates a new independent DocProperties object
*/
public static DocProperties newInstance (File location) {
return newInstance (location, null);
}
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 DocProperties object connected to another DocElement
*/
public static DocProperties newInstance (File location, DocElement parent) {
try {
return new DocProperties (location, parent);
} catch (DocException doc) {
return null;
}
}
/**
* creates a new independent DocProperties object
*/
public static DocProperties newInstance(File location) {
return newInstance(location, 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 DocProperties object connected to another DocElement
*/
public static DocProperties newInstance(File location, DocElement parent) {
try {
return new DocProperties(location, parent);
} catch (DocException doc) {
return null;
}
}
public Properties getProperties () {
return props;
}
/**
*
*
* @return ...
*/
public Properties getProperties() {
return props;
}
public Properties getMappings () {
Properties childProps = new Properties ();
for (Enumeration e = props.keys (); e.hasMoreElements (); ) {
String key = (String) e.nextElement ();
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 ();
childProps.setProperty (key, prototype);
}
}
return childProps;
}
/**
*
*
* @return ...
*/
public Properties getMappings() {
Properties childProps = new Properties();
for (Enumeration e = props.keys(); e.hasMoreElements();) {
String key = (String) e.nextElement();
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();
childProps.setProperty(key, prototype);
}
}
return childProps;
}
}

View file

@ -1,110 +1,150 @@
/*
* 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;
import FESI.Parser.*;
import helma.framework.IPathElement;
import java.io.*;
import java.util.*;
import FESI.Parser.*;
/**
*
*/
public class DocPrototype extends DocDirElement {
private DocProperties typeProperties = null;
private DocPrototype parentPrototype = null;
public class DocPrototype extends DocDirElement {
private DocPrototype(String name, File location, DocElement parent) {
super(name, location, PROTOTYPE);
this.parent = parent;
typeProperties = DocProperties.newInstance(new File(location, "type.properties"));
}
private DocProperties typeProperties = null;
private DocPrototype parentPrototype = null;
/**
* creates a prototype that is independent of an
* application object
* @param homedirectory
*/
public static DocPrototype newInstance(File location) {
return newInstance(location, null);
}
/**
* creates a prototype that is independent of an
* application object
* @param homedirectory
*/
public static DocPrototype newInstance (File location) {
return newInstance (location, null);
}
/**
* creates a prototype that is connected to an
* application object and resides in app's home dir.
* @param application
* @param name
*/
public static DocPrototype newInstance(File location, DocElement parent) {
DocPrototype pt = new DocPrototype(location.getName(), location, parent);
/**
* creates a prototype that is connected to an
* application object and resides in app's home dir.
* @param application
* @param name
*/
public static DocPrototype newInstance (File location, DocElement 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
* parent prototype with this prototype. this can't be successfull at construction
* time but only -after- all prototypes are parsed and attached to a parent
* DocApplication object.
*/
public void checkInheritance() {
// hopobject is the top prototype:
if (name.equals("hopobject")) {
return;
}
if (typeProperties != null) {
// check for "_extends" in the the type.properties
String ext = typeProperties.getProperties().getProperty("_extends");
/**
* checks the type.properites for _extend values and connected a possible
* parent prototype with this prototype. this can't be successfull at construction
* time but only -after- all prototypes are parsed and attached to a parent
* DocApplication object.
*/
public void checkInheritance () {
// hopobject is the top prototype:
if (name.equals("hopobject"))
return;
if (typeProperties!=null) {
// check for "_extends" in the the type.properties
String ext = typeProperties.getProperties ().getProperty ("_extends");
if (ext!=null && parent!=null) {
// try to get the prototype if available
parentPrototype = (DocPrototype) parent.getChildElement ("prototype_" + ext);
}
}
if (parentPrototype==null && parent!=null && !name.equals("global")) {
// if no _extend was set, get the hopobject prototype
parentPrototype = (DocPrototype) parent.getChildElement ("prototype_hopobject");
}
}
if ((ext != null) && (parent != null)) {
// try to get the prototype if available
parentPrototype = (DocPrototype) parent.getChildElement("prototype_" +
ext);
}
}
public DocPrototype getParentPrototype () {
return parentPrototype;
}
if ((parentPrototype == null) && (parent != null) && !name.equals("global")) {
// if no _extend was set, get the hopobject prototype
parentPrototype = (DocPrototype) parent.getChildElement("prototype_hopobject");
}
}
/**
*
*
* @return ...
*/
public DocPrototype getParentPrototype() {
return parentPrototype;
}
public DocProperties getTypeProperties () {
return typeProperties;
}
/**
*
*
* @return ...
*/
public DocProperties getTypeProperties() {
return typeProperties;
}
/**
* runs through the prototype directory and parses all helma files
*/
public void readFiles() {
children.clear();
/**
* runs through the prototype directory and parses all helma files
*/
public void readFiles () {
children.clear ();
String arr[] = location.list ();
for (int i=0; i<arr.length; i++) {
if (Util.isExcluded (arr[i]))
continue;
File f = new File (location.getAbsolutePath (), arr[i]);
if (f.isDirectory ())
continue;
try {
if (arr[i].endsWith (".skin")) {
addChild (DocSkin.newInstance (f, this));
} else if (arr[i].endsWith (".properties")) {
continue;
} else if (arr[i].endsWith (".hac")) {
addChild (DocFunction.newAction (f, this));
} else if (arr[i].endsWith (".hsp")) {
addChild (DocFunction.newTemplate (f, this));
} else if (arr[i].endsWith (".js")) {
DocElement[] elements = DocFunction.newFunctions (f, this);
for (int j=0; j<elements.length; j++) {
addChild (elements[j]);
}
}
} catch (Exception ex) {
System.out.println ("couldn't parse file " + f.getAbsolutePath () + ": " + ex.toString ());
ex.printStackTrace ();
}
}
}
String[] arr = location.list();
for (int i = 0; i < arr.length; i++) {
if (getDocApplication().isExcluded(arr[i])) {
continue;
}
File f = new File(location.getAbsolutePath(), arr[i]);
if (f.isDirectory()) {
continue;
}
try {
if (arr[i].endsWith(".skin")) {
addChild(DocSkin.newInstance(f, this));
} else if (arr[i].endsWith(".properties")) {
continue;
} else if (arr[i].endsWith(".hac")) {
addChild(DocFunction.newAction(f, this));
} else if (arr[i].endsWith(".hsp")) {
addChild(DocFunction.newTemplate(f, this));
} else if (arr[i].endsWith(".js")) {
DocElement[] elements = DocFunction.newFunctions(f, this);
for (int j = 0; j < elements.length; j++) {
addChild(elements[j]);
}
}
} catch (Exception ex) {
System.out.println("couldn't parse file " + f.getAbsolutePath() + ": " +
ex.toString());
ex.printStackTrace();
} catch (FESI.Parser.TokenMgrError err) {
System.out.println("couldn't parse file " + f.getAbsolutePath() + ": " +
err.toString());
}
}
}
}

View file

@ -1,87 +1,118 @@
/*
* 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;
import helma.framework.IPathElement;
import java.io.*;
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
*/
public static DocSkin newInstance (File location) {
return newInstance (location, null);
}
/**
* creates a new independent DocSkin object
*/
public static DocSkin newInstance(File location) {
return newInstance(location, null);
}
/**
* creates a new DocSkin object connected to another DocElement
*/
public static DocSkin newInstance (File location, DocElement parent) {
String skinname = nameFromFile (location, ".skin");
DocSkin skin = new DocSkin (skinname, location, parent);
return skin;
}
/**
* creates a new DocSkin object connected to another DocElement
*/
public static DocSkin newInstance(File location, DocElement parent) {
String skinname = nameFromFile(location, ".skin");
DocSkin skin = new DocSkin(skinname, location, parent);
protected DocSkin (String name, File location, DocElement parent) {
super (name, location, SKIN);
this.parent = parent;
content = readFile (location);
parseHandlers ();
}
return skin;
}
/**
* parses the source code of the skin and
* extracts all included macros. code taken
* from helma.framework.core.Skin
* @see helma.framework.core.Skin
*/
private void parseHandlers() {
ArrayList partBuffer = new ArrayList();
char[] source = content.toCharArray();
int sourceLength = source.length;
int start = 0;
/**
* parses the source code of the skin and
* extracts all included macros. code taken
* from helma.framework.core.Skin
* @see helma.framework.core.Skin
*/
private void parseHandlers () {
ArrayList partBuffer = new ArrayList ();
char[] source = content.toCharArray ();
int sourceLength = source.length;
int start = 0;
for (int i = 0; i < sourceLength-1; i++) {
if (source[i] == '<' && source[i+1] == '%') {
// found macro start tag
int j = i+2;
// search macro end tag
while (j < sourceLength-1 && (source[j] != '%' || source[j+1] != '>')) {
j++;
}
if (j > i+2) {
String str = (new String (source, i+2, j-i)).trim ();
if (str.endsWith("%>"))
str = str.substring (0, str.length()-2);
if (str.indexOf (" ")>-1)
str = str.substring (0, str.indexOf(" "));
if (str.indexOf(".")>-1 &&
(str.startsWith ("param.")
|| str.startsWith ("response.")
|| str.startsWith("request.")
|| str.startsWith ("session.")
) && !partBuffer.contains(str)) {
partBuffer.add (str);
}
start = j+2;
}
i = j+1;
}
}
String[] strArr = (String[]) partBuffer.toArray (new String [0]);
Arrays.sort (strArr);
for (int i=0; i<strArr.length; i++) {
addParameter (strArr[i]);
}
}
for (int i = 0; i < (sourceLength - 1); i++) {
if ((source[i] == '<') && (source[i + 1] == '%')) {
// found macro start tag
int j = i + 2;
/**
* from helma.framework.IPathElement. Use the same prototype as functions etc.
*/
public java.lang.String getPrototype () {
return "docfunction";
}
// search macro end tag
while ((j < (sourceLength - 1)) &&
((source[j] != '%') || (source[j + 1] != '>'))) {
j++;
}
if (j > (i + 2)) {
String str = (new String(source, i + 2, j - i)).trim();
if (str.endsWith("%>")) {
str = str.substring(0, str.length() - 2);
}
if (str.startsWith("//")) {
parseComment(str);
} else {
if (str.indexOf(" ") > -1) {
str = str.substring(0, str.indexOf(" "));
}
if ((str.indexOf(".") > -1) &&
(str.startsWith("param.") || str.startsWith("response.") ||
str.startsWith("request.") || str.startsWith("session.")) &&
!partBuffer.contains(str)) {
partBuffer.add(str);
}
}
start = j + 2;
}
i = j + 1;
}
}
String[] strArr = (String[]) partBuffer.toArray(new String[0]);
Arrays.sort(strArr);
for (int i = 0; i < strArr.length; i++) {
addParameter(strArr[i]);
}
}
/**
* from helma.framework.IPathElement. Use the same prototype as functions etc.
*/
public java.lang.String getPrototype() {
return "docfunction";
}
}

View file

@ -1,108 +1,176 @@
/*
* 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;
import java.util.*;
public final class DocTag {
/**
*
*/
public final class DocTag {
// for public use we have less types than
// internally. eg, we're combining "return" and "returns"
// or "arg" and "param".
// the values here have to match the index of
// the tags-array!
public static final int PARAMETER = 0;
public static final int RETURN = 2;
public static final int AUTHOR = 4;
public static final int VERSION = 5;
public static final int SEE = 6;
public static final int DEPRECATED = 7;
public static final int OVERRIDES = 8;
public static final String[][] tags = {
{ "@arg", "Argument" },
{ "@param", "Parameter" },
{ "@return", "Returns" },
{ "@returns", "Returns" },
{ "@author", "Author" },
{ "@version", "Version" },
{ "@see", "See also" },
{ "@deprecated", "Deprecated" },
{ "@overrides", "Overrides" }
};
private String name;
// for public use we have less types than
// internally. eg, we're combining "return" and "returns"
// or "arg" and "param".
// the values here have to match the index of
// the tags-array!
public static final int PARAMETER = 0;
public static final int RETURN = 2;
public static final int AUTHOR = 4;
public static final int VERSION = 5;
public static final int SEE = 6;
public static final int DEPRECATED = 7;
public static final int OVERRIDES = 8;
// "kind" is for internal use, "type" is external
private int kind;
private String text;
public static final String[][] tags = {
{"@arg","Argument"},
{"@param","Parameter"},
{"@return","Returns"},
{"@returns","Returns"},
{"@author","Author"},
{"@version","Version"},
{"@see","See also"},
{"@deprecated", "Deprecated"},
{"@overrides", "Overrides"}
};
private DocTag(int kind, String name, String text) {
this.kind = kind;
this.name = (name != null) ? name : "";
this.text = (text != null) ? text : "";
}
private String name;
// "kind" is for internal use, "type" is external
private int kind;
private String text;
/**
*
*
* @param rawTag ...
*
* @return ...
*/
public static boolean isTagStart(String rawTag) {
if (getTagNumber(rawTag) > -1) {
return true;
} else {
return false;
}
}
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 {
int kind = getTagNumber(rawTag);
public static DocTag parse (String rawTag) throws DocException {
int kind = getTagNumber (rawTag);
if (kind == -1)
throw new DocException ("unsupported tag type: " + rawTag);
String content = rawTag.substring (tags[kind][0].length ()+1).trim ();
if (kind == 0 || kind==1) {
StringTokenizer tok = new StringTokenizer (content);
String name = "";
if (tok.hasMoreTokens ())
name = tok.nextToken ();
String comment = "";
try {
comment = content.substring (name.length ()+1).trim ();
} catch (StringIndexOutOfBoundsException e) { }
return new DocTag (kind, name, comment);
} else {
return new DocTag (kind, "", content);
}
}
if (kind == -1) {
throw new DocException("unsupported tag type: " + rawTag);
}
private static int getTagNumber (String rawTag) {
rawTag = rawTag.trim ().toLowerCase ();
for (int i=0; i<tags.length; i++) {
if (rawTag.startsWith (tags[i][0])) {
return i;
}
}
return -1;
}
String content = rawTag.substring(tags[kind][0].length() + 1).trim();
if ((kind == 0) || (kind == 1)) {
StringTokenizer tok = new StringTokenizer(content);
String name = "";
private DocTag (int kind, String name, String text) {
this.kind = kind;
this.name = (name!=null) ? name : "";
this.text = (text!=null) ? text : "";
}
if (tok.hasMoreTokens()) {
name = tok.nextToken();
}
public String getName () {
return name;
}
String comment = "";
public int getType () {
if (kind==0 || kind==1)
return PARAMETER;
else if (kind==2 || kind==3)
return RETURN;
else
return kind;
}
try {
comment = content.substring(name.length() + 1).trim();
} catch (StringIndexOutOfBoundsException e) {
}
return new DocTag(kind, name, comment);
} else {
return new DocTag(kind, "", content);
}
}
public String getTag () {
return tags[kind][0];
}
private static int getTagNumber(String rawTag) {
rawTag = rawTag.trim().toLowerCase();
public String getText () {
return text;
}
for (int i = 0; i < tags.length; i++) {
if (rawTag.startsWith(tags[i][0])) {
return i;
}
}
public String toString() {
return tags [kind][1] + ": " + name + " " + text;
}
return -1;
}
/**
*
*
* @return ...
*/
public String getName() {
return name;
}
/**
*
*
* @return ...
*/
public int getType() {
if ((kind == 0) || (kind == 1)) {
return PARAMETER;
} else if ((kind == 2) || (kind == 3)) {
return RETURN;
} else {
return kind;
}
}
/**
*
*
* @return ...
*/
public String getTag() {
return tags[kind][0];
}
/**
*
*
* @return ...
*/
public String getText() {
return text;
}
/**
*
*
* @return ...
*/
public String toString() {
return tags[kind][1] + ": " + name + " " + text;
}
}

View file

@ -1,40 +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;
import java.io.*;
import java.util.*;
/**
*
*/
public final class Util {
static Vector excluded = new Vector ();
public static void addExlude (String str) {
excluded.add (str.toLowerCase ());
}
public static boolean isExcluded (String str) {
if (excluded.size ()==0) {
excluded.add ("cvs");
excluded.add (".docs");
}
return (excluded.contains (str.toLowerCase ()));
}
public static String chopDelimiters (String line) {
if (line==null)
return null;
else if (line.startsWith("/**"))
return line.substring (3).trim ();
else if (line.startsWith("/*"))
return line.substring (2).trim ();
else if (line.endsWith ("*/"))
return line.substring (0, line.length ()-2);
else if (line.startsWith("*"))
return line.substring (1).trim ();
else if (line.startsWith("//"))
return line.substring (2).trim ();
else
return line;
}
/**
*
*
* @param line ...
*
* @return ...
*/
public static String chopDelimiters(String line) {
if (line == null) {
return null;
} else if (line.startsWith("/**")) {
return line.substring(3).trim();
} else if (line.startsWith("/*")) {
return line.substring(2).trim();
} else if (line.endsWith("*/")) {
return line.substring(0, line.length() - 2);
} else if (line.startsWith("*")) {
return line.substring(1).trim();
} else if (line.startsWith("//")) {
return line.substring(2).trim();
} else {
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;
/**
*
*/
public class ConfigurationException extends RuntimeException {
public ConfigurationException (String msg) {
super (msg);
/**
* Creates a new ConfigurationException object.
*
* @param msg ...
*/
public ConfigurationException(String msg) {
super(msg);
}
}

View file

@ -1,53 +1,71 @@
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.main.Server;
import helma.scripting.ScriptingEngine;
import java.util.HashMap;
/**
* Helma extensions have to subclass this. The extensions to be loaded are
* defined in <code>server.properties</code> by setting <code>extensions =
* packagename.classname, packagename.classname</code>.
*/
* Helma extensions have to subclass this. The extensions to be loaded are
* defined in <code>server.properties</code> by setting <code>extensions =
* packagename.classname, packagename.classname</code>.
*/
public abstract class HelmaExtension {
/**
* called by the Server at startup time. should check wheter the needed classes
* are present and throw a ConfigurationException if not.
*/
public abstract void init(Server server) throws ConfigurationException;
/**
* called by the Server at startup time. should check wheter the needed classes
* are present and throw a ConfigurationException if not.
*/
public abstract void init (Server server) throws ConfigurationException;
/**
* called when an Application is started. This should be <b>synchronized</b> when
* any self-initialization is performed.
*/
public abstract void applicationStarted(Application app)
throws ConfigurationException;
/**
* called when an Application is started. This should be <b>synchronized</b> when
* any self-initialization is performed.
*/
public abstract void applicationStarted (Application app) throws ConfigurationException;
/**
* called when an Application is stopped.
* This should be <b>synchronized</b> when any self-destruction is performed.
*/
public abstract void applicationStopped(Application app);
/**
* called when an Application is stopped.
* This should be <b>synchronized</b> when any self-destruction is performed.
*/
public abstract void applicationStopped (Application app);
/**
* called when an Application's properties are have been updated.
* note that this will be called at startup once *before* applicationStarted().
*/
public abstract void applicationUpdated(Application app);
/**
* called when an Application's properties are have been updated.
* note that this will be called at startup once *before* applicationStarted().
*/
public abstract void applicationUpdated (Application app);
/**
* called by the ScriptingEngine when it is initizalized. Throws a ConfigurationException
* when this type of ScriptingEngine is not supported. New methods and prototypes can be
* added to the scripting environment. New global vars should be returned in a HashMap
* with pairs of varname and ESObjects. This method should be <b>synchronized</b>, if it
* performs any other self-initialization outside the scripting environment.
*/
public abstract HashMap initScripting (Application app, ScriptingEngine engine) throws ConfigurationException;
public abstract String getName ();
/**
* called by the ScriptingEngine when it is initizalized. Throws a ConfigurationException
* when this type of ScriptingEngine is not supported. New methods and prototypes can be
* added to the scripting environment. New global vars should be returned in a HashMap
* with pairs of varname and ESObjects. This method should be <b>synchronized</b>, if it
* performs any other self-initialization outside the scripting environment.
*/
public abstract HashMap initScripting(Application app, ScriptingEngine engine)
throws ConfigurationException;
/**
*
*
* @return ...
*/
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;
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:
import FESI.Data.ESObject;
@ -14,55 +23,104 @@ import FESI.Data.ESWrapper;
import FESI.Data.GlobalObject;
import FESI.Exceptions.EcmaScriptException;
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 java.util.HashMap;
/**
* a demo extension implementation, to activate this add <code>extensions =
* helma.extensions.demo.DemoExtensions</code> to your <code>server.properties</code>.
* a new global object <code>demo</code> that wraps helma.main.Server
* will be added to the scripting environment.
*/
* a demo extension implementation, to activate this add <code>extensions =
* helma.extensions.demo.DemoExtensions</code> to your <code>server.properties</code>.
* a new global object <code>demo</code> that wraps helma.main.Server
* will be added to the scripting environment.
*/
public class DemoExtension extends HelmaExtension {
/**
*
*
* @param server ...
*
* @throws ConfigurationException ...
*/
public void init(Server server) throws ConfigurationException {
try {
// just a demo with the server class itself (which is always there, obviously)
Class check = Class.forName("helma.main.Server");
} catch (ClassNotFoundException e) {
throw new ConfigurationException("helma-library not present in classpath. make sure helma.jar is included. get it from http://www.helma.org/");
}
}
public void init (Server server) throws ConfigurationException {
try {
// just a demo with the server class itself (which is always there, obviously)
Class check = Class.forName("helma.main.Server");
} catch (ClassNotFoundException e) {
throw new ConfigurationException("helma-library not present in classpath. make sure helma.jar is included. get it from http://www.helma.org/");
}
}
/**
*
*
* @param app ...
*
* @throws ConfigurationException ...
*/
public void applicationStarted(Application app) throws ConfigurationException {
app.logEvent("DemoExtension init with app " + app.getName());
}
public void applicationStarted (Application app) throws ConfigurationException {
app.logEvent ("DemoExtension init with app " + app.getName () );
}
/**
*
*
* @param app ...
*/
public void applicationStopped(Application app) {
app.logEvent("DemoExtension stopped on app " + app.getName());
}
public void applicationStopped (Application app) {
app.logEvent ("DemoExtension stopped on app " + app.getName () );
}
/**
*
*
* @param app ...
*/
public void applicationUpdated(Application app) {
app.logEvent("DemoExtension updated on app " + app.getName());
}
public void applicationUpdated (Application app) {
app.logEvent ("DemoExtension updated on app " + app.getName () );
}
/**
*
*
* @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");
}
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:
Evaluator evaluator = ((FesiEngine)engine).getEvaluator ();
// initialize prototypes and global vars here, but don't add them to fesi's global object
ESWrapper demo = new ESWrapper(Server.getServer (), evaluator);
HashMap globals = new HashMap ();
globals.put ("demo",demo);
return globals;
}
app.logEvent("initScripting DemoExtension with " + app.getName() + " and " +
engine.toString());
public String getName () {
return "DemoExtension";
}
// fesi-specific code:
Evaluator evaluator = ((FesiEngine) engine).getEvaluator();
// initialize prototypes and global vars here, but don't add them to fesi's global object
ESWrapper demo = new ESWrapper(Server.getServer(), evaluator);
HashMap globals = new HashMap();
globals.put("demo", demo);
return globals;
}
/**
*
*
* @return ...
*/
public String getName() {
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;
/**
* This is thrown when a request is made to a stopped
* application
*/
public class ApplicationStoppedException extends RuntimeException {
public ApplicationStoppedException () {
super ("The application has been stopped");
/**
* Creates a new ApplicationStoppedException object.
*/
public ApplicationStoppedException() {
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;
@ -7,68 +21,110 @@ import java.util.HashMap;
import javax.servlet.http.Cookie;
/**
* Cookie Transmitter. A simple, serializable representation
* Cookie Transmitter. A simple, serializable representation
* of an HTTP cookie.
*/
public final class CookieTrans implements Serializable {
String name, value, path, domain;
String name;
String value;
String path;
String domain;
int days;
CookieTrans (String name, String value) {
this.name = name;
this.value = value;
CookieTrans(String name, String value) {
this.name = name;
this.value = value;
}
void setValue (String value) {
this.value = value;
void setValue(String value) {
this.value = value;
}
void setDays (int days) {
this.days = days;
void setDays(int days) {
this.days = days;
}
void setPath (String path) {
this.path = path;
void setPath(String path) {
this.path = path;
}
void setDomain (String domain) {
this.domain = domain;
void setDomain(String domain) {
this.domain = domain;
}
/**
*
*
* @return ...
*/
public String getName() {
return name;
return name;
}
/**
*
*
* @return ...
*/
public String getValue() {
return value;
return value;
}
/**
*
*
* @return ...
*/
public int getDays() {
return days;
return days;
}
public String getPath () {
return path;
/**
*
*
* @return ...
*/
public String getPath() {
return path;
}
public String getDomain () {
return domain;
/**
*
*
* @return ...
*/
public String getDomain() {
return domain;
}
public Cookie getCookie (String defaultPath, String defaultDomain) {
Cookie c = new Cookie (name, value);
if (days > 0)
// Cookie time to live, days -> seconds
c.setMaxAge (days*60*60*24);
if (path != null)
c.setPath (path);
else if (defaultPath != null)
c.setPath (defaultPath);
if (domain != null)
c.setDomain (domain);
else if (defaultDomain != null)
c.setDomain (defaultDomain);
return c;
/**
*
*
* @param defaultPath ...
* @param defaultDomain ...
*
* @return ...
*/
public Cookie getCookie(String defaultPath, String defaultDomain) {
Cookie c = new Cookie(name, value);
if (days > 0) {
// Cookie time to live, days -> seconds
c.setMaxAge(days * 60 * 60 * 24);
}
if (path != null) {
c.setPath(path);
} else if (defaultPath != null) {
c.setPath(defaultPath);
}
if (domain != null) {
c.setDomain(domain);
} else if (defaultDomain != null) {
c.setDomain(defaultDomain);
}
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;
/**
* 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.
*/
public class FrameworkException extends RuntimeException {
public FrameworkException (String msg) {
super (msg);
/**
* Creates a new FrameworkException object.
*
* @param msg ...
*/
public FrameworkException(String msg) {
super(msg);
}
}

View file

@ -1,6 +1,19 @@
// 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;
@ -14,34 +27,26 @@ package helma.framework;
* parent element. <p>
*
*/
public interface IPathElement {
/**
* Return the name to be used to get this element from its parent
*/
public String getElementName ();
public String getElementName();
/**
* Retrieve a child element of this object by name.
*/
public IPathElement getChildElement (String name);
public IPathElement getChildElement(String name);
/**
* Return the parent element of this object.
*/
public IPathElement getParentElement ();
public IPathElement getParentElement();
/**
* 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
* 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;
@ -9,11 +22,22 @@ import java.util.Vector;
/**
* RMI interface for an application. Currently only execute is used and supported.
*/
public interface IRemoteApp extends Remote {
/**
*
*
* @param param ...
*
* @return ...
*
* @throws RemoteException ...
*/
public ResponseTrans execute(RequestTrans param) throws RemoteException;
public ResponseTrans execute (RequestTrans param) throws RemoteException;
public void ping () throws RemoteException;
}
/**
*
*
* @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;
@ -8,26 +21,43 @@ package helma.framework;
* RedirectException is thrown internally when a response is redirected to a
* new URL.
*/
public class RedirectException extends RuntimeException {
String url;
public RedirectException (String url) {
super ("Redirection Request to "+url);
this.url = url;
/**
* Creates a new RedirectException object.
*
* @param url ...
*/
public RedirectException(String url) {
super("Redirection Request to " + url);
this.url = url;
}
public String getMessage () {
return url;
/**
*
*
* @return ...
*/
public String getMessage() {
return url;
}
/**
*
*
* @param s ...
*/
public void printStackTrace(java.io.PrintStream s) {
// do nothing
// do nothing
}
/**
*
*
* @param w ...
*/
public void printStackTrace(java.io.PrintWriter w) {
// do nothing
// do nothing
}
}

View file

@ -1,74 +1,138 @@
/*
* 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;
import helma.framework.core.Application;
import java.io.Serializable;
import java.util.Date;
import java.util.Map;
import helma.framework.core.Application;
import java.util.Date;
/**
*
*/
public class RequestBean implements Serializable {
RequestTrans req;
RequestTrans req;
/**
* Creates a new RequestBean object.
*
* @param req ...
*/
public RequestBean(RequestTrans req) {
this.req = req;
}
public RequestBean(RequestTrans req) {
this.req = req;
}
/**
*
*
* @param name ...
*
* @return ...
*/
public Object get(String name) {
return req.get(name);
}
public Object get (String name) {
return req.get (name);
}
/**
*
*
* @return ...
*/
public boolean isGet() {
return req.isGet();
}
public boolean isGet () {
return req.isGet ();
}
/**
*
*
* @return ...
*/
public boolean isPost() {
return req.isPost();
}
public boolean isPost () {
return req.isPost ();
}
/**
*
*
* @return ...
*/
public String toString() {
return "[Request]";
}
public String toString() {
return "[Request]";
}
// property related methods:
public String getaction() {
return req.action;
}
// property related methods:
/**
*
*
* @return ...
*/
public Map getdata() {
return req.getRequestData();
}
public String getaction () {
return req.action;
}
/**
*
*
* @return ...
*/
public long getruntime() {
return (System.currentTimeMillis() - req.startTime);
}
public Map getdata () {
return req.getRequestData ();
}
/**
*
*
* @return ...
*/
public String getpassword() {
return req.getPassword();
}
public long getruntime () {
return (System.currentTimeMillis() - req.startTime);
}
/**
*
*
* @return ...
*/
public String getpath() {
return req.path;
}
public String getpassword () {
return req.getPassword ();
}
/**
*
*
* @return ...
*/
public String getusername() {
return req.getUsername();
}
public String getpath () {
return req.path;
}
public String getusername () {
return req.getUsername ();
}
/* public Date getLastModified () {
long since = req.getIfModifiedSince ();
if (since < 0)
return null;
else
return new Date (since);
}
public void setLastModified () {
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.");
} */
/* public Date getLastModified () {
long since = req.getIfModifiedSince ();
if (since < 0)
return null;
else
return new Date (since);
}
public void setLastModified () {
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.");
} */
}

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;
import java.io.*;
import java.util.*;
import helma.objectmodel.*;
import helma.util.Base64;
import java.io.*;
import java.util.*;
/**
* A Transmitter for a request from the servlet client. Objects of this
* class are directly exposed to JavaScript as global property req.
* A Transmitter for a request from the servlet client. Objects of this
* class are directly exposed to JavaScript as global property req.
*/
public class RequestTrans implements Externalizable {
static final long serialVersionUID = 5398880083482000580L;
// the uri path of the request
public String path;
// the request's session id
public String session;
// the map of form and cookie data
private Map values;
// the request method - 0 for GET, 1 for POST
private byte httpMethod = 0;
// timestamp of client-cached version, if present in request
private long ifModifiedSince = -1;
// set of ETags the client sent with If-None-Match header
private Set etags;
@ -34,185 +51,237 @@ public class RequestTrans implements Externalizable {
// the name of the action being invoked
public transient String action;
private transient String httpUsername;
private transient String httpPassword;
static final long serialVersionUID = 5398880083482000580L;
/**
* Create a new Request transmitter with an empty data map.
*/
public RequestTrans () {
httpMethod = 0;
values = new HashMap ();
public RequestTrans() {
httpMethod = 0;
values = new HashMap();
}
/**
* Create a new request transmitter with the given data map.
*/
public RequestTrans (byte method) {
httpMethod = method;
values = new HashMap ();
* Create a new request transmitter with the given data map.
*/
public RequestTrans(byte method) {
httpMethod = method;
values = new HashMap();
}
/**
* Set a parameter value in this request transmitter.
*/
public void set (String name, Object value) {
values.put (name, value);
public void set(String name, Object value) {
values.put(name, value);
}
/**
* Get a value from the requests map by key.
*/
public Object get (String name) {
try {
return values.get (name);
} catch (Exception x) {
return null;
}
public Object get(String name) {
try {
return values.get(name);
} catch (Exception x) {
return null;
}
}
/**
* Get the data map for this request transmitter.
*/
public Map getRequestData () {
return values;
public Map getRequestData() {
return values;
}
/**
* The hash code is computed from the session id if available. This is used to
* detect multiple identic requests.
*/
public int hashCode () {
return session == null ? super.hashCode () : session.hashCode ();
public int hashCode() {
return (session == null) ? super.hashCode() : session.hashCode();
}
/**
* 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
*/
public boolean equals (Object what) {
try {
RequestTrans other = (RequestTrans) what;
return (session.equals (other.session) &&
path.equalsIgnoreCase (other.path) &&
values.equals (other.getRequestData ()));
} catch (Exception x) {
return false;
}
public boolean equals(Object what) {
try {
RequestTrans other = (RequestTrans) what;
return (session.equals(other.session) && path.equalsIgnoreCase(other.path) &&
values.equals(other.getRequestData()));
} catch (Exception x) {
return false;
}
}
/**
* Return true if this object represents a HTTP GET Request.
*/
public boolean isGet () {
return httpMethod == 0;
public boolean isGet() {
return httpMethod == 0;
}
/**
* Return true if this object represents a HTTP GET Request.
*/
public boolean isPost () {
return httpMethod == 1;
public boolean isPost() {
return httpMethod == 1;
}
/**
* Custom externalization code for quicker serialization.
*/
public void readExternal (ObjectInput s) throws ClassNotFoundException, IOException {
path = s.readUTF ();
session = s.readUTF ();
values = (Map) s.readObject ();
httpMethod = s.readByte ();
ifModifiedSince = s.readLong ();
etags = (Set) s.readObject ();
public void readExternal(ObjectInput s) throws ClassNotFoundException, IOException {
path = s.readUTF();
session = s.readUTF();
values = (Map) s.readObject();
httpMethod = s.readByte();
ifModifiedSince = s.readLong();
etags = (Set) s.readObject();
}
/**
* Custom externalization code for quicker serialization.
*/
public void writeExternal (ObjectOutput s) throws IOException {
s.writeUTF (path);
s.writeUTF (session);
s.writeObject (values);
s.writeByte (httpMethod);
s.writeLong (ifModifiedSince);
s.writeObject (etags);
public void writeExternal(ObjectOutput s) throws IOException {
s.writeUTF(path);
s.writeUTF(session);
s.writeObject(values);
s.writeByte(httpMethod);
s.writeLong(ifModifiedSince);
s.writeObject(etags);
}
public void setIfModifiedSince (long since) {
ifModifiedSince = since;
/**
*
*
* @param since ...
*/
public void setIfModifiedSince(long since) {
ifModifiedSince = since;
}
public long getIfModifiedSince () {
return ifModifiedSince;
/**
*
*
* @return ...
*/
public long getIfModifiedSince() {
return ifModifiedSince;
}
public void setETags (String etagHeader) {
etags = new HashSet();
if (etagHeader.indexOf (",") > -1) {
StringTokenizer st = new StringTokenizer (etagHeader, ", \r\n");
while (st.hasMoreTokens())
etags.add (st.nextToken ());
} else {
etags.add (etagHeader);
}
/**
*
*
* @param etagHeader ...
*/
public void setETags(String etagHeader) {
etags = new HashSet();
if (etagHeader.indexOf(",") > -1) {
StringTokenizer st = new StringTokenizer(etagHeader, ", \r\n");
while (st.hasMoreTokens())
etags.add(st.nextToken());
} else {
etags.add(etagHeader);
}
}
public Set getETags () {
return etags;
/**
*
*
* @return ...
*/
public Set getETags() {
return etags;
}
public boolean hasETag (String etag) {
if (etags == null || etag == null)
return false;
return etags.contains (etag);
/**
*
*
* @param etag ...
*
* @return ...
*/
public boolean hasETag(String etag) {
if ((etags == null) || (etag == null)) {
return false;
}
return etags.contains(etag);
}
/**
*
*
* @return ...
*/
public String getUsername() {
if ( httpUsername!=null )
return httpUsername;
String auth = (String)get("authorization");
if ( auth==null || "".equals(auth) ) {
return null;
}
decodeHttpAuth(auth);
return httpUsername;
if (httpUsername != null) {
return httpUsername;
}
String auth = (String) get("authorization");
if ((auth == null) || "".equals(auth)) {
return null;
}
decodeHttpAuth(auth);
return httpUsername;
}
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 ...
*/
public String getPassword() {
if (httpPassword != null) {
return httpPassword;
}
String auth = (String) get("authorization");
if ((auth == null) || "".equals(auth)) {
return null;
}
decodeHttpAuth(auth);
return httpPassword;
}
private void decodeHttpAuth(String auth) {
if ( auth==null )
return;
StringTokenizer tok;
if( auth.startsWith("Basic ") )
tok = new StringTokenizer ( new String( Base64.decode((auth.substring(6)).toCharArray()) ), ":" );
else
tok = new StringTokenizer ( new String( Base64.decode(auth.toCharArray()) ), ":" );
try {
httpUsername = tok.nextToken();
} catch ( NoSuchElementException e ) {
httpUsername = null;
}
try {
httpPassword = tok.nextToken();
} catch ( NoSuchElementException e ) {
httpPassword = null;
}
}
private void decodeHttpAuth(String auth) {
if (auth == null) {
return;
}
StringTokenizer tok;
if (auth.startsWith("Basic ")) {
tok = new StringTokenizer(new String(Base64.decode((auth.substring(6)).toCharArray())),
":");
} else {
tok = new StringTokenizer(new String(Base64.decode(auth.toCharArray())), ":");
}
try {
httpUsername = tok.nextToken();
} catch (NoSuchElementException e) {
httpUsername = null;
}
try {
httpPassword = tok.nextToken();
} catch (NoSuchElementException e) {
httpPassword = null;
}
}
}

View file

@ -1,175 +1,386 @@
/*
* 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;
import helma.framework.core.Application;
import java.io.Serializable;
import java.util.Date;
import java.util.Map;
import helma.framework.core.Application;
import java.util.Date;
/**
*
*/
public class ResponseBean implements Serializable {
ResponseTrans res;
public ResponseBean(ResponseTrans res) {
this.res = res;
/**
* Creates a new ResponseBean object.
*
* @param res ...
*/
public ResponseBean(ResponseTrans res) {
this.res = res;
}
public void encode (Object what) {
res.encode (what);
/**
*
*
* @param what ...
*/
public void encode(Object what) {
res.encode(what);
}
public void encodeXml (Object what) {
res.encodeXml (what);
/**
*
*
* @param what ...
*/
public void encodeXml(Object what) {
res.encodeXml(what);
}
public void format (Object what) {
res.format (what);
/**
*
*
* @param what ...
*/
public void format(Object what) {
res.format(what);
}
public void redirect (String url) throws RedirectException {
res.redirect (url);
/**
*
*
* @param url ...
*
* @throws RedirectException ...
*/
public void redirect(String url) throws RedirectException {
res.redirect(url);
}
public void reset () {
res.reset ();
/**
*
*/
public void reset() {
res.reset();
}
public void setCookie (String key, String value) {
res.setCookie (key, value, -1, null, null);
/**
*
*
* @param key ...
* @param value ...
*/
public void setCookie(String key, String value) {
res.setCookie(key, value, -1, null, null);
}
public void setCookie (String key, String value, int days) {
res.setCookie (key, value, days, null, null);
}
public void setCookie (String key, String value, int days, String path) {
res.setCookie (key, value, days, path, null);
/**
*
*
* @param key ...
* @param value ...
* @param days ...
*/
public void setCookie(String key, String value, int days) {
res.setCookie(key, value, days, null, null);
}
public void setCookie (String key, String value, int days, String path, String domain) {
res.setCookie (key, value, days, path, domain);
/**
*
*
* @param key ...
* @param value ...
* @param days ...
* @param path ...
*/
public void setCookie(String key, String value, int days, String path) {
res.setCookie(key, value, days, path, null);
}
public void write (Object what) {
res.write (what);
/**
*
*
* @param key ...
* @param value ...
* @param days ...
* @param path ...
* @param domain ...
*/
public void setCookie(String key, String value, int days, String path, String domain) {
res.setCookie(key, value, days, path, domain);
}
public void writeln (Object what) {
res.writeln (what);
/**
*
*
* @param what ...
*/
public void write(Object what) {
res.write(what);
}
public void writeBinary (byte[] what) {
res.writeBinary (what);
/**
*
*
* @param what ...
*/
public void writeln(Object what) {
res.writeln(what);
}
public void debug (Object message) {
res.debug (message);
/**
*
*
* @param what ...
*/
public void writeBinary(byte[] what) {
res.writeBinary(what);
}
/**
*
*
* @param message ...
*/
public void debug(Object message) {
res.debug(message);
}
/**
*
*
* @return ...
*/
public String toString() {
return "[Response]";
return "[Response]";
}
// property-related methods:
public boolean getcache () {
return res.cache;
// property-related methods:
public boolean getcache() {
return res.cache;
}
public void setcache (boolean cache) {
res.cache = cache;
/**
*
*
* @param cache ...
*/
public void setcache(boolean cache) {
res.cache = cache;
}
public String getcharset () {
return res.charset;
/**
*
*
* @return ...
*/
public String getcharset() {
return res.charset;
}
public void setcharset (String charset) {
res.charset = charset;
/**
*
*
* @param charset ...
*/
public void setcharset(String charset) {
res.charset = charset;
}
public String getcontentType () {
return res.contentType;
/**
*
*
* @return ...
*/
public String getcontentType() {
return res.contentType;
}
public void setcontentType (String contentType) {
res.contentType = contentType;
/**
*
*
* @param contentType ...
*/
public void setcontentType(String contentType) {
res.contentType = contentType;
}
public Map getdata () {
return res.getResponseData ();
}
public Map gethandlers () {
return res.getMacroHandlers ();
/**
*
*
* @return ...
*/
public Map getdata() {
return res.getResponseData();
}
public String geterror () {
return res.error;
/**
*
*
* @return ...
*/
public Map gethandlers() {
return res.getMacroHandlers();
}
public String getmessage () {
return res.message;
/**
*
*
* @return ...
*/
public String geterror() {
return res.error;
}
public void setmessage (String message) {
res.message = message;
/**
*
*
* @return ...
*/
public String getmessage() {
return res.message;
}
public String getrealm () {
return res.realm;
/**
*
*
* @param message ...
*/
public void setmessage(String message) {
res.message = message;
}
public void setrealm (String realm) {
res.realm = realm;
/**
*
*
* @return ...
*/
public String getrealm() {
return res.realm;
}
public void setskinpath (Object[] arr) {
res.setSkinpath (arr);
/**
*
*
* @param realm ...
*/
public void setrealm(String realm) {
res.realm = realm;
}
public Object[] getskinpath () {
return res.getSkinpath ();
/**
*
*
* @param arr ...
*/
public void setskinpath(Object[] arr) {
res.setSkinpath(arr);
}
public int getstatus () {
return res.status;
/**
*
*
* @return ...
*/
public Object[] getskinpath() {
return res.getSkinpath();
}
public void setstatus (int status) {
res.status = status;
/**
*
*
* @return ...
*/
public int getstatus() {
return res.status;
}
public Date getLastModified () {
long modified = res.getLastModified ();
if (modified > -1)
return new Date (modified);
else
return null;
/**
*
*
* @param status ...
*/
public void setstatus(int status) {
res.status = status;
}
public void setLastModified (Date date) {
if (date == null)
res.setLastModified (-1);
else
res.setLastModified (date.getTime());
/**
*
*
* @return ...
*/
public Date getLastModified() {
long modified = res.getLastModified();
if (modified > -1) {
return new Date(modified);
} else {
return null;
}
}
public String getETag () {
return res.getETag ();
}
public void setETag (String etag) {
res.setETag (etag);
/**
*
*
* @param date ...
*/
public void setLastModified(Date date) {
if (date == null) {
res.setLastModified(-1);
} else {
res.setLastModified(date.getTime());
}
}
public void dependsOn (Object what) {
res.dependsOn (what);
/**
*
*
* @return ...
*/
public String getETag() {
return res.getETag();
}
public void digest () {
res.digestDependencies ();
/**
*
*
* @param etag ...
*/
public void setETag(String etag) {
res.setETag(etag);
}
/**
*
*
* @param what ...
*/
public void dependsOn(Object what) {
res.dependsOn(what);
}
/**
*
*/
public void digest() {
res.digestDependencies();
}
/////////////////////////////////////
@ -177,14 +388,16 @@ public class ResponseBean implements Serializable {
// Helma templates (*.hsp files) and shouldn't
// be used otherwise.
////////////////////////////////////
public void pushStringBuffer () {
res.pushStringBuffer ();
public void pushStringBuffer() {
res.pushStringBuffer();
}
public String popStringBuffer () {
return res.popStringBuffer ();
/**
*
*
* @return ...
*/
public String popStringBuffer() {
return res.popStringBuffer();
}
}

File diff suppressed because it is too large Load diff

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;
/**
* TimeoutException is thrown by the request evaluator when a request could
* not be serviced within the timeout period specified for an application.
* TimeoutException is thrown by the request evaluator when a request could
* not be serviced within the timeout period specified for an application.
*/
public class TimeoutException extends RuntimeException {
public TimeoutException () {
super ("Request timed out");
/**
* Creates a new TimeoutException object.
*/
public TimeoutException() {
super("Request timed out");
}
}

View file

@ -1,37 +1,53 @@
// 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;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Enumeration;
import java.security.CodeSource;
import java.security.Permission;
import java.security.PermissionCollection;
import java.security.Permissions;
import java.util.Enumeration;
/**
* ClassLoader subclass with package accessible addURL method.
*/
public class AppClassLoader extends URLClassLoader {
private final String appname;
/**
* Create a HelmaClassLoader with the given application name and the given URLs
*/
/**
* Create a HelmaClassLoader with the given application name and the given URLs
*/
public AppClassLoader(String appname, URL[] urls) {
super ( urls, AppClassLoader.class.getClassLoader());
this.appname = appname;
super(urls, AppClassLoader.class.getClassLoader());
this.appname = appname;
}
protected void addURL (URL url) {
super.addURL (url);
protected void addURL(URL url) {
super.addURL(url);
}
public String getAppName () {
return appname;
/**
*
*
* @return ...
*/
public String getAppName() {
return appname;
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,215 +1,497 @@
/*
* 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;
import java.io.Serializable;
import helma.objectmodel.INode;
import helma.util.CronJob;
import java.io.File;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.List;
import java.util.Map;
import helma.objectmodel.INode;
/**
*
*/
public class ApplicationBean implements Serializable {
Application app;
/**
* Creates a new ApplicationBean object.
*
* @param app ...
*/
public ApplicationBean(Application app) {
this.app = app;
this.app = app;
}
public void clearCache () {
app.clearCache ();
/**
*
*/
public void clearCache() {
app.clearCache();
}
public void log (Object msg) {
String str = msg == null ? "null" : msg.toString();
app.logEvent (str);
/**
*
*
* @param msg ...
*/
public void log(Object msg) {
String str = (msg == null) ? "null" : msg.toString();
app.logEvent(str);
}
public void log (String logname, Object msg) {
String str = msg == null ? "null" : msg.toString();
app.getLogger (logname).log (str);
/**
*
*
* @param logname ...
* @param msg ...
*/
public void log(String logname, Object msg) {
String str = (msg == null) ? "null" : msg.toString();
app.getLogger(logname).log(str);
}
public void debug (Object msg) {
if (app.debug()) {
String str = msg == null ? "null" : msg.toString();
app.logEvent (str);
}
/**
*
*
* @param msg ...
*/
public void debug(Object msg) {
if (app.debug()) {
String str = (msg == null) ? "null" : msg.toString();
app.logEvent(str);
}
}
public void debug (String logname, Object msg) {
if (app.debug()) {
String str = msg == null ? "null" : msg.toString();
app.getLogger (logname).log (str);
}
/**
*
*
* @param logname ...
* @param msg ...
*/
public void debug(String logname, Object msg) {
if (app.debug()) {
String str = (msg == null) ? "null" : msg.toString();
app.getLogger(logname).log(str);
}
}
public int countSessions () {
return app.sessions.size();
/**
*
*
* @return ...
*/
public int countSessions() {
return app.sessions.size();
}
public SessionBean getSession (String sessionID) {
if (sessionID==null)
return null;
Session session = app.getSession (sessionID.trim ());
if (session == null)
return null;
return new SessionBean (session);
/**
*
*
* @param sessionID ...
*
* @return ...
*/
public SessionBean getSession(String sessionID) {
if (sessionID == null) {
return null;
}
Session session = app.getSession(sessionID.trim());
if (session == null) {
return null;
}
return new SessionBean(session);
}
public SessionBean createSession (String sessionID) {
if (sessionID==null)
return null;
Session session = session = app.checkSession (sessionID.trim ());
if (session == null)
return null;
return new SessionBean (session);
/**
*
*
* @param sessionID ...
*
* @return ...
*/
public SessionBean createSession(String sessionID) {
if (sessionID == null) {
return null;
}
Session session = session = app.checkSession(sessionID.trim());
if (session == null) {
return null;
}
return new SessionBean(session);
}
public SessionBean[] getSessions () {
SessionBean[] theArray = new SessionBean[app.sessions.size()];
int i=0;
for (Enumeration e=app.sessions.elements(); e.hasMoreElements(); ) {
SessionBean sb = new SessionBean ((Session) e.nextElement ());
theArray[i++] = sb;
}
return theArray;
/**
*
*
* @return ...
*/
public SessionBean[] getSessions() {
SessionBean[] theArray = new SessionBean[app.sessions.size()];
int i = 0;
for (Enumeration e = app.sessions.elements(); e.hasMoreElements();) {
SessionBean sb = new SessionBean((Session) e.nextElement());
theArray[i++] = sb;
}
return theArray;
}
public INode registerUser (String username, String password) {
if (username==null || password==null || "".equals (username.trim ()) || "".equals (password.trim ()) )
return null;
else
return app.registerUser (username, password);
/**
*
*
* @param username ...
* @param password ...
*
* @return ...
*/
public INode registerUser(String username, String password) {
if ((username == null) || (password == null) || "".equals(username.trim()) ||
"".equals(password.trim())) {
return null;
} else {
return app.registerUser(username, password);
}
}
public INode getUser (String username) {
if (username==null || "".equals (username.trim()) )
return null;
return app.getUserNode (username);
/**
*
*
* @param username ...
*
* @return ...
*/
public INode getUser(String username) {
if ((username == null) || "".equals(username.trim())) {
return null;
}
return app.getUserNode(username);
}
public INode[] getActiveUsers () {
List activeUsers = app.getActiveUsers ();
return (INode[]) activeUsers.toArray (new INode[0]);
/**
*
*
* @return ...
*/
public INode[] getActiveUsers() {
List activeUsers = app.getActiveUsers();
return (INode[]) activeUsers.toArray(new INode[0]);
}
public INode[] getRegisteredUsers () {
List registeredUsers = app.getRegisteredUsers ();
return (INode[]) registeredUsers.toArray (new INode[0]);
}
/**
*
*
* @return ...
*/
public INode[] getRegisteredUsers() {
List registeredUsers = app.getRegisteredUsers();
public SessionBean[] getSessionsForUser (INode usernode) {
if (usernode==null)
return new SessionBean[0];
else
return getSessionsForUser(usernode.getName());
return (INode[]) registeredUsers.toArray(new INode[0]);
}
public SessionBean[] getSessionsForUser (String username) {
if (username==null || "".equals (username.trim ()) )
return new SessionBean[0];
List userSessions = app.getSessionsForUsername (username);
return (SessionBean[]) userSessions.toArray (new SessionBean[0]);
/**
*
*
* @param usernode ...
*
* @return ...
*/
public SessionBean[] getSessionsForUser(INode usernode) {
if (usernode == null) {
return new SessionBean[0];
} else {
return getSessionsForUser(usernode.getName());
}
}
/**
*
*
* @param username ...
*
* @return ...
*/
public SessionBean[] getSessionsForUser(String username) {
if ((username == null) || "".equals(username.trim())) {
return new SessionBean[0];
}
List userSessions = app.getSessionsForUsername(username);
return (SessionBean[]) userSessions.toArray(new SessionBean[0]);
}
/**
*
*
* @param functionName ...
*/
public void addCronJob(String functionName) {
CronJob job = new CronJob(functionName);
job.setFunction(functionName);
app.customCronJobs.put(functionName, job);
}
/**
*
*
* @param functionName ...
* @param year ...
* @param month ...
* @param day ...
* @param weekday ...
* @param hour ...
* @param minute ...
*/
public void addCronJob(String functionName, String year, String month, String day,
String weekday, String hour, String minute) {
CronJob job = CronJob.newJob(functionName, year, month, day, weekday, hour, minute);
app.customCronJobs.put(functionName, job);
}
/**
*
*
* @param functionName ...
*/
public void removeCronJob(String functionName) {
app.customCronJobs.remove(functionName);
}
// getter methods for readonly properties of this application
public int getcacheusage () {
return app.getCacheUsage ();
public int getcacheusage() {
return app.getCacheUsage();
}
/**
*
*
* @return ...
*/
public INode getdata() {
return app.getCacheNode ();
return app.getCacheNode();
}
/**
*
*
* @return ...
*/
public Map getmodules() {
return app.modules;
return app.modules;
}
public String getdir () {
return app.getAppDir ().getAbsolutePath ();
/**
*
*
* @return ...
*/
public String getdir() {
return app.getAppDir().getAbsolutePath();
}
public Date getupSince () {
return new Date (app.starttime);
/**
*
*
* @return ...
*/
public String getname() {
return app.getName();
}
public long getrequestCount () {
return app.getRequestCount ();
/**
*
*
* @return ...
*/
public Date getupSince() {
return new Date(app.starttime);
}
public long getxmlrpcCount () {
return app.getXmlrpcCount ();
/**
*
*
* @return ...
*/
public long getrequestCount() {
return app.getRequestCount();
}
public long geterrorCount () {
return app.getErrorCount ();
/**
*
*
* @return ...
*/
public long getxmlrpcCount() {
return app.getXmlrpcCount();
}
public Application get__app__ () {
return app;
/**
*
*
* @return ...
*/
public long geterrorCount() {
return app.getErrorCount();
}
public Map getproperties () {
return app.getProperties ();
/**
*
*
* @return ...
*/
public Application get__app__() {
return app;
}
public int getfreeThreads () {
return app.countFreeEvaluators ();
/**
*
*
* @return ...
*/
public Map getproperties() {
return app.getProperties();
}
public int getactiveThreads () {
return app.countActiveEvaluators ();
/**
*
*
* @return ...
*/
public int getfreeThreads() {
return app.countFreeEvaluators();
}
public int getmaxThreads () {
return app.countEvaluators ();
/**
*
*
* @return ...
*/
public int getactiveThreads() {
return app.countActiveEvaluators();
}
public void setmaxThreads (int n) {
// add one to the number to compensate for the internal scheduler.
app.setNumberOfEvaluators (n+1);
/**
*
*
* @return ...
*/
public int getmaxThreads() {
return app.countEvaluators();
}
public Map getSkinfiles () {
Map skinz = new HashMap ();
for (Iterator it = app.getPrototypes().iterator(); it.hasNext(); ) {
Prototype p = (Prototype) it.next ();
skinz.put (p.getName(), p.getSkinMap());
}
return skinz;
/**
*
*
* @param n ...
*/
public void setmaxThreads(int n) {
// add one to the number to compensate for the internal scheduler.
app.setNumberOfEvaluators(n + 1);
}
public Map getSkinfiles (Object[] skinpath) {
Map skinz = new HashMap ();
for (Iterator it = app.getPrototypes().iterator(); it.hasNext(); ) {
Prototype p = (Prototype) it.next ();
skinz.put (p.getName(), p.getSkinMap(skinpath));
}
return skinz;
/**
*
*
* @return ...
*/
public Map getSkinfiles() {
Map skinz = new HashMap();
for (Iterator it = app.getPrototypes().iterator(); it.hasNext();) {
Prototype p = (Prototype) it.next();
skinz.put(p.getName(), p.getSkinMap());
}
return skinz;
}
public String getAppDir () {
return app.getAppDir().getAbsolutePath();
/**
*
*
* @param skinpath ...
*
* @return ...
*/
public Map getSkinfiles(Object[] skinpath) {
Map skinz = new HashMap();
for (Iterator it = app.getPrototypes().iterator(); it.hasNext();) {
Prototype p = (Prototype) it.next();
skinz.put(p.getName(), p.getSkinMap(skinpath));
}
return skinz;
}
public String getServerDir () {
File f = app.getServerDir();
if (f == null)
f = app.getAppDir();
return f.getAbsolutePath();
/**
*
*
* @return ...
*/
public String getAppDir() {
return app.getAppDir().getAbsolutePath();
}
/**
*
*
* @return ...
*/
public String getServerDir() {
File f = app.getServerDir();
if (f == null) {
f = app.getAppDir();
}
return f.getAbsolutePath();
}
/**
*
*
* @return ...
*/
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;
import java.util.*;
import java.io.*;
import helma.framework.*;
import helma.scripting.*;
import helma.objectmodel.*;
import helma.objectmodel.db.DbMapping;
import helma.scripting.*;
import helma.util.Updatable;
import java.io.*;
import java.util.*;
/**
* The Prototype class represents Script prototypes/type defined in a Helma
@ -18,161 +30,195 @@ import helma.util.Updatable;
* as well as optional information about the mapping of this type to a
* relational database table.
*/
public final class Prototype {
String name;
Application app;
File directory;
File [] files;
File[] files;
long lastDirectoryListing;
long checksum;
HashMap code, zippedCode;
HashMap skins, zippedSkins;
HashMap code;
HashMap zippedCode;
HashMap skins;
HashMap zippedSkins;
HashMap updatables;
// a map of this prototype's skins as raw strings
// used for exposing skins to application (script) code (via app.skinfiles).
SkinMap skinMap;
DbMapping dbmap;
// lastCheck is the time the prototype's files were last checked
private long lastChecksum;
// lastUpdate is the time at which any of the prototype's files were
// found updated the last time
private long lastUpdate;
private Prototype parent;
// Tells us whether this prototype is used to script a generic Java object,
// as opposed to a Helma objectmodel node object.
boolean isJavaPrototype;
public Prototype (String name, File dir, Application app) {
// app.logEvent ("Constructing Prototype "+app.getName()+"/"+name);
this.app = app;
this.name = name;
this.directory = dir;
/**
* Creates a new Prototype object.
*
* @param name ...
* @param dir ...
* @param app ...
*/
public Prototype(String name, File dir, Application app) {
// app.logEvent ("Constructing Prototype "+app.getName()+"/"+name);
this.app = app;
this.name = name;
this.directory = dir;
code = new HashMap ();
zippedCode = new HashMap ();
skins = new HashMap ();
zippedSkins = new HashMap ();
updatables = new HashMap ();
code = new HashMap();
zippedCode = new HashMap();
skins = new HashMap();
zippedSkins = new HashMap();
updatables = new HashMap();
skinMap = new SkinMap ();
skinMap = new SkinMap();
isJavaPrototype = app.isJavaPrototype (name);
lastUpdate = lastChecksum = 0;
isJavaPrototype = app.isJavaPrototype(name);
lastUpdate = lastChecksum = 0;
}
/**
* Return the application this prototype is a part of
*/
public Application getApplication () {
return app;
public Application getApplication() {
return app;
}
/**
* Return this prototype's directory.
*/
public File getDirectory () {
return directory;
public File getDirectory() {
return directory;
}
/**
* Get the list of files in this prototype's directory
*/
public File[] getFiles () {
if (files == null || directory.lastModified() != lastDirectoryListing) {
lastDirectoryListing = directory.lastModified ();
files = directory.listFiles();
if (files == null)
files = new File[0];
}
return files;
public File[] getFiles() {
if ((files == null) || (directory.lastModified() != lastDirectoryListing)) {
lastDirectoryListing = directory.lastModified();
files = directory.listFiles();
if (files == null) {
files = new File[0];
}
}
return files;
}
/**
* Get a checksum over the files in this prototype's directory
*/
public long getChecksum () {
// long start = System.currentTimeMillis();
File[] f = getFiles ();
long c = 0;
for (int i=0; i<f.length; i++)
c += f[i].lastModified();
checksum = c;
// System.err.println ("CHECKSUM "+name+": "+(System.currentTimeMillis()-start));
return checksum;
public long getChecksum() {
// long start = System.currentTimeMillis();
File[] f = getFiles();
long c = 0;
for (int i = 0; i < f.length; i++)
c += f[i].lastModified();
checksum = c;
// System.err.println ("CHECKSUM "+name+": "+(System.currentTimeMillis()-start));
return checksum;
}
public boolean isUpToDate () {
return checksum == lastChecksum;
/**
*
*
* @return ...
*/
public boolean isUpToDate() {
return checksum == lastChecksum;
}
/**
* Set the parent prototype of this prototype, i.e. the prototype this
* prototype inherits from.
*/
public void setParentPrototype (Prototype parent) {
// this is not allowed for the hopobject and global prototypes
if ("hopobject".equalsIgnoreCase (name) || "global".equalsIgnoreCase (name))
return;
this.parent = parent;
public void setParentPrototype(Prototype parent) {
// this is not allowed for the hopobject and global prototypes
if ("hopobject".equalsIgnoreCase(name) || "global".equalsIgnoreCase(name)) {
return;
}
this.parent = parent;
}
/**
* Get the parent prototype from which we inherit, or null
* if we are top of the line.
*/
public Prototype getParentPrototype () {
return parent;
public Prototype getParentPrototype() {
return parent;
}
/**
* Check if the given prototype is within this prototype's parent chain.
*/
public final boolean isInstanceOf (String pname) {
if (name.equals (pname))
return true;
if (parent != null && !"hopobject".equalsIgnoreCase (parent.getName()))
return parent.isInstanceOf (pname);
return false;
public final boolean isInstanceOf(String pname) {
if (name.equals(pname)) {
return true;
}
if ((parent != null) && !"hopobject".equalsIgnoreCase(parent.getName())) {
return parent.isInstanceOf(pname);
}
return false;
}
/**
* Register an object as handler for this prototype and all our parent prototypes.
*/
public final void addToHandlerMap (Map handlers, Object obj) {
if (parent != null && !"hopobject".equalsIgnoreCase (parent.getName()))
parent.addToHandlerMap (handlers, obj);
handlers.put (name, obj);
public final void addToHandlerMap(Map handlers, Object obj) {
if ((parent != null) && !"hopobject".equalsIgnoreCase(parent.getName())) {
parent.addToHandlerMap(handlers, obj);
}
handlers.put(name, obj);
}
public void setDbMapping (DbMapping dbmap) {
this.dbmap = dbmap;
/**
*
*
* @param dbmap ...
*/
public void setDbMapping(DbMapping dbmap) {
this.dbmap = dbmap;
}
public DbMapping getDbMapping () {
return dbmap;
/**
*
*
* @return ...
*/
public DbMapping getDbMapping() {
return dbmap;
}
/**
* Get a Skinfile for this prototype. This only works for skins
* residing in the prototype directory, not for skin files in
* other locations or database stored skins.
*/
public SkinFile getSkinFile (String sfname) {
SkinFile sf = (SkinFile) skins.get (sfname);
if (sf == null)
sf = (SkinFile) zippedSkins.get (sfname);
return sf;
public SkinFile getSkinFile(String sfname) {
SkinFile sf = (SkinFile) skins.get(sfname);
if (sf == null) {
sf = (SkinFile) zippedSkins.get(sfname);
}
return sf;
}
/**
@ -180,25 +226,30 @@ public final class Prototype {
* residing in the prototype directory, not for skins files in
* other locations or database stored skins.
*/
public Skin getSkin (String sfname) {
SkinFile sf = getSkinFile (sfname);
if (sf != null)
return sf.getSkin ();
else
return null;
public Skin getSkin(String sfname) {
SkinFile sf = getSkinFile(sfname);
if (sf != null) {
return sf.getSkin();
} else {
return null;
}
}
public String getName () {
return name;
/**
*
*
* @return ...
*/
public String getName() {
return name;
}
/**
* Get the last time any script has been re-read for this prototype.
*/
public long getLastUpdate () {
return lastUpdate;
public long getLastUpdate() {
return lastUpdate;
}
/**
@ -206,35 +257,35 @@ public final class Prototype {
* re-read from disk and needs to be re-compiled by
* the evaluators.
*/
public void markUpdated () {
lastUpdate = System.currentTimeMillis ();
public void markUpdated() {
lastUpdate = System.currentTimeMillis();
}
/**
* Get the time at which this prototype's scripts were checked
* for changes for the last time.
*/
/* public long getLastCheck () {
return lastCheck;
} */
return lastCheck;
} */
/**
* Signal that the prototype's scripts have been checked for
* changes.
*/
public void markChecked () {
// lastCheck = System.currentTimeMillis ();
lastChecksum = checksum;
public void markChecked() {
// lastCheck = System.currentTimeMillis ();
lastChecksum = checksum;
}
/**
* Return a clone of this prototype's actions container. Synchronized
* to not return a map in a transient state where it is just being
* updated by the type manager.
*/
public synchronized Map getCode () {
return (Map) code.clone();
public synchronized Map getCode() {
return (Map) code.clone();
}
/**
@ -242,232 +293,304 @@ public final class Prototype {
* to not return a map in a transient state where it is just being
* updated by the type manager.
*/
public synchronized Map getZippedCode () {
return (Map) zippedCode.clone();
public synchronized Map getZippedCode() {
return (Map) zippedCode.clone();
}
/**
*
*
* @param action ...
*/
public synchronized void addActionFile(ActionFile action) {
File f = action.getFile();
public synchronized void addActionFile (ActionFile action) {
File f = action.getFile ();
if (f != null) {
code.put (action.getSourceName(), action);
updatables.put (f.getName(), action);
} else {
zippedCode.put (action.getSourceName(), action);
}
if (f != null) {
code.put(action.getSourceName(), action);
updatables.put(f.getName(), action);
} else {
zippedCode.put(action.getSourceName(), action);
}
}
public synchronized void addTemplate (Template template) {
File f = template.getFile ();
if (f != null) {
code.put (template.getSourceName(), template);
updatables.put (f.getName(), template);
} else {
zippedCode.put (template.getSourceName(), template);
}
/**
*
*
* @param template ...
*/
public synchronized void addTemplate(Template template) {
File f = template.getFile();
if (f != null) {
code.put(template.getSourceName(), template);
updatables.put(f.getName(), template);
} else {
zippedCode.put(template.getSourceName(), template);
}
}
public synchronized void addFunctionFile (FunctionFile funcfile) {
File f = funcfile.getFile ();
if (f != null) {
code.put (funcfile.getSourceName(), funcfile);
updatables.put (f.getName(), funcfile);
} else {
zippedCode.put (funcfile.getSourceName(), funcfile);
}
/**
*
*
* @param funcfile ...
*/
public synchronized void addFunctionFile(FunctionFile funcfile) {
File f = funcfile.getFile();
if (f != null) {
code.put(funcfile.getSourceName(), funcfile);
updatables.put(f.getName(), funcfile);
} else {
zippedCode.put(funcfile.getSourceName(), funcfile);
}
}
public synchronized void addSkinFile (SkinFile skinfile) {
File f = skinfile.getFile ();
if (f != null) {
skins.put (skinfile.getName(), skinfile);
updatables.put (f.getName(), skinfile);
} else {
zippedSkins.put (skinfile.getName(), skinfile);
}
/**
*
*
* @param skinfile ...
*/
public synchronized void addSkinFile(SkinFile skinfile) {
File f = skinfile.getFile();
if (f != null) {
skins.put(skinfile.getName(), skinfile);
updatables.put(f.getName(), skinfile);
} else {
zippedSkins.put(skinfile.getName(), skinfile);
}
}
/**
*
*
* @param action ...
*/
public synchronized void removeActionFile(ActionFile action) {
File f = action.getFile();
public synchronized void removeActionFile (ActionFile action) {
File f = action.getFile ();
if (f != null) {
code.remove (action.getSourceName());
updatables.remove (f.getName());
} else {
zippedCode.remove (action.getSourceName());
}
if (f != null) {
code.remove(action.getSourceName());
updatables.remove(f.getName());
} else {
zippedCode.remove(action.getSourceName());
}
}
public synchronized void removeFunctionFile (FunctionFile funcfile) {
File f = funcfile.getFile ();
if (f != null) {
code.remove (funcfile.getSourceName());
updatables.remove (f.getName());
} else {
zippedCode.remove (funcfile.getSourceName());
}
/**
*
*
* @param funcfile ...
*/
public synchronized void removeFunctionFile(FunctionFile funcfile) {
File f = funcfile.getFile();
if (f != null) {
code.remove(funcfile.getSourceName());
updatables.remove(f.getName());
} else {
zippedCode.remove(funcfile.getSourceName());
}
}
public synchronized void removeTemplate (Template template) {
File f = template.getFile ();
if (f != null) {
code.remove (template.getSourceName());
updatables.remove (f.getName());
} else {
zippedCode.remove (template.getSourceName());
}
/**
*
*
* @param template ...
*/
public synchronized void removeTemplate(Template template) {
File f = template.getFile();
if (f != null) {
code.remove(template.getSourceName());
updatables.remove(f.getName());
} else {
zippedCode.remove(template.getSourceName());
}
}
public synchronized void removeSkinFile (SkinFile skinfile) {
File f = skinfile.getFile ();
if (f != null) {
skins.remove (skinfile.getName());
updatables.remove (f.getName());
} else {
zippedSkins.remove (skinfile.getName());
}
/**
*
*
* @param skinfile ...
*/
public synchronized void removeSkinFile(SkinFile skinfile) {
File f = skinfile.getFile();
if (f != null) {
skins.remove(skinfile.getName());
updatables.remove(f.getName());
} else {
zippedSkins.remove(skinfile.getName());
}
}
/**
* Return a string representing this prototype.
*/
public String toString () {
return "[Prototype "+ app.getName()+"/"+name+"]";
/**
* Return a string representing this prototype.
*/
public String toString() {
return "[Prototype " + app.getName() + "/" + name + "]";
}
public SkinMap getSkinMap () {
return skinMap;
/**
*
*
* @return ...
*/
public SkinMap getSkinMap() {
return skinMap;
}
// not yet implemented
public SkinMap getSkinMap (Object[] skinpath) {
return new SkinMap (skinpath);
public SkinMap getSkinMap(Object[] skinpath) {
return new SkinMap(skinpath);
}
// a map that dynamically expands to all skins in this prototype
final class SkinMap extends HashMap {
long lastSkinmapLoad = 0;
Object[] skinpath;
long lastSkinmapLoad = 0;
SkinMap() {
super();
skinpath = null;
}
Object[] skinpath;
SkinMap(Object[] path) {
super();
skinpath = path;
}
SkinMap () {
super ();
skinpath = null;
}
public boolean containsKey(Object key) {
checkForUpdates();
SkinMap (Object[] path) {
super ();
skinpath = path;
}
return super.containsKey(key);
}
public boolean containsKey (Object key) {
checkForUpdates ();
return super.containsKey (key);
}
public boolean containsValue(Object value) {
checkForUpdates();
public boolean containsValue (Object value) {
checkForUpdates ();
return super.containsValue (value);
}
return super.containsValue(value);
}
public Set entrySet () {
checkForUpdates ();
return super.entrySet ();
}
public Set entrySet() {
checkForUpdates();
public boolean equals (Object obj) {
checkForUpdates ();
return super.equals (obj);
}
return super.entrySet();
}
public Object get (Object key) {
if (key == null)
return null;
checkForUpdates ();
SkinFile sf = (SkinFile) super.get (key);
if (sf == null)
return null;
return sf.getSkin().getSource ();
}
public boolean equals(Object obj) {
checkForUpdates();
public int hashCode () {
checkForUpdates ();
return super.hashCode ();
}
return super.equals(obj);
}
public boolean isEmpty () {
checkForUpdates ();
return super.isEmpty ();
}
public Object get(Object key) {
if (key == null) {
return null;
}
public Set keySet () {
checkForUpdates ();
return super.keySet ();
}
checkForUpdates();
public Object put (Object key, Object value) {
// checkForUpdates ();
return super.put (key, value);
}
SkinFile sf = (SkinFile) super.get(key);
public void putAll (Map t) {
// checkForUpdates ();
super.putAll (t);
}
if (sf == null) {
return null;
}
public Object remove (Object key) {
checkForUpdates ();
return super.remove (key);
}
return sf.getSkin().getSource();
}
public int size () {
checkForUpdates ();
return super.size ();
}
public int hashCode() {
checkForUpdates();
public Collection values () {
checkForUpdates ();
return super.values ();
}
return super.hashCode();
}
public boolean isEmpty() {
checkForUpdates();
private void checkForUpdates () {
if (/* lastCheck < System.currentTimeMillis()- 2000l*/ !isUpToDate())
app.typemgr.updatePrototype (Prototype.this);
if (lastUpdate > lastSkinmapLoad)
load ();
}
return super.isEmpty();
}
private synchronized void load () {
if (lastUpdate == lastSkinmapLoad)
return;
super.clear ();
// System.err.println ("LOADING SKIN VALUES: "+Prototype.this);
for (Iterator i = skins.entrySet().iterator(); i.hasNext(); ) {
Map.Entry e = (Map.Entry) i.next ();
super.put (e.getKey(), e.getValue());
}
// if skinpath is not null, overload/add skins from there
if (skinpath != null) {
for (int i=skinpath.length-1; i>=0; i--) {
if (skinpath[i] != null && skinpath[i] instanceof String) {
Map m = app.skinmgr.getSkinFiles ((String) skinpath[i], Prototype.this);
if (m != null)
super.putAll (m);
}
}
}
lastSkinmapLoad = lastUpdate;
}
public String toString () {
return "[SkinMap "+name+"]";
}
public Set keySet() {
checkForUpdates();
return super.keySet();
}
public Object put(Object key, Object value) {
// checkForUpdates ();
return super.put(key, value);
}
public void putAll(Map t) {
// checkForUpdates ();
super.putAll(t);
}
public Object remove(Object key) {
checkForUpdates();
return super.remove(key);
}
public int size() {
checkForUpdates();
return super.size();
}
public Collection values() {
checkForUpdates();
return super.values();
}
private void checkForUpdates() {
if ( /* lastCheck < System.currentTimeMillis()- 2000l*/
!isUpToDate()) {
app.typemgr.updatePrototype(Prototype.this);
}
if (lastUpdate > lastSkinmapLoad) {
load();
}
}
private synchronized void load() {
if (lastUpdate == lastSkinmapLoad) {
return;
}
super.clear();
// System.err.println ("LOADING SKIN VALUES: "+Prototype.this);
for (Iterator i = skins.entrySet().iterator(); i.hasNext();) {
Map.Entry e = (Map.Entry) i.next();
super.put(e.getKey(), e.getValue());
}
// if skinpath is not null, overload/add skins from there
if (skinpath != null) {
for (int i = skinpath.length - 1; i >= 0; i--) {
if ((skinpath[i] != null) && skinpath[i] instanceof String) {
Map m = app.skinmgr.getSkinFiles((String) skinpath[i],
Prototype.this);
if (m != null) {
super.putAll(m);
}
}
}
}
lastSkinmapLoad = lastUpdate;
}
public String toString() {
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;
@ -12,43 +25,45 @@ import java.util.Vector;
/**
* Proxy class for Aplication that listens to requests via RMI.
*/
public class RemoteApplication
extends UnicastRemoteObject
implements IRemoteApp, IReplicationListener {
public class RemoteApplication extends UnicastRemoteObject implements IRemoteApp,
IReplicationListener {
Application app;
public RemoteApplication (Application app) throws RemoteException {
this.app = app;
/**
* Creates a new RemoteApplication object.
*
* @param app ...
*
* @throws RemoteException ...
*/
public RemoteApplication(Application app) throws RemoteException {
this.app = app;
}
/**
* ping method to let clients know if the server is reachable
*/
public void ping () {
// do nothing
public void ping() {
// do nothing
}
/**
* Execute a request coming in from a web client.
*/
public ResponseTrans execute (RequestTrans req) {
return app.execute (req);
public ResponseTrans execute(RequestTrans req) {
return app.execute(req);
}
/**
* Update HopObjects in this application's cache. This is used to replicate
* application caches in a distributed app environment
*/
public void replicateCache (Vector add, Vector delete) {
if (!"true".equalsIgnoreCase (app.getProperty ("allowReplication"))) {
app.logEvent ("Rejecting cache replication event: allowReplication property is not set to true");
throw new RuntimeException ("Replication event rejected: setup does not allow replication.");
}
app.nmgr.replicateCache (add, delete);
public void replicateCache(Vector add, Vector delete) {
if (!"true".equalsIgnoreCase(app.getProperty("allowReplication"))) {
app.logEvent("Rejecting cache replication event: allowReplication property is not set to true");
throw new RuntimeException("Replication event rejected: setup does not allow replication.");
}
app.nmgr.replicateCache(add, delete);
}
}

File diff suppressed because it is too large Load diff

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;
import java.io.*;
import java.util.*;
import java.net.URLEncoder;
import helma.objectmodel.*;
import helma.objectmodel.db.*;
import java.io.*;
import java.net.URLEncoder;
import java.util.*;
/**
* 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
* persistent user node.
*/
public class Session implements Serializable {
transient Application app;
String sessionID;
@ -29,118 +41,175 @@ public class Session implements Serializable {
// the transient cache node that is exposed to javascript
// this stays the same across logins and logouts.
public TransientNode cacheNode;
long onSince, lastTouched, lastModified;
long onSince;
long lastTouched;
long lastModified;
// used to remember messages to the user between requests -
// used for redirects.
String message;
public Session (String sessionID, Application app) {
this.sessionID = sessionID;
this.app = app;
this.uid = null;
this.userHandle = null;
cacheNode = new TransientNode ("session");
onSince = System.currentTimeMillis ();
lastTouched = lastModified = onSince;
/**
* Creates a new Session object.
*
* @param sessionID ...
* @param app ...
*/
public Session(String sessionID, Application app) {
this.sessionID = sessionID;
this.app = app;
this.uid = null;
this.userHandle = null;
cacheNode = new TransientNode("session");
onSince = System.currentTimeMillis();
lastTouched = lastModified = onSince;
}
/**
* attach the given user node to this session.
*/
public void login (INode usernode) {
if (usernode==null) {
userHandle = null;
uid = null;
} else {
userHandle = ((Node)usernode).getHandle();
uid = usernode.getElementName();
}
lastModified = System.currentTimeMillis ();
public void login(INode usernode) {
if (usernode == null) {
userHandle = null;
uid = null;
} else {
userHandle = ((Node) usernode).getHandle();
uid = usernode.getElementName();
}
lastModified = System.currentTimeMillis();
}
/**
* remove this sessions's user node.
*/
public void logout() {
userHandle = null;
uid = null;
lastModified = System.currentTimeMillis ();
userHandle = null;
uid = null;
lastModified = System.currentTimeMillis();
}
/**
*
*
* @return ...
*/
public boolean isLoggedIn() {
if (userHandle!=null && uid!=null) {
return true;
} else {
return false;
}
if ((userHandle != null) && (uid != null)) {
return true;
} else {
return false;
}
}
/**
* Gets the user Node from this Application's NodeManager.
*/
public INode getUserNode() {
if (userHandle!=null)
return userHandle.getNode (app.getWrappedNodeManager());
else
return null;
if (userHandle != null) {
return userHandle.getNode(app.getWrappedNodeManager());
} else {
return null;
}
}
/**
* Gets the transient cache node.
*/
public INode getCacheNode () {
return cacheNode;
public INode getCacheNode() {
return cacheNode;
}
public Application getApp () {
return app;
/**
*
*
* @return ...
*/
public Application getApp() {
return app;
}
public void setApp (Application app) {
this.app = app;
/**
*
*
* @param app ...
*/
public void setApp(Application app) {
this.app = app;
}
public String getSessionID () {
return sessionID;
/**
*
*
* @return ...
*/
public String getSessionID() {
return sessionID;
}
public void touch () {
lastTouched = System.currentTimeMillis ();
/**
*
*/
public void touch() {
lastTouched = System.currentTimeMillis();
}
public long lastTouched () {
return lastTouched;
/**
*
*
* @return ...
*/
public long lastTouched() {
return lastTouched;
}
public long lastModified () {
return lastModified;
}
public void setLastModified (Date date) {
if (date != null)
lastModified = date.getTime ();
/**
*
*
* @return ...
*/
public long lastModified() {
return lastModified;
}
public long onSince () {
return onSince;
/**
*
*
* @param date ...
*/
public void setLastModified(Date date) {
if (date != null) {
lastModified = date.getTime();
}
}
public String toString () {
if ( uid!=null )
return "[Session for user " + uid + "]";
else
return "[Anonymous Session]";
/**
*
*
* @return ...
*/
public long onSince() {
return onSince;
}
/**
*
*
* @return ...
*/
public String toString() {
if (uid != null) {
return "[Session for user " + uid + "]";
} else {
return "[Anonymous Session]";
}
}
/**
* Get the persistent user id of a registered user. This is usually the user name, or
* null if the user is not logged in.
*/
public String getUID () {
return uid;
public String getUID() {
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;
import helma.objectmodel.INode;
import helma.scripting.fesi.*;
import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import helma.objectmodel.INode;
import helma.scripting.fesi.*;
/**
*
*/
public class SessionBean implements Serializable {
// the wrapped session object
Session session;
public SessionBean(Session session) {
this.session = session;
/**
* Creates a new SessionBean object.
*
* @param session ...
*/
public SessionBean(Session session) {
this.session = session;
}
public String toString() {
return session.toString ();
/**
*
*
* @return ...
*/
public String toString() {
return session.toString();
}
public boolean login (String username, String password) {
boolean success = session.getApp().loginSession (username, password, session);
return success;
/**
*
*
* @param username ...
* @param password ...
*
* @return ...
*/
public boolean login(String username, String password) {
boolean success = session.getApp().loginSession(username, password, session);
return success;
}
public void logout () {
session.getApp().logoutSession (session);
/**
*
*/
public void logout() {
session.getApp().logoutSession(session);
}
public void touch () {
session.touch ();
/**
*
*/
public void touch() {
session.touch();
}
/**
*
*
* @return ...
*/
public Date lastActive() {
return new Date (session.lastTouched ());
return new Date(session.lastTouched());
}
/**
*
*
* @return ...
*/
public Date onSince() {
return new Date (session.onSince ());
return new Date(session.onSince());
}
// property-related methods:
public INode getdata() {
return session.getCacheNode ();
return session.getCacheNode();
}
/**
*
*
* @return ...
*/
public INode getuser() {
return session.getUserNode();
return session.getUserNode();
}
public String get_id () {
return session.getSessionID ();
/**
*
*
* @return ...
*/
public String get_id() {
return session.getSessionID();
}
/**
*
*
* @return ...
*/
public String getcookie() {
return session.getSessionID ();
return session.getSessionID();
}
/**
*
*
* @return ...
*/
public Date getlastActive() {
return new Date (session.lastTouched ());
return new Date(session.lastTouched());
}
/**
*
*
* @return ...
*/
public Date getonSince() {
return new Date (session.onSince ());
}
public Date getLastModified () {
return new Date (session.lastModified ());
return new Date(session.onSince());
}
public void setLastModified (Date date) {
session.setLastModified (date);
/**
*
*
* @return ...
*/
public Date getLastModified() {
return new Date(session.lastModified());
}
/**
*
*
* @param date ...
*/
public void setLastModified(Date date) {
session.setLastModified(date);
}
}

File diff suppressed because it is too large Load diff

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;
import java.util.*;
import java.io.*;
import helma.util.Updatable;
import java.io.*;
import java.util.*;
/**
* This represents a File containing a Hop skin
*/
public final class SkinFile implements Updatable {
String name;
Prototype prototype;
Application app;
@ -22,12 +31,19 @@ public final class SkinFile implements Updatable {
Skin skin;
long lastmod = 0;
public SkinFile (File file, String name, Prototype proto) {
this.prototype = proto;
this.file = file;
this.name = name;
this.app = proto.app;
skin = null;
/**
* Creates a new SkinFile object.
*
* @param file ...
* @param name ...
* @param proto ...
*/
public SkinFile(File file, String name, Prototype proto) {
this.prototype = proto;
this.file = file;
this.name = name;
this.app = proto.app;
skin = null;
}
/**
@ -35,88 +51,113 @@ public final class SkinFile implements Updatable {
* Skins contained in zipped applications. The whole update mechanism is bypassed
* by immediately setting the skin member.
*/
public SkinFile (String body, String name, Prototype proto) {
this.prototype = proto;
this.app = proto.app;
this.name = name;
this.file = null;
skin = new Skin (body, app);
public SkinFile(String body, String name, Prototype proto) {
this.prototype = proto;
this.app = proto.app;
this.name = name;
this.file = null;
skin = new Skin(body, app);
}
/**
* Create a skinfile that doesn't belong to a prototype, or at
* least it doesn't know about its prototype and isn't managed by the prototype.
*/
public SkinFile (File file, String name, Application app) {
this.app = app;
this.file = file;
this.name = name;
this.prototype = null;
skin = null;
public SkinFile(File file, String name, Application app) {
this.app = app;
this.file = file;
this.name = name;
this.prototype = null;
skin = null;
}
/**
/**
* Tell the type manager whether we need an update. this is the case when
* the file has been modified or deleted.
*/
public boolean needsUpdate () {
// 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
// cases (file deleted and file changed) by just calling lastModified().
return skin != null ? lastmod != file.lastModified () : !file.exists ();
public boolean needsUpdate() {
// 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
// cases (file deleted and file changed) by just calling lastModified().
return (skin != null) ? (lastmod != file.lastModified()) : (!file.exists());
}
public void update () {
if (!file.exists ()) {
// remove skin from prototype
remove ();
} else {
// we only need to update if the skin has already been initialized
if (skin != null)
read ();
}
/**
*
*/
public void update() {
if (!file.exists()) {
// remove skin from prototype
remove();
} else {
// we only need to update if the skin has already been initialized
if (skin != null) {
read();
}
}
}
private void read () {
try {
FileReader reader = new FileReader (file);
char c[] = new char[(int) file.length()];
int length = reader.read (c);
reader.close();
skin = new Skin (c, length, app);
} catch (IOException x) {
app.logEvent ("Error reading Skin "+file+": "+x);
}
lastmod = file.lastModified ();
private void read() {
try {
FileReader reader = new FileReader(file);
char[] c = new char[(int) file.length()];
int length = reader.read(c);
reader.close();
skin = new Skin(c, length, app);
} catch (IOException x) {
app.logEvent("Error reading Skin " + file + ": " + x);
}
lastmod = file.lastModified();
}
public void remove () {
if (prototype != null) {
prototype.removeSkinFile (this);
}
/**
*
*/
public void remove() {
if (prototype != null) {
prototype.removeSkinFile(this);
}
}
public File getFile () {
return file;
/**
*
*
* @return ...
*/
public File getFile() {
return file;
}
public Skin getSkin () {
if (skin == null)
read ();
return skin;
/**
*
*
* @return ...
*/
public Skin getSkin() {
if (skin == null) {
read();
}
return skin;
}
public String getName () {
return name;
/**
*
*
* @return ...
*/
public String getName() {
return name;
}
public String toString () {
return prototype.getName()+"/"+file.getName();
/**
*
*
* @return ...
*/
public String toString() {
return prototype.getName() + "/" + file.getName();
}
}

View file

@ -1,107 +1,140 @@
// 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;
import java.util.*;
import helma.objectmodel.INode;
import java.io.*;
import java.util.*;
/**
* Manages skins for a Helma application
*/
public final class SkinManager implements FilenameFilter {
Application app;
public SkinManager (Application app) {
this.app = app;
/**
* Creates a new SkinManager object.
*
* @param app ...
*/
public SkinManager(Application app) {
this.app = app;
}
protected Skin getSkin(Prototype proto, String skinname, Object[] skinpath) {
if (proto == null) {
return null;
}
protected Skin getSkin (Prototype proto, String skinname, Object[] skinpath) {
if (proto == null)
return null;
Skin skin = null;
// First check if the skin has been already used within the execution of this request
// check for skinsets set via res.skinpath property
do {
if (skinpath != null) {
for (int i=0; i<skinpath.length; i++) {
skin = getSkinInternal (skinpath[i], proto.getName (), skinname);
if (skin != null) {
return skin;
}
}
}
// 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
skin = proto.getSkin (skinname);
if (skin != null) {
return skin;
}
// still not found. See if there is a parent prototype which might define the skin.
proto = proto.getParentPrototype ();
} while (proto != null);
// looked every where, nothing to be found
return null;
Skin skin = null;
// First check if the skin has been already used within the execution of this request
// check for skinsets set via res.skinpath property
do {
if (skinpath != null) {
for (int i = 0; i < skinpath.length; i++) {
skin = getSkinInternal(skinpath[i], proto.getName(), skinname);
if (skin != null) {
return skin;
}
}
}
// 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
skin = proto.getSkin(skinname);
if (skin != null) {
return skin;
}
// still not found. See if there is a parent prototype which might define the skin.
proto = proto.getParentPrototype();
} while (proto != null);
// looked every where, nothing to be found
return null;
}
protected Skin getSkinInternal(Object skinset, String prototype, String skinname) {
if ((prototype == null) || (skinset == null)) {
return null;
}
protected Skin getSkinInternal (Object skinset, String prototype, String skinname) {
if (prototype == null || skinset == null)
return null;
// check if the skinset object is a HopObject (db based skin)
// or a String (file based skin)
if (skinset instanceof INode) {
INode n = ((INode) skinset).getNode (prototype);
if (n != null) {
n = n.getNode (skinname);
if (n != null) {
String skin = n.getString ("skin");
if (skin != null) {
return new Skin (skin, app);
}
}
}
} else {
// Skinset is interpreted as directory name from which to
// retrieve the skin
File f = new File (skinset.toString (), prototype);
f = new File (f, skinname+".skin");
if (f.exists() && f.canRead()) {
SkinFile sf = new SkinFile (f, skinname, app);
return sf.getSkin ();
}
}
// 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.
return null;
// check if the skinset object is a HopObject (db based skin)
// or a String (file based skin)
if (skinset instanceof INode) {
INode n = ((INode) skinset).getNode(prototype);
if (n != null) {
n = n.getNode(skinname);
if (n != null) {
String skin = n.getString("skin");
if (skin != null) {
return new Skin(skin, app);
}
}
}
} else {
// Skinset is interpreted as directory name from which to
// retrieve the skin
File f = new File(skinset.toString(), prototype);
f = new File(f, skinname + ".skin");
if (f.exists() && f.canRead()) {
SkinFile sf = new SkinFile(f, skinname, app);
return sf.getSkin();
}
}
// 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.
return null;
}
protected Map getSkinFiles(String skinDir, Prototype proto) {
File dir = new File(skinDir.toString(), proto.getName());
String[] skinNames = dir.list(this);
protected Map getSkinFiles (String skinDir, Prototype proto) {
File dir = new File (skinDir.toString (), proto.getName ());
String[] skinNames = dir.list (this);
if (skinNames == null || skinNames.length == 0)
return null;
HashMap map = new HashMap ();
for (int i=0; i<skinNames.length; i++) {
String name = skinNames[i].substring (0, skinNames[i].length()-5);
File file = new File (dir, skinNames[i]);
map.put (name, new SkinFile(file, name, proto));
}
return map;
if ((skinNames == null) || (skinNames.length == 0)) {
return null;
}
HashMap map = new HashMap();
for (int i = 0; i < skinNames.length; i++) {
String name = skinNames[i].substring(0, skinNames[i].length() - 5);
File file = new File(dir, skinNames[i]);
map.put(name, new SkinFile(file, name, proto));
}
return map;
}
/**
/**
* Implements java.io.FilenameFilter.accept()
*/
public boolean accept (File d, String n) {
return n.endsWith (".skin");
public boolean accept(File d, String n) {
return n.endsWith(".skin");
}
}

View file

@ -1,230 +1,300 @@
// 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;
import helma.objectmodel.*;
import helma.objectmodel.db.DbMapping;
import helma.scripting.*;
import helma.util.*;
import java.util.*;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
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.
*/
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;
File appDir;
HashMap prototypes; // map of prototypes
HashMap zipfiles; // map of zipped script files
HashSet jarfiles; // set of Java archives
HashMap prototypes; // map of prototypes
HashMap zipfiles; // map of zipped script files
HashSet jarfiles; // set of Java archives
long lastCheck = 0;
long appDirMod = 0;
// a checksum that changes whenever something in the application files changes.
long checksum;
// the hopobject prototype
Prototype hopobjectProto;
// the global prototype
Prototype globalProto;
// app specific class loader, includes jar files in the app directory
AppClassLoader loader;
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";
public TypeManager (Application app) throws MalformedURLException {
/**
* Creates a new TypeManager object.
*
* @param app ...
*
* @throws MalformedURLException ...
* @throws RuntimeException ...
*/
public TypeManager(Application app) throws MalformedURLException {
this.app = app;
appDir = app.appDir;
// make sure the directories for the standard prototypes exist, and lament otherwise
if (appDir.list().length == 0) {
for (int i=0; i<standardTypes.length; i++) {
File f = new File (appDir, standardTypes[i]);
if (!f.exists() && !f.mkdir ())
app.logEvent ("Warning: directory "+f.getAbsolutePath ()+" could not be created.");
else if (!f.isDirectory ())
app.logEvent ("Warning: "+f.getAbsolutePath ()+" is not a directory.");
for (int i = 0; i < standardTypes.length; i++) {
File f = new File(appDir, standardTypes[i]);
if (!f.exists() && !f.mkdir()) {
app.logEvent("Warning: directory " + f.getAbsolutePath() +
" could not be created.");
} else if (!f.isDirectory()) {
app.logEvent("Warning: " + f.getAbsolutePath() +
" is not a directory.");
}
}
}
prototypes = new HashMap ();
zipfiles = new HashMap ();
jarfiles = new HashSet ();
prototypes = new HashMap();
zipfiles = new HashMap();
jarfiles = new HashSet();
URL[] urls = ((URLClassLoader) TypeManager.class.getClassLoader()).getURLs();
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();
if (url.endsWith ("helma.jar")) {
if (url.endsWith("helma.jar")) {
helmajar = urls[i];
break;
}
}
if (helmajar == null)
throw new RuntimeException ("helma.jar not found in embedding classpath");
if (helmajar == null) {
throw new RuntimeException("helma.jar not found in embedding classpath");
}
loader = new AppClassLoader(app.getName(), new URL[] { helmajar });
}
/**
* Run through application's prototype directories and create prototypes, but don't
* compile or evaluate any scripts.
*/
public void createPrototypes () {
public void createPrototypes() {
// create standard prototypes.
createPrototype ("root");
createPrototype ("user");
createPrototype("root");
createPrototype("user");
// get references to hopobject and global protos,
// since we need it regularly when setting parent prototypes.
hopobjectProto = createPrototype ("hopobject");
globalProto = createPrototype ("global");
// loop through directories and create prototypes
checkFiles ();
}
hopobjectProto = createPrototype("hopobject");
globalProto = createPrototype("global");
// loop through directories and create prototypes
checkFiles();
}
/**
* Run through application's prototype directories and check if anything has been updated.
* If so, update prototypes and scripts.
*/
public synchronized void checkPrototypes () {
if (System.currentTimeMillis () - lastCheck < 1000l)
return;
try {
checkFiles ();
} catch (Exception ignore) {}
lastCheck = System.currentTimeMillis ();
public synchronized void checkPrototypes() {
if ((System.currentTimeMillis() - lastCheck) < 1000L) {
return;
}
try {
checkFiles();
} catch (Exception ignore) {
}
lastCheck = System.currentTimeMillis();
}
/**
* Run through application's prototype directories and check if
* there are any prototypes to be created.
*/
public void checkFiles () {
// check if any files have been created/removed since last time we
// checked...
if (appDir.lastModified() > appDirMod) {
appDirMod = appDir.lastModified ();
String[] list = appDir.list ();
if (list == null)
throw new RuntimeException ("Can't read app directory "+appDir+" - check permissions");
for (int i=0; i<list.length; i++) {
if (list[i].endsWith (".zip")) {
ZippedAppFile zipped = (ZippedAppFile) zipfiles.get (list[i]);
if (zipped == null) {
File f = new File (appDir, list[i]);
if (!f.isDirectory ()) {
zipped = new ZippedAppFile (f, app);
zipfiles.put (list[i], zipped);
}
}
continue;
}
if (list[i].endsWith (".jar")) {
if (!jarfiles.contains (list[i])) {
jarfiles.add (list[i]);
File f = new File (appDir, list[i]);
try {
loader.addURL (new URL ("file:"+f.getAbsolutePath()));
} catch (MalformedURLException ignore) {}
}
continue;
}
if (list[i].indexOf ('.') > -1)
continue;
Prototype proto = getPrototype (list[i]);
// if prototype doesn't exist, create it
if (proto == null && isValidTypeName (list[i])) {
File f = new File (appDir, list[i]);
if (f.isDirectory ()) {
// create new prototype
createPrototype (list[i], f);
}
}
}
}
public void checkFiles() {
// check if any files have been created/removed since last time we
// checked...
if (appDir.lastModified() > appDirMod) {
appDirMod = appDir.lastModified();
// calculate this app's checksum by adding all checksums from all prototypes
long newChecksum = 0;
String[] list = appDir.list();
// loop through zip files to check for updates
for (Iterator it=zipfiles.values ().iterator (); it.hasNext (); ) {
ZippedAppFile zipped = (ZippedAppFile) it.next ();
if (zipped.needsUpdate ()) {
zipped.update ();
}
newChecksum += zipped.lastmod;
}
if (list == null) {
throw new RuntimeException("Can't read app directory " + appDir +
" - check permissions");
}
// loop through prototypes and check if type.properties needs updates
// it's important that we do this _after_ potentially new prototypes
// have been created in the previous loop.
for (Iterator i=prototypes.values().iterator(); i.hasNext(); ) {
Prototype proto = (Prototype) i.next ();
// calculate this app's type checksum
newChecksum += proto.getChecksum();
// update prototype's type mapping
DbMapping dbmap = proto.getDbMapping ();
if (dbmap != null && dbmap.needsUpdate ()) {
dbmap.update ();
if (proto != hopobjectProto && proto != globalProto) {
// set parent prototype, in case it has changed.
String parentName = dbmap.getExtends ();
if (parentName != null)
proto.setParentPrototype (getPrototype (parentName));
else if (!app.isJavaPrototype (proto.getName()))
proto.setParentPrototype (hopobjectProto);
}
}
}
checksum = newChecksum;
for (int i = 0; i < list.length; i++) {
if (list[i].endsWith(".zip")) {
ZippedAppFile zipped = (ZippedAppFile) zipfiles.get(list[i]);
if (zipped == null) {
File f = new File(appDir, list[i]);
if (!f.isDirectory()) {
zipped = new ZippedAppFile(f, app);
zipfiles.put(list[i], zipped);
}
}
continue;
}
if (list[i].endsWith(".jar")) {
if (!jarfiles.contains(list[i])) {
jarfiles.add(list[i]);
File f = new File(appDir, list[i]);
try {
loader.addURL(new URL("file:" + f.getAbsolutePath()));
} catch (MalformedURLException ignore) {
}
}
continue;
}
if (list[i].indexOf('.') > -1) {
continue;
}
Prototype proto = getPrototype(list[i]);
// if prototype doesn't exist, create it
if ((proto == null) && isValidTypeName(list[i])) {
File f = new File(appDir, list[i]);
if (f.isDirectory()) {
// create new prototype
createPrototype(list[i], f);
}
}
}
}
// calculate this app's checksum by adding all checksums from all prototypes
long newChecksum = 0;
// loop through zip files to check for updates
for (Iterator it = zipfiles.values().iterator(); it.hasNext();) {
ZippedAppFile zipped = (ZippedAppFile) it.next();
if (zipped.needsUpdate()) {
zipped.update();
}
newChecksum += zipped.lastmod;
}
// loop through prototypes and check if type.properties needs updates
// it's important that we do this _after_ potentially new prototypes
// have been created in the previous loop.
for (Iterator i = prototypes.values().iterator(); i.hasNext();) {
Prototype proto = (Prototype) i.next();
// calculate this app's type checksum
newChecksum += proto.getChecksum();
// update prototype's type mapping
DbMapping dbmap = proto.getDbMapping();
if ((dbmap != null) && dbmap.needsUpdate()) {
dbmap.update();
if ((proto != hopobjectProto) && (proto != globalProto)) {
// set parent prototype, in case it has changed.
String parentName = dbmap.getExtends();
if (parentName != null) {
proto.setParentPrototype(getPrototype(parentName));
} else if (!app.isJavaPrototype(proto.getName())) {
proto.setParentPrototype(hopobjectProto);
}
}
}
}
checksum = newChecksum;
}
protected void removeZipFile (String zipname) {
zipfiles.remove (zipname);
for (Iterator i=prototypes.values().iterator(); i.hasNext(); ) {
Prototype proto = (Prototype) i.next ();
// update prototype's type mapping
DbMapping dbmap = proto.getDbMapping ();
SystemProperties props = dbmap.getProperties();
props.removeProps (zipname);
}
protected void removeZipFile(String zipname) {
zipfiles.remove(zipname);
for (Iterator i = prototypes.values().iterator(); i.hasNext();) {
Prototype proto = (Prototype) i.next();
// update prototype's type mapping
DbMapping dbmap = proto.getDbMapping();
SystemProperties props = dbmap.getProperties();
props.removeProps(zipname);
}
}
private boolean isValidTypeName(String str) {
if (str == null) {
return false;
}
private boolean isValidTypeName (String str) {
if (str == null)
return false;
char[] c = str.toCharArray ();
for (int i=0; i<c.length; i++)
if (!Character.isJavaIdentifierPart (c[i]))
return false;
return true;
}
char[] c = str.toCharArray();
/**
* Return a checksum over all files in all prototypes in this application.
* The checksum can be used to find out quickly if any file has changed.
*/
public long getChecksum () {
return checksum;
for (int i = 0; i < c.length; i++)
if (!Character.isJavaIdentifierPart(c[i])) {
return false;
}
return true;
}
/**
* Get a prototype defined for this application
*/
public Prototype getPrototype (String typename) {
return (Prototype) prototypes.get (typename);
* Return a checksum over all files in all prototypes in this application.
* The checksum can be used to find out quickly if any file has changed.
*/
public long getChecksum() {
return checksum;
}
/**
* Get a prototype defined for this application
*/
public Prototype getPrototype(String typename) {
return (Prototype) prototypes.get(typename);
}
/**
@ -232,152 +302,167 @@ public final class TypeManager {
* that it doesn't create a DbMapping - this is left to the
* caller (e.g. ZippedAppFile).
*/
public Prototype createPrototype (String typename) {
return createPrototype (typename, new File (appDir, typename));
public Prototype createPrototype(String typename) {
return createPrototype(typename, new File(appDir, typename));
}
/**
* Create a prototype from a directory containing scripts and other stuff
*/
public Prototype createPrototype (String typename, File dir) {
Prototype proto = new Prototype (typename, dir, app);
// Create and register type properties file
File propfile = new File (dir, "type.properties");
SystemProperties props = new SystemProperties (propfile.getAbsolutePath ());
DbMapping dbmap = new DbMapping (app, typename, props);
// we don't need to put the DbMapping into proto.updatables, because
// dbmappings are checked separately in checkFiles for each request
// proto.updatables.put ("type.properties", dbmap);
proto.setDbMapping (dbmap);
// put the prototype into our map
prototypes.put (typename, proto);
return proto;
public Prototype createPrototype(String typename, File dir) {
Prototype proto = new Prototype(typename, dir, app);
// Create and register type properties file
File propfile = new File(dir, "type.properties");
SystemProperties props = new SystemProperties(propfile.getAbsolutePath());
DbMapping dbmap = new DbMapping(app, typename, props);
// we don't need to put the DbMapping into proto.updatables, because
// dbmappings are checked separately in checkFiles for each request
// proto.updatables.put ("type.properties", dbmap);
proto.setDbMapping(dbmap);
// put the prototype into our map
prototypes.put(typename, proto);
return proto;
}
/**
* Update a prototype to the files in the prototype directory.
*/
public void updatePrototype (String name) {
* Update a prototype to the files in the prototype directory.
*/
public void updatePrototype(String name) {
// System.err.println ("UPDATE PROTO: "+app.getName()+"/"+name);
Prototype proto = getPrototype (name);
updatePrototype (proto);
Prototype proto = getPrototype(name);
updatePrototype(proto);
}
/**
* Update a prototype to the files in the prototype directory.
*/
public void updatePrototype (Prototype proto) {
if (proto == null || proto.isUpToDate())
* Update a prototype to the files in the prototype directory.
*/
public void updatePrototype(Prototype proto) {
if ((proto == null) || proto.isUpToDate()) {
return;
}
synchronized (proto) {
// check again because another thread may have checked the
// prototype while we were waiting for access to the synchronized section
/* if (System.currentTimeMillis() - proto.getLastCheck() < 1000)
return; */
File dir = proto.getDirectory ();
/* if (System.currentTimeMillis() - proto.getLastCheck() < 1000)
return; */
File dir = proto.getDirectory();
HashSet updateSet = null;
HashSet createSet = null;
// our plan is to do as little as possible, so first check if
// 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();
if (upd.needsUpdate ()) {
if (updateSet == null)
updateSet = new HashSet ();
updateSet.add (upd);
if (upd.needsUpdate()) {
if (updateSet == null) {
updateSet = new HashSet();
}
updateSet.add(upd);
}
}
// next we check if files have been created or removed since last update
// if (proto.getLastCheck() < dir.lastModified ()) {
File[] list = proto.getFiles();
for (int i=0; i<list.length; i++) {
String fn = list[i].getName();
if (!proto.updatables.containsKey (fn)) {
if (fn.endsWith (templateExtension) ||
fn.endsWith (scriptExtension) ||
fn.endsWith (actionExtension) ||
fn.endsWith (skinExtension) ||
"type.properties".equalsIgnoreCase (fn))
{
if (createSet == null)
createSet = new HashSet ();
createSet.add (list[i]);
File[] list = proto.getFiles();
for (int i = 0; i < list.length; i++) {
String fn = list[i].getName();
if (!proto.updatables.containsKey(fn)) {
if (fn.endsWith(templateExtension) || fn.endsWith(scriptExtension) ||
fn.endsWith(actionExtension) || fn.endsWith(skinExtension) ||
"type.properties".equalsIgnoreCase(fn)) {
if (createSet == null) {
createSet = new HashSet();
}
createSet.add(list[i]);
}
}
// }
}
// }
// if nothing needs to be updated, mark prototype as checked and return
if (updateSet == null && createSet == null) {
proto.markChecked ();
if ((updateSet == null) && (createSet == null)) {
proto.markChecked();
return;
}
// first go through new files and create new items
if (createSet != null) {
Object[] newFiles = createSet.toArray ();
for (int i=0; i<newFiles.length; i++) {
Object[] newFiles = createSet.toArray();
for (int i = 0; i < newFiles.length; i++) {
File file = (File) newFiles[i];
String filename = file.getName ();
int dot = filename.lastIndexOf (".");
String filename = file.getName();
int dot = filename.lastIndexOf(".");
String tmpname = filename.substring(0, dot);
if (filename.endsWith (templateExtension)) {
if (filename.endsWith(templateExtension)) {
try {
Template t = new Template (file, tmpname, proto);
proto.addTemplate (t);
Template t = new Template(file, tmpname, proto);
proto.addTemplate(t);
} catch (Throwable x) {
app.logEvent ("Error updating prototype: "+x);
app.logEvent("Error updating prototype: " + x);
}
} else if (filename.endsWith (scriptExtension)) {
} else if (filename.endsWith(scriptExtension)) {
try {
FunctionFile ff = new FunctionFile (file, proto);
proto.addFunctionFile (ff);
FunctionFile ff = new FunctionFile(file, proto);
proto.addFunctionFile(ff);
} catch (Throwable x) {
app.logEvent ("Error updating prototype: "+x);
app.logEvent("Error updating prototype: " + x);
}
} else if (filename.endsWith (actionExtension)) {
} else if (filename.endsWith(actionExtension)) {
try {
ActionFile af = new ActionFile (file, tmpname, proto);
proto.addActionFile (af);
ActionFile af = new ActionFile(file, tmpname, proto);
proto.addActionFile(af);
} catch (Throwable x) {
app.logEvent ("Error updating prototype: "+x);
app.logEvent("Error updating prototype: " + x);
}
} else if (filename.endsWith (skinExtension)) {
SkinFile sf = new SkinFile (file, tmpname, proto);
proto.addSkinFile (sf);
} else if (filename.endsWith(skinExtension)) {
SkinFile sf = new SkinFile(file, tmpname, proto);
proto.addSkinFile(sf);
}
}
}
// next go through existing updatables
if (updateSet != null) {
for (Iterator i = updateSet.iterator(); i.hasNext(); ) {
for (Iterator i = updateSet.iterator(); i.hasNext();) {
Updatable upd = (Updatable) i.next();
try {
upd.update ();
upd.update();
} catch (Exception x) {
if (upd instanceof DbMapping)
app.logEvent ("Error updating db mapping for type "+proto.getName()+": "+x);
else
app.logEvent ("Error updating "+upd+" of prototye type "+proto.getName()+": "+x);
if (upd instanceof DbMapping) {
app.logEvent("Error updating db mapping for type " +
proto.getName() + ": " + x);
} else {
app.logEvent("Error updating " + upd + " of prototye type " +
proto.getName() + ": " + x);
}
}
}
}
// mark prototype as checked and updated.
proto.markChecked ();
proto.markChecked();
proto.markUpdated();
} // end of synchronized (proto)
}
// end of synchronized (proto)
}
}

View file

@ -1,160 +1,208 @@
// 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;
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.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.
*/
public class ZippedAppFile implements Updatable {
Application app;
File file;
long lastmod;
Set updatables;
/**
* Creates a new ZippedAppFile object.
*
* @param file ...
* @param app ...
*/
public ZippedAppFile(File file, Application app) {
this.app = app;
this.file = file;
public ZippedAppFile (File file, Application app) {
this.app = app;
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
* the file has been modified or deleted.
*/
public boolean needsUpdate () {
return !file.exists () || lastmod != file.lastModified ();
public boolean needsUpdate() {
return !file.exists() || (lastmod != file.lastModified());
}
/**
*
*/
public void update() {
if (!file.exists()) {
remove();
} else {
ZipFile zip = null;
public void update () {
// collect created protos - we need this to check DbMappings for each created
// prototype afterwards
HashSet newPrototypes = new HashSet();
if (!file.exists ()) {
remove ();
try {
lastmod = file.lastModified();
} else {
// System.err.println ("UPDATING ZIP FILE "+this);
zip = new ZipFile(file);
updatables = new HashSet();
ZipFile zip = null;
// collect created protos - we need this to check DbMappings for each created
// prototype afterwards
HashSet newPrototypes = new HashSet ();
try {
lastmod = file.lastModified ();
// System.err.println ("UPDATING ZIP FILE "+this);
zip = new ZipFile (file);
updatables = new HashSet ();
for (Enumeration en = zip.entries (); en.hasMoreElements (); ) {
ZipEntry entry = (ZipEntry) en.nextElement ();
String ename = entry.getName ();
StringTokenizer st = new StringTokenizer (ename, "/");
if (st.countTokens () == 2) {
String dir = st.nextToken ();
String fname = st.nextToken ();
// System.err.println ("ZIPENTRY: "+ dir +" ~ "+fname);
Prototype proto = app.typemgr.getPrototype (dir);
if (proto == null) {
proto = app.typemgr.createPrototype (dir);
newPrototypes.add (proto);
}
if (fname.endsWith (".hac")) {
String name = fname.substring (0, fname.lastIndexOf ("."));
String sourceName = file.getName()+"/"+ename;
String content = getZipEntryContent (zip, entry);
// System.err.println ("["+content+"]");
ActionFile act = new ActionFile (content, name, sourceName, proto);
proto.addActionFile (act);
updatables.add (act);
// mark prototype as updated
proto.markUpdated ();
}
else if (fname.endsWith (".hsp")) {
String name = fname.substring (0, fname.lastIndexOf ("."));
String sourceName = file.getName()+"/"+ename;
String content = getZipEntryContent (zip, entry);
// System.err.println ("["+content+"]");
Template tmp = new Template (content, name, sourceName, proto);
proto.addTemplate (tmp);
updatables.add (tmp);
// mark prototype as updated
proto.markUpdated ();
}
else if (fname.endsWith (".skin")) {
String name = fname.substring (0, fname.lastIndexOf ("."));
String content = getZipEntryContent (zip, entry);
// System.err.println ("["+content+"]");
SkinFile skin = new SkinFile (content, name, proto);
proto.addSkinFile (skin);
updatables.add (skin);
}
else if (fname.endsWith (".js")) {
String sourceName = file.getName()+"/"+ename;
String content = getZipEntryContent (zip, entry);
// System.err.println ("["+content+"]");
FunctionFile ff = new FunctionFile (content, sourceName, proto);
proto.addFunctionFile (ff);
updatables.add (ff);
// mark prototype as updated
proto.markUpdated ();
}
else if ("type.properties".equalsIgnoreCase (fname)) {
DbMapping dbmap = proto.getDbMapping ();
SystemProperties props = dbmap.getProperties ();
props.addProps (file.getName(), zip.getInputStream (entry));
// mark prototype as updated
proto.markUpdated ();
}
}
}
} catch (Throwable x) {
System.err.println ("Error updating ZipFile: "+x);
} finally {
try {
zip.close ();
} catch (Exception ignore) {}
}
}
for (Enumeration en = zip.entries(); en.hasMoreElements();) {
ZipEntry entry = (ZipEntry) en.nextElement();
String ename = entry.getName();
StringTokenizer st = new StringTokenizer(ename, "/");
if (st.countTokens() == 2) {
String dir = st.nextToken();
String fname = st.nextToken();
// System.err.println ("ZIPENTRY: "+ dir +" ~ "+fname);
Prototype proto = app.typemgr.getPrototype(dir);
if (proto == null) {
proto = app.typemgr.createPrototype(dir);
newPrototypes.add(proto);
}
if (fname.endsWith(".hac")) {
String name = fname.substring(0, fname.lastIndexOf("."));
String sourceName = file.getName() + "/" + ename;
String content = getZipEntryContent(zip, entry);
// System.err.println ("["+content+"]");
ActionFile act = new ActionFile(content, name, sourceName,
proto);
proto.addActionFile(act);
updatables.add(act);
// mark prototype as updated
proto.markUpdated();
} else if (fname.endsWith(".hsp")) {
String name = fname.substring(0, fname.lastIndexOf("."));
String sourceName = file.getName() + "/" + ename;
String content = getZipEntryContent(zip, entry);
// System.err.println ("["+content+"]");
Template tmp = new Template(content, name, sourceName, proto);
proto.addTemplate(tmp);
updatables.add(tmp);
// mark prototype as updated
proto.markUpdated();
} else if (fname.endsWith(".skin")) {
String name = fname.substring(0, fname.lastIndexOf("."));
String content = getZipEntryContent(zip, entry);
// System.err.println ("["+content+"]");
SkinFile skin = new SkinFile(content, name, proto);
proto.addSkinFile(skin);
updatables.add(skin);
} else if (fname.endsWith(".js")) {
String sourceName = file.getName() + "/" + ename;
String content = getZipEntryContent(zip, entry);
// System.err.println ("["+content+"]");
FunctionFile ff = new FunctionFile(content, sourceName, proto);
proto.addFunctionFile(ff);
updatables.add(ff);
// mark prototype as updated
proto.markUpdated();
} else if ("type.properties".equalsIgnoreCase(fname)) {
DbMapping dbmap = proto.getDbMapping();
SystemProperties props = dbmap.getProperties();
props.addProps(file.getName(), zip.getInputStream(entry));
// mark prototype as updated
proto.markUpdated();
}
}
}
} catch (Throwable x) {
System.err.println("Error updating ZipFile: " + x);
} finally {
try {
zip.close();
} catch (Exception ignore) {
}
}
}
}
public void remove () {
if (updatables != null) {
for (Iterator it = updatables.iterator(); it.hasNext(); )
((Updatable) it.next()).remove ();
}
app.typemgr.removeZipFile (file.getName());
// System.err.println ("REMOVING ZIP FILE "+this);
/**
*
*/
public void remove() {
if (updatables != null) {
for (Iterator it = updatables.iterator(); it.hasNext();)
((Updatable) it.next()).remove();
}
app.typemgr.removeZipFile(file.getName());
// System.err.println ("REMOVING ZIP FILE "+this);
}
/**
*
*
* @param zip ...
* @param entry ...
*
* @return ...
*
* @throws IOException ...
*/
public String getZipEntryContent(ZipFile zip, ZipEntry entry)
throws IOException {
int size = (int) entry.getSize();
char[] c = new char[size];
InputStreamReader reader = new InputStreamReader(zip.getInputStream(entry));
public String getZipEntryContent (ZipFile zip, ZipEntry entry) throws IOException {
int size = (int) entry.getSize ();
char[] c = new char[size];
InputStreamReader reader = new InputStreamReader (zip.getInputStream (entry));
reader.read (c);
return new String (c);
reader.read(c);
return new String(c);
}
public String toString () {
return file.getName();
/**
*
*
* @return ...
*/
public String toString() {
return file.getName();
}
}

View file

@ -1,198 +1,295 @@
// 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;
import java.awt.*;
import java.awt.image.*;
import java.net.URL;
import java.net.MalformedURLException;
import java.net.URL;
/**
* Factory class for generating Image objects from various sources.
*
*/
public class ImageGenerator {
public ImageGenerator () {
// nothing to do
/**
* Creates a new ImageGenerator object.
*/
public ImageGenerator() {
// nothing to do
}
public ImageWrapper createPaintableImage (int w, int h) {
BufferedImage img = new BufferedImage (w, h, BufferedImage.TYPE_INT_RGB);
Graphics g = img.getGraphics ();
ImageWrapper rimg = new SunImageWrapper (img, g, w, h, this);
return rimg;
/**
*
*
* @param w ...
* @param h ...
*
* @return ...
*/
public ImageWrapper createPaintableImage(int w, int h) {
BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Graphics g = img.getGraphics();
ImageWrapper rimg = new SunImageWrapper(img, g, w, h, this);
return rimg;
}
public ImageWrapper createPaintableImage (byte src[]) {
ImageWrapper rimg = null;
Image img1 = Toolkit.getDefaultToolkit ().createImage (src);
ImageLoader loader = new ImageLoader (img1);
try {
loader.getDimensions ();
int w = loader.getWidth ();
int h = loader.getHeight ();
Image img = new BufferedImage (w, h, BufferedImage.TYPE_INT_RGB);
Graphics g = img.getGraphics ();
g.drawImage (img1, 0, 0, null);
rimg = new SunImageWrapper (img, g, w, h, this);
} finally {
loader.done();
}
return rimg;
}
/**
*
*
* @param src ...
*
* @return ...
*/
public ImageWrapper createPaintableImage(byte[] src) {
ImageWrapper rimg = null;
Image img1 = Toolkit.getDefaultToolkit().createImage(src);
ImageLoader loader = new ImageLoader(img1);
public ImageWrapper createImage (byte src[]) {
ImageWrapper rimg = null;
Image img = Toolkit.getDefaultToolkit ().createImage (src);
ImageLoader loader = new ImageLoader (img);
try {
loader.getDimensions ();
int w = loader.getWidth ();
int h = loader.getHeight ();
rimg = new SunImageWrapper (img, null, w, h, this);
} finally {
loader.done();
}
return rimg;
}
try {
loader.getDimensions();
int w = loader.getWidth();
int h = loader.getHeight();
Image img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Graphics g = img.getGraphics();
public ImageWrapper createPaintableImage (String urlstring) throws MalformedURLException {
ImageWrapper rimg = null;
URL url = new URL (urlstring);
Image img1 = Toolkit.getDefaultToolkit ().createImage (url);
ImageLoader loader = new ImageLoader (img1);
try {
loader.getDimensions ();
int w = loader.getWidth ();
int h = loader.getHeight ();
Image img = new BufferedImage (w, h, BufferedImage.TYPE_INT_RGB);
Graphics g = img.getGraphics ();
g.drawImage (img1, 0, 0, null);
rimg = new SunImageWrapper (img, g, w, h, this);
} finally {
g.drawImage(img1, 0, 0, null);
rimg = new SunImageWrapper(img, g, w, h, this);
} finally {
loader.done();
}
return rimg;
return rimg;
}
public ImageWrapper createPaintableImage (ImageWrapper iw, ImageFilter filter) {
ImageWrapper rimg = null;
FilteredImageSource fis = new FilteredImageSource (iw.getSource(), filter);
Image img1 = Toolkit.getDefaultToolkit().createImage (fis);
ImageLoader loader = new ImageLoader (img1);
try {
loader.getDimensions ();
int w = loader.getWidth ();
int h = loader.getHeight ();
Image img = new BufferedImage (w, h, BufferedImage.TYPE_INT_RGB);
Graphics g = img.getGraphics ();
g.drawImage (img1, 0, 0, null);
rimg = new SunImageWrapper (img, g, w, h, this);
} finally {
/**
*
*
* @param src ...
*
* @return ...
*/
public ImageWrapper createImage(byte[] src) {
ImageWrapper rimg = null;
Image img = Toolkit.getDefaultToolkit().createImage(src);
ImageLoader loader = new ImageLoader(img);
try {
loader.getDimensions();
int w = loader.getWidth();
int h = loader.getHeight();
rimg = new SunImageWrapper(img, null, w, h, this);
} finally {
loader.done();
}
return rimg;
return rimg;
}
/**
*
*
* @param urlstring ...
*
* @return ...
*
* @throws MalformedURLException ...
*/
public ImageWrapper createPaintableImage(String urlstring)
throws MalformedURLException {
ImageWrapper rimg = null;
URL url = new URL(urlstring);
Image img1 = Toolkit.getDefaultToolkit().createImage(url);
ImageLoader loader = new ImageLoader(img1);
public Image createImage (String filename) {
Image img = null;
img = Toolkit.getDefaultToolkit ().createImage (filename);
ImageLoader loader = new ImageLoader (img);
loader.getDimensions ();
loader.done();
return img;
try {
loader.getDimensions();
int w = loader.getWidth();
int h = loader.getHeight();
Image img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Graphics g = img.getGraphics();
g.drawImage(img1, 0, 0, null);
rimg = new SunImageWrapper(img, g, w, h, this);
} finally {
loader.done();
}
return rimg;
}
public Image createImage (ImageProducer producer) {
Image img = null;
img = Toolkit.getDefaultToolkit ().createImage (producer);
ImageLoader loader = new ImageLoader (img);
loader.getDimensions ();
loader.done();
return img;
/**
*
*
* @param iw ...
* @param filter ...
*
* @return ...
*/
public ImageWrapper createPaintableImage(ImageWrapper iw, ImageFilter filter) {
ImageWrapper rimg = null;
FilteredImageSource fis = new FilteredImageSource(iw.getSource(), filter);
Image img1 = Toolkit.getDefaultToolkit().createImage(fis);
ImageLoader loader = new ImageLoader(img1);
try {
loader.getDimensions();
int w = loader.getWidth();
int h = loader.getHeight();
Image img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Graphics g = img.getGraphics();
g.drawImage(img1, 0, 0, null);
rimg = new SunImageWrapper(img, g, w, h, this);
} finally {
loader.done();
}
return rimg;
}
/**
*
*
* @param filename ...
*
* @return ...
*/
public Image createImage(String filename) {
Image img = null;
img = Toolkit.getDefaultToolkit().createImage(filename);
ImageLoader loader = new ImageLoader(img);
loader.getDimensions();
loader.done();
return img;
}
/**
*
*
* @param producer ...
*
* @return ...
*/
public Image createImage(ImageProducer producer) {
Image img = null;
img = Toolkit.getDefaultToolkit().createImage(producer);
ImageLoader loader = new ImageLoader(img);
loader.getDimensions();
loader.done();
return img;
}
class ImageLoader implements ImageObserver {
Image img;
int w;
int h;
boolean waiting;
boolean firstFrameLoaded;
Image img;
int w, h;
boolean waiting;
boolean firstFrameLoaded;
ImageLoader(Image img) {
this.img = img;
waiting = true;
firstFrameLoaded = false;
}
ImageLoader (Image img) {
this.img = img;
waiting = true;
firstFrameLoaded = false;
}
synchronized void getDimensions() {
w = img.getWidth(this);
h = img.getHeight(this);
synchronized void getDimensions () {
w = img.getWidth(this);
h = img.getHeight (this);
if (w == -1 || h == -1) {
try {
wait (45000);
} catch (InterruptedException x) {
waiting = false;
return;
} finally {
waiting = false;
}
}
// if width and height haven't been set, throw tantrum
if (w == -1 || h == -1) {
throw new RuntimeException ("Error loading image");
}
}
if ((w == -1) || (h == -1)) {
try {
wait(45000);
} catch (InterruptedException x) {
waiting = false;
synchronized void done () {
waiting = false;
notifyAll ();
}
return;
} finally {
waiting = false;
}
}
int getWidth () {
return w;
}
// if width and height haven't been set, throw tantrum
if ((w == -1) || (h == -1)) {
throw new RuntimeException("Error loading image");
}
}
int getHeight () {
return h;
}
synchronized void done() {
waiting = false;
notifyAll();
}
public synchronized boolean imageUpdate(Image img,
int infoflags,
int x,
int y,
int width,
int height) {
// check if there was an error
if (!waiting || (infoflags & ERROR) > 0 || (infoflags & ABORT) > 0) {
// we either timed out or there was an error.
notifyAll ();
return false;
}
if ((infoflags & WIDTH) > 0 || (infoflags & HEIGHT) > 0) {
if ((infoflags & WIDTH) > 0)
w = width;
if ((infoflags & HEIGHT) > 0)
h = height;
if (w > -1 && h > -1 && firstFrameLoaded) {
notifyAll ();
return false;
}
}
if ((infoflags & ALLBITS) > 0 || (infoflags & FRAMEBITS) > 0) {
firstFrameLoaded = true;
notifyAll ();
return false;
}
return true;
}
int getWidth() {
return w;
}
int getHeight() {
return h;
}
public synchronized boolean imageUpdate(Image img, int infoflags, int x, int y,
int width, int height) {
// check if there was an error
if (!waiting || ((infoflags & ERROR) > 0) || ((infoflags & ABORT) > 0)) {
// we either timed out or there was an error.
notifyAll();
return false;
}
if (((infoflags & WIDTH) > 0) || ((infoflags & HEIGHT) > 0)) {
if ((infoflags & WIDTH) > 0) {
w = width;
}
if ((infoflags & HEIGHT) > 0) {
h = height;
}
if ((w > -1) && (h > -1) && firstFrameLoaded) {
notifyAll();
return false;
}
}
if (((infoflags & ALLBITS) > 0) || ((infoflags & FRAMEBITS) > 0)) {
firstFrameLoaded = true;
notifyAll();
return false;
}
return true;
}
}
}

View file

@ -1,247 +1,396 @@
// 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;
import java.awt.*;
import java.awt.image.*;
import java.util.*;
import java.io.*;
import java.rmi.*;
import java.rmi.server.*;
import java.io.*;
import java.util.*;
/**
/**
* Abstract base class for Image Wrappers.
*/
public abstract class ImageWrapper {
Image img;
Graphics g;
int width, height;
int fontstyle, fontsize;
int width;
int height;
int fontstyle;
int fontsize;
String fontname;
ImageGenerator imggen;
public ImageWrapper (Image img, Graphics g, int width, int height, ImageGenerator imggen) {
this.img = img;
this.g = g;
this.width = width;
this.height = height;
this.imggen = imggen;
if (g != null) {
Font f = g.getFont ();
fontname = f.getName ();
fontstyle = f.getStyle ();
fontsize = f.getSize ();
}
/**
* 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.g = g;
this.width = width;
this.height = height;
this.imggen = imggen;
if (g != null) {
Font f = g.getFont();
fontname = f.getName();
fontstyle = f.getStyle();
fontsize = f.getSize();
}
}
/**
* image manipulation methods
*/
public void setFont (String name, int style, int size) {
this.fontname = name;
this.fontstyle = style;
this.fontsize = size;
g.setFont (new Font (name, style, size));
}
public void setColor (int red, int green, int blue) {
g.setColor (new Color (red, green, blue));
}
public void setColor (int color) {
g.setColor (new Color (color));
*/
public void setFont(String name, int style, int size) {
this.fontname = name;
this.fontstyle = style;
this.fontsize = size;
g.setFont(new Font(name, style, size));
}
public void drawString (String str, int x, int y) {
g.drawString (str, x, y);
/**
*
*
* @param red ...
* @param green ...
* @param blue ...
*/
public void setColor(int red, int green, int blue) {
g.setColor(new Color(red, green, blue));
}
public void drawLine (int x1, int y1, int x2, int y2) {
g.drawLine (x1, y1, x2, y2);
/**
*
*
* @param color ...
*/
public void setColor(int color) {
g.setColor(new Color(color));
}
public void drawRect (int x, int y, int w, int h) {
g.drawRect (x, y, w, h);
}
public void drawImage (String filename, int x, int y) {
try {
Image i = imggen.createImage (filename);
g.drawImage (i, x, y, null);
} catch (Exception ignore) {}
/**
*
*
* @param str ...
* @param x ...
* @param y ...
*/
public void drawString(String str, int x, int y) {
g.drawString(str, x, y);
}
public void fillRect (int x, int y, int w, int h) {
g.fillRect (x, y, w, h);
/**
*
*
* @param x1 ...
* @param y1 ...
* @param x2 ...
* @param y2 ...
*/
public void drawLine(int x1, int y1, int x2, int y2) {
g.drawLine(x1, y1, x2, y2);
}
public int getWidth () {
return width;
/**
*
*
* @param x ...
* @param y ...
* @param w ...
* @param h ...
*/
public void drawRect(int x, int y, int w, int h) {
g.drawRect(x, y, w, h);
}
public int getHeight () {
return height;
/**
*
*
* @param filename ...
* @param x ...
* @param y ...
*/
public void drawImage(String filename, int x, int y) {
try {
Image i = imggen.createImage(filename);
g.drawImage(i, x, y, null);
} catch (Exception ignore) {
}
}
public void crop (int x, int y, int w, int h) {
ImageFilter filter = new CropImageFilter (x, y, w, h);
img = Toolkit.getDefaultToolkit ().createImage(new FilteredImageSource(img.getSource(), filter));
/**
*
*
* @param x ...
* @param y ...
* @param w ...
* @param h ...
*/
public void fillRect(int x, int y, int w, int h) {
g.fillRect(x, y, w, h);
}
public void resize (int w, int h) {
img = img.getScaledInstance (w, h, Image.SCALE_SMOOTH);
width = w;
height = h;
}
public void resizeFast (int w, int h) {
img = img.getScaledInstance (w, h, Image.SCALE_FAST);
width = w;
height = h;
/**
*
*
* @return ...
*/
public int getWidth() {
return width;
}
public abstract void reduceColors (int colors);
/**
*
*
* @return ...
*/
public int getHeight() {
return height;
}
public abstract void saveAs (String filename);
/**
*
*
* @param x ...
* @param y ...
* @param w ...
* @param h ...
*/
public void crop(int x, int y, int w, int h) {
ImageFilter filter = new CropImageFilter(x, y, w, h);
img = Toolkit.getDefaultToolkit().createImage(new FilteredImageSource(img.getSource(),
filter));
}
/**
*
*
* @param w ...
* @param h ...
*/
public void resize(int w, int h) {
img = img.getScaledInstance(w, h, Image.SCALE_SMOOTH);
width = w;
height = h;
}
/**
*
*
* @param w ...
* @param h ...
*/
public void resizeFast(int w, int h) {
img = img.getScaledInstance(w, h, Image.SCALE_FAST);
width = w;
height = h;
}
/**
*
*
* @param colors ...
*/
public abstract void reduceColors(int colors);
/**
*
*
* @param filename ...
*/
public abstract void saveAs(String filename);
/**
* Get ImageProducer of the wrapped image
*/
public ImageProducer getSource () {
return img.getSource ();
public ImageProducer getSource() {
return img.getSource();
}
public void fillString (String str) {
Filler filler = new Filler (0, 0, width, height);
filler.layout (str);
/**
*
*
* @param str ...
*/
public void fillString(String str) {
Filler filler = new Filler(0, 0, width, height);
filler.layout(str);
}
public void fillString (String str, int x, int y, int w, int h) {
Filler filler = new Filler (x, y, w, h);
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) {
Filler filler = new Filler(x, y, w, h);
filler.layout(str);
}
class Filler {
int x;
int y;
int w;
int h;
int addedSpace = 0;
int xLeft;
int yLeft;
int realHeight;
transient Vector lines;
int x, y, w, h;
int addedSpace = 0;
int xLeft, yLeft;
int realHeight;
transient Vector lines;
public Filler (int x, int y, int w, int h) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
public Filler(int x, int y, int w, int h) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
}
public void layout(String str) {
int size = fontsize;
lines = new Vector();
while (!splitMessage(str, size) && (size > 10)) {
lines.setSize(0);
size = Math.max(2, size - 1);
}
Font oldfont = g.getFont();
g.setFont(new Font(fontname, fontstyle, size));
int l = lines.size();
for (int i = 0; i < l; i++) {
((Line) lines.elementAt(i)).paint(g, xLeft / 2, (yLeft / 2) + y);
}
g.setFont(oldfont);
}
private boolean splitMessage(String string, int size) {
Font font = new Font(fontname, fontstyle, size);
FontMetrics metrics = Toolkit.getDefaultToolkit().getFontMetrics(font);
int longestLine = 0;
int heightSoFar = 0;
int heightIncrement = (int) (0.84f * metrics.getHeight());
StringTokenizer tk = new StringTokenizer(string);
StringBuffer buffer = new StringBuffer();
int spaceWidth = metrics.stringWidth(" ");
int currentLine = 0;
int currentWidth = 0;
int maxWidth = w - 2;
int maxHeight = (h + addedSpace) - 2;
while (tk.hasMoreTokens()) {
String nextToken = tk.nextToken();
int nextWidth = metrics.stringWidth(nextToken);
if ((((currentWidth + nextWidth) >= maxWidth) && (currentWidth != 0))) {
Line line = new Line(buffer.toString(), x, heightSoFar, metrics);
lines.addElement(line);
if (line.textwidth > longestLine) {
longestLine = line.textwidth;
}
buffer = new StringBuffer();
currentWidth = 0;
heightSoFar += heightIncrement;
}
buffer.append(nextToken);
buffer.append(" ");
currentWidth += (nextWidth + spaceWidth);
if (((1.18 * heightSoFar) > maxHeight) && (fontsize > 10)) {
return false;
}
}
if (!"".equals(buffer.toString().trim())) {
Line line = new Line(buffer.toString(), x, heightSoFar, metrics);
lines.addElement(line);
if (line.textwidth > longestLine) {
longestLine = line.textwidth;
}
if ((longestLine > maxWidth) && (fontsize > 10)) {
return false;
}
heightSoFar += heightIncrement;
}
xLeft = w - longestLine;
yLeft = (addedSpace + h) - heightSoFar;
realHeight = heightSoFar;
return ((1.18 * heightSoFar) <= maxHeight);
}
}
public void layout (String str) {
int size = fontsize;
lines = new Vector ();
while (!splitMessage (str, size) && size > 10) {
lines.setSize (0);
size = Math.max (2, size-1);
}
Font oldfont = g.getFont ();
g.setFont (new Font (fontname, fontstyle, size));
int l = lines.size();
for (int i = 0; i < l; i++) {
((Line) lines.elementAt (i)).paint (g, xLeft/2, yLeft/2 + y);
}
g.setFont (oldfont);
}
private boolean splitMessage (String string, int size) {
Font font = new Font (fontname, fontstyle, size);
FontMetrics metrics = Toolkit.getDefaultToolkit ().getFontMetrics (font);
int longestLine = 0;
int heightSoFar = 0;
int heightIncrement = (int) (0.84f * metrics.getHeight ());
StringTokenizer tk = new StringTokenizer (string);
StringBuffer buffer = new StringBuffer();
int spaceWidth = metrics.stringWidth(" ");
int currentLine = 0;
int currentWidth = 0;
int maxWidth = w - 2, maxHeight = h + addedSpace - 2;
while (tk.hasMoreTokens()) {
String nextToken = tk.nextToken();
int nextWidth = metrics.stringWidth(nextToken);
if ((currentWidth + nextWidth >= maxWidth && currentWidth != 0)) {
Line line = new Line (buffer.toString(), x, heightSoFar, metrics);
lines.addElement (line);
if (line.textwidth > longestLine)
longestLine = line.textwidth;
buffer = new StringBuffer();
currentWidth = 0;
heightSoFar += heightIncrement;
}
buffer.append (nextToken);
buffer.append (" ");
currentWidth += (nextWidth + spaceWidth);
if (1.18*heightSoFar > maxHeight && fontsize > 10)
return false;
}
if (! "".equals (buffer.toString().trim())) {
Line line = new Line (buffer.toString(), x, heightSoFar, metrics);
lines.addElement (line);
if (line.textwidth > longestLine)
longestLine = line.textwidth;
if (longestLine > maxWidth && fontsize > 10)
return false;
heightSoFar += heightIncrement;
}
xLeft = w - longestLine;
yLeft = addedSpace + h - heightSoFar;
realHeight = heightSoFar;
return (1.18*heightSoFar <= maxHeight);
}
}
class Line implements Serializable {
String text;
int xoff;
int yoff;
FontMetrics fm;
public int textwidth;
public int len;
int ascent;
String text;
int xoff, yoff;
FontMetrics fm;
public int textwidth, len;
int ascent;
public Line(String text, int xoff, int yoff, FontMetrics fm) {
this.text = text.trim();
len = text.length();
this.xoff = xoff;
this.yoff = yoff;
this.fm = fm;
textwidth = (len == 0) ? 0 : fm.stringWidth(this.text);
ascent = (int) (0.9f * fm.getAscent());
}
public void paint(Graphics g, int xadd, int yadd) {
g.drawString(text, xoff + xadd, yoff + ascent + yadd);
}
public Line (String text, int xoff, int yoff, FontMetrics fm) {
this.text = text.trim();
len = text.length();
this.xoff = xoff;
this.yoff = yoff;
this.fm = fm;
textwidth = (len == 0) ? 0 : fm.stringWidth(this.text);
ascent = (int) (0.9f * fm.getAscent());
public boolean contains(int y) {
return (y < (yoff + fm.getHeight())) ? true : false;
}
}
public void paint (Graphics g, int xadd, int yadd) {
g.drawString (text, xoff+xadd, yoff+ascent+yadd);
}
public boolean contains (int y) {
return (y < yoff+fm.getHeight()) ? true : false;
}
}
}

View file

@ -1,87 +1,121 @@
// 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;
import java.awt.*;
import java.awt.image.*;
import Acme.JPM.Encoders.GifEncoder;
import com.sun.jimi.core.*;
import com.sun.jimi.core.util.*;
import Acme.JPM.Encoders.GifEncoder;
import java.io.IOException;
import java.awt.*;
import java.awt.image.*;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* A wrapper for an image that uses the Sun version of JIMI available at
* http://java.sun.com/products/jimi.
*/
public class SunImageWrapper extends ImageWrapper {
public SunImageWrapper (Image img, Graphics g, int width, int height,
ImageGenerator imggen) {
super (img, g, width, height, imggen);
}
public void reduceColors (int colors) {
try {
int pixels[][] = getPixels();
int palette[] = Quantize.quantizeImage(pixels, colors);
int w = pixels.length;
int h = pixels[0].length;
int pix[] = new int[w * h];
// convert to RGB
for (int x = w; x-- > 0; ) {
for (int y = h; y-- > 0; ) {
pix[y * w + x] = palette[pixels[x][y]];
}
}
img = imggen.createImage (new MemoryImageSource(w, h, pix, 0, w));
} catch (Exception x) {
// throw new RuntimeException (x.getMessage ());
}
/**
* 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,
ImageGenerator imggen) {
super(img, g, width, height, imggen);
}
/**
* Snag the pixels from an image.
*
*
* @param colors ...
*/
int[][] getPixels () throws IOException {
int pix[] = new int[width * height];
PixelGrabber grabber = new PixelGrabber(img, 0, 0, width, height, pix, 0, width);
try {
if (grabber.grabPixels() != true) {
throw new IOException("Grabber returned false: " + grabber.status());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
int pixels[][] = new int[width][height];
for (int x = width; x-- > 0; ) {
for (int y = height; y-- > 0; ) {
pixels[x][y] = pix[y * width + x];
}
}
return pixels;
public void reduceColors(int colors) {
try {
int[][] pixels = getPixels();
int[] palette = Quantize.quantizeImage(pixels, colors);
int w = pixels.length;
int h = pixels[0].length;
int[] pix = new int[w * h];
// convert to RGB
for (int x = w; x-- > 0;) {
for (int y = h; y-- > 0;) {
pix[(y * w) + x] = palette[pixels[x][y]];
}
}
img = imggen.createImage(new MemoryImageSource(w, h, pix, 0, w));
} catch (Exception x) {
// throw new RuntimeException (x.getMessage ());
}
}
/**
* Snag the pixels from an image.
*/
int[][] getPixels() throws IOException {
int[] pix = new int[width * height];
PixelGrabber grabber = new PixelGrabber(img, 0, 0, width, height, pix, 0, width);
public void saveAs (String filename) {
try {
if (filename.toLowerCase().endsWith (".gif")) {
// sun's jimi package doesn't encode gifs, use Acme encoder
FileOutputStream fout = new FileOutputStream (filename);
// Acme gif encoder
GifEncoder enc = new GifEncoder (img, fout);
enc.encode ();
fout.close ();
} else {
Jimi.putImage (img, filename);
}
} catch (Exception x) {
throw new RuntimeException (x.getMessage ());
}
try {
if (grabber.grabPixels() != true) {
throw new IOException("Grabber returned false: " + grabber.status());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
int[][] pixels = new int[width][height];
for (int x = width; x-- > 0;) {
for (int y = height; y-- > 0;) {
pixels[x][y] = pix[(y * width) + x];
}
}
return pixels;
}
/**
*
*
* @param filename ...
*/
public void saveAs(String filename) {
try {
if (filename.toLowerCase().endsWith(".gif")) {
// sun's jimi package doesn't encode gifs, use Acme encoder
FileOutputStream fout = new FileOutputStream(filename);
// Acme gif encoder
GifEncoder enc = new GifEncoder(img, fout);
enc.encode();
fout.close();
} else {
Jimi.putImage(img, filename);
}
} catch (Exception x) {
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;
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.core.*;
import helma.objectmodel.*;
import helma.servlet.*;
import helma.util.SystemProperties;
import org.apache.xmlrpc.XmlRpcHandler;
import org.mortbay.http.*;
import org.mortbay.http.handler.*;
import org.mortbay.jetty.servlet.*;
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 org.apache.xmlrpc.XmlRpcHandler;
/**
* This class is responsible for starting and stopping Helma applications.
*/
public class ApplicationManager implements XmlRpcHandler {
private Hashtable applications;
private Hashtable xmlrpcHandlers;
private Properties mountpoints;
@ -37,258 +47,368 @@ public class ApplicationManager implements XmlRpcHandler {
private Server server;
private long lastModified;
public ApplicationManager (int port, File hopHome, SystemProperties props, Server server) {
this.port = port;
this.hopHome = hopHome;
this.props = props;
this.server = server;
applications = new Hashtable ();
xmlrpcHandlers = new Hashtable ();
mountpoints = new Properties ();
lastModified = 0;
/**
* 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.hopHome = hopHome;
this.props = props;
this.server = server;
applications = new Hashtable();
xmlrpcHandlers = new Hashtable();
mountpoints = new Properties();
lastModified = 0;
}
// regularely check applications property file to create and start new applications
protected void checkForChanges () {
if (props.lastModified () > lastModified) {
try {
for (Enumeration e = props.keys(); e.hasMoreElements (); ) {
String appName = (String) e.nextElement ();
if (appName.indexOf (".") == -1 && applications.get (appName) == null) {
start (appName);
register (appName);
}
}
// then stop deleted ones
for (Enumeration e = applications.keys(); e.hasMoreElements (); ) {
String appName = (String) e.nextElement ();
// check if application has been removed and should be stopped
if (!props.containsKey (appName)) {
stop (appName);
} else if (server.http != null) {
// check if application should be remounted at a
// different location on embedded web server
String oldMountpoint = mountpoints.getProperty (appName);
String mountpoint = getMountpoint (appName);
String pattern = getPathPattern (mountpoint);
if (!pattern.equals (oldMountpoint)) {
Server.getLogger().log("Moving application "+appName+" from "+oldMountpoint+" to "+pattern);
HttpContext oldContext = server.http.getContext (null, oldMountpoint);
if (oldContext != null) {
// oldContext.setContextPath(pattern);
oldContext.stop ();
oldContext.destroy ();
}
Application app = (Application) applications.get (appName);
if (!app.hasExplicitBaseURI())
app.setBaseURI (mountpoint);
ServletHttpContext context = new ServletHttpContext ();
context.setContextPath(pattern);
server.http.addContext (context);
ServletHolder holder = context.addServlet (appName, "/*", "helma.servlet.EmbeddedServletClient");
holder.setInitParameter ("application", appName);
holder.setInitParameter ("mountpoint", mountpoint);
if ("true".equalsIgnoreCase (props.getProperty (appName+".responseEncoding")))
context.addHandler(new ContentEncodingHandler());
String cookieDomain = props.getProperty (appName+".cookieDomain");
if (cookieDomain != null)
holder.setInitParameter ("cookieDomain", cookieDomain);
String uploadLimit = props.getProperty (appName+".uploadLimit");
if (uploadLimit != null)
holder.setInitParameter ("uploadLimit", uploadLimit);
// holder.start ();
context.start ();
mountpoints.setProperty (appName, pattern);
}
}
}
} catch (Exception mx) {
Server.getLogger().log ("Error checking applications: "+mx);
}
protected void checkForChanges() {
if (props.lastModified() > lastModified) {
try {
for (Enumeration e = props.keys(); e.hasMoreElements();) {
String appName = (String) e.nextElement();
lastModified = System.currentTimeMillis ();
}
if ((appName.indexOf(".") == -1) &&
(applications.get(appName) == null)) {
start(appName);
register(appName);
}
}
// then stop deleted ones
for (Enumeration e = applications.keys(); e.hasMoreElements();) {
String appName = (String) e.nextElement();
// check if application has been removed and should be stopped
if (!props.containsKey(appName)) {
stop(appName);
} else if (server.http != null) {
// check if application should be remounted at a
// different location on embedded web server
String oldMountpoint = mountpoints.getProperty(appName);
String mountpoint = getMountpoint(appName);
String pattern = getPathPattern(mountpoint);
if (!pattern.equals(oldMountpoint)) {
Server.getLogger().log("Moving application " + appName +
" from " + oldMountpoint + " to " +
pattern);
HttpContext oldContext = server.http.getContext(null,
oldMountpoint);
if (oldContext != null) {
// oldContext.setContextPath(pattern);
oldContext.stop();
oldContext.destroy();
}
Application app = (Application) applications.get(appName);
if (!app.hasExplicitBaseURI()) {
app.setBaseURI(mountpoint);
}
ServletHttpContext context = new ServletHttpContext();
context.setContextPath(pattern);
server.http.addContext(context);
ServletHolder holder = context.addServlet(appName, "/*",
"helma.servlet.EmbeddedServletClient");
holder.setInitParameter("application", appName);
holder.setInitParameter("mountpoint", mountpoint);
if ("true".equalsIgnoreCase(props.getProperty(appName +
".responseEncoding"))) {
context.addHandler(new ContentEncodingHandler());
}
String cookieDomain = props.getProperty(appName +
".cookieDomain");
if (cookieDomain != null) {
holder.setInitParameter("cookieDomain", cookieDomain);
}
String uploadLimit = props.getProperty(appName +
".uploadLimit");
if (uploadLimit != null) {
holder.setInitParameter("uploadLimit", uploadLimit);
}
// holder.start ();
context.start();
mountpoints.setProperty(appName, pattern);
}
}
}
} catch (Exception mx) {
Server.getLogger().log("Error checking applications: " + mx);
}
lastModified = System.currentTimeMillis();
}
}
void start (String appName) {
Server.getLogger().log ("Building application "+appName);
try {
// check if application and db dirs are set, otherwise go with
// the defaults, passing null dirs to the constructor.
String appDirName = props.getProperty (appName+".appdir");
File appDir = appDirName == null ? null : new File (appDirName);
String dbDirName = props.getProperty (appName+".dbdir");
File dbDir = dbDirName == null ? null : new File (dbDirName);
// create the application instance
Application app = new Application (appName, server, appDir, dbDir);
applications.put (appName, app);
// the application is started later in the register method, when it's bound
app.init ();
} catch (Exception x) {
Server.getLogger().log ("Error creating application "+appName+": "+x);
x.printStackTrace ();
}
void start(String appName) {
Server.getLogger().log("Building application " + appName);
try {
// check if application and db dirs are set, otherwise go with
// the defaults, passing null dirs to the constructor.
String appDirName = props.getProperty(appName + ".appdir");
File appDir = (appDirName == null) ? null : new File(appDirName);
String dbDirName = props.getProperty(appName + ".dbdir");
File dbDir = (dbDirName == null) ? null : new File(dbDirName);
// create the application instance
Application app = new Application(appName, server, appDir, dbDir);
applications.put(appName, app);
// the application is started later in the register method, when it's bound
app.init();
} catch (Exception x) {
Server.getLogger().log("Error creating application " + appName + ": " + x);
x.printStackTrace();
}
}
void stop (String appName) {
Server.getLogger().log ("Stopping application "+appName);
try {
Application app = (Application) applications.get (appName);
// unbind from RMI server
if (port > 0) {
Naming.unbind ("//:"+port+"/"+appName);
}
// unbind from Jetty HTTP server
if (server.http != null) {
String mountpoint = mountpoints.getProperty (appName);
HttpContext context = server.http.getContext (null, mountpoint);
if (context != null) {
context.stop ();
context.destroy ();
}
}
// unregister as XML-RPC handler
xmlrpcHandlers.remove (app.getXmlRpcHandlerName());
app.stop ();
Server.getLogger().log ("Unregistered application "+appName);
} catch (Exception x) {
Server.getLogger().log ("Couldn't unregister app: "+x);
}
applications.remove (appName);
void stop(String appName) {
Server.getLogger().log("Stopping application " + appName);
try {
Application app = (Application) applications.get(appName);
// unbind from RMI server
if (port > 0) {
Naming.unbind("//:" + port + "/" + appName);
}
// unbind from Jetty HTTP server
if (server.http != null) {
String mountpoint = mountpoints.getProperty(appName);
HttpContext context = server.http.getContext(null, mountpoint);
if (context != null) {
context.stop();
context.destroy();
}
}
// unregister as XML-RPC handler
xmlrpcHandlers.remove(app.getXmlRpcHandlerName());
app.stop();
Server.getLogger().log("Unregistered application " + appName);
} catch (Exception x) {
Server.getLogger().log("Couldn't unregister app: " + x);
}
applications.remove(appName);
}
void register (String appName) {
try {
Server.getLogger().log ("Binding application "+appName);
Application app = (Application) applications.get (appName);
// bind to RMI server
if (port > 0) {
Naming.rebind ("//:"+port+"/"+appName, new RemoteApplication (app));
}
// bind to Jetty HTTP server
if (server.http != null) {
String mountpoint = getMountpoint (appName);
// if using embedded webserver (not AJP) set application URL prefix
if (!app.hasExplicitBaseURI ())
app.setBaseURI (mountpoint);
String pattern = getPathPattern (mountpoint);
ServletHttpContext context = new ServletHttpContext ();
context.setContextPath(pattern);
server.http.addContext (context);
ServletHolder holder = context.addServlet (appName, "/*", "helma.servlet.EmbeddedServletClient");
holder.setInitParameter ("application", appName);
holder.setInitParameter ("mountpoint", mountpoint);
if ("true".equalsIgnoreCase (props.getProperty (appName+".responseEncoding")))
context.addHandler(new ContentEncodingHandler());
String cookieDomain = props.getProperty (appName+".cookieDomain");
if (cookieDomain != null)
holder.setInitParameter ("cookieDomain", cookieDomain);
String uploadLimit = props.getProperty (appName+".uploadLimit");
if (uploadLimit != null)
holder.setInitParameter ("uploadLimit", uploadLimit);
String debug = props.getProperty (appName+".debug");
if (debug != null)
holder.setInitParameter ("debug", debug);
// holder.start ();
context.start ();
mountpoints.setProperty (appName, pattern);
}
// register as XML-RPC handler
xmlrpcHandlers.put (app.getXmlRpcHandlerName(), app);
app.start ();
} catch (Exception x) {
Server.getLogger().log ("Couldn't register and start app: "+x);
x.printStackTrace ();
}
void register(String appName) {
try {
Server.getLogger().log("Binding application " + appName);
Application app = (Application) applications.get(appName);
// bind to RMI server
if (port > 0) {
Naming.rebind("//:" + port + "/" + appName, new RemoteApplication(app));
}
// bind to Jetty HTTP server
if (server.http != null) {
String mountpoint = getMountpoint(appName);
// if using embedded webserver (not AJP) set application URL prefix
if (!app.hasExplicitBaseURI()) {
app.setBaseURI(mountpoint);
}
String pattern = getPathPattern(mountpoint);
ServletHttpContext context = new ServletHttpContext();
context.setContextPath(pattern);
server.http.addContext(context);
ServletHolder holder = context.addServlet(appName, "/*",
"helma.servlet.EmbeddedServletClient");
holder.setInitParameter("application", appName);
holder.setInitParameter("mountpoint", mountpoint);
if ("true".equalsIgnoreCase(props.getProperty(appName +
".responseEncoding"))) {
context.addHandler(new ContentEncodingHandler());
}
String cookieDomain = props.getProperty(appName + ".cookieDomain");
if (cookieDomain != null) {
holder.setInitParameter("cookieDomain", cookieDomain);
}
String uploadLimit = props.getProperty(appName + ".uploadLimit");
if (uploadLimit != null) {
holder.setInitParameter("uploadLimit", uploadLimit);
}
String debug = props.getProperty(appName + ".debug");
if (debug != null) {
holder.setInitParameter("debug", debug);
}
// holder.start ();
context.start();
mountpoints.setProperty(appName, pattern);
}
// register as XML-RPC handler
xmlrpcHandlers.put(app.getXmlRpcHandlerName(), app);
app.start();
} catch (Exception x) {
Server.getLogger().log("Couldn't register and start app: " + x);
x.printStackTrace();
}
}
public void startAll () {
try {
for (Enumeration e = props.keys(); e.hasMoreElements (); ) {
String appName = (String) e.nextElement ();
if (appName.indexOf (".") == -1)
start (appName);
}
for (Enumeration e = props.keys(); e.hasMoreElements (); ) {
String appName = (String) e.nextElement ();
if (appName.indexOf (".") == -1)
register (appName);
}
if (server.http != null) {
// add handler for static files.
File staticContent = new File (server.getHopHome(), "static");
Server.getLogger().log("Serving static content from "+staticContent.getAbsolutePath());
HttpContext context = server.http.addContext ("/static/*");
context.setResourceBase (staticContent.getAbsolutePath());
ResourceHandler handler = new ResourceHandler();
context.addHandler(handler);
context.start ();
}
lastModified = System.currentTimeMillis ();
} catch (Exception mx) {
Server.getLogger().log ("Error starting applications: "+mx);
mx.printStackTrace ();
}
/**
*
*/
public void startAll() {
try {
for (Enumeration e = props.keys(); e.hasMoreElements();) {
String appName = (String) e.nextElement();
if (appName.indexOf(".") == -1) {
start(appName);
}
}
for (Enumeration e = props.keys(); e.hasMoreElements();) {
String appName = (String) e.nextElement();
if (appName.indexOf(".") == -1) {
register(appName);
}
}
if (server.http != null) {
// add handler for static files.
File staticContent = new File(server.getHopHome(), "static");
Server.getLogger().log("Serving static content from " +
staticContent.getAbsolutePath());
HttpContext context = server.http.addContext("/static/*");
context.setResourceBase(staticContent.getAbsolutePath());
ResourceHandler handler = new ResourceHandler();
context.addHandler(handler);
context.start();
}
lastModified = System.currentTimeMillis();
} catch (Exception mx) {
Server.getLogger().log("Error starting applications: " + mx);
mx.printStackTrace();
}
}
public void stopAll () {
for (Enumeration en=applications.keys(); en.hasMoreElements(); ) {
String appName = (String) en.nextElement();
stop (appName);
}
/**
*
*/
public void stopAll() {
for (Enumeration en = applications.keys(); en.hasMoreElements();) {
String appName = (String) en.nextElement();
stop(appName);
}
}
/**
* Get an array containing all currently running applications.
*/
public Object[] getApplications () {
return applications.values ().toArray ();
public Object[] getApplications() {
return applications.values().toArray();
}
/**
* Get an application by name.
*/
public Application getApplication(String name) {
return (Application)applications.get(name);
* Get an application by name.
*/
public Application getApplication(String name) {
return (Application) applications.get(name);
}
/**
* Implements org.apache.xmlrpc.XmlRpcHandler.execute()
*/
public Object execute (String method, Vector params) throws Exception {
int dot = method.indexOf (".");
if (dot == -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");
String handler = method.substring (0, dot);
String method2 = method.substring (dot+1);
Application app = (Application) xmlrpcHandlers.get (handler);
if (app == null)
throw new Exception ("Handler \""+handler+"\" not found for "+method);
return app.executeXmlRpc (method2, params);
public Object execute(String method, Vector params)
throws Exception {
int dot = method.indexOf(".");
if (dot == -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");
}
String handler = method.substring(0, dot);
String method2 = method.substring(dot + 1);
Application app = (Application) xmlrpcHandlers.get(handler);
if (app == null) {
throw new Exception("Handler \"" + handler + "\" not found for " + method);
}
return app.executeXmlRpc(method2, params);
}
private String getMountpoint(String appName) {
String mountpoint = props.getProperty(appName + ".mountpoint");
private String getMountpoint (String appName) {
String mountpoint = props.getProperty (appName+".mountpoint");
if (mountpoint == null)
return "/"+URLEncoder.encode(appName);
mountpoint = mountpoint.trim ();
if ("".equals (mountpoint))
return "/";
else if (!mountpoint.startsWith ("/"))
return "/"+mountpoint;
return mountpoint;
if (mountpoint == null) {
return "/" + URLEncoder.encode(appName);
}
mountpoint = mountpoint.trim();
if ("".equals(mountpoint)) {
return "/";
} else if (!mountpoint.startsWith("/")) {
return "/" + mountpoint;
}
return mountpoint;
}
private String getPathPattern (String mountpoint) {
if ("/".equals (mountpoint))
return "/";
if (!mountpoint.endsWith ("/"))
return mountpoint+"/*";
return mountpoint+"*";
}
private String getPathPattern(String mountpoint) {
if ("/".equals(mountpoint)) {
return "/";
}
if (!mountpoint.endsWith("/")) {
return mountpoint + "/*";
}
return mountpoint + "*";
}
}

View file

@ -1,94 +1,327 @@
// 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;
import java.security.Permission;
import helma.framework.core.AppClassLoader;
import java.io.FileDescriptor;
import java.net.InetAddress;
import java.security.Permission;
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
* is not allowed to exit the VM and set a security manager.
*
* This class can be subclassed to implement actual security policies. It contains
* a utility method <code>getApplication</code> that can be used to determine
* a utility method <code>getApplication</code> that can be used to determine
* the name of the application trying to execute the action in question, if any.
*/
public class HelmaSecurityManager extends SecurityManager {
// The set of actions forbidden to application code.
// We are pretty permissive, forbidding only System.exit()
// and setting the security manager.
private final static HashSet forbidden = new HashSet ();
private final static HashSet forbidden = new HashSet();
static {
forbidden.add ("exitVM");
forbidden.add ("setSecurityManager");
forbidden.add("exitVM");
forbidden.add("setSecurityManager");
}
/**
*
*
* @param p ...
*/
public void checkPermission(Permission p) {
if (p instanceof RuntimePermission) {
if (forbidden.contains (p.getName())) {
Class[] classes = getClassContext();
for (int i=0; i<classes.length; i++) {
if (classes[i].getClassLoader() instanceof AppClassLoader)
throw new SecurityException (p.getName()+" not allowed for application code");
}
}
}
if (p instanceof RuntimePermission) {
if (forbidden.contains(p.getName())) {
Class[] classes = getClassContext();
for (int i = 0; i < classes.length; i++) {
if (classes[i].getClassLoader() instanceof AppClassLoader) {
throw new SecurityException(p.getName() +
" not allowed for application code");
}
}
}
}
}
/**
*
*
* @param p ...
* @param context ...
*/
public void checkPermission(Permission p, Object context) {
}
public void checkCreateClassLoader() {}
public void checkAccess(Thread thread) {}
public void checkAccess(ThreadGroup group) {}
public void checkExit(int status) {
Class[] classes = getClassContext();
for (int i=0; i<classes.length; i++) {
if (classes[i].getClassLoader() instanceof AppClassLoader)
throw new SecurityException ("operation not allowed for application code");
}
/**
*
*/
public void checkCreateClassLoader() {
}
/**
*
*
* @param thread ...
*/
public void checkAccess(Thread thread) {
}
/**
*
*
* @param group ...
*/
public void checkAccess(ThreadGroup group) {
}
/**
*
*
* @param status ...
*/
public void checkExit(int status) {
Class[] classes = getClassContext();
for (int i = 0; i < classes.length; i++) {
if (classes[i].getClassLoader() instanceof AppClassLoader) {
throw new SecurityException("operation not allowed for application code");
}
}
}
/**
*
*
* @param cmd ...
*/
public void checkExec(String cmd) {
}
/**
*
*
* @param lib ...
*/
public void checkLink(String lib) {
}
/**
*
*
* @param fdesc ...
*/
public void checkRead(FileDescriptor fdesc) {
}
/**
*
*
* @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) {
}
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) {}
public void checkWrite(String file) {}
public void checkDelete(String file) {}
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) {}
public void checkPropertiesAccess() {}
public void checkPropertyAccess(String key) {}
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) {}
public void checkSetFactory() {}
public void checkMemberAccess(Class clazz, int which) {}
public void checkSecurityAccess(String target) {}
/**
* Utility method that returns the name of the application trying
* to execute the code in question. Returns null if the current code
* to execute the code in question. Returns null if the current code
* does not belong to any application.
*/
protected String getApplication () {
Class[] classes = getClassContext();
for (int i=0; i<classes.length; i++) {
if (classes[i].getClassLoader() instanceof AppClassLoader)
return ((AppClassLoader) classes[i].getClassLoader()).getAppName ();
}
// no application class loader found in stack - return null
return null;
}
protected String getApplication() {
Class[] classes = getClassContext();
for (int i = 0; i < classes.length; i++) {
if (classes[i].getClassLoader() instanceof AppClassLoader) {
return ((AppClassLoader) classes[i].getClassLoader()).getAppName();
}
}
// no application class loader found in stack - 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;
import helma.util.Logger;
@ -8,23 +23,35 @@ import java.util.List;
* ShutdownHook that shuts down all running Helma applications on exit.
*/
public class HelmaShutdownHook extends Thread {
ApplicationManager appmgr;
public HelmaShutdownHook (ApplicationManager appmgr) {
this.appmgr = appmgr;
/**
* Creates a new HelmaShutdownHook object.
*
* @param appmgr ...
*/
public HelmaShutdownHook(ApplicationManager appmgr) {
this.appmgr = appmgr;
}
public void run () {
Logger logger = Server.getLogger();
if (logger != null)
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();
}
/**
*
*/
public void run() {
Logger logger = Server.getLogger();
if (logger != null) {
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();
}
}

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;
import helma.util.*;
import java.io.IOException;
import java.net.*;
import java.rmi.server.*;
import java.io.IOException;
/**
* An RMI socket factory that has a "paranoid" option to filter clients.
* We only do direct connections, no HTTP proxy stuff, since this is
* server-to-server.
*/
public class HelmaSocketFactory extends RMISocketFactory {
private InetAddressFilter filter;
public HelmaSocketFactory () {
filter = new InetAddressFilter ();
/**
* Creates a new HelmaSocketFactory object.
*/
public HelmaSocketFactory() {
filter = new InetAddressFilter();
}
public void addAddress (String address) {
try {
filter.addAddress (address);
} catch (IOException x) {
Server.getLogger().log ("Could not add "+address+" to Socket Filter: invalid address.");
}
/**
*
*
* @param address ...
*/
public void addAddress(String address) {
try {
filter.addAddress(address);
} catch (IOException x) {
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 {
return new Socket (host, port);
return new Socket(host, port);
}
/**
*
*
* @param port ...
*
* @return ...
*
* @throws IOException ...
*/
public ServerSocket createServerSocket(int port) throws IOException {
return new ParanoidServerSocket (port, filter);
return new ParanoidServerSocket(port, filter);
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,36 +1,51 @@
// 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;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Hashtable;
import java.security.CodeSource;
import java.security.PermissionCollection;
import java.security.Permissions;
import java.security.Policy;
import java.security.CodeSource;
import java.util.Hashtable;
/**
* ClassLoader that is able to exclude certain packages from loading.
*/
public class FilteredClassLoader extends URLClassLoader {
/**
* 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
* class loaders so that special security policies can be applied to them and
* so that they can load classes from jar files in the app directories.
*/
/**
* 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
* class loaders so that special security policies can be applied to them and
* so that they can load classes from jar files in the app directories.
*/
public FilteredClassLoader(URL[] urls) {
super (urls);
super(urls);
}
/**
* Mask classes that implement the scripting engine(s) contained in helma.jar
*/
protected Class findClass (String name) throws ClassNotFoundException {
if (name != null && "helma.scripting.fesi.PhantomEngine".equals (name))
throw new ClassNotFoundException (name);
return super.findClass (name);
protected Class findClass(String name) throws ClassNotFoundException {
if ((name != null) && "helma.scripting.fesi.PhantomEngine".equals(name)) {
throw new ClassNotFoundException(name);
}
return super.findClass(name);
}
}

View file

@ -1,114 +1,145 @@
// 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;
import java.net.URLClassLoader;
import java.net.URL;
import java.net.URLDecoder;
import java.io.File;
import java.io.FilenameFilter;
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.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.
*/
public class Main {
public static final String[] jars = {
"helma.jar",
"jetty.jar",
"crimson.jar",
"xmlrpc.jar",
"servlet.jar",
"regexp.jar",
"mail.jar",
"activation.jar",
"netcomponents.jar",
"jimi.jar",
"apache-dom.jar",
"jdom.jar"
};
"helma.jar", "jetty.jar", "crimson.jar",
"xmlrpc.jar", "servlet.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 {
// 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
// has been loaded from.
String installDir = null;
public static void main (String[] args) throws Exception {
// first, try to get helma home dir from command line options
for (int i = 0; i < args.length; i++) {
if (args[i].equals("-i") && ((i + 1) < args.length)) {
installDir = args[i + 1];
}
}
// 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
// has been loaded from.
String installDir = null;
// first, try to get helma home dir from command line options
for (int i=0; i<args.length; i++) {
if (args[i].equals ("-i") && i+1<args.length) {
installDir = args[i+1];
}
}
URLClassLoader apploader = (URLClassLoader) ClassLoader.getSystemClassLoader();
// try to get Helma installation directory
if (installDir == null) {
try {
URL launcherUrl = apploader.findResource("helma/main/launcher/Main.class");
// this is a JAR URL of the form
// jar:<url>!/{entry}
// we strip away the jar: prefix and the !/{entry} suffix
// to get the original jar file URL
installDir = launcherUrl.toString().substring(4);
int excl = installDir.indexOf ("!");
if (excl > -1) {
installDir = installDir.substring(0, excl);
launcherUrl = new URL (installDir);
File f = new File (launcherUrl.getPath());
installDir = f.getParentFile().getCanonicalPath();
}
} catch (Exception x) {
// unable to get Helma installation dir from launcher jar
System.err.println ("Unable to get Helma installation directory: "+x);
System.exit (2);
}
}
URLClassLoader apploader = (URLClassLoader) ClassLoader.getSystemClassLoader();
// decode installDir in case it is URL-encoded
installDir = URLDecoder.decode (installDir);
// try to get Helma installation directory
if (installDir == null) {
try {
URL launcherUrl = apploader.findResource("helma/main/launcher/Main.class");
// set up the class path
File libdir = new File (installDir, "lib");
ArrayList jarlist = new ArrayList ();
for (int i=0;i<jars.length;i++) {
File jar = new File (libdir, jars[i]);
jarlist.add (new URL ("file:" + jar.getAbsolutePath()));
}
// add all jar files from the lib/ext directory
File extdir =new File (libdir, "ext");
File[] files = extdir.listFiles (new FilenameFilter() {
public boolean accept (File dir, String name) {
String n = name.toLowerCase();
return n.endsWith (".jar") || n.endsWith (".zip");
}
});
if (files != null)
for (int i=0;i<files.length; i++) {
// WORKAROUND: add the files in lib/ext before
// lib/apache-dom.jar, since otherwise putting a full version
// of Xerces in lib/ext would cause a version conflict with the
// xerces classes in lib/apache-dom.jar. Generally, having some pieces
// of Xerces in lib/apache-dom.jar is kind of problematic.
jarlist.add (jars.length-3, new URL ("file:" + files[i].getAbsolutePath()));
System.err.println ("Adding to classpath: "+files[i].getAbsolutePath());
}
URL[] urls = new URL[jarlist.size()];
jarlist.toArray (urls);
FilteredClassLoader loader = new FilteredClassLoader (urls);
// set the new class loader as context class loader
Thread.currentThread().setContextClassLoader (loader);
// get the main server class
Class clazz = loader.loadClass ("helma.main.Server");
Class[] cargs = new Class[] { args.getClass() };
Method main = clazz.getMethod ("main", cargs);
Object[] nargs = new Object[] { args };
// run
main.invoke (null, nargs);
// this is a JAR URL of the form
// jar:<url>!/{entry}
// we strip away the jar: prefix and the !/{entry} suffix
// to get the original jar file URL
installDir = launcherUrl.toString().substring(4);
int excl = installDir.indexOf("!");
if (excl > -1) {
installDir = installDir.substring(0, excl);
launcherUrl = new URL(installDir);
File f = new File(launcherUrl.getPath());
installDir = f.getParentFile().getCanonicalPath();
}
} catch (Exception x) {
// unable to get Helma installation dir from launcher jar
System.err.println("Unable to get Helma installation directory: " + x);
System.exit(2);
}
}
// decode installDir in case it is URL-encoded
installDir = URLDecoder.decode(installDir);
// set up the class path
File libdir = new File(installDir, "lib");
ArrayList jarlist = new ArrayList();
for (int i = 0; i < jars.length; i++) {
File jar = new File(libdir, jars[i]);
jarlist.add(new URL("file:" + jar.getAbsolutePath()));
}
// add all jar files from the lib/ext directory
File extdir = new File(libdir, "ext");
File[] files = extdir.listFiles(new FilenameFilter() {
public boolean accept(File dir, String name) {
String n = name.toLowerCase();
return n.endsWith(".jar") || n.endsWith(".zip");
}
});
if (files != null) {
for (int i = 0; i < files.length; i++) {
// WORKAROUND: add the files in lib/ext before
// lib/apache-dom.jar, since otherwise putting a full version
// of Xerces in lib/ext would cause a version conflict with the
// xerces classes in lib/apache-dom.jar. Generally, having some pieces
// of Xerces in lib/apache-dom.jar is kind of problematic.
jarlist.add(jars.length - 3, new URL("file:" +
files[i].getAbsolutePath()));
System.err.println("Adding to classpath: " + files[i].getAbsolutePath());
}
}
URL[] urls = new URL[jarlist.size()];
jarlist.toArray(urls);
FilteredClassLoader loader = new FilteredClassLoader(urls);
// set the new class loader as context class loader
Thread.currentThread().setContextClassLoader(loader);
// get the main server class
Class clazz = loader.loadClass("helma.main.Server");
Class[] cargs = new Class[] { args.getClass() };
Method main = clazz.getMethod("main", cargs);
Object[] nargs = new Object[] { args };
// run
main.invoke(null, nargs);
}
}

View file

@ -1,51 +1,33 @@
// 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;
/**
* 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.
* 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.
*/
public class ConcurrencyException extends RuntimeException {
public ConcurrencyException (String msg) {
super (msg);
/**
* Creates a new ConcurrencyException object.
*
* @param msg ...
*/
public ConcurrencyException(String msg) {
super(msg);
}
}

View file

@ -1,49 +1,32 @@
// 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;
/**
* Thrown on any kind of Database-Error
*/
public class DatabaseException extends RuntimeException {
public DatabaseException (String msg) {
super (msg);
/**
* Creates a new DatabaseException object.
*
* @param msg ...
*/
public DatabaseException(String msg) {
super(msg);
}
}

View file

@ -1,35 +1,108 @@
// 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;
import helma.objectmodel.db.IDGenerator;
import helma.objectmodel.INode;
import helma.objectmodel.db.IDGenerator;
import java.io.IOException;
import org.xml.sax.SAXException;
import javax.xml.parsers.ParserConfigurationException;
/**
* Interface that is implemented by Database wrappers
*/
public interface IDatabase {
// db-related
public void shutdown();
// db-related
public void shutdown ();
// id-related
public String nextID() throws ObjectNotFoundException;
// id-related
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 IOException ...
*/
public IDGenerator getIDGenerator(ITransaction transaction)
throws IOException, ObjectNotFoundException;
// node-related
public INode getNode (ITransaction transaction, String key) throws Exception;
public void saveNode (ITransaction transaction, String key, INode node) throws Exception;
public void deleteNode (ITransaction transaction, String key) throws Exception;
/**
*
*
* @param transaction ...
* @param idgen ...
*
* @throws IOException ...
*/
public void saveIDGenerator(ITransaction transaction, IDGenerator idgen)
throws IOException;
// transaction-related
public ITransaction beginTransaction ();
public void commitTransaction (ITransaction transaction) throws DatabaseException;
public void abortTransaction (ITransaction transaction) throws DatabaseException;
// node-related
public INode getNode(ITransaction transaction, String key)
throws IOException, ObjectNotFoundException,
SAXException, ParserConfigurationException;
/**
*
*
* @param transaction ...
* @param key ...
* @param node ...
*
* @throws IOException ...
*/
public void saveNode(ITransaction transaction, String key, INode node)
throws IOException;
/**
*
*
* @param transaction ...
* @param key ...
*
* @throws IOException ...
*/
public void deleteNode(ITransaction transaction, String key)
throws IOException;
// transaction-related
public ITransaction beginTransaction();
/**
*
*
* @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;
import java.util.*;
import java.io.*;
import helma.framework.IPathElement;
import helma.objectmodel.db.DbMapping;
import java.io.*;
import java.util.*;
/**
* Interface that all Nodes implement. Currently, there are two implementations:
* 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).
*/
public interface INode extends INodeState, IPathElement {
/**
/**
* id-related methods
*/
public String getID();
public String getID ();
public String getName ();
public void setDbMapping (DbMapping dbmap);
public DbMapping getDbMapping ();
public int getState ();
public void setState (int s);
public void setName (String name);
public long lastModified ();
public long created ();
public boolean isAnonymous (); // is this a named node, or an anonymous node in a collection?
public String getPrototype ();
public void setPrototype (String prototype);
public INode getCacheNode ();
public void clearCacheNode ();
public String getFullName ();
public String getFullName (INode root);
/**
*
*
* @return ...
*/
public String getName();
/**
*
*
* @param dbmap ...
*/
public void setDbMapping(DbMapping dbmap);
/**
*
*
* @return ...
*/
public DbMapping getDbMapping();
/**
*
*
* @return ...
*/
public int getState();
/**
*
*
* @param s ...
*/
public void setState(int s);
/**
*
*
* @param name ...
*/
public void setName(String name);
/**
*
*
* @return ...
*/
public long lastModified();
/**
*
*
* @return ...
*/
public long created();
/**
*
*
* @return ...
*/
public boolean isAnonymous(); // is this a named node, or an anonymous node in a collection?
/**
*
*
* @return ...
*/
public String getPrototype();
/**
*
*
* @param prototype ...
*/
public void setPrototype(String prototype);
/**
*
*
* @return ...
*/
public INode getCacheNode();
/**
*
*/
public void clearCacheNode();
/**
*
*
* @return ...
*/
public String getFullName();
/**
*
*
* @param root ...
*
* @return ...
*/
public String getFullName(INode root);
/**
* node-related methods
*/
public INode getParent();
public INode getParent ();
public void setSubnodeRelation (String rel);
public String getSubnodeRelation ();
public int numberOfNodes ();
public INode addNode (INode node);
public INode addNode (INode node, int where);
public INode createNode (String name);
public INode createNode (String name, int where);
public Enumeration getSubnodes ();
public INode getSubnode (String name);
public INode getSubnodeAt (int index);
public int contains (INode node);
public boolean remove ();
public void removeNode (INode node);
/**
*
*
* @param rel ...
*/
public void setSubnodeRelation(String rel);
/**
*
*
* @return ...
*/
public String getSubnodeRelation();
/**
*
*
* @return ...
*/
public int numberOfNodes();
/**
*
*
* @param node ...
*
* @return ...
*/
public INode addNode(INode node);
/**
*
*
* @param node ...
* @param where ...
*
* @return ...
*/
public INode addNode(INode node, int where);
/**
*
*
* @param name ...
*
* @return ...
*/
public INode createNode(String name);
/**
*
*
* @param name ...
* @param where ...
*
* @return ...
*/
public INode createNode(String name, int where);
/**
*
*
* @return ...
*/
public Enumeration getSubnodes();
/**
*
*
* @param name ...
*
* @return ...
*/
public INode getSubnode(String name);
/**
*
*
* @param index ...
*
* @return ...
*/
public INode getSubnodeAt(int index);
/**
*
*
* @param node ...
*
* @return ...
*/
public int contains(INode node);
/**
*
*
* @return ...
*/
public boolean remove();
/**
*
*
* @param node ...
*/
public void removeNode(INode node);
/**
* property-related methods
*/
public Enumeration properties();
public Enumeration properties ();
public IProperty get (String name);
public String getString (String name);
public boolean getBoolean (String name);
public Date getDate (String name);
public long getInteger (String name);
public double getFloat (String name);
public INode getNode (String name);
public Object getJavaObject (String name);
/**
*
*
* @param name ...
*
* @return ...
*/
public IProperty get(String name);
public void setString (String name, String value);
public void setBoolean (String name, boolean value);
public void setDate (String name, Date value);
public void setInteger (String name, long value);
public void setFloat (String name, double value);
public void setNode (String name, INode value);
public void setJavaObject (String name, Object value);
/**
*
*
* @param name ...
*
* @return ...
*/
public String getString(String name);
public void unset (String name);
/**
*
*
* @param name ...
*
* @return ...
*/
public boolean getBoolean(String name);
/**
*
*
* @param name ...
*
* @return ...
*/
public Date getDate(String name);
/**
*
*
* @param name ...
*
* @return ...
*/
public long getInteger(String name);
/**
*
*
* @param name ...
*
* @return ...
*/
public double getFloat(String name);
/**
*
*
* @param name ...
*
* @return ...
*/
public INode getNode(String name);
/**
*
*
* @param name ...
*
* @return ...
*/
public Object getJavaObject(String name);
/**
*
*
* @param name ...
* @param value ...
*/
public void setString(String name, String value);
/**
*
*
* @param name ...
* @param value ...
*/
public void setBoolean(String name, boolean value);
/**
*
*
* @param name ...
* @param value ...
*/
public void setDate(String name, Date value);
/**
*
*
* @param name ...
* @param value ...
*/
public void setInteger(String name, long value);
/**
*
*
* @param name ...
* @param value ...
*/
public void setFloat(String name, double value);
/**
*
*
* @param name ...
* @param value ...
*/
public void setNode(String name, INode value);
/**
*
*
* @param name ...
* @param value ...
*/
public void setJavaObject(String name, Object value);
/**
*
*
* @param 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;
import java.util.*;
import java.io.*;
import java.util.*;
/**
* Interface that defines states of nodes
*/
public interface INodeState {
public final static int TRANSIENT = -3;
public final static int VIRTUAL = -2;
public final static int INVALID = -1;
@ -19,9 +30,4 @@ public interface INodeState {
public final static int NEW = 1;
public final static int MODIFIED = 2;
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;
@ -8,9 +21,7 @@ import java.util.Date;
/**
* Interface that is implemented by node properties.
*/
public interface IProperty {
public static final int STRING = 1;
public static final int BOOLEAN = 2;
public static final int DATE = 3;
@ -19,16 +30,73 @@ public interface IProperty {
public static final int NODE = 6;
public static final int JAVAOBJECT = 7;
public String getName ();
public int getType ();
public Object getValue ();
/**
*
*
* @return ...
*/
public String getName();
public INode getNodeValue ();
public String getStringValue ();
public boolean getBooleanValue ();
public long getIntegerValue ();
public double getFloatValue ();
public Date getDateValue ();
public Object getJavaObjectValue ();
/**
*
*
* @return ...
*/
public int getType();
}
/**
*
*
* @return ...
*/
public Object getValue();
/**
*
*
* @return ...
*/
public INode getNodeValue();
/**
*
*
* @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;
/**
* This interface is kept for databases that are able
* to run transactions. Transactions were used for the
* Berkeley database and might be used in other future
* databases, so we leave transactions in.
*/
* This interface is kept for databases that are able
* to run transactions. Transactions were used for the
* Berkeley database and might be used in other future
* databases, so we leave transactions in.
*/
public interface ITransaction {
}

View file

@ -1,59 +1,92 @@
// 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;
import java.io.*;
/**
/**
* This is passed to NodeListeners when a node is modified.
*/
public class NodeEvent implements Serializable {
public static final int CONTENT_CHANGED = 0;
public static final int PROPERTIES_CHANGED = 1;
public static final int NODE_REMOVED = 2;
public static final int NODE_RENAMED = 3;
public static final int SUBNODE_ADDED = 4;
public static final int SUBNODE_REMOVED = 5;
public int type;
public String id;
public transient INode node;
public transient Object arg;
public NodeEvent (INode node, int type) {
super ();
this.node = node;
this.id = node.getID ();
this.type = type;
/**
* Creates a new NodeEvent object.
*
* @param node ...
* @param type ...
*/
public NodeEvent(INode node, int type) {
super();
this.node = node;
this.id = node.getID();
this.type = type;
}
public NodeEvent (INode node, int type, Object arg) {
super ();
this.node = node;
this.id = node.getID ();
this.type = type;
this.arg = arg;
/**
* Creates a new NodeEvent object.
*
* @param node ...
* @param type ...
* @param arg ...
*/
public NodeEvent(INode node, int type, Object arg) {
super();
this.node = node;
this.id = node.getID();
this.type = type;
this.arg = arg;
}
public String toString () {
switch (type) {
case CONTENT_CHANGED:
return "NodeEvent: content changed";
case PROPERTIES_CHANGED:
return "NodeEvent: properties changed";
case NODE_REMOVED:
return "NodeEvent: node removed";
case NODE_RENAMED:
return "NodeEvent: node moved";
case SUBNODE_ADDED:
return "NodeEvent: subnode added";
case SUBNODE_REMOVED:
return "NodeEvent: subnode removed";
}
return "NodeEvent: invalid type";
}
/**
*
*
* @return ...
*/
public String toString() {
switch (type) {
case CONTENT_CHANGED:
return "NodeEvent: content changed";
}
case PROPERTIES_CHANGED:
return "NodeEvent: properties changed";
case NODE_REMOVED:
return "NodeEvent: node removed";
case NODE_RENAMED:
return "NodeEvent: node moved";
case SUBNODE_ADDED:
return "NodeEvent: subnode added";
case SUBNODE_REMOVED:
return "NodeEvent: subnode removed";
}
return "NodeEvent: invalid type";
}
}

View file

@ -1,6 +1,19 @@
// 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;
@ -8,42 +21,13 @@ package helma.objectmodel;
* Thrown when an object could not found in the database where
* it was expected.
*/
public class ObjectNotFoundException extends Exception {
public ObjectNotFoundException (String msg) {
super (msg);
/**
* Creates a new ObjectNotFoundException object.
*
* @param msg ...
*/
public ObjectNotFoundException(String 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;
import helma.util.*;
import java.util.Vector;
import java.util.Hashtable;
import java.util.Date;
import java.util.Enumeration;
import java.io.*;
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 {
protected String propname;
protected TransientNode node;
public String svalue;
public boolean bvalue;
public long lvalue;
public double dvalue;
public INode nvalue;
public Object jvalue;
public int type;
public Property (TransientNode node) {
this.node = node;
/**
* Creates a new Property object.
*
* @param node ...
*/
public Property(TransientNode node) {
this.node = node;
}
public Property (String propname, TransientNode node) {
this.propname = propname;
this.node = node;
/**
* Creates a new Property object.
*
* @param propname ...
* @param node ...
*/
public Property(String propname, TransientNode node) {
this.propname = propname;
this.node = node;
}
public String getName () {
return propname;
/**
*
*
* @return ...
*/
public String getName() {
return propname;
}
public Object getValue () {
switch (type) {
case STRING:
return svalue;
case BOOLEAN:
return new Boolean (bvalue);
case INTEGER:
return new Long (lvalue);
case FLOAT:
return new Double (dvalue);
case DATE:
return new Date (lvalue);
case NODE:
return nvalue;
case JAVAOBJECT:
return jvalue;
}
return null;
/**
*
*
* @return ...
*/
public Object getValue() {
switch (type) {
case STRING:
return svalue;
case BOOLEAN:
return new Boolean(bvalue);
case INTEGER:
return new Long(lvalue);
case FLOAT:
return new Double(dvalue);
case DATE:
return new Date(lvalue);
case NODE:
return nvalue;
case JAVAOBJECT:
return jvalue;
}
return null;
}
public void setStringValue (String value) {
if (type == NODE)
this.nvalue = null;
if (type == JAVAOBJECT)
this.jvalue = null;
type = STRING;
this.svalue = value;
/**
*
*
* @param value ...
*/
public void setStringValue(String value) {
if (type == NODE) {
this.nvalue = null;
}
if (type == JAVAOBJECT) {
this.jvalue = null;
}
type = STRING;
this.svalue = value;
}
public void setIntegerValue (long value) {
if (type == NODE)
this.nvalue = null;
if (type == JAVAOBJECT)
this.jvalue = null;
type = INTEGER;
this.lvalue = value;
/**
*
*
* @param value ...
*/
public void setIntegerValue(long value) {
if (type == NODE) {
this.nvalue = null;
}
if (type == JAVAOBJECT) {
this.jvalue = null;
}
type = INTEGER;
this.lvalue = value;
}
public void setFloatValue (double value) {
if (type == NODE)
this.nvalue = null;
if (type == JAVAOBJECT)
this.jvalue = null;
type = FLOAT;
this.dvalue = value;
/**
*
*
* @param value ...
*/
public void setFloatValue(double value) {
if (type == NODE) {
this.nvalue = null;
}
if (type == JAVAOBJECT) {
this.jvalue = null;
}
type = FLOAT;
this.dvalue = value;
}
public void setDateValue (Date value) {
if (type == NODE)
this.nvalue = null;
if (type == JAVAOBJECT)
this.jvalue = null;
type = DATE;
this.lvalue = value.getTime();
/**
*
*
* @param value ...
*/
public void setDateValue(Date value) {
if (type == NODE) {
this.nvalue = null;
}
if (type == JAVAOBJECT) {
this.jvalue = null;
}
type = DATE;
this.lvalue = value.getTime();
}
public void setBooleanValue (boolean value) {
if (type == NODE)
this.nvalue = null;
if (type == JAVAOBJECT)
this.jvalue = null;
type = BOOLEAN;
this.bvalue = value;
/**
*
*
* @param value ...
*/
public void setBooleanValue(boolean value) {
if (type == NODE) {
this.nvalue = null;
}
if (type == JAVAOBJECT) {
this.jvalue = null;
}
type = BOOLEAN;
this.bvalue = value;
}
public void setNodeValue (INode value) {
if (type == JAVAOBJECT)
this.jvalue = null;
type = NODE;
this.nvalue = value;
/**
*
*
* @param value ...
*/
public void setNodeValue(INode value) {
if (type == JAVAOBJECT) {
this.jvalue = null;
}
type = NODE;
this.nvalue = value;
}
/**
*
*
* @param value ...
*/
public void setJavaObjectValue(Object value) {
if (type == NODE) {
this.nvalue = null;
}
public void setJavaObjectValue (Object value) {
if (type == NODE)
this.nvalue = null;
type = JAVAOBJECT;
this.jvalue = value;
type = JAVAOBJECT;
this.jvalue = value;
}
/**
*
*
* @return ...
*/
public String getStringValue() {
switch (type) {
case STRING:
return svalue;
public String getStringValue () {
switch (type) {
case STRING:
return svalue;
case BOOLEAN:
return "" + bvalue;
case DATE:
SimpleDateFormat format = new SimpleDateFormat ("dd.MM.yy HH:mm");
return format.format (new Date (lvalue));
case INTEGER:
return Long.toString (lvalue);
case FLOAT:
return Double.toString (dvalue);
case NODE:
return nvalue.getName ();
case JAVAOBJECT:
return jvalue == null ? null : jvalue.toString ();
}
return "";
case BOOLEAN:
return "" + bvalue;
case DATE:
SimpleDateFormat format = new SimpleDateFormat("dd.MM.yy HH:mm");
return format.format(new Date(lvalue));
case INTEGER:
return Long.toString(lvalue);
case FLOAT:
return Double.toString(dvalue);
case NODE:
return nvalue.getName();
case JAVAOBJECT:
return (jvalue == null) ? null : jvalue.toString();
}
return "";
}
public String toString () {
return getStringValue ();
/**
*
*
* @return ...
*/
public String toString() {
return getStringValue();
}
public long getIntegerValue () {
if (type == INTEGER)
return lvalue;
return 0;
/**
*
*
* @return ...
*/
public long getIntegerValue() {
if (type == INTEGER) {
return lvalue;
}
return 0;
}
public double getFloatValue () {
if (type == FLOAT)
return dvalue;
return 0.0;
/**
*
*
* @return ...
*/
public double getFloatValue() {
if (type == FLOAT) {
return dvalue;
}
return 0.0;
}
/**
*
*
* @return ...
*/
public Date getDateValue() {
if (type == DATE) {
return new Date(lvalue);
}
public Date getDateValue () {
if (type == DATE)
return new Date (lvalue);
return null;
return null;
}
public boolean getBooleanValue () {
if (type == BOOLEAN)
return bvalue;
return false;
/**
*
*
* @return ...
*/
public boolean getBooleanValue() {
if (type == BOOLEAN) {
return bvalue;
}
return false;
}
public INode getNodeValue () {
if (type == NODE)
return nvalue;
return null;
/**
*
*
* @return ...
*/
public INode getNodeValue() {
if (type == NODE) {
return nvalue;
}
return null;
}
public Object getJavaObjectValue () {
if (type == JAVAOBJECT)
return jvalue;
return null;
/**
*
*
* @return ...
*/
public Object getJavaObjectValue() {
if (type == JAVAOBJECT) {
return jvalue;
}
return null;
}
public int getType () {
return type;
/**
*
*
* @return ...
*/
public int getType() {
return type;
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,48 +1,62 @@
// 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;
/**
* 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.
*/
public final class DbColumn {
private final String name;
private final int type;
private final Relation relation;
/**
* Constructor
*/
public DbColumn (String name, int type, Relation rel) {
this.name = name;
this.type = type;
this.relation = rel;
if (relation != null)
relation.setColumnType (type);
public DbColumn(String name, int type, Relation rel) {
this.name = name;
this.type = type;
this.relation = rel;
if (relation != null) {
relation.setColumnType(type);
}
}
/**
* Get the column name.
*/
public String getName() {
return name;
return name;
}
/**
* Get this columns SQL data type.
*/
public int getType() {
return type;
return type;
}
/**
* Return the relation associated with this column. May be null.
*/
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;
import java.io.Serializable;
/**
* This is the internal representation of a database key. It is constructed
* from the logical table (type) name and the object's primary key
* within the table. Currently only single keys are supported.
*/
public final class DbKey implements Key, Serializable {
// 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.
// If null, the object is stored in the embedded db.
private final String storageName;
// the id that defines this key's object within the above storage space
private final String id;
@ -26,50 +38,82 @@ public final class DbKey implements Key, Serializable {
/**
* make a key for a persistent Object, describing its datasource and id.
*/
public DbKey (DbMapping dbmap, String id) {
this.id = id;
this.storageName = dbmap == null ? null : dbmap.getStorageTypeName ();
}
public boolean equals (Object what) {
if (what == this)
return true;
if (!(what instanceof DbKey))
return false;
DbKey k = (DbKey) what;
// storageName is an interned string (by DbMapping, from where we got it)
// so we can compare by using == instead of the equals method.
return storageName == k.storageName && (id == k.id || id.equals (k.id));
public DbKey(DbMapping dbmap, String id) {
this.id = id;
this.storageName = (dbmap == null) ? null : dbmap.getStorageTypeName();
}
public int hashCode () {
if (hashcode == 0) {
hashcode = storageName == null ?
17 + 37*id.hashCode () :
17 + 37*storageName.hashCode() + +37*id.hashCode ();
}
return hashcode;
/**
*
*
* @param what ...
*
* @return ...
*/
public boolean equals(Object what) {
if (what == this) {
return true;
}
if (!(what instanceof DbKey)) {
return false;
}
DbKey k = (DbKey) what;
// storageName is an interned string (by DbMapping, from where we got it)
// so we can compare by using == instead of the equals method.
return (storageName == k.storageName) && ((id == k.id) || id.equals(k.id));
}
public Key getParentKey () {
return null;
/**
*
*
* @return ...
*/
public int hashCode() {
if (hashcode == 0) {
hashcode = (storageName == null) ? (17 + (37 * id.hashCode()))
: (17 + (37 * storageName.hashCode()) +
(+37 * id.hashCode()));
}
return hashcode;
}
public String getStorageName () {
return storageName;
/**
*
*
* @return ...
*/
public Key getParentKey() {
return null;
}
public String getID () {
return id;
/**
*
*
* @return ...
*/
public String getStorageName() {
return storageName;
}
public String toString () {
return storageName == null ? "["+id+"]" : storageName+"["+id+"]";
/**
*
*
* @return ...
*/
public String getID() {
return id;
}
/**
*
*
* @return ...
*/
public String toString() {
return (storageName == null) ? ("[" + id + "]") : (storageName + "[" + id + "]");
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,120 +1,119 @@
// 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;
import helma.util.SystemProperties;
import java.sql.*;
import java.util.Hashtable;
import helma.util.SystemProperties;
/**
* This class describes a releational data source (URL, driver, user and password).
*/
public class DbSource {
private static SystemProperties defaultProps = null;
private String name;
private SystemProperties props;
private static SystemProperties defaultProps = null;
protected String url;
private String driver;
protected String user;
private String password;
private long lastRead = 0L;
private long lastRead = 0l;
public DbSource (String name, SystemProperties props) throws ClassNotFoundException {
this.name = name;
this.props = props;
init ();
/**
* Creates a new DbSource object.
*
* @param name ...
* @param props ...
*
* @throws ClassNotFoundException ...
*/
public DbSource(String name, SystemProperties props)
throws ClassNotFoundException {
this.name = name;
this.props = props;
init();
}
public Connection getConnection () throws ClassNotFoundException, SQLException {
Transactor tx = (Transactor) Thread.currentThread ();
Connection con = tx.getConnection (this);
boolean fileUpdated = props.lastModified () > lastRead;
if (!fileUpdated && defaultProps != null)
fileUpdated = defaultProps.lastModified () > lastRead;
if (con == null || con.isClosed () || fileUpdated) {
init ();
Class.forName (driver);
con = DriverManager.getConnection (url, user, password);
// If we wanted to use SQL transactions, we'd set autoCommit to
// false here and make commit/rollback invocations in Transactor methods;
// System.err.println ("Created new Connection to "+url);
tx.registerConnection (this, con);
//////////////////////////////////////////////
/* DatabaseMetaData meta = con.getMetaData ();
ResultSet tables = meta.getCatalogs ();
while (tables.next())
System.err.println ("********* TABLE: "+ tables.getObject (1));
ResultSet types = meta.getTypeInfo ();
while (types.next())
System.err.println ("******* TYPE: "+types.getObject(1) +" - "+types.getObject(2)+" - "+types.getObject(6));
*/
}
return con;
/**
*
*
* @return ...
*
* @throws ClassNotFoundException ...
* @throws SQLException ...
*/
public Connection getConnection() throws ClassNotFoundException, SQLException {
Transactor tx = (Transactor) Thread.currentThread();
Connection con = tx.getConnection(this);
boolean fileUpdated = props.lastModified() > lastRead;
if (!fileUpdated && (defaultProps != null)) {
fileUpdated = defaultProps.lastModified() > lastRead;
}
if ((con == null) || con.isClosed() || fileUpdated) {
init();
Class.forName(driver);
con = DriverManager.getConnection(url, user, password);
// If we wanted to use SQL transactions, we'd set autoCommit to
// false here and make commit/rollback invocations in Transactor methods;
// System.err.println ("Created new Connection to "+url);
tx.registerConnection(this, con);
}
return con;
}
private void init () throws ClassNotFoundException {
lastRead = defaultProps == null ? props.lastModified () : Math.max (props.lastModified (), defaultProps.lastModified ());
url = props.getProperty (name+".url");
driver = props.getProperty (name+".driver");
Class.forName (driver);
user = props.getProperty (name+".user");
password = props.getProperty (name+".password");
private void init() throws ClassNotFoundException {
lastRead = (defaultProps == null) ? props.lastModified()
: Math.max(props.lastModified(),
defaultProps.lastModified());
url = props.getProperty(name + ".url");
driver = props.getProperty(name + ".driver");
Class.forName(driver);
user = props.getProperty(name + ".user");
password = props.getProperty(name + ".password");
}
public String getDriverName () {
return driver;
/**
*
*
* @return ...
*/
public String getDriverName() {
return driver;
}
public String getName () {
return name;
/**
*
*
* @return ...
*/
public String getName() {
return name;
}
public static void setDefaultProps (SystemProperties props) {
defaultProps = props;
/**
*
*
* @param props ...
*/
public static void setDefaultProps(SystemProperties 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;
@ -7,33 +20,45 @@ import java.io.*;
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.
*/
public class ExternalizableVector extends ArrayList implements Externalizable {
static final long serialVersionUID = 2316243615310540423L;
public synchronized void readExternal (ObjectInput in) throws IOException {
try {
int size = in.readInt ();
for (int i=0; i<size; i++)
add (in.readObject ());
} catch (ClassNotFoundException x) {
throw new IOException (x.toString ());
}
/**
*
*
* @param in ...
*
* @throws IOException ...
*/
public synchronized void readExternal(ObjectInput in)
throws IOException {
try {
int size = in.readInt();
for (int i = 0; i < size; i++)
add(in.readObject());
} catch (ClassNotFoundException x) {
throw new IOException(x.toString());
}
}
public synchronized void writeExternal (ObjectOutput out) throws IOException {
int size = size ();
out.writeInt (size);
for (int i=0; i<size; i++)
out.writeObject (get (i));
}
/**
*
*
* @param out ...
*
* @throws IOException ...
*/
public synchronized void writeExternal(ObjectOutput out)
throws IOException {
int size = size();
out.writeInt(size);
for (int i = 0; i < size; i++)
out.writeObject(get(i));
}
}

View file

@ -1,73 +1,84 @@
// 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;
import java.io.Serializable;
/**
* An object that generates IDs (Strings) that are unique across the whole system.
* It does this keeping a simple long value which is incremented for each new ID.
* This is the key generation for nodes stored in the internal database, but it can
* also be used for relational nodes if no other mechanism is available. (Sequences
* An object that generates IDs (Strings) that are unique across the whole system.
* It does this keeping a simple long value which is incremented for each new ID.
* This is the key generation for nodes stored in the internal database, but it can
* also be used for relational nodes if no other mechanism is available. (Sequences
* in Oracle are supported, while auto-IDs are not, since the HOP has to know
* the keys of new objects.)
*/
public final class IDGenerator implements Serializable {
static final long serialVersionUID = 753408631669789263L;
private long counter;
transient volatile boolean dirty;
static final long serialVersionUID = 753408631669789263L;
/**
* Builds a new IDGenerator starting with 0.
*/
public IDGenerator () {
this.counter = 0l;
dirty = false;
*/
public IDGenerator() {
this.counter = 0L;
dirty = false;
}
/**
* Builds a new IDGenerator starting with value.
*/
public IDGenerator (long value) {
this.counter = value;
dirty = false;
*/
public IDGenerator(long value) {
this.counter = value;
dirty = false;
}
/**
* Delivers a unique id and increases counter by 1.
*/
public synchronized String newID () {
counter += 1l;
dirty = true;
return Long.toString (counter);
* Delivers a unique id and increases counter by 1.
*/
public synchronized String newID() {
counter += 1L;
dirty = true;
return Long.toString(counter);
}
/**
* Set the counter to a new value
*/
protected synchronized void setValue (long value) {
counter = value;
dirty = true;
protected synchronized void setValue(long value) {
counter = value;
dirty = true;
}
/**
* Get the current counter value
*/
public long getValue () {
return counter;
public long getValue() {
return counter;
}
public String toString () {
return "helma.objectmodel.db.IDGenerator[counter="+counter+",dirty="+dirty+"]";
/**
*
*
* @return ...
*/
public String toString() {
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;
@ -9,13 +22,11 @@ import java.util.Vector;
/**
* RMI interface for an application. Currently only execute is used and supported.
*/
public interface IReplicationListener extends Remote {
/**
* Update HopObjects in this application's cache. This is used to replicate
* 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,6 +1,19 @@
// 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;
@ -9,66 +22,24 @@ package helma.objectmodel.db;
*
*/
public interface Key {
/**
*
*
* @return ...
*/
public Key getParentKey();
/**
*
*
* @return ...
*/
public String getID();
public Key getParentKey ();
public String getID ();
public String getStorageName ();
/**
*
*
* @return ...
*/
public String getStorageName();
}

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,19 @@
// 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;
import helma.objectmodel.*;
@ -16,8 +29,8 @@ import java.io.Serializable;
* and reinstanciated since being set, NodeHandle will always return an up-to-date
* instance of its node.
*/
public final class NodeHandle implements INodeState, Serializable {
static final long serialVersionUID = 3067763116576910931L;
// direct reference to the node
private Node node;
@ -25,20 +38,19 @@ public final class NodeHandle implements INodeState, Serializable {
// the node's key
private Key key;
static final long serialVersionUID = 3067763116576910931L;
/**
* Builds a handle for a node
*/
public NodeHandle (Node node) {
int state = node.getState ();
if (state == TRANSIENT) {
this.node = node;
key = null;
} else {
this.node = null;
key = node.getKey ();
}
public NodeHandle(Node node) {
int state = node.getState();
if (state == TRANSIENT) {
this.node = node;
key = null;
} else {
this.node = null;
key = node.getKey();
}
}
/**
@ -46,73 +58,90 @@ public final class NodeHandle implements INodeState, Serializable {
* the node is ususally not yet created. It will be fetched on demand when accessed by
* application code.
*/
public NodeHandle (Key key) {
this.node = null;
this.key = key;
public NodeHandle(Key key) {
this.node = null;
this.key = key;
}
/**
* Get the node described by this node handle
*/
public Node getNode (WrappedNodeManager nodemgr) {
if (node != null)
return node;
return nodemgr.getNode (key);
public Node getNode(WrappedNodeManager nodemgr) {
if (node != null) {
return node;
}
return nodemgr.getNode(key);
}
/**
* Get the key for the node described by this handle.
* Get the key for the node described by this handle.
* This may only be called on persistent Nodes.
*/
public Key getKey () {
if (key == null)
throw new RuntimeException ("getKey called on transient Node");
return key;
public Key getKey() {
if (key == null) {
throw new RuntimeException("getKey called on transient Node");
}
return key;
}
/**
* Get the ID for the node described by this handle.
* Get the ID for the node described by this handle.
* This may only be called on persistent Nodes.
*/
public String getID () {
if (key == null)
return node.getID ();
return key.getID ();
public String getID() {
if (key == null) {
return node.getID();
}
return key.getID();
}
private Object getObject () {
if (node != null)
return node;
else
return key;
private Object getObject() {
if (node != null) {
return node;
} else {
return key;
}
}
public boolean equals (Object other) {
try {
return getObject ().equals (((NodeHandle) other).getObject ());
} catch (Exception x) {
return false;
}
/**
*
*
* @param other ...
*
* @return ...
*/
public boolean equals(Object other) {
try {
return getObject().equals(((NodeHandle) other).getObject());
} catch (Exception x) {
return false;
}
}
/**
* This is to notify the handle that the underlying node is becoming
* persistent and we have to refer to it via the key from now on.
*/
protected void becomePersistent () {
if (node != null) {
key = node.getKey ();
node = null;
}
}
public String toString () {
if (node != null)
return "NodeHandle[transient:"+node+"]";
else
return "NodeHandle["+key+"]";
protected void becomePersistent() {
if (node != null) {
key = node.getKey();
node = null;
}
}
/**
*
*
* @return ...
*/
public String toString() {
if (node != null) {
return "NodeHandle[transient:" + node + "]";
} else {
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;
@ -7,35 +20,45 @@ package helma.objectmodel.db;
/**
* This class describes a parent relation between releational nodes.
*/
public class ParentInfo {
public final String propname;
public final String virtualname;
public final boolean named;
public final boolean isroot;
/**
* Creates a new ParentInfo object.
*
* @param desc ...
*/
public ParentInfo(String desc) {
int n = desc.indexOf("[named]");
public ParentInfo (String desc) {
int n = desc.indexOf ("[named]");
named = n > -1;
String d = named ? desc.substring (0, n) : desc;
named = n > -1;
int dot = d.indexOf (".");
if (dot > -1) {
propname = d.substring (0, dot).trim();
virtualname = d.substring (dot+1).trim();
} else {
propname = d.trim();
virtualname = null;
}
isroot = "root".equals (propname);
// System.err.println ("created "+this);
}
String d = named ? desc.substring(0, n) : desc;
public String toString () {
return "ParentInfo["+propname+","+virtualname+","+named+"]";
int dot = d.indexOf(".");
if (dot > -1) {
propname = d.substring(0, dot).trim();
virtualname = d.substring(dot + 1).trim();
} else {
propname = d.trim();
virtualname = null;
}
isroot = "root".equals(propname);
// System.err.println ("created "+this);
}
/**
*
*
* @return ...
*/
public String toString() {
return "ParentInfo[" + propname + "," + virtualname + "," + named + "]";
}
}

View file

@ -1,342 +1,558 @@
// 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;
import helma.util.*;
import java.util.*;
import java.io.*;
import java.text.*;
import helma.objectmodel.*;
import helma.util.*;
import java.io.*;
import java.sql.Timestamp;
import java.text.*;
import java.util.*;
/**
* A property implementation for Nodes stored inside a database. Basically
* the same as for transient nodes, with a few hooks added.
*/
public final class Property implements IProperty, Serializable, Cloneable {
static final long serialVersionUID = -1022221688349192379L;
private String propname;
private Node node;
private Object value;
private int type;
transient boolean dirty;
static final long serialVersionUID = -1022221688349192379L;
private void readObject (ObjectInputStream in) throws IOException {
try {
propname = in.readUTF ();
node = (Node) in.readObject ();
type = in.readInt ();
switch (type) {
case STRING:
// try to convert from old format
if (node.version < 7)
value = in.readUTF ();
else
value = in.readObject ();
break;
case BOOLEAN:
value = in.readBoolean () ? Boolean.TRUE : Boolean.FALSE;
break;
case INTEGER:
value = new Long (in.readLong ());
break;
case DATE:
value = new Date (in.readLong ());
break;
case FLOAT:
value = new Double (in.readDouble ());
break;
case NODE:
// try to convert from old format
if (node.version > 4)
value = (NodeHandle) in.readObject ();
else
value = new NodeHandle (new DbKey (null, in.readUTF ()));
break;
case JAVAOBJECT:
value = in.readObject ();
break;
}
} catch (ClassNotFoundException x) {
throw new IOException (x.toString ());
}
/**
* Creates a new Property object.
*
* @param node ...
*/
public Property(Node node) {
this.node = node;
dirty = true;
}
private void writeObject (ObjectOutputStream out) throws IOException {
out.writeUTF (propname);
out.writeObject (node);
out.writeInt (type);
switch (type) {
case STRING:
out.writeObject (value);
break;
case BOOLEAN:
out.writeBoolean (((Boolean) value).booleanValue());
break;
case INTEGER:
out.writeLong (((Long) value).longValue());
break;
case DATE:
out.writeLong (((Date) value).getTime());
break;
case FLOAT:
out.writeDouble (((Double) value).doubleValue());
break;
case NODE:
out.writeObject (value);
break;
case JAVAOBJECT:
if (value != null && !(value instanceof Serializable))
out.writeObject (null);
else
out.writeObject (value);
break;
}
/**
* Creates a new Property object.
*
* @param propname ...
* @param node ...
*/
public Property(String propname, Node node) {
this.propname = propname;
this.node = node;
dirty = true;
}
public Property (Node node) {
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;
}
public Property (String propname, Node node) {
this.propname = propname;
this.node = node;
dirty = true;
private void readObject(ObjectInputStream in) throws IOException {
try {
propname = in.readUTF();
node = (Node) in.readObject();
type = in.readInt();
switch (type) {
case STRING:
// try to convert from old format
if (node.version < 7) {
value = in.readUTF();
} else {
value = in.readObject();
}
break;
case BOOLEAN:
value = in.readBoolean() ? Boolean.TRUE : Boolean.FALSE;
break;
case INTEGER:
value = new Long(in.readLong());
break;
case DATE:
value = new Date(in.readLong());
break;
case FLOAT:
value = new Double(in.readDouble());
break;
case NODE:
// try to convert from old format
if (node.version > 4) {
value = (NodeHandle) in.readObject();
} else {
value = new NodeHandle(new DbKey(null, in.readUTF()));
}
break;
case JAVAOBJECT:
value = in.readObject();
break;
}
} catch (ClassNotFoundException x) {
throw new IOException(x.toString());
}
}
public Property (String propname, Node node, Node valueNode) {
this (propname, node);
type = NODE;
value = valueNode == null ? null : valueNode.getHandle ();
dirty = true;
private void writeObject(ObjectOutputStream out) throws IOException {
out.writeUTF(propname);
out.writeObject(node);
out.writeInt(type);
switch (type) {
case STRING:
out.writeObject(value);
break;
case BOOLEAN:
out.writeBoolean(((Boolean) value).booleanValue());
break;
case INTEGER:
out.writeLong(((Long) value).longValue());
break;
case DATE:
out.writeLong(((Date) value).getTime());
break;
case FLOAT:
out.writeDouble(((Double) value).doubleValue());
break;
case NODE:
out.writeObject(value);
break;
case JAVAOBJECT:
if ((value != null) && !(value instanceof Serializable)) {
out.writeObject(null);
} else {
out.writeObject(value);
}
break;
}
}
public String getName () {
return propname;
/**
*
*
* @return ...
*/
public String getName() {
return propname;
}
public Object getValue () {
return value;
/**
*
*
* @return ...
*/
public Object getValue() {
return value;
}
public int getType () {
return type;
/**
*
*
* @return ...
*/
public int getType() {
return type;
}
public void setStringValue (String str) {
if (type == NODE)
unregisterNode ();
type = STRING;
value = str;
dirty = true;
/**
*
*
* @param str ...
*/
public void setStringValue(String str) {
if (type == NODE) {
unregisterNode();
}
type = STRING;
value = str;
dirty = true;
}
/**
*
*
* @param l ...
*/
public void setIntegerValue(long l) {
if (type == NODE) {
unregisterNode();
}
public void setIntegerValue (long l) {
if (type == NODE)
unregisterNode ();
type = INTEGER;
value = new Long(l);
dirty = true;
type = INTEGER;
value = new Long(l);
dirty = true;
}
public void setFloatValue (double d) {
if (type == NODE)
unregisterNode ();
type = FLOAT;
value = new Double(d);
dirty = true;
/**
*
*
* @param d ...
*/
public void setFloatValue(double d) {
if (type == NODE) {
unregisterNode();
}
type = FLOAT;
value = new Double(d);
dirty = true;
}
public void setDateValue (Date date) {
if (type == NODE)
unregisterNode ();
type = DATE;
value = date;
dirty = true;
/**
*
*
* @param date ...
*/
public void setDateValue(Date date) {
if (type == NODE) {
unregisterNode();
}
type = DATE;
value = date;
dirty = true;
}
public void setBooleanValue (boolean bool) {
if (type == NODE)
unregisterNode ();
type = BOOLEAN;
value = bool ? Boolean.TRUE : Boolean.FALSE;
dirty = true;
/**
*
*
* @param bool ...
*/
public void setBooleanValue(boolean bool) {
if (type == NODE) {
unregisterNode();
}
type = BOOLEAN;
value = bool ? Boolean.TRUE : Boolean.FALSE;
dirty = true;
}
public void setNodeValue (Node node) {
// value.checkWriteLock ();
if (type == NODE)
unregisterNode ();
/**
*
*
* @param node ...
*/
public void setNodeValue(Node node) {
// value.checkWriteLock ();
if (type == NODE) {
unregisterNode();
}
// registerNode (value);
type = NODE;
// registerNode (value);
type = NODE;
value = node == null ? null : node.getHandle ();
dirty = true;
value = (node == null) ? null : node.getHandle();
dirty = true;
}
public void setNodeHandle (NodeHandle handle) {
if (type == NODE)
unregisterNode ();
// registerNode (value);
type = NODE;
value = handle;
dirty = true;
/**
*
*
* @param handle ...
*/
public void setNodeHandle(NodeHandle handle) {
if (type == NODE) {
unregisterNode();
}
// registerNode (value);
type = NODE;
value = handle;
dirty = true;
}
public NodeHandle getNodeHandle () {
if (type == NODE)
return (NodeHandle) value;
return null;
/**
*
*
* @return ...
*/
public NodeHandle getNodeHandle() {
if (type == NODE) {
return (NodeHandle) value;
}
return null;
}
public void convertToNodeReference (DbMapping dbm) {
if (value != null && !(value instanceof NodeHandle))
value = new NodeHandle (new DbKey (dbm, value.toString ()));
type = NODE;
/**
*
*
* @param dbm ...
*/
public void convertToNodeReference(DbMapping dbm) {
if ((value != null) && !(value instanceof NodeHandle)) {
value = new NodeHandle(new DbKey(dbm, value.toString()));
}
type = NODE;
}
public void setJavaObjectValue (Object obj) {
if (type == NODE)
unregisterNode ();
type = JAVAOBJECT;
value = obj;
}
/**
*
*
* @param obj ...
*/
public void setJavaObjectValue(Object obj) {
if (type == NODE) {
unregisterNode();
}
type = JAVAOBJECT;
value = obj;
}
/**
* 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.
*/
protected void unregisterNode () {
if (value == null || !(value instanceof NodeHandle))
return;
NodeHandle nhandle = (NodeHandle) value;
Node nvalue = nhandle.getNode (node.nmgr);
protected void unregisterNode() {
if ((value == null) || !(value instanceof NodeHandle)) {
return;
}
DbMapping nvmap = null;
Relation nvrel = null;
if (node.dbmap != null) {
nvmap = node.dbmap.getPropertyMapping (propname);
nvrel = node.dbmap.getPropertyRelation (propname);
}
NodeHandle nhandle = (NodeHandle) value;
Node nvalue = nhandle.getNode(node.nmgr);
if (nvalue == null)
return;
DbMapping nvmap = null;
Relation nvrel = null;
nvalue.checkWriteLock ();
// check if the property node is also a subnode
// BUG: this doesn't work because properties for subnode/properties are never stored and therefore
// never reused.
if (nvrel != null && nvrel.hasAccessName()) {
node.removeNode (nvalue);
}
// 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
// based on that for relational nodes.
if (nvmap == null || !nvmap.isRelational()) {
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.
nvalue.deepRemoveNode ();
}
}
if (node.dbmap != null) {
nvmap = node.dbmap.getPropertyMapping(propname);
nvrel = node.dbmap.getPropertyRelation(propname);
}
if (nvalue == null) {
return;
}
nvalue.checkWriteLock();
// check if the property node is also a subnode
// BUG: this doesn't work because properties for subnode/properties are never stored and therefore
// never reused.
if ((nvrel != null) && nvrel.hasAccessName()) {
node.removeNode(nvalue);
}
// 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
// based on that for relational nodes.
if ((nvmap == null) || !nvmap.isRelational()) {
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.
nvalue.deepRemoveNode();
}
}
}
/**
*
*
* @return ...
*/
public String getStringValue() {
if (value == null) {
return null;
}
public String getStringValue () {
if (value == null)
return null;
switch (type) {
case STRING:
case BOOLEAN:
case INTEGER:
case FLOAT:
case JAVAOBJECT:
return value.toString ();
case DATE:
SimpleDateFormat format = new SimpleDateFormat ("dd.MM.yy hh:mm:ss");
return format.format ((Date) value);
case NODE:
return ((NodeHandle) value).getID ();
}
return "";
switch (type) {
case STRING:
case BOOLEAN:
case INTEGER:
case FLOAT:
case JAVAOBJECT:
return value.toString();
case DATE:
SimpleDateFormat format = new SimpleDateFormat("dd.MM.yy hh:mm:ss");
return format.format((Date) value);
case NODE:
return ((NodeHandle) value).getID();
}
return "";
}
public String toString () {
return getStringValue ();
/**
*
*
* @return ...
*/
public String toString() {
return getStringValue();
}
public long getIntegerValue () {
if (type == INTEGER)
return ((Long) value).longValue ();
if (type == FLOAT)
return ((Double) value).longValue ();
if (type == BOOLEAN)
return ((Boolean) value).booleanValue() ? 1 : 0;
try {
return Long.parseLong (getStringValue());
} catch (Exception x) {
return 0;
}
/**
*
*
* @return ...
*/
public long getIntegerValue() {
if (type == INTEGER) {
return ((Long) value).longValue();
}
if (type == FLOAT) {
return ((Double) value).longValue();
}
if (type == BOOLEAN) {
return ((Boolean) value).booleanValue() ? 1 : 0;
}
try {
return Long.parseLong(getStringValue());
} catch (Exception x) {
return 0;
}
}
public double getFloatValue () {
if (type == FLOAT)
return ((Double) value).doubleValue();
if (type == INTEGER)
return ((Long) value).doubleValue ();
try {
return Double.parseDouble (getStringValue());
} catch (Exception x) {
return 0.0;
}
/**
*
*
* @return ...
*/
public double getFloatValue() {
if (type == FLOAT) {
return ((Double) value).doubleValue();
}
if (type == INTEGER) {
return ((Long) value).doubleValue();
}
try {
return Double.parseDouble(getStringValue());
} catch (Exception x) {
return 0.0;
}
}
/**
*
*
* @return ...
*/
public Date getDateValue() {
if (type == DATE) {
return (Date) value;
}
public Date getDateValue () {
if (type == DATE)
return (Date) value;
return null;
return null;
}
public Timestamp getTimestampValue () {
if (type == DATE && value != null)
return new Timestamp (((Date) value).getTime());
return null;
/**
*
*
* @return ...
*/
public Timestamp getTimestampValue() {
if ((type == DATE) && (value != null)) {
return new Timestamp(((Date) value).getTime());
}
return null;
}
public boolean getBooleanValue () {
if (type == BOOLEAN)
return ((Boolean) value).booleanValue();
if (type == INTEGER)
return !(0 == getIntegerValue());
return false;
/**
*
*
* @return ...
*/
public boolean getBooleanValue() {
if (type == BOOLEAN) {
return ((Boolean) value).booleanValue();
}
if (type == INTEGER) {
return !(0 == getIntegerValue());
}
return false;
}
public INode getNodeValue () {
if (type == NODE && value != null) {
NodeHandle nhandle = (NodeHandle) value;
return nhandle.getNode (node.nmgr);
}
return null;
/**
*
*
* @return ...
*/
public INode getNodeValue() {
if ((type == NODE) && (value != null)) {
NodeHandle nhandle = (NodeHandle) value;
return nhandle.getNode(node.nmgr);
}
return null;
}
public Object getJavaObjectValue () {
if (type == JAVAOBJECT)
return value;
return null;
}
/**
*
*
* @return ...
*/
public Object getJavaObjectValue() {
if (type == JAVAOBJECT) {
return value;
}
return null;
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,19 @@
// 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;
import java.rmi.*;
@ -9,76 +22,113 @@ import java.util.*;
/**
* This class replicates the updates of transactions to other applications via RMI
*/
public class Replicator implements Runnable {
Vector urls;
Vector add, delete, currentAdd, currentDelete;
Vector add;
Vector delete;
Vector currentAdd;
Vector currentDelete;
Thread runner;
NodeManager nmgr;
public Replicator (NodeManager nmgr) {
urls = new Vector ();
add = new Vector ();
delete = new Vector ();
this.nmgr = nmgr;
runner = new Thread (this);
runner.start ();
/**
* Creates a new Replicator object.
*
* @param nmgr ...
*/
public Replicator(NodeManager nmgr) {
urls = new Vector();
add = new Vector();
delete = new Vector();
this.nmgr = nmgr;
runner = new Thread(this);
runner.start();
}
public void addUrl (String url) {
urls.addElement (url);
if (nmgr.logReplication)
nmgr.app.logEvent ("Adding replication listener: "+url);
/**
*
*
* @param url ...
*/
public void addUrl(String url) {
urls.addElement(url);
if (nmgr.logReplication) {
nmgr.app.logEvent("Adding replication listener: " + url);
}
}
public void run () {
while (Thread.currentThread () == runner) {
if (prepareReplication ()) {
for (int i=0; i<urls.size(); i++) {
try {
String url = (String) urls.elementAt (i);
IReplicationListener listener = (IReplicationListener) Naming.lookup (url);
listener.replicateCache (currentAdd, currentDelete);
if (nmgr.logReplication)
nmgr.app.logEvent ("Sent cache replication event: "+add.size()+" added, "+delete.size()+" deleted");
} catch (Exception x) {
nmgr.app.logEvent ("Error sending cache replication event: "+x);
}
}
}
/**
*
*/
public void run() {
while (Thread.currentThread() == runner) {
if (prepareReplication()) {
for (int i = 0; i < urls.size(); i++) {
try {
String url = (String) urls.elementAt(i);
IReplicationListener listener = (IReplicationListener) Naming.lookup(url);
try {
if (runner != null)
runner.sleep (1000l);
} catch (InterruptedException ir) {
runner = null;
}
}
listener.replicateCache(currentAdd, currentDelete);
if (nmgr.logReplication) {
nmgr.app.logEvent("Sent cache replication event: " +
add.size() + " added, " + delete.size() +
" deleted");
}
} catch (Exception x) {
nmgr.app.logEvent("Error sending cache replication event: " + x);
}
}
}
try {
if (runner != null) {
runner.sleep(1000L);
}
} catch (InterruptedException ir) {
runner = null;
}
}
}
public synchronized void addNewNode (Node n) {
add.addElement (n);
/**
*
*
* @param n ...
*/
public synchronized void addNewNode(Node n) {
add.addElement(n);
}
public synchronized void addModifiedNode (Node n) {
add.addElement (n);
/**
*
*
* @param n ...
*/
public synchronized void addModifiedNode(Node n) {
add.addElement(n);
}
public synchronized void addDeletedNode (Node n) {
delete.addElement (n);
/**
*
*
* @param n ...
*/
public synchronized void addDeletedNode(Node n) {
delete.addElement(n);
}
private synchronized boolean prepareReplication () {
if (add.size() == 0 && delete.size() == 0)
return false;
currentAdd = add;
currentDelete = delete;
add = new Vector ();
delete = new Vector ();
return true;
}
private synchronized boolean prepareReplication() {
if ((add.size() == 0) && (delete.size() == 0)) {
return false;
}
currentAdd = add;
currentDelete = delete;
add = new Vector();
delete = new Vector();
return true;
}
}

View file

@ -1,6 +1,19 @@
// 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;
import java.io.IOException;
@ -9,16 +22,12 @@ import java.io.IOException;
* Helma server main class. This moved to the helma.main package but a
* simple redirector is kept here for backwards compatibility.
*/
public class Server {
public class Server {
/**
* Just invoke the main method in the new Server class.
*/
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.");
helma.main.Server.main (args);
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.");
helma.main.Server.main(args);
}
}

View file

@ -1,6 +1,19 @@
// 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;
import java.io.Serializable;
@ -9,59 +22,91 @@ import java.io.Serializable;
* This is the internal key for an object that is not - or not directly - fetched from a db,
* but derived from another object. This is useful for all kinds of object accessed via a
* symbolic name from another object, like objects mounted via a property name column,
* virtual nodes and groupby nodes.
* virtual nodes and groupby nodes.
*/
public final class SyntheticKey implements Key, Serializable {
private final Key parentKey;
private final String name;
// lazily initialized hashcode
private transient int hashcode = 0;
/**
* make a key for a persistent Object, describing its datasource and id.
*/
public SyntheticKey (Key key, String name) {
this.parentKey = key;
this.name = name;
public SyntheticKey(Key key, String name) {
this.parentKey = key;
this.name = name;
}
/**
*
*
* @param what ...
*
* @return ...
*/
public boolean equals(Object what) {
if (what == this) {
return true;
}
public boolean equals (Object what) {
if (what == this)
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));
}
public int hashCode () {
if (hashcode == 0)
hashcode = 17 + 37*name.hashCode () + 37*parentKey.hashCode ();
return hashcode;
/**
*
*
* @return ...
*/
public int hashCode() {
if (hashcode == 0) {
hashcode = 17 + (37 * name.hashCode()) + (37 * parentKey.hashCode());
}
return hashcode;
}
public Key getParentKey () {
return parentKey;
/**
*
*
* @return ...
*/
public Key getParentKey() {
return parentKey;
}
public String getID () {
return name;
/**
*
*
* @return ...
*/
public String getID() {
return name;
}
public String getStorageName () {
return null;
/**
*
*
* @return ...
*/
public String getStorageName() {
return null;
}
public String toString () {
return parentKey+"/"+name;
/**
*
*
* @return ...
*/
public String toString() {
return parentKey + "/" + name;
}
}

View file

@ -1,251 +1,377 @@
// 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;
import java.io.*;
import java.util.*;
import java.sql.*;
import helma.framework.TimeoutException;
import helma.objectmodel.*;
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.
*/
public class Transactor extends Thread {
NodeManager nmgr;
// List of nodes to be updated
private HashMap nodes;
private ArrayList nodesArray;
// List of visited clean nodes
private HashMap cleannodes;
// Is a transaction in progress?
private volatile boolean active;
private volatile boolean killed;
// Transaction for the embedded database
protected ITransaction txn;
// Transactions for SQL data sources
protected HashMap sqlCon;
public Timer timer;
// when did the current transaction start?
private long tstart;
// a name to log the transaction. For HTTP transactions this is the rerquest path
private String tname;
public Transactor (Runnable runnable, ThreadGroup group, NodeManager nmgr) {
super (group, runnable, group.getName ());
this.nmgr = nmgr;
nodes = new HashMap ();
nodesArray = new ArrayList ();
cleannodes = new HashMap ();
sqlCon = new HashMap ();
active = false;
killed = false;
timer = new Timer();
/**
* Creates a new Transactor object.
*
* @param runnable ...
* @param group ...
* @param nmgr ...
*/
public Transactor(Runnable runnable, ThreadGroup group, NodeManager nmgr) {
super(group, runnable, group.getName());
this.nmgr = nmgr;
nodes = new HashMap();
nodesArray = new ArrayList();
cleannodes = new HashMap();
sqlCon = new HashMap();
active = false;
killed = false;
timer = new Timer();
}
public void visitNode (Node node) {
if (node != null) {
Key key = node.getKey ();
if (!nodes.containsKey (key)) {
nodes.put (key, node);
nodesArray.add (node);
}
}
/**
*
*
* @param node ...
*/
public void visitNode(Node node) {
if (node != null) {
Key key = node.getKey();
if (!nodes.containsKey(key)) {
nodes.put(key, node);
nodesArray.add(node);
}
}
}
public void dropNode (Node node) {
if (node != null) {
Key key = node.getKey ();
nodes.remove (key);
nodesArray.remove (node);
}
/**
*
*
* @param node ...
*/
public void dropNode(Node node) {
if (node != null) {
Key key = node.getKey();
nodes.remove(key);
nodesArray.remove(node);
}
}
public void visitCleanNode (Node node) {
if (node != null) {
Key key = node.getKey ();
if (!cleannodes.containsKey (key)) {
cleannodes.put (key, node);
}
}
/**
*
*
* @param node ...
*/
public void visitCleanNode(Node node) {
if (node != null) {
Key key = node.getKey();
if (!cleannodes.containsKey(key)) {
cleannodes.put(key, node);
}
}
}
public void visitCleanNode (Key key, Node node) {
if (node != null) {
if (!cleannodes.containsKey (key)) {
cleannodes.put (key, node);
}
}
/**
*
*
* @param key ...
* @param node ...
*/
public void visitCleanNode(Key key, Node node) {
if (node != null) {
if (!cleannodes.containsKey(key)) {
cleannodes.put(key, node);
}
}
}
public Node getVisitedNode (Object key) {
return key == null ? null : (Node) cleannodes.get (key);
/**
*
*
* @param key ...
*
* @return ...
*/
public Node getVisitedNode(Object key) {
return (key == null) ? null : (Node) cleannodes.get(key);
}
public boolean isActive () {
return active;
/**
*
*
* @return ...
*/
public boolean isActive() {
return active;
}
public void registerConnection (DbSource src, Connection con) {
sqlCon.put (src, con);
/**
*
*
* @param src ...
* @param con ...
*/
public void registerConnection(DbSource src, Connection con) {
sqlCon.put(src, con);
}
public Connection getConnection (DbSource src) {
return (Connection) sqlCon.get (src);
/**
*
*
* @param src ...
*
* @return ...
*/
public Connection getConnection(DbSource src) {
return (Connection) sqlCon.get(src);
}
public synchronized void begin (String tnm) throws Exception {
/**
*
*
* @param tnm ...
*
* @throws Exception ...
* @throws DatabaseException ...
*/
public synchronized void begin(String tnm) throws Exception {
if (killed) {
throw new DatabaseException("Transaction started on killed thread");
}
if (killed)
throw new DatabaseException ("Transaction started on killed thread");
if (active) {
abort();
}
if (active)
abort ();
nodes.clear ();
nodesArray.clear ();
cleannodes.clear ();
txn = nmgr.db.beginTransaction ();
active = true;
tstart = System.currentTimeMillis ();
tname = tnm;
nodes.clear();
nodesArray.clear();
cleannodes.clear();
txn = nmgr.db.beginTransaction();
active = true;
tstart = System.currentTimeMillis();
tname = tnm;
}
public synchronized void commit () throws Exception {
/**
*
*
* @throws Exception ...
*/
public synchronized void commit() throws Exception {
if (killed) {
abort();
if (killed) {
abort ();
return;
}
return;
}
int ins = 0, upd = 0, dlt = 0;
int l = nodesArray.size ();
int ins = 0;
int upd = 0;
int dlt = 0;
int l = nodesArray.size();
Replicator replicator = nmgr.getReplicator ();
Replicator replicator = nmgr.getReplicator();
for (int i=0; i<l; i++) {
Node node = (Node) nodesArray.get (i);
// update nodes in db
int nstate = node.getState ();
if (nstate == Node.NEW) {
nmgr.registerNode (node); // register node with nodemanager cache
nmgr.insertNode (nmgr.db, txn, node);
node.setState (Node.CLEAN);
if (replicator != null)
replicator.addNewNode (node);
ins++;
nmgr.app.logEvent ("inserted: Node "+node.getPrototype ()+"/"+node.getID ());
} else if (nstate == Node.MODIFIED) {
nmgr.updateNode (nmgr.db, txn, node);
node.setState (Node.CLEAN);
if (replicator != null)
replicator.addModifiedNode (node);
upd++;
nmgr.app.logEvent ("updated: Node "+node.getPrototype ()+"/"+node.getID ());
} else if (nstate == Node.DELETED) {
// nmgr.app.logEvent ("deleted: "+node.getFullName ()+" ("+node.getName ()+")");
nmgr.deleteNode (nmgr.db, txn, node);
nmgr.evictNode (node);
if (replicator != null)
replicator.addDeletedNode (node);
dlt++;
} else {
// nmgr.app.logEvent ("noop: "+node.getFullName ());
}
node.clearWriteLock ();
}
for (int i = 0; i < l; i++) {
Node node = (Node) nodesArray.get(i);
nodes.clear ();
nodesArray.clear ();
cleannodes.clear ();
// update nodes in db
int nstate = node.getState();
if (nmgr.idgen.dirty) {
nmgr.db.saveIDGenerator (txn, nmgr.idgen);
nmgr.idgen.dirty = false;
}
if (nstate == Node.NEW) {
nmgr.registerNode(node); // register node with nodemanager cache
nmgr.insertNode(nmgr.db, txn, node);
node.setState(Node.CLEAN);
if (active) {
active = false;
nmgr.db.commitTransaction (txn);
txn = null;
}
if (replicator != null) {
replicator.addNewNode(node);
}
nmgr.app.logAccess (tname+" "+l+" marked, "+ins+" inserted, "+upd+" updated, "+dlt+" deleted in "+(System.currentTimeMillis()-tstart)+" millis");
ins++;
nmgr.app.logEvent("inserted: Node " + node.getPrototype() + "/" +
node.getID());
} else if (nstate == Node.MODIFIED) {
nmgr.updateNode(nmgr.db, txn, node);
node.setState(Node.CLEAN);
if (replicator != null) {
replicator.addModifiedNode(node);
}
upd++;
nmgr.app.logEvent("updated: Node " + node.getPrototype() + "/" +
node.getID());
} else if (nstate == Node.DELETED) {
// nmgr.app.logEvent ("deleted: "+node.getFullName ()+" ("+node.getName ()+")");
nmgr.deleteNode(nmgr.db, txn, node);
nmgr.evictNode(node);
if (replicator != null) {
replicator.addDeletedNode(node);
}
dlt++;
} else {
// nmgr.app.logEvent ("noop: "+node.getFullName ());
}
node.clearWriteLock();
}
nodes.clear();
nodesArray.clear();
cleannodes.clear();
if (nmgr.idgen.dirty) {
nmgr.db.saveIDGenerator(txn, nmgr.idgen);
nmgr.idgen.dirty = false;
}
if (active) {
active = false;
nmgr.db.commitTransaction(txn);
txn = null;
}
nmgr.app.logAccess(tname + " " + l + " marked, " + ins + " inserted, " + upd +
" updated, " + dlt + " deleted in " +
(System.currentTimeMillis() - tstart) + " millis");
}
public synchronized void abort () throws Exception {
/**
*
*
* @throws Exception ...
*/
public synchronized void abort() throws Exception {
int l = nodesArray.size();
int l = nodesArray.size ();
for (int i=0; i<l; i++ ) {
Node node = (Node) nodesArray.get (i);
// Declare node as invalid, so it won't be used by other threads that want to
// write on it and remove it from cache
nmgr.evictNode (node);
node.clearWriteLock ();
}
nodes.clear ();
nodesArray.clear ();
cleannodes.clear ();
// close any JDBC connections associated with this transactor thread
closeConnections ();
for (int i = 0; i < l; i++) {
Node node = (Node) nodesArray.get(i);
if (active) {
active = false;
if (txn != null) {
nmgr.db.abortTransaction (txn);
txn = null;
}
nmgr.app.logAccess (tname+" aborted after "+(System.currentTimeMillis()-tstart)+" millis");
}
// Declare node as invalid, so it won't be used by other threads that want to
// write on it and remove it from cache
nmgr.evictNode(node);
node.clearWriteLock();
}
nodes.clear();
nodesArray.clear();
cleannodes.clear();
// close any JDBC connections associated with this transactor thread
closeConnections();
if (active) {
active = false;
if (txn != null) {
nmgr.db.abortTransaction(txn);
txn = null;
}
nmgr.app.logAccess(tname + " aborted after " +
(System.currentTimeMillis() - tstart) + " millis");
}
}
public synchronized void kill () {
killed = true;
// 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.
try {
join (500);
} catch (InterruptedException ir) {}
/**
*
*/
public synchronized void kill() {
killed = true;
// Interrupt the thread if it has not noticed the flag (e.g. because it is busy
// reading from a network socket).
if (isAlive()) {
interrupt ();
try {
join (1000);
} catch (InterruptedException ir) {}
}
// 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.
try {
join(500);
} catch (InterruptedException ir) {
}
// Interrupt the thread if it has not noticed the flag (e.g. because it is busy
// reading from a network socket).
if (isAlive()) {
interrupt();
try {
join(1000);
} catch (InterruptedException ir) {
}
}
}
public void closeConnections () {
// nmgr.app.logEvent("Cleaning up Transactor thread");
if (sqlCon != null) {
for (Iterator i=sqlCon.values().iterator(); i.hasNext(); ) {
try {
Connection con = (Connection) i.next();
con.close ();
nmgr.app.logEvent ("Closing DB connection: "+con);
} catch (Exception ignore) {}
}
sqlCon.clear ();
}
/**
*
*/
public void closeConnections() {
// nmgr.app.logEvent("Cleaning up Transactor thread");
if (sqlCon != null) {
for (Iterator i = sqlCon.values().iterator(); i.hasNext();) {
try {
Connection con = (Connection) i.next();
con.close();
nmgr.app.logEvent("Closing DB connection: " + con);
} catch (Exception ignore) {
}
}
sqlCon.clear();
}
}
public String toString () {
return "Transactor["+tname+"]";
/**
*
*
* @return ...
*/
public String toString() {
return "Transactor[" + tname + "]";
}
}

View file

@ -1,156 +1,303 @@
// 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;
import helma.objectmodel.*;
import java.util.List;
import java.util.Vector;
/**
* 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
* in JavaScript which doesn't know about them (except for the exception message).
*/
public final class WrappedNodeManager {
public final class WrappedNodeManager {
NodeManager nmgr;
public WrappedNodeManager (NodeManager nmgr) {
this.nmgr = nmgr;
/**
* Creates a new WrappedNodeManager object.
*
* @param nmgr ...
*/
public WrappedNodeManager(NodeManager nmgr) {
this.nmgr = nmgr;
}
public Node getNode (String id, DbMapping dbmap) {
return getNode (new DbKey (dbmap, id));
/**
*
*
* @param id ...
* @param dbmap ...
*
* @return ...
*/
public Node getNode(String id, DbMapping dbmap) {
return getNode(new DbKey(dbmap, id));
}
public Node getNode (Key key) {
try {
return nmgr.getNode (key);
} catch (ObjectNotFoundException x) {
return null;
} catch (Exception x) {
nmgr.app.logEvent ("Error retrieving Node via DbMapping: "+x);
if (nmgr.app.debug ())
x.printStackTrace();
throw new RuntimeException ("Error retrieving Node: "+x);
}
/**
*
*
* @param key ...
*
* @return ...
*/
public Node getNode(Key key) {
try {
return nmgr.getNode(key);
} catch (ObjectNotFoundException x) {
return null;
} catch (Exception x) {
nmgr.app.logEvent("Error retrieving Node via DbMapping: " + x);
if (nmgr.app.debug()) {
x.printStackTrace();
}
throw new RuntimeException("Error retrieving Node: " + x);
}
}
public Node getNode (Node home, String id, Relation rel) {
try {
return nmgr.getNode (home, id, rel);
} catch (ObjectNotFoundException x) {
return null;
} catch (Exception x) {
nmgr.app.logEvent ("Error retrieving Node \""+id+"\" from "+home+": "+x);
if (nmgr.app.debug ())
x.printStackTrace();
throw new RuntimeException ("Error retrieving Node: "+x);
}
/**
*
*
* @param home ...
* @param id ...
* @param rel ...
*
* @return ...
*/
public Node getNode(Node home, String id, Relation rel) {
try {
return nmgr.getNode(home, id, rel);
} catch (ObjectNotFoundException x) {
return null;
} catch (Exception x) {
nmgr.app.logEvent("Error retrieving Node \"" + id + "\" from " + home + ": " +
x);
if (nmgr.app.debug()) {
x.printStackTrace();
}
throw new RuntimeException("Error retrieving Node: " + x);
}
}
public List getNodes (Node home, Relation rel) {
try {
return nmgr.getNodes (home, rel);
} catch (Exception x) {
if (nmgr.app.debug ())
x.printStackTrace();
throw new RuntimeException ("Error retrieving Nodes: "+x);
}
/**
*
*
* @param home ...
* @param rel ...
*
* @return ...
*/
public List getNodes(Node home, Relation rel) {
try {
return nmgr.getNodes(home, rel);
} catch (Exception x) {
if (nmgr.app.debug()) {
x.printStackTrace();
}
throw new RuntimeException("Error retrieving Nodes: " + x);
}
}
public List getNodeIDs (Node home, Relation rel) {
try {
return nmgr.getNodeIDs (home, rel);
} catch (Exception x) {
if (nmgr.app.debug ())
x.printStackTrace();
throw new RuntimeException ("Error retrieving NodeIDs: "+x);
}
/**
*
*
* @param home ...
* @param rel ...
*
* @return ...
*/
public List getNodeIDs(Node home, Relation rel) {
try {
return nmgr.getNodeIDs(home, rel);
} catch (Exception x) {
if (nmgr.app.debug()) {
x.printStackTrace();
}
throw new RuntimeException("Error retrieving NodeIDs: " + x);
}
}
public int countNodes (Node home, Relation rel) {
try {
return nmgr.countNodes (home, rel);
} catch (Exception x) {
if (nmgr.app.debug ())
x.printStackTrace();
throw new RuntimeException ("Error counting Node: "+x);
}
/**
*
*
* @param home ...
* @param rel ...
*
* @return ...
*/
public int countNodes(Node home, Relation rel) {
try {
return nmgr.countNodes(home, rel);
} catch (Exception x) {
if (nmgr.app.debug()) {
x.printStackTrace();
}
throw new RuntimeException("Error counting Node: " + x);
}
}
public void deleteNode (Node node) {
try {
nmgr.deleteNode (node);
} catch (Exception x) {
if (nmgr.app.debug ())
x.printStackTrace();
throw new RuntimeException ("Error deleting Node: "+x);
}
/**
*
*
* @param node ...
*/
public void deleteNode(Node node) {
try {
nmgr.deleteNode(node);
} catch (Exception x) {
if (nmgr.app.debug()) {
x.printStackTrace();
}
throw new RuntimeException("Error deleting Node: " + x);
}
}
public Vector getPropertyNames (Node home, Relation rel) {
try {
return nmgr.getPropertyNames (home, rel);
} catch (Exception x) {
if (nmgr.app.debug ())
x.printStackTrace();
throw new RuntimeException ("Error retrieving property names: "+x);
}
/**
*
*
* @param home ...
* @param rel ...
*
* @return ...
*/
public Vector getPropertyNames(Node home, Relation rel) {
try {
return nmgr.getPropertyNames(home, rel);
} catch (Exception x) {
if (nmgr.app.debug()) {
x.printStackTrace();
}
throw new RuntimeException("Error retrieving property names: " + x);
}
}
public void registerNode (Node node) {
nmgr.registerNode (node);
/**
*
*
* @param node ...
*/
public void registerNode(Node node) {
nmgr.registerNode(node);
}
public void evictNode (Node node) {
nmgr.evictNode (node);
/**
*
*
* @param node ...
*/
public void evictNode(Node node) {
nmgr.evictNode(node);
}
public void evictNodeByKey (Key key) {
nmgr.evictNodeByKey (key);
/**
*
*
* @param key ...
*/
public void evictNodeByKey(Key key) {
nmgr.evictNodeByKey(key);
}
public void evictKey (Key key) {
nmgr.evictKey (key);
/**
*
*
* @param key ...
*/
public void evictKey(Key key) {
nmgr.evictKey(key);
}
public String generateID () {
return nmgr.idgen.newID ();
/**
*
*
* @return ...
*/
public String generateID() {
return nmgr.idgen.newID();
}
public String generateID (DbMapping map) {
try {
// check if we use internal id generator
if (map == null || !map.isRelational () || "[hop]".equalsIgnoreCase (map.getIDgen()))
return nmgr.idgen.newID ();
// or if we query max key value
else if (map.getIDgen() == null || "[max]".equalsIgnoreCase (map.getIDgen()))
return nmgr.generateMaxID (map);
else
return nmgr.generateID (map);
// otherwise, we use an oracle sequence
} catch (Exception x) {
if (nmgr.app.debug ())
x.printStackTrace();
throw new RuntimeException (x.toString ());
}
/**
*
*
* @param map ...
*
* @return ...
*/
public String generateID(DbMapping map) {
try {
// check if we use internal id generator
if ((map == null) || !map.isRelational() ||
"[hop]".equalsIgnoreCase(map.getIDgen())) {
return nmgr.idgen.newID();
}
// or if we query max key value
else if ((map.getIDgen() == null) ||
"[max]".equalsIgnoreCase(map.getIDgen())) {
return nmgr.generateMaxID(map);
} else {
return nmgr.generateID(map);
}
// otherwise, we use an oracle sequence
} catch (Exception x) {
if (nmgr.app.debug()) {
x.printStackTrace();
}
throw new RuntimeException(x.toString());
}
}
public Object[] getCacheEntries () {
return nmgr.getCacheEntries ();
/**
*
*
* @return ...
*/
public Object[] getCacheEntries() {
return nmgr.getCacheEntries();
}
public void logEvent (String msg) {
nmgr.app.logEvent (msg);
/**
*
*
* @param msg ...
*/
public void logEvent(String msg) {
nmgr.app.logEvent(msg);
}
public DbMapping getDbMapping (String name) {
return nmgr.app.getDbMapping (name);
/**
*
*
* @param name ...
*
* @return ...
*/
public DbMapping getDbMapping(String name) {
return nmgr.app.getDbMapping(name);
}
}

View file

@ -1,97 +1,240 @@
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.*;
import java.util.Date;
import org.w3c.dom.Element;
import org.w3c.dom.Document;
package helma.objectmodel.db;
import helma.objectmodel.*;
import helma.objectmodel.dom.*;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import java.io.*;
import java.util.Date;
import javax.xml.parsers.ParserConfigurationException;
import org.xml.sax.SAXException;
/**
* A simple XML-database
*/
public final class XmlDatabase implements IDatabase {
private String dbHome;
private File dbBaseDir;
private NodeManager nmgr;
private IDGenerator idgen;
private String dbHome;
private File dbBaseDir;
private NodeManager nmgr;
private IDGenerator idgen;
// character encoding to use when writing files.
// use standard encoding by default.
private String encoding = null;
// character encoding to use when writing files.
// use standard encoding by default.
private String encoding = null;
public XmlDatabase (String dbHome, String dbFilename, NodeManager nmgr) throws DatabaseException {
this.dbHome = dbHome;
this.nmgr = nmgr;
dbBaseDir = new File (dbHome);
if (!dbBaseDir.exists() && !dbBaseDir.mkdirs() )
throw new RuntimeException("Couldn't create DB-directory");
this.encoding = nmgr.app.getCharset ();
}
/**
* 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.nmgr = nmgr;
dbBaseDir = new File(dbHome);
public void shutdown () { }
public ITransaction beginTransaction () throws DatabaseException { return null; }
public void commitTransaction (ITransaction txn) throws DatabaseException { }
public void abortTransaction (ITransaction txn) throws DatabaseException { }
if (!dbBaseDir.exists() && !dbBaseDir.mkdirs()) {
throw new RuntimeException("Couldn't create DB-directory");
}
public String nextID() throws ObjectNotFoundException {
if (idgen==null) {
getIDGenerator(null);
}
return idgen.newID();
}
this.encoding = nmgr.app.getCharset();
}
public IDGenerator getIDGenerator (ITransaction txn) throws ObjectNotFoundException {
File file = new File (dbBaseDir, "idgen.xml");
this.idgen = IDGenParser.getIDGenerator(file);
return idgen;
}
/**
*
*/
public void shutdown() {
}
public void saveIDGenerator (ITransaction txn, IDGenerator idgen) throws Exception {
File file = new File (dbBaseDir, "idgen.xml");
IDGenParser.saveIDGenerator(idgen,file);
this.idgen = idgen;
}
/**
*
*
* @return ...
*
* @throws DatabaseException ...
*/
public ITransaction beginTransaction() throws DatabaseException {
return null;
}
public INode getNode (ITransaction txn, String kstr) throws Exception {
File f = new File (dbBaseDir, kstr+".xml");
if ( ! f.exists() )
throw new ObjectNotFoundException ("Object not found for key "+kstr+".");
try {
XmlDatabaseReader reader = new XmlDatabaseReader (nmgr);
Node node = reader.read (f);
return node;
} catch ( RuntimeException x ) {
nmgr.app.logEvent("error reading node from XmlDatbase: " + x.toString() );
throw new ObjectNotFoundException(x.toString());
}
}
/**
*
*
* @param txn ...
*
* @throws DatabaseException ...
*/
public void commitTransaction(ITransaction txn) throws DatabaseException {
}
public void saveNode (ITransaction txn, String kstr, INode node) throws Exception {
XmlWriter writer = null;
File file = new File (dbBaseDir,kstr+".xml");
if (encoding != null)
writer = new XmlWriter (file, encoding);
else
writer = new XmlWriter (file);
writer.setMaxLevels(1);
boolean result = writer.write((Node)node);
writer.close();
}
/**
*
*
* @param txn ...
*
* @throws DatabaseException ...
*/
public void abortTransaction(ITransaction txn) throws DatabaseException {
}
public void deleteNode (ITransaction txn, String kstr) throws Exception {
File f = new File (dbBaseDir, kstr+".xml");
f.delete();
}
/**
*
*
* @return ...
*
* @throws ObjectNotFoundException ...
*/
public String nextID() throws ObjectNotFoundException {
if (idgen == null) {
getIDGenerator(null);
}
public void setEncoding (String enc) {
this.encoding = encoding;
}
return idgen.newID();
}
public String getEncoding () {
return encoding;
}
/**
*
*
* @param txn ...
*
* @return ...
*
* @throws ObjectNotFoundException ...
*/
public IDGenerator getIDGenerator(ITransaction txn)
throws ObjectNotFoundException {
File file = new File(dbBaseDir, "idgen.xml");
this.idgen = IDGenParser.getIDGenerator(file);
return idgen;
}
/**
*
*
* @param txn ...
* @param idgen ...
*
* @throws Exception ...
*/
public void saveIDGenerator(ITransaction txn, IDGenerator idgen)
throws IOException {
File file = new File(dbBaseDir, "idgen.xml");
IDGenParser.saveIDGenerator(idgen, file);
this.idgen = idgen;
}
/**
*
*
* @param txn ...
* @param kstr ...
*
* @return ...
*
* @throws Exception ...
* @throws ObjectNotFoundException ...
*/
public INode getNode(ITransaction txn, String kstr)
throws IOException, ObjectNotFoundException,
ParserConfigurationException, SAXException {
File f = new File(dbBaseDir, kstr + ".xml");
if (!f.exists()) {
throw new ObjectNotFoundException("Object not found for key " + kstr + ".");
}
try {
XmlDatabaseReader reader = new XmlDatabaseReader(nmgr);
Node node = reader.read(f);
return node;
} catch (RuntimeException x) {
nmgr.app.logEvent("error reading node from XmlDatbase: " + x.toString());
throw new ObjectNotFoundException(x.toString());
}
}
/**
*
*
* @param txn ...
* @param kstr ...
* @param node ...
*
* @throws Exception ...
*/
public void saveNode(ITransaction txn, String kstr, INode node)
throws IOException {
XmlWriter writer = null;
File file = new File(dbBaseDir, kstr + ".xml");
if (encoding != null) {
writer = new XmlWriter(file, encoding);
} else {
writer = new XmlWriter(file);
}
writer.setMaxLevels(1);
boolean result = writer.write((Node) node);
writer.close();
}
/**
*
*
* @param txn ...
* @param kstr ...
*
* @throws Exception ...
*/
public void deleteNode(ITransaction txn, String kstr)
throws IOException {
File f = new File(dbBaseDir, kstr + ".xml");
f.delete();
}
/**
*
*
* @param enc ...
*/
public void setEncoding(String enc) {
this.encoding = encoding;
}
/**
*
*
* @return ...
*/
public String getEncoding() {
return encoding;
}
}

View file

@ -1,37 +1,80 @@
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.*;
import java.util.Date;
import org.w3c.dom.*;
package helma.objectmodel.dom;
import helma.objectmodel.ObjectNotFoundException;
import helma.objectmodel.db.IDGenerator;
import org.w3c.dom.*;
import java.io.*;
import java.util.Date;
public class IDGenParser {
/**
*
*/
public class IDGenParser {
/**
*
*
* @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");
}
public static IDGenerator getIDGenerator (File file) throws ObjectNotFoundException {
if ( ! file.exists() )
throw new ObjectNotFoundException ("IDGenerator not found in idgen.xml");
try {
Document document = XmlUtil.parse(new FileInputStream (file));
org.w3c.dom.Element tmp = (Element)document.getDocumentElement().getElementsByTagName("counter").item(0);
return new IDGenerator( Long.parseLong (XmlUtil.getTextContent(tmp)) );
} catch (Exception e) {
throw new ObjectNotFoundException(e.toString());
}
try {
Document document = XmlUtil.parse(new FileInputStream(file));
org.w3c.dom.Element tmp = (Element) document.getDocumentElement()
.getElementsByTagName("counter")
.item(0);
return new IDGenerator(Long.parseLong(XmlUtil.getTextContent(tmp)));
} catch (Exception e) {
throw new ObjectNotFoundException(e.toString());
}
}
public static IDGenerator saveIDGenerator (IDGenerator idgen, File file) throws Exception {
OutputStreamWriter out = new OutputStreamWriter (new FileOutputStream (file));
out.write ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
out.write ("<!-- printed by helma object publisher -->\n");
out.write ("<!-- created " + (new Date()).toString() + " -->\n" );
out.write ("<xmlroot>\n");
out.write (" <counter>" + idgen.getValue() + "</counter>\n");
out.write ("</xmlroot>\n");
out.close ();
return idgen;
}
}
/**
*
*
* @param idgen ...
* @param file ...
*
* @return ...
*
* @throws Exception ...
*/
public static IDGenerator saveIDGenerator(IDGenerator idgen, File file)
throws IOException {
OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(file));
out.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
out.write("<!-- printed by helma object publisher -->\n");
out.write("<!-- created " + (new Date()).toString() + " -->\n");
out.write("<xmlroot>\n");
out.write(" <counter>" + idgen.getValue() + "</counter>\n");
out.write("</xmlroot>\n");
out.close();
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;
public interface XmlConstants {
public final String NAMESPACE = "http://www.helma.org/docs/guide/features/database";
public final String DATEFORMAT = "dd.MM.yyyy HH:mm:ss z";
/**
*
*/
public interface XmlConstants {
public final String NAMESPACE = "http://www.helma.org/docs/guide/features/database";
public final String DATEFORMAT = "dd.MM.yyyy HH:mm:ss z";
}

View file

@ -1,345 +1,536 @@
/*
* 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;
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.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 {
private boolean DEBUG = false;
private boolean sparse = false;
private Properties props;
private char defaultSeparator = '_';
private char defaultSeparator = '_';
private int offset = 0;
/**
* Creates a new XmlConverter object.
*/
public XmlConverter() {
props = new SystemProperties();
props = new SystemProperties();
}
/**
* Creates a new XmlConverter object.
*
* @param propFile ...
*/
public XmlConverter(String propFile) {
props = new SystemProperties(propFile);
extractProperties(props);
props = new SystemProperties(propFile);
extractProperties(props);
}
/**
* Creates a new XmlConverter object.
*
* @param propFile ...
*/
public XmlConverter(File propFile) {
this ( propFile.getAbsolutePath() );
this(propFile.getAbsolutePath());
}
/**
* Creates a new XmlConverter object.
*
* @param props ...
*/
public XmlConverter(Properties props) {
this.props = props;
extractProperties(props);
this.props = props;
extractProperties(props);
}
public INode convert( String desc ) {
return convert(desc, new TransientNode() );
/**
*
*
* @param desc ...
*
* @return ...
*/
public INode convert(String desc) {
return convert(desc, new TransientNode());
}
public INode convert( String desc, INode helmaNode ) throws RuntimeException {
try {
return convert( new URL(desc), helmaNode );
} catch ( MalformedURLException notanurl ) {
try {
return convert( new File(desc), helmaNode );
} catch ( FileNotFoundException notfound ) {
throw new RuntimeException( "couldn't read xml: " + desc );
}
} catch ( IOException ioerror ) {
throw new RuntimeException( "couldn't read xml: " + desc );
}
/**
*
*
* @param desc ...
* @param helmaNode ...
*
* @return ...
*
* @throws RuntimeException ...
*/
public INode convert(String desc, INode helmaNode)
throws RuntimeException {
try {
return convert(new URL(desc), helmaNode);
} catch (MalformedURLException notanurl) {
try {
return convert(new File(desc), helmaNode);
} catch (FileNotFoundException notfound) {
throw new RuntimeException("couldn't read xml: " + desc);
}
} catch (IOException ioerror) {
throw new RuntimeException("couldn't read xml: " + desc);
}
}
public INode convert( File file, INode helmaNode ) throws RuntimeException, FileNotFoundException {
return convert( new FileInputStream(file), helmaNode );
/**
*
*
* @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);
}
public INode convert( URL url, INode helmaNode ) throws RuntimeException, IOException, MalformedURLException {
return convert( url.openConnection().getInputStream(), helmaNode );
/**
*
*
* @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);
}
public INode convert( InputStream in, INode helmaNode ) throws RuntimeException {
Document document = XmlUtil.parse (in);
if ( document!=null && document.getDocumentElement()!=null ) {
return convert( document.getDocumentElement(), helmaNode, new HashMap() );
} else {
return helmaNode;
}
/**
*
*
* @param in ...
* @param helmaNode ...
*
* @return ...
*
* @throws RuntimeException ...
*/
public INode convert(InputStream in, INode helmaNode)
throws RuntimeException {
Document document = XmlUtil.parse(in);
if ((document != null) && (document.getDocumentElement() != null)) {
return convert(document.getDocumentElement(), helmaNode, new HashMap());
} else {
return helmaNode;
}
}
public INode convertFromString( String xml, INode helmaNode ) throws RuntimeException {
Document document = XmlUtil.parse (new InputSource (new StringReader (xml)));
if ( document!=null && document.getDocumentElement()!=null ) {
return convert( document.getDocumentElement(), helmaNode, new HashMap() );
} else {
return helmaNode;
}
/**
*
*
* @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)));
if ((document != null) && (document.getDocumentElement() != null)) {
return convert(document.getDocumentElement(), helmaNode, new HashMap());
} else {
return helmaNode;
}
}
public INode convert( Element element, INode helmaNode, Map nodeCache ) {
offset++;
// previousNode is used to cache previous nodes with the same prototype
// so we can reset it in the nodeCache after we've run
Object previousNode = null;
if (DEBUG)
debug("reading " + element.getNodeName() );
String prototype = props.getProperty(element.getNodeName()+"._prototype");
if ( prototype == null && !sparse )
prototype = "HopObject";
// if we have a prototype (either explicit or implicit "hopobject"),
// set it on the Helma node and store it in the node cache.
if ( prototype != null ) {
helmaNode.setName( element.getNodeName() );
helmaNode.setPrototype( prototype );
previousNode = nodeCache.put (prototype, helmaNode);
}
// check attributes of the current element
attributes(element, helmaNode, nodeCache);
// check child nodes of the current element
if ( element.hasChildNodes() )
children(element, helmaNode, nodeCache);
/**
*
*
* @param element ...
* @param helmaNode ...
* @param nodeCache ...
*
* @return ...
*/
public INode convert(Element element, INode helmaNode, Map nodeCache) {
offset++;
// if it exists, restore the previous node we've replaced in the node cache.
if (previousNode != null)
nodeCache.put (prototype, previousNode);
// previousNode is used to cache previous nodes with the same prototype
// so we can reset it in the nodeCache after we've run
Object previousNode = null;
offset--;
return helmaNode;
if (DEBUG) {
debug("reading " + element.getNodeName());
}
String prototype = props.getProperty(element.getNodeName() + "._prototype");
if ((prototype == null) && !sparse) {
prototype = "HopObject";
}
// if we have a prototype (either explicit or implicit "hopobject"),
// set it on the Helma node and store it in the node cache.
if (prototype != null) {
helmaNode.setName(element.getNodeName());
helmaNode.setPrototype(prototype);
previousNode = nodeCache.put(prototype, helmaNode);
}
// check attributes of the current element
attributes(element, helmaNode, nodeCache);
// check child nodes of the current element
if (element.hasChildNodes()) {
children(element, helmaNode, nodeCache);
}
// if it exists, restore the previous node we've replaced in the node cache.
if (previousNode != null) {
nodeCache.put(prototype, previousNode);
}
offset--;
return helmaNode;
}
/**
* parse xml children and create hopobject-children
*/
private INode children( Element element, helma.objectmodel.INode helmaNode, Map nodeCache ) {
NodeList list = element.getChildNodes();
int len = list.getLength();
boolean nodeIsInitialized = !nodeCache.isEmpty();
StringBuffer textcontent = new StringBuffer();
String domKey, helmaKey;
for ( int i=0; i<len; i++ ) {
private INode children(Element element, helma.objectmodel.INode helmaNode,
Map nodeCache) {
NodeList list = element.getChildNodes();
int len = list.getLength();
boolean nodeIsInitialized = !nodeCache.isEmpty();
StringBuffer textcontent = new StringBuffer();
String domKey;
String helmaKey;
// loop through the list of children
org.w3c.dom.Node childNode = list.item(i);
for (int i = 0; i < len; i++) {
// loop through the list of children
org.w3c.dom.Node childNode = list.item(i);
// if the current node hasn't been initialized yet, try if it can
// be initialized and converted from one of the child elements.
if (!nodeIsInitialized) {
if (childNode.getNodeType() == Node.ELEMENT_NODE) {
convert ((Element) childNode, helmaNode, nodeCache);
if (helmaNode.getPrototype() != null)
return helmaNode;
}
continue;
}
// if the current node hasn't been initialized yet, try if it can
// be initialized and converted from one of the child elements.
if (!nodeIsInitialized) {
if (childNode.getNodeType() == Node.ELEMENT_NODE) {
convert((Element) childNode, helmaNode, nodeCache);
// if it's text content of this element -> append to StringBuffer
if ( childNode.getNodeType() == Node.TEXT_NODE ||
childNode.getNodeType() == Node.CDATA_SECTION_NODE ) {
textcontent.append( childNode.getNodeValue().trim() );
continue;
}
if (helmaNode.getPrototype() != null) {
return helmaNode;
}
}
// it's some kind of element (property or child)
if ( childNode.getNodeType() == Node.ELEMENT_NODE ) {
continue;
}
Element childElement = (Element)childNode;
// if it's text content of this element -> append to StringBuffer
if ((childNode.getNodeType() == Node.TEXT_NODE) ||
(childNode.getNodeType() == Node.CDATA_SECTION_NODE)) {
textcontent.append(childNode.getNodeValue().trim());
// get the basic key we have to look for in the properties-table
domKey = element.getNodeName()+"."+childElement.getNodeName();
continue;
}
// is there a childtext-2-property mapping?
if ( props!=null && props.containsKey(domKey+"._text") ) {
helmaKey = props.getProperty(domKey+"._text");
if( helmaKey.equals("") )
// if property is set but without value, read elementname for this mapping
helmaKey = childElement.getNodeName().replace(':',defaultSeparator);
if (DEBUG)
debug("childtext-2-property mapping, helmaKey " + helmaKey + " for domKey " + domKey );
// check if helmaKey contains an explicit prototype name in which to
// set the property.
int dot = helmaKey.indexOf(".");
if (dot > -1) {
String prototype = helmaKey.substring (0, dot);
INode node = (INode) nodeCache.get (prototype);
helmaKey = helmaKey.substring (dot+1);
if (node != null && node.getString(helmaKey)==null) {
node.setString (helmaKey, XmlUtil.getTextContent (childNode));
}
} else if ( helmaNode.getString(helmaKey)==null ) {
helmaNode.setString( helmaKey, XmlUtil.getTextContent(childNode) );
if (DEBUG)
debug("childtext-2-property mapping, setting " + helmaKey + " as string" );
}
continue;
}
// it's some kind of element (property or child)
if (childNode.getNodeType() == Node.ELEMENT_NODE) {
Element childElement = (Element) childNode;
// is there a simple child-2-property mapping?
// (lets the user define to use only one element and make this a property
// and simply ignore other elements of the same name)
if ( props!=null && props.containsKey(domKey+"._property") ) {
helmaKey = props.getProperty(domKey+"._property");
// if property is set but without value, read elementname for this mapping:
if ( helmaKey.equals("") )
helmaKey = childElement.getNodeName().replace(':',defaultSeparator);
if (DEBUG)
debug("child-2-property mapping, helmaKey " + helmaKey + " for domKey " + domKey);
// get the node on which to opererate, depending on the helmaKey
// value from the properties file.
INode node = helmaNode;
int dot = helmaKey.indexOf(".");
if (dot > -1) {
String prototype = helmaKey.substring (0, dot);
if (!prototype.equalsIgnoreCase (node.getPrototype()))
node = (INode) nodeCache.get (prototype);
helmaKey = helmaKey.substring (dot+1);
}
if (node == null)
continue;
// get the basic key we have to look for in the properties-table
domKey = element.getNodeName() + "." + childElement.getNodeName();
if ( node.getNode(helmaKey)==null ) {
convert( childElement, node.createNode(helmaKey), nodeCache );
if (DEBUG)
debug( "read " + childElement.toString() + node.getNode(helmaKey).toString() );
}
continue;
}
// is there a childtext-2-property mapping?
if ((props != null) && props.containsKey(domKey + "._text")) {
helmaKey = props.getProperty(domKey + "._text");
if (helmaKey.equals("")) {
// if property is set but without value, read elementname for this mapping
helmaKey = childElement.getNodeName().replace(':',
defaultSeparator);
}
// map it to one of the children-lists
helma.objectmodel.INode newHelmaNode = null;
String childrenMapping = props.getProperty(element.getNodeName()+"._children");
// do we need a mapping directly among _children of helmaNode?
// can either be through property elname._children=_all or elname._children=childname
if( childrenMapping!=null && ( 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?
helmaKey = props.getProperty(domKey);
if ( helmaKey==null && !sparse ) {
helmaKey = childElement.getNodeName().replace(':',defaultSeparator);
}
if (helmaKey == null) {
// we don't map this child element itself since we do
// sparse parsing, but there may be something of interest
// in the child's attributes and child elements.
attributes (childElement, helmaNode, nodeCache);
children (childElement, helmaNode, nodeCache);
continue;
}
if (DEBUG) {
debug("childtext-2-property mapping, helmaKey " + helmaKey +
" for domKey " + domKey);
}
// get the node on which to opererate, depending on the helmaKey
// value from the properties file.
INode node = helmaNode;
int dot = helmaKey.indexOf(".");
if (dot > -1) {
String prototype = helmaKey.substring (0, dot);
if (!prototype.equalsIgnoreCase (node.getPrototype()))
node = (INode) nodeCache.get (prototype);
helmaKey = helmaKey.substring (dot+1);
}
if (node == null)
continue;
// check if helmaKey contains an explicit prototype name in which to
// set the property.
int dot = helmaKey.indexOf(".");
// try to get the virtual node
INode worknode = null;
if ("_children".equals (helmaKey)) {
worknode = node;
} else {
worknode = node.getNode( helmaKey );
if ( worknode==null ) {
// if virtual node doesn't exist, create it
worknode = helmaNode.createNode( helmaKey );
}
}
if (DEBUG)
debug( "mounting child "+ childElement.getNodeName() + " at worknode " + worknode.toString() );
// now mount it, possibly re-using the helmaNode that's been created before
if ( newHelmaNode!=null ) {
worknode.addNode(newHelmaNode);
} else {
convert( childElement, worknode.createNode( null ), nodeCache );
}
}
// forget about other types (comments etc)
continue;
}
if (dot > -1) {
String prototype = helmaKey.substring(0, dot);
INode node = (INode) nodeCache.get(prototype);
// if there's some text content for this element, map it:
if ( textcontent.length()>0 && !sparse ) {
helmaKey = props.getProperty(element.getNodeName()+"._text");
if ( helmaKey==null )
helmaKey = "text";
if (DEBUG)
debug ("setting text "+textcontent+" to property "+helmaKey+" of object "+helmaNode);
helmaNode.setString(helmaKey, textcontent.toString().trim() );
}
helmaKey = helmaKey.substring(dot + 1);
return helmaNode;
if ((node != null) && (node.getString(helmaKey) == null)) {
node.setString(helmaKey, XmlUtil.getTextContent(childNode));
}
} else if (helmaNode.getString(helmaKey) == null) {
helmaNode.setString(helmaKey, XmlUtil.getTextContent(childNode));
if (DEBUG) {
debug("childtext-2-property mapping, setting " + helmaKey +
" as string");
}
}
continue;
}
// is there a simple child-2-property mapping?
// (lets the user define to use only one element and make this a property
// and simply ignore other elements of the same name)
if ((props != null) && props.containsKey(domKey + "._property")) {
helmaKey = props.getProperty(domKey + "._property");
// if property is set but without value, read elementname for this mapping:
if (helmaKey.equals("")) {
helmaKey = childElement.getNodeName().replace(':',
defaultSeparator);
}
if (DEBUG) {
debug("child-2-property mapping, helmaKey " + helmaKey +
" for domKey " + domKey);
}
// get the node on which to opererate, depending on the helmaKey
// value from the properties file.
INode node = helmaNode;
int dot = helmaKey.indexOf(".");
if (dot > -1) {
String prototype = helmaKey.substring(0, dot);
if (!prototype.equalsIgnoreCase(node.getPrototype())) {
node = (INode) nodeCache.get(prototype);
}
helmaKey = helmaKey.substring(dot + 1);
}
if (node == null) {
continue;
}
if (node.getNode(helmaKey) == null) {
convert(childElement, node.createNode(helmaKey), nodeCache);
if (DEBUG) {
debug("read " + childElement.toString() +
node.getNode(helmaKey).toString());
}
}
continue;
}
// map it to one of the children-lists
helma.objectmodel.INode newHelmaNode = null;
String childrenMapping = props.getProperty(element.getNodeName() +
"._children");
// do we need a mapping directly among _children of helmaNode?
// can either be through property elname._children=_all or elname._children=childname
if ((childrenMapping != null) &&
(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?
helmaKey = props.getProperty(domKey);
if ((helmaKey == null) && !sparse) {
helmaKey = childElement.getNodeName().replace(':', defaultSeparator);
}
if (helmaKey == null) {
// we don't map this child element itself since we do
// sparse parsing, but there may be something of interest
// in the child's attributes and child elements.
attributes(childElement, helmaNode, nodeCache);
children(childElement, helmaNode, nodeCache);
continue;
}
// get the node on which to opererate, depending on the helmaKey
// value from the properties file.
INode node = helmaNode;
int dot = helmaKey.indexOf(".");
if (dot > -1) {
String prototype = helmaKey.substring(0, dot);
if (!prototype.equalsIgnoreCase(node.getPrototype())) {
node = (INode) nodeCache.get(prototype);
}
helmaKey = helmaKey.substring(dot + 1);
}
if (node == null) {
continue;
}
// try to get the virtual node
INode worknode = null;
if ("_children".equals(helmaKey)) {
worknode = node;
} else {
worknode = node.getNode(helmaKey);
if (worknode == null) {
// if virtual node doesn't exist, create it
worknode = helmaNode.createNode(helmaKey);
}
}
if (DEBUG) {
debug("mounting child " + childElement.getNodeName() +
" at worknode " + worknode.toString());
}
// now mount it, possibly re-using the helmaNode that's been created before
if (newHelmaNode != null) {
worknode.addNode(newHelmaNode);
} else {
convert(childElement, worknode.createNode(null), nodeCache);
}
}
// forget about other types (comments etc)
continue;
}
// if there's some text content for this element, map it:
if ((textcontent.length() > 0) && !sparse) {
helmaKey = props.getProperty(element.getNodeName() + "._text");
if (helmaKey == null) {
helmaKey = "text";
}
if (DEBUG) {
debug("setting text " + textcontent + " to property " + helmaKey +
" of object " + helmaNode);
}
helmaNode.setString(helmaKey, textcontent.toString().trim());
}
return helmaNode;
}
/**
* set element's attributes as properties of helmaNode
*/
private INode attributes( Element element, INode helmaNode, Map nodeCache ) {
NamedNodeMap nnm = element.getAttributes();
int len = nnm.getLength();
for ( int i=0; i<len; i++ ) {
org.w3c.dom.Node attr = nnm.item(i);
String helmaKey = props.getProperty(element.getNodeName()+"._attribute."+attr.getNodeName());
// unless we only map explicit attributes, use attribute name as property name
// in case no property name was defined.
if ( helmaKey==null && !sparse)
helmaKey = attr.getNodeName().replace(':',defaultSeparator);
if (helmaKey != null) {
// check if the mapping contains the prototype to which
// the property should be applied
int dot = helmaKey.indexOf (".");
if (dot > -1) {
String prototype = helmaKey.substring (0, dot);
INode node = (INode) nodeCache.get (prototype);
if (node != null) {
node.setString (helmaKey.substring(dot+1), attr.getNodeValue());
}
} else if (helmaNode.getPrototype() != null) {
helmaNode.setString( helmaKey, attr.getNodeValue() );
}
}
}
return helmaNode;
private INode attributes(Element element, INode helmaNode, Map nodeCache) {
NamedNodeMap nnm = element.getAttributes();
int len = nnm.getLength();
for (int i = 0; i < len; i++) {
org.w3c.dom.Node attr = nnm.item(i);
String helmaKey = props.getProperty(element.getNodeName() + "._attribute." +
attr.getNodeName());
// unless we only map explicit attributes, use attribute name as property name
// in case no property name was defined.
if ((helmaKey == null) && !sparse) {
helmaKey = attr.getNodeName().replace(':', defaultSeparator);
}
if (helmaKey != null) {
// check if the mapping contains the prototype to which
// the property should be applied
int dot = helmaKey.indexOf(".");
if (dot > -1) {
String prototype = helmaKey.substring(0, dot);
INode node = (INode) nodeCache.get(prototype);
if (node != null) {
node.setString(helmaKey.substring(dot + 1), attr.getNodeValue());
}
} else if (helmaNode.getPrototype() != null) {
helmaNode.setString(helmaKey, attr.getNodeValue());
}
}
}
return helmaNode;
}
/**
* utility function
*/
private void extractProperties( Properties props ) {
if ( props.containsKey("separator") ) {
defaultSeparator = props.getProperty("separator").charAt(0);
}
sparse = "sparse".equalsIgnoreCase (props.getProperty("_mode"));
}
private void extractProperties(Properties props) {
if (props.containsKey("separator")) {
defaultSeparator = props.getProperty("separator").charAt(0);
}
sparse = "sparse".equalsIgnoreCase(props.getProperty("_mode"));
}
/** for testing */
void debug(Object msg) {
for ( int i=0; i<offset; i++ ) {
System.out.print(" ");
}
System.out.println(msg.toString());
for (int i = 0; i < offset; i++) {
System.out.print(" ");
}
System.out.println(msg.toString());
}
public static void main ( String args[] ) {
/**
*
*
* @param args ...
*/
public static void main(String[] args) {
}
}

View file

@ -1,189 +1,263 @@
/*
* 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;
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.db.DbKey;
import helma.objectmodel.db.DbMapping;
import helma.objectmodel.db.ExternalizableVector;
import helma.objectmodel.db.Node;
import helma.objectmodel.db.NodeHandle;
import helma.objectmodel.db.NodeManager;
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 {
static SAXParserFactory factory = SAXParserFactory.newInstance();
private NodeManager nmgr = null;
private Node currentNode;
private String elementType = null;
private String elementName = null;
private StringBuffer charBuffer = null;
Hashtable propMap = null;
List subnodes = null;
static SAXParserFactory factory = SAXParserFactory.newInstance ();
public XmlDatabaseReader (NodeManager nmgr) {
this.nmgr = nmgr;
/**
* Creates a new XmlDatabaseReader object.
*
* @param nmgr ...
*/
public XmlDatabaseReader(NodeManager nmgr) {
this.nmgr = nmgr;
}
/**
* read an InputSource with xml-content.
*/
public Node read (File file)
throws ParserConfigurationException, SAXException, IOException {
if (nmgr==null)
throw new RuntimeException ("can't create a new Node without a NodeManager");
public Node read(File file)
throws ParserConfigurationException, SAXException, IOException {
if (nmgr == null) {
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);
return currentNode;
parser.parse(file, this);
return currentNode;
}
/**
*
*
* @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"));
// discard the first element called xmlroot
if ("xmlroot".equals(qName) && (currentNode == null)) {
return;
}
public void startElement(String namespaceURI, String localName, String qName, Attributes atts) {
// System.err.println ("XML-READ: startElement "+namespaceURI+", "+localName+", "+qName+", "+atts.getValue("id"));
// discard the first element called xmlroot
if ("xmlroot".equals (qName) && currentNode == null)
return;
// if currentNode is null, this must be the hopobject node
if ("hopobject".equals (qName) && currentNode == null) {
String id = atts.getValue ("id");
String name = atts.getValue ("name");
String prototype = atts.getValue ("prototype");
if ( "".equals(prototype) )
prototype = "hopobject";
// if currentNode is null, this must be the hopobject node
if ("hopobject".equals(qName) && (currentNode == null)) {
String id = atts.getValue("id");
String name = atts.getValue("name");
String prototype = atts.getValue("prototype");
try {
long created = Long.parseLong (atts.getValue ("created"));
long lastmodified = Long.parseLong (atts.getValue ("lastModified"));
currentNode = new Node (name,id,prototype,nmgr.safe,created,lastmodified);
} catch ( NumberFormatException e ) {
currentNode = new Node (name,id,prototype,nmgr.safe);
}
return;
}
// find out what kind of element this is by looking at
// the number and names of attributes.
String idref = atts.getValue ("idref");
if (idref != null) {
// a hopobject reference.
NodeHandle handle = makeNodeHandle (atts);
if ("hop:child".equals (qName)) {
if (subnodes == null) {
subnodes = new ExternalizableVector ();
currentNode.setSubnodes (subnodes);
}
subnodes.add (handle);
} else if ("hop:parent".equals (qName)) {
currentNode.setParentHandle (handle);
} else {
// property name may be encoded as "propertyname" attribute,
// otherwise it is the element name
String propName = atts.getValue ("propertyname");
if (propName == null)
propName = qName;
Property prop = new Property (propName, currentNode);
prop.setNodeHandle (handle);
if (propMap == null) {
propMap = new Hashtable ();
currentNode.setPropMap (propMap);
}
propMap.put (propName.toLowerCase(), prop);
}
} else {
// a primitive property
elementType = atts.getValue ("type");
if (elementType == null)
elementType = "string";
// property name may be encoded as "propertyname" attribute,
// otherwise it is the element name
elementName = atts.getValue ("propertyname");
if (elementName == null)
elementName = qName;
if (charBuffer == null)
charBuffer = new StringBuffer();
else
charBuffer.setLength (0);
}
if ("".equals(prototype)) {
prototype = "hopobject";
}
try {
long created = Long.parseLong(atts.getValue("created"));
long lastmodified = Long.parseLong(atts.getValue("lastModified"));
currentNode = new Node(name, id, prototype, nmgr.safe, created,
lastmodified);
} catch (NumberFormatException e) {
currentNode = new Node(name, id, prototype, nmgr.safe);
}
return;
}
// find out what kind of element this is by looking at
// the number and names of attributes.
String idref = atts.getValue("idref");
if (idref != null) {
// a hopobject reference.
NodeHandle handle = makeNodeHandle(atts);
if ("hop:child".equals(qName)) {
if (subnodes == null) {
subnodes = new ExternalizableVector();
currentNode.setSubnodes(subnodes);
}
subnodes.add(handle);
} else if ("hop:parent".equals(qName)) {
currentNode.setParentHandle(handle);
} else {
// property name may be encoded as "propertyname" attribute,
// otherwise it is the element name
String propName = atts.getValue("propertyname");
if (propName == null) {
propName = qName;
}
Property prop = new Property(propName, currentNode);
prop.setNodeHandle(handle);
if (propMap == null) {
propMap = new Hashtable();
currentNode.setPropMap(propMap);
}
propMap.put(propName.toLowerCase(), prop);
}
} else {
// a primitive property
elementType = atts.getValue("type");
if (elementType == null) {
elementType = "string";
}
// property name may be encoded as "propertyname" attribute,
// otherwise it is the element name
elementName = atts.getValue("propertyname");
if (elementName == null) {
elementName = qName;
}
if (charBuffer == null) {
charBuffer = new StringBuffer();
} else {
charBuffer.setLength(0);
}
}
}
public void characters (char[] ch, int start, int length)
throws SAXException {
// 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 {
// 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)
throws SAXException {
if (elementType != null) {
Property prop = new Property (elementName, currentNode);
String charValue = charBuffer.toString ();
charBuffer.setLength (0);
if ( "boolean".equals (elementType) ) {
if ( "true".equals(charValue) ) {
prop.setBooleanValue(true);
} else {
prop.setBooleanValue(false);
}
} else if ( "date".equals(elementType) ) {
SimpleDateFormat format = new SimpleDateFormat ( DATEFORMAT );
try {
Date date = format.parse(charValue);
prop.setDateValue (date);
} catch ( ParseException e ) {
prop.setStringValue (charValue);
}
} else if ( "float".equals(elementType) ) {
prop.setFloatValue ((new Double(charValue)).doubleValue());
} else if ( "integer".equals(elementType) ) {
prop.setIntegerValue ((new Long(charValue)).longValue());
} else {
prop.setStringValue (charValue);
}
if (propMap == null) {
propMap = new Hashtable ();
currentNode.setPropMap (propMap);
}
propMap.put (elementName.toLowerCase(), prop);
elementName = null;
elementType = null;
charValue = null;
}
}
throws SAXException {
if (elementType != null) {
Property prop = new Property(elementName, currentNode);
String charValue = charBuffer.toString();
charBuffer.setLength(0);
if ("boolean".equals(elementType)) {
if ("true".equals(charValue)) {
prop.setBooleanValue(true);
} else {
prop.setBooleanValue(false);
}
} else if ("date".equals(elementType)) {
SimpleDateFormat format = new SimpleDateFormat(DATEFORMAT);
try {
Date date = format.parse(charValue);
prop.setDateValue(date);
} catch (ParseException e) {
prop.setStringValue(charValue);
}
} else if ("float".equals(elementType)) {
prop.setFloatValue((new Double(charValue)).doubleValue());
} else if ("integer".equals(elementType)) {
prop.setIntegerValue((new Long(charValue)).longValue());
} else {
prop.setStringValue(charValue);
}
if (propMap == null) {
propMap = new Hashtable();
currentNode.setPropMap(propMap);
}
propMap.put(elementName.toLowerCase(), prop);
elementName = null;
elementType = null;
charValue = null;
}
}
// create a node handle from a node reference DOM element
private NodeHandle makeNodeHandle (Attributes atts) {
String idref = atts.getValue ("idref");
String protoref = atts.getValue ("prototyperef");
DbMapping dbmap = null;
if (protoref != null)
dbmap = nmgr.getDbMapping(protoref);
return new NodeHandle (new DbKey (dbmap, idref));
private NodeHandle makeNodeHandle(Attributes atts) {
String idref = atts.getValue("idref");
String protoref = atts.getValue("prototyperef");
DbMapping dbmap = null;
if (protoref != null) {
dbmap = nmgr.getDbMapping(protoref);
}
return new NodeHandle(new DbKey(dbmap, idref));
}
}

View file

@ -1,226 +1,305 @@
/*
* 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;
import helma.objectmodel.INode;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.text.SimpleDateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Stack;
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 {
private INode rootNode, currentNode;
static SAXParserFactory factory = SAXParserFactory.newInstance();
private INode rootNode;
private INode currentNode;
private Stack nodeStack;
private HashMap convertedNodes;
private String elementType = null;
private String elementName = null;
private StringBuffer charBuffer = null;
static SAXParserFactory factory = SAXParserFactory.newInstance ();
boolean parsingHopObject;
public XmlReader () {
/**
* Creates a new XmlReader object.
*/
public XmlReader() {
}
/**
* main entry to read an xml-file.
*/
public INode read (File file, INode helmaNode)
throws ParserConfigurationException, SAXException, IOException {
try {
return read (new FileInputStream(file), helmaNode);
} catch (FileNotFoundException notfound) {
System.err.println ("couldn't find xml-file: " + file.getAbsolutePath ());
return helmaNode;
}
public INode read(File file, INode helmaNode)
throws ParserConfigurationException, SAXException, IOException {
try {
return read(new FileInputStream(file), helmaNode);
} catch (FileNotFoundException notfound) {
System.err.println("couldn't find xml-file: " + file.getAbsolutePath());
return helmaNode;
}
}
/**
* read an InputStream with xml-content.
*/
public INode read (InputStream in, INode helmaNode)
throws ParserConfigurationException, SAXException, IOException {
return read (new InputSource (in), helmaNode);
public INode read(InputStream in, INode helmaNode)
throws ParserConfigurationException, SAXException, IOException {
return read(new InputSource(in), helmaNode);
}
/**
* read an character reader with xml-content.
*/
public INode read (Reader in, INode helmaNode)
throws ParserConfigurationException, SAXException, IOException {
return read (new InputSource (in), helmaNode);
public INode read(Reader in, INode helmaNode)
throws ParserConfigurationException, SAXException, IOException {
return read(new InputSource(in), helmaNode);
}
/**
* read an InputSource with xml-content.
*/
public INode read (InputSource in, INode helmaNode)
throws ParserConfigurationException, SAXException, IOException {
if (helmaNode==null)
throw new RuntimeException ("Can't create a new Node without a root Node");
public INode read(InputSource in, INode helmaNode)
throws ParserConfigurationException, SAXException, IOException {
if (helmaNode == null) {
throw new RuntimeException("Can't create a new Node without a root Node");
}
SAXParser parser = factory.newSAXParser ();
SAXParser parser = factory.newSAXParser();
rootNode = helmaNode;
currentNode = null;
convertedNodes = new HashMap ();
nodeStack = new Stack ();
parsingHopObject = true;
rootNode = helmaNode;
currentNode = null;
convertedNodes = new HashMap();
nodeStack = new Stack();
parsingHopObject = true;
parser.parse (in, this);
return rootNode;
parser.parse(in, this);
return rootNode;
}
/**
*
*
* @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"));
// discard the first element called xmlroot
if ("xmlroot".equals(qName) && (currentNode == null)) {
return;
}
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"));
// discard the first element called xmlroot
if ("xmlroot".equals (qName) && currentNode == null)
return;
// if currentNode is null, this must be the hopobject node
String id = atts.getValue ("id");
if (id != null) {
// check if there is a current node.
if (currentNode == null) {
// If currentNode is null, this is the root node we're parsing.
currentNode = rootNode;
} else if ("hop:child".equals (qName)) {
// it's an anonymous child node
nodeStack.push (currentNode);
currentNode = currentNode.createNode (null);
} else {
// it's a named node property
nodeStack.push (currentNode);
// property name may be encoded as "propertyname" attribute,
// otherwise it is the element name
String propName = atts.getValue ("propertyname");
if (propName == null)
propName = qName;
currentNode = currentNode.createNode (propName);
}
// set the prototype on the current node and
// add it to the map of parsed nodes.
String prototype = atts.getValue ("prototype");
if ( !"".equals(prototype) && !"hopobject".equals(prototype) )
currentNode.setPrototype (prototype);
String key = id + "-" + prototype;
convertedNodes.put( key, currentNode );
return;
}
// if currentNode is null, this must be the hopobject node
String id = atts.getValue("id");
// check if we have a currentNode to set properties on,
// otherwise throw exception.
if (currentNode == null)
throw new SAXException ("Invalid XML: No valid root HopObject found");
// check if we are inside a HopObject - otherwise throw an exception
if (!parsingHopObject)
throw new SAXException ("Invalid XML: Found nested non-HobObject elements");
if (id != null) {
// check if there is a current node.
if (currentNode == null) {
// If currentNode is null, this is the root node we're parsing.
currentNode = rootNode;
} else if ("hop:child".equals(qName)) {
// it's an anonymous child node
nodeStack.push(currentNode);
currentNode = currentNode.createNode(null);
} else {
// it's a named node property
nodeStack.push(currentNode);
// if we got so far, the element is not a hopobject. Set flag to prevent
// the hopobject stack to be popped when the element
// is closed.
parsingHopObject = false;
// property name may be encoded as "propertyname" attribute,
// otherwise it is the element name
String propName = atts.getValue("propertyname");
// Is it a reference to an already parsed node?
String idref = atts.getValue ("idref");
if (idref != null) {
// a reference to a node that should have been parsed
// and lying in our cache of parsed nodes.
String prototyperef = atts.getValue ("prototyperef");
String key = idref + "-" + prototyperef;
INode n = (INode) convertedNodes.get (key);
if (n != null) {
if ("hop:child".equals (qName)) {
// add an already parsed node as child to current node
currentNode.addNode (n);
} else {
// set an already parsed node as node property to current node
// property name may be encoded as "propertyname" attribute,
// otherwise it is the element name
String propName = atts.getValue ("propertyname");
if (propName == null)
propName = qName;
currentNode.setNode (propName, n);
}
}
} else {
// It's a primitive property. Remember the property name and type
// so we can properly parse/interpret the character data when we
// get it later on.
elementType = atts.getValue ("type");
if (elementType == null)
elementType = "string";
// property name may be encoded as "propertyname" attribute,
// otherwise it is the element name
elementName = atts.getValue ("propertyname");
if (elementName == null)
elementName = qName;
if (charBuffer == null)
charBuffer = new StringBuffer();
else
charBuffer.setLength (0);
}
if (propName == null) {
propName = qName;
}
currentNode = currentNode.createNode(propName);
}
// set the prototype on the current node and
// add it to the map of parsed nodes.
String prototype = atts.getValue("prototype");
if (!"".equals(prototype) && !"hopobject".equals(prototype)) {
currentNode.setPrototype(prototype);
}
String key = id + "-" + prototype;
convertedNodes.put(key, currentNode);
return;
}
// check if we have a currentNode to set properties on,
// otherwise throw exception.
if (currentNode == null) {
throw new SAXException("Invalid XML: No valid root HopObject found");
}
// check if we are inside a HopObject - otherwise throw an exception
if (!parsingHopObject) {
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
// the hopobject stack to be popped when the element
// is closed.
parsingHopObject = false;
// Is it a reference to an already parsed node?
String idref = atts.getValue("idref");
if (idref != null) {
// a reference to a node that should have been parsed
// and lying in our cache of parsed nodes.
String prototyperef = atts.getValue("prototyperef");
String key = idref + "-" + prototyperef;
INode n = (INode) convertedNodes.get(key);
if (n != null) {
if ("hop:child".equals(qName)) {
// add an already parsed node as child to current node
currentNode.addNode(n);
} else {
// set an already parsed node as node property to current node
// property name may be encoded as "propertyname" attribute,
// otherwise it is the element name
String propName = atts.getValue("propertyname");
if (propName == null) {
propName = qName;
}
currentNode.setNode(propName, n);
}
}
} else {
// It's a primitive property. Remember the property name and type
// so we can properly parse/interpret the character data when we
// get it later on.
elementType = atts.getValue("type");
if (elementType == null) {
elementType = "string";
}
// property name may be encoded as "propertyname" attribute,
// otherwise it is the element name
elementName = atts.getValue("propertyname");
if (elementName == null) {
elementName = qName;
}
if (charBuffer == null) {
charBuffer = new StringBuffer();
} else {
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)
throws SAXException {
if (elementType != null) {
String charValue = charBuffer.toString ();
charBuffer.setLength (0);
if ( "boolean".equals (elementType) ) {
if ( "true".equals(charValue) ) {
currentNode.setBoolean(elementName, true);
} else {
currentNode.setBoolean(elementName, false);
}
} else if ( "date".equals(elementType) ) {
SimpleDateFormat format = new SimpleDateFormat ( DATEFORMAT );
try {
Date date = format.parse(charValue);
currentNode.setDate (elementName, date);
} catch ( ParseException e ) {
currentNode.setString (elementName, charValue);
}
} else if ( "float".equals(elementType) ) {
currentNode.setFloat (elementName, (new Double(charValue)).doubleValue());
} else if ( "integer".equals(elementType) ) {
currentNode.setInteger (elementName, (new Long(charValue)).longValue());
} else {
currentNode.setString (elementName, charValue);
}
elementName = null;
elementType = null;
charValue = null;
}
if (parsingHopObject && !nodeStack.isEmpty ())
currentNode = (INode) nodeStack.pop ();
else
parsingHopObject = true; // the next element end tag closes a hopobject again
throws SAXException {
if (elementType != null) {
String charValue = charBuffer.toString();
charBuffer.setLength(0);
if ("boolean".equals(elementType)) {
if ("true".equals(charValue)) {
currentNode.setBoolean(elementName, true);
} else {
currentNode.setBoolean(elementName, false);
}
} else if ("date".equals(elementType)) {
SimpleDateFormat format = new SimpleDateFormat(DATEFORMAT);
try {
Date date = format.parse(charValue);
currentNode.setDate(elementName, date);
} catch (ParseException e) {
currentNode.setString(elementName, charValue);
}
} else if ("float".equals(elementType)) {
currentNode.setFloat(elementName, (new Double(charValue)).doubleValue());
} else if ("integer".equals(elementType)) {
currentNode.setInteger(elementName, (new Long(charValue)).longValue());
} else {
currentNode.setString(elementName, charValue);
}
elementName = null;
elementType = null;
charValue = null;
}
if (parsingHopObject && !nodeStack.isEmpty()) {
currentNode = (INode) nodeStack.pop();
} else {
parsingHopObject = true; // the next element end tag closes a hopobject again
}
}
}

View file

@ -1,109 +1,161 @@
/*
* 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;
import java.io.InputStream;
import java.io.IOException;
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 helma.objectmodel.INode;
import helma.objectmodel.TransientNode;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
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 {
private static final DocumentBuilderFactory domBuilderFactory = javax.xml.parsers.DocumentBuilderFactory.newInstance();
private static final WeakHashMap domBuilders = new WeakHashMap();
public class XmlUtil {
private static synchronized DocumentBuilder getDocumentBuilder() {
DocumentBuilder domBuilder = (DocumentBuilder) domBuilders.get(Thread.currentThread());
private static final DocumentBuilderFactory domBuilderFactory = javax.xml.parsers.DocumentBuilderFactory.newInstance();
private static final WeakHashMap domBuilders = new WeakHashMap();
if (domBuilder != null) {
return domBuilder;
} else {
try {
domBuilder = domBuilderFactory.newDocumentBuilder();
domBuilders.put(Thread.currentThread(), domBuilder);
private static synchronized DocumentBuilder getDocumentBuilder() {
DocumentBuilder domBuilder = (DocumentBuilder) domBuilders.get (Thread.currentThread());
if (domBuilder != null) {
return domBuilder;
} else {
try {
domBuilder = domBuilderFactory.newDocumentBuilder();
domBuilders.put (Thread.currentThread(), domBuilder);
return domBuilder;
} catch ( ParserConfigurationException e ) {
throw new RuntimeException ("Cannot build parser: "+e.toString());
}
}
}
return domBuilder;
} catch (ParserConfigurationException e) {
throw new RuntimeException("Cannot build parser: " + e.toString());
}
}
}
public static Document newDocument() {
DocumentBuilder d = getDocumentBuilder();
return d.newDocument();
}
/**
*
*
* @return ...
*/
public static Document newDocument() {
DocumentBuilder d = getDocumentBuilder();
public static Document parse (InputStream in) throws RuntimeException {
DocumentBuilder d = getDocumentBuilder();
try {
Document doc = d.parse (in);
doc.normalize();
return doc;
} catch (SAXException e) {
throw new RuntimeException ("Bad xml-code: "+e.toString());
} catch (IOException f) {
throw new RuntimeException ("Could not read Xml: "+f.toString());
}
}
return d.newDocument();
}
public static Document parse (InputSource in) throws RuntimeException {
DocumentBuilder d = getDocumentBuilder();
try {
Document doc = d.parse (in);
doc.normalize();
return doc;
} catch (SAXException e) {
throw new RuntimeException ("Bad xml-code: "+e.toString());
} catch (IOException f) {
throw new RuntimeException ("Could not read Xml: "+f.toString());
}
}
/**
*
*
* @param in ...
*
* @return ...
*
* @throws RuntimeException ...
*/
public static Document parse(InputStream in) throws RuntimeException {
DocumentBuilder d = getDocumentBuilder();
/**
* get first "real" element (ie not the document-rootelement, but the next one
*/
public static Element getFirstElement (Document document) {
Element workelement = null;
if ( document.getDocumentElement()!=null ) {
org.w3c.dom.Node tmp = document.getDocumentElement().getFirstChild();
while( tmp!=null ) {
tmp = tmp.getNextSibling();
if ( tmp.getNodeType()==org.w3c.dom.Node.ELEMENT_NODE ) {
workelement = (Element) tmp;
break;
}
}
}
return workelement;
}
try {
Document doc = d.parse(in);
/**
* return the text content of an element
*/
public static String getTextContent( org.w3c.dom.Node element ) {
StringBuffer childtext = new StringBuffer();
NodeList childlist = element.getChildNodes();
int ct = childlist.getLength();
for ( int j=0; j<ct; j++ ) {
org.w3c.dom.Node childNode = childlist.item(j);
if ( childNode.getNodeType() == Node.TEXT_NODE ||
childNode.getNodeType() == Node.CDATA_SECTION_NODE) {
childtext.append(childNode.getNodeValue().trim() );
}
}
return childtext.toString();
}
doc.normalize();
return doc;
} catch (SAXException e) {
throw new RuntimeException("Bad xml-code: " + e.toString());
} catch (IOException f) {
throw new RuntimeException("Could not read Xml: " + f.toString());
}
}
/**
*
*
* @param in ...
*
* @return ...
*
* @throws RuntimeException ...
*/
public static Document parse(InputSource in) throws RuntimeException {
DocumentBuilder d = getDocumentBuilder();
try {
Document doc = d.parse(in);
doc.normalize();
return doc;
} catch (SAXException e) {
throw new RuntimeException("Bad xml-code: " + e.toString());
} catch (IOException f) {
throw new RuntimeException("Could not read Xml: " + f.toString());
}
}
/**
* get first "real" element (ie not the document-rootelement, but the next one
*/
public static Element getFirstElement(Document document) {
Element workelement = null;
if (document.getDocumentElement() != null) {
org.w3c.dom.Node tmp = document.getDocumentElement().getFirstChild();
while (tmp != null) {
tmp = tmp.getNextSibling();
if (tmp.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
workelement = (Element) tmp;
break;
}
}
}
return workelement;
}
/**
* return the text content of an element
*/
public static String getTextContent(org.w3c.dom.Node element) {
StringBuffer childtext = new StringBuffer();
NodeList childlist = element.getChildNodes();
int ct = childlist.getLength();
for (int j = 0; j < ct; j++) {
org.w3c.dom.Node childNode = childlist.item(j);
if ((childNode.getNodeType() == Node.TEXT_NODE) ||
(childNode.getNodeType() == Node.CDATA_SECTION_NODE)) {
childtext.append(childNode.getNodeValue().trim());
}
}
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;
// 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.FileNotFoundException;
import java.io.FileOutputStream;
@ -12,385 +37,498 @@ import java.util.Date;
import java.util.Enumeration;
import java.util.Hashtable;
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 {
private final static String LINESEPARATOR = System.getProperty("line.separator");
private static int fileid;
private Vector convertedNodes;
private int maxLevels = 3;
private String indent = " ";
private StringBuffer prefix = new StringBuffer();
private SimpleDateFormat format = new SimpleDateFormat(DATEFORMAT);
private boolean dbmode = true;
private final static String LINESEPARATOR = System.getProperty("line.separator");
// Only add encoding to XML declaration if it was explicitly set, not when we're using
// the platform's standard encoding.
private String explicitEncoding;
private Vector convertedNodes;
private int maxLevels = 3;
/**
* empty constructor, will use System.out as outputstream.
*/
public XmlWriter() {
super(System.out);
}
private String indent = " ";
private StringBuffer prefix = new StringBuffer();
/**
* Creates a new XmlWriter object.
*
* @param out ...
*/
public XmlWriter(OutputStream out) {
super(out);
}
private static int fileid;
private SimpleDateFormat format = new SimpleDateFormat ( DATEFORMAT );
/**
* Creates a new XmlWriter object.
*
* @param out ...
* @param enc ...
*
* @throws UnsupportedEncodingException ...
*/
public XmlWriter(OutputStream out, String enc) throws UnsupportedEncodingException {
super(out, enc);
explicitEncoding = enc;
}
private boolean dbmode = true;
// Only add encoding to XML declaration if it was explicitly set, not when we're using
// the platform's standard encoding.
private String explicitEncoding;
// Set of prototypes at which to stop writing.
// private Set stopTypes = null;
/**
* Creates a new XmlWriter object.
*
* @param desc ...
*
* @throws FileNotFoundException ...
*/
public XmlWriter(String desc) throws FileNotFoundException {
super(new FileOutputStream(desc));
}
/**
* create ids that can be used for temporary files.
*/
public static int generateID() {
return fileid++;
}
/**
* 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;
}
/**
* empty constructor, will use System.out as outputstream.
*/
public XmlWriter () {
super(System.out);
}
/**
* Creates a new XmlWriter object.
*
* @param file ...
*
* @throws FileNotFoundException ...
*/
public XmlWriter(File file) throws FileNotFoundException {
super(new FileOutputStream(file));
}
public XmlWriter (OutputStream out) {
super(out);
}
/**
* 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;
}
public XmlWriter (OutputStream out, String enc) throws UnsupportedEncodingException {
super(out, enc);
explicitEncoding = enc;
}
// Set of prototypes at which to stop writing.
// private Set stopTypes = null;
public XmlWriter (String desc) throws FileNotFoundException {
super (new FileOutputStream (desc));
}
/**
* create ids that can be used for temporary files.
*/
public static int generateID() {
return fileid++;
}
public XmlWriter (String desc, String enc) throws FileNotFoundException, UnsupportedEncodingException {
super (new FileOutputStream (desc), enc);
explicitEncoding = enc;
}
/**
* by default writing only descends 50 levels into the node tree to prevent
* infite loops. number can be changed here.
*/
public void setMaxLevels(int levels) {
maxLevels = levels;
}
public XmlWriter (File file) throws FileNotFoundException {
super (new FileOutputStream (file));
}
/**
*
*
* @param dbmode ...
*/
public void setDatabaseMode(boolean dbmode) {
this.dbmode = dbmode;
}
public XmlWriter (File file, String enc) throws FileNotFoundException, UnsupportedEncodingException {
super (new FileOutputStream (file), enc);
explicitEncoding = enc;
}
/**
* Set a group of prototypes at which to stop XML serialization.
*/
/**
* by default writing only descends 50 levels into the node tree to prevent
* infite loops. number can be changed here.
*/
public void setMaxLevels (int levels) {
maxLevels = levels;
}
/* public void setStopTypes (Set set) {
this.stopTypes = set;
} */
public void setDatabaseMode (boolean dbmode) {
this.dbmode = dbmode;
}
/**
* set the number of space chars
*/
public void setIndent(int ct) {
StringBuffer tmp = new StringBuffer();
/**
* Set a group of prototypes at which to stop XML serialization.
*/
/* public void setStopTypes (Set set) {
this.stopTypes = set;
} */
for (int i = 0; i < ct; i++) {
tmp.append(" ");
}
/**
* set the number of space chars
*/
public void setIndent (int ct) {
StringBuffer tmp = new StringBuffer ();
for ( int i=0; i<ct; i++ ) {
tmp.append(" ");
}
indent = tmp.toString();
}
indent = tmp.toString();
}
/**
* starting point for printing a node tree.
* creates document header too and initializes
* the cache of already converted nodes.
*/
public boolean write( INode node ) throws IOException {
convertedNodes = new Vector();
if (explicitEncoding == null)
writeln ("<?xml version=\"1.0\"?>");
else
writeln ("<?xml version=\"1.0\" encoding=\""+explicitEncoding+"\"?>");
// writeln ("<!-- printed by helma object publisher -->");
// writeln ("<!-- created " + (new Date()).toString() + " -->" );
write ("<xmlroot xmlns:hop=\"");
write (NAMESPACE);
writeln ("\">");
write (node, null, null, 0);
writeln ("</xmlroot>");
convertedNodes = null;
return true;
}
/**
* starting point for printing a node tree.
* creates document header too and initializes
* the cache of already converted nodes.
*/
public boolean write(INode node) throws IOException {
convertedNodes = new Vector();
/**
* write a hopobject and print all its properties and children.
* 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
*/
public void write (INode node, String elementName, String propName, int level) throws IOException {
if (node==null)
return;
// if (stopTypes != null && stopTypes.contains (node.getPrototype()))
// return;
int previousLength = prefix.length();
prefix.append(indent);
if ( ++level>maxLevels ) {
writeReferenceTag (node, elementName, propName);
prefix.setLength( previousLength );
return;
}
if ( convertedNodes.contains(node) ) {
writeReferenceTag (node, elementName, propName);
} else {
convertedNodes.addElement (node);
writeTagOpen (node, elementName, propName);
INode parent = node.getParent ();
if ( parent!=null ) {
writeReferenceTag (parent, "hop:parent", null);
}
writeProperties (node, level);
writeChildren (node, level);
writeTagClose (elementName);
}
prefix.setLength( previousLength );
}
if (explicitEncoding == null) {
writeln("<?xml version=\"1.0\"?>");
} else {
writeln("<?xml version=\"1.0\" encoding=\"" + explicitEncoding + "\"?>");
}
// writeln ("<!-- printed by helma object publisher -->");
// writeln ("<!-- created " + (new Date()).toString() + " -->" );
write("<xmlroot xmlns:hop=\"");
write(NAMESPACE);
writeln("\">");
write(node, null, null, 0);
writeln("</xmlroot>");
convertedNodes = null;
return true;
}
/**
* loop through properties and print them with their property-name
* as elementname
*/
private void writeProperties (INode node, int level) throws IOException {
Enumeration e = null;
if ( dbmode==true && node instanceof helma.objectmodel.db.Node ) {
// a newly constructed db.Node doesn't have a propMap,
// but returns an enumeration of all it's db-mapped properties
Hashtable props = ((Node)node).getPropMap();
if (props==null)
return;
e = props.keys();
} else {
e = node.properties();
}
while ( e.hasMoreElements() ) {
String key = (String)e.nextElement();
IProperty prop = node.get(key);
if ( prop!=null ) {
boolean validName = isValidElementName (key);
String elementName, propName;
if (validName) {
elementName = key;
propName = null;
} else {
elementName = "property";
propName = key;
}
int type = prop.getType();
if( type==IProperty.NODE ) {
write (prop.getNodeValue(), elementName, propName, level);
} else {
writeProperty (prop, elementName, propName);
}
}
}
}
/**
* write a hopobject and print all its properties and children.
* 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
*/
public void write(INode node, String elementName, String propName, int level)
throws IOException {
if (node == null) {
return;
}
/* public void writeNullProperty (String key) throws IOException {
write (prefix.toString());
write (indent);
write ("<");
write (key);
write (" type=\"null\"/>");
write (LINESEPARATOR);
} */
// if (stopTypes != null && stopTypes.contains (node.getPrototype()))
// return;
int previousLength = prefix.length();
/**
* write a single property, set attribute type according to type,
* apply xml-encoding.
*/
public void writeProperty (IProperty property, String elementName, String propName) throws IOException {
int propType = property.getType();
// we can't encode java objects in XML
if (propType == IProperty.JAVAOBJECT)
return;
write (prefix.toString());
write (indent);
write ("<");
write (elementName);
if (propName != null) {
write (" propertyname=\"");
write (HtmlEncoder.encodeXml (propName));
write ("\"");
}
switch (propType) {
case IProperty.BOOLEAN:
write (" type=\"boolean\">");
write (property.getStringValue());
break;
case IProperty.FLOAT:
write (" type=\"float\">");
write (property.getStringValue());
break;
case IProperty.INTEGER:
write (" type=\"integer\">");
write (property.getStringValue());
break;
case IProperty.DATE:
write (" type=\"date\">");
write ( format.format (property.getDateValue()) );
break;
case IProperty.STRING:
write (">");
String str = HtmlEncoder.encodeXml (property.getStringValue());
if (str != null)
write ( str );
}
write ("</");
write (elementName);
write (">");
write (LINESEPARATOR);
}
prefix.append(indent);
/**
* loop through the children-array and print them as <hop:child>
*/
private void writeChildren (INode node, int level) throws IOException {
if ( dbmode==true && node instanceof helma.objectmodel.db.Node ) {
Node dbNode = (Node)node;
DbMapping smap = dbNode.getDbMapping() == null ? null : dbNode.getDbMapping().getSubnodeMapping ();
if (smap != null && smap.isRelational ())
return;
}
Enumeration e = node.getSubnodes();
while (e.hasMoreElements()) {
INode nextNode = (INode)e.nextElement();
write (nextNode, "hop:child", null, level);
}
}
if (++level > maxLevels) {
writeReferenceTag(node, elementName, propName);
prefix.setLength(previousLength);
/**
* write an opening tag for a node. Include id and prototype, use a
* name if parameter is non-empty.
*/
public void writeTagOpen (INode node, String name, String propName) throws IOException {
write (prefix.toString());
write ("<");
write ( (name==null)?"hopobject" : name);
write (" id=\"");
write (getNodeIdentifier(node));
if (propName != null) {
write ("\" propertyname=\"");
write (HtmlEncoder.encodeXml (propName));
}
write ("\" name=\"");
write (node.getName());
write ("\" prototype=\"");
write (getNodePrototype(node));
write ("\" created=\"");
write (Long.toString(node.created()));
write ("\" lastModified=\"");
write (Long.toString(node.lastModified()));
//FIXME: do we need anonymous-property?
write ("\">");
write (LINESEPARATOR);
}
return;
}
/**
* write a closing tag for a node
* e.g. </root>
*/
public void writeTagClose (String name) throws IOException {
write (prefix.toString());
write ("</");
write ( (name==null)?"hopobject" : name);
write (">");
write (LINESEPARATOR);
}
if (convertedNodes.contains(node)) {
writeReferenceTag(node, elementName, propName);
} else {
convertedNodes.addElement(node);
writeTagOpen(node, elementName, propName);
/**
* write a tag holding a reference to an element that has
* been written out before.
* e.g. <parent idref="35" prototyperef="hopobject"/>
*/
public void writeReferenceTag (INode node, String name, String propName) throws IOException {
write (prefix.toString());
write ("<");
write ( (name==null)?"hopobject" : name);
write ( " idref=\"");
write (getNodeIdentifier(node));
if (propName != null) {
write ("\" propertyname=\"");
write (HtmlEncoder.encodeXml (propName));
}
write ("\" prototyperef=\"");
write (getNodePrototype(node));
write ("\"/>");
write (LINESEPARATOR);
}
INode parent = node.getParent();
/**
* retrieve prototype-string of a node, defaults to "hopobject"
*/
private String getNodePrototype( INode node ) {
if ( node.getPrototype()==null || "".equals(node.getPrototype()) ) {
return "hopobject";
} else {
return node.getPrototype();
}
}
if (parent != null) {
writeReferenceTag(parent, "hop:parent", null);
}
/**
* TransientNode produces a different ID each time we call the getID()-method
* this is a workaround and uses hashCode if INode stands for a TransientNode.
*/
private String getNodeIdentifier( INode node ) {
try {
TransientNode tmp = (TransientNode)node;
return Integer.toString( tmp.hashCode() );
} catch ( ClassCastException e ) {
return node.getID();
}
}
writeProperties(node, level);
writeChildren(node, level);
writeTagClose(elementName);
}
public void writeln(String str) throws IOException {
write (str);
write (LINESEPARATOR);
}
prefix.setLength(previousLength);
}
/**
* 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
* conservative here, preferring to return false rather too often than
* not enough.
*/
private boolean isValidElementName (String str) {
char c = str.charAt (0);
if (!Character.isLetter(c))
return false;
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;
}
/**
* loop through properties and print them with their property-name
* as elementname
*/
private void writeProperties(INode node, int level)
throws IOException {
Enumeration e = null;
if ((dbmode == true) && node instanceof helma.objectmodel.db.Node) {
// a newly constructed db.Node doesn't have a propMap,
// but returns an enumeration of all it's db-mapped properties
Hashtable props = ((Node) node).getPropMap();
if (props == null) {
return;
}
e = props.keys();
} else {
e = node.properties();
}
while (e.hasMoreElements()) {
String key = (String) e.nextElement();
IProperty prop = node.get(key);
if (prop != null) {
boolean validName = isValidElementName(key);
String elementName;
String propName;
if (validName) {
elementName = key;
propName = null;
} else {
elementName = "property";
propName = key;
}
int type = prop.getType();
if (type == IProperty.NODE) {
write(prop.getNodeValue(), elementName, propName, level);
} else {
writeProperty(prop, elementName, propName);
}
}
}
}
/* public void writeNullProperty (String key) throws IOException {
write (prefix.toString());
write (indent);
write ("<");
write (key);
write (" type=\"null\"/>");
write (LINESEPARATOR);
} */
/**
* write a single property, set attribute type according to type,
* apply xml-encoding.
*/
public void writeProperty(IProperty property, String elementName, String propName)
throws IOException {
int propType = property.getType();
// we can't encode java objects in XML
if (propType == IProperty.JAVAOBJECT) {
return;
}
write(prefix.toString());
write(indent);
write("<");
write(elementName);
if (propName != null) {
write(" propertyname=\"");
write(HtmlEncoder.encodeXml(propName));
write("\"");
}
switch (propType) {
case IProperty.BOOLEAN:
write(" type=\"boolean\">");
write(property.getStringValue());
break;
case IProperty.FLOAT:
write(" type=\"float\">");
write(property.getStringValue());
break;
case IProperty.INTEGER:
write(" type=\"integer\">");
write(property.getStringValue());
break;
case IProperty.DATE:
write(" type=\"date\">");
write(format.format(property.getDateValue()));
break;
case IProperty.STRING:
write(">");
String str = HtmlEncoder.encodeXml(property.getStringValue());
if (str != null) {
write(str);
}
}
write("</");
write(elementName);
write(">");
write(LINESEPARATOR);
}
/**
* loop through the children-array and print them as <hop:child>
*/
private void writeChildren(INode node, int level) throws IOException {
if ((dbmode == true) && node instanceof helma.objectmodel.db.Node) {
Node dbNode = (Node) node;
DbMapping smap = (dbNode.getDbMapping() == null) ? null
: dbNode.getDbMapping()
.getSubnodeMapping();
if ((smap != null) && smap.isRelational()) {
return;
}
}
Enumeration e = node.getSubnodes();
while (e.hasMoreElements()) {
INode nextNode = (INode) e.nextElement();
write(nextNode, "hop:child", null, level);
}
}
/**
* write an opening tag for a node. Include id and prototype, use a
* name if parameter is non-empty.
*/
public void writeTagOpen(INode node, String name, String propName)
throws IOException {
write(prefix.toString());
write("<");
write((name == null) ? "hopobject" : name);
write(" id=\"");
write(getNodeIdentifier(node));
if (propName != null) {
write("\" propertyname=\"");
write(HtmlEncoder.encodeXml(propName));
}
write("\" name=\"");
write(node.getName());
write("\" prototype=\"");
write(getNodePrototype(node));
write("\" created=\"");
write(Long.toString(node.created()));
write("\" lastModified=\"");
write(Long.toString(node.lastModified()));
//FIXME: do we need anonymous-property?
write("\">");
write(LINESEPARATOR);
}
/**
* write a closing tag for a node
* e.g. </root>
*/
public void writeTagClose(String name) throws IOException {
write(prefix.toString());
write("</");
write((name == null) ? "hopobject" : name);
write(">");
write(LINESEPARATOR);
}
/**
* write a tag holding a reference to an element that has
* been written out before.
* e.g. <parent idref="35" prototyperef="hopobject"/>
*/
public void writeReferenceTag(INode node, String name, String propName)
throws IOException {
write(prefix.toString());
write("<");
write((name == null) ? "hopobject" : name);
write(" idref=\"");
write(getNodeIdentifier(node));
if (propName != null) {
write("\" propertyname=\"");
write(HtmlEncoder.encodeXml(propName));
}
write("\" prototyperef=\"");
write(getNodePrototype(node));
write("\"/>");
write(LINESEPARATOR);
}
/**
* retrieve prototype-string of a node, defaults to "hopobject"
*/
private String getNodePrototype(INode node) {
if ((node.getPrototype() == null) || "".equals(node.getPrototype())) {
return "hopobject";
} else {
return node.getPrototype();
}
}
/**
* TransientNode produces a different ID each time we call the getID()-method
* this is a workaround and uses hashCode if INode stands for a TransientNode.
*/
private String getNodeIdentifier(INode node) {
try {
TransientNode tmp = (TransientNode) node;
return Integer.toString(tmp.hashCode());
} catch (ClassCastException e) {
return node.getID();
}
}
/**
*
*
* @param str ...
*
* @throws IOException ...
*/
public void writeln(String str) throws IOException {
write(str);
write(LINESEPARATOR);
}
/**
* 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
* conservative here, preferring to return false rather too often than
* not enough.
*/
private boolean isValidElementName(String str) {
char c = str.charAt(0);
if (!Character.isLetter(c)) {
return false;
}
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;
import java.util.Vector;
import java.util.Iterator;
import java.io.*;
import helma.framework.*;
import helma.framework.core.*;
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
@ -17,114 +29,178 @@ import helma.util.Updatable;
* usually represented by a file with extension .hac (hop action file)
* that contains the raw body of the function.
*/
public class ActionFile implements Updatable {
String name, sourceName;
String name;
String sourceName;
Prototype prototype;
Application app;
File file;
String content;
long lastmod;
public ActionFile (File file, String name, Prototype proto) {
this.prototype = proto;
this.app = proto.getApplication ();
this.name = name;
this.sourceName = file.getParentFile().getName()+"/"+file.getName();
this.file = file;
this.lastmod = file.lastModified ();
this.content = null;
/**
* Creates a new ActionFile object.
*
* @param file ...
* @param name ...
* @param proto ...
*/
public ActionFile(File file, String name, Prototype proto) {
this.prototype = proto;
this.app = proto.getApplication();
this.name = name;
this.sourceName = file.getParentFile().getName() + "/" + file.getName();
this.file = file;
this.lastmod = file.lastModified();
this.content = null;
}
public ActionFile (String content, String name, String sourceName, Prototype proto) {
this.prototype = proto;
this.app = proto.getApplication ();
this.name = name;
this.sourceName = sourceName;
this.file = null;
this.content = content;
/**
* Creates a new ActionFile object.
*
* @param content ...
* @param name ...
* @param sourceName ...
* @param proto ...
*/
public ActionFile(String content, String name, String sourceName, Prototype proto) {
this.prototype = proto;
this.app = proto.getApplication();
this.name = name;
this.sourceName = sourceName;
this.file = null;
this.content = content;
}
/**
* Tell the type manager whether we need an update. this is the case when
* the file has been modified or deleted.
*/
public boolean needsUpdate () {
return lastmod != file.lastModified ();
public boolean needsUpdate() {
return lastmod != file.lastModified();
}
public void update () {
if (!file.exists ()) {
// remove functions declared by this from all object prototypes
remove ();
} else {
lastmod = file.lastModified ();
}
/**
*
*/
public void update() {
if (!file.exists()) {
// remove functions declared by this from all object prototypes
remove();
} else {
lastmod = file.lastModified();
}
}
public void remove () {
prototype.removeActionFile (this);
/**
*
*/
public void remove() {
prototype.removeActionFile(this);
}
public File getFile () {
return file;
/**
*
*
* @return ...
*/
public File getFile() {
return file;
}
public String getName () {
return name;
/**
*
*
* @return ...
*/
public String getName() {
return name;
}
public String getSourceName () {
return sourceName;
/**
*
*
* @return ...
*/
public String getSourceName() {
return sourceName;
}
public Reader getReader () throws FileNotFoundException {
if (content != null)
return new StringReader (content);
else if (file.length() == 0)
return new StringReader(";");
else
return new FileReader (file);
/**
*
*
* @return ...
*
* @throws FileNotFoundException ...
*/
public Reader getReader() throws FileNotFoundException {
if (content != null) {
return new StringReader(content);
} else if (file.length() == 0) {
return new StringReader(";");
} else {
return new FileReader(file);
}
}
public String getContent () {
if (content != null)
return content;
else {
try {
FileReader reader = new FileReader (file);
char cbuf[] = new char[(int) file.length ()];
reader.read (cbuf);
reader.close ();
return new String (cbuf);
} catch (Exception filex) {
app.logEvent ("Error reading "+this+": "+filex);
return null;
}
}
/**
*
*
* @return ...
*/
public String getContent() {
if (content != null) {
return content;
} else {
try {
FileReader reader = new FileReader(file);
char[] cbuf = new char[(int) file.length()];
reader.read(cbuf);
reader.close();
return new String(cbuf);
} catch (Exception filex) {
app.logEvent("Error reading " + this + ": " + filex);
return null;
}
}
}
public String getFunctionName () {
return name + "_action";
/**
*
*
* @return ...
*/
public String getFunctionName() {
return name + "_action";
}
public Prototype getPrototype () {
return prototype;
/**
*
*
* @return ...
*/
public Prototype getPrototype() {
return prototype;
}
public Application getApplication () {
return app;
/**
*
*
* @return ...
*/
public Application getApplication() {
return app;
}
public String toString () {
return "ActionFile["+sourceName+"]";
/**
*
*
* @return ...
*/
public String toString() {
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;
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.core.*;
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.
*/
public class FunctionFile implements Updatable {
Prototype prototype;
Application app;
File file;
@ -27,13 +36,18 @@ public class FunctionFile implements Updatable {
String content;
long lastmod;
public FunctionFile (File file, Prototype proto) {
this.prototype = proto;
this.app = proto.getApplication ();
this.sourceName = file.getParentFile().getName()+"/"+file.getName();
this.file = file;
update ();
/**
* Creates a new FunctionFile object.
*
* @param file ...
* @param proto ...
*/
public FunctionFile(File file, Prototype proto) {
this.prototype = proto;
this.app = proto.getApplication();
this.sourceName = file.getParentFile().getName() + "/" + file.getName();
this.file = file;
update();
}
/**
@ -41,55 +55,75 @@ public class FunctionFile implements Updatable {
* files contained in zipped applications. The whole update mechanism is bypassed
* by immediately parsing the code.
*/
public FunctionFile (String body, String sourceName, Prototype proto) {
this.prototype = proto;
this.app = proto.getApplication ();
this.sourceName = sourceName;
this.file = null;
this.content = body;
public FunctionFile(String body, String sourceName, Prototype proto) {
this.prototype = proto;
this.app = proto.getApplication();
this.sourceName = sourceName;
this.file = null;
this.content = body;
}
/**
* Tell the type manager whether we need an update. this is the case when
* the file has been modified or deleted.
*/
public boolean needsUpdate () {
return file != null && lastmod != file.lastModified ();
public boolean needsUpdate() {
return (file != null) && (lastmod != file.lastModified());
}
public void update () {
if (file != null) {
if (!file.exists ()) {
remove ();
} else {
lastmod = file.lastModified ();
}
}
/**
*
*/
public void update() {
if (file != null) {
if (!file.exists()) {
remove();
} else {
lastmod = file.lastModified();
}
}
}
public File getFile () {
return file;
/**
*
*
* @return ...
*/
public File getFile() {
return file;
}
public String getContent () {
return content;
/**
*
*
* @return ...
*/
public String getContent() {
return content;
}
public String getSourceName () {
return sourceName;
/**
*
*
* @return ...
*/
public String getSourceName() {
return sourceName;
}
public void remove () {
prototype.removeFunctionFile (this);
/**
*
*/
public void remove() {
prototype.removeFunctionFile(this);
}
public String toString () {
return sourceName;
/**
*
*
* @return ...
*/
public String toString() {
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;
@ -7,73 +20,69 @@ import helma.framework.IPathElement;
import helma.framework.core.Application;
import helma.framework.core.Prototype;
import helma.framework.core.RequestEvaluator;
import java.util.*;
import java.io.File;
import java.util.*;
/**
* This is the interface that must be implemented to make a scripting environment
* usable by the Helma application server.
*
* Implementations of this interface must have a public zero-argument constructor
* Implementations of this interface must have a public zero-argument constructor
* to be usable by the Helma framework.
*/
public interface ScriptingEngine {
/**
/**
* Init the scripting engine with an application and a request evaluator
*/
public void init (Application app, RequestEvaluator reval);
public void init(Application app, RequestEvaluator reval);
/**
* This method is called before an execution context for a request
* evaluation is entered to let the Engine know it should update
* evaluation is entered to let the Engine know it should update
* its prototype information
*/
public void updatePrototypes ();
public void updatePrototypes();
/**
* This method is called when an execution context for a request
* evaluation is entered. The globals parameter contains the global values
* to be applied during this execution context.
*/
public void enterContext (HashMap globals) throws ScriptingException;
public void enterContext(HashMap globals) throws ScriptingException;
/**
* This method is called to let the scripting engine know that the current
* execution context has terminated.
*/
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.
*/
public Object invoke (Object thisObject, String functionName, Object[] args, boolean xmlrpc)
throws ScriptingException;
public Object invoke(Object thisObject, String functionName, Object[] args,
boolean xmlrpc) throws ScriptingException;
/**
* Let the evaluator know that the current evaluation has been aborted.
*/
public void abort ();
public void abort();
/**
* Get a property on an object
*/
public Object get (Object thisObject, String key);
public Object get(Object thisObject, String key);
/**
* Return true if a function by that name is defined for that object.
*/
public boolean hasFunction (Object thisObject, String functionName);
public boolean hasFunction(Object thisObject, String functionName);
/**
* Get an IPathElement that offers introspection services into the application.
* If this method returns null, no introspection is available for this kind of engine.
* In order to be compatible with the standard Helma management application, this
* In order to be compatible with the standard Helma management application, this
* class should be compatible with helma.doc.DocApplication.
*/
public IPathElement getIntrospector ();
public IPathElement getIntrospector();
}

View file

@ -1,67 +1,105 @@
// 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;
import java.io.PrintWriter;
import java.io.PrintStream;
import java.io.PrintWriter;
/**
* The base class for exceptions thrown by Helma scripting package
*/
public class ScriptingException extends Exception {
Exception wrapped;
/**
* Construct a ScriptingException given an error message
*/
public ScriptingException (String msg) {
super (msg);
wrapped = null;
public ScriptingException(String msg) {
super(msg);
wrapped = null;
}
/**
* Construct a ScriptingException given an error message
*/
public ScriptingException (Exception w) {
wrapped = w;
public ScriptingException(Exception w) {
wrapped = w;
}
public String toString () {
if (wrapped == null)
return super.toString ();
else
return wrapped.toString ();
/**
*
*
* @return ...
*/
public String toString() {
if (wrapped == null) {
return super.toString();
} else {
return wrapped.toString();
}
}
public String getMessage () {
if (wrapped == null)
return super.getMessage ();
else
return wrapped.getMessage ();
/**
*
*
* @return ...
*/
public String getMessage() {
if (wrapped == null) {
return super.getMessage();
} else {
return wrapped.getMessage();
}
}
public void printStackTrace () {
if (wrapped == null)
super.printStackTrace ();
else
wrapped.printStackTrace ();
/**
*
*/
public void printStackTrace() {
if (wrapped == null) {
super.printStackTrace();
} else {
wrapped.printStackTrace();
}
}
public void printStackTrace (PrintStream stream) {
if (wrapped == null)
super.printStackTrace (stream);
else
wrapped.printStackTrace (stream);
/**
*
*
* @param stream ...
*/
public void printStackTrace(PrintStream stream) {
if (wrapped == null) {
super.printStackTrace(stream);
} else {
wrapped.printStackTrace(stream);
}
}
public void printStackTrace (PrintWriter writer) {
if (wrapped == null)
super.printStackTrace (writer);
else
wrapped.printStackTrace (writer);
/**
*
*
* @param writer ...
*/
public void printStackTrace(PrintWriter writer) {
if (wrapped == null) {
super.printStackTrace(writer);
} else {
wrapped.printStackTrace(writer);
}
}
}

View file

@ -1,187 +1,239 @@
// 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;
import java.io.*;
import java.util.Vector;
import java.util.Iterator;
import java.util.StringTokenizer;
import helma.framework.*;
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
* (Helma server page) that contains both parts that are to be evaluated
* as EcmaScript and parts that are to be delivered to the client as-is.
* Internally, templates are regular functions.
* Internally, templates are regular functions.
* Helma templates are callable via URL, but this is just a leftover from the
* days when there were no .hac (action) files. The recommended way
* now is to have a .hac file with all the logic which in turn calls one or more
* template files to do the formatting.
*/
public class Template extends ActionFile {
public Template (File file, String name, Prototype proto) {
super (file, name, proto);
/**
* Creates a new Template object.
*
* @param file ...
* @param name ...
* @param proto ...
*/
public Template(File file, String name, Prototype proto) {
super(file, name, proto);
}
public Template (String content, String name, String sourceName, Prototype proto) {
super (content, name, sourceName, proto);
/**
* Creates a new Template object.
*
* @param content ...
* @param name ...
* @param sourceName ...
* @param proto ...
*/
public Template(String content, String name, String sourceName, Prototype proto) {
super(content, name, sourceName, proto);
}
public String getFunctionName () {
return name;
/**
*
*
* @return ...
*/
public String getFunctionName() {
return name;
}
public Reader getReader () {
return new StringReader(getContent());
/**
*
*
* @return ...
*/
public Reader getReader() {
return new StringReader(getContent());
}
public String getContent () {
/**
*
*
* @return ...
*/
public String getContent() {
Vector partBuffer = new Vector();
String cstring = super.getContent();
char[] cnt = cstring.toCharArray();
int l = cnt.length;
Vector partBuffer = new Vector ();
String cstring = super.getContent();
char[] cnt = cstring.toCharArray ();
int l = cnt.length;
if (l == 0)
return "";
if (l == 0) {
return "";
}
// if last charackter is whitespace, swallow it. this is necessary for some inner templates to look ok.
if (Character.isWhitespace (cnt[l-1]))
l -= 1;
// if last charackter is whitespace, swallow it. this is necessary for some inner templates to look ok.
if (Character.isWhitespace(cnt[l - 1])) {
l -= 1;
}
int lastIdx = 0;
for (int i = 0; i < l-1; i++) {
if (cnt[i] == '<' && cnt[i+1] == '%') {
int j = i+2;
while (j < l-1 && (cnt[j] != '%' || cnt[j+1] != '>')) {
j++;
}
if (j > i+2) {
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);
partBuffer.addElement (new Part (this, script, false));
lastIdx = j+2;
}
i = j+1;
}
}
if (lastIdx < l)
partBuffer.addElement (new Part (this, new String (cnt, lastIdx, l - lastIdx), true));
int lastIdx = 0;
StringBuffer templateBody = new StringBuffer ();
int nparts = partBuffer.size();
for (int i = 0; i < (l - 1); i++) {
if ((cnt[i] == '<') && (cnt[i + 1] == '%')) {
int j = i + 2;
for (int k = 0; k < nparts; k++) {
Part nextPart = (Part) partBuffer.elementAt (k);
while ((j < (l - 1)) && ((cnt[j] != '%') || (cnt[j + 1] != '>'))) {
j++;
}
if (nextPart.isStatic || nextPart.content.trim ().startsWith ("=")) {
// check for <%= ... %> statements
if (!nextPart.isStatic) {
nextPart.content = nextPart.content.trim ().substring (1).trim ();
// cut trailing ";"
while (nextPart.content.endsWith (";"))
nextPart.content = nextPart.content.substring (0, nextPart.content.length()-1);
}
if (j > (i + 2)) {
if ((i - lastIdx) > 0) {
partBuffer.addElement(new Part(this,
new String(cnt, lastIdx,
i - lastIdx), true));
}
StringTokenizer st = new StringTokenizer (nextPart.content, "\r\n", true);
String nextLine = st.hasMoreTokens () ? st.nextToken () : null;
String script = new String(cnt, i + 2, (j - i) - 2);
// count newLines we "swallow", see explanation below
int newLineCount = 0;
partBuffer.addElement(new Part(this, script, false));
lastIdx = j + 2;
}
templateBody.append ("res.write (");
if (nextPart.isStatic) {
templateBody.append ("\"");
}
i = j + 1;
}
}
while (nextLine != null) {
if (lastIdx < l) {
partBuffer.addElement(new Part(this, new String(cnt, lastIdx, l - lastIdx),
true));
}
if ("\n".equals (nextLine)) {
// append a CRLF
newLineCount++;
templateBody.append ("\\r\\n");
} else if (!"\r".equals (nextLine)) try {
StringReader lineReader = new StringReader (nextLine);
int c = lineReader.read ();
while (c > -1) {
if (nextPart.isStatic && ((char)c == '"' || (char)c == '\\')) {
templateBody.append ('\\');
}
templateBody.append ((char) c);
c = lineReader.read ();
}
} catch (IOException srx) {}
StringBuffer templateBody = new StringBuffer();
int nparts = partBuffer.size();
nextLine = st.hasMoreTokens () ? st.nextToken () : null;
for (int k = 0; k < nparts; k++) {
Part nextPart = (Part) partBuffer.elementAt(k);
}
if (nextPart.isStatic || nextPart.content.trim().startsWith("=")) {
// check for <%= ... %> statements
if (!nextPart.isStatic) {
nextPart.content = nextPart.content.trim().substring(1).trim();
if (nextPart.isStatic) {
templateBody.append ("\"");
}
// cut trailing ";"
while (nextPart.content.endsWith(";"))
nextPart.content = nextPart.content.substring(0,
nextPart.content.length() -
1);
}
templateBody.append ("); ");
StringTokenizer st = new StringTokenizer(nextPart.content, "\r\n", true);
String nextLine = st.hasMoreTokens() ? st.nextToken() : null;
// append the number of lines we have "swallowed" into
// one write statement, so error messages will *approximately*
// give correct line numbers.
for (int i=0; i<newLineCount; i++) {
templateBody.append ("\r\n");
}
// count newLines we "swallow", see explanation below
int newLineCount = 0;
} else {
templateBody.append (nextPart.content);
if (!nextPart.content.trim ().endsWith (";")) {
templateBody.append (";");
}
}
}
// templateBody.append ("\r\nreturn null;\r\n");
templateBody.append("res.write (");
return templateBody.toString ();
if (nextPart.isStatic) {
templateBody.append("\"");
}
while (nextLine != null) {
if ("\n".equals(nextLine)) {
// append a CRLF
newLineCount++;
templateBody.append("\\r\\n");
} else if (!"\r".equals(nextLine)) {
try {
StringReader lineReader = new StringReader(nextLine);
int c = lineReader.read();
while (c > -1) {
if (nextPart.isStatic &&
(((char) c == '"') || ((char) c == '\\'))) {
templateBody.append('\\');
}
templateBody.append((char) c);
c = lineReader.read();
}
} catch (IOException srx) {
}
}
nextLine = st.hasMoreTokens() ? st.nextToken() : null;
}
if (nextPart.isStatic) {
templateBody.append("\"");
}
templateBody.append("); ");
// append the number of lines we have "swallowed" into
// one write statement, so error messages will *approximately*
// give correct line numbers.
for (int i = 0; i < newLineCount; i++) {
templateBody.append("\r\n");
}
} else {
templateBody.append(nextPart.content);
if (!nextPart.content.trim().endsWith(";")) {
templateBody.append(";");
}
}
}
// templateBody.append ("\r\nreturn null;\r\n");
return templateBody.toString();
}
public void remove () {
prototype.removeTemplate (this);
/**
*
*/
public void remove() {
prototype.removeTemplate(this);
}
class Part {
String content;
Template parent;
boolean isPart;
boolean isStatic;
String content;
Template parent;
boolean isPart;
boolean isStatic;
public Part(Template parent, String content, boolean isStatic) {
isPart = false;
this.parent = parent;
this.content = content;
this.isStatic = isStatic;
}
public String getName() {
return isStatic ? null : content;
}
public Part (Template parent, String content, boolean isStatic) {
isPart = false;
this.parent = parent;
this.content = content;
this.isStatic = isStatic;
}
public String getName () {
return isStatic ? null : content;
}
public String toString () {
return "Template.Part ["+content+","+isStatic+"]";
}
public String toString() {
return "Template.Part [" + content + "," + isStatic + "]";
}
}
}

View file

@ -1,65 +1,98 @@
/*
* 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;
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.ESValue;
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.
*/
public class ESBeanWrapper extends ESWrapper {
FesiEngine engine;
public ESBeanWrapper (Object object, FesiEngine engine) {
super (object, engine.getEvaluator(),true);
this.engine = engine;
/**
* Creates a new ESBeanWrapper object.
*
* @param object ...
* @param engine ...
*/
public ESBeanWrapper(Object object, FesiEngine engine) {
super(object, engine.getEvaluator(), true);
this.engine = engine;
}
/**
* Wrap getProperty, return ESNode if INode would be returned,
* ESMapWrapper if Map would be returned.
*/
public ESValue getProperty(String propertyName, int hash) throws EcmaScriptException {
try {
ESValue val = super.getProperty (propertyName, hash);
if (val instanceof ESWrapper) {
Object theObject = ((ESWrapper)val).getJavaObject ();
if (val instanceof ESWrapper && theObject instanceof INode) {
return engine.getNodeWrapper ((INode) theObject);
} else if (val instanceof ESWrapper && theObject instanceof Map) {
ESMapWrapper wrapper = new ESMapWrapper(engine, (Map) theObject);
if (theObject instanceof SystemProperties && super.getJavaObject () instanceof ApplicationBean)
wrapper.setReadonly(true);
return wrapper;
/**
* Wrap getProperty, return ESNode if INode would be returned,
* ESMapWrapper if Map would be returned.
*/
public ESValue getProperty(String propertyName, int hash)
throws EcmaScriptException {
try {
ESValue val = super.getProperty(propertyName, hash);
if (val instanceof ESWrapper) {
Object theObject = ((ESWrapper) val).getJavaObject();
if (val instanceof ESWrapper && theObject instanceof INode) {
return engine.getNodeWrapper((INode) theObject);
} else if (val instanceof ESWrapper && theObject instanceof Map) {
ESMapWrapper wrapper = new ESMapWrapper(engine, (Map) theObject);
if (theObject instanceof SystemProperties &&
super.getJavaObject() instanceof ApplicationBean) {
wrapper.setReadonly(true);
}
return wrapper;
}
}
}
return val;
} catch (Exception rte) {
return ESNull.theNull;
}
}
public void putProperty(String propertyName, ESValue propertyValue, int hash) throws EcmaScriptException {
try {
super.putProperty (propertyName, propertyValue, hash);
} catch (Exception rte) {
// create a nice error message
throw new EcmaScriptException("can't set property " + propertyName +
" to this value on " + getJavaObject().toString() );
}
return val;
} catch (Exception rte) {
return ESNull.theNull;
}
}
/**
*
*
* @param propertyName ...
* @param propertyValue ...
* @param hash ...
*
* @throws EcmaScriptException ...
*/
public void putProperty(String propertyName, ESValue propertyValue, int hash)
throws EcmaScriptException {
try {
super.putProperty(propertyName, propertyValue, hash);
} catch (Exception rte) {
// create a nice error message
throw new EcmaScriptException("can't set property " + propertyName +
" to this value on " +
getJavaObject().toString());
}
}
}

View file

@ -1,109 +1,236 @@
// 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;
import helma.framework.core.*;
import helma.framework.IPathElement;
import FESI.Interpreter.*;
import FESI.Exceptions.*;
import FESI.Data.*;
import FESI.Exceptions.*;
import FESI.Interpreter.*;
import helma.framework.IPathElement;
import helma.framework.core.*;
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 {
ESWrapper wrapper;
Object wrappedObject;
public ESGenericObject (ESObject prototype, Evaluator evaluator, Object obj) {
super (prototype, evaluator);
wrappedObject = obj;
wrapper = new ESWrapper (obj, evaluator);
}
public String getESClassName () {
return "GenericObject";
}
public String toString () {
return wrappedObject.toString ();
}
public String toDetailString () {
return wrapper.toDetailString ();
}
public void putProperty(String propertyName, ESValue propertyValue, int hash) throws EcmaScriptException {
wrapper.putProperty (propertyName, propertyValue, hash);
}
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 {
return wrapper.deleteProperty (propertyName, hash);
}
public ESValue getProperty (int i) throws EcmaScriptException {
return wrapper.getProperty (i);
}
public void putProperty(int index, ESValue propertyValue) throws EcmaScriptException {
wrapper.putProperty (index, propertyValue);
}
public ESValue getProperty(String propertyName, int hash) throws EcmaScriptException {
ESValue val = super.getProperty (propertyName, hash);
if (val == null || val == ESUndefined.theUndefined)
val = wrapper.getProperty (propertyName, hash);
return val;
}
public ESValue doIndirectCall(Evaluator evaluator, ESObject thisObject, String functionName, ESValue[] arguments)
throws EcmaScriptException, NoSuchMethodException {
if (super.hasProperty (functionName, functionName.hashCode()))
return super.doIndirectCall (evaluator, thisObject, functionName, arguments);
return wrapper.doIndirectCall (evaluator, thisObject, functionName, arguments);
}
public Enumeration getAllProperties () {
return wrapper.getProperties ();
}
public Enumeration getProperties () {
return wrapper.getProperties ();
}
public Object toJavaObject () {
return wrappedObject;
/**
* Creates a new ESGenericObject object.
*
* @param prototype ...
* @param evaluator ...
* @param obj ...
*/
public ESGenericObject(ESObject prototype, Evaluator evaluator, Object obj) {
super(prototype, evaluator);
wrappedObject = obj;
wrapper = new ESWrapper(obj, evaluator);
}
/**
* An ESNode equals another object if it is an ESNode that wraps the same INode
*
*
* @return ...
*/
public String getESClassName() {
return "GenericObject";
}
/**
*
*
* @return ...
*/
public String toString() {
return wrappedObject.toString();
}
/**
*
*
* @return ...
*/
public String toDetailString() {
return wrapper.toDetailString();
}
/**
*
*
* @param propertyName ...
* @param propertyValue ...
* @param hash ...
*
* @throws EcmaScriptException ...
*/
public void putProperty(String propertyName, ESValue propertyValue, int hash)
throws EcmaScriptException {
wrapper.putProperty(propertyName, propertyValue, 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);
}
/**
*
*
* @param propertyName ...
* @param hash ...
*
* @return ...
*
* @throws EcmaScriptException ...
*/
public boolean deleteProperty(String propertyName, int hash)
throws EcmaScriptException {
return wrapper.deleteProperty(propertyName, hash);
}
/**
*
*
* @param i ...
*
* @return ...
*
* @throws EcmaScriptException ...
*/
public ESValue getProperty(int i) throws EcmaScriptException {
return wrapper.getProperty(i);
}
/**
*
*
* @param index ...
* @param propertyValue ...
*
* @throws EcmaScriptException ...
*/
public void putProperty(int index, ESValue propertyValue)
throws EcmaScriptException {
wrapper.putProperty(index, propertyValue);
}
/**
*
*
* @param propertyName ...
* @param hash ...
*
* @return ...
*
* @throws EcmaScriptException ...
*/
public ESValue getProperty(String propertyName, int hash)
throws EcmaScriptException {
ESValue val = super.getProperty(propertyName, hash);
if ((val == null) || (val == ESUndefined.theUndefined)) {
val = wrapper.getProperty(propertyName, hash);
}
return val;
}
/**
*
*
* @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 {
if (super.hasProperty(functionName, functionName.hashCode())) {
return super.doIndirectCall(evaluator, thisObject, functionName, arguments);
}
return wrapper.doIndirectCall(evaluator, thisObject, functionName, arguments);
}
/**
*
*
* @return ...
*/
public Enumeration getAllProperties() {
return wrapper.getProperties();
}
/**
*
*
* @return ...
*/
public Enumeration getProperties() {
return wrapper.getProperties();
}
/**
*
*
* @return ...
*/
public Object toJavaObject() {
return wrappedObject;
}
/**
* An ESNode equals another object if it is an ESNode that wraps the same INode
* or the wrapped INode itself. FIXME: doesen't check dbmapping/type!
*/
public boolean equals (Object what) {
if (what == null)
public boolean equals(Object what) {
if (what == null) {
return false;
if (what == this)
}
if (what == this) {
return true;
}
if (what instanceof ESGenericObject) {
ESGenericObject other = (ESGenericObject) what;
return (wrappedObject.equals (other.wrappedObject));
return (wrappedObject.equals(other.wrappedObject));
}
return false;
}
}
}

View file

@ -1,171 +1,189 @@
// 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;
import helma.framework.core.*;
import helma.objectmodel.INode;
import FESI.Data.*;
import FESI.Exceptions.*;
import FESI.Interpreter.Evaluator;
import helma.framework.core.*;
import helma.objectmodel.INode;
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 {
private Map data;
private FesiEngine engine;
private boolean readonly = false;
public ESMapWrapper (FesiEngine engine) {
super (new Object(), engine.getEvaluator ());
this.engine = engine;
/**
* Creates a new ESMapWrapper object.
*
* @param engine ...
*/
public ESMapWrapper(FesiEngine engine) {
super(new Object(), engine.getEvaluator());
this.engine = engine;
}
public ESMapWrapper (FesiEngine engine, Map data) {
super (new Object(), engine.getEvaluator ());
this.engine = engine;
this.data = data;
/**
* Creates a new ESMapWrapper object.
*
* @param engine ...
* @param data ...
*/
public ESMapWrapper(FesiEngine engine, Map data) {
super(new Object(), engine.getEvaluator());
this.engine = engine;
this.data = data;
}
public void setReadonly (boolean readonly) {
this.readonly = readonly;
}
/**
*
*
* @param readonly ...
*/
public void setReadonly(boolean readonly) {
this.readonly = readonly;
}
public void setData (Map data) {
this.data = data;
/**
*
*
* @param data ...
*/
public void setData(Map data) {
this.data = data;
}
/**
* Overridden to make the object read-only
*/
public void putProperty(String propertyName, ESValue propertyValue, int hash) throws EcmaScriptException {
if (data == null)
data = new HashMap ();
if (propertyValue == ESNull.theNull)
deleteProperty(propertyName, hash);
else if (readonly==false)
data.put (propertyName, propertyValue.toJavaObject ());
else
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)
return ESNull.theNull;
public void putProperty(String propertyName, ESValue propertyValue, int hash)
throws EcmaScriptException {
if (data == null) {
data = new HashMap();
}
Object val = data.get (propertyName);
if (val == null)
return ESNull.theNull;
if (val instanceof String)
return new ESString ((String) val);
else if (val instanceof INode)
return engine.getNodeWrapper ((INode) val);
else if (val instanceof Map)
return new ESMapWrapper (engine, (Map)val);
else if (val instanceof ESValue)
return (ESValue) val;
return ESLoader.normalizeValue(val, evaluator);
if (propertyValue == ESNull.theNull) {
deleteProperty(propertyName, hash);
} else if (readonly == false) {
data.put(propertyName, propertyValue.toJavaObject());
} else {
throw new EcmaScriptException("object is readonly");
}
}
/**
*
*
* @param propertyName ...
* @param hash ...
*
* @return ...
*
* @throws EcmaScriptException ...
*/
public boolean deleteProperty(String propertyName, int hash)
throws EcmaScriptException {
if (readonly == false) {
data.remove(propertyName);
public Enumeration getAllProperties () {
return getProperties ();
return true;
} else {
return false;
}
}
public Enumeration getProperties () {
Object[] keys = data == null ? null : data.keySet().toArray ();
return new Enum (keys);
/**
*
*
* @param propertyName ...
* @param hash ...
*
* @return ...
*
* @throws EcmaScriptException ...
*/
public ESValue getProperty(String propertyName, int hash)
throws EcmaScriptException {
if (data == null) {
return ESNull.theNull;
}
Object val = data.get(propertyName);
if (val == null) {
return ESNull.theNull;
}
if (val instanceof String) {
return new ESString((String) val);
} else if (val instanceof INode) {
return engine.getNodeWrapper((INode) val);
} else if (val instanceof Map) {
return new ESMapWrapper(engine, (Map) val);
} else if (val instanceof ESValue) {
return (ESValue) val;
}
return ESLoader.normalizeValue(val, evaluator);
}
/**
*
*
* @return ...
*/
public Enumeration getAllProperties() {
return getProperties();
}
/**
*
*
* @return ...
*/
public Enumeration getProperties() {
Object[] keys = (data == null) ? null : data.keySet().toArray();
return new Enum(keys);
}
class Enum implements Enumeration {
Object[] elements;
int pos;
Enum (Object[] elements) {
this.elements = elements;
pos = 0;
}
public boolean hasMoreElements () {
return elements != null && pos < elements.length;
}
public Object nextElement () {
if (elements == null || pos >= elements.length)
throw new NoSuchElementException ();
return elements[pos++];
}
Object[] elements;
int pos;
Enum(Object[] elements) {
this.elements = elements;
pos = 0;
}
public boolean hasMoreElements() {
return (elements != null) && (pos < elements.length);
}
public Object nextElement() {
if ((elements == null) || (pos >= elements.length)) {
throw new NoSuchElementException();
}
return elements[pos++];
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,88 +1,121 @@
// 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;
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.ASTStatementList;
import FESI.AST.EcmaScriptTreeConstants;
import FESI.Interpreter.*;
import FESI.Data.*;
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.
*/
public class FesiActionAdapter {
Prototype prototype;
Application app;
String functionName;
String sourceName;
// this is the parsed function which can be easily applied to FesiEngine objects
TypeUpdater pfunc, pfuncAsString;
TypeUpdater pfunc;
public FesiActionAdapter (ActionFile action) {
prototype = action.getPrototype ();
app = action.getApplication ();
Reader reader = null;
functionName = action.getFunctionName ();
sourceName = action.getSourceName ();
try {
reader = action.getReader ();
pfunc = parseFunction (functionName,
"arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10",
reader,
sourceName);
} catch (Throwable x) {
String message = x.getMessage ();
pfunc = new ErrorFeedback (functionName, message);
} finally {
try {
reader.close();
} catch (Exception ignore) {}
}
// check if this is a template and we need to generate an "_as_string" variant
if (action instanceof Template) {
String content = "res.pushStringBuffer(); " +
action.getContent () +
"\r\nreturn res.popStringBuffer();\r\n";
try {
pfuncAsString = parseFunction (functionName+"_as_string",
"arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10",
new StringReader(content),
sourceName);
} catch (Throwable x) {
String message = x.getMessage ();
pfunc = new ErrorFeedback (functionName+"_as_string", message);
}
} else {
pfuncAsString = null;
}
// 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) {
prototype = action.getPrototype();
app = action.getApplication();
Reader reader = null;
functionName = action.getFunctionName();
sourceName = action.getSourceName();
try {
reader = action.getReader();
pfunc = parseFunction(functionName,
"arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10",
reader, sourceName);
} catch (Throwable x) {
String message = x.getMessage();
pfunc = new ErrorFeedback(functionName, message);
} finally {
try {
reader.close();
} catch (Exception ignore) {
}
}
// check if this is a template and we need to generate an "_as_string" variant
if (action instanceof Template) {
String content = "res.pushStringBuffer(); " + action.getContent() +
"\r\nreturn res.popStringBuffer();\r\n";
try {
pfuncAsString = parseFunction(functionName + "_as_string",
"arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10",
new StringReader(content), sourceName);
} catch (Throwable x) {
String message = x.getMessage();
pfunc = new ErrorFeedback(functionName + "_as_string", message);
}
} else {
pfuncAsString = null;
}
}
/**
*
*
* @param engine ...
*
* @throws EcmaScriptException ...
*/
public synchronized void updateEvaluator(FesiEngine engine)
throws EcmaScriptException {
if (pfunc != null) {
pfunc.updateEvaluator(engine);
}
public synchronized void updateEvaluator (FesiEngine engine) throws EcmaScriptException {
if (pfunc != null)
pfunc.updateEvaluator (engine);
if (pfuncAsString != null)
pfuncAsString.updateEvaluator (engine);
if (pfuncAsString != null) {
pfuncAsString.updateEvaluator(engine);
}
}
protected TypeUpdater parseFunction (String funcName, String params, Reader body, String sourceName) throws EcmaScriptException {
protected TypeUpdater parseFunction(String funcName, String params, Reader body,
String sourceName)
throws EcmaScriptException {
// ESObject fp = app.eval.evaluator.getFunctionPrototype();
// ConstructedFunctionObject function = null;
ASTFormalParameterList fpl = null;
@ -90,116 +123,138 @@ public class FesiActionAdapter {
FunctionEvaluationSource fes = null;
/* if (body == null || "".equals (body.trim()))
body = ";\r\n";
else
body = body + "\r\n"; */
if (params == null) params = "";
else params = params.trim ();
body = ";\r\n";
else
body = body + "\r\n"; */
if (params == null) {
params = "";
} else {
params = params.trim();
}
EcmaScript parser;
StringReader is;
// Special case for empty parameters
if (params.length()==0) {
if (params.length() == 0) {
fpl = new ASTFormalParameterList(EcmaScriptTreeConstants.JJTFORMALPARAMETERLIST);
} else {
is = new java.io.StringReader(params);
parser = new EcmaScript(is);
try {
fpl = (ASTFormalParameterList) parser.FormalParameterList();
is.close();
} 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
// deep inside the parser...
// is = new java.io.StringReader(body.toString ());
try {
parser = new EcmaScript (body);
parser = new EcmaScript(body);
sl = (ASTStatementList) parser.StatementList();
body.close();
} catch (ParseException x) {
app.logEvent ("Error parsing file "+app.getName()+":"+sourceName+": "+x);
throw new EcmaScriptParseException (x, new FileEvaluationSource(sourceName, null));
app.logEvent("Error parsing file " + app.getName() + ":" + sourceName + ": " +
x);
throw new EcmaScriptParseException(x,
new FileEvaluationSource(sourceName, null));
} catch (Exception x) {
app.logEvent ("Error parsing file "+app.getName()+":"+sourceName+": "+x);
throw new RuntimeException (x.getMessage ());
app.logEvent("Error parsing file " + app.getName() + ":" + sourceName + ": " +
x);
throw new RuntimeException(x.getMessage());
}
fes = new FunctionEvaluationSource (new FileEvaluationSource(sourceName, null), funcName);
return new ParsedFunction (fpl, sl, fes, null, funcName);
fes = new FunctionEvaluationSource(new FileEvaluationSource(sourceName, null),
funcName);
return new ParsedFunction(fpl, sl, fes, null, funcName);
}
interface TypeUpdater {
public void updateEvaluator(FesiEngine engine)
throws EcmaScriptException;
}
class ParsedFunction implements TypeUpdater {
ASTFormalParameterList fpl = null;
ASTStatementList sl = null;
FunctionEvaluationSource fes = null;
String fullFunctionText = null;
String functionName;
public ParsedFunction (ASTFormalParameterList fpl, ASTStatementList sl, FunctionEvaluationSource fes,
String fullFunctionText, String functionName) {
this.fpl = fpl;
this.sl = sl;
this.fes = fes;
this.fullFunctionText = fullFunctionText;
this.functionName = functionName;
public ParsedFunction(ASTFormalParameterList fpl, ASTStatementList sl,
FunctionEvaluationSource fes, String fullFunctionText,
String functionName) {
this.fpl = fpl;
this.sl = sl;
this.fes = fes;
this.fullFunctionText = fullFunctionText;
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();
Vector vnames = vdvisitor.processVariableDeclarations(sl, fes);
EcmaScriptVariableVisitor vdvisitor = engine.evaluator.getVarDeclarationVisitor();
Vector vnames = vdvisitor.processVariableDeclarations(sl, fes);
FunctionPrototype fp = ConstructedFunctionObject.makeNewConstructedFunction(engine.evaluator,
functionName,
fes,
fullFunctionText,
fpl.getArguments(),
vnames,
sl);
FunctionPrototype fp = ConstructedFunctionObject.makeNewConstructedFunction (
engine.evaluator, functionName, fes,
fullFunctionText, fpl.getArguments(), vnames, sl);
op.putHiddenProperty (functionName, fp);
op.putHiddenProperty(functionName, fp);
}
}
class ErrorFeedback implements TypeUpdater {
String functionName;
String errorMessage;
String functionName, errorMessage;
public ErrorFeedback (String fname, String msg) {
public ErrorFeedback(String fname, String msg) {
functionName = fname;
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 func = new ThrowException (functionName, engine.evaluator, fp, errorMessage);
op.putHiddenProperty (functionName, func);
FunctionPrototype fp = (FunctionPrototype) engine.evaluator.getFunctionPrototype();
FunctionPrototype func = new ThrowException(functionName, engine.evaluator,
fp, errorMessage);
op.putHiddenProperty(functionName, func);
}
}
class ThrowException extends BuiltinFunctionObject {
String message;
ThrowException (String name, Evaluator evaluator, FunctionPrototype fp, String message) {
super (fp, evaluator, name, 1);
this.message = message == null ? "No error message available" : message;
}
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
throw new EcmaScriptException (message);
}
public ESObject doConstruct (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
throw new EcmaScriptException (message);
}
}
interface TypeUpdater {
public void updateEvaluator (FesiEngine engine) throws EcmaScriptException;
ThrowException(String name, Evaluator evaluator, FunctionPrototype fp,
String message) {
super(fp, evaluator, name, 1);
this.message = (message == null) ? "No error message available" : message;
}
public ESValue callFunction(ESObject thisObject, ESValue[] arguments)
throws EcmaScriptException {
throw new EcmaScriptException(message);
}
public ESObject doConstruct(ESObject thisObject, ESValue[] arguments)
throws EcmaScriptException {
throw new EcmaScriptException(message);
}
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,90 +1,164 @@
// NodeConstructor.java
// Copyright (c) Hannes Wallnöfer 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;
import helma.objectmodel.db.Node;
import helma.framework.core.*;
import FESI.Data.*;
import FESI.Exceptions.*;
import FESI.Interpreter.*;
import helma.framework.core.*;
import helma.objectmodel.db.Node;
/**
* A constructor for user defined data types. This first constructs a node, sets its prototype
* and invokes the scripted constructor function on it.
*/
public class NodeConstructor extends BuiltinFunctionObject {
FesiEngine engine;
String typename;
FesiEngine engine;
String typename;
/**
* Creates a new NodeConstructor object.
*
* @param name ...
* @param fp ...
* @param engine ...
*/
public NodeConstructor(String name, FunctionPrototype fp, FesiEngine engine) {
super(fp, engine.getEvaluator(), name, 1);
typename = name;
this.engine = engine;
}
public NodeConstructor (String name, FunctionPrototype fp, FesiEngine engine) {
super(fp, engine.getEvaluator (), name, 1);
typename = name;
this.engine = engine;
/**
*
*
* @param thisObject ...
* @param arguments ...
*
* @return ...
*
* @throws EcmaScriptException ...
*/
public ESValue callFunction(ESObject thisObject, ESValue[] arguments)
throws EcmaScriptException {
return doConstruct(thisObject, arguments);
}
/**
*
*
* @param thisObject ...
* @param arguments ...
*
* @return ...
*
* @throws EcmaScriptException ...
*/
public ESObject doConstruct(ESObject thisObject, ESValue[] arguments)
throws EcmaScriptException {
ESNode node = null;
Application app = engine.getApplication();
if ("Node".equals(typename) || "hopobject".equalsIgnoreCase(typename)) {
String nodeName = null;
if ((arguments.length > 0) && (arguments[0] != null)) {
nodeName = arguments[0].toString();
}
Node n = new Node(nodeName, (String) null, app.getWrappedNodeManager());
node = new ESNode(engine.getPrototype("hopobject"), this.evaluator, n, engine);
engine.putNodeWrapper(node.getNode(), node);
} else {
// Typed nodes are instantiated as helma.objectmodel.db.Node from the beginning
// even if we don't know yet if they are going to be stored in a database. The reason
// is that we want to be able to use the specail features like subnode relations even for
// transient nodes.
ObjectPrototype op = engine.getPrototype(typename);
Node n = new Node(typename, typename, app.getWrappedNodeManager());
node = new ESNode(op, engine.getEvaluator(), n, engine);
node.setPrototype(typename);
node.getNode().setDbMapping(app.getDbMapping(typename));
try {
// first try calling "constructor", if that doesn't work, try calling a function
// with the name of the type.
// HACK: There is an incompatibility problem here, because the property
// constructor is defined as the constructor of the object by EcmaScript.
if (op.getProperty("constructor", "constructor".hashCode()) instanceof ConstructedFunctionObject) {
node.doIndirectCall(engine.getEvaluator(), node, "constructor",
arguments);
} else if (op.getProperty(typename, typename.hashCode()) instanceof ConstructedFunctionObject) {
node.doIndirectCall(engine.getEvaluator(), node, typename, arguments);
}
} catch (Exception x) {
throw new EcmaScriptException(x.toString());
}
}
public ESValue callFunction(ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
return doConstruct(thisObject, arguments);
return node;
}
/**
*
*
* @param propertyName ...
* @param previousScope ...
* @param hash ...
*
* @return ...
*
* @throws EcmaScriptException ...
*/
public ESValue getPropertyInScope(String propertyName, ScopeChain previousScope,
int hash) throws EcmaScriptException {
return super.getPropertyInScope(propertyName, previousScope, hash);
}
/**
*
*
* @param propertyName ...
* @param hash ...
*
* @return ...
*
* @throws EcmaScriptException ...
*/
public ESValue getProperty(String propertyName, int hash)
throws EcmaScriptException {
if ("prototype".equals(propertyName)) {
return engine.getPrototype(typename);
}
public ESObject doConstruct(ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
ESNode node = null;
Application app = engine.getApplication ();
if ("Node".equals (typename) || "hopobject".equalsIgnoreCase (typename)) {
String nodeName = null;
if (arguments.length > 0 && arguments[0] != null)
nodeName = arguments[0].toString();
Node n = new Node (nodeName, (String) null, app.getWrappedNodeManager ());
node = new ESNode (engine.getPrototype ("hopobject"), this.evaluator, n, engine);
engine.putNodeWrapper (node.getNode (), node);
} else {
// Typed nodes are instantiated as helma.objectmodel.db.Node from the beginning
// even if we don't know yet if they are going to be stored in a database. The reason
// is that we want to be able to use the specail features like subnode relations even for
// transient nodes.
ObjectPrototype op = engine.getPrototype (typename);
Node n = new Node (typename, typename, app.getWrappedNodeManager ());
node = new ESNode (op, engine.getEvaluator (), n, engine);
node.setPrototype (typename);
node.getNode ().setDbMapping (app.getDbMapping (typename));
try {
// first try calling "constructor", if that doesn't work, try calling a function
// with the name of the type.
// HACK: There is an incompatibility problem here, because the property
// constructor is defined as the constructor of the object by EcmaScript.
if (op.getProperty ("constructor",
"constructor".hashCode())
instanceof ConstructedFunctionObject)
node.doIndirectCall (engine.getEvaluator(), node, "constructor", arguments);
else if (op.getProperty (typename,
typename.hashCode())
instanceof ConstructedFunctionObject)
node.doIndirectCall (engine.getEvaluator(), node, typename, arguments);
} catch (Exception x) {
throw new EcmaScriptException (x.toString());
}
}
return node;
}
public ESValue getPropertyInScope(String propertyName, ScopeChain previousScope, int hash) throws EcmaScriptException {
return super.getPropertyInScope (propertyName, previousScope, hash);
}
public ESValue getProperty(String propertyName, int hash) throws EcmaScriptException {
if ("prototype".equals (propertyName))
return engine.getPrototype (typename);
return super.getProperty(propertyName, hash);
}
public String[] getSpecialPropertyNames() {
String ns[] = {};
return ns;
}
} // class NodeConstructor
return super.getProperty(propertyName, hash);
}
/**
*
*
* @return ...
*/
public String[] getSpecialPropertyNames() {
String[] ns = { };
return ns;
}
}
// class NodeConstructor

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