This commit was manufactured by cvs2svn to create tag
'Pre1_2001_02_27_stable'.
This commit is contained in:
parent
84f281fb77
commit
8bf0f8dee6
140 changed files with 7090 additions and 13818 deletions
|
@ -179,7 +179,7 @@ public class FileServlet extends HttpServlet
|
||||||
|
|
||||||
protected void serveFile( HttpServletRequest req, HttpServletResponse res, boolean headOnly, String path, String filename, File file ) throws IOException
|
protected void serveFile( HttpServletRequest req, HttpServletResponse res, boolean headOnly, String path, String filename, File file ) throws IOException
|
||||||
{
|
{
|
||||||
// log( "getting " + path );
|
log( "getting " + path );
|
||||||
if ( ! file.canRead() )
|
if ( ! file.canRead() )
|
||||||
{
|
{
|
||||||
res.sendError( HttpServletResponse.SC_FORBIDDEN );
|
res.sendError( HttpServletResponse.SC_FORBIDDEN );
|
||||||
|
|
|
@ -147,8 +147,6 @@ public class Serve implements ServletContext, Runnable
|
||||||
private int port;
|
private int port;
|
||||||
private PrintStream logStream;
|
private PrintStream logStream;
|
||||||
Acme.WildcardDictionary registry;
|
Acme.WildcardDictionary registry;
|
||||||
// the servlet to use if no other matches the request
|
|
||||||
Servlet defaultServlet;
|
|
||||||
Properties props;
|
Properties props;
|
||||||
|
|
||||||
/// Constructor.
|
/// Constructor.
|
||||||
|
@ -270,10 +268,6 @@ public class Serve implements ServletContext, Runnable
|
||||||
registry.remove (urlPat);
|
registry.remove (urlPat);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDefaultServlet (Servlet servlet) {
|
|
||||||
defaultServlet = servlet;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Register a standard set of Servlets. These will return
|
/// Register a standard set of Servlets. These will return
|
||||||
// files or directory listings, and run CGI programs, much like a
|
// files or directory listings, and run CGI programs, much like a
|
||||||
// standard HTTP server.
|
// standard HTTP server.
|
||||||
|
@ -457,7 +451,8 @@ public class Serve implements ServletContext, Runnable
|
||||||
// Same as the CGI variable SERVER_SOFTWARE.
|
// Same as the CGI variable SERVER_SOFTWARE.
|
||||||
public String getServerInfo()
|
public String getServerInfo()
|
||||||
{
|
{
|
||||||
return ServeUtils.serverName + " " + helma.main.Server.version + " (" + ServeUtils.serverUrl + ")";
|
return ServeUtils.serverName + " " + ServeUtils.serverVersion +
|
||||||
|
" (" + ServeUtils.serverUrl + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the value of the named attribute of the network service, or
|
/// Returns the value of the named attribute of the network service, or
|
||||||
|
@ -658,11 +653,6 @@ class ServeConnection implements Runnable, HttpServletRequest, HttpServletRespon
|
||||||
if (reqQuery != null)
|
if (reqQuery != null)
|
||||||
reqQuery = decode (reqQuery);
|
reqQuery = decode (reqQuery);
|
||||||
Servlet servlet = (Servlet) serve.registry.get( reqUriPath );
|
Servlet servlet = (Servlet) serve.registry.get( reqUriPath );
|
||||||
// maybe the application name without slash? try with slash appended
|
|
||||||
if (servlet == null)
|
|
||||||
servlet = (Servlet) serve.registry.get (reqUriPath+"//");
|
|
||||||
if (servlet == null)
|
|
||||||
servlet = serve.defaultServlet;
|
|
||||||
if ( servlet != null )
|
if ( servlet != null )
|
||||||
runServlet( (HttpServlet) servlet );
|
runServlet( (HttpServlet) servlet );
|
||||||
else if ( "/".equals( reqUriPath ))
|
else if ( "/".equals( reqUriPath ))
|
||||||
|
@ -687,7 +677,7 @@ class ServeConnection implements Runnable, HttpServletRequest, HttpServletRespon
|
||||||
setStatus( SC_OK );
|
setStatus( SC_OK );
|
||||||
setDateHeader( "Date", System.currentTimeMillis() );
|
setDateHeader( "Date", System.currentTimeMillis() );
|
||||||
setHeader(
|
setHeader(
|
||||||
"Server", ServeUtils.serverName + "/" + helma.main.Server.version );
|
"Server", ServeUtils.serverName + "/" + ServeUtils.serverVersion );
|
||||||
setHeader( "Connection", "close" );
|
setHeader( "Connection", "close" );
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
|
@ -42,9 +42,8 @@ public class ServeUtils
|
||||||
{
|
{
|
||||||
|
|
||||||
// Server identification.
|
// Server identification.
|
||||||
public static final String serverName = "Helma";
|
public static final String serverName = "Hop";
|
||||||
// we're using the server version from helma.main.Server class.
|
public static final String serverVersion = "1.1 p1";
|
||||||
// public static final String serverVersion = "1.2 p1";
|
|
||||||
public static final String serverUrl = "http://helma.org/";
|
public static final String serverUrl = "http://helma.org/";
|
||||||
|
|
||||||
/// Write a standard-format HTML address for this server.
|
/// Write a standard-format HTML address for this server.
|
||||||
|
@ -53,7 +52,7 @@ public class ServeUtils
|
||||||
PrintStream p = new PrintStream( o );
|
PrintStream p = new PrintStream( o );
|
||||||
p.println(
|
p.println(
|
||||||
"<ADDRESS><A HREF=\"" + serverUrl + "\">" +
|
"<ADDRESS><A HREF=\"" + serverUrl + "\">" +
|
||||||
serverName + " " + helma.main.Server.version + "</A></ADDRESS>" );
|
serverName + " " + serverVersion + "</A></ADDRESS>" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -92,4 +91,3 @@ public class ServeUtils
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -260,11 +260,8 @@ public abstract class ESLoader extends ESObject {
|
||||||
return (ESArrayWrapper) obj; // An array wrapper received externally
|
return (ESArrayWrapper) obj; // An array wrapper received externally
|
||||||
} else if (obj.getClass().isArray()) {
|
} else if (obj.getClass().isArray()) {
|
||||||
return new ESArrayWrapper(obj, evaluator);
|
return new ESArrayWrapper(obj, evaluator);
|
||||||
} // else if (obj instanceof helma.framework.IPathElement) { // Hannes Wallnoefer, 13. Aug 2001
|
}
|
||||||
// return evaluator.reval.getElementWrapper ((helma.framework.IPathElement) obj);
|
return new ESWrapper(obj, evaluator);
|
||||||
// }
|
|
||||||
// return new ESWrapper(obj, evaluator);
|
|
||||||
return evaluator.reval.getObjectWrapper (obj);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -338,7 +335,6 @@ public abstract class ESLoader extends ESObject {
|
||||||
* Check that each object in the paremeter array can be converted
|
* Check that each object in the paremeter array can be converted
|
||||||
* to the type specified by the target array and convert them if needed.
|
* to the type specified by the target array and convert them if needed.
|
||||||
* <P>Even if the parameters are compatible with an EcmaScript value,
|
* <P>Even if the parameters are compatible with an EcmaScript value,
|
||||||
|
|
||||||
* some may have to be converted to an intermediate type. For example
|
* some may have to be converted to an intermediate type. For example
|
||||||
* an EcmaScript string of 1 character long is compatible with a Java
|
* an EcmaScript string of 1 character long is compatible with a Java
|
||||||
* Character, but some conversion is needed. Arrays need a similar
|
* Character, but some conversion is needed. Arrays need a similar
|
||||||
|
@ -386,7 +382,6 @@ public abstract class ESLoader extends ESObject {
|
||||||
if (targetClass.isPrimitive()) { // or: Object.class.isAssignableFrom(targetClass)
|
if (targetClass.isPrimitive()) { // or: Object.class.isAssignableFrom(targetClass)
|
||||||
accepted = false;
|
accepted = false;
|
||||||
debugInfo = " rejected (null cannot be assigned to primitive)";
|
debugInfo = " rejected (null cannot be assigned to primitive)";
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
accepted = true;
|
accepted = true;
|
||||||
debugInfo = " accepted (null to Object)";
|
debugInfo = " accepted (null to Object)";
|
||||||
|
|
|
@ -105,16 +105,6 @@ public abstract class ESObject extends ESValue {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allow the prototype to be set, added 2001-04-05 by Hannes Wallnöfer
|
|
||||||
*
|
|
||||||
* @param prototype The new prototype object
|
|
||||||
*/
|
|
||||||
public void setPrototype(ESObject prototype) {
|
|
||||||
this.prototype = prototype;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the name of the class of objects ([[class]]), as used in the default toString
|
* Return the name of the class of objects ([[class]]), as used in the default toString
|
||||||
* method of objects (15.2.4.2)
|
* method of objects (15.2.4.2)
|
||||||
|
|
|
@ -338,10 +338,9 @@ public class ESWrapper extends ESObject {
|
||||||
return noPropertyMarker;
|
return noPropertyMarker;
|
||||||
}
|
}
|
||||||
int modifiers = fld.getModifiers();
|
int modifiers = fld.getModifiers();
|
||||||
// ALLOW ACCESS TO STATIC FIELDS. HW, 2001-11-27
|
if ((theObject == null) != Modifier.isStatic(modifiers)) {
|
||||||
// if ((theObject == null) != Modifier.isStatic(modifiers)) {
|
throw new EcmaScriptException("Field mode (static) not correct for "+ propertyName);
|
||||||
// throw new EcmaScriptException("Field mode (static) not correct for "+ propertyName);
|
}
|
||||||
// }
|
|
||||||
if (!Modifier.isPublic(modifiers)) {
|
if (!Modifier.isPublic(modifiers)) {
|
||||||
throw new EcmaScriptException("Field "+ propertyName + " not public");
|
throw new EcmaScriptException("Field "+ propertyName + " not public");
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,11 +15,3 @@ Changes to standard FESI distribution (1.1.4) for Hop
|
||||||
ESNumber.
|
ESNumber.
|
||||||
- Made EcmaScriptFunctionVisitor recognise thisObj - Functions are now assigned
|
- Made EcmaScriptFunctionVisitor recognise thisObj - Functions are now assigned
|
||||||
to the current thisObject.
|
to the current thisObject.
|
||||||
- Added setPrototype() method to FESI.Data.ESObject to be able to manipulate
|
|
||||||
the prototype after the object was created.
|
|
||||||
- Changed FESI.Interpreter.EcmaScriptEvaluateVisitor to use .equals instead of
|
|
||||||
== in equal method for helma.framework.core.ESNode objects, since different
|
|
||||||
wrappers may wrap the same object.
|
|
||||||
- Added RequestEvaluator reval field to FESI.Interpreter.Evaluator in order to
|
|
||||||
let ESLoader crate wrappers with correct prototype for path element objects.
|
|
||||||
|
|
||||||
|
|
|
@ -248,13 +248,6 @@ public class EcmaScriptEvaluateVisitor
|
||||||
return b1==b2;
|
return b1==b2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ESNode wrappers must be checked with equals() because
|
|
||||||
// it's possible that different wrappers wrap the same node!
|
|
||||||
if (v1 instanceof helma.scripting.fesi.ESNode ||
|
|
||||||
v1 instanceof helma.scripting.fesi.ESGenericObject) {
|
|
||||||
return v1.equals (v2);
|
|
||||||
}
|
|
||||||
|
|
||||||
return v1 == v2;
|
return v1 == v2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1363,5 +1356,3 @@ public class EcmaScriptEvaluateVisitor
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -44,8 +44,6 @@ public class Evaluator {
|
||||||
|
|
||||||
// used to stop thread, 06.12.99 Hannes Wallnoefer
|
// used to stop thread, 06.12.99 Hannes Wallnoefer
|
||||||
public volatile Thread thread;
|
public volatile Thread thread;
|
||||||
// used to retrieve wrappers with correct Prototype for path elements in ESLoader
|
|
||||||
public helma.scripting.fesi.FesiEvaluator reval;
|
|
||||||
|
|
||||||
private static String eol = System.getProperty("line.separator", "\n");
|
private static String eol = System.getProperty("line.separator", "\n");
|
||||||
|
|
||||||
|
|
|
@ -1,119 +0,0 @@
|
||||||
package helma.doc;
|
|
||||||
|
|
||||||
import helma.framework.IPathElement;
|
|
||||||
import helma.main.Server;
|
|
||||||
import java.io.*;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
public class DocApplication extends DocElement implements IPathElement {
|
|
||||||
|
|
||||||
private DocPrototype[] prototypes;
|
|
||||||
|
|
||||||
/** read all prototypes
|
|
||||||
* @param name application to be documented
|
|
||||||
* @param appDir directory of this application */
|
|
||||||
public DocApplication(String name, String appDir) throws DocException {
|
|
||||||
super( name, appDir, APPLICATION );
|
|
||||||
checkCommentFile();
|
|
||||||
readPrototypes();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getFullName() {
|
|
||||||
return ( "Application " + name );
|
|
||||||
}
|
|
||||||
|
|
||||||
/** return number of prototypes */
|
|
||||||
public int countPrototypes() {
|
|
||||||
return prototypes.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** return a single prototype */
|
|
||||||
public DocPrototype getDocPrototype(String name) {
|
|
||||||
for ( int i=0; i<prototypes.length; i++ ) {
|
|
||||||
if ( prototypes[i].getName().equalsIgnoreCase(name) )
|
|
||||||
return prototypes[i];
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** return array of prototypes */
|
|
||||||
public DocPrototype[] listPrototypes() {
|
|
||||||
return prototypes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DocFunction[] listFunctions() {
|
|
||||||
return listFunctions(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DocFunction[] listFunctions(int type) {
|
|
||||||
Vector funcVec = new Vector();
|
|
||||||
for ( int i=0; i<prototypes.length; i++ ) {
|
|
||||||
DocFunction[] tmp = prototypes[i].listFunctions();
|
|
||||||
for ( int j=0; j<tmp.length; j++ ) {
|
|
||||||
if ( type==-1 || tmp[j].getType()==type )
|
|
||||||
funcVec.addElement(tmp[j]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DocFunction[] funcArr = (DocFunction[])funcVec.toArray(new DocFunction[funcVec.size()]);
|
|
||||||
Arrays.sort(funcArr,new DocComparator(DocComparator.BY_NAME,this));
|
|
||||||
return funcArr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** read prototypes, create them and make them parse their functions */
|
|
||||||
private void readPrototypes() {
|
|
||||||
File d = new File ( location );
|
|
||||||
String pt[] = d.list();
|
|
||||||
Vector ptVec = new Vector();
|
|
||||||
for ( int i=0; i<pt.length; i++ ) {
|
|
||||||
File f = new File ( d.getAbsolutePath(), pt[i] );
|
|
||||||
if ( f.isDirectory() && DocRun.prototypeAllowed(pt[i]) ) {
|
|
||||||
try {
|
|
||||||
DocPrototype p = new DocPrototype(pt[i],f.getAbsolutePath(),this);
|
|
||||||
ptVec.addElement(p);
|
|
||||||
//break;
|
|
||||||
} catch ( DocException e ) {
|
|
||||||
DocRun.log( "couldn't read prototype " + pt[i] + ": " + e.getMessage() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
prototypes = (DocPrototype[])ptVec.toArray(new DocPrototype[ptVec.size()]);
|
|
||||||
Arrays.sort(prototypes,new DocComparator(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString() {
|
|
||||||
return ( "[DocApplication " + name + "]" );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////
|
|
||||||
// from helma.framework.IPathElement
|
|
||||||
////////////////////////////////////
|
|
||||||
|
|
||||||
public String getElementName() {
|
|
||||||
return "api";
|
|
||||||
}
|
|
||||||
|
|
||||||
public IPathElement getChildElement(String name) {
|
|
||||||
for( int i=0; i<prototypes.length; i++ ) {
|
|
||||||
if ( prototypes[i].getElementName().equals(name) ) {
|
|
||||||
return prototypes[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IPathElement getParentElement() {
|
|
||||||
Server s = helma.main.Server.getServer();
|
|
||||||
return s.getChildElement(this.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public java.lang.String getPrototype() {
|
|
||||||
return "docapplication";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,46 +0,0 @@
|
||||||
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 DocComparator(int mode, DocElement docEl) {
|
|
||||||
this.mode = mode;
|
|
||||||
this.docEl = docEl;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DocComparator(DocElement docEl) {
|
|
||||||
this.mode = 0;
|
|
||||||
this.docEl = docEl;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,184 +0,0 @@
|
||||||
package helma.doc;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
public abstract class DocElement {
|
|
||||||
|
|
||||||
// identifiers of this element
|
|
||||||
String name;
|
|
||||||
int type;
|
|
||||||
String location;
|
|
||||||
|
|
||||||
// comment-content
|
|
||||||
DocTag tags[];
|
|
||||||
String comment;
|
|
||||||
|
|
||||||
public static final int DOCROOT = 0;
|
|
||||||
public static final int APPLICATION = 1;
|
|
||||||
public static final int PROTOTYPE = 2;
|
|
||||||
public static final int METHOD = 3;
|
|
||||||
public static final int ACTION = 4;
|
|
||||||
public static final int TEMPLATE = 5;
|
|
||||||
public static final int FUNCTION = 6;
|
|
||||||
public static final int MACRO = 7;
|
|
||||||
public static final int SKIN = 8;
|
|
||||||
public static final int PROPERTY = 9; // to be implemented
|
|
||||||
|
|
||||||
public static final String[] typeNames = {"DocRoot","Application","Prototype","Method","Action","Template","Function","Macro","Skin","Property"};
|
|
||||||
|
|
||||||
/** a default file that is read as comment for applications and prototypes if found in their directories */
|
|
||||||
public static final String DOCFILENAME = "doc.html";
|
|
||||||
|
|
||||||
public DocElement(String name, String location, int type) throws DocException {
|
|
||||||
if ( (new File(location)).exists()==false )
|
|
||||||
throw new DocException( name + " not found in " + location );
|
|
||||||
this.name = name;
|
|
||||||
this.location = location;
|
|
||||||
this.type = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public 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.getAbsolutePath();
|
|
||||||
this.type = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @return the name of the element */
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract public String getFullName();
|
|
||||||
|
|
||||||
/** @return absolute path to location of element (directory for apps and prototypes, file for methods) */
|
|
||||||
public String getLocation() {
|
|
||||||
return location;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isApplication() { return (type==APPLICATION)?true:false; }
|
|
||||||
public boolean isPrototype() { return (type==PROTOTYPE)?true:false; }
|
|
||||||
public boolean isMethod() { if ( type>=METHOD && type<=SKIN ) return true; else return false; }
|
|
||||||
public boolean isAction() { return (type==ACTION)?true:false; }
|
|
||||||
public boolean isTemplate() { return (type==TEMPLATE)?true:false; }
|
|
||||||
public boolean isFunction() { return (type==FUNCTION)?true:false; }
|
|
||||||
public boolean isMacro() { return (type==MACRO)?true:false; }
|
|
||||||
public boolean isSkin() { return (type==SKIN)?true:false; }
|
|
||||||
|
|
||||||
public int getType() { return type; }
|
|
||||||
public String getTypeName() { return typeNames[type]; }
|
|
||||||
|
|
||||||
public String getDocFileName() { return (typeNames[type] + "_" + name).toLowerCase() + ".html"; }
|
|
||||||
|
|
||||||
/** @return the text of the comment */
|
|
||||||
public String getComment() { return (comment!=null)?comment:""; }
|
|
||||||
|
|
||||||
public int countTags() { return countTags(-1); }
|
|
||||||
public int countTags(int kind) {
|
|
||||||
int ct=0;
|
|
||||||
for ( int i=0; i<tags.length; i++ ) {
|
|
||||||
if ( kind==-1 || tags[i].getKind()==kind ) {
|
|
||||||
ct++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ct;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DocTag[] listTags() { return tags; }
|
|
||||||
/** @return an array of tags that should get a special format
|
|
||||||
* expects a -1 if it should retrieve all tags! */
|
|
||||||
public DocTag[] listTags(int kind) {
|
|
||||||
Vector vec = new Vector();
|
|
||||||
for ( int i=0; i<tags.length; i++ ) {
|
|
||||||
if ( kind==-1 || tags[i].getKind()==kind ) {
|
|
||||||
vec.addElement(tags[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DocTag[] dt = (DocTag[])vec.toArray(new DocTag[vec.size()]);
|
|
||||||
return dt;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** parse rawComment, render DocTags */
|
|
||||||
void parseComment(String rawComment) {
|
|
||||||
try {
|
|
||||||
// get rid of java comment tags (delimiter "/**")
|
|
||||||
int beg = rawComment.indexOf("/*");
|
|
||||||
beg = ( beg<0 ) ? beg=0 : beg+3;
|
|
||||||
int end = rawComment.indexOf("*/");
|
|
||||||
end = ( end<0 ) ? rawComment.length()-1 : end;
|
|
||||||
end = ( end<0 ) ? 0 : end;
|
|
||||||
rawComment = rawComment.substring(beg,end).trim();
|
|
||||||
// separate comment from tags:
|
|
||||||
StringBuffer commentBuf = new StringBuffer();
|
|
||||||
StringBuffer tagBuf = new StringBuffer();
|
|
||||||
boolean switched = false;
|
|
||||||
StringTokenizer tok = new StringTokenizer(rawComment,"\n");
|
|
||||||
while(tok.hasMoreTokens() ) {
|
|
||||||
String line = tok.nextToken().trim();
|
|
||||||
if ( line.startsWith("*") )
|
|
||||||
line = line.substring(1).trim();
|
|
||||||
if ( line.length()==0 ) continue;
|
|
||||||
if ( line.startsWith("@") && switched==false )
|
|
||||||
switched=true;
|
|
||||||
if ( switched==true )
|
|
||||||
tagBuf.append(line + "\n" );
|
|
||||||
else
|
|
||||||
commentBuf.append(line + "\n" );
|
|
||||||
}
|
|
||||||
comment = commentBuf.toString();
|
|
||||||
// now create taglist:
|
|
||||||
tok = new StringTokenizer(tagBuf.toString(),"@");
|
|
||||||
tags = new DocTag[tok.countTokens()];
|
|
||||||
int i = 0;
|
|
||||||
while(tok.hasMoreTokens() ) {
|
|
||||||
tags[i++] = new DocTag(tok.nextToken().trim());
|
|
||||||
}
|
|
||||||
} catch ( DocException e ) {
|
|
||||||
DocRun.log("parse error in " + location + ": " + e.getMessage() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** read properties file (app.props || type.props), format of comments has to be discussed! */
|
|
||||||
static Properties readPropertiesFile(String filename) throws DocException {
|
|
||||||
Properties props = new Properties();
|
|
||||||
try {
|
|
||||||
props.load(new FileInputStream(filename));
|
|
||||||
} catch ( IOException e ) {
|
|
||||||
DocRun.log("couldn't read file: " + e.getMessage() );
|
|
||||||
}
|
|
||||||
return props;
|
|
||||||
}
|
|
||||||
|
|
||||||
void checkCommentFile() throws DocException {
|
|
||||||
File f = new File (location, DOCFILENAME );
|
|
||||||
if ( f.exists() ) {
|
|
||||||
String rawComment = readAFile(f.getAbsolutePath());
|
|
||||||
parseComment(rawComment);
|
|
||||||
} else {
|
|
||||||
comment = "";
|
|
||||||
tags = new DocTag[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** read a complete file into a string */
|
|
||||||
public static String readAFile(String str) {
|
|
||||||
StringBuffer buf = new StringBuffer();
|
|
||||||
try {
|
|
||||||
BufferedReader in = new BufferedReader(new FileReader(new File(str)));
|
|
||||||
String line = in.readLine();
|
|
||||||
while(line!=null) {
|
|
||||||
buf.append(line+"\n");
|
|
||||||
line = in.readLine();
|
|
||||||
}
|
|
||||||
return ( buf.toString() );
|
|
||||||
} catch ( IOException e ) {
|
|
||||||
return ("");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
package helma.doc;
|
|
||||||
|
|
||||||
public class DocException extends Exception {
|
|
||||||
|
|
||||||
String str;
|
|
||||||
|
|
||||||
public DocException (String str) {
|
|
||||||
super (str);
|
|
||||||
this.str = str;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getMessage() {
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,103 +0,0 @@
|
||||||
package helma.doc;
|
|
||||||
|
|
||||||
import helma.framework.IPathElement;
|
|
||||||
import java.io.*;
|
|
||||||
|
|
||||||
public class DocFunction extends DocElement implements IPathElement {
|
|
||||||
|
|
||||||
public static final String[] typeSuffix = {"_action","_as_string","","_macro",""};
|
|
||||||
|
|
||||||
private DocPrototype prototype;
|
|
||||||
private String source;
|
|
||||||
|
|
||||||
public DocFunction( String name, String location, int type, DocPrototype prototype, String rawComment ) throws DocException {
|
|
||||||
super(name,location, type);
|
|
||||||
this.prototype = prototype;
|
|
||||||
parseComment(rawComment);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getFullName() {
|
|
||||||
switch(type) {
|
|
||||||
case ACTION: return ( "Action " + name );
|
|
||||||
case TEMPLATE: return ( "Template " + name );
|
|
||||||
case FUNCTION: return ( "Function " + name );
|
|
||||||
case MACRO: return ( "Macro " + name );
|
|
||||||
case SKIN: return ( "Skin " + name );
|
|
||||||
}
|
|
||||||
return ( "Method " + name );
|
|
||||||
}
|
|
||||||
|
|
||||||
public DocPrototype getDocPrototype() { return prototype; }
|
|
||||||
|
|
||||||
public void readSource(String 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 ( FileNotFoundException e ) {
|
|
||||||
} catch ( StringIndexOutOfBoundsException e ) {
|
|
||||||
} catch ( IOException e ) {
|
|
||||||
DocRun.log(e.getMessage());
|
|
||||||
}
|
|
||||||
source = buf.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void readSource(String sourceFile) {
|
|
||||||
StringBuffer buf = new StringBuffer ();
|
|
||||||
try {
|
|
||||||
BufferedReader in = new BufferedReader(new FileReader(sourceFile));
|
|
||||||
String line="";
|
|
||||||
while ( line!=null ) {
|
|
||||||
line = in.readLine();
|
|
||||||
if ( line==null ) break;
|
|
||||||
buf.append(line+"\n");
|
|
||||||
}
|
|
||||||
} catch ( FileNotFoundException e ) {
|
|
||||||
} catch ( IOException e ) {
|
|
||||||
DocRun.log(e.getMessage());
|
|
||||||
}
|
|
||||||
source = buf.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSource(String source) { this.source = source; }
|
|
||||||
public String getSource() { return (source!=null)?source:""; }
|
|
||||||
|
|
||||||
public String toString() {
|
|
||||||
return ( "[DocFunction " + getTypeName() + " " + name + "]" );
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////
|
|
||||||
// from helma.framework.IPathElement
|
|
||||||
////////////////////////////////////
|
|
||||||
|
|
||||||
public String getElementName() {
|
|
||||||
return getTypeName().toLowerCase()+"_"+name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IPathElement getChildElement(String name) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IPathElement getParentElement() {
|
|
||||||
return prototype;
|
|
||||||
}
|
|
||||||
|
|
||||||
public java.lang.String getPrototype() {
|
|
||||||
return "docfunction";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,328 +0,0 @@
|
||||||
package helma.doc;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import helma.util.*;
|
|
||||||
|
|
||||||
public class DocHtmlWriter extends PrintWriter {
|
|
||||||
|
|
||||||
public static DocApplication app;
|
|
||||||
|
|
||||||
public static final int APPLICATION = 0;
|
|
||||||
public static final int PROTOTYPE = 1;
|
|
||||||
public static final int INDEX = 2;
|
|
||||||
public static final int METHOD = 3;
|
|
||||||
|
|
||||||
public DocHtmlWriter(String filename) throws FileNotFoundException {
|
|
||||||
super(new FileOutputStream(filename));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void printHeader( String title ) { printHeader(title,false); }
|
|
||||||
|
|
||||||
/** print header, slightly different for frameset file **/
|
|
||||||
public void printHeader( String title, boolean frameset ) {
|
|
||||||
if ( frameset==true )
|
|
||||||
print("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Frameset//EN\"\"http://www.w3.org/TR/REC-html40/frameset.dtd\">");
|
|
||||||
else
|
|
||||||
print("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\">");
|
|
||||||
print("<HTML><HEAD>");
|
|
||||||
print("<!-- Generated by helmadoc on " + (new Date()).toString() + " -->");
|
|
||||||
println("<TITLE>" + title + "</TITLE>");
|
|
||||||
if ( frameset==true )
|
|
||||||
print("<LINK REL=\"stylesheet\" TYPE=\"text/css\" HREF=\"stylesheet.css\" TITLE=Style>");
|
|
||||||
println("</HEAD>");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void printFrameSet() {
|
|
||||||
println ("<FRAMESET cols=\"20%,80%\">");
|
|
||||||
println ("<FRAME src=\"app-frame.html\" name=appFrame>");
|
|
||||||
println ("<FRAME src=\"app.html\" name=prototypeFrame>");
|
|
||||||
println ("</FRAMESET><NOFRAMES>sorry, your browser doesn't understand frames!</NOFRAMES></HTML>");
|
|
||||||
}
|
|
||||||
|
|
||||||
/** print app title for left frame */
|
|
||||||
public void printAppIndexTitle(String title) {
|
|
||||||
print("<table border=0 width=\"100%\"><tr><td nowrap>");
|
|
||||||
print("<FONT size=+1 ID=FrameTitleFont><b>");
|
|
||||||
print("Application " + title + "</b></font></td></tr></table>" );
|
|
||||||
}
|
|
||||||
|
|
||||||
/** print prototype list for left frame */
|
|
||||||
public void printAppIndexList(DocElement[] pt) {
|
|
||||||
print("<TABLE BORDER=0 WIDTH=\"100%\"><TR><TD NOWRAP>");
|
|
||||||
print("<P><FONT size=+1 ID=FrameHeadingFont>Prototypes</FONT><BR><BR>");
|
|
||||||
for ( int i=0; i<pt.length; i++ ) {
|
|
||||||
print ("<FONT ID=FrameItemFont><A HREF=\"" + pt[i].getDocFileName() + "\" TARGET=prototypeFrame>" + pt[i].getName() + "</A></FONT><BR>");
|
|
||||||
}
|
|
||||||
print ("</TD></TR></TABLE>");
|
|
||||||
}
|
|
||||||
|
|
||||||
/** navigation on top of the page **/
|
|
||||||
public void printNavBar(String name, DocPrototype pt, int page ) {
|
|
||||||
String urlPrefix = ( page==METHOD ) ? "../" : "";
|
|
||||||
print("<!-- ========== START OF NAVBAR ========== -->");
|
|
||||||
print("<A NAME=navbar_top><!-- --></A>");
|
|
||||||
print("<TABLE BORDER=0 WIDTH=100% CELLPADDING=1 CELLSPACING=0>");
|
|
||||||
print("<TR><TD COLSPAN=2 BGCOLOR=#EEEEFF ID=NavBarCell1>");
|
|
||||||
print("<A NAME=navbar_top_firstrow><!-- --></A>");
|
|
||||||
|
|
||||||
print("<TABLE BORDER=0 CELLPADDING=0 CELLSPACING=3>");
|
|
||||||
print("<TR ALIGN=center VALIGN=top>");
|
|
||||||
if ( page==APPLICATION )
|
|
||||||
print("<TD BGCOLOR=#EEEEFF ID=NavBarCell1Rev><FONT ID=NavBarFont1Rev><B>Application</B></FONT> </TD>");
|
|
||||||
else
|
|
||||||
print("<TD BGCOLOR=#EEEEFF ID=NavBarCell1><A HREF=\"" + urlPrefix + "app.html\"><FONT ID=NavBarFont1><B>Application</B></FONT></A> </TD>");
|
|
||||||
if ( page==PROTOTYPE )
|
|
||||||
print("<TD BGCOLOR=#EEEEFF ID=NavBarCell1Rev> <FONT ID=NavBarFont1Rev><B>Prototype</B></FONT> </TD>");
|
|
||||||
else if ( page==METHOD )
|
|
||||||
print("<TD BGCOLOR=#EEEEFF ID=NavBarCell1> <a href=\"" + urlPrefix + "prototype_" + pt.getName() + ".html\"><FONT ID=NavBarFont1><B>Prototype</B></A></FONT> </TD>");
|
|
||||||
else
|
|
||||||
print("<TD BGCOLOR=#EEEEFF ID=NavBarCell1> <FONT ID=NavBarFont1><B>Prototype</B></FONT> </TD>");
|
|
||||||
if ( page==INDEX )
|
|
||||||
print("<TD BGCOLOR=#EEEEFF ID=NavBarCell1Rev><FONT ID=NavBarFont1><B>Index</B></FONT> </TD>");
|
|
||||||
else
|
|
||||||
print("<TD BGCOLOR=#EEEEFF ID=NavBarCell1><A HREF=\"" + urlPrefix + "index-1.html\"><FONT ID=NavBarFont1><B>Index</B></FONT></A> </TD>");
|
|
||||||
print("</TR></TABLE>");
|
|
||||||
|
|
||||||
print("</TD><TD ALIGN=right VALIGN=top ROWSPAN=3><EM><b>Application " + name + "</b><br><font size=-1></font></EM>");
|
|
||||||
print("</TD></TR>");
|
|
||||||
if ( pt!=null && page!=METHOD ) {
|
|
||||||
print("<TR><TD VALIGN=top ID=NavBarCell3><FONT SIZE=-2>");
|
|
||||||
print("<a href=\"#Actions\">ACTIONS</a> | ");
|
|
||||||
print("<a href=\"#Templates\">TEMPLATES</a> | ");
|
|
||||||
print("<a href=\"#Functions\">FUNCTIONS</a> | ");
|
|
||||||
print("<a href=\"#Macros\">MACROS</a> | ");
|
|
||||||
print("<a href=\"#Skins\">SKINS</a> ");
|
|
||||||
print("</TD></TR>");
|
|
||||||
}
|
|
||||||
|
|
||||||
print("</TABLE>");
|
|
||||||
print("<!-- =========== END OF NAVBAR =========== -->");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void printElementTitle(DocElement docEl) {
|
|
||||||
print("<HR><H2>" + docEl.getName() + "<BR>");
|
|
||||||
print(docEl.getFullName() + "</H2>");
|
|
||||||
print("<HR>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void printComment(DocElement docEl) {
|
|
||||||
if( docEl.getComment().length()>0 || docEl.countTags()>0 ) {
|
|
||||||
print("<DL><DT>" + docEl.getComment() + "</DT>");
|
|
||||||
print("<DT>");
|
|
||||||
for ( int i=0; i<DocTag.TYPE_COUNT; i++ ) {
|
|
||||||
if ( docEl.countTags(i)>0 ) {
|
|
||||||
print("<DT><b>" + DocTag.kindDesc[i] + "</b><DT>");
|
|
||||||
DocTag[] dt = docEl.listTags(i);
|
|
||||||
for ( int j=0; j<dt.length; j++ ) {
|
|
||||||
print("<DD>" + renderTag(dt[j],j) + "</DD>");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
print("</DL>");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private String renderFunctionName(DocFunction func) {
|
|
||||||
StringBuffer buf = new StringBuffer ();
|
|
||||||
buf.append("<CODE><B>");
|
|
||||||
if ( DocRun.getOption("-f").equals("true") )
|
|
||||||
buf.append("<a href=\"" + func.getDocPrototype().getName().toLowerCase()+"/"+func.getDocFileName() + "\">" );
|
|
||||||
if ( func.isMacro() ) {
|
|
||||||
buf.append( func.getDocPrototype().getName()+"."+func.getName().substring(0,func.getName().length()-6) );
|
|
||||||
} else {
|
|
||||||
buf.append(func.getName().trim());
|
|
||||||
if( func.isTemplate() || func.isFunction() ) {
|
|
||||||
buf.append("(");
|
|
||||||
int ct = func.countTags(DocTag.ARG);
|
|
||||||
for ( int i=0; i<ct; i++ ) {
|
|
||||||
buf.append("arg"+i);
|
|
||||||
if ( i<ct-1 )
|
|
||||||
buf.append(", ");
|
|
||||||
}
|
|
||||||
buf.append(")");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
buf.append("</a></B></CODE>");
|
|
||||||
if ( func.isFunction() || func.isMacro() )
|
|
||||||
buf.append(" <small><i>in " + (new File(func.getLocation())).getName() + "</i></small>" );
|
|
||||||
return buf.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private String renderTag(DocTag tag) {
|
|
||||||
return renderTag(tag,0);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String renderTag(DocTag tag, int i) {
|
|
||||||
int kind = tag.getKind();
|
|
||||||
String text = tag.getText();
|
|
||||||
String name = tag.getName();
|
|
||||||
switch (kind) {
|
|
||||||
case DocTag.ARG:
|
|
||||||
return( "<b>Argument " + i + ":</b> " + text );
|
|
||||||
case DocTag.PARAM:
|
|
||||||
return( "<b>Parameter " + name + "</b> " + text );
|
|
||||||
case DocTag.RETURNS:
|
|
||||||
case DocTag.AUTHOR:
|
|
||||||
case DocTag.VERSION:
|
|
||||||
case DocTag.RELEASE:
|
|
||||||
return( text );
|
|
||||||
case DocTag.SEE:
|
|
||||||
if ( text.startsWith("http://") ) {
|
|
||||||
StringTokenizer tok = new StringTokenizer (text.trim()," ");
|
|
||||||
String url = (tok.countTokens()>1)?tok.nextToken():text;
|
|
||||||
return( "<a href=\"" + url + "\">" + ((tok.countTokens()>0)?text.substring(url.length(),text.length()):text) + "</a>" );
|
|
||||||
} else {
|
|
||||||
StringBuffer buf = new StringBuffer();
|
|
||||||
StringTokenizer tok = new StringTokenizer (text.trim(),".");
|
|
||||||
if ( tok.countTokens()==0 ) return text;
|
|
||||||
DocPrototype dp = app.getDocPrototype( tok.nextToken() );
|
|
||||||
if ( dp==null ) return text;
|
|
||||||
buf.append("<a href=\"" );
|
|
||||||
DocFunction df = null;
|
|
||||||
if ( tok.countTokens()>0 )
|
|
||||||
df = dp.getFunction( tok.nextToken() );
|
|
||||||
if ( df==null )
|
|
||||||
buf.append( link(dp) + "\">" + dp.getName() );
|
|
||||||
else
|
|
||||||
buf.append( link(df) + "\">" + dp.getName() + "." + df.getName() );
|
|
||||||
return(buf.toString()+"</a>");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void printListHeader(String title) {
|
|
||||||
print("<A NAME=\"" + title + "\"><!-- --></A>");
|
|
||||||
print("<TABLE BORDER=1 CELLPADDING=3 CELLSPACING=0 WIDTH=100%>");
|
|
||||||
print("<TR BGCOLOR=#CCCCFF ID=TableHeadingColor><TD COLSPAN=2><FONT SIZE=+2><B>" + title + "</B></FONT></TD></TR>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void printPrototypeList(DocPrototype[] dl, String title) {
|
|
||||||
if ( dl.length==0 ) return;
|
|
||||||
printListHeader(title);
|
|
||||||
for ( int i=0; i<dl.length; i++ ) {
|
|
||||||
print("<TR BGCOLOR=white ID=TableRowColor><TD ALIGN=right VALIGN=top WIDTH=1%><FONT SIZE=-1>");
|
|
||||||
print("<a name=\"" + dl[i].getName() + "\"><!-- --></a>");
|
|
||||||
print("<CODE> " + dl[i].getTypeName() + "</CODE></FONT></TD>");
|
|
||||||
print("<TD><CODE><B><A HREF=\"" + dl[i].getDocFileName() + "\">" + dl[i].getName() + "</A></B></CODE>");
|
|
||||||
print("<BR> " + dl[i].getComment() + "<br>" );
|
|
||||||
print("</TD></TR>");
|
|
||||||
}
|
|
||||||
print("</TABLE><BR>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void printFunctionList(DocFunction[] dl, String title) {
|
|
||||||
if ( dl.length==0 ) return;
|
|
||||||
printListHeader(title);
|
|
||||||
for ( int i=0; i<dl.length; i++ ) {
|
|
||||||
print("<TR BGCOLOR=white ID=TableRowColor>");
|
|
||||||
print("<TD ALIGN=right VALIGN=top WIDTH=50><FONT SIZE=-1>");
|
|
||||||
print("<a name=\"" + dl[i].getName() + "\"><!-- --></a>");
|
|
||||||
print("<CODE> " + dl[i].getTypeName() + "</CODE></FONT></TD>");
|
|
||||||
print("<TD><DL><DT>" + renderFunctionName(dl[i]) );
|
|
||||||
print("<DT>");
|
|
||||||
printComment(dl[i]);
|
|
||||||
print("</DL></TD></TR>");
|
|
||||||
}
|
|
||||||
print("</TABLE><BR>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void printFunctionIndex(DocFunction[] dl) {
|
|
||||||
if ( dl.length==0 ) return;
|
|
||||||
String curChar = " ";
|
|
||||||
print("<DL>");
|
|
||||||
for ( int i=0; i<dl.length; i++ ) {
|
|
||||||
String name = dl[i].getName();
|
|
||||||
if ( !name.toLowerCase().startsWith(curChar) ) {
|
|
||||||
print ( "</DL><h2>" + name.substring(0,1).toUpperCase() + "</h2><dl>");
|
|
||||||
curChar = name.substring(0,1).toLowerCase();
|
|
||||||
}
|
|
||||||
print("<DT><a href=\"" + link(dl[i]) + "\">" + dl[i].getName() + "</a> - " + dl[i].getTypeName() + " in <a href=\"" + link(dl[i].getDocPrototype()) + "\">" + dl[i].getDocPrototype().getName() + "</a>" );
|
|
||||||
}
|
|
||||||
print("</DL>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void printInheritance(DocPrototype pt) {
|
|
||||||
if ( pt.getName().equalsIgnoreCase("hopobject") )
|
|
||||||
return;
|
|
||||||
DocApplication app = pt.getApplication();
|
|
||||||
DocPrototype hopobject = (DocPrototype)app.getDocPrototype("hopobject");
|
|
||||||
if ( hopobject==null || hopobject.countFunctions()==0 )
|
|
||||||
return;
|
|
||||||
print("<TABLE BORDER=1 CELLPADDING=3 CELLSPACING=0 WIDTH=100%>");
|
|
||||||
print("<TR BGCOLOR=\"#EEEEFF\" CLASS=TableSubHeadingColor>");
|
|
||||||
print("<TD><B>Methods inherited from Prototype <a href=\"" + link(hopobject) + "\">hopobject</A></B></TD>");
|
|
||||||
print("</TR>");
|
|
||||||
print("<TR BGCOLOR=\"white\" CLASS=TableRowColor><TD><code>");
|
|
||||||
DocFunction[] df = hopobject.listFunctions();
|
|
||||||
|
|
||||||
int lastType = -1;
|
|
||||||
StringBuffer buf1 = new StringBuffer();
|
|
||||||
StringBuffer buf2 = new StringBuffer();
|
|
||||||
|
|
||||||
for ( int i=0; i<df.length; i++ ) {
|
|
||||||
if ( df[i].getType()!=lastType && i>0 && buf2.length()>0 ) {
|
|
||||||
buf1.append("<b>" + DocElement.typeNames[lastType] + ":</b> <code>" );
|
|
||||||
buf1.append( buf2.toString().substring(0, buf2.toString().length()-2) );
|
|
||||||
buf1.append("</code><br>");
|
|
||||||
buf2 = new StringBuffer();
|
|
||||||
}
|
|
||||||
lastType = df[i].getType();
|
|
||||||
buf2.append ( "<a href=\"" + link(df[i]) + "\">" + df[i].getName() + "</a>, " );
|
|
||||||
}
|
|
||||||
if ( buf2.length()>0 ) {
|
|
||||||
buf1.append("<b>" + DocElement.typeNames[lastType] + ":</b> <code>" );
|
|
||||||
buf1.append( buf2.toString().substring(0, buf2.toString().length()-2) );
|
|
||||||
buf1.append("</code><br>");
|
|
||||||
}
|
|
||||||
print ( buf1.toString() );
|
|
||||||
print("</TR></TABLE>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void printFunction(DocFunction func) {
|
|
||||||
print( "<br><br><small><i>in " + func.getDocPrototype().getName() + "/" + (new File(func.getLocation())).getName() + ":</i></small>" );
|
|
||||||
print( "<br><pre>");
|
|
||||||
print( HtmlEncoder.encodeAll(func.getSource()) );
|
|
||||||
print( "</pre>" );
|
|
||||||
}
|
|
||||||
|
|
||||||
public void printStyleSheet() {
|
|
||||||
println( "/* Javadoc style sheet */");
|
|
||||||
println( "/* Define colors, fonts and other style attributes here to override the defaults */");
|
|
||||||
println( "* Page background color */");
|
|
||||||
println( "body { background-color: #FFFFFF }");
|
|
||||||
println( "/* Table colors */");
|
|
||||||
println( "#TableHeadingColor { background: #CCCCFF } /* Dark mauve */");
|
|
||||||
println( "#TableSubHeadingColor { background: #EEEEFF } /* Light mauve */");
|
|
||||||
println( "#TableRowColor { background: #FFFFFF } /* White */");
|
|
||||||
println( "/* Font used in left-hand frame lists */");
|
|
||||||
println( "#FrameTitleFont { font-size: normal; font-family: normal }");
|
|
||||||
println( "#FrameHeadingFont { font-size: normal; font-family: normal }");
|
|
||||||
println( "#FrameItemFont { font-size: normal; font-family: normal }");
|
|
||||||
println( "/* Example of smaller, sans-serif font in frames */");
|
|
||||||
println( "/* #FrameItemFont { font-size: 10pt; font-family: Helvetica, Arial, sans-serif } */");
|
|
||||||
println( "/* Navigation bar fonts and colors */");
|
|
||||||
println( "#NavBarCell1 { background-color:#EEEEFF;}/* Light mauve */");
|
|
||||||
println( "#NavBarCell1Rev { background-color:#00008B;}/* Dark Blue */");
|
|
||||||
println( "#NavBarFont1 { font-family: Arial, Helvetica, sans-serif; color:#000000;}");
|
|
||||||
println( "#NavBarFont1Rev { font-family: Arial, Helvetica, sans-serif; color:#FFFFFF;}");
|
|
||||||
println( "#NavBarCell2 { font-family: Arial, Helvetica, sans-serif; background-color:#FFFFFF;}");
|
|
||||||
println( "#NavBarCell3 { font-family: Arial, Helvetica, sans-serif; background-color:#FFFFFF;}");
|
|
||||||
}
|
|
||||||
|
|
||||||
public String link(DocElement docEl) {
|
|
||||||
if ( docEl.isPrototype() ) {
|
|
||||||
return "prototype_" + docEl.getName() + ".html";
|
|
||||||
} else if ( docEl.isMethod() ) {
|
|
||||||
DocFunction df = (DocFunction)docEl;
|
|
||||||
return "prototype_" + df.getDocPrototype().getName() + ".html#" + df.getName();
|
|
||||||
} else {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,221 +0,0 @@
|
||||||
package helma.doc;
|
|
||||||
|
|
||||||
import helma.framework.IPathElement;
|
|
||||||
import java.io.*;
|
|
||||||
import java.util.*;
|
|
||||||
import FESI.Parser.*;
|
|
||||||
|
|
||||||
|
|
||||||
public class DocPrototype extends DocElement implements IPathElement {
|
|
||||||
|
|
||||||
DocFunction[] functions;
|
|
||||||
DocApplication app;
|
|
||||||
|
|
||||||
public DocPrototype( String name, String location, DocApplication app ) throws DocException {
|
|
||||||
super( name, location, PROTOTYPE );
|
|
||||||
this.app = app;
|
|
||||||
if ( name.equals("hopobject")==false && name.equals("global")==false )
|
|
||||||
readPropertiesFile( new File(location,"type.properties").getAbsolutePath());
|
|
||||||
checkCommentFile();
|
|
||||||
readFunctions();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getFullName() { return ( "Prototype " + name ); }
|
|
||||||
|
|
||||||
/** return number of functions */
|
|
||||||
public int countFunctions() { return functions.length; }
|
|
||||||
|
|
||||||
/** return array of functions of a special type */
|
|
||||||
public int countFunctions(int type) {
|
|
||||||
int ct = 0;
|
|
||||||
for ( int i=0; i<functions.length; i++ ) {
|
|
||||||
if ( functions[i].getType()==type ) {
|
|
||||||
ct++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ct;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** return a single function */
|
|
||||||
public DocFunction getFunction(String name) {
|
|
||||||
for ( int i=0; i<functions.length; i++ ) {
|
|
||||||
if ( functions[i].getName().equals(name) )
|
|
||||||
return functions[i];
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** return array of functions */
|
|
||||||
public DocFunction[] listFunctions() {
|
|
||||||
return functions;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** return array of functions of a special type */
|
|
||||||
public DocFunction[] listFunctions(int type) {
|
|
||||||
Vector funcVec = new Vector();
|
|
||||||
for ( int i=0; i<functions.length; i++ ) {
|
|
||||||
if ( functions[i].getType()==type ) {
|
|
||||||
funcVec.addElement(functions[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (DocFunction[])funcVec.toArray(new DocFunction[funcVec.size()]);;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** return the application */
|
|
||||||
public DocApplication getApplication() { return app; }
|
|
||||||
|
|
||||||
|
|
||||||
/** create the function list & read all valid files */
|
|
||||||
private void readFunctions() {
|
|
||||||
DocRun.debug("parsing Prototype " + name + " using " + location );
|
|
||||||
String files[] = (new File(location)).list();
|
|
||||||
Vector funcVec = new Vector();;
|
|
||||||
for ( int i=0; i<files.length; i++ ) {
|
|
||||||
DocRun.debug("reading " + files[i] );
|
|
||||||
try {
|
|
||||||
if ( files[i].endsWith(DocRun.actionExtension) ) {
|
|
||||||
readAction(new File(location,files[i]).getAbsolutePath(),funcVec);
|
|
||||||
} else if ( files[i].endsWith(DocRun.scriptExtension) ) {
|
|
||||||
readFunctionFile(new File(location,files[i]).getAbsolutePath(),funcVec);
|
|
||||||
} else if ( files[i].endsWith(DocRun.templateExtension) ) {
|
|
||||||
readTemplate(new File(location,files[i]).getAbsolutePath(),funcVec);
|
|
||||||
} else if ( files[i].endsWith(DocRun.skinExtension) ) {
|
|
||||||
readSkin(new File(location,files[i]).getAbsolutePath(),funcVec);
|
|
||||||
}
|
|
||||||
} catch ( DocException e ) {
|
|
||||||
DocRun.log ( "couldn't read function " + name + "." + files[i] + ": " + e.getMessage() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
functions = (DocFunction[])funcVec.toArray(new DocFunction[funcVec.size()]);
|
|
||||||
DocRun.debug( name + " has " + functions.length + " functions" );
|
|
||||||
Arrays.sort(functions,new DocComparator(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void readAction(String f, Vector funcVec) throws DocException {
|
|
||||||
EcmaScriptTokenManager mgr = createTokenManager(new File(f));
|
|
||||||
Token tok = mgr.getNextToken();
|
|
||||||
DocFunction func = new DocFunction( fileToFuncName(f), f, DocElement.ACTION, this, getCommentFromToken(tok) );
|
|
||||||
func.readSource(f);
|
|
||||||
funcVec.addElement( func );
|
|
||||||
}
|
|
||||||
|
|
||||||
private void readFunctionFile(String f, Vector funcVec) throws DocException {
|
|
||||||
EcmaScriptTokenManager mgr = createTokenManager(new File(f));
|
|
||||||
Token tok = mgr.getNextToken();
|
|
||||||
while( tok.kind!=0 ) {
|
|
||||||
if( tok.kind == EcmaScriptConstants.FUNCTION ) {
|
|
||||||
int beginLine = tok.beginLine;
|
|
||||||
int beginColumn = tok.beginColumn;
|
|
||||||
String funcName = mgr.getNextToken().toString();
|
|
||||||
DocFunction func;
|
|
||||||
if ( funcName.endsWith("_macro") )
|
|
||||||
func = new DocFunction( funcName, f, DocElement.MACRO, this, getCommentFromToken(tok) );
|
|
||||||
else
|
|
||||||
func = new DocFunction( funcName, f, DocElement.FUNCTION, this, getCommentFromToken(tok) );
|
|
||||||
funcVec.addElement(func);
|
|
||||||
|
|
||||||
tok = mgr.getNextToken();
|
|
||||||
int endLine=0, endColumn=0;
|
|
||||||
while( tok.kind!=0 && tok.kind!=EcmaScriptConstants.FUNCTION ) {
|
|
||||||
endLine = tok.endLine;
|
|
||||||
endColumn = tok.endColumn;
|
|
||||||
tok = mgr.getNextToken();
|
|
||||||
}
|
|
||||||
func.readSource(f,beginLine,beginColumn,endLine,endColumn);
|
|
||||||
//DocRun.log("going from " + beginLine +"." + beginColumn + " to " + endLine + "." + endColumn );
|
|
||||||
//DocRun.log("============================here starts a new one");
|
|
||||||
}
|
|
||||||
if ( tok.kind!=0 && tok.kind!=EcmaScriptConstants.FUNCTION )
|
|
||||||
tok = mgr.getNextToken();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void readTemplate(String f, Vector funcVec) throws DocException {
|
|
||||||
String content = readAFile(f);
|
|
||||||
// get the first scripting zone and tokenize it
|
|
||||||
DocFunction func;
|
|
||||||
try {
|
|
||||||
StringReader str = new StringReader( content.substring(content.indexOf("<%")+2,content.indexOf("%>")) );
|
|
||||||
EcmaScriptTokenManager mgr = new EcmaScriptTokenManager(new ASCII_CharStream(str,1,1),0);
|
|
||||||
Token tok = mgr.getNextToken();
|
|
||||||
func = new DocFunction( fileToFuncName(f), f, DocElement.TEMPLATE, this, getCommentFromToken(tok) );
|
|
||||||
} catch ( IndexOutOfBoundsException e ) {
|
|
||||||
func = new DocFunction( fileToFuncName(f), f, DocElement.TEMPLATE, this, "" );
|
|
||||||
}
|
|
||||||
func.setSource(content);
|
|
||||||
funcVec.addElement(func);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void readSkin(String f, Vector funcVec) throws DocException {
|
|
||||||
// can't be commented yet
|
|
||||||
// simply add them
|
|
||||||
DocFunction func = new DocFunction(fileToFuncName(f),f,DocElement.SKIN, this,"");
|
|
||||||
func.readSource(f);
|
|
||||||
funcVec.addElement(func);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** create token manager for a file */
|
|
||||||
private 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 shouldnotappear ) { }
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** connect all available specialTokens */
|
|
||||||
private String getCommentFromToken(Token tok) {
|
|
||||||
StringBuffer buf = new StringBuffer();
|
|
||||||
while( tok.specialToken!=null ) {
|
|
||||||
buf.append(tok.specialToken.toString() );
|
|
||||||
tok = tok.specialToken;
|
|
||||||
}
|
|
||||||
return ( buf.toString().trim() );
|
|
||||||
}
|
|
||||||
|
|
||||||
private String fileToFuncName(String f) {
|
|
||||||
return fileToFuncName(new File(f));
|
|
||||||
}
|
|
||||||
|
|
||||||
private String fileToFuncName(File f) {
|
|
||||||
String tmp = f.getName();
|
|
||||||
return tmp.substring(0,tmp.indexOf("."));
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString() {
|
|
||||||
return ( "[DocPrototype " + name + "]" );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////
|
|
||||||
// from helma.framework.IPathElement
|
|
||||||
////////////////////////////////////
|
|
||||||
|
|
||||||
public String getElementName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IPathElement getChildElement(String name) {
|
|
||||||
for ( int i=0; i<functions.length; i++ ) {
|
|
||||||
if ( name.equals( functions[i].getTypeName().toLowerCase()+"_"+functions[i].getName() ) )
|
|
||||||
return functions[i];
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// return getFunction(name);
|
|
||||||
// }
|
|
||||||
|
|
||||||
public IPathElement getParentElement() {
|
|
||||||
return app;
|
|
||||||
}
|
|
||||||
|
|
||||||
public java.lang.String getPrototype() {
|
|
||||||
return "docprototype";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,227 +0,0 @@
|
||||||
package helma.doc;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.util.*;
|
|
||||||
import helma.util.SystemProperties;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Description of the Class
|
|
||||||
*
|
|
||||||
*@author Stefan Pollach
|
|
||||||
*@created August 20, 2001
|
|
||||||
*/
|
|
||||||
public class DocRun {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Description of the Field
|
|
||||||
*/
|
|
||||||
public static String propfile;
|
|
||||||
/**
|
|
||||||
* Description of the Field
|
|
||||||
*/
|
|
||||||
public static SystemProperties sysProps, dbProps;
|
|
||||||
/**
|
|
||||||
* Description of the Field
|
|
||||||
*/
|
|
||||||
public static String actionExtension = ".hac";
|
|
||||||
/**
|
|
||||||
* Description of the Field
|
|
||||||
*/
|
|
||||||
public static String scriptExtension = ".js";
|
|
||||||
/**
|
|
||||||
* Description of the Field
|
|
||||||
*/
|
|
||||||
public static String templateExtension = ".hsp";
|
|
||||||
/**
|
|
||||||
* Description of the Field
|
|
||||||
*/
|
|
||||||
public static String skinExtension = ".skin";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Description of the Field
|
|
||||||
*/
|
|
||||||
public static String hopHomeDir;
|
|
||||||
|
|
||||||
public static Hashtable options = new Hashtable();
|
|
||||||
|
|
||||||
String appName;
|
|
||||||
DocApplication app;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor for the DocRun object
|
|
||||||
*
|
|
||||||
*@param appDir Description of Parameter
|
|
||||||
*@exception DocException Description of Exception
|
|
||||||
*/
|
|
||||||
public DocRun(String appDir) throws DocException {
|
|
||||||
File d = new File(appDir);
|
|
||||||
if (!d.exists()) {
|
|
||||||
throw new DocException(d.toString() + " doesn't exist");
|
|
||||||
}
|
|
||||||
if (!d.isDirectory()) {
|
|
||||||
throw new DocException(d.toString() + " is not a directory");
|
|
||||||
}
|
|
||||||
log("parsing application " + d.getName() + " located in " + d.getAbsolutePath());
|
|
||||||
log("writing output to " + getOption("-d", new File(hopHomeDir, "/appdocs/" + d.getName()).getAbsolutePath()));
|
|
||||||
app = new DocApplication(d.getName(), d.getAbsolutePath());
|
|
||||||
DocWriter.start(getOption("-d", new File(hopHomeDir, "/appdocs/" + d.getName()).getAbsolutePath()), app);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the option attribute of the DocRun class
|
|
||||||
*
|
|
||||||
*@param name Description of Parameter
|
|
||||||
*@return The option value
|
|
||||||
*/
|
|
||||||
public static String getOption(String name) {
|
|
||||||
return getOption(name, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the option attribute of the DocRun class
|
|
||||||
*
|
|
||||||
*@param name Description of Parameter
|
|
||||||
*@param def Description of Parameter
|
|
||||||
*@return The option value
|
|
||||||
*/
|
|
||||||
public static String getOption(String name, String def) {
|
|
||||||
if (options.containsKey(name)) {
|
|
||||||
return (String) options.get(name);
|
|
||||||
} else {
|
|
||||||
return (def);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Description of the Method
|
|
||||||
*
|
|
||||||
*@param args Description of Parameter
|
|
||||||
*/
|
|
||||||
public static void main(String args[]) {
|
|
||||||
boolean usageError = false;
|
|
||||||
// parse options from command line
|
|
||||||
options = new Hashtable();
|
|
||||||
StringBuffer buf = new StringBuffer();
|
|
||||||
String name = "";
|
|
||||||
for (int i = 0; i < args.length; i++) {
|
|
||||||
if (args[i].startsWith("-")) {
|
|
||||||
if (i > 0) {
|
|
||||||
if (buf.toString().length() == 0) {
|
|
||||||
usageError = true;
|
|
||||||
} else {
|
|
||||||
options.put(name, buf.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
name = args[i];
|
|
||||||
buf = new StringBuffer();
|
|
||||||
} else {
|
|
||||||
buf.append(((buf.toString().length() > 0) ? " " : "") + args[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
options.put(name, buf.toString());
|
|
||||||
// include last option
|
|
||||||
// now check parameter
|
|
||||||
if (options.containsKey("-h")) {
|
|
||||||
hopHomeDir = (String) options.get("-h");
|
|
||||||
} else {
|
|
||||||
hopHomeDir = System.getProperty("user.dir");
|
|
||||||
}
|
|
||||||
readHopProperties(hopHomeDir);
|
|
||||||
String parAppDir = "";
|
|
||||||
if (options.containsKey("-a")) {
|
|
||||||
parAppDir = (String) options.get("-a");
|
|
||||||
} else {
|
|
||||||
usageError = true;
|
|
||||||
}
|
|
||||||
if (usageError == true) {
|
|
||||||
help();
|
|
||||||
System.exit(0);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
new DocRun(parAppDir);
|
|
||||||
} catch (DocException e) {
|
|
||||||
System.out.println("doc error: " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Description of the Method
|
|
||||||
*/
|
|
||||||
public static void help() {
|
|
||||||
System.out.println("usage: java helma.doc.DocApplication -a appdir [-f] [-h hopdir] [-d docdir] [-i ignore]");
|
|
||||||
System.out.println(" -a appdir Specify source directory");
|
|
||||||
System.out.println(" -h hopdir Specify hop home directory");
|
|
||||||
System.out.println(" -d docdir Specify destination directory");
|
|
||||||
System.out.println(" -f true Link functions to source code");
|
|
||||||
System.out.println(" -i ignore Specify prototypes to ignore (like: \"-i CVS mistsack\")");
|
|
||||||
System.out.println(" -debug");
|
|
||||||
System.out.println("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Description of the Method
|
|
||||||
*
|
|
||||||
*@param name Description of Parameter
|
|
||||||
*@return Description of the Returned Value
|
|
||||||
*/
|
|
||||||
public static boolean prototypeAllowed(String name) {
|
|
||||||
String ig = " " + getOption("-i").toLowerCase() + " ";
|
|
||||||
if (ig.equals("")) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
name = name.toLowerCase();
|
|
||||||
if (ig.indexOf(" " + name + " ") > -1) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* reads server.properties, apps.properties and db.properties from
|
|
||||||
* hop-home-directory TBD: should be cleaned up to work exactly like the
|
|
||||||
* helma server
|
|
||||||
*
|
|
||||||
*@param hopHomeDir Description of Parameter
|
|
||||||
*/
|
|
||||||
public static void readHopProperties(String hopHomeDir) {
|
|
||||||
propfile = new File(hopHomeDir, "server.properties").getAbsolutePath();
|
|
||||||
sysProps = new SystemProperties(propfile);
|
|
||||||
dbProps = new SystemProperties(new File(hopHomeDir, "db.properties").getAbsolutePath());
|
|
||||||
actionExtension = sysProps.getProperty("actionExtension", ".hac");
|
|
||||||
scriptExtension = sysProps.getProperty("scriptExtension", ".js");
|
|
||||||
templateExtension = sysProps.getProperty("templateExtension", ".hsp");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Description of the Method
|
|
||||||
*
|
|
||||||
*@param msg Description of Parameter
|
|
||||||
*/
|
|
||||||
public static void debug(String msg) {
|
|
||||||
if (options.containsKey("-debug")) {
|
|
||||||
System.out.println(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Description of the Method
|
|
||||||
*
|
|
||||||
*@param msg Description of Parameter
|
|
||||||
*/
|
|
||||||
public static void log(String msg) {
|
|
||||||
System.out.println(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1,59 +0,0 @@
|
||||||
package helma.doc;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
public class DocTag {
|
|
||||||
|
|
||||||
public static final int ARG = 0;
|
|
||||||
public static final int PARAM = 1;
|
|
||||||
public static final int RETURNS = 2;
|
|
||||||
public static final int AUTHOR = 3;
|
|
||||||
public static final int VERSION = 4;
|
|
||||||
public static final int RELEASE = 5;
|
|
||||||
public static final int SEE = 6;
|
|
||||||
|
|
||||||
/** number of different tag-types **/
|
|
||||||
public static final int TYPE_COUNT = 7;
|
|
||||||
|
|
||||||
/** constants are used as array indices! **/
|
|
||||||
public static final String[] kindNames = {"arg","param","return","author","version","release","see"};
|
|
||||||
public static final String[] kindDesc = {"Arguments","Parameter","Returns","Author","Version","Release","See also"};
|
|
||||||
|
|
||||||
private String name;
|
|
||||||
private int kind;
|
|
||||||
private String text;
|
|
||||||
|
|
||||||
public DocTag( String rawTag ) throws DocException {
|
|
||||||
//DocRun.log(rawTag);
|
|
||||||
try {
|
|
||||||
StringTokenizer tok = new StringTokenizer(rawTag);
|
|
||||||
String kindstr = tok.nextToken().toLowerCase();
|
|
||||||
for ( int i=0; i<kindNames.length; i++ ) {
|
|
||||||
if ( kindstr.startsWith(kindNames[i]) ) {
|
|
||||||
kind = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
StringBuffer buf = new StringBuffer();
|
|
||||||
if ( kind==PARAM ) {
|
|
||||||
name = tok.nextToken();
|
|
||||||
}
|
|
||||||
while ( tok.hasMoreTokens() ) {
|
|
||||||
buf.append( tok.nextToken() + " " );
|
|
||||||
}
|
|
||||||
text = buf.toString();
|
|
||||||
} catch ( Exception e ) { }
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() { return (name!=null && !name.equals("null"))?name:""; }
|
|
||||||
public int getKind() { return kind; }
|
|
||||||
public String getText() { return (text!=null && !text.equals("null"))?text:""; }
|
|
||||||
|
|
||||||
public String toString() {
|
|
||||||
return "[" + ((name!=null)?name+" ":"" ) + text + "]";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,128 +0,0 @@
|
||||||
package helma.doc;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
public class DocWriter extends DocHtmlWriter {
|
|
||||||
|
|
||||||
public static String docDir;
|
|
||||||
|
|
||||||
public DocWriter( String filename ) throws FileNotFoundException {
|
|
||||||
super( new File(docDir,filename).getAbsolutePath() );
|
|
||||||
DocRun.log("creating " + filename );
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void start( String parDocDir, DocApplication parApp ) {
|
|
||||||
app = parApp;
|
|
||||||
docDir = parDocDir;
|
|
||||||
if ( !(new File(parDocDir).exists()) ) {
|
|
||||||
DocRun.log("creating directory " + parDocDir );
|
|
||||||
(new File(parDocDir)).mkdirs();
|
|
||||||
}
|
|
||||||
printStyleSheet(app);
|
|
||||||
printFrameSet(app);
|
|
||||||
printAppDoc(app);
|
|
||||||
printAppIndex(app);
|
|
||||||
printPrototypes(app);
|
|
||||||
printFunctionIndex(app);
|
|
||||||
if ( DocRun.getOption("-f").equals("true") )
|
|
||||||
printFunctions(app);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** print index-1.html .. alphabetical list of all functions */
|
|
||||||
public static void printFunctionIndex(DocApplication app) {
|
|
||||||
try {
|
|
||||||
DocWriter dw = new DocWriter("index-1.html");
|
|
||||||
dw.printHeader("Application " + app.getName() );
|
|
||||||
dw.printNavBar(app.getName(), null, INDEX );
|
|
||||||
DocFunction[] df = app.listFunctions();
|
|
||||||
Arrays.sort(df,new DocComparator(1,df[0]));
|
|
||||||
dw.printFunctionIndex(df);
|
|
||||||
dw.close();
|
|
||||||
} catch ( FileNotFoundException e ) { DocRun.log( e.getMessage() ); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/** print stylesheet.css */
|
|
||||||
public static void printStyleSheet(DocApplication app) {
|
|
||||||
try {
|
|
||||||
DocWriter dw = new DocWriter("stylesheet.css");
|
|
||||||
dw.printStyleSheet();
|
|
||||||
dw.close();
|
|
||||||
} catch ( FileNotFoundException e ) { DocRun.log( e.getMessage() ); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/** print index.html */
|
|
||||||
public static void printFrameSet(DocApplication app) {
|
|
||||||
try {
|
|
||||||
DocWriter dw = new DocWriter("index.html");
|
|
||||||
dw.printHeader("Application " + app.getName() );
|
|
||||||
dw.printFrameSet();
|
|
||||||
dw.close();
|
|
||||||
} catch ( FileNotFoundException e ) { DocRun.log( e.getMessage() ); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/** print app.html, list of prototypes */
|
|
||||||
public static void printAppDoc(DocApplication app) {
|
|
||||||
try {
|
|
||||||
DocWriter dw = new DocWriter("app.html");
|
|
||||||
dw.printHeader("Application " + app.getName() );
|
|
||||||
dw.printNavBar(app.getName(), null, APPLICATION );
|
|
||||||
dw.printElementTitle(app);
|
|
||||||
dw.printComment(app);
|
|
||||||
dw.printPrototypeList(app.listPrototypes(),"Prototypes");
|
|
||||||
dw.close();
|
|
||||||
} catch ( FileNotFoundException e ) { DocRun.log( e.getMessage() ); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/** print app-frame.html, content of left frame */
|
|
||||||
public static void printAppIndex(DocApplication app) {
|
|
||||||
try {
|
|
||||||
DocWriter dw = new DocWriter("app-frame.html");
|
|
||||||
dw.printHeader("Application " + app.getName() );
|
|
||||||
dw.printAppIndexTitle(app.getName());
|
|
||||||
dw.printAppIndexList((DocPrototype[])app.listPrototypes());
|
|
||||||
dw.close();
|
|
||||||
} catch ( FileNotFoundException e ) { DocRun.log( e.getMessage() ); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/** print all prototype-files, lists of functions */
|
|
||||||
public static void printPrototypes(DocApplication app) {
|
|
||||||
DocPrototype[] pt = app.listPrototypes();
|
|
||||||
for ( int i=0; i<pt.length; i++ ) {
|
|
||||||
try {
|
|
||||||
DocWriter dw = new DocWriter( pt[i].getDocFileName());
|
|
||||||
dw.printHeader("Application " + app.getName() + " / Prototype " + pt[i].getName());
|
|
||||||
dw.printNavBar(app.getName(), pt[i], PROTOTYPE );
|
|
||||||
dw.printElementTitle(pt[i]);
|
|
||||||
dw.printComment(pt[i]);
|
|
||||||
dw.printFunctionList(pt[i].listFunctions(DocElement.ACTION), "Actions");
|
|
||||||
dw.printFunctionList(pt[i].listFunctions(DocElement.TEMPLATE), "Templates");
|
|
||||||
dw.printFunctionList(pt[i].listFunctions(DocElement.FUNCTION), "Functions");
|
|
||||||
dw.printFunctionList(pt[i].listFunctions(DocElement.MACRO), "Macros");
|
|
||||||
dw.printFunctionList(pt[i].listFunctions(DocElement.SKIN), "Skins");
|
|
||||||
dw.printInheritance(pt[i]);
|
|
||||||
dw.close();
|
|
||||||
} catch ( FileNotFoundException e ) { DocRun.log( e.getMessage() ); }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** print all function sources */
|
|
||||||
public static void printFunctions(DocApplication app) {
|
|
||||||
DocFunction[] df = app.listFunctions();
|
|
||||||
for ( int i=0;i<df.length; i++ ) {
|
|
||||||
try {
|
|
||||||
File d = new File ( docDir, df[i].getDocPrototype().getName().toLowerCase() );
|
|
||||||
if ( !d.exists() )
|
|
||||||
d.mkdir();
|
|
||||||
DocWriter dw = new DocWriter( df[i].getDocPrototype().getName().toLowerCase() + "/" + df[i].getDocFileName() );
|
|
||||||
dw.printHeader( app.getName() + "." + df[i].getDocPrototype().getName() + "." + df[i].getName() );
|
|
||||||
dw.printNavBar( app.getName(), df[i].getDocPrototype(), DocHtmlWriter.METHOD);
|
|
||||||
dw.printFunction( df[i] );
|
|
||||||
dw.close();
|
|
||||||
} catch ( FileNotFoundException e ) { DocRun.log( e.getMessage() ); }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,47 +0,0 @@
|
||||||
// IPathElement.java
|
|
||||||
// Copyright (c) Hannes Wallnöfer 2001
|
|
||||||
|
|
||||||
package helma.framework;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface that objects need to implement to build a Helma URL tree. Apart from methods
|
|
||||||
* to retrieve the identifier and its child and parent elements, this interface defines a method
|
|
||||||
* that determines which prototype to use to add scripts and skins to an object. <p>
|
|
||||||
*
|
|
||||||
* Please note that this interface is still work in progress. You should expect it to get some
|
|
||||||
* additional methods that allow for looping through child elements, for example, or retrieving the
|
|
||||||
* parent element. <p>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
public interface IPathElement {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the name to be used to get this element from its parent
|
|
||||||
*/
|
|
||||||
public String getElementName ();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve a child element of this object by name.
|
|
||||||
*/
|
|
||||||
public IPathElement getChildElement (String name);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the parent element of this object.
|
|
||||||
*/
|
|
||||||
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 ();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
package helma.framework;
|
package helma.framework;
|
||||||
|
|
||||||
import java.rmi.*;
|
import java.rmi.*;
|
||||||
import java.util.Vector;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RMI interface for an application. Currently only execute is used and supported.
|
* RMI interface for an application. Currently only execute is used and supported.
|
||||||
|
@ -14,6 +13,8 @@ public interface IRemoteApp extends Remote {
|
||||||
|
|
||||||
public ResponseTrans execute (RequestTrans param) throws RemoteException;
|
public ResponseTrans execute (RequestTrans param) throws RemoteException;
|
||||||
|
|
||||||
|
public ResponseTrans get (String path, String sessionID) throws RemoteException;
|
||||||
|
|
||||||
public void ping () throws RemoteException;
|
public void ping () throws RemoteException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
// IReplicatedApp.java
|
|
||||||
// Copyright (c) Hannes Wallnöfer 2001
|
|
||||||
|
|
||||||
package helma.framework;
|
|
||||||
|
|
||||||
import java.rmi.*;
|
|
||||||
import java.util.Vector;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* RMI interface for an application that is able to replicate it's node cache.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public interface IReplicatedApp extends Remote {
|
|
||||||
|
|
||||||
public void replicateCache (Vector add, Vector delete) throws RemoteException;
|
|
||||||
|
|
||||||
}
|
|
|
@ -3,13 +3,14 @@
|
||||||
|
|
||||||
package helma.framework;
|
package helma.framework;
|
||||||
|
|
||||||
|
import FESI.Exceptions.EcmaScriptException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RedirectException is thrown internally when a response is redirected to a
|
* RedirectException is thrown internally when a response is redirected to a
|
||||||
* new URL.
|
* new URL.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class RedirectException extends RuntimeException {
|
public class RedirectException extends EcmaScriptException {
|
||||||
|
|
||||||
String url;
|
String url;
|
||||||
|
|
||||||
|
@ -17,17 +18,17 @@ public class RedirectException extends RuntimeException {
|
||||||
super ("Redirection Request to "+url);
|
super ("Redirection Request to "+url);
|
||||||
this.url = url;
|
this.url = url;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getMessage () {
|
public String getMessage () {
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void printStackTrace(java.io.PrintStream s) {
|
||||||
|
|
||||||
public void printStackTrace(java.io.PrintStream s) {
|
|
||||||
// do nothing
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void printStackTrace(java.io.PrintWriter w) {
|
public void printStackTrace(java.io.PrintWriter w) {
|
||||||
// do nothing
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,83 +6,52 @@ package helma.framework;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import helma.objectmodel.*;
|
import helma.objectmodel.*;
|
||||||
import helma.xmlrpc.Base64;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Transmitter for a request from the servlet client. Objects of this
|
* A Transmitter for a request from the servlet client. Objects of this
|
||||||
* class are directly exposed to JavaScript as global property req.
|
* class are directly exposed to JavaScript as global property req.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class RequestTrans implements Externalizable {
|
public class RequestTrans implements Serializable {
|
||||||
|
|
||||||
// the uri path of the request
|
|
||||||
public String path;
|
public String path;
|
||||||
// the request's session id
|
|
||||||
public String session;
|
public String session;
|
||||||
// the map of form and cookie data
|
private Hashtable values;
|
||||||
private Map values;
|
|
||||||
// the request method - 0 for GET, 1 for POST
|
|
||||||
private byte httpMethod = 0;
|
|
||||||
|
|
||||||
// this is used to hold the EcmaScript form data object
|
// this is used to hold the EcmaScript form data object
|
||||||
public transient Object data;
|
public transient Object data;
|
||||||
// when was execution started on this request?
|
// when was execution started on this request?
|
||||||
public transient long startTime;
|
public transient long startTime;
|
||||||
|
|
||||||
// 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 () {
|
public RequestTrans () {
|
||||||
httpMethod = 0;
|
super ();
|
||||||
values = new HashMap ();
|
values = new Hashtable ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public RequestTrans (Hashtable values) {
|
||||||
* Create a new request transmitter with the given data map.
|
this.values = values;
|
||||||
*/
|
|
||||||
public RequestTrans (byte method) {
|
|
||||||
httpMethod = method;
|
|
||||||
values = new HashMap ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Set a parameter value in this request transmitter.
|
|
||||||
*/
|
|
||||||
public void set (String name, Object value) {
|
public void set (String name, Object value) {
|
||||||
values.put (name, value);
|
values.put (name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Enumeration keys () {
|
||||||
|
return values.keys ();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a value from the requests map by key.
|
|
||||||
*/
|
|
||||||
public Object get (String name) {
|
public Object get (String name) {
|
||||||
try {
|
try {
|
||||||
return values.get (name);
|
return values.get (name);
|
||||||
} catch (Exception x) {
|
} catch (Exception x) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public Hashtable getReqData () {
|
||||||
* Get the data map for this request transmitter.
|
|
||||||
*/
|
|
||||||
public Map getRequestData () {
|
|
||||||
return values;
|
return values;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* The hash code is computed from the session id if available. This is used to
|
|
||||||
* detect multiple identic requests.
|
|
||||||
*/
|
|
||||||
public int hashCode () {
|
public int hashCode () {
|
||||||
return session == null ? super.hashCode () : session.hashCode ();
|
return session == null ? super.hashCode () : session.hashCode ();
|
||||||
}
|
}
|
||||||
|
@ -97,80 +66,10 @@ public class RequestTrans implements Externalizable {
|
||||||
RequestTrans other = (RequestTrans) what;
|
RequestTrans other = (RequestTrans) what;
|
||||||
return (session.equals (other.session) &&
|
return (session.equals (other.session) &&
|
||||||
path.equalsIgnoreCase (other.path) &&
|
path.equalsIgnoreCase (other.path) &&
|
||||||
values.equals (other.getRequestData ()));
|
values.equals (other.getReqData ()));
|
||||||
} catch (Exception x) {
|
} catch (Exception x) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return true if this object represents a HTTP GET Request.
|
|
||||||
*/
|
|
||||||
public boolean isGet () {
|
|
||||||
return httpMethod == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return true if this object represents a HTTP GET Request.
|
|
||||||
*/
|
|
||||||
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 ();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getUsername() {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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; }
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,112 +13,47 @@ import helma.util.*;
|
||||||
* class are directly exposed to JavaScript as global property res.
|
* class are directly exposed to JavaScript as global property res.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class ResponseTrans implements Externalizable {
|
public class ResponseTrans implements Serializable {
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the MIME content type of the response.
|
|
||||||
*/
|
|
||||||
public String contentType = "text/html";
|
public String contentType = "text/html";
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the charset of the response.
|
|
||||||
*/
|
|
||||||
public String charset;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* used to allow or disable client side caching
|
|
||||||
*/
|
|
||||||
public boolean cache = true;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used for HTTP response code, if 0 code 200 OK will be used.
|
|
||||||
*/
|
|
||||||
public int status = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used for HTTP authentication
|
|
||||||
*/
|
|
||||||
public String realm;
|
|
||||||
|
|
||||||
// name of the skin to be rendered after completion, if any
|
|
||||||
public transient String skin = null;
|
|
||||||
|
|
||||||
// the actual response
|
// the actual response
|
||||||
private byte[] response = null;
|
private byte[] response = null;
|
||||||
|
|
||||||
// contains the redirect URL
|
// contains the redirect URL
|
||||||
private String redir = null;
|
public String redirect = null;
|
||||||
|
|
||||||
// cookies
|
// cookies
|
||||||
String cookieKeys[];
|
public String cookieKeys[];
|
||||||
String cookieValues[];
|
public String cookieValues[];
|
||||||
int cookieDays[];
|
public int cookieDays[];
|
||||||
int nCookies = 0;
|
int nCookies = 0;
|
||||||
|
|
||||||
|
// used to allow or disable client side caching
|
||||||
|
public boolean cache = true;
|
||||||
|
|
||||||
// the buffer used to build the response
|
// the buffer used to build the response
|
||||||
private transient StringBuffer buffer = null;
|
private transient StringBuffer buffer = null;
|
||||||
// these are used to implement the _as_string variants for Hop templates.
|
// these are used to implement the _as_string variants for Hop templates.
|
||||||
private transient Stack buffers;
|
private transient Stack buffers;
|
||||||
|
|
||||||
// the path used to resolve skin names
|
// the buffers used to build the single body parts -
|
||||||
private transient Object skinpath = null;
|
// transient, response must be constructed before this is serialized
|
||||||
// the processed skinpath as array of Nodes or directory names
|
|
||||||
private transient Object[] translatedSkinpath = null;
|
|
||||||
|
|
||||||
static final long serialVersionUID = -8627370766119740844L;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* the buffers used to build the single body parts -
|
|
||||||
* transient, response must be constructed before this is serialized
|
|
||||||
*/
|
|
||||||
public transient String title, head, body, message, error;
|
public transient String title, head, body, message, error;
|
||||||
|
|
||||||
/**
|
// name of the skin to be rendered after completion, if any
|
||||||
* JavaScript object to make the values Map accessible to
|
public transient String mainSkin = null;
|
||||||
* script code as res.data
|
|
||||||
*/
|
|
||||||
public transient Object data;
|
|
||||||
|
|
||||||
// the map of form and cookie data
|
|
||||||
private transient Map values;
|
|
||||||
|
|
||||||
|
|
||||||
public ResponseTrans () {
|
public ResponseTrans () {
|
||||||
super ();
|
super ();
|
||||||
title = head = body = message = error = null;
|
title = head = body = message = error = "";
|
||||||
values = new HashMap ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a value from the responses map by key.
|
|
||||||
*/
|
|
||||||
public Object get (String name) {
|
|
||||||
try {
|
|
||||||
return values.get (name);
|
|
||||||
} catch (Exception x) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the data map for this response transmitter.
|
|
||||||
*/
|
|
||||||
public Map getResponseData () {
|
|
||||||
return values;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset the response object to its initial empty state.
|
|
||||||
*/
|
|
||||||
public void reset () {
|
public void reset () {
|
||||||
if (buffer != null)
|
if (buffer != null)
|
||||||
buffer.setLength (0);
|
buffer.setLength (0);
|
||||||
response = null;
|
redirect = null;
|
||||||
redir = null;
|
mainSkin = null;
|
||||||
skin = null;
|
title = head = body = message = error = "";
|
||||||
title = head = body = message = error = null;
|
|
||||||
values.clear ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -154,26 +89,6 @@ public class ResponseTrans implements Externalizable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility function that appends a <br> to whatever is written
|
|
||||||
*/
|
|
||||||
public void writeln (Object what) {
|
|
||||||
if (buffer == null)
|
|
||||||
buffer = new StringBuffer (512);
|
|
||||||
if (what != null)
|
|
||||||
buffer.append (what.toString ());
|
|
||||||
buffer.append ("<br />\r\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Append a part from a char array to the response buffer.
|
|
||||||
*/
|
|
||||||
public void writeCharArray (char[] c, int start, int length) {
|
|
||||||
if (buffer == null)
|
|
||||||
buffer = new StringBuffer (512);
|
|
||||||
buffer.append (c, start, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replace special characters with entities, including <, > and ", thus allowing
|
* Replace special characters with entities, including <, > and ", thus allowing
|
||||||
* no HTML tags.
|
* no HTML tags.
|
||||||
|
@ -212,18 +127,6 @@ public class ResponseTrans implements Externalizable {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encode HTML entities, but leave newlines alone. This is for the content of textarea forms.
|
|
||||||
*/
|
|
||||||
public void encodeForm (Object what) {
|
|
||||||
if (what != null) {
|
|
||||||
if (buffer == null)
|
|
||||||
buffer = new StringBuffer (512);
|
|
||||||
HtmlEncoder.encodeAll (what.toString (), buffer, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void append (String what) {
|
public void append (String what) {
|
||||||
if (what != null) {
|
if (what != null) {
|
||||||
if (buffer == null)
|
if (buffer == null)
|
||||||
|
@ -233,51 +136,23 @@ public class ResponseTrans implements Externalizable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void redirect (String url) throws RedirectException {
|
public void redirect (String url) throws RedirectException {
|
||||||
redir = url;
|
redirect = url;
|
||||||
throw new RedirectException (url);
|
throw new RedirectException (url);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getRedirect () {
|
|
||||||
return redir;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allow to directly set the byte array for the response. Calling this more than once will
|
|
||||||
* overwrite the previous output. We take a generic object as parameter to be able to
|
|
||||||
* generate a better error message, but it must be byte[].
|
|
||||||
*/
|
|
||||||
public void writeBinary (byte[] what) {
|
|
||||||
response = what;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This has to be called after writing to this response has finished and before it is shipped back to the
|
* This has to be called after writing to this response has finished and before it is shipped back to the
|
||||||
* web server. Transforms the string buffer into a char array to minimize size.
|
* web server. Transforms the string buffer into a char array to minimize size.
|
||||||
*/
|
*/
|
||||||
public synchronized void close (String cset) throws UnsupportedEncodingException {
|
public synchronized void close () {
|
||||||
// only use default charset if not explicitly set for this response.
|
if (buffer != null) {
|
||||||
if (charset == null)
|
response = buffer.toString ().getBytes ();
|
||||||
charset = cset;
|
buffer = null; // make sure this is done only once, even with more requsts attached
|
||||||
|
} else {
|
||||||
boolean error = false;
|
response = new byte[0];
|
||||||
if (response == null) {
|
|
||||||
if (buffer != null) {
|
|
||||||
try {
|
|
||||||
response = buffer.toString ().getBytes (charset);
|
|
||||||
} catch (UnsupportedEncodingException uee) {
|
|
||||||
error = true;
|
|
||||||
response = buffer.toString ().getBytes ();
|
|
||||||
}
|
|
||||||
buffer = null; // make sure this is done only once, even with more requsts attached
|
|
||||||
} else {
|
|
||||||
response = new byte[0];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
notifyAll ();
|
notifyAll ();
|
||||||
// if there was a problem with the encoding, let the app know
|
|
||||||
if (error)
|
|
||||||
throw new UnsupportedEncodingException (charset);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -302,26 +177,7 @@ public class ResponseTrans implements Externalizable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getContentType () {
|
public String getContentType () {
|
||||||
if (charset != null)
|
return contentType;
|
||||||
return contentType+"; charset="+charset;
|
|
||||||
return contentType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSkinpath (Object obj) {
|
|
||||||
this.skinpath = obj;
|
|
||||||
this.translatedSkinpath = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object getSkinpath () {
|
|
||||||
return skinpath;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTranslatedSkinpath (Object[] arr) {
|
|
||||||
this.translatedSkinpath = arr;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object[] getTranslatedSkinpath () {
|
|
||||||
return translatedSkinpath;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void setCookie (String key, String value) {
|
public synchronized void setCookie (String key, String value) {
|
||||||
|
@ -371,31 +227,6 @@ public class ResponseTrans implements Externalizable {
|
||||||
return cookieValues[i];
|
return cookieValues[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
public void readExternal (ObjectInput s) throws ClassNotFoundException, IOException {
|
|
||||||
contentType = (String) s.readObject ();
|
|
||||||
response = (byte[]) s.readObject ();
|
|
||||||
redir = (String) s.readObject ();
|
|
||||||
cookieKeys = (String[]) s.readObject ();
|
|
||||||
cookieValues = (String[]) s.readObject ();
|
|
||||||
cookieDays = (int[]) s.readObject ();
|
|
||||||
nCookies = s.readInt ();
|
|
||||||
cache = s.readBoolean ();
|
|
||||||
status = s.readInt ();
|
|
||||||
realm = (String) s.readObject ();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void writeExternal (ObjectOutput s) throws IOException {
|
|
||||||
s.writeObject (contentType);
|
|
||||||
s.writeObject (response);
|
|
||||||
s.writeObject (redir);
|
|
||||||
s.writeObject (cookieKeys);
|
|
||||||
s.writeObject (cookieValues);
|
|
||||||
s.writeObject (cookieDays);
|
|
||||||
s.writeInt (nCookies);
|
|
||||||
s.writeBoolean (cache);
|
|
||||||
s.writeInt (status);
|
|
||||||
s.writeObject (realm);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,12 @@
|
||||||
// ActionFile.java
|
// Action.java
|
||||||
// Copyright (c) Hannes Wallnöfer 1998-2000
|
// Copyright (c) Hannes Wallnöfer 1998-2000
|
||||||
|
|
||||||
package helma.scripting.fesi;
|
package helma.framework.core;
|
||||||
|
|
||||||
import helma.scripting.*;
|
import java.util.*;
|
||||||
import java.util.Vector;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import helma.framework.*;
|
import helma.framework.*;
|
||||||
import helma.framework.core.*;
|
import helma.objectmodel.IServer;
|
||||||
import helma.util.Updatable;
|
|
||||||
import FESI.Data.*;
|
import FESI.Data.*;
|
||||||
import FESI.Parser.*;
|
import FESI.Parser.*;
|
||||||
import FESI.AST.ASTFormalParameterList;
|
import FESI.AST.ASTFormalParameterList;
|
||||||
|
@ -21,64 +18,90 @@ import FESI.Exceptions.*;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An class that updates fesi interpreters with actionfiles and templates.
|
* An Action is a JavaScript function that is exposed as a URI. It is
|
||||||
|
* usually represented by a file with extension .hac (hop action file)
|
||||||
|
* that contains the pure JavaScript body of the function.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
public class FesiActionAdapter {
|
public class Action {
|
||||||
|
|
||||||
|
String name;
|
||||||
|
String functionName;
|
||||||
Prototype prototype;
|
Prototype prototype;
|
||||||
Application app;
|
Application app;
|
||||||
String sourceName;
|
File file;
|
||||||
|
long lastmod;
|
||||||
|
|
||||||
// this is the parsed function which can be easily applied to RequestEvaluator objects
|
// this is the parsed function which can be easily applied to RequestEvaluator objects
|
||||||
TypeUpdater pfunc;
|
TypeUpdater pfunc;
|
||||||
|
|
||||||
public FesiActionAdapter (ActionFile action) {
|
|
||||||
prototype = action.getPrototype ();
|
public Action (File file, String name, Prototype proto) {
|
||||||
app = action.getApplication ();
|
this.prototype = proto;
|
||||||
String content = action.getContent ();
|
this.app = proto.app;
|
||||||
String functionName = action.getFunctionName ();
|
this.name = name;
|
||||||
sourceName = action.toString ();
|
this.file = file;
|
||||||
try {
|
update (file);
|
||||||
pfunc = parseFunction (functionName, "arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10", content);
|
|
||||||
} catch (Throwable x) {
|
|
||||||
String message = x.getMessage ();
|
|
||||||
pfunc = new ErrorFeedback (functionName, message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* protected void update (FesiEvaluator fesi) throws Exception {
|
|
||||||
// app.logEvent ("Reading text template " + name);
|
|
||||||
|
|
||||||
FesiScriptingEnvironment scriptEnv = (FesiScriptingEnvironment) app.getScriptingEnvironment ();
|
public void update (File f) {
|
||||||
Iterator evals = scriptEnv.getEvaluators().iterator();
|
|
||||||
while (evals.hasNext ()) {
|
this.file = f;
|
||||||
try {
|
long fmod = file.lastModified ();
|
||||||
FesiEvaluator fesi = (FesiEvaluator) evals.next ();
|
if (lastmod == fmod)
|
||||||
updateEvaluator (fesi);
|
return;
|
||||||
} catch (Exception ignore) {}
|
|
||||||
|
try {
|
||||||
|
FileReader reader = new FileReader (file);
|
||||||
|
char cbuf[] = new char[(int) file.length ()];
|
||||||
|
reader.read (cbuf);
|
||||||
|
reader.close ();
|
||||||
|
String content = new String (cbuf);
|
||||||
|
update (content);
|
||||||
|
} catch (Exception filex) {
|
||||||
|
IServer.getLogger().log ("*** Error reading action file "+file+": "+filex);
|
||||||
}
|
}
|
||||||
} */
|
lastmod = fmod;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public void update (String content) throws Exception {
|
||||||
|
// IServer.getLogger().log ("Reading text template " + name);
|
||||||
|
|
||||||
|
functionName = name+"_hop_action";
|
||||||
|
|
||||||
|
try {
|
||||||
|
pfunc = parseFunction (functionName, "arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10", content);
|
||||||
|
} catch (Exception x) {
|
||||||
|
String message = x.getMessage ();
|
||||||
|
pfunc = new ErrorFeedback (functionName, message);
|
||||||
|
}
|
||||||
|
|
||||||
/* protected void remove () {
|
|
||||||
Iterator evals = app.typemgr.getRegisteredRequestEvaluators ();
|
Iterator evals = app.typemgr.getRegisteredRequestEvaluators ();
|
||||||
while (evals.hasNext ()) {
|
while (evals.hasNext ()) {
|
||||||
try {
|
try {
|
||||||
RequestEvaluator reval = (RequestEvaluator) evals.next ();
|
RequestEvaluator reval = (RequestEvaluator) evals.next ();
|
||||||
ObjectPrototype op = reval.getPrototype (prototype.getName());
|
updateRequestEvaluator (reval);
|
||||||
functionName = name+"_action";
|
|
||||||
ESValue esv = (ESValue) op.getProperty (functionName, functionName.hashCode());
|
|
||||||
if (esv instanceof ConstructedFunctionObject || esv instanceof ThrowException) {
|
|
||||||
op.deleteProperty (functionName, functionName.hashCode());
|
|
||||||
}
|
|
||||||
} catch (Exception ignore) {}
|
} catch (Exception ignore) {}
|
||||||
}
|
}
|
||||||
} */
|
}
|
||||||
|
|
||||||
|
|
||||||
public synchronized void updateEvaluator (FesiEvaluator fesi) throws EcmaScriptException {
|
public String getName () {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFunctionName () {
|
||||||
|
return functionName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public synchronized void updateRequestEvaluator (RequestEvaluator reval) throws EcmaScriptException {
|
||||||
if (pfunc != null)
|
if (pfunc != null)
|
||||||
pfunc.updateEvaluator (fesi);
|
pfunc.updateRequestEvaluator (reval);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected TypeUpdater parseFunction (String funcname, String params, String body) throws EcmaScriptException {
|
protected TypeUpdater parseFunction (String funcname, String params, String body) throws EcmaScriptException {
|
||||||
|
@ -122,10 +145,10 @@ public class FesiActionAdapter {
|
||||||
sl = (ASTStatementList) parser.StatementList();
|
sl = (ASTStatementList) parser.StatementList();
|
||||||
is.close();
|
is.close();
|
||||||
} catch (ParseException x) {
|
} catch (ParseException x) {
|
||||||
app.logEvent ("Error parsing file "+app.getName()+":"+sourceName+": "+x);
|
IServer.getLogger().log ("Error parsing file "+app.getName()+":"+prototype.getName()+"/"+file.getName()+": "+x);
|
||||||
throw new EcmaScriptParseException (x, new StringEvaluationSource(fulltext, null));
|
throw new EcmaScriptParseException (x, new StringEvaluationSource(fulltext, null));
|
||||||
} catch (Exception x) {
|
} catch (Exception x) {
|
||||||
app.logEvent ("Error parsing file "+app.getName()+":"+sourceName+": "+x);
|
IServer.getLogger().log ("Error parsing file "+app.getName()+":"+prototype.getName()+"/"+file.getName()+": "+x);
|
||||||
throw new RuntimeException (x.getMessage ());
|
throw new RuntimeException (x.getMessage ());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,15 +173,15 @@ public class FesiActionAdapter {
|
||||||
this.functionName = functionName;
|
this.functionName = functionName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateEvaluator (FesiEvaluator fesi) throws EcmaScriptException {
|
public void updateRequestEvaluator (RequestEvaluator reval) throws EcmaScriptException {
|
||||||
|
|
||||||
ObjectPrototype op = fesi.getPrototype (prototype.getName());
|
ObjectPrototype op = reval.getPrototype (prototype.getName());
|
||||||
|
|
||||||
EcmaScriptVariableVisitor vdvisitor = fesi.evaluator.getVarDeclarationVisitor();
|
EcmaScriptVariableVisitor vdvisitor = reval.evaluator.getVarDeclarationVisitor();
|
||||||
Vector vnames = vdvisitor.processVariableDeclarations(sl, fes);
|
Vector vnames = vdvisitor.processVariableDeclarations(sl, fes);
|
||||||
|
|
||||||
FunctionPrototype fp = ConstructedFunctionObject.makeNewConstructedFunction (
|
FunctionPrototype fp = ConstructedFunctionObject.makeNewConstructedFunction (
|
||||||
fesi.evaluator, functionName, fes,
|
reval.evaluator, functionName, fes,
|
||||||
fullFunctionText, fpl.getArguments(), vnames, sl);
|
fullFunctionText, fpl.getArguments(), vnames, sl);
|
||||||
op.putHiddenProperty (functionName, fp);
|
op.putHiddenProperty (functionName, fp);
|
||||||
}
|
}
|
||||||
|
@ -174,12 +197,12 @@ public class FesiActionAdapter {
|
||||||
errorMessage = msg;
|
errorMessage = msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateEvaluator (FesiEvaluator fesi) throws EcmaScriptException {
|
public void updateRequestEvaluator (RequestEvaluator reval) throws EcmaScriptException {
|
||||||
|
|
||||||
ObjectPrototype op = fesi.getPrototype (prototype.getName ());
|
ObjectPrototype op = reval.getPrototype (prototype.getName ());
|
||||||
|
|
||||||
FunctionPrototype fp = (FunctionPrototype) fesi.evaluator.getFunctionPrototype ();
|
FunctionPrototype fp = (FunctionPrototype) reval.evaluator.getFunctionPrototype ();
|
||||||
FunctionPrototype func = new ThrowException (functionName, fesi.evaluator, fp, errorMessage);
|
FunctionPrototype func = new ThrowException (functionName, reval.evaluator, fp, errorMessage);
|
||||||
op.putHiddenProperty (functionName, func);
|
op.putHiddenProperty (functionName, func);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -200,8 +223,38 @@ public class FesiActionAdapter {
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TypeUpdater {
|
interface TypeUpdater {
|
||||||
public void updateEvaluator (FesiEvaluator fesi) throws EcmaScriptException;
|
public void updateRequestEvaluator (RequestEvaluator reval) throws EcmaScriptException;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,14 +1,12 @@
|
||||||
// ESAppNode.java
|
// ESAppNode.java
|
||||||
// Copyright (c) Hannes Wallnöfer 1998-2000
|
// Copyright (c) Hannes Wallnöfer 1998-2000
|
||||||
|
|
||||||
package helma.scripting.fesi;
|
package helma.framework.core;
|
||||||
|
|
||||||
import helma.framework.core.*;
|
|
||||||
import helma.objectmodel.*;
|
import helma.objectmodel.*;
|
||||||
import FESI.Exceptions.*;
|
import FESI.Exceptions.*;
|
||||||
import FESI.Data.*;
|
import FESI.Data.*;
|
||||||
import FESI.Interpreter.Evaluator;
|
import FESI.Interpreter.Evaluator;
|
||||||
import java.util.Iterator;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ESApp represents the app node of an application, providing an app-wide transient shared
|
* ESApp represents the app node of an application, providing an app-wide transient shared
|
||||||
|
@ -20,18 +18,17 @@ public class ESAppNode extends ESNode {
|
||||||
private Application app;
|
private Application app;
|
||||||
private DatePrototype createtime;
|
private DatePrototype createtime;
|
||||||
|
|
||||||
public ESAppNode (INode node, FesiEvaluator eval) throws EcmaScriptException {
|
public ESAppNode (INode node, RequestEvaluator eval) throws EcmaScriptException {
|
||||||
super (eval.getPrototype("hopobject"), eval.getEvaluator(), node, eval);
|
super (eval.esNodePrototype, eval.evaluator, node, eval);
|
||||||
app = eval.getApplication();
|
app = eval.app;
|
||||||
createtime = new DatePrototype (evaluator, node.created());
|
createtime = new DatePrototype (eval.evaluator, node.created());
|
||||||
FunctionPrototype fp = (FunctionPrototype) evaluator.getFunctionPrototype();
|
FunctionPrototype fp = (FunctionPrototype) eval.evaluator.getFunctionPrototype();
|
||||||
putHiddenProperty("getThreads", new AppCountThreads ("getThreads", evaluator, fp));
|
putHiddenProperty("getThreads", new AppCountThreads ("getThreads", evaluator, fp));
|
||||||
putHiddenProperty("getMaxThreads", new AppCountEvaluators ("getMaxThreads", evaluator, fp));
|
putHiddenProperty("getMaxThreads", new AppCountEvaluators ("getMaxThreads", evaluator, fp));
|
||||||
putHiddenProperty("getFreeThreads", new AppCountFreeEvaluators ("getFreeThreads", evaluator, fp));
|
putHiddenProperty("getFreeThreads", new AppCountFreeEvaluators ("getFreeThreads", evaluator, fp));
|
||||||
putHiddenProperty("getActiveThreads", new AppCountActiveEvaluators ("getActiveThreads", evaluator, fp));
|
putHiddenProperty("getActiveThreads", new AppCountBusyEvaluators ("getActiveThreads", evaluator, fp));
|
||||||
putHiddenProperty("getMaxActiveThreads", new AppCountMaxActiveEvaluators ("getMaxActiveThreads", evaluator, fp));
|
putHiddenProperty("getMaxActiveThreads", new AppCountMaxBusyEvaluators ("getMaxActiveThreads", evaluator, fp));
|
||||||
putHiddenProperty("setMaxThreads", new AppSetNumberOfEvaluators ("setMaxThreads", evaluator, fp));
|
putHiddenProperty("setMaxThreads", new AppSetNumberOfEvaluators ("setMaxThreads", evaluator, fp));
|
||||||
putHiddenProperty("clearCache", new AppClearCache ("clearCache", evaluator, fp));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -39,32 +36,17 @@ public class ESAppNode extends ESNode {
|
||||||
*/
|
*/
|
||||||
public ESValue getProperty (String propname, int hash) throws EcmaScriptException {
|
public ESValue getProperty (String propname, int hash) throws EcmaScriptException {
|
||||||
if ("requestCount".equals (propname)) {
|
if ("requestCount".equals (propname)) {
|
||||||
return new ESNumber (app.getRequestCount ());
|
return new ESNumber (app.requestCount);
|
||||||
}
|
}
|
||||||
if ("xmlrpcCount".equals (propname)) {
|
if ("xmlrpcCount".equals (propname)) {
|
||||||
return new ESNumber (app.getXmlrpcCount ());
|
return new ESNumber (app.xmlrpcCount);
|
||||||
}
|
}
|
||||||
if ("errorCount".equals (propname)) {
|
if ("errorCount".equals (propname)) {
|
||||||
return new ESNumber (app.getErrorCount ());
|
return new ESNumber (app.errorCount);
|
||||||
}
|
}
|
||||||
if ("upSince".equals (propname)) {
|
if ("upSince".equals (propname)) {
|
||||||
return createtime;
|
return createtime;
|
||||||
}
|
}
|
||||||
if ("skinfiles".equals (propname)) {
|
|
||||||
ESObject skinz = new ObjectPrototype (null, evaluator);
|
|
||||||
for (Iterator it = app.getPrototypes().iterator(); it.hasNext(); ) {
|
|
||||||
Prototype p = (Prototype) it.next ();
|
|
||||||
ESObject proto = new ObjectPrototype (null, evaluator);
|
|
||||||
for (Iterator it2 = p.skins.values().iterator(); it2.hasNext(); ) {
|
|
||||||
SkinFile sf = (SkinFile) it2.next ();
|
|
||||||
String name = sf.getName ();
|
|
||||||
Skin skin = sf.getSkin ();
|
|
||||||
proto.putProperty (name, new ESString (skin.getSource ()), name.hashCode ());
|
|
||||||
}
|
|
||||||
skinz.putProperty (p.getName (), proto, p.getName ().hashCode ());
|
|
||||||
}
|
|
||||||
return skinz;
|
|
||||||
}
|
|
||||||
if ("__app__".equals (propname)) {
|
if ("__app__".equals (propname)) {
|
||||||
return new ESWrapper (app, evaluator);
|
return new ESWrapper (app, evaluator);
|
||||||
}
|
}
|
||||||
|
@ -77,7 +59,7 @@ public class ESAppNode extends ESNode {
|
||||||
super (fp, evaluator, name, 0);
|
super (fp, evaluator, name, 0);
|
||||||
}
|
}
|
||||||
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
||||||
return new ESNumber (app.countEvaluators ());
|
return new ESNumber (app.allThreads.size()-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,25 +68,25 @@ public class ESAppNode extends ESNode {
|
||||||
super (fp, evaluator, name, 0);
|
super (fp, evaluator, name, 0);
|
||||||
}
|
}
|
||||||
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
||||||
return new ESNumber (app.countFreeEvaluators ());
|
return new ESNumber (app.freeThreads.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AppCountActiveEvaluators extends BuiltinFunctionObject {
|
class AppCountBusyEvaluators extends BuiltinFunctionObject {
|
||||||
AppCountActiveEvaluators (String name, Evaluator evaluator, FunctionPrototype fp) {
|
AppCountBusyEvaluators (String name, Evaluator evaluator, FunctionPrototype fp) {
|
||||||
super (fp, evaluator, name, 0);
|
super (fp, evaluator, name, 0);
|
||||||
}
|
}
|
||||||
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
||||||
return new ESNumber (app.countActiveEvaluators ());
|
return new ESNumber (app.allThreads.size() - app.freeThreads.size() -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AppCountMaxActiveEvaluators extends BuiltinFunctionObject {
|
class AppCountMaxBusyEvaluators extends BuiltinFunctionObject {
|
||||||
AppCountMaxActiveEvaluators (String name, Evaluator evaluator, FunctionPrototype fp) {
|
AppCountMaxBusyEvaluators (String name, Evaluator evaluator, FunctionPrototype fp) {
|
||||||
super (fp, evaluator, name, 0);
|
super (fp, evaluator, name, 0);
|
||||||
}
|
}
|
||||||
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
||||||
return new ESNumber (app.countMaxActiveEvaluators ());
|
return new ESNumber (app.typemgr.countRegisteredRequestEvaluators () -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,7 +95,7 @@ public class ESAppNode extends ESNode {
|
||||||
super (fp, evaluator, name, 0);
|
super (fp, evaluator, name, 0);
|
||||||
}
|
}
|
||||||
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
||||||
return new ESNumber (app.countThreads ());
|
return new ESNumber (app.threadgroup.activeCount() -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,25 +107,59 @@ public class ESAppNode extends ESNode {
|
||||||
RequestEvaluator ev = new RequestEvaluator (app);
|
RequestEvaluator ev = new RequestEvaluator (app);
|
||||||
if (arguments.length != 1)
|
if (arguments.length != 1)
|
||||||
return ESBoolean.makeBoolean (false);
|
return ESBoolean.makeBoolean (false);
|
||||||
// add one to the number to compensate for the internal scheduler.
|
|
||||||
return ESBoolean.makeBoolean (app.setNumberOfEvaluators (1 + arguments[0].toInt32()));
|
return ESBoolean.makeBoolean (app.setNumberOfEvaluators (1 + arguments[0].toInt32()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AppClearCache extends BuiltinFunctionObject {
|
|
||||||
AppClearCache (String name, Evaluator evaluator, FunctionPrototype fp) {
|
|
||||||
super (fp, evaluator, name, 1);
|
|
||||||
}
|
|
||||||
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
|
||||||
app.clearCache ();
|
|
||||||
return ESBoolean.makeBoolean (true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public String toString () {
|
public String toString () {
|
||||||
return ("AppNode "+node.getElementName ());
|
return ("AppNode "+node.getNameOrID ());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,11 +2,9 @@
|
||||||
// Copyright (c) Hannes Wallnöfer 1998-2000
|
// Copyright (c) Hannes Wallnöfer 1998-2000
|
||||||
|
|
||||||
|
|
||||||
package helma.scripting.fesi;
|
package helma.framework.core;
|
||||||
|
|
||||||
import helma.objectmodel.*;
|
import helma.objectmodel.*;
|
||||||
import helma.objectmodel.db.*;
|
|
||||||
import helma.framework.core.*;
|
|
||||||
import helma.util.*;
|
import helma.util.*;
|
||||||
import FESI.Interpreter.*;
|
import FESI.Interpreter.*;
|
||||||
import FESI.Exceptions.*;
|
import FESI.Exceptions.*;
|
||||||
|
@ -24,106 +22,158 @@ import java.util.*;
|
||||||
public class ESNode extends ObjectPrototype {
|
public class ESNode extends ObjectPrototype {
|
||||||
|
|
||||||
INode node;
|
INode node;
|
||||||
|
|
||||||
// the cache node - persistent nodes have a transient property as a commodity to
|
|
||||||
// store temporary stuff.
|
|
||||||
INode cache;
|
INode cache;
|
||||||
// the ecmascript wrapper for the cache.
|
|
||||||
ESNode cacheWrapper;
|
|
||||||
|
|
||||||
// The handle of the wrapped Node. Makes ESNodes comparable without accessing the wrapped node.
|
// The ID of the wrapped Node. Makes ESNodes comparable without accessing the wrapped node.
|
||||||
NodeHandle handle;
|
String nodeID;
|
||||||
DbMapping dbmap;
|
DbMapping dbmap;
|
||||||
|
ESObject cacheWrapper;
|
||||||
Throwable lastError = null;
|
Throwable lastError = null;
|
||||||
FesiEvaluator eval;
|
RequestEvaluator eval;
|
||||||
|
|
||||||
/**
|
// used to create cache nodes
|
||||||
* Constructor used to create transient cache nodes
|
protected ESNode (INode node, RequestEvaluator eval) {
|
||||||
*/
|
super (eval.esNodePrototype, eval.evaluator);
|
||||||
public ESNode (INode node, FesiEvaluator eval) {
|
this.eval = eval;
|
||||||
super (eval.getPrototype("hopobject"), eval.getEvaluator());
|
this.node = node;
|
||||||
this.eval = eval;
|
cache = null;
|
||||||
this.node = node;
|
|
||||||
cache = null;
|
|
||||||
cacheWrapper = null;
|
|
||||||
|
|
||||||
// this is a transient node, set node handle to null
|
cacheWrapper = null;
|
||||||
handle = null;
|
nodeID = node.getID ();
|
||||||
|
dbmap = node.getDbMapping ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ESNode (ESObject prototype, Evaluator evaluator, Object obj, RequestEvaluator eval) {
|
||||||
|
super (prototype, evaluator);
|
||||||
|
// IServer.getLogger().log ("in ESNode constructor: "+o.getClass ());
|
||||||
|
this.eval = eval;
|
||||||
|
if (obj == null)
|
||||||
|
node = new Node ();
|
||||||
|
else if (obj instanceof ESWrapper)
|
||||||
|
node = (INode) ((ESWrapper) obj).getJavaObject ();
|
||||||
|
else if (obj instanceof INode)
|
||||||
|
node = (INode) obj;
|
||||||
|
else
|
||||||
|
node = new Node (obj.toString ());
|
||||||
|
// set nodeID to id of wrapped node
|
||||||
|
nodeID = node.getID ();
|
||||||
|
dbmap = node.getDbMapping ();
|
||||||
|
|
||||||
public ESNode (ESObject prototype, Evaluator evaluator, Object obj, FesiEvaluator eval) {
|
// get transient cache Node
|
||||||
super (prototype, evaluator);
|
cache = node.getCacheNode ();
|
||||||
// eval.app.logEvent ("in ESNode constructor: "+o.getClass ());
|
cacheWrapper = new ESNode (cache, eval);
|
||||||
this.eval = eval;
|
|
||||||
if (obj == null)
|
|
||||||
node = new TransientNode (null);
|
|
||||||
else if (obj instanceof ESWrapper)
|
|
||||||
node = (INode) ((ESWrapper) obj).getJavaObject ();
|
|
||||||
else if (obj instanceof INode)
|
|
||||||
node = (INode) obj;
|
|
||||||
else
|
|
||||||
node = new TransientNode (obj.toString ());
|
|
||||||
// set node handle to wrapped node
|
|
||||||
if (node instanceof Node)
|
|
||||||
handle = ((Node) node).getHandle ();
|
|
||||||
else
|
|
||||||
handle = null;
|
|
||||||
|
|
||||||
// cache Node is initialized on demend when it is needed
|
|
||||||
cache = null;
|
|
||||||
cacheWrapper = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the node has been invalidated. If so, it has to be re-fetched
|
* Check if the node has been invalidated. If so, it has to be re-fetched
|
||||||
* from the db via the app's node manager.
|
* from the db via the app's node manager.
|
||||||
*/
|
*/
|
||||||
protected void checkNode () {
|
private void checkNode () {
|
||||||
if (node.getState () == INode.INVALID) try {
|
if (node.getState () == INode.INVALID) try {
|
||||||
node = handle.getNode (eval.app.getWrappedNodeManager ());
|
setNode (eval.app.nmgr.getNode (node.getID (), node.getDbMapping ()));
|
||||||
} catch (Exception nx) {}
|
} catch (Exception nx) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
public INode getNode () {
|
public INode getNode () {
|
||||||
checkNode ();
|
checkNode ();
|
||||||
return node;
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNode (INode node) {
|
||||||
|
if (node != null) {
|
||||||
|
this.node = node;
|
||||||
|
nodeID = node.getID ();
|
||||||
|
dbmap = node.getDbMapping ();
|
||||||
|
eval.objectcache.put (node, this);
|
||||||
|
// get transient cache Node
|
||||||
|
cache = node.getCacheNode ();
|
||||||
|
cacheWrapper = new ESNode (cache, eval);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPrototype (String protoName) {
|
public void setPrototype (String protoName) {
|
||||||
checkNode ();
|
checkNode ();
|
||||||
node.setPrototype (protoName);
|
node.setPrototype (protoName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPrototypeName () {
|
public String getPrototypeName () {
|
||||||
return node.getPrototype ();
|
return node.getPrototype ();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getESClassName () {
|
public String getESClassName () {
|
||||||
return "HopObject";
|
return "HopObject";
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString () {
|
public String toString () {
|
||||||
if (node == null)
|
if (node == null)
|
||||||
return "<null>";
|
return "<null>";
|
||||||
return node.toString ();
|
return node.toString ();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toDetailString () {
|
public String toDetailString () {
|
||||||
return "ES:[Object: builtin " + this.getClass().getName() + ":" +
|
return "ES:[Object: builtin " + this.getClass().getName() + ":" +
|
||||||
((node == null) ? "null" : node.toString()) + "]";
|
((node == null) ? "null" : node.toString()) + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setError (Throwable e) {
|
protected void setError (Throwable e) {
|
||||||
lastError = e;
|
lastError = e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean setContent (ESValue what[]) {
|
||||||
|
checkNode ();
|
||||||
|
if (what.length > 0) {
|
||||||
|
if (what[0] instanceof ESString) {
|
||||||
|
node.setContent (what[0].toString ());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (what[0] instanceof ESWrapper) {
|
||||||
|
Object o = ((ESWrapper) what[0]).toJavaObject ();
|
||||||
|
if (o instanceof INode) {
|
||||||
|
try {
|
||||||
|
INode p = (INode) o;
|
||||||
|
node.setContent (p.getContent (), p.getContentType ());
|
||||||
|
return true;
|
||||||
|
} catch (Exception x) {
|
||||||
|
IServer.getLogger().log ("error in ESNode.setContent: "+x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (what[0] instanceof ESNode) {
|
||||||
|
INode i = ((ESNode) what[0]).getNode ();
|
||||||
|
try {
|
||||||
|
node.setContent (i.getContent (), i.getContentType ());
|
||||||
|
return true;
|
||||||
|
} catch (Exception x) {
|
||||||
|
IServer.getLogger().log ("error in ESNode.setContent: "+x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getContent () {
|
||||||
|
checkNode ();
|
||||||
|
if (node.getContentLength () == 0)
|
||||||
|
return null;
|
||||||
|
String contentType = node.getContentType ();
|
||||||
|
if (contentType != null && contentType.startsWith ("text/")) {
|
||||||
|
return node.getText ();
|
||||||
|
} else {
|
||||||
|
return node.getContent ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public boolean add (ESValue what[]) {
|
public boolean add (ESValue what[]) {
|
||||||
checkNode ();
|
checkNode ();
|
||||||
for (int i=0; i<what.length; i++)
|
for (int i=0; i<what.length; i++)
|
||||||
if (what[i] instanceof ESNode) {
|
if (what[i] instanceof ESNode) {
|
||||||
ESNode esn = (ESNode) what[i];
|
ESNode esn = (ESNode) what[i];
|
||||||
INode added = node.addNode (esn.getNode ());
|
INode added = node.addNode (esn.getNode ());
|
||||||
|
// only rewrap if a transient node was addet to a persistent one.
|
||||||
|
if (esn.getNode () instanceof helma.objectmodel.Node &&
|
||||||
|
!(node instanceof helma.objectmodel.Node))
|
||||||
|
esn.rewrap (added);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -153,25 +203,61 @@ public class ESNode extends ObjectPrototype {
|
||||||
throw new EcmaScriptException ("Can ony add Node objects as subnodes");
|
throw new EcmaScriptException ("Can ony add Node objects as subnodes");
|
||||||
ESNode esn = (ESNode) what[1];
|
ESNode esn = (ESNode) what[1];
|
||||||
INode added = node.addNode (esn.getNode (), (int) what[0].toInt32 ());
|
INode added = node.addNode (esn.getNode (), (int) what[0].toInt32 ());
|
||||||
|
// only rewrap if a transient node was addet to a persistent one.
|
||||||
|
if (esn.getNode () instanceof helma.objectmodel.Node &&
|
||||||
|
!(node instanceof helma.objectmodel.Node))
|
||||||
|
esn.rewrap (added);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is necessary to remap ESNodes to their new peers
|
||||||
|
* when they go from transient to persistent state.
|
||||||
|
*/
|
||||||
|
protected void rewrap (INode newnode) {
|
||||||
|
// IServer.getLogger().log ("rewrapping "+this+" from "+node+" to "+newnode);
|
||||||
|
if (newnode == null)
|
||||||
|
throw new RuntimeException ("Non-consistent check-in detected in rewrap ()");
|
||||||
|
INode oldnode = node;
|
||||||
|
if (oldnode == newnode) {
|
||||||
|
// IServer.getLogger().log ("loop detected or new peers unchanged in rewrap");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// set node and nodeID to new node
|
||||||
|
node = newnode;
|
||||||
|
nodeID = node.getID ();
|
||||||
|
dbmap = node.getDbMapping ();
|
||||||
|
|
||||||
|
int l = oldnode.numberOfNodes ();
|
||||||
|
for (int i=0; i<l; i++) {
|
||||||
|
INode next = oldnode.getSubnodeAt (i);
|
||||||
|
ESNode esn = eval.getNodeWrapperFromCache (next);
|
||||||
|
// IServer.getLogger().log ("rewrapping node: "+next+" -> "+esn);
|
||||||
|
if (esn != null) {
|
||||||
|
esn.rewrap (newnode.getSubnodeAt (i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (Enumeration e=oldnode.properties (); e.hasMoreElements (); ) {
|
||||||
|
IProperty p = oldnode.get ((String) e.nextElement (), false);
|
||||||
|
if (p != null && p.getType () == IProperty.NODE) {
|
||||||
|
INode next = p.getNodeValue ();
|
||||||
|
ESNode esn = eval.getNodeWrapperFromCache (next);
|
||||||
|
if (esn != null) {
|
||||||
|
esn.rewrap (newnode.getNode (p.getName (), false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove node itself or one or more subnodes.
|
* Remove one or more subnodes.
|
||||||
*/
|
*/
|
||||||
public boolean remove (ESValue args[]) {
|
public boolean remove (ESValue args[]) {
|
||||||
checkNode ();
|
checkNode ();
|
||||||
// semantics: if called without arguments, remove self.
|
for (int i=0; i<args.length; i++) {
|
||||||
// otherwise, remove given subnodes.
|
if (args[i] instanceof ESNode) {
|
||||||
if (args.length == 0) {
|
ESNode esn = (ESNode) args[i];
|
||||||
return node.remove ();
|
node.removeNode (esn.getNode ());
|
||||||
} else {
|
|
||||||
for (int i=0; i<args.length; i++) {
|
|
||||||
if (args[i] instanceof ESNode) {
|
|
||||||
ESNode esn = (ESNode) args[i];
|
|
||||||
node.removeNode (esn.getNode ());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -230,8 +316,9 @@ public class ESNode extends ObjectPrototype {
|
||||||
|
|
||||||
public void putProperty(String propertyName, ESValue propertyValue, int hash) throws EcmaScriptException {
|
public void putProperty(String propertyName, ESValue propertyValue, int hash) throws EcmaScriptException {
|
||||||
checkNode ();
|
checkNode ();
|
||||||
// eval.app.logEvent ("put property called: "+propertyName+", "+propertyValue.getClass());
|
// IServer.getLogger().log ("put property called: "+propertyName+", "+propertyValue.getClass());
|
||||||
if ("cache".equalsIgnoreCase (propertyName))
|
if ("lastmodified".equalsIgnoreCase (propertyName) || "created".equalsIgnoreCase (propertyName) ||
|
||||||
|
"contentlength".equalsIgnoreCase (propertyName) || "cache".equalsIgnoreCase (propertyName))
|
||||||
throw new EcmaScriptException ("Can't modify read-only property \""+propertyName+"\".");
|
throw new EcmaScriptException ("Can't modify read-only property \""+propertyName+"\".");
|
||||||
|
|
||||||
if ("subnodeRelation".equalsIgnoreCase (propertyName)) {
|
if ("subnodeRelation".equalsIgnoreCase (propertyName)) {
|
||||||
|
@ -239,15 +326,9 @@ public class ESNode extends ObjectPrototype {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if the property is write protected, i.e. the type.property file describes it as [readonly]
|
if ("contenttype".equalsIgnoreCase (propertyName))
|
||||||
DbMapping dbm = node.getDbMapping ();
|
node.setContentType (propertyValue.toString ());
|
||||||
if (dbm != null) {
|
else if (propertyValue instanceof ESNull)
|
||||||
Relation rel = dbm.getPropertyRelation (propertyName);
|
|
||||||
if (rel != null && rel.isReadonly ())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (propertyValue instanceof ESNull || propertyValue instanceof ESUndefined)
|
|
||||||
node.unset (propertyName);
|
node.unset (propertyName);
|
||||||
else if (propertyValue instanceof ESString)
|
else if (propertyValue instanceof ESString)
|
||||||
node.setString (propertyName, propertyValue.toString ());
|
node.setString (propertyName, propertyValue.toString ());
|
||||||
|
@ -261,9 +342,14 @@ public class ESNode extends ObjectPrototype {
|
||||||
// long now = System.currentTimeMillis ();
|
// long now = System.currentTimeMillis ();
|
||||||
ESNode esn = (ESNode) propertyValue;
|
ESNode esn = (ESNode) propertyValue;
|
||||||
node.setNode (propertyName, esn.getNode ());
|
node.setNode (propertyName, esn.getNode ());
|
||||||
// eval.app.logEvent ("*** spent "+(System.currentTimeMillis () - now)+" ms to set property "+propertyName);
|
if (esn.getNode () instanceof helma.objectmodel.Node &&
|
||||||
|
!(node instanceof helma.objectmodel.Node)) {
|
||||||
|
INode newnode = node.getNode (propertyName, false);
|
||||||
|
esn.rewrap (newnode);
|
||||||
|
}
|
||||||
|
// IServer.getLogger().log ("*** spent "+(System.currentTimeMillis () - now)+" ms to set property "+propertyName);
|
||||||
} else {
|
} else {
|
||||||
// eval.app.logEvent ("got "+propertyValue.getClass ());
|
// IServer.getLogger().log ("got "+propertyValue.getClass ());
|
||||||
// A persistent node can't store anything other than the types above, so throw an exception
|
// A persistent node can't store anything other than the types above, so throw an exception
|
||||||
// throw new EcmaScriptException ("Can't set a JavaScript Object or Array as property of "+node);
|
// throw new EcmaScriptException ("Can't set a JavaScript Object or Array as property of "+node);
|
||||||
node.setJavaObject (propertyName, propertyValue.toJavaObject ());
|
node.setJavaObject (propertyName, propertyValue.toJavaObject ());
|
||||||
|
@ -271,25 +357,25 @@ public class ESNode extends ObjectPrototype {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean deleteProperty(String propertyName, int hash) throws EcmaScriptException {
|
public boolean deleteProperty(String propertyName, int hash) throws EcmaScriptException {
|
||||||
checkNode ();
|
checkNode ();
|
||||||
// eval.app.logEvent ("delete property called: "+propertyName);
|
// IServer.getLogger().log ("delete property called: "+propertyName);
|
||||||
if (node.get (propertyName, false) != null) {
|
if (node.get (propertyName, false) != null) {
|
||||||
node.unset (propertyName);
|
node.unset (propertyName);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return super.deleteProperty (propertyName, hash);
|
return super.deleteProperty (propertyName, hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ESValue getProperty (int i) throws EcmaScriptException {
|
public ESValue getProperty (int i) throws EcmaScriptException {
|
||||||
checkNode ();
|
checkNode ();
|
||||||
INode n = node.getSubnodeAt (i);
|
INode n = node.getSubnodeAt (i);
|
||||||
if (n == null)
|
if (n == null)
|
||||||
return ESNull.theNull;
|
return ESNull.theNull;
|
||||||
return eval.getNodeWrapper (n);
|
return eval.getNodeWrapper (n);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void putProperty(int index, ESValue propertyValue) throws EcmaScriptException {
|
public void putProperty(int index, ESValue propertyValue) throws EcmaScriptException {
|
||||||
checkNode ();
|
checkNode ();
|
||||||
if (propertyValue instanceof ESNode) {
|
if (propertyValue instanceof ESNode) {
|
||||||
ESNode n = (ESNode) propertyValue;
|
ESNode n = (ESNode) propertyValue;
|
||||||
node.addNode (n.getNode (), index);
|
node.addNode (n.getNode (), index);
|
||||||
|
@ -298,55 +384,29 @@ public class ESNode extends ObjectPrototype {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve a property from the node object or the underlying EcmaScript prototype.
|
|
||||||
* Normally we would first check the node object and then the prototype, but since
|
|
||||||
* node properties are potentially expensive to look up because they require database
|
|
||||||
* queries, we do the prototype lookup first. This usually doesn't cause any confusion
|
|
||||||
* because generally things are divided cleanly between prototype and object - the
|
|
||||||
* first holds the functions, the latter the mapped data properties.
|
|
||||||
*/
|
|
||||||
public ESValue getProperty(String propertyName, int hash) throws EcmaScriptException {
|
public ESValue getProperty(String propertyName, int hash) throws EcmaScriptException {
|
||||||
checkNode ();
|
checkNode ();
|
||||||
// eval.app.logEvent ("get property called: "+propertyName);
|
// IServer.getLogger().log ("get property called: "+propertyName);
|
||||||
ESValue retval = super.getProperty (propertyName, hash);
|
ESValue retval = super.getProperty (propertyName, hash);
|
||||||
if (! (retval instanceof ESUndefined))
|
if (! (retval instanceof ESUndefined))
|
||||||
return retval;
|
return retval;
|
||||||
return getNodeProperty (propertyName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
if ("cache".equalsIgnoreCase (propertyName) && cache != null)
|
||||||
* Retrieve a property only from the node itself, not the underlying EcmaScript prototype object.
|
return cacheWrapper;
|
||||||
* This is called directly when we call get(x) on a hopobject, since we don't want to return
|
if ("created".equalsIgnoreCase (propertyName))
|
||||||
* the prototype functions in that case.
|
return new DatePrototype (evaluator, node.created ());
|
||||||
*/
|
if ("lastmodified".equalsIgnoreCase (propertyName))
|
||||||
public ESValue getNodeProperty (String propertyName) throws EcmaScriptException {
|
return new DatePrototype (evaluator, node.lastModified ());
|
||||||
|
if ("contenttype".equalsIgnoreCase (propertyName))
|
||||||
|
return new ESString (node.getContentType ());
|
||||||
|
if ("contentlength".equalsIgnoreCase (propertyName))
|
||||||
|
return new ESNumber (node.getContentLength ());
|
||||||
|
|
||||||
// persistent or persistent capable nodes have a cache property that's a transient node.
|
|
||||||
// it it hasn't requested before, initialize it now
|
|
||||||
if ("cache".equalsIgnoreCase (propertyName) && node instanceof Node) {
|
|
||||||
cache = node.getCacheNode ();
|
|
||||||
if (cacheWrapper == null)
|
|
||||||
cacheWrapper = new ESNode (cache, eval);
|
|
||||||
else
|
|
||||||
cacheWrapper.node = cache;
|
|
||||||
return cacheWrapper;
|
|
||||||
}
|
|
||||||
if ("subnodeRelation".equalsIgnoreCase (propertyName)) {
|
if ("subnodeRelation".equalsIgnoreCase (propertyName)) {
|
||||||
String rel = node.getSubnodeRelation ();
|
String rel = node.getSubnodeRelation ();
|
||||||
return rel == null ? (ESValue) ESNull.theNull : new ESString (rel);
|
return rel == null ? (ESValue) ESNull.theNull : new ESString (rel);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ("_id".equals (propertyName))
|
|
||||||
return new ESString (node.getID ());
|
|
||||||
if ("_parent".equals (propertyName)) {
|
|
||||||
INode n = node.getParent ();
|
|
||||||
if (n != null)
|
|
||||||
return eval.getNodeWrapper (n);
|
|
||||||
else
|
|
||||||
return ESNull.theNull;
|
|
||||||
}
|
|
||||||
|
|
||||||
// this is not very nice, but as a hack we return the id of a node as node.__id__
|
// this is not very nice, but as a hack we return the id of a node as node.__id__
|
||||||
if (propertyName.startsWith ("__") && propertyName.endsWith ("__"))
|
if (propertyName.startsWith ("__") && propertyName.endsWith ("__"))
|
||||||
return getInternalProperty (propertyName);
|
return getInternalProperty (propertyName);
|
||||||
|
@ -363,7 +423,7 @@ public class ESNode extends ObjectPrototype {
|
||||||
}
|
}
|
||||||
if (p.getType () == IProperty.BOOLEAN)
|
if (p.getType () == IProperty.BOOLEAN)
|
||||||
return ESBoolean.makeBoolean (p.getBooleanValue ());
|
return ESBoolean.makeBoolean (p.getBooleanValue ());
|
||||||
if (p.getType () == IProperty.DATE)
|
if (p.getType () == IProperty.DATE)
|
||||||
return new DatePrototype (evaluator, p.getDateValue ());
|
return new DatePrototype (evaluator, p.getDateValue ());
|
||||||
if (p.getType () == IProperty.INTEGER)
|
if (p.getType () == IProperty.INTEGER)
|
||||||
return new ESNumber ((double) p.getIntegerValue ());
|
return new ESNumber ((double) p.getIntegerValue ());
|
||||||
|
@ -388,14 +448,9 @@ public class ESNode extends ObjectPrototype {
|
||||||
return ESNull.theNull;
|
return ESNull.theNull;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Some internal properties defined for every Node object. These are most commonly
|
|
||||||
* used for debugging Helma applications.
|
|
||||||
*/
|
|
||||||
private ESValue getInternalProperty (String propertyName) throws EcmaScriptException {
|
private ESValue getInternalProperty (String propertyName) throws EcmaScriptException {
|
||||||
if ("__id__".equalsIgnoreCase (propertyName)) {
|
if ("__id__".equalsIgnoreCase (propertyName))
|
||||||
return new ESString (node.getID ());
|
return new ESString (node.getID ());
|
||||||
}
|
|
||||||
if ("__prototype__".equalsIgnoreCase (propertyName)) {
|
if ("__prototype__".equalsIgnoreCase (propertyName)) {
|
||||||
String p = node.getPrototype ();
|
String p = node.getPrototype ();
|
||||||
if (p == null)
|
if (p == null)
|
||||||
|
@ -418,27 +473,16 @@ public class ESNode extends ObjectPrototype {
|
||||||
if ("__hash__".equals (propertyName))
|
if ("__hash__".equals (propertyName))
|
||||||
return new ESString (""+node.hashCode ());
|
return new ESString (""+node.hashCode ());
|
||||||
if ("__node__".equals (propertyName))
|
if ("__node__".equals (propertyName))
|
||||||
return new ESWrapper (node, evaluator);
|
return ESLoader.normalizeObject (node, evaluator);
|
||||||
if ("__created__".equalsIgnoreCase (propertyName))
|
|
||||||
return new DatePrototype (evaluator, node.created ());
|
|
||||||
if ("__lastmodified__".equalsIgnoreCase (propertyName))
|
|
||||||
return new DatePrototype (evaluator, node.lastModified ());
|
|
||||||
|
|
||||||
return ESNull.theNull;
|
return ESNull.theNull;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean clearCache () {
|
|
||||||
checkNode ();
|
|
||||||
node.clearCacheNode ();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Enumeration getAllProperties () {
|
public Enumeration getAllProperties () {
|
||||||
return getProperties ();
|
return getProperties ();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Enumeration getProperties () {
|
public Enumeration getProperties () {
|
||||||
checkNode ();
|
checkNode ();
|
||||||
return node.properties ();
|
return node.properties ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -457,13 +501,9 @@ public class ESNode extends ObjectPrototype {
|
||||||
public void clearError() {
|
public void clearError() {
|
||||||
lastError = null;
|
lastError = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object toJavaObject () {
|
/**
|
||||||
return getNode ();
|
* An ESNode equals another object if it is an ESNode that wraps the same INode
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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!
|
* or the wrapped INode itself. FIXME: doesen't check dbmapping/type!
|
||||||
*/
|
*/
|
||||||
public boolean equals (Object what) {
|
public boolean equals (Object what) {
|
||||||
|
@ -473,19 +513,62 @@ public class ESNode extends ObjectPrototype {
|
||||||
return true;
|
return true;
|
||||||
if (what instanceof ESNode) {
|
if (what instanceof ESNode) {
|
||||||
ESNode other = (ESNode) what;
|
ESNode other = (ESNode) what;
|
||||||
if (handle != null)
|
return (other.nodeID.equals (nodeID) && other.dbmap == dbmap);
|
||||||
return handle.equals (other.handle);
|
|
||||||
else
|
|
||||||
return (node == other.node);
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ESValue getDefaultValue(int hint) throws EcmaScriptException {
|
|
||||||
return new ESString (this.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
} // class ESNode
|
} // class ESNode
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
126
src/helma/framework/core/ESRequestData.java
Normal file
126
src/helma/framework/core/ESRequestData.java
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
// ESRequestData.java
|
||||||
|
// Copyright (c) Hannes Wallnöfer 1998-2000
|
||||||
|
|
||||||
|
|
||||||
|
package helma.framework.core;
|
||||||
|
|
||||||
|
import FESI.Data.*;
|
||||||
|
import FESI.Exceptions.*;
|
||||||
|
import FESI.Interpreter.Evaluator;
|
||||||
|
import java.util.*;
|
||||||
|
import helma.objectmodel.INode;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An EcmaScript object that makes stuff in a hashtable accessible as its properties
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class ESRequestData extends ESWrapper {
|
||||||
|
|
||||||
|
private Hashtable data;
|
||||||
|
private RequestEvaluator reval;
|
||||||
|
|
||||||
|
public ESRequestData (RequestEvaluator reval) {
|
||||||
|
super (new Object(), reval.evaluator);
|
||||||
|
this.reval = reval;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setData (Hashtable data) {
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overridden to make the object read-only
|
||||||
|
*/
|
||||||
|
public void putProperty(String propertyName, ESValue propertyValue, int hash) throws EcmaScriptException {
|
||||||
|
throw new EcmaScriptException ("Can't set property, object is read-only");
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean deleteProperty(String propertyName, int hash) throws EcmaScriptException {
|
||||||
|
throw new EcmaScriptException ("Can't delete property, object is read-only");
|
||||||
|
}
|
||||||
|
|
||||||
|
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 reval.getNodeWrapper ((INode) val);
|
||||||
|
|
||||||
|
return ESLoader.normalizeValue(val, evaluator);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Enumeration getAllProperties () {
|
||||||
|
return getProperties ();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Enumeration getProperties () {
|
||||||
|
if (data == null)
|
||||||
|
return new Hashtable().keys();
|
||||||
|
return data.keys();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
125
src/helma/framework/core/ESUser.java
Normal file
125
src/helma/framework/core/ESUser.java
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
// ESUser.java
|
||||||
|
// Copyright (c) Hannes Wallnöfer 1998-2000
|
||||||
|
|
||||||
|
package helma.framework.core;
|
||||||
|
|
||||||
|
import helma.objectmodel.*;
|
||||||
|
import FESI.Interpreter.*;
|
||||||
|
import FESI.Exceptions.*;
|
||||||
|
import FESI.Data.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ESUser is a special kind of Node object that represents a user of
|
||||||
|
* a HOP application. The actual user session data are kept in class User.
|
||||||
|
* If the user is logged in as a registered member, the wrapped node represents
|
||||||
|
* the user object in the database, while for anonymous surfers the node object
|
||||||
|
* is just a transient node. <p>
|
||||||
|
* This means that the wrapped node will be swapped when the user logs in or out.
|
||||||
|
* To save session state across logins and logouts, the
|
||||||
|
* cache property of the user object stays the same for the whole time the user
|
||||||
|
* spends on this site.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class ESUser extends ESNode {
|
||||||
|
|
||||||
|
// if the user is online, this is his/her online session object
|
||||||
|
public User user;
|
||||||
|
|
||||||
|
public ESUser (INode node, RequestEvaluator eval) {
|
||||||
|
super (eval.esUserPrototype, eval.evaluator, node, eval);
|
||||||
|
user = (User) eval.app.activeUsers.get (node.getNameOrID ());
|
||||||
|
if (user == null)
|
||||||
|
user = (User) eval.app.sessions.get (node.getNameOrID ());
|
||||||
|
if (user != null) {
|
||||||
|
cache = user.cache;
|
||||||
|
cacheWrapper = new ESNode (cache, eval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overrides getProperty to return the uid (which is not a regular property)
|
||||||
|
*/
|
||||||
|
public ESValue getProperty (String propname, int hash) throws EcmaScriptException {
|
||||||
|
if ("uid".equals (propname)) {
|
||||||
|
if (user == null || user.uid == null)
|
||||||
|
return ESNull.theNull;
|
||||||
|
else
|
||||||
|
return new ESString (user.uid);
|
||||||
|
}
|
||||||
|
if ("sessionID".equals (propname)) {
|
||||||
|
return new ESString (user.getSessionID ());
|
||||||
|
}
|
||||||
|
return super.getProperty (propname, hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setUser (User user) {
|
||||||
|
if (this.user != user) {
|
||||||
|
this.user = user;
|
||||||
|
cache = user.cache;
|
||||||
|
}
|
||||||
|
cacheWrapper = new ESNode (cache, eval);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNode (INode node) {
|
||||||
|
if (node != null) {
|
||||||
|
this.node = node;
|
||||||
|
nodeID = node.getID ();
|
||||||
|
dbmap = node.getDbMapping ();
|
||||||
|
eval.objectcache.put (node, this);
|
||||||
|
// we don't take over the transient cache from the node,
|
||||||
|
// because we always use the one from the user object.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String toString () {
|
||||||
|
return ("UserObject "+node.getNameOrID ());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
120
src/helma/framework/core/FunctionFile.java
Normal file
120
src/helma/framework/core/FunctionFile.java
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
// FunctionFile.java
|
||||||
|
// Copyright (c) Hannes Wallnöfer 1998-2000
|
||||||
|
|
||||||
|
package helma.framework.core;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.io.*;
|
||||||
|
import helma.framework.*;
|
||||||
|
import helma.objectmodel.IServer;
|
||||||
|
import FESI.Data.ObjectPrototype;
|
||||||
|
import FESI.Exceptions.EcmaScriptException;
|
||||||
|
import FESI.Interpreter.*;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This represents a File containing JavaScript functions for a given Object.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
public class FunctionFile {
|
||||||
|
|
||||||
|
String name;
|
||||||
|
Prototype prototype;
|
||||||
|
Application app;
|
||||||
|
File file;
|
||||||
|
long lastmod;
|
||||||
|
|
||||||
|
public FunctionFile (File file, String name, Prototype proto) {
|
||||||
|
this.prototype = proto;
|
||||||
|
this.app = proto.app;
|
||||||
|
this.name = name;
|
||||||
|
this.file = file;
|
||||||
|
update (file);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void update (File f) {
|
||||||
|
|
||||||
|
this.file = f;
|
||||||
|
|
||||||
|
long fmod = file.lastModified ();
|
||||||
|
if (lastmod == fmod)
|
||||||
|
return;
|
||||||
|
|
||||||
|
lastmod = fmod;
|
||||||
|
// app.typemgr.readFunctionFile (file, prototype.getName ());
|
||||||
|
Iterator evals = app.typemgr.getRegisteredRequestEvaluators ();
|
||||||
|
while (evals.hasNext ()) {
|
||||||
|
try {
|
||||||
|
RequestEvaluator reval = (RequestEvaluator) evals.next ();
|
||||||
|
updateRequestEvaluator (reval);
|
||||||
|
} catch (Exception ignore) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void updateRequestEvaluator (RequestEvaluator reval) {
|
||||||
|
|
||||||
|
EvaluationSource es = new FileEvaluationSource(file.getPath(), null);
|
||||||
|
FileReader fr = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
fr = new FileReader(file);
|
||||||
|
ObjectPrototype op = reval.getPrototype (prototype.getName());
|
||||||
|
reval.evaluator.evaluate(fr, op, es, false);
|
||||||
|
} catch (IOException e) {
|
||||||
|
IServer.getLogger().log ("Error parsing function file "+app.getName()+":"+prototype.getName()+"/"+file.getName()+": "+e);
|
||||||
|
} catch (EcmaScriptException e) {
|
||||||
|
IServer.getLogger().log ("Error parsing function file "+app.getName()+":"+prototype.getName()+"/"+file.getName()+": "+e);
|
||||||
|
} finally {
|
||||||
|
if (fr!=null) {
|
||||||
|
try {
|
||||||
|
fr.close();
|
||||||
|
} catch (IOException ignore) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
// HopExtension.java
|
// HopExtension.java
|
||||||
// Copyright (c) Hannes Wallnöfer 1998-2000
|
// Copyright (c) Hannes Wallnöfer 1998-2000
|
||||||
|
|
||||||
package helma.scripting.fesi;
|
package helma.framework.core;
|
||||||
|
|
||||||
import helma.framework.*;
|
|
||||||
import helma.framework.core.*;
|
|
||||||
import helma.objectmodel.*;
|
import helma.objectmodel.*;
|
||||||
import helma.util.*;
|
import helma.util.*;
|
||||||
import helma.framework.IPathElement;
|
|
||||||
import FESI.Interpreter.*;
|
import FESI.Interpreter.*;
|
||||||
import FESI.Exceptions.*;
|
import FESI.Exceptions.*;
|
||||||
import FESI.Extensions.*;
|
import FESI.Extensions.*;
|
||||||
|
@ -17,34 +14,33 @@ import java.util.*;
|
||||||
import java.text.*;
|
import java.text.*;
|
||||||
import org.xml.sax.InputSource;
|
import org.xml.sax.InputSource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the basic Extension for FESI interpreters used in Helma. It sets up
|
* This is the basic Extension for FESI interpreters used in HOP. It sets up
|
||||||
* varios constructors, global functions and properties on the HopObject prototype
|
* varios constructors, global functions and properties etc.
|
||||||
* (Node objects), the user prototype, the global prototype etc.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class HopExtension {
|
public class HopExtension {
|
||||||
|
|
||||||
protected Application app;
|
protected Application app;
|
||||||
protected FesiEvaluator fesi;
|
|
||||||
|
|
||||||
public HopExtension (Application app) {
|
public HopExtension () {
|
||||||
this.app = app;
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called by the evaluator after the extension is loaded.
|
* Called by the evaluator after the extension is loaded.
|
||||||
*/
|
*/
|
||||||
public void initializeExtension (FesiEvaluator fesi) throws EcmaScriptException {
|
public void initializeExtension (RequestEvaluator reval) throws EcmaScriptException {
|
||||||
this.fesi = fesi;
|
|
||||||
Evaluator evaluator = fesi.getEvaluator ();
|
this.app = reval.app;
|
||||||
|
Evaluator evaluator = reval.evaluator;
|
||||||
GlobalObject go = evaluator.getGlobalObject();
|
GlobalObject go = evaluator.getGlobalObject();
|
||||||
FunctionPrototype fp = (FunctionPrototype) evaluator.getFunctionPrototype();
|
FunctionPrototype fp = (FunctionPrototype) evaluator.getFunctionPrototype();
|
||||||
|
|
||||||
ESObject op = evaluator.getObjectPrototype();
|
ESObject op = evaluator.getObjectPrototype();
|
||||||
|
|
||||||
// The editor functions for String, Boolean and Number are deprecated!
|
////////// The editor functions for String, Boolean and Number are deprecated!
|
||||||
ESObject sp = evaluator.getStringPrototype ();
|
ESObject sp = evaluator.getStringPrototype ();
|
||||||
sp.putHiddenProperty ("editor", new StringEditor ("editor", evaluator, fp));
|
sp.putHiddenProperty ("editor", new StringEditor ("editor", evaluator, fp));
|
||||||
ESObject np = evaluator.getNumberPrototype ();
|
ESObject np = evaluator.getNumberPrototype ();
|
||||||
|
@ -55,87 +51,96 @@ public class HopExtension {
|
||||||
ESObject dp = evaluator.getDatePrototype ();
|
ESObject dp = evaluator.getDatePrototype ();
|
||||||
dp.putHiddenProperty ("format", new DatePrototypeFormat ("format", evaluator, fp));
|
dp.putHiddenProperty ("format", new DatePrototypeFormat ("format", evaluator, fp));
|
||||||
|
|
||||||
sp.putHiddenProperty ("trim", new StringTrim ("trim", evaluator, fp));
|
reval.esNodePrototype = new ObjectPrototype(op, evaluator); // the Node prototype
|
||||||
|
|
||||||
// generic (Java wrapper) object prototype
|
reval.esUserPrototype = new ObjectPrototype (reval.esNodePrototype, evaluator); // the User prototype
|
||||||
ObjectPrototype esObjectPrototype = new ObjectPrototype (op, evaluator);
|
|
||||||
// the Node prototype
|
ESObject node = new NodeConstructor ("Node", fp, reval); // the Node constructor
|
||||||
ObjectPrototype esNodePrototype = new ObjectPrototype(op, evaluator);
|
|
||||||
// the User prototype
|
|
||||||
ObjectPrototype esUserPrototype = new ObjectPrototype (esNodePrototype, evaluator);
|
|
||||||
// the Node constructor
|
|
||||||
ESObject node = new NodeConstructor ("Node", fp, fesi);
|
|
||||||
|
|
||||||
// register the default methods of Node objects in the Node prototype
|
// register the default methods of Node objects in the Node prototype
|
||||||
esNodePrototype.putHiddenProperty ("add", new NodeAdd ("add", evaluator, fp));
|
reval.esNodePrototype.putHiddenProperty ("add", new NodeAdd ("add", evaluator, fp));
|
||||||
esNodePrototype.putHiddenProperty ("addAt", new NodeAddAt ("addAt", evaluator, fp));
|
reval.esNodePrototype.putHiddenProperty ("addAt", new NodeAddAt ("addAt", evaluator, fp));
|
||||||
esNodePrototype.putHiddenProperty ("remove", new NodeRemove ("remove", evaluator, fp));
|
reval.esNodePrototype.putHiddenProperty ("remove", new NodeRemove ("remove", evaluator, fp));
|
||||||
esNodePrototype.putHiddenProperty ("link", new NodeLink ("link", evaluator, fp));
|
reval.esNodePrototype.putHiddenProperty ("link", new NodeLink ("link", evaluator, fp));
|
||||||
esNodePrototype.putHiddenProperty ("list", new NodeList ("list", evaluator, fp));
|
reval.esNodePrototype.putHiddenProperty ("list", new NodeList ("list", evaluator, fp, reval));
|
||||||
esNodePrototype.putHiddenProperty ("set", new NodeSet ("set", evaluator, fp));
|
reval.esNodePrototype.putHiddenProperty ("set", new NodeSet ("set", evaluator, fp));
|
||||||
esNodePrototype.putHiddenProperty ("get", new NodeGet ("get", evaluator, fp));
|
reval.esNodePrototype.putHiddenProperty ("get", new NodeGet ("get", evaluator, fp));
|
||||||
esNodePrototype.putHiddenProperty ("count", new NodeCount ("count", evaluator, fp));
|
reval.esNodePrototype.putHiddenProperty ("count", new NodeCount ("count", evaluator, fp));
|
||||||
esNodePrototype.putHiddenProperty ("contains", new NodeContains ("contains", evaluator, fp));
|
reval.esNodePrototype.putHiddenProperty ("contains", new NodeContains ("contains", evaluator, fp));
|
||||||
esNodePrototype.putHiddenProperty ("size", new NodeCount ("size", evaluator, fp));
|
reval.esNodePrototype.putHiddenProperty ("size", new NodeCount ("size", evaluator, fp));
|
||||||
esNodePrototype.putHiddenProperty ("editor", new NodeEditor ("editor", evaluator, fp));
|
reval.esNodePrototype.putHiddenProperty ("editor", new NodeEditor ("editor", evaluator, fp));
|
||||||
esNodePrototype.putHiddenProperty ("path", new NodeHref ("path", evaluator, fp));
|
reval.esNodePrototype.putHiddenProperty ("chooser", new NodeChooser ("chooser", evaluator, fp));
|
||||||
esNodePrototype.putHiddenProperty ("href", new NodeHref ("href", evaluator, fp));
|
reval.esNodePrototype.putHiddenProperty ("multiChooser", new MultiNodeChooser ("multiChooser", evaluator, fp));
|
||||||
esNodePrototype.putHiddenProperty ("setParent", new NodeSetParent ("setParent", evaluator, fp));
|
reval.esNodePrototype.putHiddenProperty ("getContent", new NodeGetContent ("getContent", evaluator, fp));
|
||||||
esNodePrototype.putHiddenProperty ("invalidate", new NodeInvalidate ("invalidate", evaluator, fp));
|
reval.esNodePrototype.putHiddenProperty ("setContent", new NodeSetContent ("setContent", evaluator, fp));
|
||||||
esNodePrototype.putHiddenProperty ("renderSkin", new RenderSkin ("renderSkin", evaluator, fp, false, false));
|
reval.esNodePrototype.putHiddenProperty ("path", new NodePath ("path", evaluator, fp));
|
||||||
esNodePrototype.putHiddenProperty ("renderSkinAsString", new RenderSkin ("renderSkinAsString", evaluator, fp, false, true));
|
reval.esNodePrototype.putHiddenProperty ("href", new NodeHref ("href", evaluator, fp));
|
||||||
esNodePrototype.putHiddenProperty ("clearCache", new NodeClearCache ("clearCache", evaluator, fp));
|
reval.esNodePrototype.putHiddenProperty ("setParent", new NodeSetParent ("setParent", evaluator, fp));
|
||||||
|
reval.esNodePrototype.putHiddenProperty ("invalidate", new NodeInvalidate ("invalidate", evaluator, fp));
|
||||||
// default methods for generic Java wrapper object prototype.
|
reval.esNodePrototype.putHiddenProperty("renderSkin", new RenderSkin ("renderSkin", evaluator, fp, reval, false, false));
|
||||||
// This is a small subset of the methods in esNodePrototype.
|
reval.esNodePrototype.putHiddenProperty("renderSkin_as_string", new RenderSkin ("renderSkin_as_string", evaluator, fp, reval, false, true));
|
||||||
esObjectPrototype.putHiddenProperty ("href", new NodeHref ("href", evaluator, fp));
|
|
||||||
esObjectPrototype.putHiddenProperty("renderSkin", new RenderSkin ("renderSkin", evaluator, fp, false, false));
|
|
||||||
esObjectPrototype.putHiddenProperty("renderSkinAsString", new RenderSkin ("renderSkinAsString", evaluator, fp, false, true));
|
|
||||||
|
|
||||||
// methods that give access to properties and global user lists
|
// methods that give access to properties and global user lists
|
||||||
go.putHiddenProperty("Node", node); // register the constructor for a plain Node object.
|
go.putHiddenProperty("Node", node); // register the constructor for a plain Node object.
|
||||||
go.putHiddenProperty("HopObject", node); // HopObject is the new name for node.
|
go.putHiddenProperty("HopObject", node); // HopObject is the new name for node.
|
||||||
go.putHiddenProperty("getProperty", new GlobalGetProperty ("getProperty", evaluator, fp));
|
go.putHiddenProperty("getProperty", new GlobalGetProperty ("getProperty", evaluator, fp));
|
||||||
go.putHiddenProperty("token", new GlobalGetProperty ("token", evaluator, fp));
|
go.putHiddenProperty("token", new GlobalGetProperty ("token", evaluator, fp));
|
||||||
go.putHiddenProperty("getUser", new GlobalGetUser ("getUser", evaluator, fp));
|
go.putHiddenProperty("getUser", new GlobalGetUser ("getUser", evaluator, fp, reval));
|
||||||
go.putHiddenProperty("getUserBySession", new GlobalGetUserBySession ("getUserBySession", evaluator, fp));
|
go.putHiddenProperty("getUserBySession", new GlobalGetUserBySession ("getUserBySession", evaluator, fp, reval));
|
||||||
go.putHiddenProperty("getAllUsers", new GlobalGetAllUsers ("getAllUsers", evaluator, fp));
|
go.putHiddenProperty("getAllUsers", new GlobalGetAllUsers ("getAllUsers", evaluator, fp, reval));
|
||||||
go.putHiddenProperty("getActiveUsers", new GlobalGetActiveUsers ("getActiveUsers", evaluator, fp));
|
go.putHiddenProperty("getActiveUsers", new GlobalGetActiveUsers ("getActiveUsers", evaluator, fp, reval));
|
||||||
go.putHiddenProperty("countActiveUsers", new GlobalCountActiveUsers ("countActiveUsers", evaluator, fp));
|
|
||||||
go.putHiddenProperty("isActive", new GlobalIsActive ("isActive", evaluator, fp));
|
go.putHiddenProperty("isActive", new GlobalIsActive ("isActive", evaluator, fp));
|
||||||
go.putHiddenProperty("getAge", new GlobalGetAge ("getAge", evaluator, fp));
|
go.putHiddenProperty("getAge", new GlobalGetAge ("getAge", evaluator, fp));
|
||||||
go.putHiddenProperty("getURL", new GlobalGetURL ("getURL", evaluator, fp));
|
go.putHiddenProperty("getURL", new GlobalGetURL ("getURL", evaluator, fp));
|
||||||
go.putHiddenProperty("encode", new GlobalEncode ("encode", evaluator, fp));
|
go.putHiddenProperty("encode", new GlobalEncode ("encode", evaluator, fp));
|
||||||
go.putHiddenProperty("encodeXml", new GlobalEncodeXml ("encodeXml", evaluator, fp));
|
go.putHiddenProperty("encodeXml", new GlobalEncodeXml ("encodeXml", evaluator, fp));
|
||||||
go.putHiddenProperty("encodeForm", new GlobalEncodeForm ("encodeForm", evaluator, fp));
|
|
||||||
go.putHiddenProperty("format", new GlobalFormat ("format", evaluator, fp));
|
go.putHiddenProperty("format", new GlobalFormat ("format", evaluator, fp));
|
||||||
go.putHiddenProperty("stripTags", new GlobalStripTags ("stripTags", evaluator, fp));
|
go.putHiddenProperty("stripTags", new GlobalStripTags ("stripTags", evaluator, fp));
|
||||||
go.putHiddenProperty("getXmlDocument", new GlobalGetXmlDocument ("getXmlDocument", evaluator, fp));
|
go.putHiddenProperty("getXmlDocument", new GlobalGetXmlDocument ("getXmlDocument", evaluator, fp));
|
||||||
go.putHiddenProperty("getHtmlDocument", new GlobalGetHtmlDocument ("getHtmlDocument", evaluator, fp));
|
go.putHiddenProperty("getHtmlDocument", new GlobalGetHtmlDocument ("getHtmlDocument", evaluator, fp));
|
||||||
go.putHiddenProperty("jdomize", new GlobalJDOM ("jdomize", evaluator, fp));
|
go.putHiddenProperty("jdomize", new GlobalJDOM ("jdomize", evaluator, fp));
|
||||||
go.putHiddenProperty("getSkin", new GlobalCreateSkin ("getSkin", evaluator, fp));
|
go.putHiddenProperty("getSkin", new GlobalGetSkin ("getSkin", evaluator, fp));
|
||||||
go.putHiddenProperty("createSkin", new GlobalCreateSkin ("createSkin", evaluator, fp));
|
go.putHiddenProperty("createSkin", new GlobalCreateSkin ("createSkin", evaluator, fp));
|
||||||
go.putHiddenProperty("renderSkin", new RenderSkin ("renderSkin", evaluator, fp, true, false));
|
go.putHiddenProperty("renderSkin", new RenderSkin ("renderSkin", evaluator, fp, reval, true, false));
|
||||||
go.putHiddenProperty("renderSkinAsString", new RenderSkin ("renderSkinAsString", evaluator, fp, true, true));
|
go.putHiddenProperty("renderSkin_as_string", new RenderSkin ("renderSkin_as_string", evaluator, fp, reval, true, true));
|
||||||
go.putHiddenProperty("authenticate", new GlobalAuthenticate ("authenticate", evaluator, fp));
|
|
||||||
go.deleteProperty("exit", "exit".hashCode());
|
go.deleteProperty("exit", "exit".hashCode());
|
||||||
|
|
||||||
// and some methods for session management from JS...
|
// and some methods for session management from JS...
|
||||||
esUserPrototype.putHiddenProperty("logon", new UserLogin ("logon", evaluator, fp));
|
reval.esUserPrototype.putHiddenProperty("logon", new UserLogin ("logon", evaluator, fp));
|
||||||
esUserPrototype.putHiddenProperty("login", new UserLogin ("login", evaluator, fp));
|
reval.esUserPrototype.putHiddenProperty("login", new UserLogin ("login", evaluator, fp));
|
||||||
esUserPrototype.putHiddenProperty("register", new UserRegister ("register", evaluator, fp));
|
reval.esUserPrototype.putHiddenProperty("register", new UserRegister ("register", evaluator, fp, reval));
|
||||||
esUserPrototype.putHiddenProperty("logout", new UserLogout ("logout", evaluator, fp));
|
reval.esUserPrototype.putHiddenProperty("logout", new UserLogout ("logout", evaluator, fp));
|
||||||
esUserPrototype.putHiddenProperty("onSince", new UserOnSince ("onSince", evaluator, fp));
|
reval.esUserPrototype.putHiddenProperty("onSince", new UserOnSince ("onSince", evaluator, fp));
|
||||||
esUserPrototype.putHiddenProperty("lastActive", new UserLastActive ("lastActive", evaluator, fp));
|
reval.esUserPrototype.putHiddenProperty("lastActive", new UserLastActive ("lastActive", evaluator, fp));
|
||||||
esUserPrototype.putHiddenProperty("touch", new UserTouch ("touch", evaluator, fp));
|
reval.esUserPrototype.putHiddenProperty("touch", new UserTouch ("touch", evaluator, fp));
|
||||||
|
|
||||||
// register object prototypes with FesiEvaluator
|
|
||||||
fesi.putPrototype ("global", go);
|
|
||||||
fesi.putPrototype ("hopobject", esNodePrototype);
|
|
||||||
fesi.putPrototype ("__javaobject__", esObjectPrototype);
|
|
||||||
fesi.putPrototype ("user", esUserPrototype);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class NodeSetContent extends BuiltinFunctionObject {
|
||||||
|
NodeSetContent (String name, Evaluator evaluator, FunctionPrototype fp) {
|
||||||
|
super (fp, evaluator, name, 1);
|
||||||
|
}
|
||||||
|
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
||||||
|
ESNode node = (ESNode) thisObject;
|
||||||
|
return ESBoolean.makeBoolean (node.setContent (arguments));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class NodeGetContent extends BuiltinFunctionObject {
|
||||||
|
NodeGetContent (String name, Evaluator evaluator, FunctionPrototype fp) {
|
||||||
|
super (fp, evaluator, name, 1);
|
||||||
|
}
|
||||||
|
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
||||||
|
ESNode node = (ESNode) thisObject;
|
||||||
|
Object content = node.getContent ();
|
||||||
|
if (content == null)
|
||||||
|
return ESNull.theNull;
|
||||||
|
else
|
||||||
|
return ESLoader.normalizeValue (content, this.evaluator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class NodeAdd extends BuiltinFunctionObject {
|
class NodeAdd extends BuiltinFunctionObject {
|
||||||
NodeAdd (String name, Evaluator evaluator, FunctionPrototype fp) {
|
NodeAdd (String name, Evaluator evaluator, FunctionPrototype fp) {
|
||||||
super (fp, evaluator, name, 1);
|
super (fp, evaluator, name, 1);
|
||||||
|
@ -178,8 +183,10 @@ public class HopExtension {
|
||||||
}
|
}
|
||||||
|
|
||||||
class NodeList extends BuiltinFunctionObject {
|
class NodeList extends BuiltinFunctionObject {
|
||||||
NodeList (String name, Evaluator evaluator, FunctionPrototype fp) {
|
RequestEvaluator reval;
|
||||||
|
NodeList (String name, Evaluator evaluator, FunctionPrototype fp, RequestEvaluator reval) {
|
||||||
super(fp, evaluator, name, 0);
|
super(fp, evaluator, name, 0);
|
||||||
|
this.reval = reval;
|
||||||
}
|
}
|
||||||
public ESValue callFunction(ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
public ESValue callFunction(ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
||||||
ESNode node = (ESNode) thisObject;
|
ESNode node = (ESNode) thisObject;
|
||||||
|
@ -198,10 +205,7 @@ public class HopExtension {
|
||||||
esv = thisObject.getProperty (i);
|
esv = thisObject.getProperty (i);
|
||||||
} else {
|
} else {
|
||||||
String name = arguments[0].toString ();
|
String name = arguments[0].toString ();
|
||||||
// call esNodeProperty() method special to ESNode because we want to avoid
|
esv = thisObject.getProperty (name, name.hashCode ());
|
||||||
// retrieving prototype functions when calling hopobject.get().
|
|
||||||
ESNode esn = (ESNode) thisObject;
|
|
||||||
esv = esn.getNodeProperty (name);
|
|
||||||
}
|
}
|
||||||
return (esv);
|
return (esv);
|
||||||
}
|
}
|
||||||
|
@ -253,7 +257,10 @@ public class HopExtension {
|
||||||
INode node = esn.getNode ();
|
INode node = esn.getNode ();
|
||||||
if (node instanceof helma.objectmodel.db.Node) {
|
if (node instanceof helma.objectmodel.db.Node) {
|
||||||
((helma.objectmodel.db.Node) node).invalidate ();
|
((helma.objectmodel.db.Node) node).invalidate ();
|
||||||
esn.checkNode ();
|
try {
|
||||||
|
node = app.nmgr.getNode (node.getID (), node.getDbMapping ());
|
||||||
|
esn.setNode (node);
|
||||||
|
} catch (Exception x) {}
|
||||||
}
|
}
|
||||||
return ESBoolean.makeBoolean (true);
|
return ESBoolean.makeBoolean (true);
|
||||||
}
|
}
|
||||||
|
@ -406,21 +413,51 @@ public class HopExtension {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class StringTrim extends BuiltinFunctionObject {
|
class NodeChooser extends BuiltinFunctionObject {
|
||||||
StringTrim (String name, Evaluator evaluator, FunctionPrototype fp) {
|
NodeChooser (String name, Evaluator evaluator, FunctionPrototype fp) {
|
||||||
super (fp, evaluator, name, 1);
|
super (fp, evaluator, name, 1);
|
||||||
}
|
}
|
||||||
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
||||||
return new ESString ( thisObject.toString().trim() );
|
ESNode esn = (ESNode) thisObject;
|
||||||
}
|
if (arguments.length < 1) {
|
||||||
}
|
return ESBoolean.makeBoolean(false);
|
||||||
|
}
|
||||||
|
String nodename = arguments[0].toString ();
|
||||||
|
INode target = esn.getNode ().getNode (nodename, false);
|
||||||
|
ESNode collection = arguments.length > 1 ? (ESNode) arguments[1] : esn;
|
||||||
|
if (arguments.length > 2)
|
||||||
|
return new ESString (getNodeChooserDD (nodename, collection.getNode (), target, arguments[2].toString ()));
|
||||||
|
else
|
||||||
|
return new ESString (getNodeChooserRB (nodename, collection.getNode (), target));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MultiNodeChooser extends BuiltinFunctionObject {
|
||||||
|
MultiNodeChooser (String name, Evaluator evaluator, FunctionPrototype fp) {
|
||||||
|
super (fp, evaluator, name, 1);
|
||||||
|
}
|
||||||
|
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
||||||
|
ESNode esn = (ESNode) thisObject;
|
||||||
|
if (arguments.length < 1) {
|
||||||
|
return ESBoolean.makeBoolean(false);
|
||||||
|
}
|
||||||
|
String nodename = arguments[0].toString ();
|
||||||
|
INode thisNode = esn.getNode ();
|
||||||
|
INode target = thisNode.getNode (nodename, false);
|
||||||
|
if (target == null) {
|
||||||
|
target = thisNode.createNode (nodename);
|
||||||
|
}
|
||||||
|
ESNode collection = arguments.length > 1 ? (ESNode) arguments[1] : esn;
|
||||||
|
return new ESString (getNodeChooserCB (nodename, collection.getNode (), target));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class UserLogin extends BuiltinFunctionObject {
|
class UserLogin extends BuiltinFunctionObject {
|
||||||
UserLogin (String name, Evaluator evaluator, FunctionPrototype fp) {
|
UserLogin (String name, Evaluator evaluator, FunctionPrototype fp) {
|
||||||
super (fp, evaluator, name, 1);
|
super (fp, evaluator, name, 1);
|
||||||
}
|
}
|
||||||
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
||||||
if (arguments.length < 2)
|
if (arguments.length < 2)
|
||||||
return ESBoolean.makeBoolean(false);
|
return ESBoolean.makeBoolean(false);
|
||||||
ESUser u = (ESUser) thisObject;
|
ESUser u = (ESUser) thisObject;
|
||||||
if (u.user == null)
|
if (u.user == null)
|
||||||
|
@ -434,8 +471,10 @@ public class HopExtension {
|
||||||
}
|
}
|
||||||
|
|
||||||
class UserRegister extends BuiltinFunctionObject {
|
class UserRegister extends BuiltinFunctionObject {
|
||||||
UserRegister (String name, Evaluator evaluator, FunctionPrototype fp) {
|
RequestEvaluator reval;
|
||||||
|
UserRegister (String name, Evaluator evaluator, FunctionPrototype fp, RequestEvaluator reval) {
|
||||||
super (fp, evaluator, name, 2);
|
super (fp, evaluator, name, 2);
|
||||||
|
this.reval = reval;
|
||||||
}
|
}
|
||||||
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
||||||
if (arguments.length < 2)
|
if (arguments.length < 2)
|
||||||
|
@ -444,7 +483,7 @@ public class HopExtension {
|
||||||
if (unode == null)
|
if (unode == null)
|
||||||
return ESNull.theNull;
|
return ESNull.theNull;
|
||||||
else
|
else
|
||||||
return fesi.getNodeWrapper (unode);
|
return reval.getNodeWrapper (unode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -471,7 +510,7 @@ public class HopExtension {
|
||||||
ESUser u = (ESUser) thisObject;
|
ESUser u = (ESUser) thisObject;
|
||||||
if (u.user == null)
|
if (u.user == null)
|
||||||
throw new EcmaScriptException ("onSince() can only be called for users that are online at the moment!");
|
throw new EcmaScriptException ("onSince() can only be called for users that are online at the moment!");
|
||||||
DatePrototype date = new DatePrototype(this.evaluator, new Date (u.user.onSince ()));
|
DatePrototype date = new DatePrototype(this.evaluator, new Date (u.user.onSince));
|
||||||
return date;
|
return date;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -484,7 +523,7 @@ public class HopExtension {
|
||||||
ESUser u = (ESUser) thisObject;
|
ESUser u = (ESUser) thisObject;
|
||||||
if (u.user == null)
|
if (u.user == null)
|
||||||
throw new EcmaScriptException ("lastActive() can only be called for users that are online at the moment!");
|
throw new EcmaScriptException ("lastActive() can only be called for users that are online at the moment!");
|
||||||
DatePrototype date = new DatePrototype(this.evaluator, new Date (u.user.lastTouched ()));
|
DatePrototype date = new DatePrototype(this.evaluator, new Date (u.user.lastTouched));
|
||||||
return date;
|
return date;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -509,20 +548,28 @@ public class HopExtension {
|
||||||
if (arguments.length == 0)
|
if (arguments.length == 0)
|
||||||
return new ESString ("");
|
return new ESString ("");
|
||||||
String defval = (arguments.length > 1) ? arguments[1].toString () : "";
|
String defval = (arguments.length > 1) ? arguments[1].toString () : "";
|
||||||
return new ESString (app.getProperty (arguments[0].toString (), defval));
|
return new ESString (app.props.getProperty (arguments[0].toString (), defval));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class GlobalAuthenticate extends BuiltinFunctionObject {
|
/**
|
||||||
GlobalAuthenticate (String name, Evaluator evaluator, FunctionPrototype fp) {
|
* Get a parsed Skin from the central skin cache if possible, otherwise create it
|
||||||
|
*/
|
||||||
|
class GlobalGetSkin extends BuiltinFunctionObject {
|
||||||
|
GlobalGetSkin (String name, Evaluator evaluator, FunctionPrototype fp) {
|
||||||
super (fp, evaluator, name, 1);
|
super (fp, evaluator, name, 1);
|
||||||
}
|
}
|
||||||
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
||||||
if (arguments.length != 2)
|
if (arguments.length != 1 || ESNull.theNull.equals (arguments[0]))
|
||||||
return ESBoolean.makeBoolean (false);
|
throw new EcmaScriptException ("getSkin must be called with one String argument!");
|
||||||
return ESBoolean.makeBoolean (app.authenticate (arguments[0].toString (), arguments[1].toString ()));
|
String str = arguments[0].toString ();
|
||||||
|
Skin skin = (Skin) app.skincache.get (str);
|
||||||
|
if (skin == null) {
|
||||||
|
skin = new Skin (str);
|
||||||
|
app.skincache.put (str, skin);
|
||||||
|
}
|
||||||
|
return new ESWrapper (skin, evaluator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -535,14 +582,8 @@ public class HopExtension {
|
||||||
}
|
}
|
||||||
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
||||||
if (arguments.length != 1 || ESNull.theNull.equals (arguments[0]))
|
if (arguments.length != 1 || ESNull.theNull.equals (arguments[0]))
|
||||||
throw new EcmaScriptException ("createSkin must be called with one String argument");
|
throw new EcmaScriptException ("createSkin must be called with one String argument!");
|
||||||
String str = arguments[0].toString ();
|
return new ESWrapper (new Skin (arguments[0].toString()), evaluator);
|
||||||
Skin skin = (Skin) app.skincache.get (str);
|
|
||||||
if (skin == null) {
|
|
||||||
skin = new Skin (str, app);
|
|
||||||
app.skincache.put (str, skin);
|
|
||||||
}
|
|
||||||
return new ESWrapper (skin, evaluator);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -550,29 +591,25 @@ public class HopExtension {
|
||||||
* Render a skin
|
* Render a skin
|
||||||
*/
|
*/
|
||||||
class RenderSkin extends BuiltinFunctionObject {
|
class RenderSkin extends BuiltinFunctionObject {
|
||||||
|
RequestEvaluator reval;
|
||||||
boolean global;
|
boolean global;
|
||||||
boolean asString;
|
boolean asString;
|
||||||
RenderSkin (String name, Evaluator evaluator, FunctionPrototype fp, boolean global, boolean asString) {
|
RenderSkin (String name, Evaluator evaluator, FunctionPrototype fp,
|
||||||
|
RequestEvaluator reval, boolean global, boolean asString) {
|
||||||
super (fp, evaluator, name, 1);
|
super (fp, evaluator, name, 1);
|
||||||
|
this.reval = reval;
|
||||||
this.global = global;
|
this.global = global;
|
||||||
this.asString = asString;
|
this.asString = asString;
|
||||||
}
|
}
|
||||||
public ESValue callFunction (ESObject thisObj, ESValue[] arguments) throws EcmaScriptException {
|
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
||||||
if (arguments.length < 1 || arguments.length > 2 || arguments[0] ==null || arguments[0] == ESNull.theNull)
|
if (arguments.length < 1 || arguments.length > 2 || arguments[0] ==null || arguments[0] == ESNull.theNull)
|
||||||
throw new EcmaScriptException ("renderSkin requires one argument containing the skin name and an optional parameter object argument");
|
throw new EcmaScriptException ("renderSkin must be called with one Skin argument and an optional parameter argument");
|
||||||
try {
|
try {
|
||||||
Skin skin = null;
|
Skin skin = null;
|
||||||
ESObject thisObject = global ? null : thisObj;
|
ESNode handlerNode = global ? null : (ESNode) thisObject;
|
||||||
HashMap params = null;
|
ESObject paramObject = null;
|
||||||
if (arguments.length > 1 && arguments[1] instanceof ESObject) {
|
if (arguments.length > 1 && arguments[1] instanceof ESObject)
|
||||||
// create an parameter object to pass to the skin
|
paramObject = (ESObject) arguments[1];
|
||||||
ESObject paramObject = (ESObject) arguments[1];
|
|
||||||
params = new HashMap ();
|
|
||||||
for (Enumeration en=paramObject.getProperties(); en.hasMoreElements(); ) {
|
|
||||||
String propname = (String) en.nextElement();
|
|
||||||
params.put (propname, paramObject.getProperty (propname, propname.hashCode()).toJavaObject());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// first, see if the first argument already is a skin object. If not, it's the name of the skin to be called
|
// first, see if the first argument already is a skin object. If not, it's the name of the skin to be called
|
||||||
if (arguments[0] instanceof ESWrapper) {
|
if (arguments[0] instanceof ESWrapper) {
|
||||||
|
@ -581,41 +618,16 @@ public class HopExtension {
|
||||||
skin = (Skin) obj;
|
skin = (Skin) obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if res.skinpath is set, transform it into an array of java objects
|
|
||||||
// (strings for directory names and INodes for internal, db-stored skinsets)
|
|
||||||
ResponseTrans res = fesi.getResponse();
|
|
||||||
Object[] skinpath = res.getTranslatedSkinpath ();
|
|
||||||
if (skinpath == null) {
|
|
||||||
skinpath = new Object[0];
|
|
||||||
Object rawSkinpath = res.getSkinpath ();
|
|
||||||
if (rawSkinpath != null && rawSkinpath instanceof JSWrapper) {
|
|
||||||
JSWrapper jsw = (JSWrapper) rawSkinpath;
|
|
||||||
ESObject eso = jsw.getESObject ();
|
|
||||||
if (eso instanceof ArrayPrototype) {
|
|
||||||
ArrayPrototype array = (ArrayPrototype) eso;
|
|
||||||
skinpath = new Object[array.size()];
|
|
||||||
for (int i=0; i<skinpath.length; i++)
|
|
||||||
skinpath[i] = array.getProperty(i).toJavaObject ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
res.setTranslatedSkinpath (skinpath);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ready... retrieve the skin and render it.
|
|
||||||
Object javaObject = thisObject == null ? null : thisObject.toJavaObject ();
|
|
||||||
if (skin == null)
|
if (skin == null)
|
||||||
skin = app.getSkin (javaObject, arguments[0].toString (), skinpath);
|
skin = reval.getSkin (handlerNode, arguments[0].toString ());
|
||||||
if (asString)
|
if (asString)
|
||||||
res.pushStringBuffer ();
|
reval.res.pushStringBuffer ();
|
||||||
if (skin != null)
|
if (skin != null)
|
||||||
skin.render (fesi.getRequestEvaluator(), javaObject, params);
|
skin.render (reval, handlerNode, paramObject);
|
||||||
else
|
else
|
||||||
res.write ("[Skin not found: "+arguments[0]+"]");
|
reval.res.write ("[Skin not found: "+arguments[0]+"]");
|
||||||
if (asString)
|
if (asString)
|
||||||
return new ESString (res.popStringBuffer ());
|
return new ESString (reval.res.popStringBuffer ());
|
||||||
} catch (RedirectException redir) {
|
|
||||||
// let redirect pass through
|
|
||||||
throw redir;
|
|
||||||
} catch (Exception x) {
|
} catch (Exception x) {
|
||||||
x.printStackTrace ();
|
x.printStackTrace ();
|
||||||
throw new EcmaScriptException ("renderSkin: "+x);
|
throw new EcmaScriptException ("renderSkin: "+x);
|
||||||
|
@ -627,42 +639,48 @@ public class HopExtension {
|
||||||
|
|
||||||
|
|
||||||
class GlobalGetUser extends BuiltinFunctionObject {
|
class GlobalGetUser extends BuiltinFunctionObject {
|
||||||
GlobalGetUser (String name, Evaluator evaluator, FunctionPrototype fp) {
|
RequestEvaluator reval;
|
||||||
|
GlobalGetUser (String name, Evaluator evaluator, FunctionPrototype fp, RequestEvaluator reval) {
|
||||||
super (fp, evaluator, name, 1);
|
super (fp, evaluator, name, 1);
|
||||||
|
this.reval = reval;
|
||||||
}
|
}
|
||||||
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
||||||
INode user = null;
|
INode user = null;
|
||||||
if (arguments.length > 0) {
|
if (arguments.length > 0) {
|
||||||
String uname = arguments[0].toString ().trim ();
|
String uname = arguments[0].toString ().trim ();
|
||||||
user = app.getUserNode (uname);
|
user = app.getUserNode (uname);
|
||||||
}
|
}
|
||||||
if (user == null)
|
if (user == null)
|
||||||
return ESNull.theNull;
|
return ESNull.theNull;
|
||||||
return fesi.getNodeWrapper (user);
|
return reval.getNodeWrapper (user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class GlobalGetUserBySession extends BuiltinFunctionObject {
|
class GlobalGetUserBySession extends BuiltinFunctionObject {
|
||||||
GlobalGetUserBySession (String name, Evaluator evaluator, FunctionPrototype fp) {
|
RequestEvaluator reval;
|
||||||
|
GlobalGetUserBySession (String name, Evaluator evaluator, FunctionPrototype fp, RequestEvaluator reval) {
|
||||||
super (fp, evaluator, name, 1);
|
super (fp, evaluator, name, 1);
|
||||||
|
this.reval = reval;
|
||||||
}
|
}
|
||||||
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
||||||
User user = null;
|
User user = null;
|
||||||
if (arguments.length > 0) {
|
if (arguments.length > 0) {
|
||||||
String sid = arguments[0].toString ().trim ();
|
String sid = arguments[0].toString ().trim ();
|
||||||
user = app.getUser (sid);
|
user = app.getUser (sid);
|
||||||
}
|
}
|
||||||
if (user == null || user.getUID() == null)
|
if (user == null || user.uid == null)
|
||||||
return ESNull.theNull;
|
return ESNull.theNull;
|
||||||
user.touch ();
|
user.touch ();
|
||||||
return fesi.getNodeWrapper (user.getNode ());
|
return reval.getNodeWrapper (user.getNode ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class GlobalGetAllUsers extends BuiltinFunctionObject {
|
class GlobalGetAllUsers extends BuiltinFunctionObject {
|
||||||
GlobalGetAllUsers (String name, Evaluator evaluator, FunctionPrototype fp) {
|
RequestEvaluator reval;
|
||||||
|
GlobalGetAllUsers (String name, Evaluator evaluator, FunctionPrototype fp, RequestEvaluator reval) {
|
||||||
super (fp, evaluator, name, 1);
|
super (fp, evaluator, name, 1);
|
||||||
|
this.reval = reval;
|
||||||
}
|
}
|
||||||
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
||||||
INode users = app.getUserRoot ();
|
INode users = app.getUserRoot ();
|
||||||
|
@ -678,37 +696,30 @@ public class HopExtension {
|
||||||
}
|
}
|
||||||
|
|
||||||
class GlobalGetActiveUsers extends BuiltinFunctionObject {
|
class GlobalGetActiveUsers extends BuiltinFunctionObject {
|
||||||
GlobalGetActiveUsers (String name, Evaluator evaluator, FunctionPrototype fp) {
|
RequestEvaluator reval;
|
||||||
|
GlobalGetActiveUsers (String name, Evaluator evaluator, FunctionPrototype fp, RequestEvaluator reval) {
|
||||||
super (fp, evaluator, name, 1);
|
super (fp, evaluator, name, 1);
|
||||||
|
this.reval = reval;
|
||||||
}
|
}
|
||||||
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
||||||
Hashtable sessions = (Hashtable) app.sessions.clone ();
|
Hashtable sessions = (Hashtable) app.sessions.clone ();
|
||||||
|
int l = sessions.size ();
|
||||||
ESObject ap = this.evaluator.getArrayPrototype();
|
ESObject ap = this.evaluator.getArrayPrototype();
|
||||||
ArrayPrototype theArray = new ArrayPrototype (ap, this.evaluator);
|
ArrayPrototype theArray = new ArrayPrototype (ap, this.evaluator);
|
||||||
theArray.setSize (sessions.size ());
|
theArray.setSize(l);
|
||||||
int i=0;
|
int i=0;
|
||||||
// Hashtable visited = new Hashtable ();
|
Hashtable visited = new Hashtable ();
|
||||||
for (Enumeration e=sessions.elements(); e.hasMoreElements(); ) {
|
for (Enumeration e=sessions.elements(); e.hasMoreElements(); ) {
|
||||||
User u = (User) e.nextElement ();
|
User u = (User) e.nextElement ();
|
||||||
// Note: we previously sorted out duplicate users - now we simply enumerate all active sessions.
|
if (u.uid == null || !visited.containsKey (u.uid)) {
|
||||||
// if (u.uid == null || !visited.containsKey (u.uid)) {
|
theArray.setElementAt (reval.getNodeWrapper (u.getNode ()), i++);
|
||||||
theArray.setElementAt (fesi.getNodeWrapper (u), i++);
|
if (u.uid != null) visited.put (u.uid, u);
|
||||||
// if (u.uid != null) visited.put (u.uid, u);
|
}
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
return theArray;
|
return theArray;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class GlobalCountActiveUsers extends BuiltinFunctionObject {
|
|
||||||
GlobalCountActiveUsers (String name, Evaluator evaluator, FunctionPrototype fp) {
|
|
||||||
super (fp, evaluator, name, 1);
|
|
||||||
}
|
|
||||||
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
|
||||||
return new ESNumber (app.sessions.size ());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class GlobalIsActive extends BuiltinFunctionObject {
|
class GlobalIsActive extends BuiltinFunctionObject {
|
||||||
GlobalIsActive (String name, Evaluator evaluator, FunctionPrototype fp) {
|
GlobalIsActive (String name, Evaluator evaluator, FunctionPrototype fp) {
|
||||||
super (fp, evaluator, name, 1);
|
super (fp, evaluator, name, 1);
|
||||||
|
@ -759,7 +770,7 @@ public class HopExtension {
|
||||||
return new ESString (age.toString ());
|
return new ESString (age.toString ());
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
app.logEvent ("Error formatting date: "+e);
|
IServer.getLogger().log ("Error formatting date: "+e);
|
||||||
e.printStackTrace ();
|
e.printStackTrace ();
|
||||||
return new ESString ("");
|
return new ESString ("");
|
||||||
}
|
}
|
||||||
|
@ -810,17 +821,6 @@ public class HopExtension {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class GlobalEncodeForm extends BuiltinFunctionObject {
|
|
||||||
GlobalEncodeForm (String name, Evaluator evaluator, FunctionPrototype fp) {
|
|
||||||
super (fp, evaluator, name, 1);
|
|
||||||
}
|
|
||||||
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
|
||||||
if (arguments.length < 1)
|
|
||||||
return ESNull.theNull;
|
|
||||||
return new ESString (HtmlEncoder.encodeFormValue (arguments[0].toString ()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// strip tags from XML/HTML text
|
// strip tags from XML/HTML text
|
||||||
class GlobalStripTags extends BuiltinFunctionObject {
|
class GlobalStripTags extends BuiltinFunctionObject {
|
||||||
GlobalStripTags (String name, Evaluator evaluator, FunctionPrototype fp) {
|
GlobalStripTags (String name, Evaluator evaluator, FunctionPrototype fp) {
|
||||||
|
@ -865,7 +865,7 @@ public class HopExtension {
|
||||||
Object p = arguments[0].toJavaObject ();
|
Object p = arguments[0].toJavaObject ();
|
||||||
if (p instanceof String) try {
|
if (p instanceof String) try {
|
||||||
// first try to interpret string as URL
|
// first try to interpret string as URL
|
||||||
java.net.URL u = new java.net.URL (p.toString ());
|
java.net.URL u = new java.net.URL (p.toString ());
|
||||||
parser.parse (p.toString());
|
parser.parse (p.toString());
|
||||||
} catch (java.net.MalformedURLException nourl) {
|
} catch (java.net.MalformedURLException nourl) {
|
||||||
// if not a URL, maybe it is the XML itself
|
// if not a URL, maybe it is the XML itself
|
||||||
|
@ -877,7 +877,7 @@ public class HopExtension {
|
||||||
parser.parse (new InputSource ((Reader) p));
|
parser.parse (new InputSource ((Reader) p));
|
||||||
return ESLoader.normalizeObject (parser.getDocument(), evaluator);
|
return ESLoader.normalizeObject (parser.getDocument(), evaluator);
|
||||||
} catch (Exception noluck) {
|
} catch (Exception noluck) {
|
||||||
app.logEvent ("Error creating XML document: "+noluck);
|
IServer.getLogger().log ("Error creating XML document: "+noluck);
|
||||||
}
|
}
|
||||||
return ESNull.theNull;
|
return ESNull.theNull;
|
||||||
}
|
}
|
||||||
|
@ -894,7 +894,7 @@ public class HopExtension {
|
||||||
Object p = arguments[0].toJavaObject ();
|
Object p = arguments[0].toJavaObject ();
|
||||||
if (p instanceof String) try {
|
if (p instanceof String) try {
|
||||||
// first try to interpret string as URL
|
// first try to interpret string as URL
|
||||||
java.net.URL u = new java.net.URL (p.toString ());
|
java.net.URL u = new java.net.URL (p.toString ());
|
||||||
parser.parse (p.toString());
|
parser.parse (p.toString());
|
||||||
} catch (java.net.MalformedURLException nourl) {
|
} catch (java.net.MalformedURLException nourl) {
|
||||||
// if not a URL, maybe it is the HTML itself
|
// if not a URL, maybe it is the HTML itself
|
||||||
|
@ -906,7 +906,7 @@ public class HopExtension {
|
||||||
parser.parse (new InputSource ((Reader) p));
|
parser.parse (new InputSource ((Reader) p));
|
||||||
return ESLoader.normalizeObject (parser.getDocument(), evaluator);
|
return ESLoader.normalizeObject (parser.getDocument(), evaluator);
|
||||||
} catch (Exception noluck) {
|
} catch (Exception noluck) {
|
||||||
app.logEvent ("Error creating HTML document: "+noluck);
|
IServer.getLogger().log ("Error creating HTML document: "+noluck);
|
||||||
}
|
}
|
||||||
return ESNull.theNull;
|
return ESNull.theNull;
|
||||||
}
|
}
|
||||||
|
@ -924,12 +924,24 @@ public class HopExtension {
|
||||||
org.jdom.input.DOMBuilder builder = new org.jdom.input.DOMBuilder ();
|
org.jdom.input.DOMBuilder builder = new org.jdom.input.DOMBuilder ();
|
||||||
return ESLoader.normalizeObject (builder.build (doc), evaluator);
|
return ESLoader.normalizeObject (builder.build (doc), evaluator);
|
||||||
} catch (Exception noluck) {
|
} catch (Exception noluck) {
|
||||||
app.logEvent ("Error wrapping JDOM document: "+noluck);
|
IServer.getLogger().log ("Error wrapping JDOM document: "+noluck);
|
||||||
}
|
}
|
||||||
return ESNull.theNull;
|
return ESNull.theNull;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class NodePath extends BuiltinFunctionObject {
|
||||||
|
NodePath (String name, Evaluator evaluator, FunctionPrototype fp) {
|
||||||
|
super (fp, evaluator, name, 1);
|
||||||
|
}
|
||||||
|
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
||||||
|
INode n = ((ESNode) thisObject).getNode ();
|
||||||
|
String tmpname = arguments[0].toString ();
|
||||||
|
return new ESString (app.getNodePath (n, tmpname));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class NodeSetParent extends BuiltinFunctionObject {
|
class NodeSetParent extends BuiltinFunctionObject {
|
||||||
NodeSetParent (String name, Evaluator evaluator, FunctionPrototype fp) {
|
NodeSetParent (String name, Evaluator evaluator, FunctionPrototype fp) {
|
||||||
super (fp, evaluator, name, 2);
|
super (fp, evaluator, name, 2);
|
||||||
|
@ -940,52 +952,16 @@ public class HopExtension {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class NodeClearCache extends BuiltinFunctionObject {
|
|
||||||
NodeClearCache (String name, Evaluator evaluator, FunctionPrototype fp) {
|
|
||||||
super (fp, evaluator, name, 2);
|
|
||||||
}
|
|
||||||
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
|
||||||
ESNode node = (ESNode) thisObject;
|
|
||||||
return ESBoolean.makeBoolean (node.clearCache ());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class NodeHref extends BuiltinFunctionObject {
|
class NodeHref extends BuiltinFunctionObject {
|
||||||
NodeHref (String name, Evaluator evaluator, FunctionPrototype fp) {
|
NodeHref (String name, Evaluator evaluator, FunctionPrototype fp) {
|
||||||
super (fp, evaluator, name, 1);
|
super (fp, evaluator, name, 1);
|
||||||
}
|
}
|
||||||
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
||||||
Object elem = thisObject.toJavaObject ();
|
INode n = ((ESNode) thisObject).getNode ();
|
||||||
String tmpname = arguments.length == 0 ? "" : arguments[0].toString ();
|
String tmpname = arguments.length == 0 ? "" : arguments[0].toString ();
|
||||||
String basicHref =app.getNodeHref (elem, tmpname);
|
return new ESString (app.getNodeHref (n, tmpname));
|
||||||
String hrefSkin = app.getProperty ("hrefSkin", null);
|
|
||||||
// FIXME: we should actually walk down the path from the object we called href() on
|
|
||||||
// instead we move down the URL path.
|
|
||||||
if (hrefSkin != null) {
|
|
||||||
// we need to post-process the href with a skin for this application
|
|
||||||
// first, look in the object href was called on.
|
|
||||||
Object skinElem = elem;
|
|
||||||
Skin skin = null;
|
|
||||||
while (skin == null && skinElem != null) {
|
|
||||||
Prototype proto = app.getPrototype (skinElem);
|
|
||||||
if (proto != null)
|
|
||||||
skin = proto.getSkin (hrefSkin);
|
|
||||||
if (skin == null)
|
|
||||||
skinElem = app.getParentElement (skinElem);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (skin != null) {
|
|
||||||
return renderSkin (skin, basicHref, skinElem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new ESString (basicHref);
|
|
||||||
}
|
|
||||||
private ESString renderSkin (Skin skin, String path, Object skinElem) throws EcmaScriptException {
|
|
||||||
fesi.getResponse().pushStringBuffer ();
|
|
||||||
HashMap param = new HashMap ();
|
|
||||||
param.put ("path", path);
|
|
||||||
skin.render (fesi.getRequestEvaluator(), skinElem, param);
|
|
||||||
return new ESString (fesi.getResponse().popStringBuffer ().trim ());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1002,7 +978,7 @@ public class HopExtension {
|
||||||
double d = from <= to ? 1.0 : -1.0;
|
double d = from <= to ? 1.0 : -1.0;
|
||||||
for (double i=from; i*d<=to*d; i+=step) {
|
for (double i=from; i*d<=to*d; i+=step) {
|
||||||
if (Math.abs (i%1) < l) {
|
if (Math.abs (i%1) < l) {
|
||||||
int j = (int) i;
|
int j = (int) i;
|
||||||
b.append ("<option value=\""+j);
|
b.append ("<option value=\""+j);
|
||||||
if (i == value) b.append ("\" selected=\"true");
|
if (i == value) b.append ("\" selected=\"true");
|
||||||
b.append ("\">"+j);
|
b.append ("\">"+j);
|
||||||
|
@ -1015,7 +991,165 @@ public class HopExtension {
|
||||||
b.append ("</select>");
|
b.append ("</select>");
|
||||||
return b.toString ();
|
return b.toString ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getNodeChooserDD (String name, INode collection, INode target, String teaser) {
|
||||||
|
StringBuffer buffer = new StringBuffer ("<select name=\"");
|
||||||
|
buffer.append (name);
|
||||||
|
buffer.append ("\">");
|
||||||
|
if (collection.contains (target) == -1) {
|
||||||
|
buffer.append ("<option value=>");
|
||||||
|
buffer.append (HtmlEncoder.encodeAll (teaser));
|
||||||
|
}
|
||||||
|
if (collection != null) {
|
||||||
|
int l = collection.numberOfNodes ();
|
||||||
|
for (int i=0; i<l; i++) {
|
||||||
|
INode next = collection.getSubnodeAt (i);
|
||||||
|
buffer.append ("<option value=\"");
|
||||||
|
buffer.append (next.getID ());
|
||||||
|
if (target == next)
|
||||||
|
buffer.append ("\" selected=\"true");
|
||||||
|
buffer.append ("\">");
|
||||||
|
String cname = next.getString ("name", false);
|
||||||
|
if (cname == null) cname = next.getName ();
|
||||||
|
buffer.append (HtmlEncoder.encodeAll (cname));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buffer.append ("</select>");
|
||||||
|
return buffer.toString ();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getNodeChooserRB (String name, INode collection, INode target) {
|
||||||
|
StringBuffer buffer = new StringBuffer ();
|
||||||
|
if (collection != null) {
|
||||||
|
int l = collection.numberOfNodes ();
|
||||||
|
for (int i=0; i<l; i++) {
|
||||||
|
INode next = collection.getSubnodeAt (i);
|
||||||
|
buffer.append ("<input type=radio name=\"");
|
||||||
|
buffer.append (name);
|
||||||
|
buffer.append ("\" value=\"");
|
||||||
|
buffer.append (next.getNameOrID ()+"\"");
|
||||||
|
if (target == next)
|
||||||
|
buffer.append (" checked");
|
||||||
|
buffer.append (">");
|
||||||
|
String cname = next.getString ("name", false);
|
||||||
|
if (cname == null) cname = next.getName ();
|
||||||
|
buffer.append (HtmlEncoder.encodeAll (cname));
|
||||||
|
buffer.append ("<br>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return buffer.toString ();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getNodeChooserCB (String name, INode collection, INode target) {
|
||||||
|
StringBuffer buffer = new StringBuffer ();
|
||||||
|
if (collection != null) {
|
||||||
|
int l = collection.numberOfNodes ();
|
||||||
|
for (int i=0; i<l; i++) {
|
||||||
|
INode next = collection.getSubnodeAt (i);
|
||||||
|
buffer.append ("<input type=checkbox name=\"");
|
||||||
|
buffer.append (name);
|
||||||
|
buffer.append ("\" value=");
|
||||||
|
buffer.append (next.getNameOrID ());
|
||||||
|
if (target.contains (next) > -1)
|
||||||
|
buffer.append (" checked");
|
||||||
|
buffer.append (">");
|
||||||
|
buffer.append (HtmlEncoder.encodeAll (next.getName ()));
|
||||||
|
buffer.append ("<br>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return buffer.toString ();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
// NodeConstructor.java
|
// NodeConstructor.java
|
||||||
// Copyright (c) Hannes Wallnöfer 2000
|
// Copyright (c) Hannes Wallnöfer 2000
|
||||||
|
|
||||||
package helma.scripting.fesi;
|
package helma.framework.core;
|
||||||
|
|
||||||
import helma.objectmodel.db.Node;
|
|
||||||
import helma.framework.core.*;
|
|
||||||
import FESI.Data.*;
|
import FESI.Data.*;
|
||||||
import FESI.Exceptions.*;
|
import FESI.Exceptions.*;
|
||||||
import FESI.Interpreter.*;
|
import FESI.Interpreter.*;
|
||||||
|
@ -15,14 +13,14 @@ import FESI.Interpreter.*;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class NodeConstructor extends BuiltinFunctionObject {
|
public class NodeConstructor extends BuiltinFunctionObject {
|
||||||
|
|
||||||
FesiEvaluator fesi;
|
RequestEvaluator reval;
|
||||||
String typename;
|
String typename;
|
||||||
|
|
||||||
public NodeConstructor (String name, FunctionPrototype fp, FesiEvaluator fesi) {
|
public NodeConstructor (String name, FunctionPrototype fp, RequestEvaluator reval) {
|
||||||
super(fp, fesi.getEvaluator (), name, 1);
|
super(fp, reval.evaluator, name, 1);
|
||||||
typename = name;
|
typename = name;
|
||||||
this.fesi = fesi;
|
this.reval = reval;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ESValue callFunction(ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
public ESValue callFunction(ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
||||||
|
@ -31,33 +29,32 @@ public class NodeConstructor extends BuiltinFunctionObject {
|
||||||
|
|
||||||
public ESObject doConstruct(ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
public ESObject doConstruct(ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
||||||
ESNode node = null;
|
ESNode node = null;
|
||||||
Application app = fesi.getApplication ();
|
|
||||||
if ("Node".equals (typename) || "hopobject".equalsIgnoreCase (typename)) {
|
if ("Node".equals (typename) || "hopobject".equalsIgnoreCase (typename)) {
|
||||||
String nodeName = null;
|
if (arguments.length == 0) {
|
||||||
if (arguments.length > 0 && arguments[0] != null)
|
node = new ESNode (reval.esNodePrototype, this.evaluator, null, reval);
|
||||||
nodeName = arguments[0].toString();
|
reval.objectcache.put (node.getNode (), node);
|
||||||
Node n = new Node (nodeName, (String) null, app.getWrappedNodeManager ());
|
} else {
|
||||||
node = new ESNode (fesi.getPrototype ("hopobject"), this.evaluator, n, fesi);
|
node = new ESNode (reval.esNodePrototype, this.evaluator, arguments[0], reval);
|
||||||
fesi.putNodeWrapper (node.getNode (), node);
|
reval.objectcache.put (node.getNode (), node);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Typed nodes are instantiated as helma.objectmodel.db.Node from the beginning
|
// 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
|
// 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
|
// is that we want to be able to use the specail features like subnode relations even for
|
||||||
// transient nodes.
|
// transient nodes.
|
||||||
ObjectPrototype op = fesi.getPrototype (typename);
|
ObjectPrototype op = reval.getPrototype (typename);
|
||||||
Node n = new Node (typename, typename, app.getWrappedNodeManager ());
|
node = new ESNode (op, reval.evaluator, typename, reval);
|
||||||
node = new ESNode (op, fesi.getEvaluator (), n, fesi);
|
|
||||||
node.setPrototype (typename);
|
node.setPrototype (typename);
|
||||||
node.getNode ().setDbMapping (app.getDbMapping (typename));
|
node.getNode ().setDbMapping (reval.app.getDbMapping (typename));
|
||||||
try {
|
try {
|
||||||
// first try calling "constructor", if that doesn't work, try calling a function
|
// first try calling "constructor", if that doesn't work, try calling a function
|
||||||
// with the name of the type.
|
// with the name of the type.
|
||||||
// HACK: There is an incompatibility problem here, because the property
|
// HACK: There is an incompatibility problem here, because the property
|
||||||
// constructor is defined as the constructor of the object by EcmaScript.
|
// constructor is defined as the constructor of the object by EcmaScript.
|
||||||
if (op.getProperty ("constructor", "constructor".hashCode()) instanceof ConstructedFunctionObject)
|
if (op.getProperty("constructor", "constructor".hashCode()) instanceof ConstructedFunctionObject)
|
||||||
node.doIndirectCall (fesi.getEvaluator(), node, "constructor", arguments);
|
node.doIndirectCall (reval.evaluator, node, "constructor", arguments);
|
||||||
else
|
else
|
||||||
node.doIndirectCall (fesi.getEvaluator(), node, typename, arguments);
|
node.doIndirectCall (reval.evaluator, node, typename, arguments);
|
||||||
} catch (Exception ignore) {}
|
} catch (Exception ignore) {}
|
||||||
}
|
}
|
||||||
return node;
|
return node;
|
||||||
|
@ -68,9 +65,9 @@ public class NodeConstructor extends BuiltinFunctionObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ESValue getProperty(String propertyName, int hash) throws EcmaScriptException {
|
public ESValue getProperty(String propertyName, int hash) throws EcmaScriptException {
|
||||||
if ("prototype".equals (propertyName))
|
if ("prototype".equals (propertyName))
|
||||||
return fesi.getPrototype (typename);
|
return reval.getPrototype (typename);
|
||||||
return super.getProperty(propertyName, hash);
|
return super.getProperty(propertyName, hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String[] getSpecialPropertyNames() {
|
public String[] getSpecialPropertyNames() {
|
|
@ -3,13 +3,12 @@
|
||||||
|
|
||||||
package helma.framework.core;
|
package helma.framework.core;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.*;
|
||||||
import java.util.Iterator;
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import helma.framework.*;
|
import helma.framework.*;
|
||||||
import helma.scripting.*;
|
|
||||||
import helma.objectmodel.*;
|
import helma.objectmodel.*;
|
||||||
import helma.util.Updatable;
|
import FESI.Data.*;
|
||||||
|
import FESI.Exceptions.EcmaScriptException;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -25,65 +24,54 @@ public class Prototype {
|
||||||
String id;
|
String id;
|
||||||
String name;
|
String name;
|
||||||
Application app;
|
Application app;
|
||||||
public HashMap templates, functions, actions, skins, updatables;
|
Hashtable templates, functions, actions, skins;
|
||||||
|
File codeDir;
|
||||||
long lastUpdate;
|
long lastUpdate;
|
||||||
|
|
||||||
Prototype parent;
|
DbMapping dbmap;
|
||||||
|
|
||||||
// Tells us whether this prototype is used to script a generic Java object,
|
Prototype prototype;
|
||||||
// as opposed to a Helma objectmodel node object.
|
|
||||||
boolean isJavaPrototype;
|
|
||||||
|
|
||||||
public Prototype (String name, Application app) {
|
|
||||||
// app.logEvent ("Constructing Prototype "+app.getName()+"/"+name);
|
public Prototype (File codeDir, Application app) {
|
||||||
|
|
||||||
|
IServer.getLogger().log ("Constructing Prototype "+app.getName()+"/"+codeDir.getName ());
|
||||||
|
|
||||||
|
this.codeDir = codeDir;
|
||||||
this.app = app;
|
this.app = app;
|
||||||
this.name = name;
|
this.name = codeDir.getName ();
|
||||||
isJavaPrototype = app.isJavaPrototype (name);
|
|
||||||
lastUpdate = 0; // System.currentTimeMillis ();
|
File propfile = new File (codeDir, "type.properties");
|
||||||
}
|
SystemProperties props = new SystemProperties (propfile.getAbsolutePath ());
|
||||||
|
dbmap = new DbMapping (app, name, props);
|
||||||
|
|
||||||
|
lastUpdate = System.currentTimeMillis ();
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the application this prototype is a part of
|
|
||||||
*/
|
|
||||||
public Application getApplication () {
|
|
||||||
return app;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
public Action getActionOrTemplate (String aname) {
|
||||||
* Set the parent prototype of this prototype, i.e. the prototype this one 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;
|
|
||||||
|
|
||||||
Prototype old = this.parent;
|
|
||||||
this.parent = parent;
|
|
||||||
|
|
||||||
// if parent has changed, update ES-prototypes in request evaluators
|
Action retval = null;
|
||||||
if (parent != old) {
|
if (aname == null || "".equals (aname))
|
||||||
/* Iterator evals = app.typemgr.getRegisteredRequestEvaluators ();
|
aname = "main";
|
||||||
while (evals.hasNext ()) {
|
retval = (Action) actions.get (aname);
|
||||||
try {
|
// check if it's allowed to access templates via URL
|
||||||
RequestEvaluator reval = (RequestEvaluator) evals.next ();
|
// this should be cached in the future
|
||||||
ObjectPrototype op = reval.getPrototype (getName());
|
if (retval == null && "true".equalsIgnoreCase (app.props.getProperty ("exposetemplates")))
|
||||||
// use hopobject (node) as prototype even if prototype is null -
|
retval = (Action) templates.get (aname);
|
||||||
// this is the case if no hopobject directory exists
|
// if still not found, check if the action is defined for the generic node prototype
|
||||||
ObjectPrototype opp = parent == null ?
|
if (retval == null && this != app.typemgr.nodeProto && app.typemgr.nodeProto != null)
|
||||||
reval.esNodePrototype : reval.getPrototype (parent.getName ());
|
retval = app.typemgr.nodeProto.getActionOrTemplate (aname);
|
||||||
// don't think this is possible, but check anyway
|
return retval;
|
||||||
if (opp == null)
|
|
||||||
opp = reval.esNodePrototype;
|
|
||||||
op.setPrototype (opp);
|
|
||||||
} catch (Exception ignore) {
|
|
||||||
}
|
|
||||||
} */
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Prototype getParentPrototype () {
|
public void setPrototype (Prototype prototype) {
|
||||||
return parent;
|
this.prototype = prototype;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Prototype getPrototype () {
|
||||||
|
return prototype;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Template getTemplate (String tmpname) {
|
public Template getTemplate (String tmpname) {
|
||||||
|
@ -94,8 +82,8 @@ public class Prototype {
|
||||||
return (FunctionFile) functions.get (ffname);
|
return (FunctionFile) functions.get (ffname);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ActionFile getActionFile (String afname) {
|
public Action getAction (String afname) {
|
||||||
return (ActionFile) actions.get (afname);
|
return (Action) actions.get (afname);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SkinFile getSkinFile (String sfname) {
|
public SkinFile getSkinFile (String sfname) {
|
||||||
|
@ -110,29 +98,131 @@ public class Prototype {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public File getCodeDir () {
|
||||||
|
return codeDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized boolean checkCodeDir () {
|
||||||
|
|
||||||
|
boolean retval = false;
|
||||||
|
String[] list = codeDir.list ();
|
||||||
|
|
||||||
|
for (int i=0; i<list.length; i++) {
|
||||||
|
if (list[i].endsWith (app.templateExtension) || list[i].endsWith (app.scriptExtension)) {
|
||||||
|
File f = new File (codeDir, list[i]);
|
||||||
|
|
||||||
|
if (f.lastModified () > lastUpdate) {
|
||||||
|
lastUpdate = System.currentTimeMillis ();
|
||||||
|
try {
|
||||||
|
app.typemgr.updatePrototype (this.name, codeDir, this);
|
||||||
|
// TypeManager.broadcaster.broadcast ("Finished update for prototype "+name+" @ "+new Date ()+"<br><hr>");
|
||||||
|
} catch (Exception x) {
|
||||||
|
IServer.getLogger().log ("Error building function protos in prototype: "+x);
|
||||||
|
// TypeManager.broadcaster.broadcast ("Error updating prototype "+name+" in application "+app.getName()+":<br>"+x.getMessage ()+"<br><hr>");
|
||||||
|
}
|
||||||
|
retval = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public String getName () {
|
public String getName () {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
Updatable[] upd = null;
|
|
||||||
public Updatable[] getUpdatables () {
|
public void initRequestEvaluator (RequestEvaluator reval) {
|
||||||
if (upd == null) {
|
ObjectPrototype op = null;
|
||||||
upd = new Updatable[updatables.size()];
|
if ("user".equalsIgnoreCase (name))
|
||||||
int i = 0;
|
op = reval.esUserPrototype;
|
||||||
for (Iterator it = updatables.values().iterator(); it.hasNext(); ) {
|
else if ("global".equalsIgnoreCase (name))
|
||||||
upd[i++] = (Updatable) it.next();
|
op = reval.global;
|
||||||
}
|
else if ("hopobject".equalsIgnoreCase (name))
|
||||||
|
op = reval.esNodePrototype;
|
||||||
|
else {
|
||||||
|
op = new ObjectPrototype (reval.esNodePrototype, reval.evaluator);
|
||||||
|
try {
|
||||||
|
op.putProperty ("prototypename", new ESString (name), "prototypename".hashCode ());
|
||||||
|
} catch (EcmaScriptException ignore) {}
|
||||||
|
}
|
||||||
|
reval.putPrototype (name, op);
|
||||||
|
|
||||||
|
// Register a constructor for all types except global.
|
||||||
|
// This will first create a node and then call the actual (scripted) constructor on it.
|
||||||
|
if (!"global".equalsIgnoreCase (name)) {
|
||||||
|
try {
|
||||||
|
FunctionPrototype fp = (FunctionPrototype) reval.evaluator.getFunctionPrototype();
|
||||||
|
reval.global.putHiddenProperty (name, new NodeConstructor (name, fp, reval));
|
||||||
|
} catch (EcmaScriptException ignore) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Enumeration en = functions.elements(); en.hasMoreElements(); ) {
|
||||||
|
FunctionFile ff = (FunctionFile) en.nextElement ();
|
||||||
|
ff.updateRequestEvaluator (reval);
|
||||||
|
}
|
||||||
|
for (Enumeration en = templates.elements(); en.hasMoreElements(); ) {
|
||||||
|
Template tmp = (Template) en.nextElement ();
|
||||||
|
try {
|
||||||
|
tmp.updateRequestEvaluator (reval);
|
||||||
|
} catch (EcmaScriptException ignore) {}
|
||||||
|
}
|
||||||
|
for (Enumeration en = actions.elements(); en.hasMoreElements(); ) {
|
||||||
|
Action act = (Action) en.nextElement ();
|
||||||
|
try {
|
||||||
|
act.updateRequestEvaluator (reval);
|
||||||
|
} catch (EcmaScriptException ignore) {}
|
||||||
}
|
}
|
||||||
return upd;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public String toString () {
|
|
||||||
return "[Prototype "+ app.getName()+"/"+name+"]";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,136 +1,69 @@
|
||||||
// Skin.java
|
// Skin.java
|
||||||
// Copyright (c) Hannes Wallnöfer 2001
|
// Copyright (c) Hannes Wallnöfer 2001
|
||||||
|
|
||||||
package helma.framework.core;
|
package helma.framework.core;
|
||||||
|
|
||||||
import helma.framework.*;
|
|
||||||
import helma.scripting.*;
|
|
||||||
import helma.objectmodel.INode;
|
|
||||||
import helma.objectmodel.ConcurrencyException;
|
|
||||||
import helma.util.HtmlEncoder;
|
|
||||||
import java.net.URLEncoder;
|
|
||||||
import java.io.*;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.io.*;
|
||||||
|
import helma.framework.*;
|
||||||
|
import FESI.Data.*;
|
||||||
|
import FESI.Exceptions.*;
|
||||||
|
import helma.objectmodel.INode;
|
||||||
|
import helma.objectmodel.IServer;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This represents a Helma skin, i.e. a template created from containing Macro tags
|
* This represents a HOP skin, i.e. a template created from JavaScript. It uses the request path array
|
||||||
* that will be dynamically evaluated.. It uses the request path array
|
* from the RequestEvaluator object to resolve dynamic tokens.
|
||||||
* from the RequestEvaluator object to resolve Macro handlers by type name.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class Skin {
|
public class Skin {
|
||||||
|
|
||||||
Macro[] parts;
|
Object[] parts;
|
||||||
Application app;
|
|
||||||
char[] source;
|
|
||||||
int sourceLength;
|
|
||||||
HashSet sandbox;
|
|
||||||
|
|
||||||
/**
|
public Skin (String content) {
|
||||||
* Create a skin without any restrictions on which macros are allowed to be called from it
|
parse (content);
|
||||||
*/
|
|
||||||
public Skin (String content, Application app) {
|
|
||||||
this (content, app, null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public void parse (String content) {
|
||||||
* Create a skin with a sandbox which contains the names of macros allowed to be called
|
|
||||||
*/
|
|
||||||
public Skin (String content, Application app, HashSet sandbox) {
|
|
||||||
this.app = app;
|
|
||||||
this.sandbox = sandbox;
|
|
||||||
source = content.toCharArray ();
|
|
||||||
sourceLength = source.length;
|
|
||||||
parse ();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
Vector partBuffer = new Vector ();
|
||||||
* Create a skin without any restrictions on the macros from a char array.
|
int l = content.length ();
|
||||||
*/
|
char cnt[] = new char[l];
|
||||||
public Skin (char[] content, int length, Application app) {
|
content.getChars (0, l, cnt, 0);
|
||||||
this.app = app;
|
|
||||||
this.sandbox = null;
|
|
||||||
this.source = content;
|
|
||||||
this.sourceLength = length;
|
|
||||||
parse ();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
int lastIdx = 0;
|
||||||
* Parse a skin object from source text
|
for (int i = 0; i < l-1; i++) {
|
||||||
*/
|
if (cnt[i] == '<' && cnt[i+1] == '%') {
|
||||||
private void parse () {
|
|
||||||
|
|
||||||
ArrayList partBuffer = new ArrayList ();
|
|
||||||
|
|
||||||
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;
|
int j = i+2;
|
||||||
// search macr end tag
|
while (j < l-1 && (cnt[j] != '%' || cnt[j+1] != '>')) {
|
||||||
while (j < sourceLength-1 && (source[j] != '%' || source[j+1] != '>')) {
|
|
||||||
j++;
|
j++;
|
||||||
}
|
}
|
||||||
if (j > i+2) {
|
if (j > i+2) {
|
||||||
partBuffer.add (new Macro (i, j+2));
|
if (i - lastIdx > 0)
|
||||||
start = j+2;
|
partBuffer.addElement (new String (cnt, lastIdx, i - lastIdx));
|
||||||
|
String macrotext = new String (cnt, i+2, (j-i)-2);
|
||||||
|
partBuffer.addElement (new Macro (macrotext));
|
||||||
|
lastIdx = j+2;
|
||||||
}
|
}
|
||||||
i = j+1;
|
i = j+1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (lastIdx < l)
|
||||||
|
partBuffer.addElement (new String (cnt, lastIdx, l - lastIdx));
|
||||||
|
|
||||||
parts = new Macro[partBuffer.size()];
|
parts = partBuffer.toArray ();
|
||||||
partBuffer.toArray (parts);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the raw source text this skin was parsed from
|
|
||||||
*/
|
|
||||||
public String getSource () {
|
|
||||||
return new String (source, 0, sourceLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Render this skin
|
|
||||||
*/
|
|
||||||
public void render (RequestEvaluator reval, Object thisObject, HashMap paramObject) throws RedirectException {
|
|
||||||
|
|
||||||
|
public void render (RequestEvaluator reval, ESNode thisNode, ESObject paramObject) {
|
||||||
if (parts == null)
|
if (parts == null)
|
||||||
reval.res.writeCharArray (source, 0, sourceLength);
|
return;
|
||||||
|
|
||||||
int written = 0;
|
|
||||||
for (int i=0; i<parts.length; i++) {
|
for (int i=0; i<parts.length; i++) {
|
||||||
if (parts[i].start > written)
|
if (parts[i] instanceof Macro)
|
||||||
reval.res.writeCharArray (source, written, parts[i].start-written);
|
((Macro) parts[i]).render (reval, thisNode, paramObject);
|
||||||
parts[i].render (reval, thisObject, paramObject);
|
else
|
||||||
written = parts[i].end;
|
reval.res.write (parts[i]);
|
||||||
}
|
}
|
||||||
if (written < sourceLength)
|
|
||||||
reval.res.writeCharArray (source, written, sourceLength-written);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if a certain macro is present in this skin. The macro name is in handler.name notation
|
|
||||||
*/
|
|
||||||
public boolean containsMacro (String macroname) {
|
|
||||||
for (int i=0; i<parts.length; i++) {
|
|
||||||
if (parts[i] instanceof Macro) {
|
|
||||||
Macro m = (Macro) parts[i];
|
|
||||||
if (macroname.equals (m.getFullName ()))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a macro to the list of allowed macros. The macro is in handler.name notation.
|
|
||||||
*/
|
|
||||||
public void allowMacro (String macroname) {
|
|
||||||
if (sandbox == null) {
|
|
||||||
sandbox = new HashSet ();
|
|
||||||
}
|
|
||||||
sandbox.add (macroname);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static final int HANDLER = 0;
|
static final int HANDLER = 0;
|
||||||
|
@ -140,18 +73,17 @@ public class Skin {
|
||||||
|
|
||||||
class Macro {
|
class Macro {
|
||||||
|
|
||||||
int start, end;
|
|
||||||
String handler;
|
String handler;
|
||||||
String name;
|
String name;
|
||||||
String fullname;
|
Hashtable parameters;
|
||||||
HashMap parameters;
|
|
||||||
|
|
||||||
public Macro (int start, int end) {
|
public Macro (String str) {
|
||||||
|
|
||||||
this.start = start;
|
parameters = new Hashtable ();
|
||||||
this.end = end;
|
|
||||||
|
|
||||||
parameters = new HashMap ();
|
int l = str.length ();
|
||||||
|
char cnt[] = new char[l];
|
||||||
|
str.getChars (0, l, cnt, 0);
|
||||||
|
|
||||||
int state = HANDLER;
|
int state = HANDLER;
|
||||||
boolean escape = false;
|
boolean escape = false;
|
||||||
|
@ -159,37 +91,37 @@ public class Skin {
|
||||||
String lastParamName = null;
|
String lastParamName = null;
|
||||||
StringBuffer b = new StringBuffer();
|
StringBuffer b = new StringBuffer();
|
||||||
|
|
||||||
for (int i=start+2; i<end-2; i++) {
|
for (int i=0; i<l; i++) {
|
||||||
switch (source[i]) {
|
switch (cnt[i]) {
|
||||||
case '.':
|
case '.':
|
||||||
if (state == HANDLER) {
|
if (state == HANDLER) {
|
||||||
handler = b.toString ().trim();
|
handler = b.toString ().trim();
|
||||||
b.setLength (0);
|
b.setLength (0);
|
||||||
state = MACRO;
|
state = MACRO;
|
||||||
} else
|
} else
|
||||||
b.append (source[i]);
|
b.append (cnt[i]);
|
||||||
break;
|
break;
|
||||||
case '\\':
|
case '\\':
|
||||||
if (escape)
|
if (escape)
|
||||||
b.append (source[i]);
|
b.append (cnt[i]);
|
||||||
escape = !escape;
|
escape = !escape;
|
||||||
break;
|
break;;
|
||||||
case '"':
|
case '"':
|
||||||
case '\'':
|
case '\'':
|
||||||
if (!escape && state == PARAMVALUE) {
|
if (!escape && state == PARAMVALUE) {
|
||||||
if (quotechar == source[i]) {
|
if (quotechar == cnt[i]) {
|
||||||
parameters.put (lastParamName, b.toString());
|
parameters.put (lastParamName, b.toString());
|
||||||
lastParamName = null;
|
lastParamName = null;
|
||||||
b.setLength (0);
|
b.setLength (0);
|
||||||
state = PARAMNAME;
|
state = PARAMNAME;
|
||||||
quotechar = '\u0000';
|
quotechar = '\u0000';
|
||||||
} else if (quotechar == '\u0000') {
|
} else if (quotechar == '\u0000') {
|
||||||
quotechar = source[i];
|
quotechar = cnt[i];
|
||||||
b.setLength (0);
|
b.setLength (0);
|
||||||
} else
|
} else
|
||||||
b.append (source[i]);
|
b.append (cnt[i]);
|
||||||
} else
|
} else
|
||||||
b.append (source[i]);
|
b.append (cnt[i]);
|
||||||
escape = false;
|
escape = false;
|
||||||
break;
|
break;
|
||||||
case ' ':
|
case ' ':
|
||||||
|
@ -207,7 +139,7 @@ public class Skin {
|
||||||
b.setLength (0);
|
b.setLength (0);
|
||||||
state = PARAMNAME;
|
state = PARAMNAME;
|
||||||
} else if (state == PARAMVALUE)
|
} else if (state == PARAMVALUE)
|
||||||
b.append (source[i]);
|
b.append (cnt[i]);
|
||||||
else
|
else
|
||||||
b.setLength (0);
|
b.setLength (0);
|
||||||
break;
|
break;
|
||||||
|
@ -217,10 +149,10 @@ public class Skin {
|
||||||
b.setLength (0);
|
b.setLength (0);
|
||||||
state = PARAMVALUE;
|
state = PARAMVALUE;
|
||||||
} else
|
} else
|
||||||
b.append (source[i]);
|
b.append (cnt[i]);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
b.append (source[i]);
|
b.append (cnt[i]);
|
||||||
escape = false;
|
escape = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -233,16 +165,9 @@ public class Skin {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
public void render (RequestEvaluator reval, ESNode thisNode, ESObject paramObject) {
|
||||||
* Render the macro given a handler object
|
|
||||||
*/
|
|
||||||
public void render (RequestEvaluator reval, Object thisObject, HashMap paramObject) throws RedirectException {
|
|
||||||
|
|
||||||
if (sandbox != null && !sandbox.contains (getFullName ())) {
|
if ("response".equalsIgnoreCase (handler)) {
|
||||||
String h = handler == null ? "global" : handler;
|
|
||||||
reval.res.write ("[Macro "+getFullName()+" not allowed in sandbox]");
|
|
||||||
return;
|
|
||||||
} else if ("response".equalsIgnoreCase (handler)) {
|
|
||||||
renderFromResponse (reval);
|
renderFromResponse (reval);
|
||||||
return;
|
return;
|
||||||
} else if ("request".equalsIgnoreCase (handler)) {
|
} else if ("request".equalsIgnoreCase (handler)) {
|
||||||
|
@ -255,178 +180,129 @@ public class Skin {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
Object handlerObject = null;
|
ESObject handlerObject = null;
|
||||||
|
|
||||||
Object[] arguments = new Object[1];
|
ESValue[] arguments = new ESValue[1];
|
||||||
arguments[0] = parameters;
|
ESRequestData par = new ESRequestData (reval);
|
||||||
|
par.setData (parameters);
|
||||||
// flag to tell whether we found our invocation target object
|
arguments[0] = par;
|
||||||
boolean objectFound = true;
|
|
||||||
|
|
||||||
if (handler != null) {
|
if (handler != null) {
|
||||||
if ("currentuser".equalsIgnoreCase (handler)) {
|
// not a global macro - need to find handler object
|
||||||
// as a special convention, we use "currentuser" to access macros in the current user object
|
if (thisNode != null) {
|
||||||
handlerObject = reval.user.getNode ();
|
|
||||||
} else if (thisObject != null) {
|
|
||||||
// not a global macro - need to find handler object
|
|
||||||
// was called with this object - check it or its parents for matching prototype
|
// was called with this object - check it or its parents for matching prototype
|
||||||
if (!handler.equalsIgnoreCase ("this") && !handler.equalsIgnoreCase (app.getPrototypeName (thisObject))) {
|
if (!handler.equalsIgnoreCase ("this") && !handler.equalsIgnoreCase (thisNode.getPrototypeName ())) {
|
||||||
// the handler object is not what we want
|
// the handler object is not what we want
|
||||||
Object n = thisObject;
|
INode n = thisNode.getNode();
|
||||||
// walk down parent chain to find handler object
|
// walk down parent chain to find handler object
|
||||||
while (n != null) {
|
while (n != null) {
|
||||||
if (handler.equalsIgnoreCase (app.getPrototypeName (n))) {
|
if (handler.equalsIgnoreCase (n.getPrototype())) {
|
||||||
handlerObject = n;
|
handlerObject = reval.getNodeWrapper (n);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
n = app.getParentElement (n);
|
n = n.getParent ();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// we already have the right handler object
|
// we already have the right handler object
|
||||||
handlerObject = thisObject;
|
handlerObject = thisNode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (handlerObject == null) {
|
if (handlerObject == null) {
|
||||||
// eiter because thisObject == null or the right object wasn't found in the object's parent path
|
// eiter because thisNode == null or the right object wasn't found in the targetNode path
|
||||||
// go check request path for an object with matching prototype
|
// go check request path for an object with matching prototype
|
||||||
int l = reval.requestPath.size();
|
int l = reval.reqPath.size();
|
||||||
for (int i=l-1; i>=0; i--) {
|
for (int i=l-1; i>=0; i--) {
|
||||||
Object pathelem = reval.requestPath.get (i);
|
if (handler.equalsIgnoreCase (((ESNode) reval.reqPath.getProperty(i)).getPrototypeName())) {
|
||||||
if (handler.equalsIgnoreCase (app.getPrototypeName (pathelem))) {
|
handlerObject = (ESNode) reval.reqPath.getProperty(i);
|
||||||
handlerObject = pathelem;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// the macro handler object couldn't be found
|
|
||||||
if (handlerObject == null)
|
|
||||||
objectFound = false;
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// this is a global macro with no handler specified
|
// this is a global macro with no handler specified
|
||||||
handlerObject = null;
|
handlerObject = reval.global;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (objectFound) {
|
if (handlerObject != null) {
|
||||||
// check if a function called name_macro is defined.
|
ESValue v = handlerObject.doIndirectCall (reval.evaluator, handlerObject, name+"_macro", arguments);
|
||||||
// if so, the macro evaluates to the function. Otherwise,
|
if (v != ESUndefined.theUndefined && v != ESNull.theNull)
|
||||||
// a property/field with the name is used, if defined.
|
reval.res.write (v);
|
||||||
Object v = null;
|
|
||||||
if (app.scriptingEngine.hasFunction (handlerObject, name+"_macro", reval)) {
|
|
||||||
// System.err.println ("Getting macro from function");
|
|
||||||
v = app.scriptingEngine.invoke (handlerObject, name+"_macro", arguments, null, reval);
|
|
||||||
} else {
|
|
||||||
// System.err.println ("Getting macro from property");
|
|
||||||
v = app.scriptingEngine.get (handlerObject, name, reval);
|
|
||||||
}
|
|
||||||
if (v != null)
|
|
||||||
writeToResponse (v.toString (), reval.res);
|
|
||||||
} else {
|
} else {
|
||||||
String msg = "[HopMacro unhandled: "+getFullName()+"]";
|
String msg = "[HopMacro unhandled: "+handler+"."+name+"]";
|
||||||
reval.res.write (" "+msg+" ");
|
reval.res.write (" "+msg+" ");
|
||||||
app.logEvent (msg);
|
IServer.getLogger().log (msg);
|
||||||
}
|
}
|
||||||
} catch (RedirectException redir) {
|
|
||||||
throw redir;
|
|
||||||
} catch (ConcurrencyException concur) {
|
|
||||||
throw concur;
|
|
||||||
} catch (Exception x) {
|
} catch (Exception x) {
|
||||||
x.printStackTrace();
|
|
||||||
String msg = "[HopMacro error: "+x+"]";
|
String msg = "[HopMacro error: "+x+"]";
|
||||||
reval.res.write (" "+msg+" ");
|
reval.res.write (" "+msg+" ");
|
||||||
app.logEvent (msg);
|
IServer.getLogger().log (msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderFromResponse (RequestEvaluator reval) {
|
private void renderFromResponse (RequestEvaluator reval) {
|
||||||
Object value = null;
|
if ("title".equals (name) && reval.res.title != null)
|
||||||
// as a transitional solution, try to get the value from the
|
reval.res.write (reval.res.title);
|
||||||
// hardcoded fields in the response object. If not present, try
|
else if ("head".equals (name) && reval.res.head != null)
|
||||||
// the response object's data object.
|
reval.res.write (reval.res.head);
|
||||||
if ("title".equals (name))
|
else if ("body".equals (name) && reval.res.body != null)
|
||||||
value = reval.res.title;
|
reval.res.write (reval.res.body);
|
||||||
else if ("head".equals (name))
|
else if ("message".equals (name) && reval.res.message != null)
|
||||||
value = reval.res.head;
|
reval.res.write (reval.res.message);
|
||||||
else if ("body".equals (name))
|
|
||||||
value = reval.res.body;
|
|
||||||
else if ("message".equals (name))
|
|
||||||
value = reval.res.message;
|
|
||||||
if (value == null)
|
|
||||||
value = reval.res.get (name);
|
|
||||||
if (value != null)
|
|
||||||
writeToResponse (value.toString (), reval.res);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderFromRequest (RequestEvaluator reval) {
|
private void renderFromRequest (RequestEvaluator reval) {
|
||||||
Object value = reval.req.get (name);
|
Object value = reval.req.get (name);
|
||||||
if (value != null)
|
if (value != null)
|
||||||
writeToResponse (value.toString (), reval.res);
|
reval.res.write (value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderFromParam (RequestEvaluator reval, HashMap paramObject) {
|
private void renderFromParam (RequestEvaluator reval, ESObject paramObject) {
|
||||||
if (paramObject == null)
|
if (paramObject == null)
|
||||||
reval.res.write ("[HopMacro error: Skin requires a parameter object]");
|
reval.res.write ("[HopMacro error: Skin requires a parameter object]");
|
||||||
else {
|
else {
|
||||||
Object value = paramObject.get (name);
|
try {
|
||||||
if (value != null)
|
ESValue value = paramObject.getProperty (name, name.hashCode());
|
||||||
writeToResponse (value.toString (), reval.res);
|
if (value != null && value != ESUndefined.theUndefined)
|
||||||
|
reval.res.write (value);
|
||||||
|
} catch (EcmaScriptException ignore) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility method for writing text out to the response object.
|
|
||||||
*/
|
|
||||||
void writeToResponse (String text, ResponseTrans res) {
|
|
||||||
if (text == null || text.length() == 0)
|
|
||||||
return;
|
|
||||||
String encoding = (String) parameters.get ("encoding");
|
|
||||||
String prefix = (String) parameters.get ("prefix");
|
|
||||||
String suffix = (String) parameters.get ("suffix");
|
|
||||||
res.write (prefix);
|
|
||||||
res.write (encode (text, encoding));
|
|
||||||
res.write (suffix);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility method for performing different kind of character
|
|
||||||
* encodings on the macro output.
|
|
||||||
*/
|
|
||||||
String encode (String text, String encoding) {
|
|
||||||
if (encoding == null || text == null)
|
|
||||||
return text;
|
|
||||||
if ("html".equalsIgnoreCase (encoding))
|
|
||||||
return HtmlEncoder.encode (text);
|
|
||||||
if ("xml".equalsIgnoreCase (encoding))
|
|
||||||
return HtmlEncoder.encodeXml (text);
|
|
||||||
if ("form".equalsIgnoreCase (encoding))
|
|
||||||
return HtmlEncoder.encodeFormValue (text);
|
|
||||||
if ("url".equalsIgnoreCase (encoding))
|
|
||||||
return URLEncoder.encode (text);
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public String toString () {
|
public String toString () {
|
||||||
return "[HopMacro: "+getFullName()+"]";
|
return "[HopMacro: "+handler+","+name+"]";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the full name of the macro in handler.name notation
|
|
||||||
*/
|
|
||||||
public String getFullName () {
|
|
||||||
if (fullname == null) {
|
|
||||||
if (handler == null)
|
|
||||||
fullname = name;
|
|
||||||
else
|
|
||||||
fullname = handler+"."+name;
|
|
||||||
}
|
|
||||||
return fullname;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ package helma.framework.core;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import helma.util.Updatable;
|
import helma.objectmodel.IServer;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -13,7 +13,7 @@ import helma.util.Updatable;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
public class SkinFile implements Updatable {
|
public class SkinFile {
|
||||||
|
|
||||||
String name;
|
String name;
|
||||||
Prototype prototype;
|
Prototype prototype;
|
||||||
|
@ -30,65 +30,28 @@ public class SkinFile implements Updatable {
|
||||||
this.skin = null;
|
this.skin = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a skinfile without a file, passing the skin body directly. This is used for
|
|
||||||
* 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;
|
|
||||||
this.skin = new Skin (body, app);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
public void update (File f) {
|
||||||
* Create a skinfile without 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.prototype = null;
|
|
||||||
this.app = app;
|
|
||||||
this.name = name;
|
|
||||||
this.file = file;
|
|
||||||
this.skin = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
this.file = f;
|
||||||
|
|
||||||
/**
|
long fmod = file.lastModified ();
|
||||||
* Tell the type manager whether we need an update. this is the case when
|
// we only update this if we already have read the skin
|
||||||
* the file has been modified or deleted.
|
if (skin == null || lastmod == fmod)
|
||||||
*/
|
return;
|
||||||
public boolean needsUpdate () {
|
|
||||||
return (skin != null && lastmod != file.lastModified ()) || !file.exists ();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
read ();
|
||||||
public void update () {
|
|
||||||
|
|
||||||
if (!file.exists ()) {
|
|
||||||
// remove skin from prototype
|
|
||||||
if (prototype != null) {
|
|
||||||
prototype.skins.remove (name);
|
|
||||||
prototype.updatables.remove (file.getName());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// we only need to update if the skin has already been initialized
|
|
||||||
if (skin != null)
|
|
||||||
read ();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void read () {
|
private void read () {
|
||||||
try {
|
try {
|
||||||
FileReader reader = new FileReader (file);
|
FileReader reader = new FileReader (file);
|
||||||
char c[] = new char[(int) file.length()];
|
char c[] = new char[(int) file.length()];
|
||||||
int length = reader.read (c);
|
reader.read (c);
|
||||||
reader.close();
|
reader.close();
|
||||||
skin = new Skin (c, length, app);
|
skin = new Skin (new String (c));
|
||||||
} catch (IOException x) {
|
} catch (IOException x) {
|
||||||
app.logEvent ("Error reading Skin "+file+": "+x);
|
IServer.getLogger().log ("Error reading Skin "+file+": "+x);
|
||||||
}
|
}
|
||||||
|
|
||||||
lastmod = file.lastModified ();
|
lastmod = file.lastModified ();
|
||||||
|
@ -99,15 +62,45 @@ public class SkinFile implements Updatable {
|
||||||
read ();
|
read ();
|
||||||
return skin;
|
return skin;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName () {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString () {
|
|
||||||
return prototype.getName()+"/"+file.getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,141 +0,0 @@
|
||||||
// SkinManager.java
|
|
||||||
// Copyright (c) Hannes Wallnöfer 2002
|
|
||||||
|
|
||||||
package helma.framework.core;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.WeakHashMap;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import helma.objectmodel.INode;
|
|
||||||
import java.io.*;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Manages skins for a Helma application
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
public class SkinManager {
|
|
||||||
|
|
||||||
Application app;
|
|
||||||
Map skincache;
|
|
||||||
|
|
||||||
public SkinManager (Application app) {
|
|
||||||
this.app = app;
|
|
||||||
skincache = new WeakHashMap ();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Skin getSkin (Object object, String skinname, Object[] skinpath) {
|
|
||||||
Prototype proto = app.getPrototype (object);
|
|
||||||
String key = new StringBuffer(proto.getName()).append ("/").append (skinname)
|
|
||||||
.append ("#").append (skinpath.hashCode()).toString ();
|
|
||||||
// System.err.print ("SKINKEY: "+key);
|
|
||||||
Skin skin = (Skin) skincache.get (key);
|
|
||||||
if (skin != null) {
|
|
||||||
// System.err.println (" ... cached");
|
|
||||||
return skin;
|
|
||||||
}
|
|
||||||
// System.err.println (" ... uncached");
|
|
||||||
skin = getSkin (proto, skinname, "skin", skinpath);
|
|
||||||
if (skin != null)
|
|
||||||
skincache.put (key, skin);
|
|
||||||
return skin;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
protected Skin getSkin (Prototype proto, String skinname, String extension, 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, extension);
|
|
||||||
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, String extension) {
|
|
||||||
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, false);
|
|
||||||
if (n != null) {
|
|
||||||
n = n.getNode (skinname, false);
|
|
||||||
if (n != null) {
|
|
||||||
String skin = n.getString (extension, false);
|
|
||||||
if (skin != null) {
|
|
||||||
Skin s = (Skin) app.skincache.get (skin);
|
|
||||||
if (s == null) {
|
|
||||||
s = new Skin (skin, app);
|
|
||||||
app.skincache.put (skin, s);
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} 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+"."+extension);
|
|
||||||
if (f.exists() && f.canRead()) {
|
|
||||||
SkinFile sf = new SkinFile (f, skinname, app);
|
|
||||||
Skin s = sf.getSkin ();
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility class to use for caching skins in a Hashtable.
|
|
||||||
* The key consists out of two strings: prototype name and skin name.
|
|
||||||
*/
|
|
||||||
final class SkinKey {
|
|
||||||
|
|
||||||
final String first, second, third;
|
|
||||||
|
|
||||||
public SkinKey (String first, String second, String third) {
|
|
||||||
this.first = first;
|
|
||||||
this.second = second;
|
|
||||||
this.third = third;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean equals (Object other) {
|
|
||||||
try {
|
|
||||||
SkinKey key = (SkinKey) other;
|
|
||||||
return first.equals (key.first) && second.equals (key.second) && third.equals (key.third);
|
|
||||||
} catch (Exception x) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int hashCode () {
|
|
||||||
return first.hashCode () + second.hashCode () + third.hashCode ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,47 +1,37 @@
|
||||||
// Template.java
|
// Template.java
|
||||||
// Copyright (c) Hannes Wallnöfer 1998-2000
|
// Copyright (c) Hannes Wallnöfer 1998-2000
|
||||||
|
|
||||||
package helma.scripting;
|
package helma.framework.core;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.Vector;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.StringTokenizer;
|
|
||||||
import helma.framework.*;
|
import helma.framework.*;
|
||||||
import helma.framework.core.*;
|
import FESI.Data.*;
|
||||||
// import FESI.Data.*;
|
import FESI.Exceptions.*;
|
||||||
// import FESI.Exceptions.*;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This represents a Helma template, i.e. a file with the extension .hsp
|
* This represents a HOP template, i.e. a file with the extension .hsp
|
||||||
* (Helma server page) that contains both parts that are to be evaluated
|
* (HOP 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.
|
* 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
|
* HOP templates are callable via URL, but this is just a leftover from the
|
||||||
* days when there were no .hac (action) files. The recommended way
|
* 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
|
* now is to have a .hac file with all the logic which in turn calls one or more
|
||||||
* template files to do the formatting.
|
* template files to do the formatting.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class Template extends ActionFile {
|
public class Template extends Action {
|
||||||
|
|
||||||
// this is the *_as_string function, which is in addition to the normal one
|
// this is the *_as_string function, which is in addition to the normal one
|
||||||
// TypeUpdater psfunc;
|
TypeUpdater psfunc;
|
||||||
|
|
||||||
|
|
||||||
public Template (File file, String name, Prototype proto) {
|
public Template (File file, String name, Prototype proto) {
|
||||||
super (file, name, proto);
|
super (file, name, proto);
|
||||||
functionName = name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Template (String content, String name, Prototype proto) {
|
public void update (String content) throws Exception {
|
||||||
super (content, name, proto);
|
|
||||||
functionName = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public String getContent () {
|
|
||||||
// IServer.getLogger().log ("Reading text template " + name);
|
// IServer.getLogger().log ("Reading text template " + name);
|
||||||
|
|
||||||
Vector partBuffer = new Vector ();
|
Vector partBuffer = new Vector ();
|
||||||
|
@ -105,7 +95,7 @@ public class Template extends ActionFile {
|
||||||
// append a CRLF
|
// append a CRLF
|
||||||
newLineCount++;
|
newLineCount++;
|
||||||
templateBody.append ("\\r\\n");
|
templateBody.append ("\\r\\n");
|
||||||
} else if (!"\r".equals (nextLine)) try {
|
} else if (!"\r".equals (nextLine)){
|
||||||
StringReader lineReader = new StringReader (nextLine);
|
StringReader lineReader = new StringReader (nextLine);
|
||||||
int c = lineReader.read ();
|
int c = lineReader.read ();
|
||||||
while (c > -1) {
|
while (c > -1) {
|
||||||
|
@ -115,7 +105,7 @@ public class Template extends ActionFile {
|
||||||
templateBody.append ((char) c);
|
templateBody.append ((char) c);
|
||||||
c = lineReader.read ();
|
c = lineReader.read ();
|
||||||
}
|
}
|
||||||
} catch (IOException srx) {}
|
}
|
||||||
|
|
||||||
nextLine = st.hasMoreTokens () ? st.nextToken () : null;
|
nextLine = st.hasMoreTokens () ? st.nextToken () : null;
|
||||||
|
|
||||||
|
@ -130,7 +120,7 @@ public class Template extends ActionFile {
|
||||||
// append the number of lines we have "swallowed" into
|
// append the number of lines we have "swallowed" into
|
||||||
// one write statement, so error messages will *approximately*
|
// one write statement, so error messages will *approximately*
|
||||||
// give correct line numbers.
|
// give correct line numbers.
|
||||||
for (int i=0; i<newLineCount; i++) {
|
for (int i=0; i<newLineCount; i++) {
|
||||||
templateBody.append ("\r\n");
|
templateBody.append ("\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,9 +133,7 @@ public class Template extends ActionFile {
|
||||||
}
|
}
|
||||||
// templateBody.append ("\r\nreturn null;\r\n");
|
// templateBody.append ("\r\nreturn null;\r\n");
|
||||||
|
|
||||||
return templateBody.toString ();
|
functionName = name;
|
||||||
|
|
||||||
/*
|
|
||||||
String fname = name+"_as_string";
|
String fname = name+"_as_string";
|
||||||
String body = templateBody.toString ();
|
String body = templateBody.toString ();
|
||||||
|
|
||||||
|
@ -153,7 +141,7 @@ public class Template extends ActionFile {
|
||||||
pfunc = parseFunction (name,
|
pfunc = parseFunction (name,
|
||||||
"arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10",
|
"arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10",
|
||||||
body+"\r\nreturn null;\r\n");
|
body+"\r\nreturn null;\r\n");
|
||||||
} catch (Throwable x) {
|
} catch (Exception x) {
|
||||||
String message = x.getMessage ();
|
String message = x.getMessage ();
|
||||||
pfunc = new ErrorFeedback (name, message);
|
pfunc = new ErrorFeedback (name, message);
|
||||||
}
|
}
|
||||||
|
@ -161,7 +149,7 @@ public class Template extends ActionFile {
|
||||||
psfunc = parseFunction (fname,
|
psfunc = parseFunction (fname,
|
||||||
"arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10",
|
"arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10",
|
||||||
"res.pushStringBuffer(); "+body+"\r\nreturn res.popStringBuffer();\r\n");
|
"res.pushStringBuffer(); "+body+"\r\nreturn res.popStringBuffer();\r\n");
|
||||||
} catch (Throwable x) {
|
} catch (Exception x) {
|
||||||
String message = x.getMessage ();
|
String message = x.getMessage ();
|
||||||
psfunc = new ErrorFeedback (fname, message);
|
psfunc = new ErrorFeedback (fname, message);
|
||||||
}
|
}
|
||||||
|
@ -172,40 +160,15 @@ public class Template extends ActionFile {
|
||||||
RequestEvaluator reval = (RequestEvaluator) evals.next ();
|
RequestEvaluator reval = (RequestEvaluator) evals.next ();
|
||||||
updateRequestEvaluator (reval);
|
updateRequestEvaluator (reval);
|
||||||
} catch (Exception ignore) {}
|
} catch (Exception ignore) {}
|
||||||
} */
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void remove () {
|
public synchronized void updateRequestEvaluator (RequestEvaluator reval) throws EcmaScriptException {
|
||||||
prototype.templates.remove (name);
|
|
||||||
if (file != null)
|
|
||||||
prototype.updatables.remove (file.getName());
|
|
||||||
|
|
||||||
/* Iterator evals = app.typemgr.getRegisteredRequestEvaluators ();
|
|
||||||
while (evals.hasNext ()) {
|
|
||||||
try {
|
|
||||||
RequestEvaluator reval = (RequestEvaluator) evals.next ();
|
|
||||||
ObjectPrototype op = reval.getPrototype (prototype.getName());
|
|
||||||
functionName = name;
|
|
||||||
ESValue esv = (ESValue) op.getProperty (functionName, functionName.hashCode());
|
|
||||||
if (esv instanceof ConstructedFunctionObject || esv instanceof ThrowException) {
|
|
||||||
op.deleteProperty (functionName, functionName.hashCode());
|
|
||||||
}
|
|
||||||
String fname = name+"_as_string";
|
|
||||||
esv = (ESValue) op.getProperty (fname, fname.hashCode());
|
|
||||||
if (esv instanceof ConstructedFunctionObject || esv instanceof ThrowException) {
|
|
||||||
op.deleteProperty (fname, fname.hashCode());
|
|
||||||
}
|
|
||||||
} catch (Exception ignore) {}
|
|
||||||
} */
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* public synchronized void updateRequestEvaluator (RequestEvaluator reval) throws EcmaScriptException {
|
|
||||||
if (pfunc != null)
|
if (pfunc != null)
|
||||||
pfunc.updateRequestEvaluator (reval);
|
pfunc.updateRequestEvaluator (reval);
|
||||||
if (psfunc != null)
|
if (psfunc != null)
|
||||||
psfunc.updateRequestEvaluator (reval);
|
psfunc.updateRequestEvaluator (reval);
|
||||||
} */
|
}
|
||||||
|
|
||||||
class Part {
|
class Part {
|
||||||
|
|
||||||
|
@ -233,9 +196,34 @@ public class Template extends ActionFile {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
package helma.framework.core;
|
package helma.framework.core;
|
||||||
|
|
||||||
import helma.objectmodel.*;
|
import helma.objectmodel.*;
|
||||||
import helma.objectmodel.db.DbMapping;
|
|
||||||
import helma.scripting.*;
|
|
||||||
import helma.util.*;
|
import helma.util.*;
|
||||||
|
import FESI.Exceptions.*;
|
||||||
|
import FESI.Data.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
|
||||||
|
@ -16,13 +16,12 @@ import java.io.*;
|
||||||
* applications and updates the evaluators if anything has changed.
|
* applications and updates the evaluators if anything has changed.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class TypeManager {
|
public class TypeManager implements Runnable {
|
||||||
|
|
||||||
Application app;
|
Application app;
|
||||||
File appDir;
|
File appDir;
|
||||||
HashMap prototypes;
|
Hashtable prototypes;
|
||||||
HashMap zipfiles;
|
Prototype nodeProto;
|
||||||
long lastCheck = 0;
|
|
||||||
long idleSeconds = 120; // if idle for longer than 5 minutes, slow down
|
long idleSeconds = 120; // if idle for longer than 5 minutes, slow down
|
||||||
boolean rewire;
|
boolean rewire;
|
||||||
|
|
||||||
|
@ -30,366 +29,293 @@ public class TypeManager {
|
||||||
// and thus need to get updates
|
// and thus need to get updates
|
||||||
List registeredEvaluators;
|
List registeredEvaluators;
|
||||||
|
|
||||||
|
Thread typechecker;
|
||||||
|
|
||||||
|
// The http broadcaster for pushing out parser output
|
||||||
|
// static WebBroadcaster broadcaster;
|
||||||
|
// static {
|
||||||
|
// try {
|
||||||
|
// broadcaster = new WebBroadcaster (9999);
|
||||||
|
// } catch (IOException ignore) {}
|
||||||
|
// }
|
||||||
|
|
||||||
static HashSet standardTypes;
|
|
||||||
static {
|
|
||||||
standardTypes = new HashSet ();
|
|
||||||
standardTypes.add ("user");
|
|
||||||
standardTypes.add ("global");
|
|
||||||
standardTypes.add ("root");
|
|
||||||
standardTypes.add ("hopobject");
|
|
||||||
}
|
|
||||||
|
|
||||||
public TypeManager (Application app) {
|
public TypeManager (Application app) {
|
||||||
this.app = app;
|
this.app = app;
|
||||||
appDir = app.appDir;
|
appDir = app.appDir;
|
||||||
// make sure the directories for the standard prototypes exist, and lament otherwise
|
File f = new File (appDir, "user");
|
||||||
if (appDir.list().length == 0) {
|
if (!f.exists())
|
||||||
for (Iterator it=standardTypes.iterator (); it.hasNext (); ) {
|
f.mkdir ();
|
||||||
File f = new File (appDir, (String) it.next ());
|
f = new File (appDir, "root");
|
||||||
if (!f.exists() && !f.mkdir ())
|
if (!f.exists())
|
||||||
app.logEvent ("Warning: directory "+f.getAbsolutePath ()+" could not be created.");
|
f.mkdir ();
|
||||||
else if (!f.isDirectory ())
|
f = new File (appDir, "global");
|
||||||
app.logEvent ("Warning: "+f.getAbsolutePath ()+" is not a directory.");
|
if (!f.exists())
|
||||||
}
|
f.mkdir ();
|
||||||
}
|
prototypes = new Hashtable ();
|
||||||
prototypes = new HashMap ();
|
registeredEvaluators = Collections.synchronizedList (new ArrayList (30));
|
||||||
zipfiles = new HashMap ();
|
nodeProto = null;
|
||||||
registeredEvaluators = Collections.synchronizedList (new ArrayList ());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
public void check () {
|
||||||
* Run through application's prototype directories and create prototypes, but don't
|
|
||||||
* compile or evaluate any scripts.
|
|
||||||
*/
|
|
||||||
public void createPrototypes () {
|
|
||||||
check (false);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 < 500l)
|
|
||||||
return;
|
|
||||||
try {
|
|
||||||
check (true);
|
|
||||||
} catch (Exception ignore) {}
|
|
||||||
lastCheck = System.currentTimeMillis ();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Run through application's prototype directories and check if anything has been updated.
|
|
||||||
*/
|
|
||||||
public void check (boolean update) {
|
|
||||||
// long now = System.currentTimeMillis ();
|
// long now = System.currentTimeMillis ();
|
||||||
// System.out.print ("checking "+Thread.currentThread ());
|
// System.out.print ("checking "+Thread.currentThread ());
|
||||||
File[] list = appDir.listFiles ();
|
try {
|
||||||
if (list == null)
|
String[] list = appDir.list ();
|
||||||
throw new RuntimeException ("Can't read app directory "+appDir+" - check permissions");
|
for (int i=0; i<list.length; i++) {
|
||||||
for (int i=0; i<list.length; i++) {
|
File protoDir = new File (appDir, list[i]);
|
||||||
String filename = list[i].getName ();
|
// cut out ".." and other directories that contain "."
|
||||||
Prototype proto = getPrototype (filename);
|
if (isValidTypeName (list[i]) && protoDir.isDirectory ()) {
|
||||||
if (proto != null) {
|
Prototype proto = getPrototype (list[i]);
|
||||||
// check if existing prototype needs update
|
if (proto != null) {
|
||||||
// app.logEvent (protoDir.lastModified ());
|
// check if existing prototype needs update
|
||||||
updatePrototype (filename, list[i], proto);
|
// IServer.getLogger().log (protoDir.lastModified ());
|
||||||
} else if (list[i].isDirectory () && isValidTypeName (filename)) {
|
updatePrototype (list[i], protoDir, proto);
|
||||||
// leave out ".." and other directories that contain "."
|
} else {
|
||||||
// create new prototype
|
// create new prototype
|
||||||
proto = new Prototype (filename, app);
|
proto = new Prototype (protoDir, app);
|
||||||
registerPrototype (filename, list[i], proto, update);
|
registerPrototype (list[i], protoDir, proto);
|
||||||
prototypes.put (filename, proto);
|
prototypes.put (list[i], proto);
|
||||||
// give logger thread a chance to tell what's going on
|
if ("hopobject".equalsIgnoreCase (list[i]))
|
||||||
// Thread.yield();
|
nodeProto = proto;
|
||||||
} else if (filename.toLowerCase().endsWith (".zip") && !list[i].isDirectory ()) {
|
// give logger thread a chance to tell what's going on
|
||||||
ZippedAppFile zipped = (ZippedAppFile) zipfiles.get (filename);
|
Thread.yield();
|
||||||
if (zipped == null) {
|
}
|
||||||
zipped = new ZippedAppFile (list[i], app);
|
|
||||||
zipfiles.put (filename, zipped);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} catch (Exception ignore) {
|
||||||
|
IServer.getLogger().log (this+": "+ignore);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if standard prototypes have been created
|
|
||||||
// as a performance hack, we only do this when update is false, i.e. the first time we're called.
|
|
||||||
if (!update) {
|
|
||||||
for (Iterator it=standardTypes.iterator (); it.hasNext (); ) {
|
|
||||||
String pname = (String) it.next();
|
|
||||||
if (prototypes.get (pname) == null) {
|
|
||||||
Prototype proto = new Prototype (pname, app);
|
|
||||||
registerPrototype (pname, new File (appDir, pname), proto, false);
|
|
||||||
prototypes.put (pname, proto);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rewire) {
|
if (rewire) {
|
||||||
// there have been changes in the DbMappings
|
// there have been changes @ DbMappings
|
||||||
app.rewireDbMappings ();
|
app.rewireDbMappings ();
|
||||||
rewire = false;
|
rewire = false;
|
||||||
}
|
}
|
||||||
// app.logEvent (" ...done @ "+ (System.currentTimeMillis () - now)+ "--- "+idleSeconds);
|
// IServer.getLogger().log (" ...done @ "+ (System.currentTimeMillis () - now)+ "--- "+idleSeconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private boolean isValidTypeName (String str) {
|
private boolean isValidTypeName (String str) {
|
||||||
if (str == null)
|
if (str == null)
|
||||||
return false;
|
return false;
|
||||||
char[] c = str.toCharArray ();
|
int l = str.length ();
|
||||||
for (int i=0; i<c.length; i++)
|
if (l == 0)
|
||||||
if (!Character.isJavaIdentifierPart (c[i]))
|
return false;
|
||||||
|
for (int i=0; i<l; i++)
|
||||||
|
if (!Character.isJavaIdentifierPart (str.charAt (i)))
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public void start () {
|
||||||
* Get a prototype defined for this application
|
stop ();
|
||||||
*/
|
typechecker = new Thread (this, "Typechecker-"+app.getName());
|
||||||
|
typechecker.setPriority (Thread.MIN_PRIORITY);
|
||||||
|
typechecker.start ();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stop () {
|
||||||
|
if (typechecker != null && typechecker.isAlive ())
|
||||||
|
typechecker.interrupt ();
|
||||||
|
typechecker = null;
|
||||||
|
}
|
||||||
|
|
||||||
public Prototype getPrototype (String typename) {
|
public Prototype getPrototype (String typename) {
|
||||||
return (Prototype) prototypes.get (typename);
|
return (Prototype) prototypes.get (typename);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a prototype, creating it if id doesn't already exist
|
public void run () {
|
||||||
*/
|
|
||||||
public Prototype createPrototype (String typename) {
|
while (Thread.currentThread () == typechecker) {
|
||||||
Prototype p = getPrototype (typename);
|
idleSeconds++;
|
||||||
if (p == null) {
|
try {
|
||||||
p = new Prototype (typename, app);
|
// for each idle minute, add 300 ms to sleeptime until 5 secs are reached.
|
||||||
p.templates = new HashMap ();
|
// (10 secs are reached after 30 minutes of idle state)
|
||||||
p.functions = new HashMap ();
|
// the above is all false.
|
||||||
p.actions = new HashMap ();
|
long sleeptime = 1500 + Math.min (idleSeconds*30, 3500);
|
||||||
p.skins = new HashMap ();
|
typechecker.sleep (sleeptime);
|
||||||
p.updatables = new HashMap ();
|
} catch (InterruptedException x) {
|
||||||
prototypes.put (typename, p);
|
// IServer.getLogger().log ("Typechecker interrupted");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
check ();
|
||||||
}
|
}
|
||||||
return p;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
public void registerPrototype (String name, File dir, Prototype proto) {
|
||||||
* Create a prototype from a directory containing scripts and other stuff
|
// IServer.getLogger().log ("registering prototype "+name);
|
||||||
*/
|
|
||||||
public void registerPrototype (String name, File dir, Prototype proto, boolean update) {
|
|
||||||
// app.logEvent ("registering prototype "+name);
|
|
||||||
|
|
||||||
// show the type checker thread that there has been type activity
|
// show the type checker thread that there has been type activity
|
||||||
idleSeconds = 0;
|
idleSeconds = 0;
|
||||||
|
|
||||||
HashMap ntemp = new HashMap ();
|
String list[] = dir.list();
|
||||||
HashMap nfunc = new HashMap ();
|
Hashtable ntemp = new Hashtable ();
|
||||||
HashMap nact = new HashMap ();
|
Hashtable nfunc = new Hashtable ();
|
||||||
HashMap nskins = new HashMap ();
|
Hashtable nact = new Hashtable ();
|
||||||
HashMap updatables = new HashMap ();
|
Hashtable nskins = new Hashtable ();
|
||||||
|
|
||||||
if (update) {
|
|
||||||
String list[] = dir.list();
|
|
||||||
for (int i=0; i<list.length; i++) {
|
|
||||||
File tmpfile = new File (dir, list[i]);
|
|
||||||
int dot = list[i].indexOf (".");
|
|
||||||
|
|
||||||
if (dot < 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
String tmpname = list[i].substring(0, dot);
|
|
||||||
|
|
||||||
if (list[i].endsWith (app.templateExtension)) {
|
|
||||||
try {
|
|
||||||
Template t = new Template (tmpfile, tmpname, proto);
|
|
||||||
updatables.put (list[i], t);
|
|
||||||
ntemp.put (tmpname, t);
|
|
||||||
} catch (Throwable x) {
|
|
||||||
app.logEvent ("Error creating prototype: "+x);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (list[i].endsWith (app.scriptExtension) && tmpfile.length () > 0) {
|
|
||||||
try {
|
|
||||||
FunctionFile ff = new FunctionFile (tmpfile, tmpname, proto);
|
|
||||||
updatables.put (list[i], ff);
|
|
||||||
nfunc.put (tmpname, ff);
|
|
||||||
} catch (Throwable x) {
|
|
||||||
app.logEvent ("Error creating prototype: "+x);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (list[i].endsWith (app.actionExtension) && tmpfile.length () > 0) {
|
|
||||||
try {
|
|
||||||
ActionFile af = new ActionFile (tmpfile, tmpname, proto);
|
|
||||||
updatables.put (list[i], af);
|
|
||||||
nact.put (tmpname, af);
|
|
||||||
} catch (Throwable x) {
|
|
||||||
app.logEvent ("Error creating prototype: "+x);
|
|
||||||
}
|
|
||||||
} else if (list[i].endsWith (app.skinExtension)) {
|
|
||||||
try {
|
|
||||||
SkinFile sf = new SkinFile (tmpfile, tmpname, proto);
|
|
||||||
updatables.put (list[i], sf);
|
|
||||||
nskins.put (tmpname, sf);
|
|
||||||
} catch (Throwable x) {
|
|
||||||
app.logEvent ("Error creating prototype: "+x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create and register type properties file
|
|
||||||
File propfile = new File (dir, "type.properties");
|
|
||||||
SystemProperties props = new SystemProperties (propfile.getAbsolutePath ());
|
|
||||||
DbMapping dbmap = new DbMapping (app, name, props);
|
|
||||||
updatables.put ("type.properties", dbmap);
|
|
||||||
|
|
||||||
|
|
||||||
proto.templates = ntemp;
|
|
||||||
proto.functions = nfunc;
|
|
||||||
proto.actions = nact;
|
|
||||||
proto.skins = nskins;
|
|
||||||
proto.updatables = updatables;
|
|
||||||
|
|
||||||
// init prototype on evaluators that are already initialized.
|
|
||||||
/* Iterator evals = getRegisteredRequestEvaluators ();
|
|
||||||
while (evals.hasNext ()) {
|
|
||||||
RequestEvaluator reval = (RequestEvaluator) evals.next ();
|
|
||||||
proto.initRequestEvaluator (reval);
|
|
||||||
}*/
|
|
||||||
app.scriptingEngine.updatePrototype (proto);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update a prototype based on the directory which defines it.
|
|
||||||
*/
|
|
||||||
public void updatePrototype (String name, File dir, Prototype proto) {
|
|
||||||
|
|
||||||
boolean needsUpdate = false;
|
|
||||||
HashSet updatables = null;
|
|
||||||
|
|
||||||
// our plan is to do as little as possible, so first check if anything has changed at all...
|
|
||||||
for (Iterator i = proto.updatables.values().iterator(); i.hasNext(); ) {
|
|
||||||
Updatable upd = (Updatable) i.next();
|
|
||||||
if (upd.needsUpdate ()) {
|
|
||||||
if (updatables == null)
|
|
||||||
updatables = new HashSet ();
|
|
||||||
needsUpdate = true;
|
|
||||||
updatables.add (upd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if file have been created since last update
|
|
||||||
if (proto.lastUpdate < dir.lastModified ()) {
|
|
||||||
String[] list = dir.list();
|
|
||||||
for (int i=0; i<list.length; i++) {
|
|
||||||
String fn = list[i];
|
|
||||||
if (!proto.updatables.containsKey (fn)) {
|
|
||||||
if (fn.endsWith (app.templateExtension) || fn.endsWith (app.scriptExtension) ||
|
|
||||||
fn.endsWith (app.actionExtension) || fn.endsWith (app.skinExtension) ||
|
|
||||||
"type.properties".equalsIgnoreCase (fn)) {
|
|
||||||
needsUpdate = true;
|
|
||||||
// updatables.add ("[new:"+proto.getName()+"/"+fn+"]");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!needsUpdate)
|
|
||||||
return;
|
|
||||||
|
|
||||||
proto.lastUpdate = System.currentTimeMillis ();
|
|
||||||
|
|
||||||
// let the thread know we had to do something.
|
|
||||||
idleSeconds = 0;
|
|
||||||
// app.logEvent ("TypeManager: Updating prototypes for "+app.getName()+": "+updatables);
|
|
||||||
|
|
||||||
// first go through new files and create new items
|
|
||||||
String[] list = dir.list ();
|
|
||||||
for (int i=0; i<list.length; i++) {
|
for (int i=0; i<list.length; i++) {
|
||||||
String fn = list[i];
|
File tmpfile = new File (dir, list[i]);
|
||||||
int dot = fn.indexOf (".");
|
int dot = list[i].indexOf (".");
|
||||||
|
|
||||||
if (dot < 0)
|
if (dot < 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (proto.updatables.containsKey (fn) || !(fn.endsWith (app.templateExtension) || fn.endsWith (app.scriptExtension) ||
|
|
||||||
fn.endsWith (app.actionExtension) || fn.endsWith (app.skinExtension) || "type.properties".equalsIgnoreCase (fn))) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
String tmpname = list[i].substring(0, dot);
|
String tmpname = list[i].substring(0, dot);
|
||||||
File tmpfile = new File (dir, list[i]);
|
|
||||||
|
|
||||||
if (list[i].endsWith (app.templateExtension)) {
|
if (list[i].endsWith (app.templateExtension)) {
|
||||||
try {
|
try {
|
||||||
Template t = new Template (tmpfile, tmpname, proto);
|
Template t = new Template (tmpfile, tmpname, proto);
|
||||||
proto.updatables.put (list[i], t);
|
ntemp.put (tmpname, t);
|
||||||
proto.templates.put (tmpname, t);
|
|
||||||
} catch (Throwable x) {
|
} catch (Throwable x) {
|
||||||
app.logEvent ("Error updating prototype: "+x);
|
IServer.getLogger().log ("Error creating prototype: "+x);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (list[i].endsWith (app.scriptExtension)) {
|
} else if (list[i].endsWith (app.scriptExtension) && tmpfile.length () > 0) {
|
||||||
try {
|
try {
|
||||||
FunctionFile ff = new FunctionFile (tmpfile, tmpname, proto);
|
FunctionFile ff = new FunctionFile (tmpfile, tmpname, proto);
|
||||||
proto.updatables.put (list[i], ff);
|
nfunc.put (tmpname, ff);
|
||||||
proto.functions.put (tmpname, ff);
|
|
||||||
} catch (Throwable x) {
|
} catch (Throwable x) {
|
||||||
app.logEvent ("Error updating prototype: "+x);
|
IServer.getLogger().log ("Error creating prototype: "+x);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (list[i].endsWith (app.actionExtension)) {
|
} else if (list[i].endsWith (app.actionExtension) && tmpfile.length () > 0) {
|
||||||
try {
|
try {
|
||||||
ActionFile af = new ActionFile (tmpfile, tmpname, proto);
|
Action af = new Action (tmpfile, tmpname, proto);
|
||||||
proto.updatables.put (list[i], af);
|
nact.put (tmpname, af);
|
||||||
proto.actions.put (tmpname, af);
|
|
||||||
} catch (Throwable x) {
|
} catch (Throwable x) {
|
||||||
app.logEvent ("Error updating prototype: "+x);
|
IServer.getLogger().log ("Error creating prototype: "+x);
|
||||||
}
|
}
|
||||||
|
} else if (list[i].endsWith (app.skinExtension)) {
|
||||||
|
try {
|
||||||
|
SkinFile sf = new SkinFile (tmpfile, tmpname, proto);
|
||||||
|
nskins.put (tmpname, sf);
|
||||||
|
} catch (Throwable x) {
|
||||||
|
IServer.getLogger().log ("Error creating prototype: "+x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
proto.templates = ntemp;
|
||||||
|
proto.functions = nfunc;
|
||||||
|
proto.actions = nact;
|
||||||
|
proto.skins = nskins;
|
||||||
|
|
||||||
} else if (list[i].endsWith (app.skinExtension)) {
|
// init prototype on evaluators that are already initialized.
|
||||||
SkinFile sf = new SkinFile (tmpfile, tmpname, proto);
|
Iterator evals = getRegisteredRequestEvaluators ();
|
||||||
proto.updatables.put (list[i], sf);
|
while (evals.hasNext ()) {
|
||||||
proto.skins.put (tmpname, sf);
|
RequestEvaluator reval = (RequestEvaluator) evals.next ();
|
||||||
}
|
proto.initRequestEvaluator (reval);
|
||||||
}
|
}
|
||||||
|
|
||||||
// next go through existing updatables
|
|
||||||
if (updatables != null) {
|
|
||||||
for (Iterator i = updatables.iterator(); i.hasNext(); ) {
|
|
||||||
Updatable upd = (Updatable) i.next();
|
|
||||||
|
|
||||||
if (upd.needsUpdate ()) {
|
|
||||||
if (upd instanceof DbMapping)
|
|
||||||
rewire = true;
|
|
||||||
try {
|
|
||||||
upd.update ();
|
|
||||||
} catch (Exception x) {
|
|
||||||
if (upd instanceof DbMapping)
|
|
||||||
app.logEvent ("Error updating db mapping for type "+name+": "+x);
|
|
||||||
else
|
|
||||||
app.logEvent ("Error updating "+upd+" of prototye type "+name+": "+x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
app.scriptingEngine.updatePrototype (proto);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*public void initRequestEvaluator (RequestEvaluator reval) {
|
public void updatePrototype (String name, File dir, Prototype proto) {
|
||||||
|
// IServer.getLogger().log ("updating prototype "+name);
|
||||||
|
|
||||||
|
String list[] = dir.list();
|
||||||
|
Hashtable ntemp = new Hashtable ();
|
||||||
|
Hashtable nfunc = new Hashtable ();
|
||||||
|
Hashtable nact = new Hashtable ();
|
||||||
|
Hashtable nskins = new Hashtable ();
|
||||||
|
|
||||||
|
for (int i=0; i<list.length; i++) {
|
||||||
|
File tmpfile = new File (dir, list[i]);
|
||||||
|
int dot = list[i].indexOf (".");
|
||||||
|
|
||||||
|
if (dot < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
String tmpname = list[i].substring(0, dot);
|
||||||
|
if (list[i].endsWith (app.templateExtension)) {
|
||||||
|
Template t = proto.getTemplate (tmpname);
|
||||||
|
try {
|
||||||
|
if (t == null) {
|
||||||
|
t = new Template (tmpfile, tmpname, proto);
|
||||||
|
idleSeconds = 0;
|
||||||
|
} else if (t.lastmod != tmpfile.lastModified ()) {
|
||||||
|
t.update (tmpfile);
|
||||||
|
idleSeconds = 0;
|
||||||
|
}
|
||||||
|
} catch (Throwable x) {
|
||||||
|
IServer.getLogger().log ("Error updating prototype: "+x);
|
||||||
|
}
|
||||||
|
ntemp.put (tmpname, t);
|
||||||
|
|
||||||
|
} else if (list[i].endsWith (app.scriptExtension) && tmpfile.length () > 0) {
|
||||||
|
FunctionFile ff = proto.getFunctionFile (tmpname);
|
||||||
|
try {
|
||||||
|
if (ff == null) {
|
||||||
|
ff = new FunctionFile (tmpfile, tmpname, proto);
|
||||||
|
idleSeconds = 0;
|
||||||
|
} else if (ff.lastmod != tmpfile.lastModified ()) {
|
||||||
|
ff.update (tmpfile);
|
||||||
|
idleSeconds = 0;
|
||||||
|
}
|
||||||
|
} catch (Throwable x) {
|
||||||
|
IServer.getLogger().log ("Error updating prototype: "+x);
|
||||||
|
}
|
||||||
|
nfunc.put (tmpname, ff);
|
||||||
|
|
||||||
|
} else if (list[i].endsWith (app.actionExtension) && tmpfile.length () > 0) {
|
||||||
|
Action af = proto.getAction (tmpname);
|
||||||
|
try {
|
||||||
|
if (af == null) {
|
||||||
|
af = new Action (tmpfile, tmpname, proto);
|
||||||
|
idleSeconds = 0;
|
||||||
|
} else if (af.lastmod != tmpfile.lastModified ()) {
|
||||||
|
af.update (tmpfile);
|
||||||
|
idleSeconds = 0;
|
||||||
|
}
|
||||||
|
} catch (Throwable x) {
|
||||||
|
IServer.getLogger().log ("Error updating prototype: "+x);
|
||||||
|
}
|
||||||
|
nact.put (tmpname, af);
|
||||||
|
|
||||||
|
} else if (list[i].endsWith (app.skinExtension)) {
|
||||||
|
SkinFile sf = proto.getSkinFile (tmpname);
|
||||||
|
try {
|
||||||
|
if (sf == null) {
|
||||||
|
sf = new SkinFile (tmpfile, tmpname, proto);
|
||||||
|
idleSeconds = 0;
|
||||||
|
} else if (sf.lastmod != tmpfile.lastModified ()) {
|
||||||
|
sf.update (tmpfile);
|
||||||
|
idleSeconds = 0;
|
||||||
|
}
|
||||||
|
} catch (Throwable x) {
|
||||||
|
IServer.getLogger().log ("Error updating prototype: "+x);
|
||||||
|
}
|
||||||
|
nskins.put (tmpname, sf);
|
||||||
|
|
||||||
|
} else if ("type.properties".equalsIgnoreCase (list[i])) {
|
||||||
|
try {
|
||||||
|
if (proto.dbmap.read ()) {
|
||||||
|
idleSeconds = 0;
|
||||||
|
rewire = true;
|
||||||
|
}
|
||||||
|
} catch (Exception ignore) {
|
||||||
|
IServer.getLogger().log ("Error updating db mapping for type "+name+": "+ignore);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
proto.templates = ntemp;
|
||||||
|
proto.functions = nfunc;
|
||||||
|
proto.actions = nact;
|
||||||
|
proto.skins = nskins;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public void initRequestEvaluator (RequestEvaluator reval) {
|
||||||
if (!registeredEvaluators.contains (reval))
|
if (!registeredEvaluators.contains (reval))
|
||||||
registeredEvaluators.add (reval);
|
registeredEvaluators.add (reval);
|
||||||
for (Iterator it = prototypes.values().iterator(); it.hasNext(); ) {
|
for (Enumeration en = prototypes.elements(); en.hasMoreElements(); ) {
|
||||||
Prototype p = (Prototype) it.next ();
|
Prototype p = (Prototype) en.nextElement ();
|
||||||
p.initRequestEvaluator (reval);
|
p.initRequestEvaluator (reval);
|
||||||
}
|
}
|
||||||
reval.initialized = true;
|
reval.initialized = true;
|
||||||
|
@ -405,7 +331,103 @@ public class TypeManager {
|
||||||
|
|
||||||
public int countRegisteredRequestEvaluators () {
|
public int countRegisteredRequestEvaluators () {
|
||||||
return registeredEvaluators.size ();
|
return registeredEvaluators.size ();
|
||||||
} */
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -7,46 +7,29 @@ import java.io.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import helma.objectmodel.*;
|
import helma.objectmodel.*;
|
||||||
import helma.objectmodel.db.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This represents a user who is currently using the Hop application. This does
|
* This represents a user who is currently using the HOP application. This does
|
||||||
* not just comprend registered users, but anybody who happens to surf the site.
|
* not just comprend registered users, but anybody who happens to surf the site.
|
||||||
* Depending on whether the user is logged in or not, the user object holds a
|
|
||||||
* persistent user node or just a transient cache node
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class User implements Serializable {
|
public class User implements Serializable {
|
||||||
|
|
||||||
Application app;
|
Application app;
|
||||||
String sessionID;
|
String sessionID;
|
||||||
|
String uid, nid;
|
||||||
// the unique id (login name) for the user, if logged in
|
|
||||||
String uid;
|
|
||||||
|
|
||||||
// the handle to this user's persistent db node, if logged in
|
|
||||||
NodeHandle nhandle;
|
|
||||||
|
|
||||||
// the transient cache node. This stays the same across logins and logouts.
|
|
||||||
// If logged out, this also represents the user's main node.
|
|
||||||
TransientNode cache;
|
|
||||||
|
|
||||||
DbMapping umap;
|
|
||||||
long onSince, lastTouched;
|
long onSince, lastTouched;
|
||||||
|
Node cache;
|
||||||
// used to remember messages to the user between requests -
|
DbMapping umap;
|
||||||
// used for redirects.
|
|
||||||
String message;
|
String message;
|
||||||
|
|
||||||
public User (String sid, Application app) {
|
public User (String sid, Application app) {
|
||||||
this.uid = null;
|
this.uid = null;
|
||||||
this.nhandle = null;
|
this.nid = null;
|
||||||
this.app = app;
|
this.app = app;
|
||||||
setNode (null);
|
setNode (null);
|
||||||
umap = app.getDbMapping ("user");
|
cache = new Node (sid);
|
||||||
cache = new TransientNode ("[session cache]");
|
cache.setPrototype ("user");
|
||||||
cache.setPrototype ("user");
|
|
||||||
cache.setDbMapping (umap);
|
|
||||||
sessionID = sid;
|
sessionID = sid;
|
||||||
onSince = System.currentTimeMillis ();
|
onSince = System.currentTimeMillis ();
|
||||||
lastTouched = onSince;
|
lastTouched = onSince;
|
||||||
|
@ -54,38 +37,26 @@ public class User implements Serializable {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is used to turn for login and logout.
|
* This is used to turn an anonymous user into a registered or known one.
|
||||||
* Calling this weith a DB Node object will turn an anonymous user into a registered or known one.
|
* The user object remains the same, but she gets some persistent storage.
|
||||||
* The user object remains the same, but he or she gets some persistent storage.
|
|
||||||
* On the other side, calling this method with a parameter value of null is means the user
|
|
||||||
* is logged out and will be represented by its transient cache node.
|
|
||||||
*/
|
*/
|
||||||
public void setNode (INode n) {
|
public void setNode (INode n) {
|
||||||
// IServer.getLogger().log ("esn = "+esn);
|
// IServer.getLogger().log ("esn = "+esn);
|
||||||
if (n == null) {
|
if (n == null) {
|
||||||
nhandle = null;
|
nid = null;
|
||||||
uid = null;
|
uid = null;
|
||||||
} else {
|
} else {
|
||||||
uid = n.getElementName ();
|
uid = n.getNameOrID ();
|
||||||
nhandle = ((Node) n).getHandle ();
|
nid = n.getID ();
|
||||||
|
umap = n.getDbMapping ();
|
||||||
}
|
}
|
||||||
// System.err.println ("User.setNode: "+nhandle);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public INode getNode () {
|
public INode getNode () {
|
||||||
if (nhandle == null) {
|
if (uid == null) {
|
||||||
return cache;
|
return cache;
|
||||||
} else {
|
} else {
|
||||||
// in some special cases, a user's node handle may go bad, for instance
|
return app.nmgr.safe.getNode (nid, umap);
|
||||||
// if something bad happens during registration. For this reason, we check
|
|
||||||
// if the handle actually works. If not, it is reset to the transient cache, which
|
|
||||||
// means the user is logged out.
|
|
||||||
Node n = nhandle.getNode (app.nmgr.safe);
|
|
||||||
if (n == null) {
|
|
||||||
setNode (null);
|
|
||||||
return cache;
|
|
||||||
}
|
|
||||||
return n;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,37 +69,39 @@ public class User implements Serializable {
|
||||||
lastTouched = System.currentTimeMillis ();
|
lastTouched = System.currentTimeMillis ();
|
||||||
}
|
}
|
||||||
|
|
||||||
public long lastTouched () {
|
public long touched () {
|
||||||
return lastTouched;
|
return lastTouched;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long onSince () {
|
|
||||||
return onSince;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the transient cache node for this user.
|
|
||||||
*/
|
|
||||||
public INode getCache () {
|
|
||||||
return cache;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset the session cache node, clearing all properties.
|
|
||||||
* This is done by recreating the cache node object.
|
|
||||||
*/
|
|
||||||
public void clearCache () {
|
|
||||||
cache = new TransientNode ("[session cache]");
|
|
||||||
cache.setPrototype ("user");
|
|
||||||
cache.setDbMapping (umap);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,186 +0,0 @@
|
||||||
// ZippedFile.java
|
|
||||||
// Copyright (c) Hannes Wallnöfer 2001
|
|
||||||
|
|
||||||
package helma.framework.core;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
|
|
||||||
public ZippedAppFile (File file, Application app) {
|
|
||||||
this.app = app;
|
|
||||||
this.file = file;
|
|
||||||
// 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 lastmod != file.lastModified ();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void update () {
|
|
||||||
|
|
||||||
if (!file.exists ()) {
|
|
||||||
remove ();
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
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);
|
|
||||||
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 content = getZipEntryContent (zip, entry);
|
|
||||||
// System.err.println ("["+content+"]");
|
|
||||||
ActionFile act = new ActionFile (content, name, proto);
|
|
||||||
proto.actions.put (name, act);
|
|
||||||
}
|
|
||||||
else if (fname.endsWith (".hsp")) {
|
|
||||||
String name = fname.substring (0, fname.lastIndexOf ("."));
|
|
||||||
String content = getZipEntryContent (zip, entry);
|
|
||||||
// System.err.println ("["+content+"]");
|
|
||||||
Template tmp = new Template (content, name, proto);
|
|
||||||
proto.templates.put (name, tmp);
|
|
||||||
}
|
|
||||||
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.skins.put (name, skin);
|
|
||||||
}
|
|
||||||
else if (fname.endsWith (".js")) {
|
|
||||||
String name = fname.substring (0, fname.lastIndexOf ("."));
|
|
||||||
String content = getZipEntryContent (zip, entry);
|
|
||||||
// System.err.println ("["+content+"]");
|
|
||||||
FunctionFile ff = new FunctionFile (content, name, proto);
|
|
||||||
proto.functions.put (name, ff);
|
|
||||||
}
|
|
||||||
else if ("type.properties".equalsIgnoreCase (fname)) {
|
|
||||||
String name = fname.substring (0, fname.lastIndexOf ("."));
|
|
||||||
SystemProperties props = new SystemProperties (zip.getInputStream (entry));
|
|
||||||
// DbMapping does its own registering, just construct it.
|
|
||||||
new DbMapping (app, proto.getName (), props);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (Iterator it = newPrototypes.iterator (); it.hasNext (); ) {
|
|
||||||
Prototype proto = (Prototype) it.next ();
|
|
||||||
if (app.getDbMapping (proto.getName ()) == null) {
|
|
||||||
// DbMapping doesn't exist, we still need to create one
|
|
||||||
SystemProperties props = new SystemProperties ();
|
|
||||||
// DbMapping does its own registering, just construct it.
|
|
||||||
new DbMapping (app, proto.getName (), props);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Throwable x) {
|
|
||||||
System.err.println ("Error updating ZipFile: "+x);
|
|
||||||
} finally {
|
|
||||||
try {
|
|
||||||
zip.close ();
|
|
||||||
} catch (Exception ignore) {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void remove () {
|
|
||||||
app.typemgr.zipfiles.remove (file.getName());
|
|
||||||
// System.err.println ("REMOVING ZIP FILE "+this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public String toString () {
|
|
||||||
return file.getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,74 +0,0 @@
|
||||||
// SimplePathElement.java
|
|
||||||
// Copyright Hannes Wallnöfer 2001
|
|
||||||
|
|
||||||
package helma.framework.demo;
|
|
||||||
|
|
||||||
import helma.framework.IPathElement;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is an example implementation for the helma.framework.IPathElement interface.
|
|
||||||
* It creates any child element which is requested on the fly without ever asking.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class SimplePathElement implements IPathElement {
|
|
||||||
|
|
||||||
String name;
|
|
||||||
String prototype;
|
|
||||||
IPathElement parent;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor for the root element.
|
|
||||||
*/
|
|
||||||
public SimplePathElement () {
|
|
||||||
name = "root";
|
|
||||||
prototype = "root";
|
|
||||||
parent = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor for non-root elements.
|
|
||||||
*/
|
|
||||||
public SimplePathElement (String n, IPathElement p) {
|
|
||||||
name = n;
|
|
||||||
prototype = "hopobject";
|
|
||||||
parent = p;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a child element for this object, creating it on the fly.
|
|
||||||
*/
|
|
||||||
public IPathElement getChildElement (String n) {
|
|
||||||
return new SimplePathElement (n, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns this object's parent element
|
|
||||||
*/
|
|
||||||
public IPathElement getParentElement () {
|
|
||||||
return parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the element name to be used for this object.
|
|
||||||
*/
|
|
||||||
public String getElementName () {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the name of the scripting prototype to be used for this object.
|
|
||||||
* This will be "root" for the root element and "hopobject for everything else.
|
|
||||||
*/
|
|
||||||
public String getPrototype () {
|
|
||||||
return prototype;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a string representation of this element.
|
|
||||||
*/
|
|
||||||
public String toString () {
|
|
||||||
return "SimplePathElement "+name;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -16,12 +16,11 @@
|
||||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
|
||||||
// Modified to use Helma database connections, Hannes Wallnöfer 2000
|
// Modified to use HOP database connections, Hannes Wallnöfer 2000
|
||||||
|
|
||||||
package helma.scripting.fesi.extensions;
|
package helma.framework.extensions;
|
||||||
|
|
||||||
import helma.framework.core.Application;
|
import helma.objectmodel.*;
|
||||||
import helma.objectmodel.db.DbSource;
|
|
||||||
import FESI.Parser.*;
|
import FESI.Parser.*;
|
||||||
import FESI.AST.*;
|
import FESI.AST.*;
|
||||||
import FESI.Interpreter.*;
|
import FESI.Interpreter.*;
|
||||||
|
@ -60,12 +59,13 @@ class ESDatabase extends ESObject {
|
||||||
ESDatabase(ESObject prototype,
|
ESDatabase(ESObject prototype,
|
||||||
Evaluator evaluator,
|
Evaluator evaluator,
|
||||||
ESObject esRowSetPrototype,
|
ESObject esRowSetPrototype,
|
||||||
DbSource dbsource, int flag) {
|
String dbsource, int flag) {
|
||||||
super(prototype, evaluator);
|
super(prototype, evaluator);
|
||||||
this.esRowSetPrototype = esRowSetPrototype; // specific to an evaluator
|
this.esRowSetPrototype = esRowSetPrototype; // specific to an evaluator
|
||||||
try {
|
try {
|
||||||
connection = dbsource.getConnection ();
|
DbSource src = (DbSource) IServer.dbSources.get (dbsource.toLowerCase ());
|
||||||
driverName = dbsource.getDriverName ();
|
connection = src.getConnection ();
|
||||||
|
this.driverName = src.getDriverName ();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// System.err.println("##Cannot find driver class: " + e);
|
// System.err.println("##Cannot find driver class: " + e);
|
||||||
// e.printStackTrace();
|
// e.printStackTrace();
|
||||||
|
@ -717,17 +717,11 @@ public class Database extends Extension {
|
||||||
private transient Evaluator evaluator = null;
|
private transient Evaluator evaluator = null;
|
||||||
private ESObject esDatabasePrototype = null;
|
private ESObject esDatabasePrototype = null;
|
||||||
private ESObject esRowSetPrototype = null;
|
private ESObject esRowSetPrototype = null;
|
||||||
Application app;
|
|
||||||
|
|
||||||
public Database () {
|
public Database () {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void setApplication (Application app) {
|
|
||||||
this.app = app;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////// Added by Hannes Wallnoefer
|
////////////////// Added by Hannes Wallnoefer
|
||||||
class GlobalGetDBConnection extends BuiltinFunctionObject {
|
class GlobalGetDBConnection extends BuiltinFunctionObject {
|
||||||
GlobalGetDBConnection(String name, Evaluator evaluator, FunctionPrototype fp) {
|
GlobalGetDBConnection(String name, Evaluator evaluator, FunctionPrototype fp) {
|
||||||
|
@ -737,17 +731,13 @@ public class Database extends Extension {
|
||||||
throws EcmaScriptException {
|
throws EcmaScriptException {
|
||||||
if (arguments.length != 1)
|
if (arguments.length != 1)
|
||||||
throw new EcmaScriptException ("Wrong number of arguments in getDBConnection(dbsource)");
|
throw new EcmaScriptException ("Wrong number of arguments in getDBConnection(dbsource)");
|
||||||
String srcname = arguments[0].toString ();
|
|
||||||
DbSource dbsrc = app.getDbSource (srcname.toLowerCase ());
|
|
||||||
if (dbsrc == null)
|
|
||||||
throw new EcmaScriptException ("DbSource "+srcname+" does not exist");
|
|
||||||
ESDatabase db = new ESDatabase (esDatabasePrototype, this.evaluator,
|
ESDatabase db = new ESDatabase (esDatabasePrototype, this.evaluator,
|
||||||
esRowSetPrototype, dbsrc, 0);
|
esRowSetPrototype, arguments[0].toString(), 0);
|
||||||
return db;
|
return db;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class GlobalObjectDatabase extends BuiltinFunctionObject {
|
class GlobalObjectDatabase extends BuiltinFunctionObject {
|
||||||
GlobalObjectDatabase(String name, Evaluator evaluator, FunctionPrototype fp) {
|
GlobalObjectDatabase(String name, Evaluator evaluator, FunctionPrototype fp) {
|
||||||
super(fp, evaluator, name, 1);
|
super(fp, evaluator, name, 1);
|
|
@ -2,7 +2,7 @@
|
||||||
// Copyright (c) Hannes Wallnöfer 1998-2000
|
// Copyright (c) Hannes Wallnöfer 1998-2000
|
||||||
|
|
||||||
|
|
||||||
package helma.scripting.fesi.extensions;
|
package helma.framework.extensions;
|
||||||
|
|
||||||
import javax.mail.*;
|
import javax.mail.*;
|
||||||
import javax.mail.internet.*;
|
import javax.mail.internet.*;
|
||||||
|
@ -10,18 +10,19 @@ import javax.activation.*;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import helma.framework.core.*;
|
import helma.framework.core.*;
|
||||||
import helma.util.*;
|
import helma.objectmodel.*;
|
||||||
import FESI.Data.*;
|
import FESI.Data.*;
|
||||||
import FESI.Interpreter.*;
|
import FESI.Interpreter.*;
|
||||||
import FESI.Exceptions.*;
|
import FESI.Exceptions.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A JavaScript wrapper around a JavaMail message class to send
|
* A JavaScript wrapper around a JavaMail message class to send
|
||||||
* mail via SMTP from Helma
|
* mail via SMTP from HOP
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class ESMail extends ESObject implements Serializable {
|
public class ESMail extends ESObject implements Serializable {
|
||||||
|
|
||||||
|
INode node;
|
||||||
MailExtension mailx;
|
MailExtension mailx;
|
||||||
Properties mprops;
|
Properties mprops;
|
||||||
MimeMessage message;
|
MimeMessage message;
|
||||||
|
@ -56,7 +57,7 @@ public class ESMail extends ESObject implements Serializable {
|
||||||
Session session = Session.getDefaultInstance(props, null);
|
Session session = Session.getDefaultInstance(props, null);
|
||||||
message = new MimeMessage (session);
|
message = new MimeMessage (session);
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
this.evaluator.reval.app.logEvent ("Error in mail constructor: "+t);
|
IServer.getLogger().log ("caught in mail constructor: "+t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,16 +94,20 @@ public class ESMail extends ESObject implements Serializable {
|
||||||
multipart = new MimeMultipart ();
|
multipart = new MimeMultipart ();
|
||||||
}
|
}
|
||||||
for (int i=0; i<val.length; i++) {
|
for (int i=0; i<val.length; i++) {
|
||||||
// FIXME: addPart is broken.
|
INode node = getNode (val[i]);
|
||||||
MimeBodyPart part = new MimeBodyPart ();
|
if (node != null) {
|
||||||
Object obj = val[i].toJavaObject ();
|
BodyPart part = new MimeBodyPart ();
|
||||||
if (obj instanceof String) {
|
IServer.getLogger().log ("Adding MimePart: "+node.getContentType ());
|
||||||
part.setContent (obj.toString (), "text/plain");
|
NodeDataSource nds=new NodeDataSource (node);
|
||||||
} else if (obj instanceof File) {
|
part.setDataHandler(new DataHandler(nds));
|
||||||
FileDataSource source = new FileDataSource ((File) obj);
|
// part.setFileName(filename);
|
||||||
part.setDataHandler (new DataHandler (source));
|
// part.setDataHandler (new javax.activation.DataHandler (node.getContent(), node.getContentType ()));
|
||||||
|
multipart.addBodyPart (part);
|
||||||
|
} else if (val[i] != null) {
|
||||||
|
BodyPart part = new MimeBodyPart ();
|
||||||
|
part.setContent (val[i].toString (), "text/plain");
|
||||||
|
multipart.addBodyPart (part);
|
||||||
}
|
}
|
||||||
multipart.addBodyPart (part);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,6 +185,20 @@ public class ESMail extends ESObject implements Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private final INode getNode (Object obj) {
|
||||||
|
if (obj == null)
|
||||||
|
return null;
|
||||||
|
if (obj instanceof ESNode)
|
||||||
|
return ((ESNode) obj).getNode ();
|
||||||
|
if (obj instanceof ESWrapper) {
|
||||||
|
Object n = ((ESWrapper) obj).getJavaObject();
|
||||||
|
if (n instanceof INode)
|
||||||
|
return (INode) n;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// FtpExtension.java
|
// FtpExtension.java
|
||||||
// Copyright (c) Hannes Wallnöfer 1998-2000
|
// Copyright (c) Hannes Wallnöfer 1998-2000
|
||||||
|
|
||||||
package helma.scripting.fesi.extensions;
|
package helma.framework.extensions;
|
||||||
|
|
||||||
import helma.objectmodel.*;
|
import helma.objectmodel.*;
|
||||||
import FESI.Parser.*;
|
import FESI.Parser.*;
|
||||||
|
@ -80,8 +80,8 @@ class ESFtpClient extends ESObject {
|
||||||
try {
|
try {
|
||||||
ftpclient = new FTPClient ();
|
ftpclient = new FTPClient ();
|
||||||
ftpclient.connect (server);
|
ftpclient.connect (server);
|
||||||
boolean b = ftpclient.login (arguments[0].toString(), arguments[1].toString());
|
ftpclient.login (arguments[0].toString(), arguments[1].toString());
|
||||||
return ESBoolean.makeBoolean (b);
|
return ESBoolean.makeBoolean (true);
|
||||||
} catch (Exception x) {
|
} catch (Exception x) {
|
||||||
return ESBoolean.makeBoolean (false);
|
return ESBoolean.makeBoolean (false);
|
||||||
} catch (NoClassDefFoundError x) {
|
} catch (NoClassDefFoundError x) {
|
|
@ -1,7 +1,7 @@
|
||||||
// ImageExtension.java
|
// ImageExtension.java
|
||||||
// Copyright (c) Hannes Wallnöfer 1998-2000
|
// Copyright (c) Hannes Wallnöfer 1998-2000
|
||||||
|
|
||||||
package helma.scripting.fesi.extensions;
|
package helma.framework.extensions;
|
||||||
|
|
||||||
import helma.objectmodel.*;
|
import helma.objectmodel.*;
|
||||||
import helma.util.*;
|
import helma.util.*;
|
||||||
|
@ -13,7 +13,6 @@ import FESI.Extensions.*;
|
||||||
import FESI.Data.*;
|
import FESI.Data.*;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.awt.image.*;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.rmi.Naming;
|
import java.rmi.Naming;
|
||||||
|
|
||||||
|
@ -79,12 +78,7 @@ public class ImageExtension extends Extension {
|
||||||
(Object) imggen.createPaintableImage (imgurl);
|
(Object) imggen.createPaintableImage (imgurl);
|
||||||
}
|
}
|
||||||
} else if (arguments.length == 2) {
|
} else if (arguments.length == 2) {
|
||||||
if (arguments[0] instanceof ESWrapper && arguments[1] instanceof ESWrapper) {
|
if (arguments[0].isNumberValue () && arguments[1].isNumberValue ()) {
|
||||||
// create a new image from an existing one and an image filter
|
|
||||||
Object image = arguments[0].toJavaObject ();
|
|
||||||
Object filter = arguments[1].toJavaObject ();
|
|
||||||
img = imggen.createPaintableImage ((ImageWrapper) image, (ImageFilter) filter);
|
|
||||||
} else if (arguments[0].isNumberValue () && arguments[1].isNumberValue ()) {
|
|
||||||
img = remote ?
|
img = remote ?
|
||||||
(Object) rgen.createPaintableImage (arguments[0].toInt32(), arguments[1].toInt32()) :
|
(Object) rgen.createPaintableImage (arguments[0].toInt32(), arguments[1].toInt32()) :
|
||||||
(Object) imggen.createPaintableImage (arguments[0].toInt32(), arguments[1].toInt32());
|
(Object) imggen.createPaintableImage (arguments[0].toInt32(), arguments[1].toInt32());
|
|
@ -1,8 +1,9 @@
|
||||||
// MailExtension.java
|
// MailExtension.java
|
||||||
// Copyright (c) Hannes Wallnöfer 1998-2000
|
// Copyright (c) Hannes Wallnöfer 1998-2000
|
||||||
|
|
||||||
package helma.scripting.fesi.extensions;
|
package helma.framework.extensions;
|
||||||
|
|
||||||
|
import helma.objectmodel.*;
|
||||||
import helma.util.*;
|
import helma.util.*;
|
||||||
|
|
||||||
import FESI.Interpreter.*;
|
import FESI.Interpreter.*;
|
||||||
|
@ -242,7 +243,7 @@ public class MailExtension extends Extension {
|
||||||
try {
|
try {
|
||||||
mail.send ();
|
mail.send ();
|
||||||
} catch (Exception x) {
|
} catch (Exception x) {
|
||||||
this.evaluator.reval.app.logEvent ("Error sending mail: "+x);
|
IServer.getLogger().log ("Error sending mail: "+x);
|
||||||
mail.setStatus (ESMail.SEND);
|
mail.setStatus (ESMail.SEND);
|
||||||
return ESBoolean.makeBoolean(false);
|
return ESBoolean.makeBoolean(false);
|
||||||
}
|
}
|
47
src/helma/image/ActivatedImageWrapper.java
Normal file
47
src/helma/image/ActivatedImageWrapper.java
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
// ActivatedImageWrapper.java
|
||||||
|
// Copyright (c) Hannes Wallnöfer 1999-2000
|
||||||
|
|
||||||
|
package helma.image;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.image.*;
|
||||||
|
import com.activated.jimi.*;
|
||||||
|
import com.activated.jimi.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A wrapper for an image that uses the Activated version of JIMI.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class ActivatedImageWrapper extends ImageWrapper {
|
||||||
|
|
||||||
|
public ActivatedImageWrapper (Image img, Graphics g, int width, int height,
|
||||||
|
ImageGenerator imggen) throws ClassNotFoundException {
|
||||||
|
super (img, g, width, height, imggen);
|
||||||
|
Class.forName ("com.activated.jimi.Jimi");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void reduceColors (int colors) {
|
||||||
|
try {
|
||||||
|
ColorReducer redux = new ColorReducer (colors, true);
|
||||||
|
img = redux.getColorReducedImage (img);
|
||||||
|
} catch (Exception x) {
|
||||||
|
throw new RuntimeException (x.getMessage ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void saveAs (String filename) {
|
||||||
|
try {
|
||||||
|
Jimi.putImage (img, filename);
|
||||||
|
} catch (JimiException x) {
|
||||||
|
throw new RuntimeException (x.getMessage ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,6 @@ public interface IRemoteImage extends Remote {
|
||||||
public void setFont (String name, int style, int size) throws RemoteException;
|
public void setFont (String name, int style, int size) throws RemoteException;
|
||||||
public void setColor (int color) throws RemoteException;
|
public void setColor (int color) throws RemoteException;
|
||||||
public void setColor (int r, int g, int b) throws RemoteException;
|
public void setColor (int r, int g, int b) throws RemoteException;
|
||||||
|
|
||||||
public void reduceColors (int colors) throws RemoteException;
|
public void reduceColors (int colors) throws RemoteException;
|
||||||
|
|
||||||
public void drawString (String str, int x, int y) throws RemoteException;
|
public void drawString (String str, int x, int y) throws RemoteException;
|
||||||
|
@ -30,5 +29,9 @@ public interface IRemoteImage extends Remote {
|
||||||
public void resize (int w, int h) throws RemoteException;
|
public void resize (int w, int h) throws RemoteException;
|
||||||
|
|
||||||
public void saveAs (String filename) throws RemoteException;
|
public void saveAs (String filename) throws RemoteException;
|
||||||
|
public void readFrom (String filename) throws RemoteException;
|
||||||
|
|
||||||
|
public byte[] getBytes (String type) throws RemoteException;
|
||||||
|
public void setBytes (byte[] bytes, String type) throws RemoteException;
|
||||||
|
|
||||||
}
|
}
|
|
@ -4,7 +4,6 @@
|
||||||
package helma.image;
|
package helma.image;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.image.*;
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -38,10 +37,14 @@ public class ImageGenerator extends Window {
|
||||||
Graphics g = img.getGraphics ();
|
Graphics g = img.getGraphics ();
|
||||||
ImageWrapper rimg = null;
|
ImageWrapper rimg = null;
|
||||||
try {
|
try {
|
||||||
rimg = new SunImageWrapper (img, g, w, h, this);
|
try {
|
||||||
} catch (Exception x) {
|
rimg = new ActivatedImageWrapper (img, g, w, h, this);
|
||||||
System.err.println ("Can't create image: "+x);
|
} catch (NoClassDefFoundError notfound) {
|
||||||
}
|
rimg = new SunImageWrapper (img, g, w, h, this);
|
||||||
|
} catch (ClassNotFoundException notfound) {
|
||||||
|
rimg = new SunImageWrapper (img, g, w, h, this);
|
||||||
|
}
|
||||||
|
} catch (Exception x) {}
|
||||||
return rimg;
|
return rimg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,10 +60,14 @@ public class ImageGenerator extends Window {
|
||||||
Image img = createImage (w, h);
|
Image img = createImage (w, h);
|
||||||
Graphics g = img.getGraphics ();
|
Graphics g = img.getGraphics ();
|
||||||
g.drawImage (img1, 0, 0, null);
|
g.drawImage (img1, 0, 0, null);
|
||||||
rimg = new SunImageWrapper (img, g, w, h, this);
|
try {
|
||||||
} catch (Exception x) {
|
rimg = new ActivatedImageWrapper (img, g, w, h, this);
|
||||||
System.err.println ("Can't create image: "+x);
|
} catch (ClassNotFoundException notfound) {
|
||||||
}
|
rimg = new SunImageWrapper (img, g, w, h, this);
|
||||||
|
} catch (NoClassDefFoundError notfound) {
|
||||||
|
rimg = new SunImageWrapper (img, g, w, h, this);
|
||||||
|
}
|
||||||
|
} catch (Exception x) {}
|
||||||
return rimg;
|
return rimg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,10 +80,14 @@ public class ImageGenerator extends Window {
|
||||||
tracker.waitForAll ();
|
tracker.waitForAll ();
|
||||||
int w = img.getWidth (null);
|
int w = img.getWidth (null);
|
||||||
int h = img.getHeight (null);
|
int h = img.getHeight (null);
|
||||||
rimg = new SunImageWrapper (img, null, w, h, this);
|
try {
|
||||||
} catch (Exception x) {
|
rimg = new ActivatedImageWrapper (img, null, w, h, this);
|
||||||
System.err.println ("Can't create image: "+x);
|
} catch (ClassNotFoundException notfound) {
|
||||||
}
|
rimg = new SunImageWrapper (img, null, w, h, this);
|
||||||
|
} catch (NoClassDefFoundError notfound) {
|
||||||
|
rimg = new SunImageWrapper (img, null, w, h, this);
|
||||||
|
}
|
||||||
|
} catch (Exception x) {}
|
||||||
return rimg;
|
return rimg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,7 +97,7 @@ public class ImageGenerator extends Window {
|
||||||
MediaTracker tracker = new MediaTracker (this);
|
MediaTracker tracker = new MediaTracker (this);
|
||||||
try {
|
try {
|
||||||
URL url = new URL (urlstring);
|
URL url = new URL (urlstring);
|
||||||
Image img1 = Toolkit.getDefaultToolkit ().createImage (url);
|
Image img1 = Toolkit.getDefaultToolkit ().getImage (url);
|
||||||
tracker.addImage (img1, 0);
|
tracker.addImage (img1, 0);
|
||||||
tracker.waitForAll ();
|
tracker.waitForAll ();
|
||||||
int w = img1.getWidth (null);
|
int w = img1.getWidth (null);
|
||||||
|
@ -94,44 +105,27 @@ public class ImageGenerator extends Window {
|
||||||
Image img = createImage (w, h);
|
Image img = createImage (w, h);
|
||||||
Graphics g = img.getGraphics ();
|
Graphics g = img.getGraphics ();
|
||||||
g.drawImage (img1, 0, 0, null);
|
g.drawImage (img1, 0, 0, null);
|
||||||
rimg = new SunImageWrapper (img, g, w, h, this);
|
try {
|
||||||
|
rimg = new ActivatedImageWrapper (img, g, w, h, this);
|
||||||
|
} catch (ClassNotFoundException notfound) {
|
||||||
|
rimg = new SunImageWrapper (img, g, w, h, this);
|
||||||
|
} catch (NoClassDefFoundError notfound) {
|
||||||
|
rimg = new SunImageWrapper (img, g, w, h, this);
|
||||||
|
}
|
||||||
} catch (Exception x) {
|
} catch (Exception x) {
|
||||||
System.err.println ("Can't create image: "+x);
|
|
||||||
x.printStackTrace ();
|
x.printStackTrace ();
|
||||||
}
|
}
|
||||||
return rimg;
|
return rimg;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ImageWrapper createPaintableImage (ImageWrapper iw, ImageFilter filter) {
|
|
||||||
ImageWrapper rimg = null;
|
|
||||||
MediaTracker tracker = new MediaTracker (this);
|
|
||||||
try {
|
|
||||||
FilteredImageSource fis = new FilteredImageSource (iw.getSource(), filter);
|
|
||||||
Image img1 = createImage (fis);
|
|
||||||
tracker.addImage (img1, 0);
|
|
||||||
tracker.waitForAll ();
|
|
||||||
int w = img1.getWidth (null);
|
|
||||||
int h = img1.getHeight (null);
|
|
||||||
Image img = createImage (w, h);
|
|
||||||
Graphics g = img.getGraphics ();
|
|
||||||
g.drawImage (img1, 0, 0, null);
|
|
||||||
rimg = new SunImageWrapper (img, g, w, h, this);
|
|
||||||
} catch (Exception x) {
|
|
||||||
System.err.println ("Can't create image: "+x);
|
|
||||||
}
|
|
||||||
return rimg;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public Image createImage (String filename) {
|
public Image createImage (String filename) {
|
||||||
Image img = null;
|
Image img = null;
|
||||||
MediaTracker tracker = new MediaTracker (this);
|
MediaTracker tracker = new MediaTracker (this);
|
||||||
try {
|
try {
|
||||||
img = Toolkit.getDefaultToolkit ().createImage (filename);
|
img = Toolkit.getDefaultToolkit ().getImage (filename);
|
||||||
tracker.addImage (img, 0);
|
tracker.addImage (img, 0);
|
||||||
tracker.waitForAll ();
|
tracker.waitForAll ();
|
||||||
} catch (Exception x) {
|
} catch (Exception x) {
|
||||||
System.err.println ("Can't create image: "+x);
|
|
||||||
x.printStackTrace ();
|
x.printStackTrace ();
|
||||||
}
|
}
|
||||||
return img;
|
return img;
|
||||||
|
|
|
@ -102,11 +102,16 @@ public abstract class ImageWrapper {
|
||||||
|
|
||||||
public abstract void saveAs (String filename);
|
public abstract void saveAs (String filename);
|
||||||
|
|
||||||
/**
|
public void readFrom (String filename) {
|
||||||
* Get ImageProducer of the wrapped image
|
throw new RuntimeException ("Image.readFrom() is currently not implemented.");
|
||||||
*/
|
}
|
||||||
public ImageProducer getSource () {
|
|
||||||
return img.getSource ();
|
public byte[] getBytes (String type) {
|
||||||
|
throw new RuntimeException ("Image.getBytes() is currently not implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBytes (byte[] bytes, String type) {
|
||||||
|
throw new RuntimeException ("Image.setBytes() is currently not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void fillString (String str) {
|
public void fillString (String str) {
|
||||||
|
|
|
@ -77,6 +77,18 @@ public class RemoteImage extends UnicastRemoteObject implements IRemoteImage {
|
||||||
wrapped.saveAs (filename);
|
wrapped.saveAs (filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void readFrom (String filename) {
|
||||||
|
wrapped.readFrom (filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getBytes (String type) {
|
||||||
|
return wrapped.getBytes (type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBytes (byte[] bytes, String type) {
|
||||||
|
wrapped.setBytes (bytes, type);
|
||||||
|
}
|
||||||
|
|
||||||
public void fillString (String str) {
|
public void fillString (String str) {
|
||||||
wrapped.fillString (str);
|
wrapped.fillString (str);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,395 +0,0 @@
|
||||||
// Server.java
|
|
||||||
// Copyright (c) Hannes Wallnöfer 1998-2000
|
|
||||||
|
|
||||||
package helma.main;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.rmi.*;
|
|
||||||
import java.rmi.server.*;
|
|
||||||
import java.rmi.registry.*;
|
|
||||||
import java.net.*;
|
|
||||||
import java.util.*;
|
|
||||||
// import helma.objectmodel.*;
|
|
||||||
import helma.objectmodel.db.DbSource;
|
|
||||||
import helma.framework.*;
|
|
||||||
import helma.framework.core.*;
|
|
||||||
import helma.xmlrpc.*;
|
|
||||||
import helma.util.*;
|
|
||||||
import com.sleepycat.db.*;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helma server main class.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class Server implements IPathElement, Runnable {
|
|
||||||
|
|
||||||
public static final String version = "1.2pre3 2002/05/15";
|
|
||||||
public static final long starttime = System.currentTimeMillis();
|
|
||||||
|
|
||||||
public static boolean useTransactions = true;
|
|
||||||
public static boolean paranoid;
|
|
||||||
public static String dbFilename = "hop.db";
|
|
||||||
|
|
||||||
private ApplicationManager appManager;
|
|
||||||
|
|
||||||
private Thread mainThread;
|
|
||||||
|
|
||||||
static String propfile;
|
|
||||||
static String dbPropfile = "db.properties";
|
|
||||||
static String appsPropfile;
|
|
||||||
static SystemProperties appsProps;
|
|
||||||
static SystemProperties dbProps;
|
|
||||||
static SystemProperties sysProps;
|
|
||||||
static int port = 5055;
|
|
||||||
static int webport = 0;
|
|
||||||
|
|
||||||
Acme.Serve.Serve websrv;
|
|
||||||
|
|
||||||
static Hashtable dbSources;
|
|
||||||
|
|
||||||
private static Server server;
|
|
||||||
|
|
||||||
protected static File hopHome = null;
|
|
||||||
|
|
||||||
private static Logger logger;
|
|
||||||
|
|
||||||
protected static WebServer xmlrpc;
|
|
||||||
|
|
||||||
|
|
||||||
public static void main (String args[]) throws IOException {
|
|
||||||
|
|
||||||
// check if we are running on a Java 2 VM - otherwise exit with an error message
|
|
||||||
String jversion = System.getProperty ("java.version");
|
|
||||||
if (jversion == null || jversion.startsWith ("1.1") || jversion.startsWith ("1.0")) {
|
|
||||||
System.err.println ("This version of Helma requires Java 1.2 or greater.");
|
|
||||||
if (jversion == null) // don't think this will ever happen, but you never know
|
|
||||||
System.err.println ("Your Java Runtime did not provide a version number. Please update to a more recent version.");
|
|
||||||
else
|
|
||||||
System.err.println ("Your Java Runtime is version "+jversion+". Please update to a more recent version.");
|
|
||||||
System.exit (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
String homeDir = null;
|
|
||||||
|
|
||||||
boolean usageError = false;
|
|
||||||
|
|
||||||
useTransactions = true;
|
|
||||||
|
|
||||||
for (int i=0; i<args.length; i++) {
|
|
||||||
if (args[i].equals ("-h") && i+1<args.length)
|
|
||||||
homeDir = args[++i];
|
|
||||||
else if (args[i].equals ("-f") && i+1<args.length)
|
|
||||||
propfile = args[++i];
|
|
||||||
else if (args[i].equals ("-t"))
|
|
||||||
useTransactions = false;
|
|
||||||
else if (args[i].equals ("-p") && i+1<args.length) {
|
|
||||||
try {
|
|
||||||
port = Integer.parseInt (args[++i]);
|
|
||||||
} catch (Exception portx) {
|
|
||||||
usageError = true;
|
|
||||||
}
|
|
||||||
} else if (args[i].equals ("-w") && i+1<args.length) {
|
|
||||||
try {
|
|
||||||
webport = Integer.parseInt (args[++i]);
|
|
||||||
} catch (Exception portx) {
|
|
||||||
usageError = true;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
usageError = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (usageError ) {
|
|
||||||
System.out.println ("usage: java helma.objectmodel.db.Server [-h dir] [-f file] [-p port] [-w port] [-t]");
|
|
||||||
System.out.println (" -h dir Specify hop home directory");
|
|
||||||
System.out.println (" -f file Specify server.properties file");
|
|
||||||
System.out.println (" -p port Specify TCP port number");
|
|
||||||
System.out.println (" -w port Start embedded Web server on that port");
|
|
||||||
System.out.println (" -t Disable Berkeley DB Transactions");
|
|
||||||
getLogger().log ("Usage Error - exiting");
|
|
||||||
System.exit (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
server = new Server (homeDir);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Server (String home) {
|
|
||||||
|
|
||||||
String homeDir = home;
|
|
||||||
|
|
||||||
// get main property file from home dir or vice versa, depending on what we have.
|
|
||||||
// get property file from hopHome
|
|
||||||
if (propfile == null) {
|
|
||||||
if (homeDir != null)
|
|
||||||
propfile = new File (homeDir, "server.properties").getAbsolutePath ();
|
|
||||||
else
|
|
||||||
propfile = new File ("server.properties").getAbsolutePath ();
|
|
||||||
}
|
|
||||||
|
|
||||||
sysProps = new SystemProperties (propfile);
|
|
||||||
// get hopHome from property file
|
|
||||||
if (homeDir == null)
|
|
||||||
homeDir = sysProps.getProperty ("hophome");
|
|
||||||
if (homeDir == null)
|
|
||||||
homeDir = new File (propfile).getParent ();
|
|
||||||
|
|
||||||
// create hopHome File object
|
|
||||||
hopHome = new File (homeDir);
|
|
||||||
|
|
||||||
// from now on it's safe to call getLogger()
|
|
||||||
|
|
||||||
getLogger().log ("Starting Helma "+version);
|
|
||||||
|
|
||||||
getLogger().log ("propfile = "+propfile);
|
|
||||||
getLogger().log ("hopHome = "+hopHome);
|
|
||||||
|
|
||||||
|
|
||||||
File helper = new File (hopHome, "db.properties");
|
|
||||||
dbPropfile = helper.getAbsolutePath ();
|
|
||||||
dbProps = new SystemProperties (dbPropfile);
|
|
||||||
DbSource.setDefaultProps (dbProps);
|
|
||||||
getLogger().log ("dbPropfile = "+dbPropfile);
|
|
||||||
|
|
||||||
appsPropfile = sysProps.getProperty ("appsPropFile");
|
|
||||||
if (appsPropfile != null && !"".equals (appsPropfile.trim()))
|
|
||||||
helper = new File (appsPropfile);
|
|
||||||
else
|
|
||||||
helper = new File (hopHome, "apps.properties");
|
|
||||||
appsPropfile = helper.getAbsolutePath ();
|
|
||||||
getLogger().log ("appsPropfile = "+appsPropfile);
|
|
||||||
|
|
||||||
paranoid = "true".equalsIgnoreCase (sysProps.getProperty ("paranoid"));
|
|
||||||
|
|
||||||
String language = sysProps.getProperty ("language");
|
|
||||||
String country = sysProps.getProperty ("country");
|
|
||||||
String timezone = sysProps.getProperty ("timezone");
|
|
||||||
|
|
||||||
if (language != null && country != null)
|
|
||||||
Locale.setDefault (new Locale (language, country));
|
|
||||||
if (timezone != null)
|
|
||||||
TimeZone.setDefault (TimeZone.getTimeZone (timezone));
|
|
||||||
|
|
||||||
getLogger().log ("Locale = "+Locale.getDefault());
|
|
||||||
getLogger().log ("TimeZone = "+TimeZone.getDefault().getDisplayName (Locale.getDefault ()));
|
|
||||||
|
|
||||||
dbSources = new Hashtable ();
|
|
||||||
|
|
||||||
try {
|
|
||||||
checkRunning (); // check if a server is already running with this db
|
|
||||||
} catch (Exception running) {
|
|
||||||
System.out.println (running.getMessage ());
|
|
||||||
System.exit (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// nmgr = new NodeManager (this, sysProps);
|
|
||||||
|
|
||||||
// Start running, finishing setup and then entering a loop to check changes
|
|
||||||
// in the apps.properties file.
|
|
||||||
mainThread = new Thread (this);
|
|
||||||
mainThread.start ();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The main method of the Server. Basically, we set up Applications and than
|
|
||||||
* periodically check for changes in the apps.properties file, shutting down
|
|
||||||
* apps or starting new ones.
|
|
||||||
*/
|
|
||||||
public void run () {
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
// start embedded web server if port is specified
|
|
||||||
if (webport > 0) {
|
|
||||||
websrv = new Acme.Serve.Serve (webport, sysProps);
|
|
||||||
}
|
|
||||||
|
|
||||||
String xmlparser = sysProps.getProperty ("xmlparser");
|
|
||||||
if (xmlparser != null)
|
|
||||||
XmlRpc.setDriver (xmlparser);
|
|
||||||
// XmlRpc.setDebug (true);
|
|
||||||
xmlrpc = new WebServer (port+1);
|
|
||||||
if (paranoid) {
|
|
||||||
xmlrpc.setParanoid (true);
|
|
||||||
String xallow = sysProps.getProperty ("allowXmlRpc");
|
|
||||||
if (xallow != null) {
|
|
||||||
StringTokenizer st = new StringTokenizer (xallow, " ,;");
|
|
||||||
while (st.hasMoreTokens ())
|
|
||||||
xmlrpc.acceptClient (st.nextToken ());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
getLogger().log ("Starting XML-RPC server on port "+(port+1));
|
|
||||||
|
|
||||||
// the following seems not to be necessary after all ...
|
|
||||||
// System.setSecurityManager(new RMISecurityManager());
|
|
||||||
if (paranoid) {
|
|
||||||
HopSocketFactory factory = new HopSocketFactory ();
|
|
||||||
String rallow = sysProps.getProperty ("allowWeb");
|
|
||||||
if (rallow != null) {
|
|
||||||
StringTokenizer st = new StringTokenizer (rallow, " ,;");
|
|
||||||
while (st.hasMoreTokens ())
|
|
||||||
factory.addAddress (st.nextToken ());
|
|
||||||
}
|
|
||||||
RMISocketFactory.setSocketFactory (factory);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (websrv == null) {
|
|
||||||
getLogger().log ("Starting server on port "+port);
|
|
||||||
LocateRegistry.createRegistry (port);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// start application framework
|
|
||||||
appsProps = new SystemProperties (appsPropfile);
|
|
||||||
appManager = new ApplicationManager (port, hopHome, appsProps, this);
|
|
||||||
|
|
||||||
|
|
||||||
} catch (Exception gx) {
|
|
||||||
getLogger().log ("Error initializing embedded database: "+gx);
|
|
||||||
gx.printStackTrace ();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// start applications
|
|
||||||
appManager.startAll ();
|
|
||||||
|
|
||||||
// start embedded web server
|
|
||||||
if (websrv != null) {
|
|
||||||
Thread webthread = new Thread (websrv, "WebServer");
|
|
||||||
webthread.start ();
|
|
||||||
}
|
|
||||||
|
|
||||||
int count = 0;
|
|
||||||
while (Thread.currentThread () == mainThread) {
|
|
||||||
try {
|
|
||||||
mainThread.sleep (3000l);
|
|
||||||
} catch (InterruptedException ie) {}
|
|
||||||
try {
|
|
||||||
appManager.checkForChanges ();
|
|
||||||
} catch (Exception x) {
|
|
||||||
getLogger().log ("Caught in app manager loop: "+x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get an Iterator over the applications currently running on this Server.
|
|
||||||
*/
|
|
||||||
public Object[] getApplications () {
|
|
||||||
return appManager.getApplications ();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get an Application by name
|
|
||||||
*/
|
|
||||||
public Application getApplication(String name) {
|
|
||||||
return appManager.getApplication(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a logger to use for output in this server.
|
|
||||||
*/
|
|
||||||
protected static Logger getLogger () {
|
|
||||||
if (logger == null) {
|
|
||||||
String logDir = sysProps.getProperty ("logdir");
|
|
||||||
if (logDir == null || "console".equalsIgnoreCase (logDir)) {
|
|
||||||
logger = new Logger (System.out);
|
|
||||||
} else {
|
|
||||||
File helper = new File (logDir);
|
|
||||||
if (hopHome != null && !helper.isAbsolute ())
|
|
||||||
helper = new File (hopHome, logDir);
|
|
||||||
logDir = helper.getAbsolutePath ();
|
|
||||||
logger = Logger.getLogger (logDir, "hop");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the Home directory of this server.
|
|
||||||
*/
|
|
||||||
public static File getHopHome () {
|
|
||||||
return hopHome;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the main Server
|
|
||||||
*/
|
|
||||||
public static Server getServer() {
|
|
||||||
return server;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the Server's XML-RPC web server.
|
|
||||||
*/
|
|
||||||
public static WebServer getXmlRpcServer() {
|
|
||||||
return xmlrpc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A primitive method to check whether a server is already running on our port.
|
|
||||||
*/
|
|
||||||
private void checkRunning () throws Exception {
|
|
||||||
try {
|
|
||||||
java.net.Socket socket = new java.net.Socket ("localhost", port);
|
|
||||||
} catch (Exception x) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// if we got so far, another server is already running on this port and db
|
|
||||||
throw new Exception ("Error: Server already running on this port");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getProperty( String key ) {
|
|
||||||
return (String)sysProps.get(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SystemProperties getProperties() {
|
|
||||||
return sysProps;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static File getAppsHome() {
|
|
||||||
String appHome = sysProps.getProperty ("appHome");
|
|
||||||
if (appHome != null && !"".equals (appHome.trim()))
|
|
||||||
return new File (appHome);
|
|
||||||
else
|
|
||||||
return new File (hopHome, "apps");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void startApplication(String name) {
|
|
||||||
appManager.start (name);
|
|
||||||
appManager.register (name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void stopApplication(String name) {
|
|
||||||
appManager.stop (name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* method from helma.framework.IPathElement
|
|
||||||
*/
|
|
||||||
public String getElementName() {
|
|
||||||
return "root";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* method from helma.framework.IPathElement,
|
|
||||||
* returning active applications
|
|
||||||
*/
|
|
||||||
public IPathElement getChildElement(String name) {
|
|
||||||
return appManager.getApplication(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* method from helma.framework.IPathElement
|
|
||||||
*/
|
|
||||||
public IPathElement getParentElement() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* method from helma.framework.IPathElement
|
|
||||||
*/
|
|
||||||
public String getPrototype() {
|
|
||||||
return "root";
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -3,7 +3,7 @@
|
||||||
// (c) COPYRIGHT MIT, INRIA and Keio, 1999
|
// (c) COPYRIGHT MIT, INRIA and Keio, 1999
|
||||||
// Please first read the full copyright statement in file COPYRIGHT.html
|
// Please first read the full copyright statement in file COPYRIGHT.html
|
||||||
|
|
||||||
package helma.util.mime;
|
package helma.mime;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.io.*;
|
import java.io.*;
|
|
@ -3,7 +3,7 @@
|
||||||
// (c) COPYRIGHT MIT and INRIA, 1996.
|
// (c) COPYRIGHT MIT and INRIA, 1996.
|
||||||
// Please first read the full copyright statement in file COPYRIGHT.html
|
// Please first read the full copyright statement in file COPYRIGHT.html
|
||||||
|
|
||||||
package helma.util.mime;
|
package helma.mime;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
// (c) COPYRIGHT MIT and INRIA, 1996.
|
// (c) COPYRIGHT MIT and INRIA, 1996.
|
||||||
// Please first read the full copyright statement in file COPYRIGHT.html
|
// Please first read the full copyright statement in file COPYRIGHT.html
|
||||||
|
|
||||||
package helma.util.mime;
|
package helma.mime;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
|
@ -3,7 +3,7 @@
|
||||||
// (c) COPYRIGHT MIT and INRIA, 1996.
|
// (c) COPYRIGHT MIT and INRIA, 1996.
|
||||||
// Please first read the full copyright statement in file COPYRIGHT.html
|
// Please first read the full copyright statement in file COPYRIGHT.html
|
||||||
|
|
||||||
package helma.util.mime;
|
package helma.mime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Mime header factory, that will build instances of the MimeHeaders class
|
* A Mime header factory, that will build instances of the MimeHeaders class
|
|
@ -3,7 +3,7 @@
|
||||||
// (c) COPYRIGHT MIT and INRIA, 1996.
|
// (c) COPYRIGHT MIT and INRIA, 1996.
|
||||||
// Please first read the full copyright statement in file COPYRIGHT.html
|
// Please first read the full copyright statement in file COPYRIGHT.html
|
||||||
|
|
||||||
package helma.util.mime;
|
package helma.mime;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.io.* ;
|
import java.io.* ;
|
|
@ -3,7 +3,7 @@
|
||||||
// (c) COPYRIGHT MIT and INRIA, 1996.
|
// (c) COPYRIGHT MIT and INRIA, 1996.
|
||||||
// Please first read the full copyright statement in file COPYRIGHT.html
|
// Please first read the full copyright statement in file COPYRIGHT.html
|
||||||
|
|
||||||
package helma.util.mime;
|
package helma.mime;
|
||||||
|
|
||||||
public class MimeParserException extends Exception {
|
public class MimeParserException extends Exception {
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
// (c) COPYRIGHT MIT and INRIA, 1996.
|
// (c) COPYRIGHT MIT and INRIA, 1996.
|
||||||
// Please first read the full copyright statement in file COPYRIGHT.html
|
// Please first read the full copyright statement in file COPYRIGHT.html
|
||||||
|
|
||||||
package helma.util.mime;
|
package helma.mime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is used by the MimeParser, to create new MIME message holders.
|
* This class is used by the MimeParser, to create new MIME message holders.
|
|
@ -3,7 +3,7 @@
|
||||||
// (c) COPYRIGHT MIT and INRIA, 1996.
|
// (c) COPYRIGHT MIT and INRIA, 1996.
|
||||||
// Please first read the full copyright statement in file COPYRIGHT.html
|
// Please first read the full copyright statement in file COPYRIGHT.html
|
||||||
|
|
||||||
package helma.util.mime;
|
package helma.mime;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.io.*;
|
import java.io.*;
|
|
@ -3,7 +3,7 @@
|
||||||
// (c) COPYRIGHT MIT and INRIA, 1996.
|
// (c) COPYRIGHT MIT and INRIA, 1996.
|
||||||
// Please first read the full copyright statement in file COPYRIGHT.html
|
// Please first read the full copyright statement in file COPYRIGHT.html
|
||||||
|
|
||||||
package helma.util.mime;
|
package helma.mime;
|
||||||
|
|
||||||
public class MimeTypeFormatException extends Exception {
|
public class MimeTypeFormatException extends Exception {
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
// (c) COPYRIGHT MIT and INRIA, 1996.
|
// (c) COPYRIGHT MIT and INRIA, 1996.
|
||||||
// Please first read the full copyright statement in file COPYRIGHT.html
|
// Please first read the full copyright statement in file COPYRIGHT.html
|
||||||
|
|
||||||
package helma.util.mime;
|
package helma.mime;
|
||||||
|
|
||||||
import java.io.* ;
|
import java.io.* ;
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
// (c) COPYRIGHT MIT and INRIA, 1998.
|
// (c) COPYRIGHT MIT and INRIA, 1998.
|
||||||
// Please first read the full copyright statement in file COPYRIGHT.html
|
// Please first read the full copyright statement in file COPYRIGHT.html
|
||||||
|
|
||||||
package helma.util.mime;
|
package helma.mime;
|
||||||
|
|
||||||
import java.util.Hashtable;
|
import java.util.Hashtable;
|
||||||
|
|
510
src/helma/objectmodel/DbMapping.java
Normal file
510
src/helma/objectmodel/DbMapping.java
Normal file
|
@ -0,0 +1,510 @@
|
||||||
|
// DbMapping.java
|
||||||
|
// Copyright (c) Hannes Wallnöfer 1998-2000
|
||||||
|
|
||||||
|
package helma.objectmodel;
|
||||||
|
|
||||||
|
import helma.framework.core.Application;
|
||||||
|
import helma.objectmodel.db.WrappedNodeManager;
|
||||||
|
import java.util.*;
|
||||||
|
import java.sql.*;
|
||||||
|
import com.workingdogs.village.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A DbMapping describes how a certain type of Nodes is to mapped to a
|
||||||
|
* relational database table. Basically it consists of a set of JavaScript property-to-
|
||||||
|
* Database row bindings which are represented by instances of the Relation class.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class DbMapping {
|
||||||
|
|
||||||
|
Application app;
|
||||||
|
String typename;
|
||||||
|
|
||||||
|
SystemProperties props;
|
||||||
|
|
||||||
|
DbSource source;
|
||||||
|
String table;
|
||||||
|
|
||||||
|
String[] parent; // list of properties to try for parent
|
||||||
|
Boolean[] anonymous; // are parent relations anonymous or not?
|
||||||
|
DbMapping subnodes;
|
||||||
|
DbMapping properties;
|
||||||
|
private Relation subnodesRel;
|
||||||
|
private Relation propertiesRel;
|
||||||
|
|
||||||
|
// Map of property names to Relations objects
|
||||||
|
public Hashtable prop2db;
|
||||||
|
// Map of db columns to Relations objects
|
||||||
|
public Hashtable db2prop;
|
||||||
|
|
||||||
|
String idField;
|
||||||
|
String nameField;
|
||||||
|
|
||||||
|
// descriptor for key generation method
|
||||||
|
private String idgen;
|
||||||
|
// remember last key generated for this table
|
||||||
|
public long lastID;
|
||||||
|
|
||||||
|
|
||||||
|
Schema schema = null;
|
||||||
|
KeyDef keydef = null;
|
||||||
|
|
||||||
|
private long lastTypeChange;
|
||||||
|
public long lastDataChange;
|
||||||
|
|
||||||
|
public DbMapping () {
|
||||||
|
|
||||||
|
prop2db = new Hashtable ();
|
||||||
|
db2prop = new Hashtable ();
|
||||||
|
|
||||||
|
parent = null;
|
||||||
|
subnodes = null;
|
||||||
|
properties = null;
|
||||||
|
idField = "id";
|
||||||
|
}
|
||||||
|
|
||||||
|
public DbMapping (Application app, String typename, SystemProperties props) {
|
||||||
|
|
||||||
|
this.app = app;
|
||||||
|
this.typename = typename;
|
||||||
|
|
||||||
|
prop2db = new Hashtable ();
|
||||||
|
db2prop = new Hashtable ();
|
||||||
|
|
||||||
|
parent = null;
|
||||||
|
subnodes = null;
|
||||||
|
properties = null;
|
||||||
|
idField = "id";
|
||||||
|
|
||||||
|
this.props = props;
|
||||||
|
read ();
|
||||||
|
|
||||||
|
app.putDbMapping (typename, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the mapping from the Properties. Return true if the properties were changed.
|
||||||
|
* The read is split in two, this method and the rewire method. The reason is that in order
|
||||||
|
* for rewire to work, all other db mappings must have been initialized and registered.
|
||||||
|
*/
|
||||||
|
public synchronized boolean read () {
|
||||||
|
|
||||||
|
long lastmod = props.lastModified ();
|
||||||
|
if (lastmod == lastTypeChange)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
this.table = props.getProperty ("_tablename");
|
||||||
|
this.idgen = props.getProperty ("_idgen");
|
||||||
|
|
||||||
|
String sourceName = props.getProperty ("_datasource");
|
||||||
|
if (sourceName != null)
|
||||||
|
source = (DbSource) IServer.dbSources.get (sourceName.toLowerCase ());
|
||||||
|
|
||||||
|
// id field must not be null, default is "id"
|
||||||
|
idField = props.getProperty ("_id", "id");
|
||||||
|
|
||||||
|
nameField = props.getProperty ("_name");
|
||||||
|
|
||||||
|
lastTypeChange = lastmod;
|
||||||
|
// set the cached schema & keydef to null so it's rebuilt the next time around
|
||||||
|
schema = null;
|
||||||
|
keydef = null;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the second part of the property reading process, called after the first part has been
|
||||||
|
* completed on all other mappings in this application
|
||||||
|
*/
|
||||||
|
public synchronized void rewire () {
|
||||||
|
|
||||||
|
// if (table != null && source != null) {
|
||||||
|
// IServer.getLogger().log ("set data source for "+typename+" to "+source);
|
||||||
|
Hashtable p2d = new Hashtable ();
|
||||||
|
Hashtable d2p = new Hashtable ();
|
||||||
|
|
||||||
|
for (Enumeration e=props.keys(); e.hasMoreElements(); ) {
|
||||||
|
String propName = (String) e.nextElement ();
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (!propName.startsWith ("_") && propName.indexOf (".") < 0) {
|
||||||
|
String dbField = props.getProperty (propName);
|
||||||
|
Relation rel = new Relation (dbField, propName, this, props);
|
||||||
|
p2d.put (propName, rel);
|
||||||
|
if (rel.localField != null)
|
||||||
|
d2p.put (rel.localField, rel);
|
||||||
|
// IServer.getLogger().log ("Mapping "+propName+" -> "+dbField);
|
||||||
|
}
|
||||||
|
} catch (Exception x) {
|
||||||
|
IServer.getLogger ().log ("Error in type.properties: "+x.getMessage ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
prop2db = p2d;
|
||||||
|
db2prop = d2p;
|
||||||
|
|
||||||
|
String ano = props.getProperty ("_anonymous");
|
||||||
|
if (ano != null) {
|
||||||
|
// comma-separated list of true/false values
|
||||||
|
StringTokenizer st = new StringTokenizer (ano, ",; ");
|
||||||
|
anonymous = new Boolean[st.countTokens()];
|
||||||
|
for (int i=0; i<anonymous.length; i++)
|
||||||
|
anonymous[i] = "false".equalsIgnoreCase (st.nextToken().trim()) ? Boolean.FALSE : Boolean.TRUE;
|
||||||
|
} else
|
||||||
|
anonymous = null;
|
||||||
|
|
||||||
|
String parentMapping = props.getProperty ("_parent");
|
||||||
|
if (parentMapping != null) {
|
||||||
|
// comma-separated list of properties to be used as parent
|
||||||
|
StringTokenizer st = new StringTokenizer (parentMapping, ",; ");
|
||||||
|
parent = new String[st.countTokens()];
|
||||||
|
for (int i=0; i<parent.length; i++)
|
||||||
|
parent[i] = st.nextToken().trim();
|
||||||
|
} else
|
||||||
|
parent = null;
|
||||||
|
|
||||||
|
String subnodeMapping = props.getProperty ("_subnodes");
|
||||||
|
if (subnodeMapping != null) {
|
||||||
|
try {
|
||||||
|
subnodesRel = new Relation (subnodeMapping, "_subnodes", this, props);
|
||||||
|
if (subnodesRel.isReference ())
|
||||||
|
subnodes = subnodesRel.other;
|
||||||
|
else
|
||||||
|
subnodes = (DbMapping) app.getDbMapping (subnodeMapping);
|
||||||
|
} catch (Exception x) {
|
||||||
|
IServer.getLogger ().log ("Error in type.properties: "+x.getMessage ());
|
||||||
|
subnodesRel = null;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
subnodesRel = null;
|
||||||
|
|
||||||
|
String propertiesMapping = props.getProperty ("_properties");
|
||||||
|
if (propertiesMapping != null) {
|
||||||
|
try {
|
||||||
|
propertiesRel = new Relation (propertiesMapping, "_properties", this, props);
|
||||||
|
if (propertiesRel.isReference ())
|
||||||
|
properties = propertiesRel.other;
|
||||||
|
else
|
||||||
|
properties = (DbMapping) app.getDbMapping (propertiesMapping);
|
||||||
|
// take over groupby flag from subnodes, if properties are subnodes
|
||||||
|
if (propertiesRel.subnodesAreProperties && subnodesRel != null)
|
||||||
|
propertiesRel.groupby = subnodesRel.groupby;
|
||||||
|
} catch (Exception x) {
|
||||||
|
IServer.getLogger ().log ("Error in type.properties: "+x.getMessage ());
|
||||||
|
propertiesRel = null;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
propertiesRel = null;
|
||||||
|
|
||||||
|
IServer.getLogger().log ("rewiring: "+this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public Connection getConnection () throws ClassNotFoundException, SQLException {
|
||||||
|
if (source == null)
|
||||||
|
throw new SQLException ("Tried to get Connection from non-relational embedded data source.");
|
||||||
|
return source.getConnection ();
|
||||||
|
}
|
||||||
|
|
||||||
|
public DbSource getDbSource () {
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSourceID () {
|
||||||
|
return source == null ? "" : source.url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTableName () {
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Application getApplication () {
|
||||||
|
return app;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAppName () {
|
||||||
|
return app.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTypeName () {
|
||||||
|
return typename;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the primary key column name for objects using this mapping.
|
||||||
|
*/
|
||||||
|
public String getIDField () {
|
||||||
|
return idField;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the column used for (internal) names of objects of this type.
|
||||||
|
*/
|
||||||
|
public String getNameField () {
|
||||||
|
return nameField;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translate a database column name to a JavaScript property name according to this mapping.
|
||||||
|
*/
|
||||||
|
public Relation columnNameToProperty (String columnName) {
|
||||||
|
return (Relation) db2prop.get (columnName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translate a JavaScript property name to a database column name according to this mapping.
|
||||||
|
*/
|
||||||
|
public Relation propertyToColumnName (String propName) {
|
||||||
|
return (Relation) prop2db.get (propName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized String[] getParentPropNames () {
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized Boolean[] getAnonymous () {
|
||||||
|
return anonymous;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DbMapping getSubnodeMapping () {
|
||||||
|
return subnodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSubnodeMapping (DbMapping sm) {
|
||||||
|
subnodes = sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DbMapping getExactPropertyMapping (String propname) {
|
||||||
|
if (propname == null)
|
||||||
|
return null;
|
||||||
|
Relation rel = (Relation) prop2db.get (propname.toLowerCase());
|
||||||
|
return rel != null ? rel.other : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DbMapping getPropertyMapping (String propname) {
|
||||||
|
if (propname == null)
|
||||||
|
return properties;
|
||||||
|
Relation rel = (Relation) prop2db.get (propname.toLowerCase());
|
||||||
|
if (rel != null) {
|
||||||
|
// if this is a virtual node, it doesn't have a dbmapping
|
||||||
|
if (rel.virtual && rel.prototype == null)
|
||||||
|
return null;
|
||||||
|
else
|
||||||
|
return rel.other;
|
||||||
|
}
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPropertyMapping (DbMapping pm) {
|
||||||
|
properties = pm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSubnodeRelation (Relation rel) {
|
||||||
|
subnodesRel = rel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPropertyRelation (Relation rel) {
|
||||||
|
propertiesRel = rel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Relation getSubnodeRelation () {
|
||||||
|
return subnodesRel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Relation getPropertyRelation () {
|
||||||
|
return propertiesRel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Relation getPropertyRelation (String propname) {
|
||||||
|
if (propname == null)
|
||||||
|
return propertiesRel;
|
||||||
|
Relation rel = (Relation) prop2db.get (propname.toLowerCase());
|
||||||
|
return rel != null ? rel : propertiesRel;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getIDgen () {
|
||||||
|
return idgen;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public WrappedNodeManager getWrappedNodeManager () {
|
||||||
|
if (app == null)
|
||||||
|
throw new RuntimeException ("Can't get node manager from internal db mapping");
|
||||||
|
return app.getWrappedNodeManager ();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isRelational () {
|
||||||
|
return source != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a Village Schema object for this DbMapping.
|
||||||
|
*/
|
||||||
|
public synchronized Schema getSchema () throws ClassNotFoundException, SQLException, DataSetException {
|
||||||
|
if (!isRelational ())
|
||||||
|
throw new SQLException ("Can't get Schema for non-relational data mapping");
|
||||||
|
// Use local variable s to avoid synchronization (schema may be nulled elsewhere)
|
||||||
|
Schema s = schema;
|
||||||
|
if (s != null)
|
||||||
|
return s;
|
||||||
|
schema = new Schema ().schema (getConnection (), table, "*");
|
||||||
|
return schema;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a Village Schema object for this DbMapping.
|
||||||
|
*/
|
||||||
|
public synchronized KeyDef getKeyDef () {
|
||||||
|
if (!isRelational ())
|
||||||
|
throw new RuntimeException ("Can't get KeyDef for non-relational data mapping");
|
||||||
|
// Use local variable s to avoid synchronization (keydef may be nulled elsewhere)
|
||||||
|
KeyDef k = keydef;
|
||||||
|
if (k != null)
|
||||||
|
return k;
|
||||||
|
keydef = new KeyDef ().addAttrib (idField);
|
||||||
|
return keydef;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString () {
|
||||||
|
if (app == null)
|
||||||
|
return "[unspecified internal DbMapping]";
|
||||||
|
else
|
||||||
|
return ("["+app.getName()+"."+typename+"]");
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getLastTypeChange () {
|
||||||
|
return lastTypeChange;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
95
src/helma/objectmodel/DbSource.java
Normal file
95
src/helma/objectmodel/DbSource.java
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
// DbSource.java
|
||||||
|
// Copyright (c) Hannes Wallnöfer 1999-2000
|
||||||
|
|
||||||
|
package helma.objectmodel;
|
||||||
|
|
||||||
|
import java.sql.*;
|
||||||
|
import java.util.Hashtable;
|
||||||
|
import helma.objectmodel.db.Transactor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class describes a releational data source (URL, driver, user and password).
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class DbSource {
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
protected String url;
|
||||||
|
private String driver;
|
||||||
|
protected String user;
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
public DbSource (String name) throws ClassNotFoundException {
|
||||||
|
this.name = name;
|
||||||
|
IServer.dbSources.put (name.toLowerCase (), this);
|
||||||
|
url = IServer.dbProps.getProperty (name+".url");
|
||||||
|
driver = IServer.dbProps.getProperty (name+".driver");
|
||||||
|
Class.forName (driver);
|
||||||
|
user = IServer.dbProps.getProperty (name+".user");
|
||||||
|
password = IServer.dbProps.getProperty (name+".password");
|
||||||
|
IServer.getLogger().log ("created db source ["+name+", "+url+", "+driver+", "+user+"]");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Connection getConnection () throws ClassNotFoundException, SQLException {
|
||||||
|
Transactor tx = (Transactor) Thread.currentThread ();
|
||||||
|
Connection con = tx.getConnection (this);
|
||||||
|
if (con == null || con.isClosed ()) {
|
||||||
|
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;
|
||||||
|
IServer.getLogger().log ("Created new Connection to "+url);
|
||||||
|
tx.registerConnection (this, con);
|
||||||
|
}
|
||||||
|
return con;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDriverName () {
|
||||||
|
return driver;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName () {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,6 @@ package helma.objectmodel;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import helma.framework.IPathElement;
|
|
||||||
import helma.objectmodel.db.DbMapping;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface that all Nodes implement. Currently, there are two implementations:
|
* Interface that all Nodes implement. Currently, there are two implementations:
|
||||||
|
@ -14,7 +12,18 @@ import helma.objectmodel.db.DbMapping;
|
||||||
* stored in a database (either the internal Object DB or an external relational DB).
|
* stored in a database (either the internal Object DB or an external relational DB).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public interface INode extends INodeState, IPathElement {
|
public interface INode {
|
||||||
|
|
||||||
|
public final static String webTypes = "image/jpeg, image/gif, image/png";
|
||||||
|
|
||||||
|
public final static int TRANSIENT = -3;
|
||||||
|
public final static int VIRTUAL = -2;
|
||||||
|
public final static int INVALID = -1;
|
||||||
|
public final static int CLEAN = 0;
|
||||||
|
public final static int NEW = 1;
|
||||||
|
public final static int MODIFIED = 2;
|
||||||
|
public final static int DELETED = 3;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -23,10 +32,14 @@ public interface INode extends INodeState, IPathElement {
|
||||||
|
|
||||||
public String getID ();
|
public String getID ();
|
||||||
public String getName ();
|
public String getName ();
|
||||||
|
public String getNameOrID (); // get name or id depending if it's a named or an anonymous node.
|
||||||
public void setDbMapping (DbMapping dbmap);
|
public void setDbMapping (DbMapping dbmap);
|
||||||
public DbMapping getDbMapping ();
|
public DbMapping getDbMapping ();
|
||||||
public int getState ();
|
public int getState ();
|
||||||
public void setState (int s);
|
public void setState (int s);
|
||||||
|
public String getFullName ();
|
||||||
|
public String getFullName (INode root);
|
||||||
|
public INode[] getPath ();
|
||||||
public void setName (String name);
|
public void setName (String name);
|
||||||
public long lastModified ();
|
public long lastModified ();
|
||||||
public long created ();
|
public long created ();
|
||||||
|
@ -34,9 +47,6 @@ public interface INode extends INodeState, IPathElement {
|
||||||
public String getPrototype ();
|
public String getPrototype ();
|
||||||
public void setPrototype (String prototype);
|
public void setPrototype (String prototype);
|
||||||
public INode getCacheNode ();
|
public INode getCacheNode ();
|
||||||
public void clearCacheNode ();
|
|
||||||
public String getFullName ();
|
|
||||||
public String getFullName (INode root);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* node-related methods
|
* node-related methods
|
||||||
|
@ -64,7 +74,7 @@ public interface INode extends INodeState, IPathElement {
|
||||||
public Enumeration properties ();
|
public Enumeration properties ();
|
||||||
public IProperty get (String name, boolean inherit);
|
public IProperty get (String name, boolean inherit);
|
||||||
public String getString (String name, boolean inherit);
|
public String getString (String name, boolean inherit);
|
||||||
// public String getString (String name, String defaultValue, boolean inherit);
|
public String getString (String name, String defaultValue, boolean inherit);
|
||||||
public boolean getBoolean (String name, boolean inherit);
|
public boolean getBoolean (String name, boolean inherit);
|
||||||
public Date getDate (String name, boolean inherit);
|
public Date getDate (String name, boolean inherit);
|
||||||
public long getInteger (String name, boolean inherit);
|
public long getInteger (String name, boolean inherit);
|
||||||
|
@ -82,6 +92,21 @@ public interface INode extends INodeState, IPathElement {
|
||||||
|
|
||||||
public void unset (String name);
|
public void unset (String name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* content-related methods
|
||||||
|
*/
|
||||||
|
|
||||||
|
public String getContentType ();
|
||||||
|
public void setContentType (String type);
|
||||||
|
public int getContentLength ();
|
||||||
|
public void setContent (byte content[], String type);
|
||||||
|
public void setContent (String content);
|
||||||
|
public byte[] getContent ();
|
||||||
|
public String getText ();
|
||||||
|
public String getUrl (INode root, INode userroot, String tmpname);
|
||||||
|
public String getHref (INode root, INode userroot, String tmpname, String prefix);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
15
src/helma/objectmodel/INodeListener.java
Normal file
15
src/helma/objectmodel/INodeListener.java
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
// INodeListener.java
|
||||||
|
// Copyright (c) Hannes Wallnöfer 1998-2000
|
||||||
|
|
||||||
|
package helma.objectmodel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An interface for objects that wish to be notified when certain nodes are
|
||||||
|
* modified. This is not used in the HOP as much as it used to be.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public interface INodeListener {
|
||||||
|
|
||||||
|
public void nodeChanged (NodeEvent event);
|
||||||
|
|
||||||
|
}
|
|
@ -1,27 +0,0 @@
|
||||||
// INodeState.java
|
|
||||||
// Copyright (c) Hannes Wallnöfer 2001
|
|
||||||
|
|
||||||
package helma.objectmodel;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
import java.io.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
public final static int CLEAN = 0;
|
|
||||||
public final static int NEW = 1;
|
|
||||||
public final static int MODIFIED = 2;
|
|
||||||
public final static int DELETED = 3;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
21
src/helma/objectmodel/IPathElement.java
Normal file
21
src/helma/objectmodel/IPathElement.java
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
// INode.java
|
||||||
|
// Copyright (c) Hannes Wallnöfer 2000
|
||||||
|
|
||||||
|
package helma.objectmodel;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Minimal Interface for Nodes that build a hierarchic tree
|
||||||
|
*/
|
||||||
|
|
||||||
|
public interface IPathElement {
|
||||||
|
|
||||||
|
public INode getSubnode (String name);
|
||||||
|
public INode getNode (String name, boolean inherit);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
79
src/helma/objectmodel/IServer.java
Normal file
79
src/helma/objectmodel/IServer.java
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
// IServer.java
|
||||||
|
// Copyright (c) Hannes Wallnöfer 1998-2000
|
||||||
|
|
||||||
|
package helma.objectmodel;
|
||||||
|
|
||||||
|
import helma.util.*;
|
||||||
|
import helma.xmlrpc.WebServer;
|
||||||
|
import java.util.*;
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract Server class. Defines the methods all servers have to implement.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public abstract class IServer {
|
||||||
|
|
||||||
|
// public static final Object sync = new Object ();
|
||||||
|
public static SystemProperties sysProps, dbProps;
|
||||||
|
public static Hashtable dbSources;
|
||||||
|
|
||||||
|
protected static String hopHome = null;
|
||||||
|
|
||||||
|
private static Logger logger;
|
||||||
|
|
||||||
|
protected static WebServer xmlrpc;
|
||||||
|
|
||||||
|
|
||||||
|
/* public abstract INode getAppRoot (String appID);
|
||||||
|
|
||||||
|
public abstract INode getAppNode (String appID, Vector path, String name);
|
||||||
|
|
||||||
|
public abstract INode getSubnode (String path); */
|
||||||
|
|
||||||
|
public static void throwNodeEvent (NodeEvent evt) {
|
||||||
|
// noop
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void addNodeListener (String id, INodeListener listener) {
|
||||||
|
// noop
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void removeNodeListener (String node, INodeListener listener) {
|
||||||
|
// noop
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Logger getLogger () {
|
||||||
|
if (logger == null) {
|
||||||
|
String logDir = sysProps.getProperty ("logdir");
|
||||||
|
if (logDir == null) {
|
||||||
|
logger = new Logger (System.out);
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
File helper = new File (logDir);
|
||||||
|
if (hopHome != null && !helper.isAbsolute ())
|
||||||
|
helper = new File (hopHome, logDir);
|
||||||
|
logDir = helper.getAbsolutePath ();
|
||||||
|
logger = new Logger (logDir, "hop");
|
||||||
|
} catch (IOException iox) {
|
||||||
|
System.err.println ("Could not create Logger for log/hop: "+iox);
|
||||||
|
// fallback to System.out
|
||||||
|
logger = new Logger (System.out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getHopHome () {
|
||||||
|
return hopHome;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static WebServer getXmlRpcServer() {
|
||||||
|
return xmlrpc;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
136
src/helma/objectmodel/Key.java
Normal file
136
src/helma/objectmodel/Key.java
Normal file
|
@ -0,0 +1,136 @@
|
||||||
|
// Key.java
|
||||||
|
// Copyright (c) Hannes Wallnöfer 1998-2000
|
||||||
|
|
||||||
|
package helma.objectmodel;
|
||||||
|
|
||||||
|
|
||||||
|
import helma.util.CacheMap;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the internal representation of a database key. It is constructed
|
||||||
|
* out of the database URL, the table name, the user name and the database
|
||||||
|
* key of the node and unique within each HOP application. Currently only
|
||||||
|
* single keys are supported.
|
||||||
|
*/
|
||||||
|
public class Key {
|
||||||
|
|
||||||
|
private String type;
|
||||||
|
private String id;
|
||||||
|
private int hash;
|
||||||
|
|
||||||
|
|
||||||
|
public Key (DbMapping dbmap, String id) {
|
||||||
|
this.type = dbmap == null ? null : dbmap.typename;
|
||||||
|
this.id = id;
|
||||||
|
hash = id.hashCode ();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Key (String type, String id) {
|
||||||
|
this.type = type;
|
||||||
|
this.id = id;
|
||||||
|
hash = id.hashCode ();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals (Object what) {
|
||||||
|
try {
|
||||||
|
Key k = (Key) what;
|
||||||
|
return ((type == k.type || type.equals (k.type)) && (id == k.id || id.equals (k.id)));
|
||||||
|
} catch (Exception x) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int hashCode () {
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the Key for a virtual node contained by this node, that is, a node that does
|
||||||
|
* not represent a record in the database. The main objective here is to generate
|
||||||
|
* a key that can't be mistaken for a relational db key.
|
||||||
|
*/
|
||||||
|
public Key getVirtualKey (String sid) {
|
||||||
|
return new Key ((String) null, makeVirtualID (type, id, sid));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getVirtualID (String sid) {
|
||||||
|
return makeVirtualID (type, id, sid);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String makeVirtualID (DbMapping pmap, String pid, String sid) {
|
||||||
|
return makeVirtualID (pmap == null ? (String) null : pmap.typename, pid, sid);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String makeVirtualID (String ptype, String pid, String sid) {
|
||||||
|
return ptype+"/"+pid + "~" + sid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getType () {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getID () {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString () {
|
||||||
|
return type+"["+id+"]";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,32 +1,25 @@
|
||||||
// TransientNode.java
|
// Node.java
|
||||||
// Copyright (c) Hannes Wallnöfer 1997-2000
|
// Copyright (c) Hannes Wallnöfer 1997-2000
|
||||||
|
|
||||||
package helma.objectmodel;
|
package helma.objectmodel;
|
||||||
|
|
||||||
|
|
||||||
import java.util.Vector;
|
import java.util.*;
|
||||||
import java.util.Hashtable;
|
|
||||||
import java.util.Enumeration;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.StringTokenizer;
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import helma.util.*;
|
import helma.util.*;
|
||||||
import helma.framework.IPathElement;
|
|
||||||
import helma.objectmodel.db.DbMapping;
|
|
||||||
import helma.objectmodel.db.Relation;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A transient implementation of INode. An instance of this class can't be
|
* A transient implementation of INode. If a transient node is stored in a
|
||||||
* made persistent by reachability from a persistent node. To make a persistent-capable
|
* database, it is automatically (along with all reachable subnodes) rebuilt
|
||||||
* object, class helma.objectmodel.db.Node has to be used.
|
* as a persistent node.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class TransientNode implements INode, Serializable {
|
public class Node implements INode, Serializable {
|
||||||
|
|
||||||
|
|
||||||
protected Hashtable propMap, nodeMap;
|
protected Hashtable propMap, nodeMap;
|
||||||
protected Vector nodes;
|
protected Vector nodes;
|
||||||
protected TransientNode parent;
|
protected Node parent;
|
||||||
protected Vector links; // links to this node
|
protected Vector links; // links to this node
|
||||||
protected Vector proplinks; // nodes using this node as property
|
protected Vector proplinks; // nodes using this node as property
|
||||||
|
|
||||||
|
@ -48,27 +41,69 @@ public class TransientNode implements INode, Serializable {
|
||||||
|
|
||||||
private static long idgen = 0;
|
private static long idgen = 0;
|
||||||
|
|
||||||
public static String generateID () {
|
public String generateID () {
|
||||||
// make transient ids differ from persistent ones
|
return "t"+idgen++; // make transient ids differ from persistent ones
|
||||||
// and are unique within on runtime session
|
|
||||||
return "t"+idgen++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public TransientNode () {
|
public Node () {
|
||||||
id = generateID ();
|
id = generateID ();
|
||||||
name = id;
|
name = id;
|
||||||
created = lastmodified = System.currentTimeMillis ();
|
created = lastmodified = System.currentTimeMillis ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make a new TransientNode object with a given name
|
* Make a new Node object with a given name
|
||||||
*/
|
*/
|
||||||
public TransientNode (String n) {
|
public Node (String n) {
|
||||||
id = generateID ();
|
id = generateID ();
|
||||||
name = n == null || "".equals (n) ? id : n;
|
name = n == null || "".equals (n) ? id : n;
|
||||||
created = lastmodified = System.currentTimeMillis ();
|
created = lastmodified = System.currentTimeMillis ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a clone of a given node that implements this class
|
||||||
|
*/
|
||||||
|
public Node (INode node, Hashtable ntable, boolean conversionRoot) {
|
||||||
|
this.id = generateID ();
|
||||||
|
this.name = node.getName ();
|
||||||
|
created = lastmodified = System.currentTimeMillis ();
|
||||||
|
setContent (node.getContent (), node.getContentType ());
|
||||||
|
created = lastmodified = System.currentTimeMillis ();
|
||||||
|
ntable.put (node, this);
|
||||||
|
adoptName = !conversionRoot; // only take over name from property if this is not the transient root
|
||||||
|
for (Enumeration e = node.getSubnodes (); e.hasMoreElements (); ) {
|
||||||
|
INode next = (INode) e.nextElement ();
|
||||||
|
Node nextc = (Node) ntable.get (next);
|
||||||
|
if (nextc == null)
|
||||||
|
nextc = new Node (next, ntable, true);
|
||||||
|
addNode (nextc);
|
||||||
|
}
|
||||||
|
for (Enumeration e = node.properties (); e.hasMoreElements (); ) {
|
||||||
|
IProperty next = node.get ((String) e.nextElement (), false);
|
||||||
|
if (next == null)
|
||||||
|
continue;
|
||||||
|
int t = next.getType ();
|
||||||
|
if (t == IProperty.NODE) {
|
||||||
|
INode n = next.getNodeValue ();
|
||||||
|
Node nextc = (Node) ntable.get (n);
|
||||||
|
if (nextc == null)
|
||||||
|
nextc = new Node (n, ntable, true);
|
||||||
|
setNode (next.getName (), nextc);
|
||||||
|
} else if (t == IProperty.STRING) {
|
||||||
|
setString (next.getName (), next.getStringValue ());
|
||||||
|
} else if (t == IProperty.INTEGER) {
|
||||||
|
setInteger (next.getName (), next.getIntegerValue ());
|
||||||
|
} else if (t == IProperty.FLOAT) {
|
||||||
|
setFloat (next.getName (), next.getFloatValue ());
|
||||||
|
} else if (t == IProperty.BOOLEAN) {
|
||||||
|
setBoolean (next.getName (), next.getBooleanValue ());
|
||||||
|
} else if (t == IProperty.DATE) {
|
||||||
|
setDate (next.getName (), next.getDateValue ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
adoptName = true; // switch back to normal name adoption behaviour
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void setDbMapping (DbMapping dbmap) {
|
public void setDbMapping (DbMapping dbmap) {
|
||||||
this.dbmap = dbmap;
|
this.dbmap = dbmap;
|
||||||
|
@ -96,7 +131,7 @@ public class TransientNode implements INode, Serializable {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getElementName () {
|
public String getNameOrID () {
|
||||||
return anonymous ? id : name;
|
return anonymous ? id : name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,22 +151,37 @@ public class TransientNode implements INode, Serializable {
|
||||||
String fullname = "";
|
String fullname = "";
|
||||||
String divider = null;
|
String divider = null;
|
||||||
StringBuffer b = new StringBuffer ();
|
StringBuffer b = new StringBuffer ();
|
||||||
TransientNode p = this;
|
Node p = this;
|
||||||
while (p != null && p.parent != null && p != root) {
|
while (p != null && p.parent != null && p != root) {
|
||||||
if (divider != null)
|
if (divider != null)
|
||||||
b.insert (0, divider);
|
b.insert (0, divider);
|
||||||
else
|
else
|
||||||
divider = "/";
|
divider = "/";
|
||||||
b.insert (0, p.getElementName ());
|
b.insert (0, p.getNameOrID ());
|
||||||
p = p.parent;
|
p = p.parent;
|
||||||
}
|
}
|
||||||
return b.toString ();
|
return b.toString ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public INode[] getPath () {
|
||||||
|
int pathSize = 1;
|
||||||
|
INode p = getParent ();
|
||||||
|
while (p != null) {
|
||||||
|
pathSize +=1;
|
||||||
|
p = p.getParent ();
|
||||||
|
}
|
||||||
|
INode path[] = new INode[pathSize];
|
||||||
|
p = this;
|
||||||
|
for (int i = pathSize-1; i>=0; i--) {
|
||||||
|
path[i] = p;
|
||||||
|
p = p.getParent ();
|
||||||
|
}
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
public void setName (String name) {
|
public void setName (String name) {
|
||||||
// if (name.indexOf('/') > -1)
|
if (name.indexOf('/') > -1)
|
||||||
// throw new RuntimeException ("The name of the node must not contain \"/\".");
|
throw new RuntimeException ("The name of the node must not contain \"/\".");
|
||||||
if (name == null || name.trim().length() == 0)
|
if (name == null || name.trim().length() == 0)
|
||||||
this.name = id;
|
this.name = id;
|
||||||
else
|
else
|
||||||
|
@ -195,12 +245,15 @@ public class TransientNode implements INode, Serializable {
|
||||||
nodeMap.put (elem.getID (), elem);
|
nodeMap.put (elem.getID (), elem);
|
||||||
nodes.insertElementAt (elem, where);
|
nodes.insertElementAt (elem, where);
|
||||||
|
|
||||||
if (elem instanceof TransientNode) {
|
if (elem instanceof Node) {
|
||||||
TransientNode node = (TransientNode) elem;
|
Node node = (Node) elem;
|
||||||
if (node.parent == null) {
|
if (node.parent == null) {
|
||||||
node.parent = this;
|
node.parent = this;
|
||||||
node.anonymous = true;
|
node.anonymous = true;
|
||||||
}
|
}
|
||||||
|
if (node.parent != null && (node.parent != this || !node.anonymous)) {
|
||||||
|
node.registerLink (this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lastmodified = System.currentTimeMillis ();
|
lastmodified = System.currentTimeMillis ();
|
||||||
|
@ -224,7 +277,7 @@ public class TransientNode implements INode, Serializable {
|
||||||
boolean anon = false;
|
boolean anon = false;
|
||||||
if (nm == null || "".equals (nm.trim ()))
|
if (nm == null || "".equals (nm.trim ()))
|
||||||
anon = true;
|
anon = true;
|
||||||
INode n = new TransientNode (nm);
|
INode n = new Node (nm);
|
||||||
if (anon)
|
if (anon)
|
||||||
addNode (n, where);
|
addNode (n, where);
|
||||||
else
|
else
|
||||||
|
@ -236,19 +289,11 @@ public class TransientNode implements INode, Serializable {
|
||||||
/**
|
/**
|
||||||
* register a node that links to this node.
|
* register a node that links to this node.
|
||||||
*/
|
*/
|
||||||
/* protected void registerLink (TransientNode from) {
|
protected void registerLink (Node from) {
|
||||||
if (links == null)
|
if (links == null)
|
||||||
links = new Vector ();
|
links = new Vector ();
|
||||||
if (!links.contains (from))
|
if (!links.contains (from))
|
||||||
links.addElement (from);
|
links.addElement (from);
|
||||||
} */
|
|
||||||
|
|
||||||
public IPathElement getParentElement () {
|
|
||||||
return getParent ();
|
|
||||||
}
|
|
||||||
|
|
||||||
public IPathElement getChildElement (String name) {
|
|
||||||
return getNode (name, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public INode getSubnode (String name) {
|
public INode getSubnode (String name) {
|
||||||
|
@ -257,18 +302,18 @@ public class TransientNode implements INode, Serializable {
|
||||||
|
|
||||||
public INode getSubnode (String name, boolean inherit) {
|
public INode getSubnode (String name, boolean inherit) {
|
||||||
StringTokenizer st = new StringTokenizer (name, "/");
|
StringTokenizer st = new StringTokenizer (name, "/");
|
||||||
TransientNode retval = this, runner;
|
Node retval = this, runner;
|
||||||
while (st.hasMoreTokens () && retval != null) {
|
while (st.hasMoreTokens () && retval != null) {
|
||||||
runner = retval;
|
runner = retval;
|
||||||
String next = st.nextToken().trim().toLowerCase ();
|
String next = st.nextToken().trim().toLowerCase ();
|
||||||
if ("".equals (next))
|
if ("".equals (next))
|
||||||
retval = this;
|
retval = this;
|
||||||
else
|
else
|
||||||
retval = runner.nodeMap == null ? null : (TransientNode) runner.nodeMap.get (next);
|
retval = runner.nodeMap == null ? null : (Node) runner.nodeMap.get (next);
|
||||||
if (retval == null)
|
if (retval == null)
|
||||||
retval = (TransientNode) runner.getNode (next, inherit);
|
retval = (Node) runner.getNode (next, inherit);
|
||||||
if (retval == null && inherit && runner == this && parent != null)
|
if (retval == null && inherit && runner == this && parent != null)
|
||||||
retval = (TransientNode) parent.getSubnode (next, inherit);
|
retval = (Node) parent.getSubnode (next, inherit);
|
||||||
}
|
}
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -296,11 +341,11 @@ public class TransientNode implements INode, Serializable {
|
||||||
public void removeNode (INode node) {
|
public void removeNode (INode node) {
|
||||||
// IServer.getLogger().log ("removing: "+ node);
|
// IServer.getLogger().log ("removing: "+ node);
|
||||||
releaseNode (node);
|
releaseNode (node);
|
||||||
TransientNode n = (TransientNode) node;
|
Node n = (Node) node;
|
||||||
if (n.getParent () == this && n.anonymous) {
|
if (n.getParent () == this && n.anonymous) {
|
||||||
int l = n.links == null ? 0 : n.links.size (); // notify nodes that link to n that n is going down.
|
int l = n.links == null ? 0 : n.links.size (); // notify nodes that link to n that n is going down.
|
||||||
for (int i = 0; i < l; i++) {
|
for (int i = 0; i < l; i++) {
|
||||||
TransientNode link = (TransientNode) n.links.elementAt (i);
|
Node link = (Node) n.links.elementAt (i);
|
||||||
link.releaseNode (n);
|
link.releaseNode (n);
|
||||||
}
|
}
|
||||||
if (n.proplinks != null) {
|
if (n.proplinks != null) {
|
||||||
|
@ -310,12 +355,12 @@ public class TransientNode implements INode, Serializable {
|
||||||
p.node.propMap.remove (p.propname.toLowerCase ());
|
p.node.propMap.remove (p.propname.toLowerCase ());
|
||||||
} catch (Exception ignore) {}
|
} catch (Exception ignore) {}
|
||||||
}
|
}
|
||||||
/* for (Enumeration e2 = n.properties (); e2.hasMoreElements (); ) {
|
for (Enumeration e2 = n.properties (); e2.hasMoreElements (); ) {
|
||||||
// tell all nodes that are properties of n that they are no longer used as such
|
// tell all nodes that are properties of n that they are no longer used as such
|
||||||
Property p = (Property) n.get ((String) e2.nextElement (), false);
|
Property p = (Property) n.get ((String) e2.nextElement (), false);
|
||||||
if (p != null && p.type == Property.NODE)
|
if (p != null && p.type == Property.NODE)
|
||||||
p.unregisterNode ();
|
p.unregisterNode ();
|
||||||
} */
|
}
|
||||||
// remove all subnodes, giving them a chance to destroy themselves.
|
// remove all subnodes, giving them a chance to destroy themselves.
|
||||||
Vector v = new Vector (); // removeElement modifies the Vector we are enumerating, so we are extra careful.
|
Vector v = new Vector (); // removeElement modifies the Vector we are enumerating, so we are extra careful.
|
||||||
for (Enumeration e3 = n.getSubnodes (); e3.hasMoreElements (); ) {
|
for (Enumeration e3 = n.getSubnodes (); e3.hasMoreElements (); ) {
|
||||||
|
@ -323,7 +368,7 @@ public class TransientNode implements INode, Serializable {
|
||||||
}
|
}
|
||||||
int m = v.size ();
|
int m = v.size ();
|
||||||
for (int i=0; i<m; i++) {
|
for (int i=0; i<m; i++) {
|
||||||
n.removeNode ((TransientNode) v.elementAt (i));
|
n.removeNode ((Node) v.elementAt (i));
|
||||||
}
|
}
|
||||||
if (n.content != null) {
|
if (n.content != null) {
|
||||||
// IServer.getLogger().log ("destroying content of node "+n.getName ());
|
// IServer.getLogger().log ("destroying content of node "+n.getName ());
|
||||||
|
@ -379,7 +424,7 @@ public class TransientNode implements INode, Serializable {
|
||||||
// check if we have to create a virtual node
|
// check if we have to create a virtual node
|
||||||
if (prop == null && dbmap != null) {
|
if (prop == null && dbmap != null) {
|
||||||
Relation rel = dbmap.getPropertyRelation (propname);
|
Relation rel = dbmap.getPropertyRelation (propname);
|
||||||
if (rel != null && rel.isVirtual ()) {
|
if (rel != null && rel.virtual) {
|
||||||
prop = makeVirtualNode (propname, rel);
|
prop = makeVirtualNode (propname, rel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -387,13 +432,15 @@ public class TransientNode implements INode, Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Property makeVirtualNode (String propname, Relation rel) {
|
private Property makeVirtualNode (String propname, Relation rel) {
|
||||||
INode node = new helma.objectmodel.db.Node (rel.getPropName (), rel.getPrototype (), dbmap.getWrappedNodeManager());
|
INode node = new helma.objectmodel.db.Node (rel.propname, dbmap.getWrappedNodeManager());
|
||||||
// node.setState (TRANSIENT);
|
// node.setState (TRANSIENT);
|
||||||
// make a db mapping good enough that the virtual node finds its subnodes
|
// make a db mapping good enough that the virtual node finds its subnodes
|
||||||
// DbMapping dbm = new DbMapping ();
|
DbMapping dbm = new DbMapping ();
|
||||||
// dbm.setSubnodeRelation (rel);
|
dbm.setSubnodeMapping (rel.other);
|
||||||
// dbm.setPropertyRelation (rel);
|
dbm.setSubnodeRelation (rel);
|
||||||
node.setDbMapping (rel.getVirtualMapping ());
|
dbm.setPropertyMapping (rel.other);
|
||||||
|
dbm.setPropertyRelation (rel);
|
||||||
|
node.setDbMapping (dbm);
|
||||||
setNode (propname, node);
|
setNode (propname, node);
|
||||||
return (Property) propMap.get (propname);
|
return (Property) propMap.get (propname);
|
||||||
}
|
}
|
||||||
|
@ -547,8 +594,8 @@ public class TransientNode implements INode, Serializable {
|
||||||
|
|
||||||
// check if the main identity of this node is as a named property
|
// check if the main identity of this node is as a named property
|
||||||
// or as an anonymous node in a collection
|
// or as an anonymous node in a collection
|
||||||
if (value instanceof TransientNode) {
|
if (value instanceof Node) {
|
||||||
TransientNode n = (TransientNode) value;
|
Node n = (Node) value;
|
||||||
if (n.parent == null && n.adoptName) {
|
if (n.parent == null && n.adoptName) {
|
||||||
n.name = propname;
|
n.name = propname;
|
||||||
n.parent = this;
|
n.parent = this;
|
||||||
|
@ -556,6 +603,8 @@ public class TransientNode implements INode, Serializable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Server.throwNodeEvent (new NodeEvent (this, NodeEvent.SUBNODE_ADDED, n));
|
||||||
|
// Server.throwNodeEvent (new NodeEvent (this, NodeEvent.PROPERTIES_CHANGED));
|
||||||
lastmodified = System.currentTimeMillis ();
|
lastmodified = System.currentTimeMillis ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -564,14 +613,132 @@ public class TransientNode implements INode, Serializable {
|
||||||
return;
|
return;
|
||||||
try {
|
try {
|
||||||
Property p = (Property) propMap.remove (propname.toLowerCase ());
|
Property p = (Property) propMap.remove (propname.toLowerCase ());
|
||||||
|
if (p != null && p.type == Property.NODE)
|
||||||
|
p.unregisterNode ();
|
||||||
|
// Server.throwNodeEvent (new NodeEvent (this, NodeEvent.PROPERTIES_CHANGED));
|
||||||
lastmodified = System.currentTimeMillis ();
|
lastmodified = System.currentTimeMillis ();
|
||||||
} catch (Exception ignore) {}
|
} catch (Exception ignore) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void registerPropLink (Property p) {
|
||||||
|
if (proplinks == null)
|
||||||
|
proplinks = new Vector ();
|
||||||
|
proplinks.addElement (p);
|
||||||
|
// IServer.getLogger().log ("registered proplink from "+p.node.getFullName ());
|
||||||
|
// the NodeEvent is thrown later, since the node is not yet in the prop table
|
||||||
|
}
|
||||||
|
|
||||||
/* public String getUrl (INode root, INode users, String tmpname, String rootproto) {
|
protected void unregisterPropLink (Property p) {
|
||||||
|
if (proplinks != null)
|
||||||
|
proplinks.removeElement (p);
|
||||||
|
// IServer.getLogger().log ("unregistered proplink from "+p.node.getFullName ());
|
||||||
|
// Server.throwNodeEvent (new NodeEvent (this, NodeEvent.NODE_REMOVED));
|
||||||
|
// Server.throwNodeEvent (new NodeEvent (p.node, NodeEvent.SUBNODE_REMOVED, this));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* content-related
|
||||||
|
*/
|
||||||
|
|
||||||
|
public boolean isText () throws IOException {
|
||||||
|
return getContentType().indexOf ("text/") == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isBinary () throws IOException {
|
||||||
|
return getContentType().indexOf ("text/") != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContentType () {
|
||||||
|
if (contentType == null)
|
||||||
|
return "text/plain";
|
||||||
|
return contentType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContentType (String type) {
|
||||||
|
contentType = type;
|
||||||
|
lastmodified = System.currentTimeMillis ();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getContentLength () {
|
||||||
|
if (content == null)
|
||||||
|
return 0;
|
||||||
|
return content.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContent (byte cnt[], String type) {
|
||||||
|
if (type != null)
|
||||||
|
contentType = type;
|
||||||
|
content = cnt;
|
||||||
|
lastmodified = System.currentTimeMillis ();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContent (String cstr) {
|
||||||
|
content = cstr == null ? null : cstr.getBytes ();
|
||||||
|
lastmodified = System.currentTimeMillis ();
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getContent () {
|
||||||
|
if (content == null || content.length == 0)
|
||||||
|
return "".getBytes ();
|
||||||
|
byte retval[] = new byte[content.length];
|
||||||
|
System.arraycopy (content, 0, retval, 0, content.length);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String writeToFile (String dir) {
|
||||||
|
return writeToFile (dir, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String writeToFile (String dir, String fname) {
|
||||||
|
try {
|
||||||
|
File base = new File (dir);
|
||||||
|
// make directories if they don't exist
|
||||||
|
if (!base.exists ())
|
||||||
|
base.mkdirs ();
|
||||||
|
|
||||||
|
String filename = name;
|
||||||
|
if (fname != null) {
|
||||||
|
if (fname.indexOf (".") < 0) {
|
||||||
|
// check if we can use extension from name
|
||||||
|
int ndot = name == null ? -1 : name.lastIndexOf (".");
|
||||||
|
if (ndot > -1)
|
||||||
|
filename = fname + name.substring (ndot);
|
||||||
|
else
|
||||||
|
filename = fname;
|
||||||
|
} else {
|
||||||
|
filename = fname;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
File file = new File (base, filename);
|
||||||
|
FileOutputStream fout = new FileOutputStream (file);
|
||||||
|
fout.write (getContent ());
|
||||||
|
fout.close ();
|
||||||
|
return filename;
|
||||||
|
} catch (Exception x) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getText () {
|
||||||
|
if (content != null) {
|
||||||
|
if (getContentType ().indexOf ("text/") == 0) {
|
||||||
|
return new String (content);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getHref (INode root, INode userroot, String tmpname, String prefix) {
|
||||||
|
return prefix + getUrl (root, userroot, tmpname);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUrl (INode root, INode userroot, String tmpname) {
|
||||||
throw new RuntimeException ("HREFs on transient (non-db based) Nodes not supported");
|
throw new RuntimeException ("HREFs on transient (non-db based) Nodes not supported");
|
||||||
} */
|
}
|
||||||
|
|
||||||
|
|
||||||
public long lastModified () {
|
public long lastModified () {
|
||||||
|
@ -583,29 +750,26 @@ public class TransientNode implements INode, Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString () {
|
public String toString () {
|
||||||
return "TransientNode " + name;
|
return "Node " + name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected Node convert (INode n) {
|
||||||
|
Hashtable ntable = new Hashtable ();
|
||||||
|
Node converted = new Node (n, ntable, false);
|
||||||
|
return converted;
|
||||||
|
}
|
||||||
|
|
||||||
INode cacheNode;
|
INode cacheNode;
|
||||||
/**
|
/**
|
||||||
* Get the cache node for this node. This can
|
* Get the cache node for this node. This can be used to store transient cache data per node from Javascript.
|
||||||
* be used to store transient cache data per node
|
|
||||||
* from Javascript.
|
|
||||||
*/
|
*/
|
||||||
public synchronized INode getCacheNode () {
|
public synchronized INode getCacheNode () {
|
||||||
if (cacheNode == null)
|
if (cacheNode == null)
|
||||||
cacheNode = new TransientNode();
|
cacheNode = new Node();
|
||||||
return cacheNode;
|
return cacheNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset the cache node for this node.
|
|
||||||
*/
|
|
||||||
public synchronized void clearCacheNode () {
|
|
||||||
cacheNode = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
46
src/helma/objectmodel/NodeDataSource.java
Normal file
46
src/helma/objectmodel/NodeDataSource.java
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
// NodeDataSource.java
|
||||||
|
// Copyright (c) Hannes Wallnöfer 1999-2000
|
||||||
|
|
||||||
|
package helma.objectmodel;
|
||||||
|
|
||||||
|
import javax.activation.*;
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Makes Nodes usable as Datasources in the Java Activation Framework (JAF)
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class NodeDataSource implements DataSource {
|
||||||
|
|
||||||
|
private INode node;
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public NodeDataSource (INode node) {
|
||||||
|
this.node = node;
|
||||||
|
this.name = node.getName ();
|
||||||
|
}
|
||||||
|
|
||||||
|
public NodeDataSource (INode node, String name) {
|
||||||
|
this.node = node;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public InputStream getInputStream() throws IOException {
|
||||||
|
return new ByteArrayInputStream(node.getContent ());
|
||||||
|
}
|
||||||
|
|
||||||
|
public OutputStream getOutputStream () throws IOException {
|
||||||
|
throw new IOException ("Can't write to Node object.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContentType() {
|
||||||
|
return node.getContentType ();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName()
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -4,10 +4,7 @@
|
||||||
package helma.objectmodel;
|
package helma.objectmodel;
|
||||||
|
|
||||||
import helma.util.*;
|
import helma.util.*;
|
||||||
import java.util.Vector;
|
import java.util.*;
|
||||||
import java.util.Hashtable;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.Enumeration;
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.text.*;
|
import java.text.*;
|
||||||
|
|
||||||
|
@ -15,11 +12,11 @@ import java.text.*;
|
||||||
* A property implementation for Nodes stored inside a database.
|
* A property implementation for Nodes stored inside a database.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public final class Property implements IProperty, Serializable {
|
public final class Property implements IProperty, Serializable, Cloneable {
|
||||||
|
|
||||||
|
|
||||||
protected String propname;
|
protected String propname;
|
||||||
protected TransientNode node;
|
protected Node node;
|
||||||
|
|
||||||
public String svalue;
|
public String svalue;
|
||||||
public boolean bvalue;
|
public boolean bvalue;
|
||||||
|
@ -31,11 +28,11 @@ public final class Property implements IProperty, Serializable {
|
||||||
public int type;
|
public int type;
|
||||||
|
|
||||||
|
|
||||||
public Property (TransientNode node) {
|
public Property (Node node) {
|
||||||
this.node = node;
|
this.node = node;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Property (String propname, TransientNode node) {
|
public Property (String propname, Node node) {
|
||||||
this.propname = propname;
|
this.propname = propname;
|
||||||
this.node = node;
|
this.node = node;
|
||||||
}
|
}
|
||||||
|
@ -66,16 +63,39 @@ public final class Property implements IProperty, Serializable {
|
||||||
|
|
||||||
public void setStringValue (String value) throws ParseException {
|
public void setStringValue (String value) throws ParseException {
|
||||||
if (type == NODE)
|
if (type == NODE)
|
||||||
this.nvalue = null;
|
unregisterNode ();
|
||||||
|
// IServer.getLogger().log ("setting string value of property "+propname + " to "+value);
|
||||||
|
if (type == DATE) {
|
||||||
|
SimpleDateFormat dateformat = new SimpleDateFormat ();
|
||||||
|
dateformat.setLenient (true);
|
||||||
|
Date date = dateformat.parse (value);
|
||||||
|
this.lvalue = date.getTime ();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (type == BOOLEAN) {
|
||||||
|
if ("true".equalsIgnoreCase (value))
|
||||||
|
this.bvalue = true;
|
||||||
|
else if ("false".equalsIgnoreCase (value))
|
||||||
|
this.bvalue = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (type == INTEGER) {
|
||||||
|
this.lvalue = Long.parseLong (value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (type == FLOAT) {
|
||||||
|
this.dvalue = new Double (value).doubleValue ();
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (type == JAVAOBJECT)
|
if (type == JAVAOBJECT)
|
||||||
this.jvalue = null;
|
this.jvalue = null;
|
||||||
type = STRING;
|
|
||||||
this.svalue = value;
|
this.svalue = value;
|
||||||
|
type = STRING;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setIntegerValue (long value) {
|
public void setIntegerValue (long value) {
|
||||||
if (type == NODE)
|
if (type == NODE)
|
||||||
this.nvalue = null;
|
unregisterNode ();
|
||||||
if (type == JAVAOBJECT)
|
if (type == JAVAOBJECT)
|
||||||
this.jvalue = null;
|
this.jvalue = null;
|
||||||
type = INTEGER;
|
type = INTEGER;
|
||||||
|
@ -84,7 +104,7 @@ public final class Property implements IProperty, Serializable {
|
||||||
|
|
||||||
public void setFloatValue (double value) {
|
public void setFloatValue (double value) {
|
||||||
if (type == NODE)
|
if (type == NODE)
|
||||||
this.nvalue = null;
|
unregisterNode ();
|
||||||
if (type == JAVAOBJECT)
|
if (type == JAVAOBJECT)
|
||||||
this.jvalue = null;
|
this.jvalue = null;
|
||||||
type = FLOAT;
|
type = FLOAT;
|
||||||
|
@ -93,7 +113,7 @@ public final class Property implements IProperty, Serializable {
|
||||||
|
|
||||||
public void setDateValue (Date value) {
|
public void setDateValue (Date value) {
|
||||||
if (type == NODE)
|
if (type == NODE)
|
||||||
this.nvalue = null;
|
unregisterNode ();
|
||||||
if (type == JAVAOBJECT)
|
if (type == JAVAOBJECT)
|
||||||
this.jvalue = null;
|
this.jvalue = null;
|
||||||
type = DATE;
|
type = DATE;
|
||||||
|
@ -102,7 +122,7 @@ public final class Property implements IProperty, Serializable {
|
||||||
|
|
||||||
public void setBooleanValue (boolean value) {
|
public void setBooleanValue (boolean value) {
|
||||||
if (type == NODE)
|
if (type == NODE)
|
||||||
this.nvalue = null;
|
unregisterNode ();
|
||||||
if (type == JAVAOBJECT)
|
if (type == JAVAOBJECT)
|
||||||
this.jvalue = null;
|
this.jvalue = null;
|
||||||
type = BOOLEAN;
|
type = BOOLEAN;
|
||||||
|
@ -112,18 +132,58 @@ public final class Property implements IProperty, Serializable {
|
||||||
public void setNodeValue (INode value) {
|
public void setNodeValue (INode value) {
|
||||||
if (type == JAVAOBJECT)
|
if (type == JAVAOBJECT)
|
||||||
this.jvalue = null;
|
this.jvalue = null;
|
||||||
|
if (type == NODE && nvalue != value) {
|
||||||
|
unregisterNode ();
|
||||||
|
registerNode (value);
|
||||||
|
} else if (type != NODE)
|
||||||
|
registerNode (value);
|
||||||
type = NODE;
|
type = NODE;
|
||||||
this.nvalue = value;
|
this.nvalue = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setJavaObjectValue (Object value) {
|
public void setJavaObjectValue (Object value) {
|
||||||
if (type == NODE)
|
if (type == NODE)
|
||||||
this.nvalue = null;
|
unregisterNode ();
|
||||||
type = JAVAOBJECT;
|
type = JAVAOBJECT;
|
||||||
this.jvalue = value;
|
this.jvalue = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tell a the value node that it is no longer used as a property.
|
||||||
|
*/
|
||||||
|
protected void unregisterNode () {
|
||||||
|
if (nvalue != null && nvalue instanceof Node) {
|
||||||
|
Node n = (Node) nvalue;
|
||||||
|
if (!n.anonymous && propname.equals (n.getName()) && this.node == n.getParent()) {
|
||||||
|
// this is the "main" property of a named node, so handle this as a total delete.
|
||||||
|
IServer.getLogger().log ("deleting named property");
|
||||||
|
if (n.proplinks != null) {
|
||||||
|
for (Enumeration e = n.proplinks.elements (); e.hasMoreElements (); ) {
|
||||||
|
Property p = (Property) e.nextElement ();
|
||||||
|
p.node.propMap.remove (p.propname.toLowerCase ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (n.links != null) {
|
||||||
|
for (Enumeration e = n.links.elements (); e.hasMoreElements (); ) {
|
||||||
|
Node n2 = (Node) e.nextElement ();
|
||||||
|
n2.releaseNode (n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
n.unregisterPropLink (this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tell the value node that it is being used as a property value.
|
||||||
|
*/
|
||||||
|
protected void registerNode (INode n) {
|
||||||
|
if (n != null && n instanceof Node)
|
||||||
|
((Node) n).registerPropLink (this);
|
||||||
|
}
|
||||||
|
|
||||||
public String getStringValue () {
|
public String getStringValue () {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
@ -141,7 +201,7 @@ public final class Property implements IProperty, Serializable {
|
||||||
case NODE:
|
case NODE:
|
||||||
return nvalue.getName ();
|
return nvalue.getName ();
|
||||||
case JAVAOBJECT:
|
case JAVAOBJECT:
|
||||||
return jvalue == null ? null : jvalue.toString ();
|
return jvalue.toString ();
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
@ -187,9 +247,86 @@ public final class Property implements IProperty, Serializable {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getEditor () {
|
||||||
|
switch (type) {
|
||||||
|
case STRING:
|
||||||
|
return "password".equalsIgnoreCase (propname) ?
|
||||||
|
"<input type=password name=\""+propname+"\" value='"+ svalue.replace ('\'', '"') +"'>" :
|
||||||
|
"<input type=text name=\""+propname+"\" value='"+ svalue.replace ('\'', '"') +"'>" ;
|
||||||
|
case BOOLEAN:
|
||||||
|
return "<select name=\""+propname+"\"><option selected value="+bvalue+">"+bvalue+"</option><option value="+!bvalue+">"+!bvalue+"</option></select>";
|
||||||
|
case INTEGER:
|
||||||
|
return "<input type=text name=\""+propname+"\" value=\""+lvalue+"\">" ;
|
||||||
|
case FLOAT:
|
||||||
|
return "<input type=text name=\""+propname+"\" value=\""+dvalue+"\">" ;
|
||||||
|
case DATE:
|
||||||
|
SimpleDateFormat format = new SimpleDateFormat ("dd.MM.yy hh:mm");
|
||||||
|
String date = format.format (new Date (lvalue));
|
||||||
|
return "<input type=text name=\""+propname+"\" value=\""+date+"\">";
|
||||||
|
case NODE:
|
||||||
|
return "<input type=text size=25 name="+propname+" value='"+ nvalue.getFullName () +"'>";
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
private String escape (String s) {
|
||||||
|
char c[] = new char[s.length()];
|
||||||
|
s.getChars (0, c.length, c, 0);
|
||||||
|
StringBuffer b = new StringBuffer ();
|
||||||
|
int copyfrom = 0;
|
||||||
|
for (int i = 0; i < c.length; i++) {
|
||||||
|
switch (c[i]) {
|
||||||
|
case '\\':
|
||||||
|
case '"':
|
||||||
|
if (i-copyfrom > 0)
|
||||||
|
b.append (c, copyfrom, i-copyfrom);
|
||||||
|
b.append ('\\');
|
||||||
|
b.append (c[i]);
|
||||||
|
copyfrom = i+1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (c.length-copyfrom > 0)
|
||||||
|
b.append (c, copyfrom, c.length-copyfrom);
|
||||||
|
return b.toString ();
|
||||||
|
}
|
||||||
|
|
||||||
public int getType () {
|
public int getType () {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getTypeString () {
|
||||||
|
switch (type) {
|
||||||
|
case STRING:
|
||||||
|
return "string";
|
||||||
|
case BOOLEAN:
|
||||||
|
return "boolean";
|
||||||
|
case DATE:
|
||||||
|
return "date";
|
||||||
|
case INTEGER:
|
||||||
|
return "integer";
|
||||||
|
case FLOAT:
|
||||||
|
return "float";
|
||||||
|
case NODE:
|
||||||
|
return "node";
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Object clone () {
|
||||||
|
try {
|
||||||
|
Property c = (Property) super.clone();
|
||||||
|
c.propname = this.propname;
|
||||||
|
c.svalue = this.svalue;
|
||||||
|
c.bvalue = this.bvalue;
|
||||||
|
c.lvalue = this.lvalue;
|
||||||
|
c.dvalue = this.dvalue;
|
||||||
|
c.type = this.type;
|
||||||
|
return c;
|
||||||
|
} catch (CloneNotSupportedException e) {
|
||||||
|
// this shouldn't happen, since we are Cloneable
|
||||||
|
throw new InternalError ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
341
src/helma/objectmodel/Relation.java
Normal file
341
src/helma/objectmodel/Relation.java
Normal file
|
@ -0,0 +1,341 @@
|
||||||
|
// Relation.java
|
||||||
|
// Copyright (c) Hannes Wallnöfer 1997-2000
|
||||||
|
|
||||||
|
package helma.objectmodel;
|
||||||
|
|
||||||
|
import helma.framework.core.Application;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This describes how a property of a persistent Object is stored in a
|
||||||
|
* relational database table. This can be either a scalar property (string, date, number etc.)
|
||||||
|
* or a reference to one or more other objects.
|
||||||
|
*/
|
||||||
|
public class Relation {
|
||||||
|
|
||||||
|
// TODO: explain hop mapping types
|
||||||
|
public final static int INVALID = -1;
|
||||||
|
public final static int PRIMITIVE = 0;
|
||||||
|
public final static int FORWARD = 1;
|
||||||
|
public final static int BACKWARD = 2;
|
||||||
|
public final static int DIRECT = 3;
|
||||||
|
|
||||||
|
public DbMapping home;
|
||||||
|
public DbMapping other;
|
||||||
|
public String propname;
|
||||||
|
protected String localField, remoteField;
|
||||||
|
public int direction;
|
||||||
|
|
||||||
|
public boolean virtual;
|
||||||
|
public boolean readonly;
|
||||||
|
public boolean aggressiveLoading;
|
||||||
|
public boolean aggressiveCaching;
|
||||||
|
public boolean subnodesAreProperties;
|
||||||
|
public String order;
|
||||||
|
public String groupbyorder;
|
||||||
|
public String groupby;
|
||||||
|
public String prototype;
|
||||||
|
|
||||||
|
Relation filter = null; // additional relation used to filter subnodes
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This constructor is used to directly construct a Relation, as opposed to reading it from a proerty file
|
||||||
|
*/
|
||||||
|
public Relation (DbMapping other, String localField, String remoteField, int direction, boolean subnodesAreProperties) {
|
||||||
|
this.other = other;
|
||||||
|
this.localField = localField;
|
||||||
|
this.remoteField = remoteField;
|
||||||
|
this.direction = direction;
|
||||||
|
this.subnodesAreProperties = subnodesAreProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a relation entry from a line in a properties file.
|
||||||
|
*/
|
||||||
|
public Relation (String desc, String propname, DbMapping home, Properties props) {
|
||||||
|
|
||||||
|
this.home = home;
|
||||||
|
this.propname = propname;
|
||||||
|
other = null;
|
||||||
|
Application app = home.getApplication ();
|
||||||
|
boolean mountpoint = false;
|
||||||
|
|
||||||
|
if (desc == null || "".equals (desc.trim ())) {
|
||||||
|
if (propname != null) {
|
||||||
|
direction = PRIMITIVE;
|
||||||
|
localField = propname;
|
||||||
|
} else {
|
||||||
|
direction = INVALID;
|
||||||
|
localField = propname;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
desc = desc.trim ();
|
||||||
|
String descLower = desc.toLowerCase ();
|
||||||
|
if (descLower.startsWith ("[virtual]")) {
|
||||||
|
desc = desc.substring (9).trim ();
|
||||||
|
virtual = true;
|
||||||
|
} else if (descLower.startsWith ("[collection]")) {
|
||||||
|
desc = desc.substring (12).trim ();
|
||||||
|
virtual = true;
|
||||||
|
} else if (descLower.startsWith ("[mountpoint]")) {
|
||||||
|
desc = desc.substring (12).trim ();
|
||||||
|
virtual = true;
|
||||||
|
mountpoint = true;
|
||||||
|
} else {
|
||||||
|
virtual = false;
|
||||||
|
}
|
||||||
|
if (descLower.startsWith ("[readonly]")) {
|
||||||
|
desc = desc.substring (10).trim ();
|
||||||
|
readonly = true;
|
||||||
|
} else {
|
||||||
|
readonly = false;
|
||||||
|
}
|
||||||
|
if (desc.indexOf ("<") > -1) {
|
||||||
|
direction = BACKWARD;
|
||||||
|
int lt = desc.indexOf ("<");
|
||||||
|
int dot = desc.indexOf (".");
|
||||||
|
String otherType = dot < 0 ? desc.substring (1).trim () : desc.substring (1, dot).trim ();
|
||||||
|
other = app.getDbMapping (otherType);
|
||||||
|
if (other == null)
|
||||||
|
throw new RuntimeException ("DbMapping for "+otherType+" not found from "+home.typename);
|
||||||
|
remoteField = dot < 0 ? null : desc.substring (dot+1).trim ();
|
||||||
|
localField = lt < 0 ? null : desc.substring (0, lt).trim ();
|
||||||
|
if (mountpoint) prototype = otherType;
|
||||||
|
} else if (desc.indexOf (">") > -1) {
|
||||||
|
direction = FORWARD;
|
||||||
|
int bt = desc.indexOf (">");
|
||||||
|
int dot = desc.indexOf (".");
|
||||||
|
String otherType = dot > -1 ? desc.substring (bt+1, dot).trim () : desc.substring (bt+1).trim ();
|
||||||
|
other = app.getDbMapping (otherType);
|
||||||
|
if (other == null)
|
||||||
|
throw new RuntimeException ("DbMapping for "+otherType+" not found from "+home.typename);
|
||||||
|
localField = desc.substring (0, bt).trim ();
|
||||||
|
remoteField = dot < 0 ? null : desc.substring (dot+1).trim ();
|
||||||
|
if (mountpoint) prototype = otherType;
|
||||||
|
} else if (desc.indexOf (".") > -1) {
|
||||||
|
direction = DIRECT;
|
||||||
|
int dot = desc.indexOf (".");
|
||||||
|
String otherType = desc.substring (0, dot).trim ();
|
||||||
|
other = app.getDbMapping (otherType);
|
||||||
|
if (other == null)
|
||||||
|
throw new RuntimeException ("DbMapping for "+otherType+" not found from "+home.typename);
|
||||||
|
remoteField = desc.substring (dot+1).trim ();
|
||||||
|
localField = null;
|
||||||
|
if (mountpoint) prototype = otherType;
|
||||||
|
} else {
|
||||||
|
if (virtual) {
|
||||||
|
direction = DIRECT;
|
||||||
|
other = app.getDbMapping (desc);
|
||||||
|
if (other == null)
|
||||||
|
throw new RuntimeException ("DbMapping for "+desc+" not found from "+home.typename);
|
||||||
|
remoteField = localField = null;
|
||||||
|
if (mountpoint) prototype = desc;
|
||||||
|
} else {
|
||||||
|
direction = PRIMITIVE;
|
||||||
|
localField = desc.trim ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String loading = props.getProperty (propname+".loadmode");
|
||||||
|
aggressiveLoading = loading != null && "aggressive".equalsIgnoreCase (loading.trim());
|
||||||
|
String caching = props.getProperty (propname+".cachemode");
|
||||||
|
aggressiveCaching = caching != null && "aggressive".equalsIgnoreCase (caching.trim());
|
||||||
|
// get order property
|
||||||
|
order = props.getProperty (propname+".order");
|
||||||
|
if (order != null && order.trim().length() == 0) order = null;
|
||||||
|
// get group by property
|
||||||
|
groupby = props.getProperty (propname+".groupby");
|
||||||
|
if (groupby != null && groupby.trim().length() == 0)
|
||||||
|
groupby = null;
|
||||||
|
if (groupby != null) {
|
||||||
|
groupbyorder = props.getProperty (propname+".groupby.order");
|
||||||
|
if (groupbyorder != null && groupbyorder.trim().length() == 0)
|
||||||
|
groupbyorder = null;
|
||||||
|
}
|
||||||
|
// check if subnode condition should be applied for property relations
|
||||||
|
if ("_properties".equalsIgnoreCase (propname) || virtual) {
|
||||||
|
String subnodes2props = props.getProperty (propname+".aresubnodes");
|
||||||
|
subnodesAreProperties = "true".equalsIgnoreCase (subnodes2props);
|
||||||
|
if (virtual) {
|
||||||
|
String subnodefilter = props.getProperty (propname+".subnoderelation");
|
||||||
|
if (subnodefilter != null) {
|
||||||
|
filter = new Relation (subnodefilter, propname+".subnoderelation", home, props);
|
||||||
|
filter.groupby = groupby;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isReference () {
|
||||||
|
return direction > PRIMITIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean usesPrimaryKey () {
|
||||||
|
if (other == null)
|
||||||
|
return false;
|
||||||
|
if (remoteField == null)
|
||||||
|
// if remote field is null, it is assumed that it points to the primary key
|
||||||
|
return true;
|
||||||
|
return remoteField.equalsIgnoreCase (other.getIDField());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Relation getFilter () {
|
||||||
|
return filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a key string to cache a node with a specific value for this relation. If the
|
||||||
|
* Relation uses the primary key return just the key value, otherwise include info on the
|
||||||
|
* used column or even the base node to avoid collisions.
|
||||||
|
*/
|
||||||
|
public String getKeyID (INode home, String kval) {
|
||||||
|
// if the column is not the primary key, we add the column name to the key
|
||||||
|
if ((direction == DIRECT || direction == FORWARD) && !usesPrimaryKey ()) {
|
||||||
|
// check if the subnode relation also has to be considered
|
||||||
|
if (subnodesAreProperties)
|
||||||
|
return "["+home.getID()+"]"+remoteField+"="+kval; // HACK
|
||||||
|
else
|
||||||
|
return remoteField+"="+kval;
|
||||||
|
} else {
|
||||||
|
return kval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the local column name for this relation to use in where clauses of select statements.
|
||||||
|
* This uses the home node's id as fallback if local field is not specified.
|
||||||
|
*/
|
||||||
|
public String getLocalField () {
|
||||||
|
// only assume local field is primary key if other objects "point" to this object
|
||||||
|
if (localField == null && direction == BACKWARD)
|
||||||
|
return home.getIDField ();
|
||||||
|
return localField;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the local field name for updates. This is the same as getLocalField, but does not return the
|
||||||
|
* primary key name as a fallback.
|
||||||
|
*/
|
||||||
|
public String getDbField () {
|
||||||
|
return localField;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the "remote" column name for this relation. Uses the remote node's id as fallback if the remote field is not specified.
|
||||||
|
*/
|
||||||
|
public String getRemoteField () {
|
||||||
|
// only assume remote field is primary key if this relation "points" to an object
|
||||||
|
if (remoteField == null && direction == FORWARD)
|
||||||
|
return other.getIDField ();
|
||||||
|
return remoteField;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a Relation that defines the subnodes of a virtual node.
|
||||||
|
*/
|
||||||
|
public Relation getVirtualSubnodeRelation () {
|
||||||
|
if (!virtual)
|
||||||
|
throw new RuntimeException ("getVirtualSubnodeRelation called on non-virtual relation");
|
||||||
|
if (filter != null)
|
||||||
|
return filter;
|
||||||
|
Relation vr = new Relation (other, localField, remoteField, direction, subnodesAreProperties);
|
||||||
|
vr.groupby = groupby;
|
||||||
|
vr.groupbyorder = groupbyorder;
|
||||||
|
vr.order = order;
|
||||||
|
vr.filter = filter;
|
||||||
|
return vr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a Relation that defines the properties of a virtual node.
|
||||||
|
*/
|
||||||
|
public Relation getVirtualPropertyRelation () {
|
||||||
|
if (!virtual)
|
||||||
|
throw new RuntimeException ("getVirtualPropertyRelation called on non-virtual relation");
|
||||||
|
Relation vr = new Relation (other, localField, remoteField, direction, subnodesAreProperties);
|
||||||
|
vr.groupby = groupby;
|
||||||
|
vr.groupbyorder = groupbyorder;
|
||||||
|
vr.order = order;
|
||||||
|
vr.filter = filter;
|
||||||
|
return vr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a Relation that defines the subnodes of a group-by node.
|
||||||
|
*/
|
||||||
|
public Relation getGroupbySubnodeRelation () {
|
||||||
|
if (groupby == null)
|
||||||
|
throw new RuntimeException ("getGroupbyPropertyRelation called on non-group-by relation");
|
||||||
|
if (filter != null)
|
||||||
|
return filter;
|
||||||
|
Relation vr = new Relation (other, localField, remoteField, direction, true);
|
||||||
|
vr.order = order;
|
||||||
|
return vr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a Relation that defines the properties of a group-by node.
|
||||||
|
*/
|
||||||
|
public Relation getGroupbyPropertyRelation () {
|
||||||
|
if (groupby == null)
|
||||||
|
throw new RuntimeException ("getGroupbyPropertyRelation called on non-group-by relation");
|
||||||
|
Relation vr = new Relation (other, localField, remoteField, direction, true);
|
||||||
|
vr.order = order;
|
||||||
|
return vr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
// Property.java
|
// Property.java
|
||||||
// Copyright (c) Hannes Wallnöfer 1997-2000
|
// Copyright (c) Hannes Wallnöfer 1997-2000
|
||||||
|
|
||||||
package helma.util;
|
package helma.objectmodel;
|
||||||
|
|
||||||
|
import helma.util.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
|
||||||
|
@ -19,27 +20,11 @@ public final class SystemProperties extends Properties {
|
||||||
private File file;
|
private File file;
|
||||||
private long lastread, lastcheck;
|
private long lastread, lastcheck;
|
||||||
|
|
||||||
final static long cacheTime = 1500l;
|
|
||||||
|
|
||||||
|
|
||||||
public SystemProperties () {
|
public SystemProperties () {
|
||||||
this (null, null);
|
this (null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SystemProperties (InputStream in) {
|
|
||||||
this (null, null);
|
|
||||||
try {
|
|
||||||
load (in);
|
|
||||||
} catch (Exception x) {
|
|
||||||
System.err.println ("Error reading properties from file "+file+": "+x);
|
|
||||||
} finally {
|
|
||||||
try {
|
|
||||||
in.close ();
|
|
||||||
} catch (Exception ignore) {}
|
|
||||||
}
|
|
||||||
lastread = System.currentTimeMillis ();
|
|
||||||
}
|
|
||||||
|
|
||||||
public SystemProperties (String filename) {
|
public SystemProperties (String filename) {
|
||||||
this (filename, null);
|
this (filename, null);
|
||||||
}
|
}
|
||||||
|
@ -49,7 +34,7 @@ public final class SystemProperties extends Properties {
|
||||||
}
|
}
|
||||||
|
|
||||||
public SystemProperties (String filename, Properties defaultProps) {
|
public SystemProperties (String filename, Properties defaultProps) {
|
||||||
// System.err.println ("building sysprops with file "+filename+" and node "+node);
|
// IServer.getLogger().log ("building sysprops with file "+filename+" and node "+node);
|
||||||
this.defaultProps = defaultProps;
|
this.defaultProps = defaultProps;
|
||||||
props = defaultProps == null ?
|
props = defaultProps == null ?
|
||||||
new Properties () : new Properties (defaultProps);
|
new Properties () : new Properties (defaultProps);
|
||||||
|
@ -79,7 +64,7 @@ public final class SystemProperties extends Properties {
|
||||||
load (bpin);
|
load (bpin);
|
||||||
bpin.close ();
|
bpin.close ();
|
||||||
} catch (Exception x) {
|
} catch (Exception x) {
|
||||||
System.err.println ("Error reading properties from file "+file+": "+x);
|
IServer.getLogger().log ("Error reading properties from file "+file+": "+x);
|
||||||
}
|
}
|
||||||
lastread = System.currentTimeMillis ();
|
lastread = System.currentTimeMillis ();
|
||||||
props = newProps;
|
props = newProps;
|
||||||
|
@ -124,42 +109,30 @@ public final class SystemProperties extends Properties {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getProperty (String name) {
|
public String getProperty (String name) {
|
||||||
if (System.currentTimeMillis () - lastcheck > cacheTime)
|
if (System.currentTimeMillis () - lastcheck > 1500l)
|
||||||
checkFile ();
|
checkFile ();
|
||||||
return props.getProperty (name.toLowerCase());
|
return props.getProperty (name.toLowerCase());
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getProperty (String name, String defaultValue) {
|
public String getProperty (String name, String defaultValue) {
|
||||||
if (System.currentTimeMillis () - lastcheck > cacheTime)
|
if (System.currentTimeMillis () - lastcheck > 1500l)
|
||||||
checkFile ();
|
checkFile ();
|
||||||
return props.getProperty (name.toLowerCase(), defaultValue);
|
return props.getProperty (name.toLowerCase(), defaultValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Enumeration keys () {
|
public Enumeration keys () {
|
||||||
if (System.currentTimeMillis () - lastcheck > cacheTime)
|
if (System.currentTimeMillis () - lastcheck > 1500l)
|
||||||
checkFile ();
|
checkFile ();
|
||||||
return props.keys();
|
return props.keys();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Enumeration elements () {
|
public Enumeration elements () {
|
||||||
if (System.currentTimeMillis () - lastcheck > cacheTime)
|
if (System.currentTimeMillis () - lastcheck > 1500l)
|
||||||
checkFile ();
|
checkFile ();
|
||||||
return props.elements();
|
return props.elements();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int size() {
|
|
||||||
if (System.currentTimeMillis () - lastcheck > cacheTime)
|
|
||||||
checkFile ();
|
|
||||||
return props.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString () {
|
|
||||||
return props.toString ();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
// ApplicationManager.java
|
// ApplicationManager.java
|
||||||
// Copyright (c) Hannes Wallnöfer 1998-2000
|
// Copyright (c) Hannes Wallnöfer 1998-2000
|
||||||
|
|
||||||
package helma.main;
|
package helma.objectmodel.db;
|
||||||
|
|
||||||
import java.util.Hashtable;
|
import java.util.*;
|
||||||
import java.util.Enumeration;
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.lang.reflect.*;
|
import java.lang.reflect.*;
|
||||||
import java.rmi.*;
|
import java.rmi.*;
|
||||||
|
@ -13,27 +12,27 @@ import helma.framework.*;
|
||||||
import helma.framework.core.*;
|
import helma.framework.core.*;
|
||||||
import helma.objectmodel.*;
|
import helma.objectmodel.*;
|
||||||
import helma.servlet.*;
|
import helma.servlet.*;
|
||||||
import helma.util.SystemProperties;
|
|
||||||
import Acme.Serve.*;
|
import Acme.Serve.*;
|
||||||
import javax.servlet.Servlet;
|
import javax.servlet.Servlet;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is responsible for starting and stopping Helma applications.
|
* This class is responsible for starting and stopping HOP applications.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class ApplicationManager {
|
public class ApplicationManager {
|
||||||
|
|
||||||
private Hashtable applications;
|
private Hashtable applications;
|
||||||
private int port;
|
private int port;
|
||||||
private File hopHome;
|
private File appHome, dbHome;
|
||||||
private SystemProperties props;
|
private SystemProperties props;
|
||||||
private Server server;
|
private Server server;
|
||||||
private long lastModified;
|
private long lastModified;
|
||||||
|
|
||||||
public ApplicationManager (int port, File hopHome, SystemProperties props, Server server) {
|
public ApplicationManager (int port, File appHome, File dbHome, SystemProperties props, Server server) {
|
||||||
this.port = port;
|
this.port = port;
|
||||||
this.hopHome = hopHome;
|
this.appHome = appHome;
|
||||||
|
this.dbHome = dbHome;
|
||||||
this.props = props;
|
this.props = props;
|
||||||
this.server = server;
|
this.server = server;
|
||||||
applications = new Hashtable ();
|
applications = new Hashtable ();
|
||||||
|
@ -60,65 +59,60 @@ public class ApplicationManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception mx) {
|
} catch (Exception mx) {
|
||||||
Server.getLogger().log ("Error starting applications: "+mx);
|
IServer.getLogger().log ("Error starting applications: "+mx);
|
||||||
}
|
}
|
||||||
|
|
||||||
lastModified = System.currentTimeMillis ();
|
lastModified = System.currentTimeMillis ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void start (String appName) {
|
|
||||||
Server.getLogger().log ("Building application "+appName);
|
private void start (String appName) {
|
||||||
|
IServer.getLogger().log ("Building application "+appName);
|
||||||
try {
|
try {
|
||||||
Application app = new Application (appName, hopHome, Server.sysProps, Server.dbProps);
|
Application app = new Application (appName, dbHome, appHome);
|
||||||
applications.put (appName, app);
|
applications.put (appName, app);
|
||||||
// if we're running with the embedded web server, set app base uri to /appname
|
// if we're running with the embedded web server, set app base uri to /appname
|
||||||
if (server.websrv != null && !"base".equalsIgnoreCase (appName))
|
if (server.websrv != null)
|
||||||
app.setBaseURI ("/"+java.net.URLEncoder.encode (appName));
|
app.setBaseURI ("/"+java.net.URLEncoder.encode (appName));
|
||||||
// the application is started later in the register method, when it's bound
|
app.start ();
|
||||||
app.init ();
|
|
||||||
} catch (Exception x) {
|
} catch (Exception x) {
|
||||||
Server.getLogger().log ("Error creating application "+appName+": "+x);
|
IServer.getLogger().log ("Error creating application "+appName+": "+x);
|
||||||
x.printStackTrace ();
|
x.printStackTrace ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void stop (String appName) {
|
private void stop (String appName) {
|
||||||
Server.getLogger().log ("Stopping application "+appName);
|
IServer.getLogger().log ("Stopping application "+appName);
|
||||||
try {
|
try {
|
||||||
Application app = (Application) applications.get (appName);
|
Application app = (Application) applications.get (appName);
|
||||||
if (server.websrv == null) {
|
if (server.websrv == null) {
|
||||||
Naming.unbind ("//:"+port+"/"+appName);
|
Naming.unbind ("//:"+port+"/"+appName);
|
||||||
} else {
|
} else {
|
||||||
// server.websrv.removeServlet ("/"+appName+"/");
|
server.websrv.removeServlet ("/"+appName+"/");
|
||||||
server.websrv.removeServlet ("/"+appName+"/*");
|
server.websrv.removeServlet ("/"+appName+"/*");
|
||||||
}
|
}
|
||||||
app.stop ();
|
app.stop ();
|
||||||
Server.getLogger().log ("Unregistered application "+appName);
|
IServer.getLogger().log ("Unregistered application "+appName);
|
||||||
} catch (Exception x) {
|
} catch (Exception x) {
|
||||||
Server.getLogger().log ("Couldn't unregister app: "+x);
|
IServer.getLogger().log ("Couldn't unregister app: "+x);
|
||||||
}
|
}
|
||||||
applications.remove (appName);
|
applications.remove (appName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void register (String appName) {
|
private void register (String appName) {
|
||||||
try {
|
try {
|
||||||
Server.getLogger().log ("Binding application "+appName);
|
IServer.getLogger().log ("Binding application "+appName);
|
||||||
Application app = (Application) applications.get (appName);
|
Application app = (Application) applications.get (appName);
|
||||||
if (server.websrv == null) {
|
if (server.websrv == null) {
|
||||||
Naming.rebind ("//:"+port+"/"+appName, app);
|
Naming.rebind ("//:"+port+"/"+appName, app);
|
||||||
} else {
|
} else {
|
||||||
AcmeServletClient servlet = new AcmeServletClient (app);
|
AcmeServletClient servlet = new AcmeServletClient (app);
|
||||||
if ("base".equalsIgnoreCase (appName))
|
server.websrv.addServlet ("/"+appName+"/", servlet);
|
||||||
server.websrv.setDefaultServlet (servlet);
|
server.websrv.addServlet ("/"+appName+"/*", servlet);
|
||||||
else {
|
|
||||||
// server.websrv.addServlet ("/"+appName+"/", servlet);
|
|
||||||
server.websrv.addServlet ("/"+appName+"/*", servlet);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
app.start ();
|
|
||||||
} catch (Exception x) {
|
} catch (Exception x) {
|
||||||
Server.getLogger().log ("Couldn't register and start app: "+x);
|
IServer.getLogger().log ("Couldn't register app: "+x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,27 +128,16 @@ public class ApplicationManager {
|
||||||
}
|
}
|
||||||
if (server.websrv != null) {
|
if (server.websrv != null) {
|
||||||
File staticContent = new File (server.getHopHome(), "static");
|
File staticContent = new File (server.getHopHome(), "static");
|
||||||
Server.getLogger().log("Serving static content from "+staticContent.getAbsolutePath());
|
IServer.getLogger().log("Serving static content from "+staticContent.getAbsolutePath());
|
||||||
AcmeFileServlet fsrv = new AcmeFileServlet (staticContent);
|
AcmeFileServlet fsrv = new AcmeFileServlet (staticContent);
|
||||||
server.websrv.addServlet ("/static/", fsrv);
|
server.websrv.addServlet ("/static/", fsrv);
|
||||||
server.websrv.addServlet ("/static/*", fsrv);
|
server.websrv.addServlet ("/static/*", fsrv);
|
||||||
}
|
}
|
||||||
lastModified = System.currentTimeMillis ();
|
lastModified = System.currentTimeMillis ();
|
||||||
} catch (Exception mx) {
|
} catch (Exception mx) {
|
||||||
Server.getLogger().log ("Error starting applications: "+mx);
|
IServer.getLogger().log ("Error starting applications: "+mx);
|
||||||
mx.printStackTrace ();
|
mx.printStackTrace ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get an enumeration of all currently running applications.
|
|
||||||
*/
|
|
||||||
public Object[] getApplications () {
|
|
||||||
return applications.values ().toArray ();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Application getApplication(String name) {
|
|
||||||
return (Application)applications.get(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,130 +0,0 @@
|
||||||
// DbKey.java
|
|
||||||
// Copyright (c) Hannes Wallnöfer 1998-2000
|
|
||||||
|
|
||||||
package helma.objectmodel.db;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is the internal representation of a database key. It is constructed
|
|
||||||
* out of the database URL, the table name, the user name and the database
|
|
||||||
* key of the node and unique within each Helma application. 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;
|
|
||||||
|
|
||||||
// lazily initialized hashcode
|
|
||||||
private transient int hashcode = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
try {
|
|
||||||
DbKey k = (DbKey) what;
|
|
||||||
return (storageName == k.storageName || storageName.equals (k.storageName)) &&
|
|
||||||
(id == k.id || id.equals (k.id));
|
|
||||||
} catch (Exception x) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int hashCode () {
|
|
||||||
if (hashcode == 0) {
|
|
||||||
hashcode = storageName == null ?
|
|
||||||
17 + 37*id.hashCode () :
|
|
||||||
17 + 37*storageName.hashCode() + +37*id.hashCode ();
|
|
||||||
}
|
|
||||||
return hashcode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Key getParentKey () {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getStorageName () {
|
|
||||||
return storageName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getID () {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString () {
|
|
||||||
return storageName == null ? "["+id+"]" : storageName+"["+id+"]";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,725 +0,0 @@
|
||||||
// DbMapping.java
|
|
||||||
// Copyright (c) Hannes Wallnöfer 1998-2000
|
|
||||||
|
|
||||||
package helma.objectmodel.db;
|
|
||||||
|
|
||||||
import helma.framework.core.Application;
|
|
||||||
import helma.util.Updatable;
|
|
||||||
import helma.util.SystemProperties;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Enumeration;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.StringTokenizer;
|
|
||||||
import java.sql.*;
|
|
||||||
import com.workingdogs.village.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A DbMapping describes how a certain type of Nodes is to mapped to a
|
|
||||||
* relational database table. Basically it consists of a set of JavaScript property-to-
|
|
||||||
* Database row bindings which are represented by instances of the Relation class.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class DbMapping implements Updatable {
|
|
||||||
|
|
||||||
// DbMappings belong to an application
|
|
||||||
Application app;
|
|
||||||
// prototype name of this mapping
|
|
||||||
String typename;
|
|
||||||
|
|
||||||
int version;
|
|
||||||
|
|
||||||
// properties from where the mapping is read
|
|
||||||
SystemProperties props;
|
|
||||||
|
|
||||||
// name of data source to which this mapping writes
|
|
||||||
DbSource source;
|
|
||||||
// name of datasource
|
|
||||||
String sourceName;
|
|
||||||
// name of db table
|
|
||||||
String table;
|
|
||||||
|
|
||||||
// list of properties to try for parent
|
|
||||||
ParentInfo[] parent;
|
|
||||||
|
|
||||||
// Relations describing subnodes and properties.
|
|
||||||
Relation subnodesRel;
|
|
||||||
Relation propertiesRel;
|
|
||||||
|
|
||||||
// if this defines a subnode mapping with groupby layer, we need a DbMapping for those groupby nodes
|
|
||||||
DbMapping groupbyMapping;
|
|
||||||
|
|
||||||
// Map of property names to Relations objects
|
|
||||||
HashMap prop2db;
|
|
||||||
// Map of db columns to Relations objects
|
|
||||||
HashMap db2prop;
|
|
||||||
|
|
||||||
// db field used as primary key
|
|
||||||
private String idField;
|
|
||||||
// db field used as object name
|
|
||||||
String nameField;
|
|
||||||
// db field used to identify name of prototype to use for object instantiation
|
|
||||||
String protoField;
|
|
||||||
|
|
||||||
// name of parent prototype, if any
|
|
||||||
String extendsProto;
|
|
||||||
// dbmapping of parent prototype, if any
|
|
||||||
DbMapping parentMapping;
|
|
||||||
|
|
||||||
// db field that specifies the prototype of an object
|
|
||||||
String prototypeField;
|
|
||||||
|
|
||||||
// descriptor for key generation method
|
|
||||||
private String idgen;
|
|
||||||
// remember last key generated for this table
|
|
||||||
long lastID;
|
|
||||||
|
|
||||||
// the (village) schema of the database table
|
|
||||||
Schema schema = null;
|
|
||||||
// the (village) keydef of the db table
|
|
||||||
KeyDef keydef = null;
|
|
||||||
|
|
||||||
// timestamp of last modification of the mapping (type.properties)
|
|
||||||
long lastTypeChange;
|
|
||||||
// timestamp of last modification of an object of this type
|
|
||||||
long lastDataChange;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an empty DbMapping
|
|
||||||
*/
|
|
||||||
public DbMapping (Application app) {
|
|
||||||
|
|
||||||
this.app = app;
|
|
||||||
|
|
||||||
prop2db = new HashMap ();
|
|
||||||
db2prop = new HashMap ();
|
|
||||||
|
|
||||||
parent = null;
|
|
||||||
|
|
||||||
idField = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a DbMapping from a type.properties property file
|
|
||||||
*/
|
|
||||||
public DbMapping (Application app, String typename, SystemProperties props) {
|
|
||||||
|
|
||||||
this.app = app;
|
|
||||||
this.typename = typename;
|
|
||||||
|
|
||||||
prop2db = new HashMap ();
|
|
||||||
db2prop = new HashMap ();
|
|
||||||
|
|
||||||
parent = null;
|
|
||||||
|
|
||||||
idField = null;
|
|
||||||
|
|
||||||
this.props = props;
|
|
||||||
update ();
|
|
||||||
|
|
||||||
app.putDbMapping (typename, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tell the type manager whether we need update() to be called
|
|
||||||
*/
|
|
||||||
public boolean needsUpdate () {
|
|
||||||
return props.lastModified () != lastTypeChange;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read the mapping from the Properties. Return true if the properties were changed.
|
|
||||||
* The read is split in two, this method and the rewire method. The reason is that in order
|
|
||||||
* for rewire to work, all other db mappings must have been initialized and registered.
|
|
||||||
*/
|
|
||||||
public synchronized void update () {
|
|
||||||
|
|
||||||
// determin file format version of type.properties file
|
|
||||||
String versionInfo = props.getProperty ("_version");
|
|
||||||
if ("1.2".equals (versionInfo))
|
|
||||||
version = 1;
|
|
||||||
else
|
|
||||||
version = 0;
|
|
||||||
|
|
||||||
table = props.getProperty (version == 0 ? "_tablename" : "_table");
|
|
||||||
idgen = props.getProperty ("_idgen");
|
|
||||||
// see if there is a field which specifies the prototype of objects, if different prototypes
|
|
||||||
// can be stored in this table
|
|
||||||
prototypeField = props.getProperty ("_prototypefield");
|
|
||||||
// see if this prototype extends (inherits from) any other prototype
|
|
||||||
extendsProto = props.getProperty ("_extends");
|
|
||||||
|
|
||||||
sourceName = props.getProperty (version == 0 ? "_datasource" : "_db");
|
|
||||||
if (sourceName != null) {
|
|
||||||
source = app.getDbSource (sourceName);
|
|
||||||
if (source == null) {
|
|
||||||
app.logEvent ("*** Data Source for prototype "+typename+" does not exist: "+sourceName);
|
|
||||||
app.logEvent ("*** accessing or storing a "+typename+" object will cause an error.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if id field is null, we assume "ID" as default. We don't set it
|
|
||||||
// however, so that if null we check the parent prototype first.
|
|
||||||
idField = props.getProperty ("_id");
|
|
||||||
|
|
||||||
nameField = props.getProperty ("_name");
|
|
||||||
|
|
||||||
protoField = props.getProperty ("_prototype");
|
|
||||||
|
|
||||||
String parentMapping = props.getProperty ("_parent");
|
|
||||||
if (parentMapping != null) {
|
|
||||||
// comma-separated list of properties to be used as parent
|
|
||||||
StringTokenizer st = new StringTokenizer (parentMapping, ",;");
|
|
||||||
parent = new ParentInfo[st.countTokens()];
|
|
||||||
for (int i=0; i<parent.length; i++)
|
|
||||||
parent[i] = new ParentInfo (st.nextToken().trim());
|
|
||||||
} else
|
|
||||||
parent = null;
|
|
||||||
|
|
||||||
lastTypeChange = props.lastModified ();
|
|
||||||
// set the cached schema & keydef to null so it's rebuilt the next time around
|
|
||||||
schema = null;
|
|
||||||
keydef = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is the second part of the property reading process, called after the first part has been
|
|
||||||
* completed on all other mappings in this application
|
|
||||||
*/
|
|
||||||
public synchronized void rewire () {
|
|
||||||
if (extendsProto != null) {
|
|
||||||
parentMapping = app.getDbMapping (extendsProto);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if (table != null && source != null) {
|
|
||||||
// app.logEvent ("set data source for "+typename+" to "+source);
|
|
||||||
HashMap p2d = new HashMap ();
|
|
||||||
HashMap d2p = new HashMap ();
|
|
||||||
|
|
||||||
for (Enumeration e=props.keys(); e.hasMoreElements(); ) {
|
|
||||||
String propName = (String) e.nextElement ();
|
|
||||||
|
|
||||||
try {
|
|
||||||
// ignore internal properties (starting with "_") and sub-options (containing a ".")
|
|
||||||
if (!propName.startsWith ("_") && propName.indexOf (".") < 0) {
|
|
||||||
String dbField = props.getProperty (propName);
|
|
||||||
// check if a relation for this propery already exists. If so, reuse it
|
|
||||||
Relation rel = propertyToRelation (propName);
|
|
||||||
if (rel == null)
|
|
||||||
rel = new Relation (dbField, propName, this, props);
|
|
||||||
rel.update (dbField, props, version);
|
|
||||||
p2d.put (propName, rel);
|
|
||||||
if (rel.columnName != null &&
|
|
||||||
(rel.reftype == Relation.PRIMITIVE ||
|
|
||||||
rel.reftype == Relation.REFERENCE))
|
|
||||||
d2p.put (rel.columnName.toUpperCase (), rel);
|
|
||||||
// app.logEvent ("Mapping "+propName+" -> "+dbField);
|
|
||||||
}
|
|
||||||
} catch (Exception x) {
|
|
||||||
app.logEvent ("Error in type.properties: "+x.getMessage ());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
prop2db = p2d;
|
|
||||||
db2prop = d2p;
|
|
||||||
|
|
||||||
if (version == 1) {
|
|
||||||
String subnodeMapping = props.getProperty ("_children");
|
|
||||||
if (subnodeMapping != null) {
|
|
||||||
try {
|
|
||||||
// check if subnode relation already exists. If so, reuse it
|
|
||||||
if (subnodesRel == null)
|
|
||||||
subnodesRel = new Relation (subnodeMapping, "_children", this, props);
|
|
||||||
subnodesRel.update (subnodeMapping, props, version);
|
|
||||||
if (subnodesRel.accessor != null)
|
|
||||||
propertiesRel = subnodesRel;
|
|
||||||
|
|
||||||
} catch (Exception x) {
|
|
||||||
app.logEvent ("Error reading _subnodes relation for "+typename+": "+x.getMessage ());
|
|
||||||
// subnodesRel = null;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
subnodesRel = null;
|
|
||||||
} else {
|
|
||||||
String subnodeMapping = props.getProperty ("_subnodes");
|
|
||||||
if (subnodeMapping != null) {
|
|
||||||
try {
|
|
||||||
// check if subnode relation already exists. If so, reuse it
|
|
||||||
if (subnodesRel == null)
|
|
||||||
subnodesRel = new Relation (subnodeMapping, "_subnodes", this, props);
|
|
||||||
subnodesRel.update (subnodeMapping, props, version);
|
|
||||||
|
|
||||||
} catch (Exception x) {
|
|
||||||
app.logEvent ("Error reading _subnodes relation for "+typename+": "+x.getMessage ());
|
|
||||||
// subnodesRel = null;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
subnodesRel = null;
|
|
||||||
|
|
||||||
String propertiesMapping = props.getProperty ("_properties");
|
|
||||||
if (propertiesMapping != null) {
|
|
||||||
try {
|
|
||||||
// check if property relation already exists. If so, reuse it
|
|
||||||
if (propertiesRel == null)
|
|
||||||
propertiesRel = new Relation (propertiesMapping, "_properties", this, props);
|
|
||||||
propertiesRel.update (propertiesMapping, props, version);
|
|
||||||
|
|
||||||
// take over groupby flag from subnodes, if properties are subnodes
|
|
||||||
if (propertiesRel.subnodesAreProperties && subnodesRel != null) {
|
|
||||||
propertiesRel.groupby = subnodesRel.groupby;
|
|
||||||
propertiesRel.constraints = subnodesRel.constraints;
|
|
||||||
propertiesRel.filter = subnodesRel.filter;
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (Exception x) {
|
|
||||||
app.logEvent ("Error reading _properties relation for "+typename+": "+x.getMessage ());
|
|
||||||
// propertiesRel = null;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
propertiesRel = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (groupbyMapping != null) {
|
|
||||||
initGroupbyMapping ();
|
|
||||||
groupbyMapping.lastTypeChange = this.lastTypeChange;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a JDBC connection for this DbMapping.
|
|
||||||
*/
|
|
||||||
public Connection getConnection () throws ClassNotFoundException, SQLException {
|
|
||||||
// if source was previously not available, check again
|
|
||||||
if (source == null && sourceName != null)
|
|
||||||
source = app.getDbSource (sourceName);
|
|
||||||
if (sourceName == null && parentMapping != null)
|
|
||||||
return parentMapping.getConnection ();
|
|
||||||
if (source == null) {
|
|
||||||
if (sourceName == null)
|
|
||||||
throw new SQLException ("Tried to get Connection from non-relational embedded data source.");
|
|
||||||
else
|
|
||||||
throw new SQLException ("Datasource is not defined: "+sourceName+".");
|
|
||||||
}
|
|
||||||
return source.getConnection ();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the DbSource object for this DbMapping. The DbSource describes a JDBC
|
|
||||||
* data source including URL, JDBC driver, username and password.
|
|
||||||
*/
|
|
||||||
public DbSource getDbSource () {
|
|
||||||
if (source == null && parentMapping != null)
|
|
||||||
return parentMapping.getDbSource ();
|
|
||||||
return source;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the URL of the data source used for this mapping.
|
|
||||||
*/
|
|
||||||
public String getSourceID () {
|
|
||||||
if (source == null && parentMapping != null)
|
|
||||||
return parentMapping.getSourceID ();
|
|
||||||
return source == null ? "" : source.url;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the table name used for this type mapping.
|
|
||||||
*/
|
|
||||||
public String getTableName () {
|
|
||||||
if (source == null && parentMapping != null)
|
|
||||||
return parentMapping.getTableName ();
|
|
||||||
return table;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the application this DbMapping belongs to.
|
|
||||||
*/
|
|
||||||
public Application getApplication () {
|
|
||||||
return app;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the name of this mapping's application
|
|
||||||
*/
|
|
||||||
public String getAppName () {
|
|
||||||
return app.getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the name of the object type this DbMapping belongs to.
|
|
||||||
*/
|
|
||||||
public String getTypeName () {
|
|
||||||
return typename;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the name of this type's parent type, if any.
|
|
||||||
*/
|
|
||||||
public String getExtends () {
|
|
||||||
return extendsProto;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the primary key column name for objects using this mapping.
|
|
||||||
*/
|
|
||||||
public String getIDField () {
|
|
||||||
if (idField == null && parentMapping != null)
|
|
||||||
return parentMapping.getIDField ();
|
|
||||||
return idField == null ? "ID" : idField;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the column used for (internal) names of objects of this type.
|
|
||||||
*/
|
|
||||||
public String getNameField () {
|
|
||||||
if (nameField == null && parentMapping != null)
|
|
||||||
return parentMapping.getNameField ();
|
|
||||||
return nameField;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the column used for names of prototype.
|
|
||||||
*/
|
|
||||||
public String getPrototypeField () {
|
|
||||||
if (protoField == null && parentMapping != null)
|
|
||||||
return parentMapping.getPrototypeField ();
|
|
||||||
return protoField;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Translate a database column name to an object property name according to this mapping.
|
|
||||||
*/
|
|
||||||
public String columnNameToProperty (String columnName) {
|
|
||||||
if (columnName == null)
|
|
||||||
return null;
|
|
||||||
if (table == null && parentMapping != null)
|
|
||||||
return parentMapping.columnNameToProperty (columnName);
|
|
||||||
Relation rel = (Relation) db2prop.get (columnName.toUpperCase ());
|
|
||||||
if (rel != null && (rel.reftype == Relation.PRIMITIVE || rel.reftype == Relation.REFERENCE))
|
|
||||||
return rel.propName;
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Translate an object property name to a database column name according to this mapping.
|
|
||||||
*/
|
|
||||||
public String propertyToColumnName (String propName) {
|
|
||||||
if (propName == null)
|
|
||||||
return null;
|
|
||||||
if (table == null && parentMapping != null)
|
|
||||||
return parentMapping.propertyToColumnName (propName);
|
|
||||||
Relation rel = (Relation) prop2db.get (propName);
|
|
||||||
if (rel != null && (rel.reftype == Relation.PRIMITIVE || rel.reftype == Relation.REFERENCE))
|
|
||||||
return rel.columnName;
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Translate a database column name to an object property name according to this mapping.
|
|
||||||
*/
|
|
||||||
public Relation columnNameToRelation (String columnName) {
|
|
||||||
if (columnName == null)
|
|
||||||
return null;
|
|
||||||
if (table == null && parentMapping != null)
|
|
||||||
return parentMapping.columnNameToRelation (columnName);
|
|
||||||
return (Relation) db2prop.get (columnName.toUpperCase ());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Translate an object property name to a database column name according to this mapping.
|
|
||||||
*/
|
|
||||||
public Relation propertyToRelation (String propName) {
|
|
||||||
if (propName == null)
|
|
||||||
return null;
|
|
||||||
if (table == null && parentMapping != null)
|
|
||||||
return parentMapping.propertyToRelation (propName);
|
|
||||||
return (Relation) prop2db.get (propName);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This returns the parent info array, which tells an object of this type how to
|
|
||||||
* determine its parent object.
|
|
||||||
*/
|
|
||||||
public synchronized ParentInfo[] getParentInfo () {
|
|
||||||
if (parent == null && parentMapping != null)
|
|
||||||
return parentMapping.getParentInfo ();
|
|
||||||
return parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public DbMapping getSubnodeMapping () {
|
|
||||||
if (subnodesRel != null)
|
|
||||||
return subnodesRel.otherType;
|
|
||||||
if (parentMapping != null)
|
|
||||||
return parentMapping.getSubnodeMapping ();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public DbMapping getExactPropertyMapping (String propname) {
|
|
||||||
Relation rel = getExactPropertyRelation (propname);
|
|
||||||
return rel != null ? rel.otherType : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DbMapping getPropertyMapping (String propname) {
|
|
||||||
Relation rel = getPropertyRelation (propname);
|
|
||||||
if (rel != null) {
|
|
||||||
// if this is a virtual node, it doesn't have a dbmapping
|
|
||||||
if (rel.virtual && rel.prototype == null)
|
|
||||||
return null;
|
|
||||||
else
|
|
||||||
return rel.otherType;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If subnodes are grouped by one of their properties, return the
|
|
||||||
* db-mapping with the right relations to create the group-by nodes
|
|
||||||
*/
|
|
||||||
public synchronized DbMapping getGroupbyMapping () {
|
|
||||||
if (subnodesRel == null || subnodesRel.groupby == null)
|
|
||||||
return null;
|
|
||||||
if (groupbyMapping == null) {
|
|
||||||
initGroupbyMapping ();
|
|
||||||
}
|
|
||||||
return groupbyMapping;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize the dbmapping used for group-by nodes.
|
|
||||||
*/
|
|
||||||
private void initGroupbyMapping () {
|
|
||||||
// if a prototype is defined for groupby nodes, use that
|
|
||||||
// if mapping doesn' exist or isn't defined, create a new (anonymous internal) one
|
|
||||||
groupbyMapping = new DbMapping (app);
|
|
||||||
// If a mapping is defined, make the internal mapping inherit from
|
|
||||||
// the defined named prototype.
|
|
||||||
if (subnodesRel.groupbyprototype != null)
|
|
||||||
groupbyMapping.parentMapping = app.getDbMapping (subnodesRel.groupbyprototype);
|
|
||||||
groupbyMapping.subnodesRel = subnodesRel.getGroupbySubnodeRelation ();
|
|
||||||
if (propertiesRel != null)
|
|
||||||
groupbyMapping.propertiesRel = propertiesRel.getGroupbyPropertyRelation ();
|
|
||||||
else
|
|
||||||
groupbyMapping.propertiesRel = subnodesRel.getGroupbyPropertyRelation ();
|
|
||||||
groupbyMapping.typename = subnodesRel.groupbyprototype;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* public void setPropertyMapping (DbMapping pm) {
|
|
||||||
properties = pm;
|
|
||||||
} */
|
|
||||||
|
|
||||||
/* public void setSubnodeRelation (Relation rel) {
|
|
||||||
subnodesRel = rel;
|
|
||||||
} */
|
|
||||||
|
|
||||||
public void setPropertyRelation (Relation rel) {
|
|
||||||
propertiesRel = rel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Relation getSubnodeRelation () {
|
|
||||||
if (subnodesRel == null && parentMapping != null)
|
|
||||||
return parentMapping.getSubnodeRelation ();
|
|
||||||
return subnodesRel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Relation getPropertyRelation () {
|
|
||||||
if (propertiesRel == null && parentMapping != null)
|
|
||||||
return parentMapping.getPropertyRelation ();
|
|
||||||
return propertiesRel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Relation getPropertyRelation (String propname) {
|
|
||||||
if (propname == null)
|
|
||||||
return getPropertyRelation ();
|
|
||||||
// first try finding an exact match for the property name
|
|
||||||
Relation rel = getExactPropertyRelation (propname);
|
|
||||||
// if not defined, return the generic property mapping
|
|
||||||
if (rel == null)
|
|
||||||
rel = getPropertyRelation ();
|
|
||||||
return rel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Relation getExactPropertyRelation (String propname) {
|
|
||||||
if (propname == null)
|
|
||||||
return null;
|
|
||||||
Relation rel = (Relation) prop2db.get (propname.toLowerCase());
|
|
||||||
if (rel == null && parentMapping != null)
|
|
||||||
rel = parentMapping.getExactPropertyRelation (propname);
|
|
||||||
return rel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSubnodeGroupby () {
|
|
||||||
if (subnodesRel == null && parentMapping != null)
|
|
||||||
return parentMapping.getSubnodeGroupby ();
|
|
||||||
return subnodesRel == null ? null : subnodesRel.groupby;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getIDgen () {
|
|
||||||
if (idgen == null && parentMapping != null)
|
|
||||||
return parentMapping.getIDgen ();
|
|
||||||
return idgen;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public WrappedNodeManager getWrappedNodeManager () {
|
|
||||||
if (app == null)
|
|
||||||
throw new RuntimeException ("Can't get node manager from internal db mapping");
|
|
||||||
return app.getWrappedNodeManager ();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tell whether this data mapping maps to a relational database table. This returns true
|
|
||||||
* if a datasource is specified, even if it is not a valid one. Otherwise, objects with invalid
|
|
||||||
* mappings would be stored in the embedded db instead of an error being thrown, which is
|
|
||||||
* not what we want.
|
|
||||||
*/
|
|
||||||
public boolean isRelational () {
|
|
||||||
if (sourceName != null)
|
|
||||||
return true;
|
|
||||||
if (parentMapping != null)
|
|
||||||
return parentMapping.isRelational ();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a Village Schema object for this DbMapping.
|
|
||||||
*/
|
|
||||||
public synchronized Schema getSchema () throws ClassNotFoundException, SQLException, DataSetException {
|
|
||||||
if (!isRelational ())
|
|
||||||
throw new SQLException ("Can't get Schema for non-relational data mapping");
|
|
||||||
if (source == null && parentMapping != null)
|
|
||||||
return parentMapping.getSchema ();
|
|
||||||
// Use local variable s to avoid synchronization (schema may be nulled elsewhere)
|
|
||||||
Schema s = schema;
|
|
||||||
if (s != null)
|
|
||||||
return s;
|
|
||||||
schema = new Schema ().schema (getConnection (), table, "*");
|
|
||||||
return schema;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return true if the column identified by the parameter is a string type. This is
|
|
||||||
* used in query building to determine if a value needs to be quoted.
|
|
||||||
*/
|
|
||||||
public boolean isStringColumn (String columnName) throws SQLException {
|
|
||||||
try {
|
|
||||||
Schema s = getSchema ();
|
|
||||||
if (s == null)
|
|
||||||
throw new SQLException ("Error retrieving relational schema for "+this);
|
|
||||||
Column c = s.getColumn (columnName);
|
|
||||||
if (c == null)
|
|
||||||
throw new SQLException ("Column "+columnName+" not found in "+this);
|
|
||||||
return c.isString () || c.isVarBinary () || c.isLongVarBinary ();
|
|
||||||
} catch (Exception x) {
|
|
||||||
throw new SQLException (x.getMessage ());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a Village Schema object for this DbMapping.
|
|
||||||
*/
|
|
||||||
public synchronized KeyDef getKeyDef () {
|
|
||||||
if (!isRelational ())
|
|
||||||
throw new RuntimeException ("Can't get KeyDef for non-relational data mapping");
|
|
||||||
if (source == null && parentMapping != null)
|
|
||||||
return parentMapping.getKeyDef ();
|
|
||||||
// Use local variable s to avoid synchronization (keydef may be nulled elsewhere)
|
|
||||||
KeyDef k = keydef;
|
|
||||||
if (k != null)
|
|
||||||
return k;
|
|
||||||
keydef = new KeyDef ().addAttrib (getIDField ());
|
|
||||||
return keydef;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString () {
|
|
||||||
if (typename == null)
|
|
||||||
return "[unspecified internal DbMapping]";
|
|
||||||
else
|
|
||||||
return ("["+app.getName()+"."+typename+"]");
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getLastTypeChange () {
|
|
||||||
return lastTypeChange;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public long getLastDataChange () {
|
|
||||||
return lastDataChange;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void notifyDataChange () {
|
|
||||||
lastDataChange = System.currentTimeMillis ();
|
|
||||||
if (parentMapping != null && source == null)
|
|
||||||
parentMapping.notifyDataChange ();
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized long getNewID (long dbmax) {
|
|
||||||
if (parentMapping != null && source == null)
|
|
||||||
return parentMapping.getNewID (dbmax);
|
|
||||||
lastID = Math.max (dbmax+1, lastID+1);
|
|
||||||
return lastID;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HashMap getProp2DB () {
|
|
||||||
if (table == null && parentMapping != null)
|
|
||||||
return parentMapping.getProp2DB ();
|
|
||||||
return prop2db;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Iterator getDBPropertyIterator () {
|
|
||||||
if (table == null && parentMapping != null)
|
|
||||||
return parentMapping.getDBPropertyIterator ();
|
|
||||||
return db2prop.values ().iterator ();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the name of the prototype which specifies the storage location
|
|
||||||
* (dbsource + tablename) for this type, or null if it is stored in the embedded
|
|
||||||
* db.
|
|
||||||
*/
|
|
||||||
public String getStorageTypeName () {
|
|
||||||
if (table == null && parentMapping != null)
|
|
||||||
return parentMapping.getStorageTypeName ();
|
|
||||||
return sourceName == null ? null : typename;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tell if another DbMapping is storage-compatible to this one, i.e. it is stored in the same table or
|
|
||||||
* embedded database.
|
|
||||||
*/
|
|
||||||
public boolean isStorageCompatible (DbMapping other) {
|
|
||||||
if (other == null)
|
|
||||||
return !isRelational ();
|
|
||||||
if (isRelational ())
|
|
||||||
return getTableName().equals (other.getTableName ()) &&
|
|
||||||
getDbSource().equals (other.getDbSource ());
|
|
||||||
return !other.isRelational ();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return true if this db mapping represents the prototype indicated
|
|
||||||
* by the string argument, either itself or via one of its parent prototypes.
|
|
||||||
*/
|
|
||||||
public boolean isInstanceOf (String other) {
|
|
||||||
if (typename != null && typename.equals (other))
|
|
||||||
return true;
|
|
||||||
DbMapping p = parentMapping;
|
|
||||||
while (p != null) {
|
|
||||||
if (p.typename != null && p.typename.equals (other))
|
|
||||||
return true;
|
|
||||||
p = p.parentMapping;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public DbMapping getParentMapping () {
|
|
||||||
return parentMapping;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,120 +0,0 @@
|
||||||
// DbSource.java
|
|
||||||
// Copyright (c) Hannes Wallnöfer 1999-2000
|
|
||||||
|
|
||||||
package helma.objectmodel.db;
|
|
||||||
|
|
||||||
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 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;
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName () {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void setDefaultProps (SystemProperties props) {
|
|
||||||
defaultProps = props;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -24,15 +24,13 @@ public class DbWrapper {
|
||||||
volatile long txncount=0;
|
volatile long txncount=0;
|
||||||
|
|
||||||
private File dbBaseDir;
|
private File dbBaseDir;
|
||||||
private NodeManager nmgr;
|
|
||||||
private String dbHome;
|
private String dbHome;
|
||||||
|
|
||||||
public DbWrapper (String dbHome, String dbFilename, NodeManager nmgr, boolean useTx) throws DbException {
|
public DbWrapper (String dbHome, String dbFilename, boolean useTx) throws DbException {
|
||||||
|
|
||||||
this.dbHome = dbHome;
|
|
||||||
this.nmgr = nmgr;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
this.dbHome = dbHome;
|
||||||
dbBaseDir = new File (dbHome);
|
dbBaseDir = new File (dbHome);
|
||||||
if (!dbBaseDir.exists())
|
if (!dbBaseDir.exists())
|
||||||
dbBaseDir.mkdirs();
|
dbBaseDir.mkdirs();
|
||||||
|
@ -73,12 +71,12 @@ public class DbWrapper {
|
||||||
loaded = true;
|
loaded = true;
|
||||||
|
|
||||||
} catch (NoClassDefFoundError noclass) {
|
} catch (NoClassDefFoundError noclass) {
|
||||||
nmgr.app.logEvent ("Warning: Using internal file based db as fallback.");
|
Server.getLogger().log ("Warning: Using internal file based db as fallback.");
|
||||||
nmgr.app.logEvent ("Reason: "+noclass);
|
Server.getLogger().log ("Reason: "+noclass);
|
||||||
loaded = false;
|
loaded = false;
|
||||||
} catch (UnsatisfiedLinkError nolib) {
|
} catch (UnsatisfiedLinkError nolib) {
|
||||||
nmgr.app.logEvent ("Warning: Using internal file based db as fallback.");
|
Server.getLogger().log ("Warning: Using internal file based db as fallback.");
|
||||||
nmgr.app.logEvent ("Reason: "+nolib);
|
Server.getLogger().log ("Reason: "+nolib);
|
||||||
loaded = false;
|
loaded = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,7 +89,7 @@ public class DbWrapper {
|
||||||
// closing the dbenv leads to segfault when app is restarted
|
// closing the dbenv leads to segfault when app is restarted
|
||||||
// dbenv.close (0);
|
// dbenv.close (0);
|
||||||
// dbenv.remove (dbHome, Db.DB_FORCE);
|
// dbenv.remove (dbHome, Db.DB_FORCE);
|
||||||
nmgr.app.logEvent ("Closed Berkeley DB");
|
Server.getLogger ().log ("Closed Berkeley DB");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,7 +126,7 @@ public class DbWrapper {
|
||||||
dbenv.txn_checkpoint (0, 0, 0); // for berkeley 3.0, remove third 0 parameter
|
dbenv.txn_checkpoint (0, 0, 0); // for berkeley 3.0, remove third 0 parameter
|
||||||
txncount = 0;
|
txncount = 0;
|
||||||
lastCheckpoint = now;
|
lastCheckpoint = now;
|
||||||
nmgr.app.logEvent ("Spent "+(System.currentTimeMillis()-now)+" in checkpoint");
|
Server.getLogger().log ("Spent "+(System.currentTimeMillis()-now)+" in checkpoint");
|
||||||
}
|
}
|
||||||
|
|
||||||
public IDGenerator getIDGenerator (DbTxn txn, String kstr) throws Exception {
|
public IDGenerator getIDGenerator (DbTxn txn, String kstr) throws Exception {
|
||||||
|
@ -222,7 +220,7 @@ public class DbWrapper {
|
||||||
value.set_size (vbuf.length);
|
value.set_size (vbuf.length);
|
||||||
|
|
||||||
db.put (txn, key, value, 0);
|
db.put (txn, key, value, 0);
|
||||||
// nmgr.app.logEvent ("saved "+obj+", size = "+vbuf.length);
|
// IServer.getLogger().log ("saved "+obj+", size = "+vbuf.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void deleteFromDB (DbTxn txn, String kstr) throws Exception {
|
private void deleteFromDB (DbTxn txn, String kstr) throws Exception {
|
||||||
|
|
|
@ -4,14 +4,14 @@
|
||||||
package helma.objectmodel.db;
|
package helma.objectmodel.db;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A subclass of Vector that implements the Externalizable interface in order
|
* A subclass of Vector that implements the Externalizable interface in order
|
||||||
* to be able to control how it is serialized and deserialized.
|
* to be able to control how it is serialized and deserialized.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class ExternalizableVector extends ArrayList implements Externalizable {
|
public class ExternalizableVector extends Vector implements Externalizable {
|
||||||
|
|
||||||
static final long serialVersionUID = 2316243615310540423L;
|
static final long serialVersionUID = 2316243615310540423L;
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ public class ExternalizableVector extends ArrayList implements Externalizable {
|
||||||
try {
|
try {
|
||||||
int size = in.readInt ();
|
int size = in.readInt ();
|
||||||
for (int i=0; i<size; i++)
|
for (int i=0; i<size; i++)
|
||||||
add (in.readObject ());
|
addElement (in.readObject ());
|
||||||
} catch (ClassNotFoundException x) {
|
} catch (ClassNotFoundException x) {
|
||||||
throw new IOException (x.toString ());
|
throw new IOException (x.toString ());
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ public class ExternalizableVector extends ArrayList implements Externalizable {
|
||||||
int size = size ();
|
int size = size ();
|
||||||
out.writeInt (size);
|
out.writeInt (size);
|
||||||
for (int i=0; i<size; i++)
|
for (int i=0; i<size; i++)
|
||||||
out.writeObject (get (i));
|
out.writeObject (elementAt (i));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,9 @@
|
||||||
// Copyright (c) Hannes Wallnöfer 1999-2000
|
// Copyright (c) Hannes Wallnöfer 1999-2000
|
||||||
|
|
||||||
|
|
||||||
package helma.main;
|
package helma.objectmodel.db;
|
||||||
|
|
||||||
|
import helma.objectmodel.IServer;
|
||||||
import helma.util.*;
|
import helma.util.*;
|
||||||
import java.net.*;
|
import java.net.*;
|
||||||
import java.rmi.server.*;
|
import java.rmi.server.*;
|
||||||
|
@ -27,7 +28,7 @@ public class HopSocketFactory extends RMISocketFactory {
|
||||||
try {
|
try {
|
||||||
filter.addAddress (address);
|
filter.addAddress (address);
|
||||||
} catch (IOException x) {
|
} catch (IOException x) {
|
||||||
Server.getLogger().log ("Could not add "+address+" to Socket Filter: invalid address.");
|
IServer.getLogger().log ("Could not add "+address+" to Socket Filter: invalid address.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,4 +40,4 @@ public class HopSocketFactory extends RMISocketFactory {
|
||||||
return new ParanoidServerSocket (port, filter);
|
return new ParanoidServerSocket (port, filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,74 +0,0 @@
|
||||||
// Key.java
|
|
||||||
// Copyright (c) Hannes Wallnöfer 1998-2000
|
|
||||||
|
|
||||||
package helma.objectmodel.db;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is the interface for the internal representation of an object key.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public interface Key {
|
|
||||||
|
|
||||||
|
|
||||||
public Key getParentKey ();
|
|
||||||
|
|
||||||
public String getID ();
|
|
||||||
|
|
||||||
public String getStorageName ();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,119 +0,0 @@
|
||||||
// NodeHandle.java
|
|
||||||
// Copyright (c) Hannes Wallnöfer 1998-2000
|
|
||||||
|
|
||||||
package helma.objectmodel.db;
|
|
||||||
|
|
||||||
import helma.objectmodel.*;
|
|
||||||
import java.io.Serializable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class is a handle or reference to a Node. This is to abstract from different
|
|
||||||
* methods of reference: Transient Nodes are referred to directly, while persistent
|
|
||||||
* nodes are referred to via key/node manager.
|
|
||||||
*
|
|
||||||
* A handle is used to refer to a node in a safe way over a longer period.
|
|
||||||
* While a direct reference may point to a node that has been evicted from the cache
|
|
||||||
* and reinstanciated since being set, NodeHandle will always return an up-to-date
|
|
||||||
* instance of its node.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public final class NodeHandle implements INodeState, Serializable {
|
|
||||||
|
|
||||||
// direct reference to the node
|
|
||||||
private Node node;
|
|
||||||
|
|
||||||
// the node's key
|
|
||||||
private Key key;
|
|
||||||
|
|
||||||
// cached DbMapping
|
|
||||||
private transient DbMapping dbmap;
|
|
||||||
|
|
||||||
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 ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds a handle given a node's retrieval information. At the time this is called,
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the node described by this node handle
|
|
||||||
*/
|
|
||||||
public Node getNode (WrappedNodeManager nodemgr) {
|
|
||||||
if (node != null)
|
|
||||||
return node;
|
|
||||||
return nodemgr.getNode (key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 ();
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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+"]";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,41 +0,0 @@
|
||||||
// ParentInfo.java
|
|
||||||
// Copyright (c) Hannes Wallnöfer 1999-2000
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
|
|
||||||
public ParentInfo (String desc) {
|
|
||||||
int n = desc.indexOf ("[named]");
|
|
||||||
named = n > -1;
|
|
||||||
String d = named ? desc.substring (0, n) : desc;
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString () {
|
|
||||||
return "ParentInfo["+propname+","+virtualname+","+named+"]";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -23,8 +23,8 @@ public final class Property implements IProperty, Serializable, Cloneable {
|
||||||
protected boolean bvalue;
|
protected boolean bvalue;
|
||||||
protected long lvalue;
|
protected long lvalue;
|
||||||
protected double dvalue;
|
protected double dvalue;
|
||||||
// protected String nvalueID;
|
protected String nvalueID;
|
||||||
protected NodeHandle nhandle;
|
private transient DbMapping dbm;
|
||||||
protected Object jvalue;
|
protected Object jvalue;
|
||||||
|
|
||||||
protected int type;
|
protected int type;
|
||||||
|
@ -40,11 +40,7 @@ public final class Property implements IProperty, Serializable, Cloneable {
|
||||||
type = in.readInt ();
|
type = in.readInt ();
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case STRING:
|
case STRING:
|
||||||
// try to convert from old format
|
svalue = in.readUTF ();
|
||||||
if (node.version < 7)
|
|
||||||
svalue = in.readUTF ();
|
|
||||||
else
|
|
||||||
svalue = (String) in.readObject ();
|
|
||||||
break;
|
break;
|
||||||
case BOOLEAN:
|
case BOOLEAN:
|
||||||
bvalue = in.readBoolean ();
|
bvalue = in.readBoolean ();
|
||||||
|
@ -57,11 +53,7 @@ public final class Property implements IProperty, Serializable, Cloneable {
|
||||||
dvalue = in.readDouble ();
|
dvalue = in.readDouble ();
|
||||||
break;
|
break;
|
||||||
case NODE:
|
case NODE:
|
||||||
// try to convert from old format
|
nvalueID = in.readUTF ();
|
||||||
if (node.version > 4)
|
|
||||||
nhandle = (NodeHandle) in.readObject ();
|
|
||||||
else
|
|
||||||
nhandle = new NodeHandle (new DbKey (null, in.readUTF ()));
|
|
||||||
break;
|
break;
|
||||||
case JAVAOBJECT:
|
case JAVAOBJECT:
|
||||||
jvalue = in.readObject ();
|
jvalue = in.readObject ();
|
||||||
|
@ -73,12 +65,15 @@ public final class Property implements IProperty, Serializable, Cloneable {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeObject (ObjectOutputStream out) throws IOException {
|
private void writeObject (ObjectOutputStream out) throws IOException {
|
||||||
|
// don't even start if this is a non-serializable Java object
|
||||||
|
if (type == JAVAOBJECT && jvalue != null && !(jvalue instanceof Serializable))
|
||||||
|
return;
|
||||||
out.writeUTF (propname);
|
out.writeUTF (propname);
|
||||||
out.writeObject (node);
|
out.writeObject (node);
|
||||||
out.writeInt (type);
|
out.writeInt (type);
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case STRING:
|
case STRING:
|
||||||
out.writeObject (svalue);
|
out.writeUTF (svalue);
|
||||||
break;
|
break;
|
||||||
case BOOLEAN:
|
case BOOLEAN:
|
||||||
out.writeBoolean (bvalue);
|
out.writeBoolean (bvalue);
|
||||||
|
@ -91,13 +86,10 @@ public final class Property implements IProperty, Serializable, Cloneable {
|
||||||
out.writeDouble (dvalue);
|
out.writeDouble (dvalue);
|
||||||
break;
|
break;
|
||||||
case NODE:
|
case NODE:
|
||||||
out.writeObject (nhandle);
|
out.writeUTF (nvalueID);
|
||||||
break;
|
break;
|
||||||
case JAVAOBJECT:
|
case JAVAOBJECT:
|
||||||
if (jvalue != null && !(jvalue instanceof Serializable))
|
out.writeObject (jvalue);
|
||||||
out.writeObject (null);
|
|
||||||
else
|
|
||||||
out.writeObject (jvalue);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -117,7 +109,7 @@ public final class Property implements IProperty, Serializable, Cloneable {
|
||||||
public Property (String propname, Node node, Node value) {
|
public Property (String propname, Node node, Node value) {
|
||||||
this (propname, node);
|
this (propname, node);
|
||||||
type = NODE;
|
type = NODE;
|
||||||
nhandle = value == null ? null : value.getHandle ();
|
nvalueID = value == null ? null : value.getID ();
|
||||||
dirty = true;
|
dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,11 +140,41 @@ public final class Property implements IProperty, Serializable, Cloneable {
|
||||||
public void setStringValue (String value) {
|
public void setStringValue (String value) {
|
||||||
if (type == NODE)
|
if (type == NODE)
|
||||||
unregisterNode ();
|
unregisterNode ();
|
||||||
|
// IServer.getLogger().log ("setting string value of property "+propname + " to "+value);
|
||||||
|
// mark property as dirty
|
||||||
|
dirty = true;
|
||||||
|
// if this is not a string property, try to parse a value out of it
|
||||||
|
if (type == DATE) {
|
||||||
|
SimpleDateFormat dateformat = new SimpleDateFormat ();
|
||||||
|
try {
|
||||||
|
dateformat.setLenient (true);
|
||||||
|
Date date = dateformat.parse (value);
|
||||||
|
this.lvalue = date.getTime ();
|
||||||
|
return;
|
||||||
|
} catch (ParseException nodate) {
|
||||||
|
IServer.getLogger().log ("Couldn't parse date: was expecting something like "+dateformat.format (new Date()));
|
||||||
|
// store as plain string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (type == BOOLEAN) {
|
||||||
|
if ("true".equalsIgnoreCase (value))
|
||||||
|
this.bvalue = true;
|
||||||
|
else if ("false".equalsIgnoreCase (value))
|
||||||
|
this.bvalue = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (type == INTEGER) {
|
||||||
|
this.lvalue = Long.parseLong (value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (type == FLOAT) {
|
||||||
|
this.dvalue = new Double (value).doubleValue ();
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (type == JAVAOBJECT)
|
if (type == JAVAOBJECT)
|
||||||
this.jvalue = null;
|
this.jvalue = null;
|
||||||
type = STRING;
|
|
||||||
this.svalue = value;
|
this.svalue = value;
|
||||||
dirty = true;
|
type = STRING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -197,16 +219,39 @@ public final class Property implements IProperty, Serializable, Cloneable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setNodeValue (Node value) {
|
public void setNodeValue (Node value) {
|
||||||
// value.checkWriteLock ();
|
value.checkWriteLock ();
|
||||||
if (type == NODE)
|
if (type == NODE)
|
||||||
unregisterNode ();
|
unregisterNode ();
|
||||||
if (type == JAVAOBJECT)
|
if (type == JAVAOBJECT)
|
||||||
this.jvalue = null;
|
this.jvalue = null;
|
||||||
|
registerNode (value);
|
||||||
// registerNode (value);
|
|
||||||
type = NODE;
|
type = NODE;
|
||||||
|
if (node.dbmap != null) {
|
||||||
nhandle = value.getHandle ();
|
Relation rel = node.dbmap.getPropertyRelation (propname);
|
||||||
|
if (rel != null && rel.other != null) {
|
||||||
|
DbMapping vmap = value.getDbMapping ();
|
||||||
|
// check if actual type matches expected type
|
||||||
|
if (rel.other != vmap && (!rel.virtual || rel.prototype != null)) {
|
||||||
|
throw new RuntimeException ("Can't assign property: expected prototype "+rel.other+", got "+vmap);
|
||||||
|
}
|
||||||
|
// check if this is a forward relation, i.e. if we point to a field in the value object
|
||||||
|
// if so, we may use something else than the object's id to refer to it.
|
||||||
|
if (!rel.virtual && rel.direction == Relation.FORWARD) {
|
||||||
|
if (rel.usesPrimaryKey ()) {
|
||||||
|
this.nvalueID = value.getID ();
|
||||||
|
} else try {
|
||||||
|
this.nvalueID = value.getString (vmap.columnNameToProperty (rel.getRemoteField()).propname, false);
|
||||||
|
} catch (Exception x) {
|
||||||
|
throw new RuntimeException ("Can't set "+propname+" to "+value+": error retrieving target property");
|
||||||
|
}
|
||||||
|
this.dbm = null;
|
||||||
|
dirty = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.nvalueID = value == null ? null : value.getID ();
|
||||||
|
this.dbm = value == null ? null : value.getDbMapping ();
|
||||||
dirty = true;
|
dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,39 +268,48 @@ public final class Property implements IProperty, Serializable, Cloneable {
|
||||||
* If this was the "main" property for the node, also remove all other references.
|
* If this was the "main" property for the node, also remove all other references.
|
||||||
*/
|
*/
|
||||||
protected void unregisterNode () {
|
protected void unregisterNode () {
|
||||||
Node nvalue = null;
|
if (nvalueID != null) {
|
||||||
if (nhandle != null)
|
DbMapping nvmap = null;
|
||||||
nvalue = nhandle.getNode (node.nmgr);
|
Relation nvrel = null;
|
||||||
|
if (node.dbmap != null) {
|
||||||
DbMapping nvmap = null;
|
nvmap = node.dbmap.getPropertyMapping (propname);
|
||||||
Relation nvrel = null;
|
nvrel = node.dbmap.getPropertyRelation (propname);
|
||||||
if (node.dbmap != null) {
|
}
|
||||||
nvmap = node.dbmap.getPropertyMapping (propname);
|
Node nvalue = node.nmgr.getNode (nvalueID, nvmap);
|
||||||
nvrel = node.dbmap.getPropertyRelation (propname);
|
if (nvalue == null)
|
||||||
}
|
return;
|
||||||
|
nvalue.checkWriteLock ();
|
||||||
if (nvalue == null)
|
// check if the property node is also a subnode
|
||||||
return;
|
// BUG: this doesn't work because properties for subnode/properties are never stored and therefore
|
||||||
|
// never reused.
|
||||||
nvalue.checkWriteLock ();
|
if (nvrel != null && nvrel.subnodesAreProperties) {
|
||||||
// check if the property node is also a subnode
|
node.removeNode (nvalue);
|
||||||
// BUG: this doesn't work because properties for subnode/properties are never stored and therefore
|
}
|
||||||
// never reused.
|
// only need to call unregisterPropLink if the value node is not stored in a relational db
|
||||||
if (nvrel != null && nvrel.subnodesAreProperties) {
|
// also, getParent is heuristical/implicit for relational nodes, so we don't do deepRemoveNode
|
||||||
node.removeNode (nvalue);
|
// based on that for relational nodes.
|
||||||
}
|
if (nvmap == null || !nvmap.isRelational()) {
|
||||||
// only need to call unregisterPropLink if the value node is not stored in a relational db
|
if (!nvalue.isAnonymous() && propname.equals (nvalue.getName()) && this.node == nvalue.getParent()) {
|
||||||
// also, getParent is heuristical/implicit for relational nodes, so we don't do deepRemoveNode
|
// this is the "main" property of a named node, so handle this as a cascading delete.
|
||||||
// based on that for relational nodes.
|
nvalue.deepRemoveNode ();
|
||||||
if (nvmap == null || !nvmap.isRelational()) {
|
} else {
|
||||||
if (!nvalue.isAnonymous() && propname.equals (nvalue.getName()) && this.node == nvalue.getParent()) {
|
nvalue.unregisterPropLink (this.node);
|
||||||
// this is the "main" property of a named node, so handle this as a cascading delete.
|
}
|
||||||
nvalue.deepRemoveNode ();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tell the value node that it is being used as a property value.
|
||||||
|
*/
|
||||||
|
protected void registerNode (Node n) {
|
||||||
|
// only need to call registerPropLink if the value node is not stored in a relational db
|
||||||
|
if (n != null && (n.dbmap == null || !n.dbmap.isRelational())) {
|
||||||
|
n.registerPropLink (this.node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public String getStringValue () {
|
public String getStringValue () {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case STRING:
|
case STRING:
|
||||||
|
@ -270,9 +324,9 @@ public final class Property implements IProperty, Serializable, Cloneable {
|
||||||
case FLOAT:
|
case FLOAT:
|
||||||
return Double.toString (dvalue);
|
return Double.toString (dvalue);
|
||||||
case NODE:
|
case NODE:
|
||||||
return nhandle.getID ();
|
return nvalueID;
|
||||||
case JAVAOBJECT:
|
case JAVAOBJECT:
|
||||||
return jvalue == null ? null : jvalue.toString ();
|
return jvalue.toString ();
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
@ -307,10 +361,46 @@ public final class Property implements IProperty, Serializable, Cloneable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public INode getNodeValue () {
|
public INode getNodeValue () {
|
||||||
|
|
||||||
if (nhandle != null) {
|
if (type == NODE && nvalueID != null) {
|
||||||
Node n = nhandle.getNode (node.nmgr);
|
Relation rel = null;
|
||||||
if (n != null) return n;
|
if (dbm == null && node.dbmap != null) {
|
||||||
|
// try to get DbMap for property, if it isn't known yet
|
||||||
|
rel = node.dbmap.getPropertyRelation (propname);
|
||||||
|
// figure out db mapping from relation
|
||||||
|
if (rel != null) {
|
||||||
|
// is the property a virtual node containing objects from relational db?
|
||||||
|
if (rel.virtual && rel.other.isRelational ())
|
||||||
|
return node.nmgr.getNode (node, propname, rel);
|
||||||
|
else if (!rel.virtual && rel.direction == Relation.FORWARD)
|
||||||
|
return node.nmgr.getNode (node, nvalueID, rel);
|
||||||
|
// avoid setting dbm for virtual and groupby relations, except for
|
||||||
|
// [mountpoint] kind of prototyped virtual nodes
|
||||||
|
else if ((!rel.virtual || rel.prototype != null) && rel.groupby == null)
|
||||||
|
dbm = rel.other;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// we have what we need, now get the node from the node manager
|
||||||
|
Node retval = node.nmgr.getNode (nvalueID, dbm);
|
||||||
|
if (retval != null && retval.parentID == null && !"root".equalsIgnoreCase (retval.getPrototype ())) {
|
||||||
|
retval.setParent (node);
|
||||||
|
retval.setName (propname);
|
||||||
|
retval.anonymous = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (retval != null && retval.getDbMapping () == null && rel != null && rel.virtual && rel.prototype == null) {
|
||||||
|
// a virtual node whose child nodes are not relational -
|
||||||
|
// set up dbmapping that describes subnodes and properties
|
||||||
|
DbMapping _dbm = new DbMapping ();
|
||||||
|
_dbm.setSubnodeMapping (rel.other);
|
||||||
|
_dbm.setPropertyMapping (rel.other);
|
||||||
|
_dbm.setSubnodeRelation (rel.getVirtualSubnodeRelation());
|
||||||
|
_dbm.setPropertyRelation (rel.getVirtualPropertyRelation());
|
||||||
|
retval.setDbMapping (_dbm);
|
||||||
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -321,9 +411,91 @@ public final class Property implements IProperty, Serializable, Cloneable {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getEditor () {
|
||||||
|
switch (type) {
|
||||||
|
case STRING:
|
||||||
|
return "password".equalsIgnoreCase (propname) ?
|
||||||
|
"<input type=password name=\""+propname+"\" value='"+ svalue.replace ('\'', '"') +"'>" :
|
||||||
|
"<input type=text name=\""+propname+"\" value='"+ svalue.replace ('\'', '"') +"'>" ;
|
||||||
|
case BOOLEAN:
|
||||||
|
return "<select name=\""+propname+"\"><option selected value="+bvalue+">"+bvalue+"</option><option value="+!bvalue+">"+!bvalue+"</option></select>";
|
||||||
|
case INTEGER:
|
||||||
|
return "<input type=text name=\""+propname+"\" value=\""+lvalue+"\">" ;
|
||||||
|
case FLOAT:
|
||||||
|
return "<input type=text name=\""+propname+"\" value=\""+dvalue+"\">" ;
|
||||||
|
case DATE:
|
||||||
|
SimpleDateFormat format = new SimpleDateFormat ("dd.MM.yy hh:mm");
|
||||||
|
String date = format.format (new Date (lvalue));
|
||||||
|
return "<input type=text name=\""+propname+"\" value=\""+date+"\">";
|
||||||
|
case NODE:
|
||||||
|
DbMapping nvmap = null;
|
||||||
|
if (node.dbmap != null)
|
||||||
|
nvmap = node.dbmap.getPropertyMapping (propname);
|
||||||
|
return "<input type=text size=25 name="+propname+" value='"+ node.nmgr.getNode (nvalueID, nvmap).getName () +"'>";
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
private String escape (String s) {
|
||||||
|
char c[] = new char[s.length()];
|
||||||
|
s.getChars (0, c.length, c, 0);
|
||||||
|
StringBuffer b = new StringBuffer ();
|
||||||
|
int copyfrom = 0;
|
||||||
|
for (int i = 0; i < c.length; i++) {
|
||||||
|
switch (c[i]) {
|
||||||
|
case '\\':
|
||||||
|
case '"':
|
||||||
|
if (i-copyfrom > 0)
|
||||||
|
b.append (c, copyfrom, i-copyfrom);
|
||||||
|
b.append ('\\');
|
||||||
|
b.append (c[i]);
|
||||||
|
copyfrom = i+1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (c.length-copyfrom > 0)
|
||||||
|
b.append (c, copyfrom, c.length-copyfrom);
|
||||||
|
return b.toString ();
|
||||||
|
}
|
||||||
|
|
||||||
public int getType () {
|
public int getType () {
|
||||||
return type;
|
return type;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTypeString () {
|
||||||
|
switch (type) {
|
||||||
|
case STRING:
|
||||||
|
return "string";
|
||||||
|
case BOOLEAN:
|
||||||
|
return "boolean";
|
||||||
|
case DATE:
|
||||||
|
return "date";
|
||||||
|
case INTEGER:
|
||||||
|
return "integer";
|
||||||
|
case FLOAT:
|
||||||
|
return "float";
|
||||||
|
case NODE:
|
||||||
|
return "node";
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Object clone () {
|
||||||
|
try {
|
||||||
|
Property c = (Property) super.clone();
|
||||||
|
c.propname = this.propname;
|
||||||
|
c.svalue = this.svalue;
|
||||||
|
c.bvalue = this.bvalue;
|
||||||
|
c.lvalue = this.lvalue;
|
||||||
|
c.dvalue = this.dvalue;
|
||||||
|
c.nvalueID = this.nvalueID;
|
||||||
|
c.type = this.type;
|
||||||
|
return c;
|
||||||
|
} catch (CloneNotSupportedException e) {
|
||||||
|
// this shouldn't happen, since we are Cloneable
|
||||||
|
throw new InternalError ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,773 +0,0 @@
|
||||||
// Relation.java
|
|
||||||
// Copyright (c) Hannes Wallnöfer 1997-2000
|
|
||||||
|
|
||||||
package helma.objectmodel.db;
|
|
||||||
|
|
||||||
import helma.objectmodel.*;
|
|
||||||
import helma.framework.core.Application;
|
|
||||||
import java.util.Properties;
|
|
||||||
import java.util.Vector;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This describes how a property of a persistent Object is stored in a
|
|
||||||
* relational database table. This can be either a scalar property (string, date, number etc.)
|
|
||||||
* or a reference to one or more other objects.
|
|
||||||
*/
|
|
||||||
public class Relation {
|
|
||||||
|
|
||||||
// these constants define different type of property-to-db-mappings
|
|
||||||
|
|
||||||
// there is an error in the description of this relation
|
|
||||||
public final static int INVALID = -1;
|
|
||||||
// a mapping of a non-object, scalar type
|
|
||||||
public final static int PRIMITIVE = 0;
|
|
||||||
// a 1-to-1 relation, i.e. a field in the table is a foreign key to another object
|
|
||||||
public final static int REFERENCE = 1;
|
|
||||||
// a 1-to-many relation, a field in another table points to objects of this type
|
|
||||||
public final static int COLLECTION = 2;
|
|
||||||
// direct mapping is a very powerful feature: objects of some types can be directly accessed
|
|
||||||
// by one of their properties/db fields.
|
|
||||||
// public final static int DIRECT = 3;
|
|
||||||
|
|
||||||
// the DbMapping of the type we come from
|
|
||||||
DbMapping ownType;
|
|
||||||
// the DbMapping of the prototype we link to, unless this is a "primitive" (non-object) relation
|
|
||||||
DbMapping otherType;
|
|
||||||
|
|
||||||
// if this relation defines a virtual node, we need to provide a DbMapping for these virtual nodes
|
|
||||||
DbMapping virtualMapping;
|
|
||||||
|
|
||||||
Relation virtualRelation;
|
|
||||||
Relation groupRelation;
|
|
||||||
|
|
||||||
String propName;
|
|
||||||
String columnName;
|
|
||||||
|
|
||||||
int reftype;
|
|
||||||
|
|
||||||
Constraint[] constraints;
|
|
||||||
|
|
||||||
boolean virtual;
|
|
||||||
boolean readonly;
|
|
||||||
boolean aggressiveLoading;
|
|
||||||
boolean aggressiveCaching;
|
|
||||||
boolean subnodesAreProperties;
|
|
||||||
String accessor; // db column used to access objects through this relation
|
|
||||||
String order;
|
|
||||||
String groupbyorder;
|
|
||||||
String groupby;
|
|
||||||
String prototype;
|
|
||||||
String groupbyprototype;
|
|
||||||
String filter;
|
|
||||||
int maxSize = 0;
|
|
||||||
|
|
||||||
// Relation subnoderelation = null; // additional relation used to filter subnodes for virtual nodes
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This constructor makes a copy of an existing relation. Not all fields are copied, just those
|
|
||||||
* which are needed in groupby- and virtual nodes defined by this relation.
|
|
||||||
*/
|
|
||||||
public Relation (Relation rel) {
|
|
||||||
this.ownType = rel.ownType;
|
|
||||||
this.otherType = rel.otherType;
|
|
||||||
this.propName = rel.propName;
|
|
||||||
this.columnName = rel.columnName;
|
|
||||||
this.reftype = rel.reftype;
|
|
||||||
this.constraints = rel.constraints;
|
|
||||||
this.accessor = rel.accessor;
|
|
||||||
this.maxSize = rel.maxSize;
|
|
||||||
this.subnodesAreProperties = rel.subnodesAreProperties;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads a relation entry from a line in a properties file.
|
|
||||||
*/
|
|
||||||
public Relation (String desc, String propName, DbMapping ownType, Properties props) {
|
|
||||||
this.ownType = ownType;
|
|
||||||
this.propName = propName;
|
|
||||||
otherType = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void update (String desc, Properties props, int version) {
|
|
||||||
if (version == 0)
|
|
||||||
update_v0 (desc, props);
|
|
||||||
else if (version == 1)
|
|
||||||
update_v1 (desc, props);
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// parse methods for file format v0
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
private void update_v0 (String desc, Properties props) {
|
|
||||||
boolean mountpoint = false;
|
|
||||||
Vector cnst = null;
|
|
||||||
|
|
||||||
if (desc == null || "".equals (desc.trim ())) {
|
|
||||||
if (propName != null) {
|
|
||||||
reftype = PRIMITIVE;
|
|
||||||
columnName = propName;
|
|
||||||
} else {
|
|
||||||
reftype = INVALID;
|
|
||||||
columnName = propName;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
desc = desc.trim ();
|
|
||||||
String descLower = desc.toLowerCase ();
|
|
||||||
if (descLower.startsWith ("[virtual]")) {
|
|
||||||
desc = desc.substring (9).trim ();
|
|
||||||
virtual = true;
|
|
||||||
} else if (descLower.startsWith ("[collection]")) {
|
|
||||||
desc = desc.substring (12).trim ();
|
|
||||||
virtual = true;
|
|
||||||
} else if (descLower.startsWith ("[mountpoint]")) {
|
|
||||||
desc = desc.substring (12).trim ();
|
|
||||||
virtual = true;
|
|
||||||
mountpoint = true;
|
|
||||||
} else {
|
|
||||||
virtual = false;
|
|
||||||
}
|
|
||||||
if (descLower.startsWith ("[readonly]")) {
|
|
||||||
desc = desc.substring (10).trim ();
|
|
||||||
readonly = true;
|
|
||||||
} else {
|
|
||||||
readonly = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// parse the basic properties of this mapping
|
|
||||||
parseMapping_v0 (desc, mountpoint);
|
|
||||||
|
|
||||||
// the following options only apply to object relations
|
|
||||||
if (reftype != PRIMITIVE && reftype != INVALID) {
|
|
||||||
|
|
||||||
cnst = new Vector ();
|
|
||||||
|
|
||||||
Constraint c = parseConstraint_v0 (desc);
|
|
||||||
|
|
||||||
if (c != null)
|
|
||||||
cnst.add (c);
|
|
||||||
|
|
||||||
parseOptions_v0 (cnst, props);
|
|
||||||
|
|
||||||
constraints = new Constraint[cnst.size()];
|
|
||||||
cnst.copyInto (constraints);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse a line describing a mapping of a property field. If the mapping is a
|
|
||||||
* object reference of a collection of objects, put any constraints in the Vector.
|
|
||||||
*/
|
|
||||||
protected void parseMapping_v0 (String desc, boolean mountpoint) {
|
|
||||||
|
|
||||||
Application app = ownType.getApplication ();
|
|
||||||
|
|
||||||
if (desc.indexOf ("<") > -1) {
|
|
||||||
reftype = COLLECTION;
|
|
||||||
int lt = desc.indexOf ("<");
|
|
||||||
int dot = desc.indexOf (".");
|
|
||||||
String other = dot < 0 ? desc.substring (lt+1).trim () : desc.substring (lt+1, dot).trim ();
|
|
||||||
otherType = app.getDbMapping (other);
|
|
||||||
if (otherType == null)
|
|
||||||
throw new RuntimeException ("DbMapping for "+other+" not found from "+ownType.typename);
|
|
||||||
columnName = null;
|
|
||||||
if (mountpoint)
|
|
||||||
prototype = other;
|
|
||||||
} else if (desc.indexOf (">") > -1) {
|
|
||||||
reftype = REFERENCE;
|
|
||||||
int bt = desc.indexOf (">");
|
|
||||||
int dot = desc.indexOf (".");
|
|
||||||
String other = dot > -1 ? desc.substring (bt+1, dot).trim () : desc.substring (bt+1).trim ();
|
|
||||||
otherType = app.getDbMapping (other);
|
|
||||||
if (otherType == null)
|
|
||||||
throw new RuntimeException ("DbMapping for "+other+" not found from "+ownType.typename);
|
|
||||||
columnName = desc.substring (0, bt).trim ();
|
|
||||||
if (mountpoint)
|
|
||||||
prototype = other;
|
|
||||||
} else if (desc.indexOf (".") > -1) {
|
|
||||||
reftype = COLLECTION;
|
|
||||||
int dot = desc.indexOf (".");
|
|
||||||
String other = desc.substring (0, dot).trim ();
|
|
||||||
otherType = app.getDbMapping (other);
|
|
||||||
if (otherType == null)
|
|
||||||
throw new RuntimeException ("DbMapping for "+other+" not found from "+ownType.typename);
|
|
||||||
columnName = null;
|
|
||||||
// set accessor
|
|
||||||
accessor = desc.substring (dot+1).trim ();
|
|
||||||
if (mountpoint)
|
|
||||||
prototype = other;
|
|
||||||
} else {
|
|
||||||
if (virtual) {
|
|
||||||
reftype = COLLECTION;
|
|
||||||
otherType = app.getDbMapping (desc);
|
|
||||||
if (otherType == null)
|
|
||||||
throw new RuntimeException ("DbMapping for "+desc+" not found from "+ownType.typename);
|
|
||||||
if (mountpoint)
|
|
||||||
prototype = desc;
|
|
||||||
} else {
|
|
||||||
reftype = PRIMITIVE;
|
|
||||||
columnName = desc.trim ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse a line describing a mapping of a property field. If the mapping is a
|
|
||||||
* object reference of a collection of objects, put any constraints in the Vector.
|
|
||||||
*/
|
|
||||||
protected Constraint parseConstraint_v0 (String desc) {
|
|
||||||
if (desc.indexOf ("<") > -1) {
|
|
||||||
int lt = desc.indexOf ("<");
|
|
||||||
int dot = desc.indexOf (".");
|
|
||||||
String remoteField = dot < 0 ? null : desc.substring (dot+1).trim ();
|
|
||||||
String localField = lt <= 0 ? null : desc.substring (0, lt).trim ();
|
|
||||||
return new Constraint (localField, otherType.getTableName (), remoteField, false);
|
|
||||||
} else if (desc.indexOf (">") > -1) {
|
|
||||||
int bt = desc.indexOf (">");
|
|
||||||
int dot = desc.indexOf (".");
|
|
||||||
String localField = desc.substring (0, bt).trim ();
|
|
||||||
String remoteField = dot < 0 ? null : desc.substring (dot+1).trim ();
|
|
||||||
return new Constraint (localField, otherType.getTableName (), remoteField, false);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void parseOptions_v0 (Vector cnst, Properties props) {
|
|
||||||
String loading = props.getProperty (propName+".loadmode");
|
|
||||||
aggressiveLoading = loading != null && "aggressive".equalsIgnoreCase (loading.trim());
|
|
||||||
String caching = props.getProperty (propName+".cachemode");
|
|
||||||
aggressiveCaching = caching != null && "aggressive".equalsIgnoreCase (caching.trim());
|
|
||||||
// get order property
|
|
||||||
order = props.getProperty (propName+".order");
|
|
||||||
if (order != null && order.trim().length() == 0)
|
|
||||||
order = null;
|
|
||||||
// get additional filter property
|
|
||||||
filter = props.getProperty (propName+".filter");
|
|
||||||
if (filter != null && filter.trim().length() == 0)
|
|
||||||
filter = null;
|
|
||||||
// get max size of collection
|
|
||||||
String max = props.getProperty (propName+".maxSize");
|
|
||||||
if (max != null) try {
|
|
||||||
maxSize = Integer.parseInt (max);
|
|
||||||
} catch (NumberFormatException nfe) {
|
|
||||||
maxSize = 0;
|
|
||||||
}
|
|
||||||
// get group by property
|
|
||||||
groupby = props.getProperty (propName+".groupby");
|
|
||||||
if (groupby != null && groupby.trim().length() == 0)
|
|
||||||
groupby = null;
|
|
||||||
if (groupby != null) {
|
|
||||||
groupbyorder = props.getProperty (propName+".groupby.order");
|
|
||||||
if (groupbyorder != null && groupbyorder.trim().length() == 0)
|
|
||||||
groupbyorder = null;
|
|
||||||
groupbyprototype = props.getProperty (propName+".groupby.prototype");
|
|
||||||
if (groupbyprototype != null && groupbyprototype.trim().length() == 0)
|
|
||||||
groupbyprototype = null;
|
|
||||||
// aggressive loading and caching is not supported for groupby-nodes
|
|
||||||
aggressiveLoading = aggressiveCaching = false;
|
|
||||||
}
|
|
||||||
// check if subnode condition should be applied for property relations
|
|
||||||
if ("_properties".equalsIgnoreCase (propName) || virtual) {
|
|
||||||
String subnodes2props = props.getProperty (propName+".aresubnodes");
|
|
||||||
subnodesAreProperties = "true".equalsIgnoreCase (subnodes2props);
|
|
||||||
if (virtual) {
|
|
||||||
String subnodefilter = props.getProperty (propName+".subnoderelation");
|
|
||||||
if (subnodefilter != null) {
|
|
||||||
Constraint c = parseConstraint_v0 (subnodefilter);
|
|
||||||
if (c != null) {
|
|
||||||
cnst.add (c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// update virtual mapping, if it already exists
|
|
||||||
if (virtualMapping != null) {
|
|
||||||
virtualMapping.subnodesRel = getVirtualSubnodeRelation ();
|
|
||||||
virtualMapping.propertiesRel = getVirtualPropertyRelation ();
|
|
||||||
virtualMapping.lastTypeChange = ownType.lastTypeChange;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// parse methods for file format v1
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
private void update_v1 (String desc, Properties props) {
|
|
||||||
Application app = ownType.getApplication ();
|
|
||||||
if (desc == null || "".equals (desc.trim ())) {
|
|
||||||
if (propName != null) {
|
|
||||||
reftype = PRIMITIVE;
|
|
||||||
columnName = propName;
|
|
||||||
} else {
|
|
||||||
reftype = INVALID;
|
|
||||||
columnName = propName;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
desc = desc.trim ();
|
|
||||||
int open = desc.indexOf ("(");
|
|
||||||
int close = desc.indexOf (")");
|
|
||||||
if (open > -1 && close > open) {
|
|
||||||
String ref = desc.substring (0, open).trim ();
|
|
||||||
String proto = desc.substring (open+1, close).trim ();
|
|
||||||
if ("collection".equalsIgnoreCase (ref)) {
|
|
||||||
virtual = !"_children".equalsIgnoreCase (propName);
|
|
||||||
reftype = COLLECTION;
|
|
||||||
} else if ("mountpoint".equalsIgnoreCase (ref)) {
|
|
||||||
virtual = true;
|
|
||||||
reftype = COLLECTION;
|
|
||||||
prototype = proto;
|
|
||||||
} else if ("object".equalsIgnoreCase (ref)) {
|
|
||||||
virtual = false;
|
|
||||||
reftype = REFERENCE;
|
|
||||||
} else {
|
|
||||||
throw new RuntimeException ("Invalid property Mapping: "+desc);
|
|
||||||
}
|
|
||||||
otherType = app.getDbMapping (proto);
|
|
||||||
if (otherType == null)
|
|
||||||
throw new RuntimeException ("DbMapping for "+proto+" not found from "+ownType.typename);
|
|
||||||
} else {
|
|
||||||
virtual = false;
|
|
||||||
columnName = desc;
|
|
||||||
reftype = PRIMITIVE;
|
|
||||||
}
|
|
||||||
String rdonly = props.getProperty (desc+".readonly");
|
|
||||||
if (rdonly != null && "true".equalsIgnoreCase (rdonly)) {
|
|
||||||
readonly = true;
|
|
||||||
} else {
|
|
||||||
readonly = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// the following options only apply to object and collection relations
|
|
||||||
if (reftype != PRIMITIVE && reftype != INVALID) {
|
|
||||||
|
|
||||||
Vector newConstraints = new Vector ();
|
|
||||||
parseOptions_v1 (newConstraints, props);
|
|
||||||
|
|
||||||
constraints = new Constraint[newConstraints.size()];
|
|
||||||
newConstraints.copyInto (constraints);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
protected void parseOptions_v1 (Vector cnst, Properties props) {
|
|
||||||
String loading = props.getProperty (propName+".loadmode");
|
|
||||||
aggressiveLoading = loading != null && "aggressive".equalsIgnoreCase (loading.trim());
|
|
||||||
String caching = props.getProperty (propName+".cachemode");
|
|
||||||
aggressiveCaching = caching != null && "aggressive".equalsIgnoreCase (caching.trim());
|
|
||||||
// get order property
|
|
||||||
order = props.getProperty (propName+".order");
|
|
||||||
if (order != null && order.trim().length() == 0)
|
|
||||||
order = null;
|
|
||||||
// get additional filter property
|
|
||||||
filter = props.getProperty (propName+".filter");
|
|
||||||
if (filter != null && filter.trim().length() == 0)
|
|
||||||
filter = null;
|
|
||||||
// get max size of collection
|
|
||||||
String max = props.getProperty (propName+".maxSize");
|
|
||||||
if (max != null) try {
|
|
||||||
maxSize = Integer.parseInt (max);
|
|
||||||
} catch (NumberFormatException nfe) {
|
|
||||||
maxSize = 0;
|
|
||||||
}
|
|
||||||
// get group by property
|
|
||||||
groupby = props.getProperty (propName+".group");
|
|
||||||
if (groupby != null && groupby.trim().length() == 0)
|
|
||||||
groupby = null;
|
|
||||||
if (groupby != null) {
|
|
||||||
groupbyorder = props.getProperty (propName+".group.order");
|
|
||||||
if (groupbyorder != null && groupbyorder.trim().length() == 0)
|
|
||||||
groupbyorder = null;
|
|
||||||
groupbyprototype = props.getProperty (propName+".group.prototype");
|
|
||||||
if (groupbyprototype != null && groupbyprototype.trim().length() == 0)
|
|
||||||
groupbyprototype = null;
|
|
||||||
// aggressive loading and caching is not supported for groupby-nodes
|
|
||||||
aggressiveLoading = aggressiveCaching = false;
|
|
||||||
}
|
|
||||||
// check if subnode condition should be applied for property relations
|
|
||||||
accessor = props.getProperty (propName+".accessname");
|
|
||||||
if (accessor != null)
|
|
||||||
subnodesAreProperties = true;
|
|
||||||
// parse contstraints
|
|
||||||
String local = props.getProperty (propName+".local");
|
|
||||||
String foreign = props.getProperty (propName+".foreign");
|
|
||||||
if (local != null && foreign != null) {
|
|
||||||
cnst.addElement (new Constraint (local, otherType.getTableName (), foreign, false));
|
|
||||||
columnName = local;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Does this relation describe a virtual (collection) node?
|
|
||||||
*/
|
|
||||||
public boolean isVirtual () {
|
|
||||||
return virtual;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tell if this relation represents a primitive (scalar) value mapping.
|
|
||||||
*/
|
|
||||||
public boolean isPrimitive () {
|
|
||||||
return reftype == PRIMITIVE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the prototype to be used for object reached by this relation
|
|
||||||
*/
|
|
||||||
public String getPrototype () {
|
|
||||||
return prototype;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the name of the local property this relation is defined for
|
|
||||||
*/
|
|
||||||
public String getPropName () {
|
|
||||||
return propName;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a constraint to the current list of constraints
|
|
||||||
*/
|
|
||||||
protected void addConstraint (Constraint c) {
|
|
||||||
if (constraints == null) {
|
|
||||||
constraints = new Constraint[1];
|
|
||||||
constraints[0] = c;
|
|
||||||
} else {
|
|
||||||
Constraint[] nc = new Constraint[constraints.length+1];
|
|
||||||
System.arraycopy (constraints, 0, nc, 0, constraints.length);
|
|
||||||
nc[nc.length-1] = c;
|
|
||||||
constraints = nc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public boolean usesPrimaryKey () {
|
|
||||||
if (otherType != null) {
|
|
||||||
if (reftype == REFERENCE)
|
|
||||||
return constraints.length == 1 && constraints[0].foreignKeyIsPrimary ();
|
|
||||||
if (reftype == COLLECTION)
|
|
||||||
return accessor == null || accessor.equalsIgnoreCase (otherType.getIDField ());
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getAccessor () {
|
|
||||||
return accessor;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Relation getSubnodeRelation () {
|
|
||||||
// return subnoderelation;
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the local field name for updates.
|
|
||||||
*/
|
|
||||||
public String getDbField () {
|
|
||||||
return columnName;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public DbMapping getVirtualMapping () {
|
|
||||||
if (!virtual)
|
|
||||||
return null;
|
|
||||||
if (virtualMapping == null) {
|
|
||||||
virtualMapping = new DbMapping (ownType.app);
|
|
||||||
virtualMapping.subnodesRel = getVirtualSubnodeRelation ();
|
|
||||||
virtualMapping.propertiesRel = getVirtualPropertyRelation ();
|
|
||||||
}
|
|
||||||
return virtualMapping;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a Relation that defines the subnodes of a virtual node.
|
|
||||||
*/
|
|
||||||
Relation getVirtualSubnodeRelation () {
|
|
||||||
if (!virtual)
|
|
||||||
throw new RuntimeException ("getVirtualSubnodeRelation called on non-virtual relation");
|
|
||||||
Relation vr = new Relation (this);
|
|
||||||
vr.groupby = groupby;
|
|
||||||
vr.groupbyorder = groupbyorder;
|
|
||||||
vr.groupbyprototype = groupbyprototype;
|
|
||||||
vr.order = order;
|
|
||||||
vr.filter = filter;
|
|
||||||
vr.constraints = constraints;
|
|
||||||
vr.aggressiveLoading = aggressiveLoading;
|
|
||||||
vr.aggressiveCaching = aggressiveCaching;
|
|
||||||
return vr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a Relation that defines the properties of a virtual node.
|
|
||||||
*/
|
|
||||||
Relation getVirtualPropertyRelation () {
|
|
||||||
if (!virtual)
|
|
||||||
throw new RuntimeException ("getVirtualPropertyRelation called on non-virtual relation");
|
|
||||||
Relation vr = new Relation (this);
|
|
||||||
vr.groupby = groupby;
|
|
||||||
vr.groupbyorder = groupbyorder;
|
|
||||||
vr.groupbyprototype = groupbyprototype;
|
|
||||||
vr.order = order;
|
|
||||||
vr.filter = filter;
|
|
||||||
vr.constraints = constraints;
|
|
||||||
return vr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a Relation that defines the subnodes of a group-by node.
|
|
||||||
*/
|
|
||||||
Relation getGroupbySubnodeRelation () {
|
|
||||||
if (groupby == null)
|
|
||||||
throw new RuntimeException ("getGroupbySubnodeRelation called on non-group-by relation");
|
|
||||||
Relation vr = new Relation (this);
|
|
||||||
vr.order = order;
|
|
||||||
vr.prototype = groupbyprototype;
|
|
||||||
vr.filter = filter;
|
|
||||||
vr.constraints = constraints;
|
|
||||||
vr.addConstraint (new Constraint (null, null, groupby, true));
|
|
||||||
return vr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a Relation that defines the properties of a group-by node.
|
|
||||||
*/
|
|
||||||
Relation getGroupbyPropertyRelation () {
|
|
||||||
if (groupby == null)
|
|
||||||
throw new RuntimeException ("getGroupbyPropertyRelation called on non-group-by relation");
|
|
||||||
Relation vr = new Relation (this);
|
|
||||||
vr.order = order;
|
|
||||||
vr.prototype = groupbyprototype;
|
|
||||||
vr.filter = filter;
|
|
||||||
vr.constraints = constraints;
|
|
||||||
vr.addConstraint (new Constraint (null, null, groupby, true));
|
|
||||||
return vr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Build the second half of an SQL select statement according to this relation
|
|
||||||
* and a local object.
|
|
||||||
*/
|
|
||||||
public String buildQuery (INode home, INode nonvirtual, String kstr, String pre, boolean useOrder) throws SQLException {
|
|
||||||
StringBuffer q = new StringBuffer ();
|
|
||||||
String prefix = pre;
|
|
||||||
if (kstr != null) {
|
|
||||||
q.append (prefix);
|
|
||||||
String accessColumn = accessor == null ? otherType.getIDField () : accessor;
|
|
||||||
q.append (accessColumn);
|
|
||||||
q.append (" = ");
|
|
||||||
// check if column is string type and value needs to be quoted
|
|
||||||
if (otherType.isStringColumn (accessColumn)) {
|
|
||||||
q.append ("'");
|
|
||||||
q.append (escape (kstr));
|
|
||||||
q.append ("'");
|
|
||||||
} else
|
|
||||||
q.append (escape (kstr));
|
|
||||||
prefix = " AND ";
|
|
||||||
}
|
|
||||||
for (int i=0; i<constraints.length; i++) {
|
|
||||||
q.append (prefix);
|
|
||||||
constraints[i].addToQuery (q, home, nonvirtual);
|
|
||||||
prefix = " AND ";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter != null) {
|
|
||||||
q.append (prefix);
|
|
||||||
q.append (filter);
|
|
||||||
}
|
|
||||||
if (groupby != null) {
|
|
||||||
q.append (" GROUP BY "+groupby);
|
|
||||||
if (useOrder && groupbyorder != null)
|
|
||||||
q.append (" ORDER BY "+groupbyorder);
|
|
||||||
} else if (useOrder && order != null)
|
|
||||||
q.append (" ORDER BY "+order);
|
|
||||||
return q.toString ();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the order section to use for this relation
|
|
||||||
*/
|
|
||||||
public String getOrder () {
|
|
||||||
if (groupby != null)
|
|
||||||
return groupbyorder;
|
|
||||||
else
|
|
||||||
return order;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tell wether the property described by this relation is to be handled as readonly/write protected.
|
|
||||||
*/
|
|
||||||
public boolean isReadonly () {
|
|
||||||
return readonly;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the child node fullfills the constraints defined by this relation.
|
|
||||||
*/
|
|
||||||
public boolean checkConstraints (Node parent, Node child) {
|
|
||||||
// problem: if a filter property is defined for this relation,
|
|
||||||
// i.e. a piece of static SQL-where clause, we'd have to evaluate it
|
|
||||||
// in order to check the constraints. Because of this, if a filter
|
|
||||||
// is defined, we return false as soon as the modified-time is greater
|
|
||||||
// than the create-time of the child, i.e. if the child node has been
|
|
||||||
// modified since it was first fetched from the db.
|
|
||||||
if (filter != null && child.lastModified() > child.created())
|
|
||||||
return false;
|
|
||||||
for (int i=0; i<constraints.length; i++) {
|
|
||||||
String propname = constraints[i].foreignProperty ();
|
|
||||||
if (propname != null) {
|
|
||||||
INode home = constraints[i].isGroupby ? parent : parent.getNonVirtualParent ();
|
|
||||||
String localName = constraints[i].localName;
|
|
||||||
String value = null;
|
|
||||||
if (localName == null || localName.equalsIgnoreCase (ownType.getIDField ()))
|
|
||||||
value = home.getID ();
|
|
||||||
else if (ownType.isRelational ())
|
|
||||||
value = home.getString (ownType.columnNameToProperty (localName), false);
|
|
||||||
else
|
|
||||||
value = home.getString (localName, false);
|
|
||||||
if (value != null && !value.equals (child.getString (propname, false))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Make sure that the child node fullfills the constraints defined by this relation by setting the
|
|
||||||
* appropriate properties
|
|
||||||
*/
|
|
||||||
public void setConstraints (Node parent, Node child) {
|
|
||||||
INode home = parent.getNonVirtualParent ();
|
|
||||||
for (int i=0; i<constraints.length; i++) {
|
|
||||||
// don't set groupby constraints since we don't know if the
|
|
||||||
// parent node is the base node or a group node
|
|
||||||
if (constraints[i].isGroupby)
|
|
||||||
continue;
|
|
||||||
Relation crel = otherType.columnNameToRelation (constraints[i].foreignName);
|
|
||||||
if (crel != null) {
|
|
||||||
// INode home = constraints[i].isGroupby ? parent : nonVirtual;
|
|
||||||
String localName = constraints[i].localName;
|
|
||||||
if (localName == null || localName.equalsIgnoreCase (ownType.getIDField ())) {
|
|
||||||
// only set node if property in child object is defined as reference.
|
|
||||||
if (crel.reftype == REFERENCE) {
|
|
||||||
INode currentValue = child.getNode (crel.propName, false);
|
|
||||||
// we set the backwards reference iff the reference is currently unset, if
|
|
||||||
// is set to a transient object, or if the new target is not transient. This
|
|
||||||
// prevents us from overwriting a persistent refererence with a transient one,
|
|
||||||
// which would most probably not be what we want.
|
|
||||||
if (currentValue == null ||
|
|
||||||
(currentValue != home &&
|
|
||||||
(currentValue.getState() == Node.TRANSIENT ||
|
|
||||||
home.getState() != Node.TRANSIENT)))
|
|
||||||
child.setNode (crel.propName, home);
|
|
||||||
} else if (crel.reftype == PRIMITIVE) {
|
|
||||||
child.setString (crel.propName, home.getID ());
|
|
||||||
}
|
|
||||||
} else if (crel.reftype == PRIMITIVE) {
|
|
||||||
String value = null;
|
|
||||||
if (ownType.isRelational ())
|
|
||||||
value = home.getString (ownType.columnNameToProperty (localName), false);
|
|
||||||
else
|
|
||||||
value = home.getString (localName, false);
|
|
||||||
if (value != null) {
|
|
||||||
child.setString (crel.propName, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// a utility method to escape single quotes
|
|
||||||
String escape (String str) {
|
|
||||||
if (str == null)
|
|
||||||
return null;
|
|
||||||
if (str.indexOf ("'") < 0)
|
|
||||||
return str;
|
|
||||||
int l = str.length();
|
|
||||||
StringBuffer sbuf = new StringBuffer (l + 10);
|
|
||||||
for (int i=0; i<l; i++) {
|
|
||||||
char c = str.charAt (i);
|
|
||||||
if (c == '\'')
|
|
||||||
sbuf.append ("\\");
|
|
||||||
sbuf.append (c);
|
|
||||||
}
|
|
||||||
return sbuf.toString ();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString () {
|
|
||||||
String c = "";
|
|
||||||
if (constraints != null) {
|
|
||||||
for (int i=0; i<constraints.length; i++)
|
|
||||||
c += constraints[i].toString ();
|
|
||||||
}
|
|
||||||
return "Relation["+ownType+"."+propName+">"+otherType+"]" + c;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Constraint class represents a part of the where clause in the query used to
|
|
||||||
* establish a relation between database mapped objects.
|
|
||||||
*/
|
|
||||||
class Constraint {
|
|
||||||
|
|
||||||
String localName;
|
|
||||||
String tableName;
|
|
||||||
String foreignName;
|
|
||||||
boolean isGroupby;
|
|
||||||
|
|
||||||
Constraint (String local, String table, String foreign, boolean groupby) {
|
|
||||||
localName = local;
|
|
||||||
tableName = table;
|
|
||||||
foreignName = foreign;
|
|
||||||
isGroupby = groupby;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addToQuery (StringBuffer q, INode home, INode nonvirtual) throws SQLException {
|
|
||||||
String local = null;
|
|
||||||
INode ref = isGroupby ? home : nonvirtual;
|
|
||||||
if (localName == null || localName.equalsIgnoreCase (ref.getDbMapping ().getIDField ()))
|
|
||||||
local = ref.getID ();
|
|
||||||
else {
|
|
||||||
String homeprop = ownType.columnNameToProperty (localName);
|
|
||||||
local = ref.getString (homeprop, false);
|
|
||||||
}
|
|
||||||
q.append (foreignName);
|
|
||||||
q.append (" = ");
|
|
||||||
if (otherType.isStringColumn (foreignName)) {
|
|
||||||
q.append ("'");
|
|
||||||
q.append (escape (local));
|
|
||||||
q.append ("'");
|
|
||||||
} else
|
|
||||||
q.append (escape (local));
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean foreignKeyIsPrimary () {
|
|
||||||
return foreignName == null || foreignName.equalsIgnoreCase (otherType.getIDField ());
|
|
||||||
}
|
|
||||||
|
|
||||||
public String foreignProperty () {
|
|
||||||
return otherType.columnNameToProperty (foreignName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String localProperty () {
|
|
||||||
return ownType.columnNameToProperty (localName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString () {
|
|
||||||
return ownType+"."+localName+"="+tableName+"."+foreignName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1,158 +0,0 @@
|
||||||
// Replicator.java
|
|
||||||
// Copyright (c) Hannes Wallnöfer 2001
|
|
||||||
|
|
||||||
package helma.objectmodel.db;
|
|
||||||
|
|
||||||
import helma.framework.IReplicatedApp;
|
|
||||||
import java.rmi.*;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class replicates the updates of transactions to other applications via RMI
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class Replicator implements Runnable {
|
|
||||||
|
|
||||||
Vector urls;
|
|
||||||
Vector apps;
|
|
||||||
Vector add, delete, currentAdd, currentDelete;
|
|
||||||
Thread runner;
|
|
||||||
|
|
||||||
public Replicator () {
|
|
||||||
urls = new Vector ();
|
|
||||||
apps = new Vector ();
|
|
||||||
add = new Vector ();
|
|
||||||
delete = new Vector ();
|
|
||||||
runner = new Thread (this);
|
|
||||||
runner.start ();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addUrl (String url) {
|
|
||||||
urls.addElement (url);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addApp (IReplicatedApp app) {
|
|
||||||
apps.addElement (app);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void run () {
|
|
||||||
while (Thread.currentThread () == runner) {
|
|
||||||
if (prepareReplication ()) {
|
|
||||||
for (int i=0; i<urls.size(); i++) {
|
|
||||||
try {
|
|
||||||
IReplicatedApp app = (IReplicatedApp) Naming.lookup ((String) urls.elementAt (i));
|
|
||||||
app.replicateCache (currentAdd, currentDelete);
|
|
||||||
} catch (Exception x) {
|
|
||||||
System.err.println ("ERROR REPLICATING CACHE: "+x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (int i=0; i<apps.size(); i++) {
|
|
||||||
try {
|
|
||||||
IReplicatedApp app = (IReplicatedApp) apps.elementAt (i);
|
|
||||||
app.replicateCache (currentAdd, currentDelete);
|
|
||||||
} catch (Exception x) {
|
|
||||||
System.err.println ("ERROR REPLICATING CACHE: "+x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (runner != null)
|
|
||||||
runner.sleep (1000l);
|
|
||||||
} catch (InterruptedException ir) {
|
|
||||||
runner = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void addNewNode (Node n) {
|
|
||||||
add.addElement (n);
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void addModifiedNode (Node n) {
|
|
||||||
add.addElement (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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -3,22 +3,346 @@
|
||||||
|
|
||||||
package helma.objectmodel.db;
|
package helma.objectmodel.db;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.util.*;
|
||||||
|
import java.io.*;
|
||||||
|
import java.rmi.*;
|
||||||
|
import java.rmi.server.*;
|
||||||
|
import java.rmi.registry.*;
|
||||||
|
import java.net.*;
|
||||||
|
import helma.objectmodel.*;
|
||||||
|
import helma.framework.*;
|
||||||
|
import helma.framework.core.*;
|
||||||
|
import helma.xmlrpc.*;
|
||||||
|
import helma.util.*;
|
||||||
|
import com.sleepycat.db.*;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helma server main class. This moved to the helma.main package but a
|
* HOP main class.
|
||||||
* simple redirector is kept here for backwards compatibility.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class Server {
|
public class Server extends IServer implements Runnable {
|
||||||
|
|
||||||
|
|
||||||
|
static boolean useTransactions, paranoid;
|
||||||
|
|
||||||
|
private ApplicationManager appManager;
|
||||||
|
|
||||||
|
private Thread mainThread;
|
||||||
|
|
||||||
|
static String dbFilename = "hop.db";
|
||||||
|
static String propfile;
|
||||||
|
static String dbPropfile = "db.properties";
|
||||||
|
static String appsPropfile = "apps.properties";
|
||||||
|
static SystemProperties appsProps;
|
||||||
|
static String dbDir = null;
|
||||||
|
static int port = 5055;
|
||||||
|
static int webport = 0;
|
||||||
|
|
||||||
|
Acme.Serve.Serve websrv;
|
||||||
|
|
||||||
/**
|
|
||||||
* Just invoke the main method in the new Server class.
|
|
||||||
*/
|
|
||||||
public static void main (String args[]) throws IOException {
|
public static void main (String args[]) throws IOException {
|
||||||
System.err.println ("The Helma main class is now in helma.main.Server. Please update your start script accordingly.");
|
|
||||||
helma.main.Server.main (args);
|
boolean usageError = false;
|
||||||
|
|
||||||
|
useTransactions = true;
|
||||||
|
|
||||||
|
for (int i=0; i<args.length; i++) {
|
||||||
|
if (args[i].equals ("-h") && i+1<args.length)
|
||||||
|
hopHome = args[++i];
|
||||||
|
else if (args[i].equals ("-f") && i+1<args.length)
|
||||||
|
propfile = args[++i];
|
||||||
|
else if (args[i].equals ("-t"))
|
||||||
|
useTransactions = false;
|
||||||
|
else if (args[i].equals ("-p") && i+1<args.length) {
|
||||||
|
try {
|
||||||
|
port = Integer.parseInt (args[++i]);
|
||||||
|
} catch (Exception portx) {
|
||||||
|
usageError = true;
|
||||||
|
}
|
||||||
|
} else if (args[i].equals ("-w") && i+1<args.length) {
|
||||||
|
try {
|
||||||
|
webport = Integer.parseInt (args[++i]);
|
||||||
|
} catch (Exception portx) {
|
||||||
|
usageError = true;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
usageError = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get main property file from home dir or vice versa, depending on what we have.
|
||||||
|
// get property file from hopHome
|
||||||
|
if (propfile == null) {
|
||||||
|
if (hopHome != null)
|
||||||
|
propfile = new File (hopHome, "server.properties").getAbsolutePath ();
|
||||||
|
else
|
||||||
|
propfile = new File ("server.properties").getAbsolutePath ();
|
||||||
|
}
|
||||||
|
sysProps = new SystemProperties (propfile);
|
||||||
|
// get hopHome from property file
|
||||||
|
if (hopHome == null)
|
||||||
|
hopHome = sysProps.getProperty ("hophome");
|
||||||
|
if (hopHome == null)
|
||||||
|
hopHome = new File (propfile).getParent ();
|
||||||
|
|
||||||
|
getLogger().log ("propfile = "+propfile);
|
||||||
|
getLogger().log ("hopHome = "+hopHome);
|
||||||
|
|
||||||
|
if (usageError ) {
|
||||||
|
System.out.println ("usage: java helma.objectmodel.db.Server [-h dir] [-f file] [-p port] [-w port] [-t]");
|
||||||
|
System.out.println (" -h dir Specify hop home directory");
|
||||||
|
System.out.println (" -f file Specify server.properties file");
|
||||||
|
System.out.println (" -p port Specify TCP port number");
|
||||||
|
System.out.println (" -w port Start embedded Web server on that port");
|
||||||
|
System.out.println (" -t Disable Berkeley DB Transactions");
|
||||||
|
getLogger().log ("Usage Error - exiting");
|
||||||
|
System.exit (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
dbDir = sysProps.getProperty ("dbhome", "db");
|
||||||
|
File helper = new File (dbDir);
|
||||||
|
if (hopHome != null && !helper.isAbsolute ())
|
||||||
|
helper = new File (hopHome, dbDir);
|
||||||
|
dbDir = helper.getAbsolutePath ();
|
||||||
|
getLogger().log ("dbHome = "+dbDir);
|
||||||
|
|
||||||
|
dbPropfile = sysProps.getProperty ("dbpropfile", "db.properties");
|
||||||
|
helper = new File (dbPropfile);
|
||||||
|
if (hopHome != null && !helper.isAbsolute ())
|
||||||
|
helper = new File (hopHome, dbPropfile);
|
||||||
|
dbPropfile = helper.getAbsolutePath ();
|
||||||
|
getLogger().log ("dbPropfile = "+dbPropfile);
|
||||||
|
|
||||||
|
appsPropfile = sysProps.getProperty ("appspropfile", "apps.properties");
|
||||||
|
helper = new File (appsPropfile);
|
||||||
|
if (hopHome != null && !helper.isAbsolute ())
|
||||||
|
helper = new File (hopHome, appsPropfile);
|
||||||
|
appsPropfile = helper.getAbsolutePath ();
|
||||||
|
getLogger().log ("appsPropfile = "+appsPropfile);
|
||||||
|
|
||||||
|
File libdir = new File (hopHome, "lib");
|
||||||
|
Properties p = System.getProperties ();
|
||||||
|
String libpath = p.getProperty ("java.library.path");
|
||||||
|
if (libpath != null && libpath.length () > 0)
|
||||||
|
p.put ("java.library.path", libpath+System.getProperty("path.separator")+libdir.getCanonicalPath());
|
||||||
|
else
|
||||||
|
p.put ("java.library.path", libdir.getCanonicalPath());
|
||||||
|
|
||||||
|
paranoid = "true".equalsIgnoreCase (sysProps.getProperty ("paranoid"));
|
||||||
|
|
||||||
|
String language = sysProps.getProperty ("language");
|
||||||
|
String country = sysProps.getProperty ("country");
|
||||||
|
String timezone = sysProps.getProperty ("timezone");
|
||||||
|
|
||||||
|
if (language != null && country != null)
|
||||||
|
Locale.setDefault (new Locale (language, country));
|
||||||
|
if (timezone != null)
|
||||||
|
TimeZone.setDefault (TimeZone.getTimeZone (timezone));
|
||||||
|
|
||||||
|
getLogger().log ("Locale = "+Locale.getDefault());
|
||||||
|
getLogger().log ("TimeZone = "+TimeZone.getDefault());
|
||||||
|
|
||||||
|
dbSources = new Hashtable ();
|
||||||
|
|
||||||
|
new Server ();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public Server () {
|
||||||
|
|
||||||
|
try {
|
||||||
|
checkRunning (); // check if a server is already running with this db
|
||||||
|
} catch (Exception running) {
|
||||||
|
System.out.println (running.getMessage ());
|
||||||
|
System.exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// nmgr = new NodeManager (this, sysProps);
|
||||||
|
|
||||||
|
mainThread = new Thread (this);
|
||||||
|
mainThread.start ();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run () {
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
// set up dbSources
|
||||||
|
try {
|
||||||
|
dbProps = new SystemProperties (dbPropfile);
|
||||||
|
String sources = dbProps.getProperty ("sources", "");
|
||||||
|
StringTokenizer st = new StringTokenizer (sources, ",; ");
|
||||||
|
String next = null;
|
||||||
|
while (st.hasMoreTokens ()) try {
|
||||||
|
next = st.nextToken ();
|
||||||
|
new DbSource (next);
|
||||||
|
} catch (Exception wrong) {
|
||||||
|
getLogger().log ("Error creating DbSource "+next);
|
||||||
|
getLogger().log ("Reason: "+wrong);
|
||||||
|
}
|
||||||
|
} catch (Exception x) {
|
||||||
|
getLogger().log ("Error loading data source properties: "+x);
|
||||||
|
}
|
||||||
|
|
||||||
|
// start embedded web server if port is specified
|
||||||
|
if (webport > 0) {
|
||||||
|
websrv = new Acme.Serve.Serve (webport, sysProps);
|
||||||
|
}
|
||||||
|
|
||||||
|
String xmlparser = sysProps.getProperty ("xmlparser");
|
||||||
|
if (xmlparser != null)
|
||||||
|
XmlRpc.setDriver (xmlparser);
|
||||||
|
// XmlRpc.setDebug (true);
|
||||||
|
xmlrpc = new WebServer (port+1);
|
||||||
|
if (paranoid) {
|
||||||
|
xmlrpc.setParanoid (true);
|
||||||
|
String xallow = sysProps.getProperty ("allowXmlRpc");
|
||||||
|
if (xallow != null) {
|
||||||
|
StringTokenizer st = new StringTokenizer (xallow, " ,;");
|
||||||
|
while (st.hasMoreTokens ())
|
||||||
|
xmlrpc.acceptClient (st.nextToken ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getLogger().log ("Starting XML-RPC server on port "+(port+1));
|
||||||
|
|
||||||
|
// the following seems not to be necessary after all ...
|
||||||
|
// System.setSecurityManager(new RMISecurityManager());
|
||||||
|
if (paranoid) {
|
||||||
|
HopSocketFactory factory = new HopSocketFactory ();
|
||||||
|
String rallow = sysProps.getProperty ("allowWeb");
|
||||||
|
if (rallow != null) {
|
||||||
|
StringTokenizer st = new StringTokenizer (rallow, " ,;");
|
||||||
|
while (st.hasMoreTokens ())
|
||||||
|
factory.addAddress (st.nextToken ());
|
||||||
|
}
|
||||||
|
RMISocketFactory.setSocketFactory (factory);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (websrv == null) {
|
||||||
|
getLogger().log ("Starting server on port "+port);
|
||||||
|
LocateRegistry.createRegistry (port);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// start application framework
|
||||||
|
String appDir = sysProps.getProperty ("apphome", "apps");
|
||||||
|
File appHome = new File (appDir);
|
||||||
|
if (hopHome != null && !appHome.isAbsolute())
|
||||||
|
appHome = new File (hopHome, appDir);
|
||||||
|
appsProps = new SystemProperties (appsPropfile);
|
||||||
|
File dbHome = new File (dbDir);
|
||||||
|
appManager = new ApplicationManager (port, appHome, dbHome, appsProps, this);
|
||||||
|
|
||||||
|
|
||||||
|
} catch (Exception gx) {
|
||||||
|
getLogger().log ("Error initializing embedded database: "+gx);
|
||||||
|
gx.printStackTrace ();
|
||||||
|
/* try {
|
||||||
|
transactor.abort ();
|
||||||
|
} catch (Exception ignore) {} */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// start applications
|
||||||
|
appManager.startAll ();
|
||||||
|
|
||||||
|
// start embedded web server
|
||||||
|
if (websrv != null) {
|
||||||
|
Thread webthread = new Thread (websrv, "WebServer");
|
||||||
|
webthread.start ();
|
||||||
|
}
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
while (Thread.currentThread () == mainThread) {
|
||||||
|
try {
|
||||||
|
mainThread.sleep (3000l);
|
||||||
|
} catch (InterruptedException ie) {}
|
||||||
|
try {
|
||||||
|
appManager.checkForChanges ();
|
||||||
|
} catch (Exception x) {
|
||||||
|
getLogger().log ("Caught in app manager loop: "+x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void checkRunning () throws Exception {
|
||||||
|
try {
|
||||||
|
java.net.Socket socket = new java.net.Socket ("localhost", port);
|
||||||
|
} catch (Exception x) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// if we got so far, another server is already running on this port and db
|
||||||
|
throw new Exception ("Error: Server already running on this port");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,123 +0,0 @@
|
||||||
// SyntheticKey.java
|
|
||||||
// Copyright (c) Hannes Wallnöfer 1998-2000
|
|
||||||
|
|
||||||
package helma.objectmodel.db;
|
|
||||||
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
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 boolean equals (Object what) {
|
|
||||||
if (what == this)
|
|
||||||
return true;
|
|
||||||
try {
|
|
||||||
SyntheticKey k = (SyntheticKey) what;
|
|
||||||
return parentKey.equals (k.parentKey) &&
|
|
||||||
(name == k.name || name.equals (k.name));
|
|
||||||
} catch (Exception x) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int hashCode () {
|
|
||||||
if (hashcode == 0)
|
|
||||||
hashcode = 17 + 37*name.hashCode () + 37*parentKey.hashCode ();
|
|
||||||
return hashcode;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public Key getParentKey () {
|
|
||||||
return parentKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getID () {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getStorageName () {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString () {
|
|
||||||
return parentKey+"/"+name;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,6 @@ public class Transactor extends Thread {
|
||||||
|
|
||||||
// List of nodes to be updated
|
// List of nodes to be updated
|
||||||
private HashMap nodes;
|
private HashMap nodes;
|
||||||
private ArrayList nodesArray;
|
|
||||||
// List of visited clean nodes
|
// List of visited clean nodes
|
||||||
private HashMap cleannodes;
|
private HashMap cleannodes;
|
||||||
// Is a transaction in progress?
|
// Is a transaction in progress?
|
||||||
|
@ -45,7 +44,6 @@ public class Transactor extends Thread {
|
||||||
super (group, runnable, group.getName ());
|
super (group, runnable, group.getName ());
|
||||||
this.nmgr = nmgr;
|
this.nmgr = nmgr;
|
||||||
nodes = new HashMap ();
|
nodes = new HashMap ();
|
||||||
nodesArray = new ArrayList ();
|
|
||||||
cleannodes = new HashMap ();
|
cleannodes = new HashMap ();
|
||||||
sqlCon = new HashMap ();
|
sqlCon = new HashMap ();
|
||||||
active = false;
|
active = false;
|
||||||
|
@ -58,7 +56,6 @@ public class Transactor extends Thread {
|
||||||
Key key = node.getKey ();
|
Key key = node.getKey ();
|
||||||
if (!nodes.containsKey (key)) {
|
if (!nodes.containsKey (key)) {
|
||||||
nodes.put (key, node);
|
nodes.put (key, node);
|
||||||
nodesArray.add (node);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,7 +64,6 @@ public class Transactor extends Thread {
|
||||||
if (node != null) {
|
if (node != null) {
|
||||||
Key key = node.getKey ();
|
Key key = node.getKey ();
|
||||||
nodes.remove (key);
|
nodes.remove (key);
|
||||||
nodesArray.remove (node);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +110,6 @@ public class Transactor extends Thread {
|
||||||
abort ();
|
abort ();
|
||||||
|
|
||||||
nodes.clear ();
|
nodes.clear ();
|
||||||
nodesArray.clear ();
|
|
||||||
cleannodes.clear ();
|
cleannodes.clear ();
|
||||||
txn = nmgr.db.beginTransaction ();
|
txn = nmgr.db.beginTransaction ();
|
||||||
active = true;
|
active = true;
|
||||||
|
@ -130,44 +125,36 @@ public class Transactor extends Thread {
|
||||||
}
|
}
|
||||||
|
|
||||||
int ins = 0, upd = 0, dlt = 0;
|
int ins = 0, upd = 0, dlt = 0;
|
||||||
int l = nodesArray.size ();
|
int l = nodes.size ();
|
||||||
|
|
||||||
Replicator replicator = nmgr.getReplicator ();
|
for (Iterator i=nodes.values().iterator(); i.hasNext (); ) {
|
||||||
|
Node node = (Node) i.next ();
|
||||||
|
|
||||||
for (int i=0; i<l; i++) {
|
|
||||||
Node node = (Node) nodesArray.get (i);
|
|
||||||
// update nodes in db
|
// update nodes in db
|
||||||
int nstate = node.getState ();
|
int nstate = node.getState ();
|
||||||
if (nstate == Node.NEW) {
|
if (nstate == Node.NEW) {
|
||||||
nmgr.registerNode (node); // register node with nodemanager cache
|
nmgr.registerNode (node); // register node with nodemanager cache
|
||||||
nmgr.insertNode (nmgr.db, txn, node);
|
nmgr.insertNode (nmgr.db, txn, node);
|
||||||
node.setState (Node.CLEAN);
|
node.setState (Node.CLEAN);
|
||||||
if (replicator != null)
|
|
||||||
replicator.addNewNode (node);
|
|
||||||
ins++;
|
ins++;
|
||||||
nmgr.app.logEvent ("inserted: Node "+node.getPrototype ()+"/"+node.getID ());
|
IServer.getLogger().log ("inserted: Node "+node.getName ()+"/"+node.getID ());
|
||||||
} else if (nstate == Node.MODIFIED) {
|
} else if (nstate == Node.MODIFIED) {
|
||||||
nmgr.updateNode (nmgr.db, txn, node);
|
nmgr.updateNode (nmgr.db, txn, node);
|
||||||
node.setState (Node.CLEAN);
|
node.setState (Node.CLEAN);
|
||||||
if (replicator != null)
|
|
||||||
replicator.addModifiedNode (node);
|
|
||||||
upd++;
|
upd++;
|
||||||
nmgr.app.logEvent ("updated: Node "+node.getPrototype ()+"/"+node.getID ());
|
IServer.getLogger().log ("updated: Node "+node.getName ()+"/"+node.getID ());
|
||||||
} else if (nstate == Node.DELETED) {
|
} else if (nstate == Node.DELETED) {
|
||||||
// nmgr.app.logEvent ("deleted: "+node.getFullName ()+" ("+node.getName ()+")");
|
// IServer.getLogger().log ("deleted: "+node.getFullName ()+" ("+node.getName ()+")");
|
||||||
nmgr.deleteNode (nmgr.db, txn, node);
|
nmgr.deleteNode (nmgr.db, txn, node);
|
||||||
nmgr.evictNode (node);
|
nmgr.evictNode (node);
|
||||||
if (replicator != null)
|
|
||||||
replicator.addDeletedNode (node);
|
|
||||||
dlt++;
|
dlt++;
|
||||||
} else {
|
} else {
|
||||||
// nmgr.app.logEvent ("noop: "+node.getFullName ());
|
// IServer.getLogger().log ("noop: "+node.getFullName ());
|
||||||
}
|
}
|
||||||
node.clearWriteLock ();
|
node.clearWriteLock ();
|
||||||
}
|
}
|
||||||
|
|
||||||
nodes.clear ();
|
nodes.clear ();
|
||||||
nodesArray.clear ();
|
|
||||||
cleannodes.clear ();
|
cleannodes.clear ();
|
||||||
|
|
||||||
if (nmgr.idgen.dirty) {
|
if (nmgr.idgen.dirty) {
|
||||||
|
@ -181,21 +168,19 @@ public class Transactor extends Thread {
|
||||||
txn = null;
|
txn = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
nmgr.app.logAccess (tname+" "+l+" marked, "+ins+" inserted, "+upd+" updated, "+dlt+" deleted in "+(System.currentTimeMillis()-tstart)+" millis");
|
IServer.getLogger().log (tname+" "+l+" marked, "+ins+" inserted, "+upd+" updated, "+dlt+" deleted in "+(System.currentTimeMillis()-tstart)+" millis");
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void abort () throws Exception {
|
public synchronized void abort () throws Exception {
|
||||||
|
|
||||||
int l = nodesArray.size ();
|
for (Iterator i=nodes.values().iterator(); i.hasNext(); ) {
|
||||||
for (int i=0; i<l; i++ ) {
|
Node node = (Node) i.next ();
|
||||||
Node node = (Node) nodesArray.get (i);
|
|
||||||
// Declare node as invalid, so it won't be used by other threads that want to
|
// Declare node as invalid, so it won't be used by other threads that want to
|
||||||
// write on it and remove it from cache
|
// write on it and remove it from cache
|
||||||
nmgr.evictNode (node);
|
nmgr.evictNode (node);
|
||||||
node.clearWriteLock ();
|
node.clearWriteLock ();
|
||||||
}
|
}
|
||||||
nodes.clear ();
|
nodes.clear ();
|
||||||
nodesArray.clear ();
|
|
||||||
cleannodes.clear ();
|
cleannodes.clear ();
|
||||||
// close any JDBC connections associated with this transactor thread
|
// close any JDBC connections associated with this transactor thread
|
||||||
closeConnections ();
|
closeConnections ();
|
||||||
|
@ -206,7 +191,7 @@ public class Transactor extends Thread {
|
||||||
nmgr.db.abortTransaction (txn);
|
nmgr.db.abortTransaction (txn);
|
||||||
txn = null;
|
txn = null;
|
||||||
}
|
}
|
||||||
nmgr.app.logEvent (tname+" aborted after "+(System.currentTimeMillis()-tstart)+" millis");
|
IServer.getLogger().log (tname+" aborted after "+(System.currentTimeMillis()-tstart)+" millis");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,13 +214,13 @@ public class Transactor extends Thread {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void closeConnections () {
|
public void closeConnections () {
|
||||||
// nmgr.app.logEvent("Cleaning up Transactor thread");
|
// IServer.getLogger().log("Cleaning up Transactor thread");
|
||||||
if (sqlCon != null) {
|
if (sqlCon != null) {
|
||||||
for (Iterator i=sqlCon.values().iterator(); i.hasNext(); ) {
|
for (Iterator i=sqlCon.values().iterator(); i.hasNext(); ) {
|
||||||
try {
|
try {
|
||||||
Connection con = (Connection) i.next();
|
Connection con = (Connection) i.next();
|
||||||
con.close ();
|
con.close ();
|
||||||
nmgr.app.logEvent ("Closing DB connection: "+con);
|
IServer.getLogger ().log ("Closing DB connection: "+con);
|
||||||
} catch (Exception ignore) {}
|
} catch (Exception ignore) {}
|
||||||
}
|
}
|
||||||
sqlCon.clear ();
|
sqlCon.clear ();
|
||||||
|
@ -250,3 +235,101 @@ public class Transactor extends Thread {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
package helma.objectmodel.db;
|
package helma.objectmodel.db;
|
||||||
|
|
||||||
import helma.objectmodel.*;
|
import helma.objectmodel.*;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
|
|
||||||
|
|
||||||
|
@ -23,17 +22,13 @@ import java.util.Vector;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Node getNode (String id, DbMapping dbmap) {
|
public Node getNode (String id, DbMapping dbmap) {
|
||||||
return getNode (new DbKey (dbmap, id));
|
|
||||||
}
|
|
||||||
|
|
||||||
public Node getNode (Key key) {
|
|
||||||
try {
|
try {
|
||||||
return nmgr.getNode (key);
|
return nmgr.getNode (id, dbmap);
|
||||||
} catch (ObjectNotFoundException x) {
|
} catch (ObjectNotFoundException x) {
|
||||||
return null;
|
return null;
|
||||||
} catch (Exception x) {
|
} catch (Exception x) {
|
||||||
nmgr.app.logEvent ("Error retrieving Node via DbMapping: "+x.getMessage ());
|
Server.getLogger().log ("Error retrieving Node via DbMapping: "+x.getMessage ());
|
||||||
if (nmgr.app.debug ())
|
if ("true".equalsIgnoreCase (Server.sysProps.getProperty("debug")))
|
||||||
x.printStackTrace();
|
x.printStackTrace();
|
||||||
throw new RuntimeException ("Error retrieving Node: "+x.getMessage ());
|
throw new RuntimeException ("Error retrieving Node: "+x.getMessage ());
|
||||||
}
|
}
|
||||||
|
@ -45,28 +40,28 @@ import java.util.Vector;
|
||||||
} catch (ObjectNotFoundException x) {
|
} catch (ObjectNotFoundException x) {
|
||||||
return null;
|
return null;
|
||||||
} catch (Exception x) {
|
} catch (Exception x) {
|
||||||
nmgr.app.logEvent ("Error retrieving Node \""+id+"\" from "+home+": "+x.getMessage ());
|
Server.getLogger().log ("Error retrieving Node \""+id+"\" from "+home+": "+x.getMessage ());
|
||||||
if (nmgr.app.debug ())
|
if ("true".equalsIgnoreCase (Server.sysProps.getProperty("debug")))
|
||||||
x.printStackTrace();
|
x.printStackTrace();
|
||||||
throw new RuntimeException ("Error retrieving Node: "+x.getMessage ());
|
throw new RuntimeException ("Error retrieving Node: "+x.getMessage ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List getNodes (Node home, Relation rel) {
|
public Vector getNodes (Node home, Relation rel) {
|
||||||
try {
|
try {
|
||||||
return nmgr.getNodes (home, rel);
|
return nmgr.getNodes (home, rel);
|
||||||
} catch (Exception x) {
|
} catch (Exception x) {
|
||||||
if (nmgr.app.debug ())
|
if ("true".equalsIgnoreCase (Server.sysProps.getProperty("debug")))
|
||||||
x.printStackTrace();
|
x.printStackTrace();
|
||||||
throw new RuntimeException ("Error retrieving Nodes: "+x.getMessage ());
|
throw new RuntimeException ("Error retrieving Nodes: "+x.getMessage ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List getNodeIDs (Node home, Relation rel) {
|
public Vector getNodeIDs (Node home, Relation rel) {
|
||||||
try {
|
try {
|
||||||
return nmgr.getNodeIDs (home, rel);
|
return nmgr.getNodeIDs (home, rel);
|
||||||
} catch (Exception x) {
|
} catch (Exception x) {
|
||||||
if (nmgr.app.debug ())
|
if ("true".equalsIgnoreCase (Server.sysProps.getProperty("debug")))
|
||||||
x.printStackTrace();
|
x.printStackTrace();
|
||||||
throw new RuntimeException ("Error retrieving NodeIDs: "+x.getMessage ());
|
throw new RuntimeException ("Error retrieving NodeIDs: "+x.getMessage ());
|
||||||
}
|
}
|
||||||
|
@ -76,7 +71,7 @@ import java.util.Vector;
|
||||||
try {
|
try {
|
||||||
return nmgr.countNodes (home, rel);
|
return nmgr.countNodes (home, rel);
|
||||||
} catch (Exception x) {
|
} catch (Exception x) {
|
||||||
if (nmgr.app.debug ())
|
if ("true".equalsIgnoreCase (Server.sysProps.getProperty("debug")))
|
||||||
x.printStackTrace();
|
x.printStackTrace();
|
||||||
throw new RuntimeException ("Error counting Node: "+x.getMessage ());
|
throw new RuntimeException ("Error counting Node: "+x.getMessage ());
|
||||||
}
|
}
|
||||||
|
@ -86,7 +81,7 @@ import java.util.Vector;
|
||||||
try {
|
try {
|
||||||
nmgr.deleteNode (node);
|
nmgr.deleteNode (node);
|
||||||
} catch (Exception x) {
|
} catch (Exception x) {
|
||||||
if (nmgr.app.debug ())
|
if ("true".equalsIgnoreCase (Server.sysProps.getProperty("debug")))
|
||||||
x.printStackTrace();
|
x.printStackTrace();
|
||||||
throw new RuntimeException ("Error deleting Node: "+x.getMessage ());
|
throw new RuntimeException ("Error deleting Node: "+x.getMessage ());
|
||||||
}
|
}
|
||||||
|
@ -96,7 +91,7 @@ import java.util.Vector;
|
||||||
try {
|
try {
|
||||||
return nmgr.getPropertyNames (home, rel);
|
return nmgr.getPropertyNames (home, rel);
|
||||||
} catch (Exception x) {
|
} catch (Exception x) {
|
||||||
if (nmgr.app.debug ())
|
if ("true".equalsIgnoreCase (Server.sysProps.getProperty("debug")))
|
||||||
x.printStackTrace();
|
x.printStackTrace();
|
||||||
throw new RuntimeException ("Error retrieving property names: "+x.getMessage ());
|
throw new RuntimeException ("Error retrieving property names: "+x.getMessage ());
|
||||||
}
|
}
|
||||||
|
@ -139,14 +134,6 @@ import java.util.Vector;
|
||||||
return nmgr.getCacheEntries ();
|
return nmgr.getCacheEntries ();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void logEvent (String msg) {
|
|
||||||
nmgr.app.logEvent (msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DbMapping getDbMapping (String name) {
|
|
||||||
return nmgr.app.getDbMapping (name);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
package helma.objectmodel.dom;
|
|
||||||
|
|
||||||
public interface XmlConstants {
|
|
||||||
|
|
||||||
public final String NAMESPACE = "http://www.helma.org/";
|
|
||||||
public final String DATEFORMAT = "dd.MM.yyyy HH:mm:ss z";
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,239 +0,0 @@
|
||||||
package helma.objectmodel.dom;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.net.*;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import javax.xml.parsers.*;
|
|
||||||
import org.w3c.dom.*;
|
|
||||||
|
|
||||||
import helma.objectmodel.*;
|
|
||||||
import helma.util.SystemProperties;
|
|
||||||
|
|
||||||
public class XmlConverter implements XmlConstants {
|
|
||||||
|
|
||||||
private boolean DEBUG=false;
|
|
||||||
|
|
||||||
private Properties props;
|
|
||||||
|
|
||||||
private char defaultSeparator = '_';
|
|
||||||
|
|
||||||
private int offset = 0;
|
|
||||||
|
|
||||||
public XmlConverter() {
|
|
||||||
props = new SystemProperties();
|
|
||||||
}
|
|
||||||
|
|
||||||
public XmlConverter(String propFile) {
|
|
||||||
props = new SystemProperties(propFile);
|
|
||||||
extractProperties(props);
|
|
||||||
}
|
|
||||||
|
|
||||||
public XmlConverter(File propFile) {
|
|
||||||
this ( propFile.getAbsolutePath() );
|
|
||||||
}
|
|
||||||
|
|
||||||
public XmlConverter(Properties props) {
|
|
||||||
this.props = props;
|
|
||||||
extractProperties(props);
|
|
||||||
}
|
|
||||||
|
|
||||||
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 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 );
|
|
||||||
}
|
|
||||||
|
|
||||||
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 );
|
|
||||||
} else {
|
|
||||||
return helmaNode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public INode convert( Element element, INode helmaNode ) {
|
|
||||||
offset++;
|
|
||||||
if (DEBUG) debug("reading " + element.getNodeName() );
|
|
||||||
helmaNode.setName( element.getNodeName() );
|
|
||||||
String prototype = (String)props.get(element.getNodeName().toLowerCase()+"._prototype");
|
|
||||||
if ( prototype == null )
|
|
||||||
prototype = "HopObject";
|
|
||||||
helmaNode.setPrototype( prototype );
|
|
||||||
attributes(element, helmaNode);
|
|
||||||
if ( element.hasChildNodes() ) {
|
|
||||||
children(element, helmaNode);
|
|
||||||
}
|
|
||||||
offset--;
|
|
||||||
return helmaNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* parse xml children and create hopobject-children
|
|
||||||
*/
|
|
||||||
private INode children( Element element, helma.objectmodel.INode helmaNode ) {
|
|
||||||
NodeList list = element.getChildNodes();
|
|
||||||
int len = list.getLength();
|
|
||||||
StringBuffer textcontent = new StringBuffer();
|
|
||||||
String domKey, helmaKey;
|
|
||||||
for ( int i=0; i<len; i++ ) {
|
|
||||||
|
|
||||||
// loop through the list of children
|
|
||||||
org.w3c.dom.Node childNode = list.item(i);
|
|
||||||
|
|
||||||
// if it's text content of this element -> append to StringBuffer
|
|
||||||
if ( childNode.getNodeType()==org.w3c.dom.Node.TEXT_NODE ) {
|
|
||||||
textcontent.append( childNode.getNodeValue().trim() );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// it's some kind of element (property or child)
|
|
||||||
if ( childNode.getNodeType()==org.w3c.dom.Node.ELEMENT_NODE ) {
|
|
||||||
|
|
||||||
Element childElement = (Element)childNode;
|
|
||||||
|
|
||||||
// get the basic key we have to look for in the properties-table
|
|
||||||
domKey = (element.getNodeName()+"."+childElement.getNodeName()).toLowerCase();
|
|
||||||
|
|
||||||
// is there a childtext-2-property mapping?
|
|
||||||
if ( props!=null && props.containsKey(domKey+"._text") ) {
|
|
||||||
helmaKey = (String)props.get(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 );
|
|
||||||
if ( helmaNode.getString(helmaKey,false)==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 = (String)props.get(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);
|
|
||||||
if ( helmaNode.getNode(helmaKey,false)==null ) {
|
|
||||||
convert( childElement, helmaNode.createNode(helmaKey) );
|
|
||||||
if (DEBUG) debug( "read " + childElement.toString() + helmaNode.getNode(helmaKey,false).toString() );
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// map it to one of the children-lists
|
|
||||||
helma.objectmodel.INode newHelmaNode = null;
|
|
||||||
String childrenMapping = (String)props.get(element.getNodeName().toLowerCase()+"._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) );
|
|
||||||
}
|
|
||||||
// which name to choose for a virtual subnode:
|
|
||||||
helmaKey = (String)props.get(domKey);
|
|
||||||
if ( helmaKey==null ) {
|
|
||||||
helmaKey = childElement.getNodeName().replace(':',defaultSeparator);
|
|
||||||
}
|
|
||||||
// try to get the virtual node
|
|
||||||
helma.objectmodel.INode worknode = helmaNode.getNode( helmaKey, false );
|
|
||||||
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 ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// forget about other types (comments etc)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if there's some text content for this element, map it:
|
|
||||||
if ( textcontent.length()>0 ) {
|
|
||||||
helmaKey = (String)props.get(element.getNodeName().toLowerCase()+"._text");
|
|
||||||
if ( helmaKey==null )
|
|
||||||
helmaKey = "text";
|
|
||||||
helmaNode.setString(helmaKey, textcontent.toString().trim() );
|
|
||||||
}
|
|
||||||
|
|
||||||
return helmaNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* set element's attributes as properties of helmaNode
|
|
||||||
*/
|
|
||||||
private INode attributes( Element element, INode helmaNode ) {
|
|
||||||
NamedNodeMap nnm = element.getAttributes();
|
|
||||||
int len = nnm.getLength();
|
|
||||||
for ( int i=0; i<len; i++ ) {
|
|
||||||
org.w3c.dom.Node attr = nnm.item(i);
|
|
||||||
if ( attr.getNodeName().equals("_prototype") ) {
|
|
||||||
helmaNode.setPrototype( attr.getNodeValue() );
|
|
||||||
} else if ( attr.getNodeName().equals("_name") ) {
|
|
||||||
helmaNode.setName( attr.getNodeValue() );
|
|
||||||
} else {
|
|
||||||
String helmaKey = (String)props.get(element.getNodeName().toLowerCase()+"._attribute."+attr.getNodeName().toLowerCase());
|
|
||||||
if ( helmaKey==null )
|
|
||||||
helmaKey = attr.getNodeName().replace(':',defaultSeparator);
|
|
||||||
helmaNode.setString( helmaKey, attr.getNodeValue() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return helmaNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* utility function
|
|
||||||
*/
|
|
||||||
private void extractProperties( Properties props ) {
|
|
||||||
if ( props.containsKey("separator") ) {
|
|
||||||
defaultSeparator = ((String)props.get("separator")).charAt(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** for testing */
|
|
||||||
void debug(Object msg) {
|
|
||||||
for ( int i=0; i<offset; i++ ) {
|
|
||||||
System.out.print(" ");
|
|
||||||
}
|
|
||||||
System.out.println(msg.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static void main ( String args[] ) {
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue