diff --git a/README.txt b/README.txt index f9245f46..c84bde52 100644 --- a/README.txt +++ b/README.txt @@ -1,97 +1,93 @@ This is the README file for version 1.2 of Helma Object Publisher. -=========== -ABOUT HELMA -=========== +============================ +ABOUT HELMA OBJECT PUBLISHER +============================ -Helma is a scriptable platform for creating dynamic, database backed -web sites. +Helma Object Publisher is a web application server. -Helma provides an easy way to map relational database tables to objects. -These objects are wrapped with a layer of scripts and skins that allow -them to be presented and manipulated over the web. The clue here is that -both functions and skins work in an object oriented manner and force -a clear separation between content, functionality and presentation. -Actions are special functions that are callable over the web. Macros are -special functions that expose functionality to the presentation layer. -Skins are pieces of layout that do not contain any application logic, -only macro tags as placeholders for parts that are dynamically provided -by the application. +With Helma Object Publisher (sometimes simply refered to as Helma or +Hop) you can define Objects and map them to a relational database +table. These so-called HopObjects can be created, modified and deleted +using a comfortable object/container model. Hence, no manual fiddling +around with database code is necessary. + +HopObjects are extended JavaScript objects which can be scripted using +server-side JavaScript. Beyond the common JavaScript features, Helma +provides special "skin" and template functionalities which facilitate +the rendering of objects via a web interface. + +Thanks to Helma's relational database mapping technology, HopObjects +create a hierarchical structure, the Url space of a Helma site. The +parts between slashes in a Helma Url represent HopObjects (similar to +the document tree in static sites). The Helma Url space can be thought +of as an analogy to the Document Object Model (Dom) in client-side +JavaScript. -In short, Helma provides a one stop framework to create web applications -with less code and in shorter time than most of the other software out -there. =================== SYSTEM REQUIREMENTS =================== -You need a Java virtual machine 1.3 or higher to run Helma. +Windows: 1) On Windows Helma won't run with Microsoft's version of +Java (jview). You can get a compatible Java runtime from Sun or IBM: +http://java.sun.com/j2se/1.3/jre/download-windows.html +http://www.ibm.com/java/jdk/download/ 2) In the Windows start script +I've hardcoded c:\java\lib\classes.zip in the CLASSPATH argument. Not +good. -For Windows, Linux and Solaris you can get a Java runtime or development -kit from http://java.sun.com/j2se/downloads.html. +Macintosh: 1) If you are using the Mac version you should own a G3 CPU +and/or have MRJ 2.2 (http://www.apple.com/java) installed. Other +platforms have less frustration potential. The Mac OS version +currently is not up-to-date (version 0.1). -If you are on Mac OS X, you already have a Java runtime that will work -well with Helma. +Linux: The recomended virtual machine for running Helma on Linux is +Blackdown's port of JDK 1.2.2 RC4 +(http://www.blackdown.org/java-linux/mirrors.html). JDK 1.1.7v3 will +work, but much slower and show a lot of CPU activity even when the +Helma is idle. IBM's version of JDK 1.1.8 also works well, but this +JVM has some problems of its own with thread handling. -Unfortunately, there is no Java 2 interpreter for Mac OS Classic, so -you can't use Helma on Mac OS 9. ============================ INSTALLING AND RUNNING HELMA ============================ -Simply unzip or untar the contents of the archive file into any place -on your hard disk. Start Helma by invoking hop.bat or hop.sh from the -command line, depending on whether you are on Windows or -Linux/Unix/MacOSX. If the java command is not found, try setting the -JAVA_HOME variable in the start script to the location of your Java -installation. - -You may also want to have a look at the start script for other settings. -You can adjust server wide settings in the server.properties file. For -example, you should set the smtp property to the name of the SMTP server -that Helma should use to send Email. Applications can be started or -stopped by editing the apps.properties file through the web interface -using the Management application that is part of Helma. +Simply unzip the contents of the archive file into any place on your +hard disk. Start Helma by opening the file hop.bat or hop.sh, +respectively. If you manage to get it running you should be able to connect your -browser to http://localhost:8080/ or http://127.0.0.1:8080/ -(port 8080 on the local machine, that is). +browser to http://127.0.0.1:8080/ (port 8080, that is). -Helma comes with a version of Jetty, a lightweight yet industrial strenth -web server developed by Mortbay Consulting. See http://jetty.mortbay.com/ -for more information. While Jetty works well for deploying real web sites, -you may want to run Helma behind an existing web server. This is most -easily done by running Helma with the AJPv13 listener which allows you to -plug Helma into any web server using the Apache mod_jk module. See -http://jakarta.apache.org/tomcat/tomcat-4.1-doc/jk2/index.html for more -information on mod_jk and AJPv13. +This version is set up to use its own embedded Web server and a very +basic embedded object database. For this reason it is able to run +virtually without installation on any platform with a Java 1.1 virtual +machine. -Finally, Helma can be plugged into Servlet containers using Servlet -classes that communicate with Helma either directly or via Java RMI. -(Be warned that these options may be harder to set up and maintain though, -since most of the recent development efforts have been geared towards the -mod_jk/AJPv13 setup.) +On the other hand, the embedded Web server and object db are meant for +development work and not ready for prime time deployment. For that +you'd probably use an external relational database, the Berkeley DB +package and a full featured Web server like Apache. ===================================== DOCUMENTATION AND FURTHER INFORMATION ===================================== -Currently, documentation-in-progress is available online at -http://helma.org/. We know that it sucks and hope to do some substantial -improvments within the coming weeks and months. +Currently, a documentation-in-progress is available online only. +Please refer to http://helma.org/docs/. -Your input is highly welcome. There is a mailing-list to discuss Helma at -http://helma.org/lists/listinfo/hop. Don't hesitate to voice any questions, -proposals, complaints, praise you may have on the list. We know we have -a lot to do and to learn, and we're open to suggestions. +For further information http://helma.org generally is a good place. +There is also a mailing-list about Helma-related stuff available at +http://helma.org/lists/listinfo/hop. + +For questions, comments or suggestions feel free to contact +tobi@helma.at. -For questions, comments or suggestions also feel free to contact -hannes@helma.at. -- -Last modified on December 5, 2002 by Hannes Wallnoefer +This document was last modified on Friday 22 June 2001 by +tobi@helma.at \ No newline at end of file diff --git a/build/antclick/README.txt b/build/antclick/README.txt index 7254d628..86372298 100644 --- a/build/antclick/README.txt +++ b/build/antclick/README.txt @@ -25,7 +25,7 @@ On Unix systems open a terminal window, change to the Antclick directory and type ./hop.sh. If you manage to get it running you should be able to connect your -browser to http://127.0.0.1:8080/ (port 8080, that is). Now you can +browser to http://127.0.0.1:8080/ (port 8080, that is). Now you can set up and configure your antville site. @@ -33,111 +33,89 @@ set up and configure your antville site. ABOUT ANTVILLE ============== -Antville is an open source project aimed to the development of an -"easy to maintain and use" weblog-hosting system. It is not limited -to just one weblog, it can easily host up to several hundred or -thousand weblogs (the number of weblogs is more limited by the site +Antville is an open source project aimed to the development of an +"easy to maintain and use" weblog-hosting system. It is not limited +to just one weblog, it can easily host up to several hundred or +thousand weblogs (the number of weblogs is more limited by the site owner's choice and server power than software limitations). -Antville is entirely written in JavaScript and based on the Helma -Object Publisher, a powerful and fast scriptable open source web -application server (which itself is written in Java). Antville works +Antville is entirely written in JavaScript and based on the Helma +Object Publisher, a powerful and fast scriptable open source web +application server (which itself is written in Java). Antville works with a relational database in the backend. -Check out http://project.antville.org/ for more information. +============================ +ABOUT HELMA OBJECT PUBLISHER +============================ -=========== -ABOUT HELMA -=========== +Helma Object Publisher is a web application server. -Helma is a scriptable platform for creating dynamic, database backed -web sites. +With Helma Object Publisher (sometimes simply refered to as Helma or +Hop) you can define Objects and map them to a relational database +table. These so-called HopObjects can be created, modified and deleted +using a comfortable object/container model. Hence, no manual fiddling +around with database code is necessary. -Helma provides an easy way to map relational database tables to objects. -These objects are wrapped with a layer of scripts and skins that allow -them to be presented and manipulated over the web. The clue here is that -both functions and skins work in an object oriented manner and force -a clear separation between content, functionality and presentation. -Actions are special functions that are callable over the web. Macros are -special functions that expose functionality to the presentation layer. -Skins are pieces of layout that do not contain any application logic, -only macro tags as placeholders for parts that are dynamically provided -by the application. +HopObjects are extended JavaScript objects which can be scripted using +server-side JavaScript. Beyond the common JavaScript features, Helma +provides special "skin" and template functionalities which facilitate +the rendering of objects via a web interface. + +Thanks to Helma's relational database mapping technology, HopObjects +create a hierarchical structure, the Url space of a Helma site. The +parts between slashes in a Helma Url represent HopObjects (similar to +the document tree in static sites). The Helma Url space can be thought +of as an analogy to the Document Object Model (Dom) in client-side +JavaScript. -In short, Helma provides a one stop framework to create web applications -with less code and in shorter time than most of the other software out -there. =================== SYSTEM REQUIREMENTS =================== -You need a Java virtual machine 1.3 or higher to run Helma. +You need Java 2 runtime version 1.3 or higher to run Helma. Helma has +been used successfully on Windows, Linux and Mac OS X platforms. -For Windows, Linux and Solaris you can get a Java runtime or development -kit from http://java.sun.com/j2se/downloads.html. - -If you are on Mac OS X, you already have a Java runtime that will work -well with Helma. - -Unfortunately, there is no Java 2 interpreter for Mac OS Classic, so -you can't use Helma on Mac OS 9. ============================ INSTALLING AND RUNNING HELMA ============================ -Simply unzip or untar the contents of the archive file into any place -on your hard disk. Start Helma by invoking hop.bat or hop.sh from the -command line, depending on whether you are on Windows or -Linux/Unix/MacOSX. If the java command is not found, try setting the -JAVA_HOME variable in the start script to the location of your Java -installation. - -You may also want to have a look at the start script for other settings. -You can adjust server wide settings in the server.properties file. For -example, you should set the smtp property to the name of the SMTP server -that Helma should use to send Email. Applications can be started or -stopped by editing the apps.properties file through the web interface -using the Management application that is part of Helma. +Simply unzip the contents of the archive file into any place on your +hard disk. Start Helma by opening the file hop.bat or hop.sh, +respectively. If you manage to get it running you should be able to connect your -browser to http://localhost:8080/ or http://127.0.0.1:8080/ -(port 8080 on the local machine, that is). +browser to http://127.0.0.1:8080/ (port 8080, that is). -Helma comes with a version of Jetty, a lightweight yet industrial strenth -web server developed by Mortbay Consulting. See http://jetty.mortbay.com/ -for more information. While Jetty works well for deploying real web sites, -you may want to run Helma behind an existing web server. This is most -easily done by running Helma with the AJPv13 listener which allows you to -plug Helma into any web server using the Apache mod_jk module. See -http://jakarta.apache.org/tomcat/tomcat-4.1-doc/jk2/index.html for more -information on mod_jk and AJPv13. +This version is set up to use its own embedded Web server and a very +basic embedded object database. For this reason it is able to run +virtually without installation on any platform with a Java 1.1 virtual +machine. -Finally, Helma can be plugged into Servlet containers using Servlet -classes that communicate with Helma either directly or via Java RMI. -(Be warned that these options may be harder to set up and maintain though, -since most of the recent development efforts have been geared towards the -mod_jk/AJPv13 setup.) +On the other hand, the embedded Web server and object db are meant for +development work and not ready for prime time deployment. For that +you'd probably use an external relational database, the Berkeley DB +package and a full featured Web server like Apache. ===================================== DOCUMENTATION AND FURTHER INFORMATION ===================================== -Currently, documentation-in-progress is available online at -http://helma.org/. We know that it sucks and hope to do some substantial -improvments within the coming weeks and months. +Currently, a documentation-in-progress is available online only. +Please refer to http://helma.org/. -Your input is highly welcome. There is a mailing-list to discuss Helma at -http://helma.org/lists/listinfo/hop. Don't hesitate to voice any questions, -proposals, complaints, praise you may have on the list. We know we have -a lot to do and to learn, and we're open to suggestions. +For further information http://helma.org generally is a good place. +There is also a mailing-list about Helma-related stuff available at +http://helma.org/lists/listinfo/hop. + +For questions, comments or suggestions feel free to contact +tobi@helma.at. -For questions, comments or suggestions also feel free to contact -antville@helma.org. -- -Last modified on December 5, 2002 by Hannes Wallnoefer +This document was last modified on Friday 25 October 2002 by +hannes@helma.at diff --git a/build/antclick/hop.bat b/build/antclick/hop.bat index 06771c62..ad4d6968 100755 --- a/build/antclick/hop.bat +++ b/build/antclick/hop.bat @@ -35,7 +35,7 @@ rem set JAVA_OPTIONS=-server -Xmx128m ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: :: Setting the script path -set INSTALL_DIR=%~d0%~p0 +set SCRIPT_DIR=%~d0%~p0 :: Using JAVA_HOME variable if defined. Otherwise, :: Java executable must be contained in PATH variable @@ -48,7 +48,7 @@ if "%JAVA_HOME%"=="" goto default :: Setting HOP_HOME to script path if undefined if "%HOP_HOME%"=="" ( - set HOP_HOME=%INSTALL_DIR% + set HOP_HOME=%SCRIPT_DIR% ) cd %HOP_HOME% @@ -76,4 +76,4 @@ if not "%HOP_HOME%"=="" ( ) :: Invoking the Java virtual machine -%JAVACMD% %JAVA_OPTIONS% -jar "%INSTALL_DIR%\launcher.jar" %OPTIONS% +%JAVACMD% %JAVA_OPTIONS% -jar launcher.jar %OPTIONS% diff --git a/build/antclick/hop.sh b/build/antclick/hop.sh index 9ab42a07..1126339c 100755 --- a/build/antclick/hop.sh +++ b/build/antclick/hop.sh @@ -1,7 +1,7 @@ #!/bin/sh # Shell script for starting Helma with a JDK-like virtual machine. -# To add JAR files to the classpath, simply place them into the +# To add JAR files to the classpath, simply place them into the # lib/ext directory. # uncomment to set JAVA_HOME variable @@ -32,11 +32,6 @@ else JAVACMD=java fi -# Get the Helma installation directory -INSTALL_DIR="${0%/*}" -cd $INSTALL_DIR -INSTALL_DIR=$PWD - # get HOP_HOME variable if it isn't set if test -z "$HOP_HOME"; then # try to get HOP_HOME from script file and pwd @@ -69,5 +64,5 @@ if [ "$HOP_HOME" ]; then SWITCHES="$SWITCHES -h $HOP_HOME" fi -# Invoke the Java VM -$JAVACMD $JAVA_OPTIONS -jar "$INSTALL_DIR/launcher.jar" $SWITCHES +# Invoking the Java VM +$JAVACMD $JAVA_OPTIONS -jar launcher.jar $SWITCHES diff --git a/build/build.xml b/build/build.xml index 7cc45c1a..6e1b572d 100644 --- a/build/build.xml +++ b/build/build.xml @@ -8,7 +8,7 @@ - + @@ -28,7 +28,7 @@ - + @@ -196,13 +196,10 @@ - - - - + diff --git a/hop.bat b/hop.bat index 06771c62..ad4d6968 100755 --- a/hop.bat +++ b/hop.bat @@ -35,7 +35,7 @@ rem set JAVA_OPTIONS=-server -Xmx128m ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: :: Setting the script path -set INSTALL_DIR=%~d0%~p0 +set SCRIPT_DIR=%~d0%~p0 :: Using JAVA_HOME variable if defined. Otherwise, :: Java executable must be contained in PATH variable @@ -48,7 +48,7 @@ if "%JAVA_HOME%"=="" goto default :: Setting HOP_HOME to script path if undefined if "%HOP_HOME%"=="" ( - set HOP_HOME=%INSTALL_DIR% + set HOP_HOME=%SCRIPT_DIR% ) cd %HOP_HOME% @@ -76,4 +76,4 @@ if not "%HOP_HOME%"=="" ( ) :: Invoking the Java virtual machine -%JAVACMD% %JAVA_OPTIONS% -jar "%INSTALL_DIR%\launcher.jar" %OPTIONS% +%JAVACMD% %JAVA_OPTIONS% -jar launcher.jar %OPTIONS% diff --git a/hop.sh b/hop.sh index 9ab42a07..1126339c 100755 --- a/hop.sh +++ b/hop.sh @@ -1,7 +1,7 @@ #!/bin/sh # Shell script for starting Helma with a JDK-like virtual machine. -# To add JAR files to the classpath, simply place them into the +# To add JAR files to the classpath, simply place them into the # lib/ext directory. # uncomment to set JAVA_HOME variable @@ -32,11 +32,6 @@ else JAVACMD=java fi -# Get the Helma installation directory -INSTALL_DIR="${0%/*}" -cd $INSTALL_DIR -INSTALL_DIR=$PWD - # get HOP_HOME variable if it isn't set if test -z "$HOP_HOME"; then # try to get HOP_HOME from script file and pwd @@ -69,5 +64,5 @@ if [ "$HOP_HOME" ]; then SWITCHES="$SWITCHES -h $HOP_HOME" fi -# Invoke the Java VM -$JAVACMD $JAVA_OPTIONS -jar "$INSTALL_DIR/launcher.jar" $SWITCHES +# Invoking the Java VM +$JAVACMD $JAVA_OPTIONS -jar launcher.jar $SWITCHES diff --git a/lib/jetty.jar b/lib/jetty.jar index 2304e01a..a7ab11ec 100644 Binary files a/lib/jetty.jar and b/lib/jetty.jar differ diff --git a/src/FESI/Interpreter/ClassInfo.java b/src/FESI/Interpreter/ClassInfo.java index fe0a1204..b5bc3b33 100644 --- a/src/FESI/Interpreter/ClassInfo.java +++ b/src/FESI/Interpreter/ClassInfo.java @@ -168,13 +168,7 @@ public class ClassInfo { if (indexedReadMethod != null && indexedReadMethod.getParameterTypes().length != 1) { throw new ProgrammingError("Indexed getter of property ' " + propertyName + "' should have 1 parameter!"); } - // Work around reflection bug, Hannes Wallnoefer 11/2002 - if (indexedReadMethod != null && Modifier.isPublic (indexedReadMethod.getModifiers ())) - indexedReadMethod.setAccessible (true); if (indexedWriteMethod != null) { - // Work around reflection bug, Hannes Wallnoefer 11/2002 - if (Modifier.isPublic (indexedWriteMethod.getModifiers ())) - indexedWriteMethod.setAccessible (true); Class [] paramCls = indexedWriteMethod.getParameterTypes(); if (paramCls == null || paramCls.length != 2) { throw new ProgrammingError("Indexed setter of property ' " + propertyName + "' should have 2 parameter!"); @@ -194,13 +188,7 @@ public class ClassInfo { if (readMethod != null && readMethod.getParameterTypes().length != 0) { throw new ProgrammingError("Non indexed getter of indxed property ' " + propertyName + "' is not supposed to have a parameter!"); } - // Work around reflection bug, Hannes Wallnoefer 11/2002 - if (readMethod != null && Modifier.isPublic (readMethod.getModifiers ())) - readMethod.setAccessible (true); if (writeMethod != null) { - // Work around reflection bug, Hannes Wallnoefer 11/2002 - if (Modifier.isPublic (writeMethod.getModifiers ())) - writeMethod.setAccessible (true); Class [] paramCls = writeMethod.getParameterTypes(); if (paramCls == null || paramCls.length != 1) { throw new ProgrammingError("Non indexed setter of indexed property ' " + propertyName + "' should have 1 parameter!"); @@ -220,13 +208,7 @@ public class ClassInfo { if (readMethod != null && readMethod.getParameterTypes().length != 0) { throw new ProgrammingError("Non indexed getter of property ' " + propertyName + "' is not supposed to have a parameter!"); } - // Work around reflection bug, Hannes Wallnoefer 11/2002 - if (readMethod != null && Modifier.isPublic (readMethod.getModifiers ())) - readMethod.setAccessible (true); if (writeMethod != null) { - // Work around reflection bug, Hannes Wallnoefer 11/2002 - if (Modifier.isPublic (writeMethod.getModifiers ())) - writeMethod.setAccessible (true); Class [] paramCls = writeMethod.getParameterTypes(); if (paramCls == null || paramCls.length != 1) { throw new ProgrammingError("Non indexed setter of property ' " + propertyName + "' should have 1 parameter!"); @@ -236,8 +218,8 @@ public class ClassInfo { } } } - - // Add to cache + + // Add to cache if (debug) System.out.println("** property '" + propertyName + "' + found, add to cache"); if (beanProperties==null) { beanProperties = new Hashtable(); @@ -248,7 +230,7 @@ public class ClassInfo { } return descriptor; } - + /** * Get the list of public method in this class or superclass, by name (the @@ -417,7 +399,6 @@ public class ClassInfo { } } // if class not public - // Work around reflection bug, Hannes Wallnoefer 11/2002 if (Modifier.isPublic (method.getModifiers ())) method.setAccessible (true); // save it @@ -537,7 +518,6 @@ public class ClassInfo { } } // for } // if class not public - // Work around reflection bug, Hannes Wallnoefer 11/2002 if (Modifier.isPublic (method.getModifiers ())) method.setAccessible (true); // save it diff --git a/src/helma/main/Server.java b/src/helma/main/Server.java index 1d8669e5..3af98da5 100644 --- a/src/helma/main/Server.java +++ b/src/helma/main/Server.java @@ -25,7 +25,7 @@ import org.apache.xmlrpc.*; public class Server implements IPathElement, Runnable { - public static final String version = "1.2 RC2 2002/12/05"; + public static final String version = "1.2 RC1 2002/12/03"; public final long starttime; // if true we only accept RMI and XML-RPC connections from diff --git a/src/helma/objectmodel/db/DbColumn.java b/src/helma/objectmodel/db/DbColumn.java deleted file mode 100644 index 394702dc..00000000 --- a/src/helma/objectmodel/db/DbColumn.java +++ /dev/null @@ -1,46 +0,0 @@ -// DbColumn.java -// Copyright 2002 Hannes Wallnoefer, Helma.org - -package helma.objectmodel.db; - -/** - * A class that encapsulates the Column name and data type of a - * column in a relational table. - */ -public final class DbColumn { - - private final String name; - private final int type; - private final Relation relation; - - /** - * Constructor - */ - public DbColumn (String name, int type, Relation rel) { - this.name = name; - this.type = type; - this.relation = rel; - } - - /** - * Get the column name. - */ - public String getName() { - return name; - } - - /** - * Get this columns SQL data type. - */ - public int getType() { - return type; - } - - /** - * Return the relation associated with this column. May be null. - */ - public Relation getRelation() { - return relation; - } - -} \ No newline at end of file diff --git a/src/helma/objectmodel/db/DbMapping.java b/src/helma/objectmodel/db/DbMapping.java index ff169db9..d2186c25 100644 --- a/src/helma/objectmodel/db/DbMapping.java +++ b/src/helma/objectmodel/db/DbMapping.java @@ -13,8 +13,8 @@ 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 +/** + * 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. */ @@ -43,21 +43,15 @@ public final class DbMapping implements Updatable { Relation subRelation; Relation propRelation; - // if this defines a subnode mapping with groupby layer, - // we need a DbMapping for those groupby nodes + // 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. - // Case insensitive, keys are stored in upper case so - // lookups must do a toUpperCase(). + // Map of db columns to Relations objects HashMap db2prop; - // list of columns to fetch from db - DbColumn[] columns = null; - // Map of db columns by name - HashMap columnMap; + String[] columns = null; // pre-rendered select statement String select = null; @@ -121,8 +115,6 @@ public final class DbMapping implements Updatable { prop2db = new HashMap (); db2prop = new HashMap (); - - columnMap = new HashMap (); parent = null; @@ -193,7 +185,6 @@ public final class DbMapping implements Updatable { keydef = null; // same with columns and select string columns = null; - columnMap.clear(); select = null; @@ -220,8 +211,8 @@ public final class DbMapping implements Updatable { rel.update (dbField, props); p2d.put (propName, rel); if (rel.columnName != null && - (rel.reftype == Relation.PRIMITIVE || - rel.reftype == Relation.REFERENCE)) + (rel.reftype == Relation.PRIMITIVE || + rel.reftype == Relation.REFERENCE)) d2p.put (rel.columnName.toUpperCase (), rel); // app.logEvent ("Mapping "+propName+" -> "+dbField); } @@ -240,7 +231,7 @@ public final class DbMapping implements Updatable { if (subRelation == null) subRelation = new Relation (subnodeMapping, "_children", this, props); subRelation.update (subnodeMapping, props); - // if subnodes are accessed via access name or group name, + // if subnodes are accessed via access name or group name, // the subnode relation is also the property relation. if (subRelation.accessor != null || subRelation.groupby != null) propRelation = subRelation; @@ -259,7 +250,7 @@ public final class DbMapping implements Updatable { } - /** + /** * Method in interface Updatable. */ public void remove () { @@ -488,7 +479,7 @@ public final class DbMapping implements Updatable { groupbyMapping.typename = subRelation.groupbyPrototype; } - + public void setPropertyRelation (Relation rel) { propRelation = rel; } @@ -576,11 +567,11 @@ public final class DbMapping implements Updatable { /** - * Return an array of DbColumns for the relational table mapped by this DbMapping. + * Return a Village Schema object for this DbMapping. */ - public synchronized DbColumn[] getColumns() throws ClassNotFoundException, SQLException { + public synchronized String[] getColumns() throws ClassNotFoundException, SQLException { if (!isRelational ()) - throw new SQLException ("Can't get columns for non-relational data mapping "+this); + throw new SQLException ("Can't get Schema for non-relational data mapping"); if (source == null && parentMapping != null) return parentMapping.getColumns (); // Use local variable cols to avoid synchronization (schema may be nulled elsewhere) @@ -589,46 +580,25 @@ public final class DbMapping implements Updatable { // and build a string of column names. Connection con = getConnection (); Statement stmt = con.createStatement (); - String t = getTableName(); - if (t == null) - throw new SQLException ("Table name is null in getColumns() for "+this); - ResultSet rs = stmt.executeQuery ( - new StringBuffer("SELECT * FROM ") - .append(t).append(" WHERE 1 = 0").toString()); + ResultSet rs = stmt.executeQuery ("select * from "+getTableName()+" where 1 = 0"); if (rs == null) - throw new SQLException ("Error retrieving columns for "+this); + throw new SQLException ("Error retrieving DB scheme for "+this); ResultSetMetaData meta = rs.getMetaData (); // ok, we have the meta data, now loop through mapping... int ncols = meta.getColumnCount (); - columns = new DbColumn[ncols]; + columns = new String[ncols]; for (int i=0; i 0) @@ -305,20 +305,20 @@ public final class Node implements INode, Serializable { case Types.LONGVARBINARY: case Types.VARBINARY: case Types.BINARY: - newprop.setStringValue (rs.getString(columns[i].getName())); + newprop.setStringValue (rs.getString(columns[i])); break; case Types.LONGVARCHAR: case Types.CHAR: case Types.VARCHAR: case Types.OTHER: - newprop.setStringValue (rs.getString(columns[i].getName())); + newprop.setStringValue (rs.getString(columns[i])); break; case Types.DATE: case Types.TIME: case Types.TIMESTAMP: - newprop.setDateValue (rs.getTimestamp(columns[i].getName())); + newprop.setDateValue (rs.getTimestamp(columns[i])); break; case Types.NULL: @@ -327,7 +327,7 @@ public final class Node implements INode, Serializable { // continue; default: - newprop.setStringValue (rs.getString(columns[i].getName())); + newprop.setStringValue (rs.getString(columns[i])); break; } @@ -1837,7 +1837,7 @@ public final class Node implements INode, Serializable { */ public INode getNonVirtualParent () { INode node = this; - for (int i=0; i<5; i++) { + for (int i=0; i<3; i++) { if (node == null) break; if (node.getState() != Node.VIRTUAL) return node; diff --git a/src/helma/objectmodel/db/NodeManager.java b/src/helma/objectmodel/db/NodeManager.java index bab0a103..0850372f 100644 --- a/src/helma/objectmodel/db/NodeManager.java +++ b/src/helma/objectmodel/db/NodeManager.java @@ -580,13 +580,7 @@ public final class NodeManager { try { Connection con = dbm.getConnection (); st = con.createStatement (); - st.executeUpdate (new StringBuffer ("DELETE FROM ") - .append(dbm.getTableName ()) - .append(" WHERE ") - .append(dbm.getIDField()) - .append(" = ") - .append(node.getID()) - .toString()); + st.executeUpdate ("DELETE FROM "+dbm.getTableName ()+" WHERE "+dbm.getIDField ()+" = "+node.getID ()); } finally { if (st != null) try { st.close (); @@ -611,11 +605,7 @@ public final class NodeManager { Statement stmt = null; try { Connection con = map.getConnection (); - String q = new StringBuffer("SELECT MAX(") - .append(map.getIDField()) - .append(") FROM ") - .append(map.getTableName()) - .toString(); + String q = "SELECT MAX("+map.getIDField()+") FROM "+map.getTableName(); stmt = con.createStatement (); ResultSet rs = stmt.executeQuery (q); // check for empty table @@ -649,10 +639,7 @@ public final class NodeManager { String retval = null; try { Connection con = map.getConnection (); - String q = new StringBuffer("SELECT ") - .append(map.getIDgen()) - .append(".nextval FROM dual") - .toString(); + String q = "SELECT "+map.getIDgen()+".nextval FROM dual"; stmt = con.createStatement(); ResultSet rs = stmt.executeQuery (q); if (!rs.next ()) @@ -690,28 +677,15 @@ public final class NodeManager { Statement stmt = null; try { - + String q = null; - + if (home.getSubnodeRelation() != null) { // subnode relation was explicitly set - q = new StringBuffer("SELECT ") - .append(idfield) - .append(" FROM ") - .append(table) - .append(" ") - .append(home.getSubnodeRelation()) - .toString(); + q = "SELECT "+idfield+" FROM "+table+" "+home.getSubnodeRelation(); } else { // let relation object build the query - q = new StringBuffer("SELECT ") - .append(idfield) - .append(" FROM ") - .append(table) - .append(rel.buildQuery (home, - home.getNonVirtualParent (), null, - " WHERE ", true)) - .toString(); + q = "SELECT "+idfield+" FROM "+table + rel.buildQuery (home, home.getNonVirtualParent (), null, " WHERE ", true); } if (logSql) @@ -721,7 +695,7 @@ public final class NodeManager { if (rel.maxSize > 0) stmt.setMaxRows (rel.maxSize); ResultSet result = stmt.executeQuery (q); - + // problem: how do we derive a SyntheticKey from a not-yet-persistent Node? Key k = rel.groupby != null ? home.getKey (): null; while (result.next ()) { @@ -732,8 +706,8 @@ public final class NodeManager { continue; // make the proper key for the object, either a generic DB key or a groupby key Key key = rel.groupby == null ? - (Key) new DbKey (rel.otherType, kstr) : - (Key) new SyntheticKey (k, kstr); + (Key) new DbKey (rel.otherType, kstr) : + (Key) new SyntheticKey (k, kstr); retval.add (new NodeHandle (key)); // if these are groupby nodes, evict nullNode keys if (rel.groupby != null) { @@ -776,7 +750,7 @@ public final class NodeManager { Connection con = dbm.getConnection (); Statement stmt = con.createStatement (); - DbColumn[] columns = dbm.getColumns (); + String[] columns = dbm.getColumns (); StringBuffer q = dbm.getSelect (); try { if (home.getSubnodeRelation() != null) { @@ -834,7 +808,7 @@ public final class NodeManager { if (missing > 0) { Connection con = dbm.getConnection (); Statement stmt = con.createStatement (); - DbColumn[] columns = dbm.getColumns (); + String[] columns = dbm.getColumns (); StringBuffer q = dbm.getSelect (); try { String idfield = rel.groupby != null ? rel.groupby : dbm.getIDField (); @@ -861,10 +835,8 @@ public final class NodeManager { q.append (") "); if (rel.groupby != null) { q.append (rel.renderConstraints (home, home.getNonVirtualParent ())); - if (rel.order != null) { - q.append (" ORDER BY "); - q.append (rel.order); - } + if (rel.order != null) + q.append (" ORDER BY "+rel.order); } if (logSql) @@ -965,27 +937,19 @@ public final class NodeManager { Statement stmt = null; try { - + String q = null; if (home.getSubnodeRelation() != null) { // use the manually set subnoderelation of the home node - q = new StringBuffer("SELECT count(*) FROM ") - .append(table) - .append(" ") - .append(home.getSubnodeRelation()) - .toString(); + q = "SELECT count(*) FROM "+table+" "+home.getSubnodeRelation(); } else { // let relation object build the query - q = new StringBuffer("SELECT count(*) FROM ") - .append(table) - .append(rel.buildQuery (home, home.getNonVirtualParent(), - null, " WHERE ", false)) - .toString(); + q = "SELECT count(*) FROM "+table + rel.buildQuery (home, home.getNonVirtualParent (), null, " WHERE ", false); } - + if (logSql) app.logEvent ("### countNodes: "+q); - + stmt = con.createStatement(); ResultSet rs = stmt.executeQuery (q); @@ -1026,13 +990,7 @@ public final class NodeManager { Statement stmt = null; try { - String q = new StringBuffer("SELECT ") - .append(namefield) - .append(" FROM ") - .append(table) - .append(" ORDER BY ") - .append(namefield) - .toString(); + String q = "SELECT "+namefield+" FROM "+table+" ORDER BY "+namefield; stmt = con.createStatement (); if (logSql) @@ -1079,7 +1037,7 @@ public final class NodeManager { Connection con = dbm.getConnection (); stmt = con.createStatement (); - DbColumn[] columns = dbm.getColumns (); + String[] columns = dbm.getColumns (); StringBuffer q = dbm.getSelect (); q.append ("WHERE "); q.append (idfield); @@ -1141,7 +1099,7 @@ public final class NodeManager { DbMapping dbm = rel.otherType; Connection con = dbm.getConnection (); - DbColumn[] columns = dbm.getColumns (); + String[] columns = dbm.getColumns (); StringBuffer q = dbm.getSelect (); if (home.getSubnodeRelation () != null) { // combine our key with the constraints in the manually set subnode relation @@ -1186,7 +1144,7 @@ public final class NodeManager { } /** - * Get a DbMapping for a given prototype name. This is just a proxy + * Get a DbMapping for a given prototype name. This is just a proxy * method to the app's getDbMapping() method. */ public DbMapping getDbMapping (String protoname) {