You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by ha...@apache.org on 2001/11/23 11:50:36 UTC
cvs commit: xml-cocoon2/scratchpad/src/org/apache/cocoon/acting/ModularDatabaseAccess AbstractAutoIncrementHelper.java AbstractOutputHelper.java AutoIncrementHelper.java AbstractAttributeHelper.java AttributeHelper.java HsqlIdentityKeyAttributeHelper.java IfxSerialKeyAttributeHelper.java ManualKeyAttributeHelper.java OutputHelper.java RequestAttributeHelper.java RequestAttributeOutputHelper.java RequestParameterHelper.java AbstractKeyAttributeHelper.java AccessHelper.java KeyAttributeHelper.java
haul 01/11/23 02:50:36
Modified: webapp/WEB-INF/db cocoondb.properties cocoondb.script
scratchpad/webapp/mount/mod-db database.xml edit-groups.xsp
schema.sql sitemap.xmap user-list.xsp
scratchpad/src/org/apache/cocoon/acting
ModularDatabaseAddAction.java
ModularDatabaseDeleteAction.java
ModularDatabaseSelectAction.java
ModularDatabaseUpdateAction.java
scratchpad/src/org/apache/cocoon/acting/ModularDatabaseAccess
AbstractAttributeHelper.java AttributeHelper.java
HsqlIdentityKeyAttributeHelper.java
IfxSerialKeyAttributeHelper.java
ManualKeyAttributeHelper.java OutputHelper.java
RequestAttributeHelper.java
RequestAttributeOutputHelper.java
RequestParameterHelper.java
Added: scratchpad/src/org/apache/cocoon/acting
ModularDatabaseAction.java
scratchpad/src/org/apache/cocoon/acting/ModularDatabaseAccess
AbstractAutoIncrementHelper.java
AbstractOutputHelper.java AutoIncrementHelper.java
Removed: scratchpad/src/org/apache/cocoon/acting/ModularDatabaseAccess
AbstractKeyAttributeHelper.java AccessHelper.java
KeyAttributeHelper.java
Log:
Polished interfaces + some restructuring.
Now open for review.
Revision Changes Path
1.5 +1 -1 xml-cocoon2/webapp/WEB-INF/db/cocoondb.properties
Index: cocoondb.properties
===================================================================
RCS file: /home/cvs/xml-cocoon2/webapp/WEB-INF/db/cocoondb.properties,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- cocoondb.properties 2001/11/19 16:06:33 1.4
+++ cocoondb.properties 2001/11/23 10:50:35 1.5
@@ -1,4 +1,4 @@
#HSQL database
-#Mon Nov 19 17:19:34 CET 2001
+#Fri Nov 23 11:13:29 CET 2001
version=1.6
modified=no
1.3 +3 -3 xml-cocoon2/webapp/WEB-INF/db/cocoondb.script
Index: cocoondb.script
===================================================================
RCS file: /home/cvs/xml-cocoon2/webapp/WEB-INF/db/cocoondb.script,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- cocoondb.script 2001/11/19 16:06:34 1.2
+++ cocoondb.script 2001/11/23 10:50:35 1.3
@@ -1,10 +1,10 @@
CREATE TABLE DEPARTMENT_TABLE(ID INTEGER,NAME VARCHAR,UNIQUE(ID))
CREATE TABLE EMPLOYEE_TABLE(ID INTEGER,DEPARTMENT_ID INTEGER,NAME VARCHAR,UNIQUE(ID))
-CREATE TABLE USER(UID INTEGER IDENTITY PRIMARY KEY,NAME VARCHAR,SURNAME VARCHAR,UNAME VARCHAR,UNIQUE(UNAME))
+CREATE TABLE USER(UID INTEGER IDENTITY PRIMARY KEY,NAME VARCHAR,FIRSTNAME VARCHAR,UNAME VARCHAR,UNIQUE(UNAME))
CREATE TABLE GROUPS(GID INTEGER IDENTITY PRIMARY KEY,GNAME VARCHAR,UNIQUE(GNAME))
CREATE TABLE USER_GROUPS(UID INTEGER,GID INTEGER,UNIQUE(UID,GID),FOREIGN KEY(UID)REFERENCES USER(UID),FOREIGN KEY(GID)REFERENCES GROUPS(GID))
-GRANT ALL ON CLASS "java.lang.Math" TO PUBLIC
GRANT ALL ON CLASS "org.hsqldb.Library" TO PUBLIC
+GRANT ALL ON CLASS "java.lang.Math" TO PUBLIC
CREATE USER SA PASSWORD "" ADMIN
CREATE ALIAS DAYNAME FOR "org.hsqldb.Library.dayname"
CREATE ALIAS SPACE FOR "org.hsqldb.Library.space"
@@ -52,7 +52,7 @@
CREATE ALIAS CURTIME FOR "org.hsqldb.Library.curtime"
CREATE ALIAS DIFFERENCE FOR "org.hsqldb.Library.difference"
CREATE ALIAS INSERT FOR "org.hsqldb.Library.insert"
-CREATE ALIAS SUBSTR FOR "org.hsql.Library.substring"
+CREATE ALIAS SUBSTR FOR "org.hsqldb.Library.substring"
CREATE ALIAS DATABASE FOR "org.hsqldb.Library.database"
CREATE ALIAS MINUTE FOR "org.hsqldb.Library.minute"
CREATE ALIAS HOUR FOR "org.hsqldb.Library.hour"
1.2 +38 -24 xml-cocoon2/scratchpad/webapp/mount/mod-db/database.xml
Index: database.xml
===================================================================
RCS file: /home/cvs/xml-cocoon2/scratchpad/webapp/mount/mod-db/database.xml,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- database.xml 2001/11/19 16:28:32 1.1
+++ database.xml 2001/11/23 10:50:35 1.2
@@ -9,35 +9,50 @@
autoincrements work differently on different DBMSs, so we need
special support to find out about the value set by the DBMS.
-->
- <table name="user"><!-- @name is the table's name in the DB -->
+ <table name="user" alias="user">
+ <!-- @name is the table's name in the DB -->
+ <!-- @alias is used instead (if present) for those weirdos that put -->
+ <!-- complex queries into @name ;-) You obviously loose all but select -->
+ <!-- functionality, although this is not enforced. -->
<keys>
- <key name="uid" type="int">
+ <key name="uid" type="int" autoincrement="true">
<!-- @name is the column's name -->
<!-- @type is the column's jdbc type -->
- <mode name="auto" type="insert"/>
+ <!-- @autoincrement : column value is determined by special component -->
+ <mode name="auto" type="autoincr"/>
<!-- this entry says:
- when inserting a new column (@type="insert"), use the
- helper named "auto" to find out about how to handle this
- column. All other operations use the default mode.
- There are two distinct mode types: "insert" for insert
- operations and "others" for all other (delete, update,
- select) -->
+ when inserting a new column into a autoincrement column
+ (@type="autoincr"), use the helper named "auto" to find out about
+ how to handle this column. All other operations use the default
+ mode.
+ There are two distinct mode types: "autoincr" for insert
+ operations on autoincrement columns and "others" for all other
+ (delete, update, select) operations on autoincrement columns and
+ all operations on other columns.
+ -->
</key>
</keys>
<values>
- <value name="name" type="string"></value>
- <value name="surname" type="string"></value>
- <value name="uname" type="string"></value>
+ <value name="name" type="string"></value>
+ <value name="firstname" type="string"></value>
+ <value name="uname" type="string"></value>
</values>
</table>
<table name="user_groups">
<keys>
<key name="uid" type="int">
- <!-- Next we have two different modes: a default and
+ <!-- Next we have two different modes: "request" and
"attrib". See below for explanation. -->
<mode name="request" parameter="user_groups.uid" type="request"/>
- <mode name="attribute" parameter="org.apache.cocoon.acting.ModularDatabaseAccess.OutputHelper:user.uid" type="attrib"/>
+ <mode name="attribute" parameter="org.apache.cocoon.acting.ModularDatabaseAccess.OutputHelper:user.uid[0]" type="attrib"/>
+ <!-- note here, that the actual parameter has a row index
+ to it. We don't expect to insert more than one user plus
+ her groups at any time, so we append just "[0]". However,
+ if that would be the case, we could let this column be
+ part of a set and ask for "[*]" instead. Might be tricky
+ to find the associated groups, though, if we insert x
+ users plus y_1, y_2, ... , y_x groups.... -->
</key>
<key name="gid" type="int" set="master">
<!-- now, this is tricky: when we need to insert multiple
@@ -47,7 +62,8 @@
master is used to obtain a sorted set of index values for
these rows. These will then be used to get the actual
values for the master and slave columns. Note that it is
- not necessary to have the master be a key column.
+ not necessary to have the master be a key column. Note too, that an
+ autoincrement column may not serve as a master here.
This attribute may be specified on a column level or on a
mode level to allow different behavious. Mode level @set
@@ -61,12 +77,12 @@
<table name="groups">
<keys>
- <key name="gid" type="int">
- <mode name="auto" type="insert"/>
+ <key name="gid" type="int" autoincrement="true">
+ <mode name="auto" type="autoincr"/>
</key>
</keys>
<values>
- <value name="gname" type="string"></value>
+ <value name="gname" type="string"/>
</values>
</table>
@@ -88,21 +104,19 @@
<table-set name="user+groups">
<table name="user"/>
- <table name="user_groups" add-mode="attrib" others-mode="request"/>
+ <table name="user_groups" others-mode="attrib"/>
<!-- below we have another table set that inserts data into
user_groups. When inserting into user_groups alone, we'd know
the uid before hand, but when inserting a new user as well, we
need to find out the autoincrement value first. Therefore we
need a different approach to obtain that value. So we can
- instruct the action to use for add operations ("request") a
- different type (here "attrib") which reads the result from the
- first insert operation. We could as well specify a different
- mode for "others" operations as well: others-mode
+ instruct the action to use a different type (here "attrib") which reads
+ the result from the first insert operation.
-->
</table-set>
<table-set name="user_groups">
- <table name="user_groups" add-mode="request" others-mode="request"/>
+ <table name="user_groups" others-mode="request"/>
</table-set>
</root>
1.2 +210 -209 xml-cocoon2/scratchpad/webapp/mount/mod-db/edit-groups.xsp
Index: edit-groups.xsp
===================================================================
RCS file: /home/cvs/xml-cocoon2/scratchpad/webapp/mount/mod-db/edit-groups.xsp,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- edit-groups.xsp 2001/11/19 16:28:32 1.1
+++ edit-groups.xsp 2001/11/23 10:50:35 1.2
@@ -5,229 +5,230 @@
xmlns:xsp="http://apache.org/xsp"
xmlns:esql="http://apache.org/cocoon/SQL/v2"
xmlns:xsp-request="http://apache.org/xsp/request/2.0"
->
-<!--
--->
-<xsp:structure>
- <xsp:include>java.util.Enumeration</xsp:include>
-</xsp:structure>
-
-<page>
- <title>edit-groups</title>
-
+ >
+ <!--
+ -->
+ <xsp:structure>
+ <xsp:include>java.util.Enumeration</xsp:include>
+ </xsp:structure>
+
+ <page>
+ <title>edit-groups</title>
+
- <esql:connection>
- <esql:pool>personnel</esql:pool>
+ <esql:connection>
+ <esql:pool>personnel</esql:pool>
- <xsp:logic>
- String user = <xsp-request:get-parameter name="user.uid"/>;
- if ( user == null ) {
- user = <xsp-request:get-parameter name="user_groups.uid"/>;
- }
- int uid=-1;
- if ( user != null ) {
- try {
- uid = Integer.parseInt(user);
- } catch ( NumberFormatException e ) {
- uid = -1;
- }
- }
- String uname="";
- String name="";
- String surname="";
- if ( uid != -1 ) {
- <esql:execute-query>
- <esql:query>select * from user where uid=<esql:parameter><xsp:expr>uid</xsp:expr></esql:parameter></esql:query>
- <esql:results>
- <esql:row-results>
- <xsp:logic>
- uid=<esql:get-int column="uid"/>;
- uname=<esql:get-string column="uname"/>;
- name=<esql:get-string column="name"/>;
- surname=<esql:get-string column="surname"/>;
- </xsp:logic>
- </esql:row-results>
- </esql:results>
- </esql:execute-query>
- }
- </xsp:logic>
-
-
-<h1>Edit User's Groups</h1>
-<table cellpadding="2" cellspacing="2" border="0">
- <tbody>
- <form>
- <tr>
- <td valign="Top" align="Right">uname
- </td>
- <td valign="Top">
- <input type="text" name="user.uname">
- <xsp:attribute name="value"><xsp:expr>uname</xsp:expr></xsp:attribute>
- </input>
- </td>
- <td>
- </td>
- </tr>
- <tr>
- <td valign="Top" align="Right">surname, name</td>
- <td>
- <input type="text" name="user.surname">
- <xsp:attribute name="value"><xsp:expr>surname</xsp:expr></xsp:attribute>
- </input>,
- <input type="text" name="user.name">
- <xsp:attribute name="value"><xsp:expr>name</xsp:expr></xsp:attribute>
- </input>
- </td>
- <td>
- <input type="hidden" name="user.uid">
- <xsp:attribute name="value"><xsp:expr>uid</xsp:expr></xsp:attribute>
- </input>
- <input type="submit" name="upd-user" value="update"/>
- </td>
- </tr>
- </form>
- <tr>
- <td valign="Top">
- </td>
- <td valign="Top" align="right">
- <form>
- <table border="1">
- <tbody>
+ <xsp:logic>
+ String user = <xsp-request:get-parameter name="user.uid"/>;
+ if ( user == null ) {
+ user = <xsp-request:get-parameter name="user_groups.uid"/>;
+ }
+ int uid=-1;
+ if ( user != null ) {
+ try {
+ uid = Integer.parseInt(user);
+ } catch ( NumberFormatException e ) {
+ uid = -1;
+ }
+ }
+ String uname="";
+ String name="";
+ String firstname="";
+ if ( uid != -1 ) {
+ <esql:execute-query>
+ <esql:query>select * from user where uid=<esql:parameter><xsp:expr>uid</xsp:expr></esql:parameter></esql:query>
+ <esql:results>
+ <esql:row-results>
+ <xsp:logic>
+ uid=<esql:get-int column="uid"/>;
+ uname=<esql:get-string column="uname"/>;
+ name=<esql:get-string column="name"/>;
+ firstname=<esql:get-string column="firstname"/>;
+ </xsp:logic>
+ </esql:row-results>
+ </esql:results>
+ </esql:execute-query>
+ }
+ </xsp:logic>
+
+
+ <h1>Edit User's Groups</h1>
+ <table cellpadding="2" cellspacing="2" border="0">
+ <tbody>
+ <form>
<tr>
- <td>
- <table border="0">
+ <td valign="Top" align="Right">uname
+ </td>
+ <td valign="Top">
+ <input type="text" name="user.uname">
+ <xsp:attribute name="value"><xsp:expr>uname</xsp:expr></xsp:attribute>
+ </input>
+ </td>
+ <td>
+ </td>
+ </tr>
+ <tr>
+ <td valign="Top" align="Right">firstname, name</td>
+ <td>
+ <input type="text" name="user.firstname">
+ <xsp:attribute name="value"><xsp:expr>firstname</xsp:expr></xsp:attribute>
+ </input>,
+ <input type="text" name="user.name">
+ <xsp:attribute name="value"><xsp:expr>name</xsp:expr></xsp:attribute>
+ </input>
+ </td>
+ <td>
+ <input type="hidden" name="user.uid">
+ <xsp:attribute name="value"><xsp:expr>uid</xsp:expr></xsp:attribute>
+ </input>
+ <input type="submit" name="upd-user" value="update"/>
+ </td>
+ </tr>
+ </form>
+ <tr>
+ <td valign="Top">
+ </td>
+ <td valign="Top" align="right">
+ <form>
+ <table border="1">
<tbody>
<tr>
- <td>current groups</td>
- </tr>
- <tr>
<td>
- <select multiple="1" name="user_groups.gid" size="7">
- <esql:execute-query>
- <esql:query>select gid, gname from user_groups, groups where user_groups.gid = groups.gid and uid=<esql:parameter type="int"><xsp:expr>uid</xsp:expr></esql:parameter> order by gname</esql:query>
- <esql:results>
- <esql:row-results>
- <option>
- <xsp:attribute name="value"><esql:get-string column="gid"/></xsp:attribute>
- <esql:get-string column="gname"/>
- </option>
- </esql:row-results>
- </esql:results>
- </esql:execute-query>
- </select>
+ <table border="0">
+ <tbody>
+ <tr>
+ <td>current groups</td>
+ </tr>
+ <tr>
+ <td>
+ <select multiple="1" name="user_groups.gid" size="7">
+ <esql:execute-query>
+ <esql:query>select gid, gname from user_groups, groups where user_groups.gid = groups.gid and uid=<esql:parameter type="int"><xsp:expr>uid</xsp:expr></esql:parameter> order by gname</esql:query>
+ <esql:results>
+ <esql:row-results>
+ <option>
+ <xsp:attribute name="value"><esql:get-string column="gid"/></xsp:attribute>
+ <esql:get-string column="gname"/>
+ </option>
+ </esql:row-results>
+ </esql:results>
+ </esql:execute-query>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td valign="Top">
+ <input type="hidden" name="user_groups.uid">
+ <xsp:attribute name="value"><xsp:expr>uid</xsp:expr></xsp:attribute>
+ </input>
+ <input type="submit" name="remove-groups" value="remove"/>
+ </td>
+ </tr>
+ </tbody>
+ </table>
</td>
</tr>
- <tr>
- <td valign="Top">
- <input type="hidden" name="user_groups.uid">
- <xsp:attribute name="value"><xsp:expr>uid</xsp:expr></xsp:attribute>
- </input>
- <input type="submit" name="remove-groups" value="remove"/></td>
- </tr>
</tbody>
</table>
- </td>
- </tr>
- </tbody>
- </table>
- </form>
- </td>
- <td valign="Top" align="left">
- <form>
- <table border="1">
- <tbody>
- <tr>
- <td>
- <table border="0">
+ </form>
+ </td>
+ <td valign="Top" align="left">
+ <form>
+ <table border="1">
<tbody>
<tr>
- <td>available groups</td>
- </tr>
- <tr>
<td>
- <select name="user_groups.gid" multiple="1" size="7">
- <esql:execute-query>
- <esql:query>select gid, gname from groups where gid not in (select gid from user_groups where uid=<esql:parameter type="int"><xsp:expr>uid</xsp:expr></esql:parameter>) order by gname</esql:query>
- <esql:results>
- <esql:row-results>
- <option>
- <xsp:attribute name="value"><esql:get-string column="gid"/></xsp:attribute>
- <esql:get-string column="gname"/>
- </option>
- </esql:row-results>
- </esql:results>
- </esql:execute-query>
- </select>
- </td>
- </tr>
- <tr>
- <td valign="Top">
- <input type="hidden" name="user_groups.uid">
- <xsp:attribute name="value"><xsp:expr>uid</xsp:expr></xsp:attribute>
- </input>
- <input type="submit" name="add-groups" value="add"/></td>
- </tr>
- </tbody>
- </table>
- </td>
- </tr>
- </tbody>
- </table>
- </form>
- </td>
- </tr>
- </tbody>
-</table>
- <div align="Right"><form action="user-list"><input value="back to list" type="submit"/></form></div>
-
- </esql:connection>
-
- <hr/>
-
- <p><h3>Request Attributes</h3></p>
- <p>
- <table border="0">
- <tbody>
- <xsp:logic>{
- Enumeration e=request.getAttributeNames();
- while ( e.hasMoreElements() ) {
- String attribute = (String) e.nextElement();
- Object value = request.getAttribute(attribute);
- <tr>
- <td align="right"><xsp:expr>attribute</xsp:expr></td>
- <td>="<xsp:expr>value</xsp:expr>"</td>
- </tr>
- }
- }</xsp:logic>
- </tbody>
- </table><br/>
- </p>
- <hr/>
-
- <p><h3>Request Parameters</h3></p>
- <p>
- <table border="0">
- <tbody>
- <xsp:logic>{
- Enumeration e=request.getParameterNames();
- while ( e.hasMoreElements() ) {
- String attribute = (String) e.nextElement();
- Object[] value = request.getParameterValues(attribute);
- for (int i=0; i < value.length; i++) {
- <tr>
- <td align="right"><xsp:expr>attribute</xsp:expr>[<xsp:expr>i</xsp:expr>]</td>
- <td>="<xsp:expr>value[i]</xsp:expr>"</td>
- </tr>
- }
- }
- }</xsp:logic>
- </tbody>
- </table><br/>
- </p>
- <hr/>
-
+ <table border="0">
+ <tbody>
+ <tr>
+ <td>available groups</td>
+ </tr>
+ <tr>
+ <td>
+ <select name="user_groups.gid" multiple="1" size="7">
+ <esql:execute-query>
+ <esql:query>select gid, gname from groups where gid not in (select gid from user_groups where uid=<esql:parameter type="int"><xsp:expr>uid</xsp:expr></esql:parameter>) order by gname</esql:query>
+ <esql:results>
+ <esql:row-results>
+ <option>
+ <xsp:attribute name="value"><esql:get-string column="gid"/></xsp:attribute>
+ <esql:get-string column="gname"/>
+ </option>
+ </esql:row-results>
+ </esql:results>
+ </esql:execute-query>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td valign="Top">
+ <input type="hidden" name="user_groups.uid">
+ <xsp:attribute name="value"><xsp:expr>uid</xsp:expr></xsp:attribute>
+ </input>
+ <input type="submit" name="add-groups" value="add"/></td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </form>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ <div align="Right"><form action="user-list"><input value="back to list" type="submit"/></form></div>
+
+ </esql:connection>
+
+ <hr/>
+
+ <p><h3>Request Attributes</h3></p>
+ <p>
+ <table border="0">
+ <tbody>
+ <xsp:logic>{
+ Enumeration e=request.getAttributeNames();
+ while ( e.hasMoreElements() ) {
+ String attribute = (String) e.nextElement();
+ Object value = request.getAttribute(attribute);
+ <tr>
+ <td align="right"><xsp:expr>attribute</xsp:expr></td>
+ <td>="<xsp:expr>value</xsp:expr>"</td>
+ </tr>
+ }
+ }</xsp:logic>
+ </tbody>
+ </table>
+ </p>
+
+ <hr/>
+
+ <p><h3>Request Parameters</h3></p>
+ <p>
+ <table border="0">
+ <tbody>
+ <xsp:logic>{
+ Enumeration e=request.getParameterNames();
+ while ( e.hasMoreElements() ) {
+ String attribute = (String) e.nextElement();
+ Object[] value = request.getParameterValues(attribute);
+ for (int i=0; i < value.length; i++) {
+ <tr>
+ <td align="right"><xsp:expr>attribute</xsp:expr>[<xsp:expr>i</xsp:expr>]</td>
+ <td>="<xsp:expr>value[i]</xsp:expr>"</td>
+ </tr>
+ }
+ }
+ }</xsp:logic>
+ </tbody>
+ </table>
+ </p>
+ <hr/>
-
</page>
+
</xsp:page>
1.2 +1 -1 xml-cocoon2/scratchpad/webapp/mount/mod-db/schema.sql
Index: schema.sql
===================================================================
RCS file: /home/cvs/xml-cocoon2/scratchpad/webapp/mount/mod-db/schema.sql,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- schema.sql 2001/11/19 16:28:32 1.1
+++ schema.sql 2001/11/23 10:50:35 1.2
@@ -8,7 +8,7 @@
create table user (
uid integer identity primary key,
name varchar(50),
- surname varchar(50),
+ firstname varchar(50),
uname varchar(20),
unique (uname)
);
1.2 +52 -17 xml-cocoon2/scratchpad/webapp/mount/mod-db/sitemap.xmap
Index: sitemap.xmap
===================================================================
RCS file: /home/cvs/xml-cocoon2/scratchpad/webapp/mount/mod-db/sitemap.xmap,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- sitemap.xmap 2001/11/19 16:28:32 1.1
+++ sitemap.xmap 2001/11/23 10:50:35 1.2
@@ -5,6 +5,8 @@
<!-- ========================= Components ============================== -->
<map:components>
+ <!-- most components are inherited from parent sitemap -->
+ <!-- just make sure that defaults suit our needs -->
<map:generators default="file"/>
@@ -14,17 +16,19 @@
<map:serializers default="html"/>
- <map:selectors default="browser">
- <map:selector name="request" src="org.apache.cocoon.selection.RequestSelectorFactory"/>
- </map:selectors>
-
- <map:matchers default="wildcard">
- <map:matcher name="wildcard" src="org.apache.cocoon.matching.WildcardURIMatcherFactory"/>
- </map:matchers>
+ <map:selectors default="browser"/>
+ <map:matchers default="wildcard"/>
+
<map:actions>
+ <!-- these action are in addition to the ones inherited -->
<map:action name="mod-db-add" src="org.apache.cocoon.acting.ModularDatabaseAddAction">
<descriptor>context://mount/mod-db/database.xml</descriptor>
+ <throw-exception>false</throw-exception>
+ <!-- shall we throw an exception in addition to rolling back
+ the transaction when encountering an error during
+ database ops?
+ -->
<!-- <mode name="auto" src="org.apache.cocoon.acting.ModularDatabaseAccess.IfxSerialKeyAttributeHelper"/> -->
<mode name="auto" src="org.apache.cocoon.acting.ModularDatabaseAccess.HsqlIdentityKeyAttributeHelper"/>
<mode name="request" src="org.apache.cocoon.acting.ModularDatabaseAccess.RequestParameterHelper"/>
@@ -33,6 +37,14 @@
</map:action>
<map:action name="mod-db-del" src="org.apache.cocoon.acting.ModularDatabaseDeleteAction">
<descriptor>context://mount/mod-db/database.xml</descriptor>
+ <throw-exception>false</throw-exception>
+ <!--
+ It doesn't make sense to declare AutoIncrementHelpers for
+ this action, but until component handling is removed from
+ ModularDatabaseAction and done e.g. in sitemap,
+ ModularDatabaseAction will complain if such a helper is
+ missing.
+ -->
<!-- <mode name="auto" src="org.apache.cocoon.acting.ModularDatabaseAccess.IfxSerialKeyAttributeHelper"/> -->
<mode name="auto" src="org.apache.cocoon.acting.ModularDatabaseAccess.HsqlIdentityKeyAttributeHelper"/>
<mode name="request" src="org.apache.cocoon.acting.ModularDatabaseAccess.RequestParameterHelper"/>
@@ -41,6 +53,14 @@
</map:action>
<map:action name="mod-db-upd" src="org.apache.cocoon.acting.ModularDatabaseUpdateAction">
<descriptor>context://mount/mod-db/database.xml</descriptor>
+ <throw-exception>false</throw-exception>
+ <!--
+ It doesn't make sense to declare AutoIncrementHelpers for
+ this action, but until component handling is removed from
+ ModularDatabaseAction and done e.g. in sitemap,
+ ModularDatabaseAction will complain if such a helper is
+ missing.
+ -->
<!-- <mode name="auto" src="org.apache.cocoon.acting.ModularDatabaseAccess.IfxSerialKeyAttributeHelper"/> -->
<mode name="auto" src="org.apache.cocoon.acting.ModularDatabaseAccess.HsqlIdentityKeyAttributeHelper"/>
<mode name="request" src="org.apache.cocoon.acting.ModularDatabaseAccess.RequestParameterHelper"/>
@@ -68,8 +88,22 @@
<!-- ========================== Modular DB ================================= -->
+ <map:match pattern="">
+ <map:redirect-to uri="user-list"/>
+ </map:match>
+
+
<map:match pattern="*">
+ <!--
+ First, the logic to do all the database operations. Note,
+ that we do no parameter validation here, just see if some
+ parameters are present. For a real application, you'd
+ want to check their values as well. Note too, that in a
+ more complex setup you'd want to use an action set for
+ this rather than spell it out everywhere.
+ -->
+
<!-- ______________________________ inserts ______________________________ -->
<!-- add new groups to a user's groups -->
@@ -80,25 +114,28 @@
</map:act>
</map:act>
- <!-- add one new user -->
+ <!-- add onw new group -->
<map:act type="req-params">
- <map:parameter name="parameters" value="add-user user.name user.surname user.uname"/>
+ <map:parameter name="parameters" value="add-group groups.gname"/>
<map:act type="mod-db-add">
- <map:parameter name="table-set" value="user"/>
+ <map:parameter name="table-set" value="groups"/>
</map:act>
</map:act>
- <!-- add onw new group -->
+ <!-- add one new user -->
+ <!-- Actually, this one is not used anymore. The one below
+ works well when no groups are supplied.
+ -->
<map:act type="req-params">
- <map:parameter name="parameters" value="add-group groups.gname"/>
+ <map:parameter name="parameters" value="add-user user.name user.firstname user.uname"/>
<map:act type="mod-db-add">
- <map:parameter name="table-set" value="groups"/>
+ <map:parameter name="table-set" value="user"/>
</map:act>
</map:act>
<!-- add one new user plus groups -->
<map:act type="req-params">
- <map:parameter name="parameters" value="add-user-groups user.name user.surname user.uname"/>
+ <map:parameter name="parameters" value="add-user-groups user.name user.firstname user.uname"/>
<map:act type="mod-db-add">
<map:parameter name="table-set" value="user+groups"/>
</map:act>
@@ -108,7 +145,7 @@
<!-- update one user -->
<map:act type="req-params">
- <map:parameter name="parameters" value="upd-user user.uid user.name user.surname user.uname"/>
+ <map:parameter name="parameters" value="upd-user user.uid user.name user.firstname user.uname"/>
<map:act type="mod-db-upd">
<map:parameter name="table-set" value="user"/>
</map:act>
@@ -152,8 +189,6 @@
<!-- ______________________________ content ______________________________ -->
<map:generate type="serverpages" src="{1}.xsp"/>
- <map:label name="content"/>
-
<map:transform src="context://stylesheets/dynamic-page2html.xsl">
<map:parameter name="view-source" value="{1}.xsp"/>
</map:transform>
1.2 +241 -346 xml-cocoon2/scratchpad/webapp/mount/mod-db/user-list.xsp
Index: user-list.xsp
===================================================================
RCS file: /home/cvs/xml-cocoon2/scratchpad/webapp/mount/mod-db/user-list.xsp,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- user-list.xsp 2001/11/19 16:28:32 1.1
+++ user-list.xsp 2001/11/23 10:50:35 1.2
@@ -5,354 +5,249 @@
xmlns:xsp="http://apache.org/xsp"
xmlns:esql="http://apache.org/cocoon/SQL/v2"
xmlns:xsp-request="http://apache.org/xsp/request/2.0"
->
-<!--
--->
-<xsp:structure>
- <xsp:include>java.util.Enumeration</xsp:include>
-</xsp:structure>
-
- <page>
-
- <title>user-list</title>
-
- <content>
-
-
- <h1>Modular Database Actions</h1>
-
- <hr/>
-
- <p>The intention is to factor out those parts that are dependent on
- the utilised DBMS as well as the methods used to obtain the values
- and communicate results. Therefore three classes of adaptors
- exist:</p>
-
- <ol>
- <li>Attribute Helpers read data from some source (e.g. the request
- object or session attributes or whatever)</li>
-
- <li>Key Attribute Helpers determine the value of a key attribute
- column in a database. This could be by querying the database,
- reading from an arbitrary source (e.g. request object) or just
- skipping the column when inserting a row and querying the
- database afterwards. This needs to be done e.g. for Informix's
- SERIAL or HSQLDB's IDENTITY column types.</li>
-
- <li>Output Helpers send the data to an arbitrary
- destination. Again, this could be request attributes or
- anything else. When the database transaction finishes, it is
- signalled to them whether the transaction succeeded or
- failed.</li>
- </ol>
- <hr/>
- <!--
- forms
- -->
-
+ >
<!--
-
- <h2>Insert a user</h2>
- <blockquote>
- <form method="Get">
- <table cellpadding="2" cellspacing="2" border="0">
- <tbody>
- <tr>
- <td valign="Top" align="Right">surname</td>
- <td valign="Top">
- <input type="text" name="user.surname" size="20" maxsize="20">
- <xsp:attribute name="value"><xsp-request:get-parameter default="" name="user.surname"/></xsp:attribute>
- </input>
- </td>
- </tr>
- <tr>
- <td valign="Top" align="Right">name
- </td>
- <td valign="Top"><input type="text" name="user.name" size="20" maxsize="20"><xsp:attribute name="value"><xsp-request:get-parameter default="" name="user.name"/></xsp:attribute></input></td>
- </tr>
- <tr>
- <td valign="Top" align="Right">uname
- </td>
- <td valign="Top"><input type="text" name="user.uname" size="20" maxsize="20"><xsp:attribute name="value"><xsp-request:get-parameter default="" name="user.uname"/></xsp:attribute></input>
- </td>
- </tr>
- <tr>
- <td valign="Top">
- </td>
- <td align="Right"><input type="submit" name="add-user" value="OK"/></td>
- </tr>
- </tbody>
- </table>
- </form>
- </blockquote>
- <hr/>
-
-
- <h2>Add groups to a user account</h2>
- <blockquote>
- <form method="Get">
- <table cellpadding="2" cellspacing="2" border="0">
- <tbody>
- <tr>
- <td valign="Top" align="Right">user</td>
- <td valign="Top">
- <select name="user_groups.uid" size="1">
- <esql:connection>
- <esql:pool>personnel</esql:pool>
- <esql:execute-query>
- <esql:query>select uid, uname from user order by name, surname</esql:query>
- <esql:results>
- <esql:row-results>
- <option>
- <xsp:attribute name="value"><esql:get-string column="uid"/></xsp:attribute>
- <esql:get-string column="uname"/>
- </option>
- </esql:row-results>
- </esql:results>
- </esql:execute-query>
- </esql:connection>
- </select>
- </td>
- <td>
- </td>
- </tr>
- <tr>
- <td valign="Top" align="Right">groups</td>
- <td valign="Top">
- <select multiple="1" name="user_groups.gid" size="4">
- <esql:connection>
- <esql:pool>personnel</esql:pool>
- <esql:execute-query>
- <esql:query>select gid, gname from groups order by gname</esql:query>
- <esql:results>
- <esql:row-results>
- <option>
- <xsp:attribute name="value"><esql:get-string column="gid"/></xsp:attribute>
- <esql:get-string column="gname"/>
- </option>
- </esql:row-results>
- </esql:results>
- </esql:execute-query>
- </esql:connection>
- </select>
- </td>
- </tr>
- <tr>
- <td valign="Top">
- </td>
- <td>
- </td>
- <td align="Right"><input type="submit" name="add-groups" value="OK"/></td>
- </tr>
- </tbody>
- </table>
- </form>
- </blockquote>
- -->
- <!--
- current db content
- -->
-
- <h2>Current database content</h2>
-
- <esql:connection>
- <esql:pool>personnel</esql:pool>
-
- <p>
- <sqltbl>
- <esql:execute-query>
- <esql:query>select * from user order by name, surname, uname, uid</esql:query>
- <esql:results>
- <esql:row-results>
-
- <sqltblrow>
- <name>
- <esql:get-string column="name"/>
- </name>
- <surname>
- <esql:get-string column="surname"/>
- </surname>
- <uname>
- <esql:get-string column="uname"/>
- </uname>
- <action>
- <form action="edit-groups">
- <input type="hidden" name="user.uid">
- <xsp:attribute name="value"><esql:get-string column="uid"/></xsp:attribute>
- </input>
- <input type="submit" name="edit-user" value="edit"/>
- </form>
- <form>
- <input type="hidden" name="user.uid">
- <xsp:attribute name="value"><esql:get-string column="uid"/></xsp:attribute>
- </input>
- <input type="submit" name="del-user" value="delete"/>
- </form>
- </action>
- </sqltblrow>
-
- </esql:row-results>
- </esql:results>
- <esql:error-results>
- <error><esql:get-message/></error>
- </esql:error-results>
- </esql:execute-query>
- <form method="Get">
- <sqltblrow>
- <name>
- <input type="text" name="user.name" size="20" maxsize="20">
- <xsp:attribute name="value"><!-- <xsp-request:get-parameter default="" name="user.name"/> --></xsp:attribute>
- </input>
- </name>
- <surname>
- <input type="text" name="user.surname" size="20" maxsize="20">
- <xsp:attribute name="value"><!-- <xsp-request:get-parameter default="" name="user.surname"/> --></xsp:attribute>
- </input>
- </surname>
- <uname>
- <input type="text" name="user.uname" size="20" maxsize="20">
- <xsp:attribute name="value"><!-- <xsp-request:get-parameter default="" name="user.uname"/> --></xsp:attribute>
- </input>
- </uname>
- <action>
- <select multiple="1" name="user_groups.gid" size="4">
- <esql:execute-query>
- <esql:query>select gid, gname from groups order by gname</esql:query>
- <esql:results>
- <esql:row-results>
- <option>
- <xsp:attribute name="value"><esql:get-string column="gid"/></xsp:attribute>
- <esql:get-string column="gname"/>
- </option>
- </esql:row-results>
- </esql:results>
- </esql:execute-query>
- </select>
- <input type="submit" name="add-user-groups" value="new user"/>
+ -->
+ <xsp:structure>
+ <xsp:include>java.util.Enumeration</xsp:include>
+ </xsp:structure>
+
+ <page>
+
+ <title>user-list</title>
+
+ <content>
+
+
+ <h1>Modular Database Actions</h1>
+
+ <hr/>
+
+ <p>The intention is to factor out those parts that are dependent on
+ the utilised DBMS as well as the methods used to obtain the values
+ and communicate results. Therefore three classes of adaptors
+ exist:</p>
+
+ <ol>
+ <li>Attribute Helpers read data from some source (e.g. the request
+ object or session attributes or whatever)</li>
+
+ <li>Auto Increment Helpers determine the value of a key attribute
+ column in a database if it's is of auto increment type. This
+ could be by querying the database, reading from an arbitrary
+ source (e.g. request object) or just skipping the column when
+ inserting a row and querying the database afterwards. This
+ needs to be done e.g. for Informix's SERIAL or HSQLDB's
+ IDENTITY column types.</li>
+
+ <li>Output Helpers send the data to an arbitrary
+ destination. Again, this could be request attributes or
+ anything else. When the database transaction finishes, it is
+ signalled to them whether the transaction succeeded or
+ failed.</li>
+ </ol>
+ <hr/>
+
+ <h2>Current database content</h2>
+
+ <esql:connection>
+ <esql:pool>personnel</esql:pool>
+
+ <p>
+ <sqltbl>
+ <esql:execute-query>
+ <esql:query>select * from user order by name, firstname, uname, uid</esql:query>
+ <esql:results>
+ <esql:row-results>
+
+ <sqltblrow>
+ <name>
+ <esql:get-string column="name"/>
+ </name>
+ <firstname>
+ <esql:get-string column="firstname"/>
+ </firstname>
+ <uname>
+ <esql:get-string column="uname"/>
+ </uname>
+ <action>
+ <form action="edit-groups">
+ <input type="hidden" name="user.uid">
+ <xsp:attribute name="value"><esql:get-string column="uid"/></xsp:attribute>
+ </input>
+ <input type="submit" name="edit-user" value="edit"/>
+ </form>
+ <form>
+ <input type="hidden" name="user.uid">
+ <xsp:attribute name="value"><esql:get-string column="uid"/></xsp:attribute>
+ </input>
+ <input type="submit" name="del-user" value="delete"/>
+ </form>
</action>
- </sqltblrow>
- </form>
- </sqltbl>
- </p>
-
- <p>
- <sqltbl>
- <esql:execute-query>
- <esql:query>select * from groups order by gname</esql:query>
- <esql:results>
- <esql:row-results>
- <form>
- <sqltblrow>
- <gname>
- <input type="text" name="groups.gname">
- <xsp:attribute name="value"><esql:get-string column="gname"/></xsp:attribute>
- </input>
- <input type="hidden" name="groups.gid">
- <xsp:attribute name="value"><esql:get-string column="gid"/></xsp:attribute>
- </input>
- <input type="submit" name="upd-group" value="update"/>
- <input type="submit" name="del-group" value="delete"/>
- </gname>
- </sqltblrow>
- </form>
- </esql:row-results>
- </esql:results>
- <esql:error-results>
- <error><esql:get-message/></error>
- </esql:error-results>
- </esql:execute-query>
- <sqltblrow>
- <gname>
- <form>
- <input type="text" name="groups.gname" size="20" maxsize="20">
- <xsp:attribute name="value"><!-- <xsp-request:get-parameter default="" name="groups.gname"/> --></xsp:attribute>
- </input>
- <input type="submit" name="add-group" value="new group"/>
- </form>
- </gname>
- </sqltblrow>
- </sqltbl>
- </p>
-
- <p>
- <form>
- <esql:execute-query>
- <esql:query>select user.uid, user.uname, groups.gid, groups.gname from user, user_groups, groups where user.uid=user_groups.uid and user_groups.gid=groups.gid order by user.uname, groups.gname</esql:query>
- <esql:results>
- <sqltbl>
- <esql:row-results>
- <form action="edit-groups">
- <sqltblrow>
- <uname>
- <input type="hidden" name="user.uid">
- <xsp:attribute name="value"><esql:get-string column="uid"/></xsp:attribute>
- </input>
- <esql:get-string column="uname"/>
- </uname>
- <gname><esql:get-string column="gname"/></gname>
- <action>
- <input value="edit groups" type="submit"/>
- </action>
- </sqltblrow>
- </form>
- </esql:row-results>
- </sqltbl>
- </esql:results>
- <esql:error-results>
- <error><esql:get-message/></error>
- </esql:error-results>
- </esql:execute-query>
- </form>
- </p>
- </esql:connection>
-
- <hr/>
-
- <p><h3>Request Attributes</h3></p>
- <p>
- <table border="0">
- <tbody>
- <xsp:logic>{
- Enumeration e=request.getAttributeNames();
- while ( e.hasMoreElements() ) {
- String attribute = (String) e.nextElement();
- Object value = request.getAttribute(attribute);
- <tr>
- <td align="right"><xsp:expr>attribute</xsp:expr></td>
- <td>="<xsp:expr>value</xsp:expr>"</td>
- </tr>
- }
- }</xsp:logic>
- </tbody>
- </table><br/>
- </p>
- <hr/>
-
- <p><h3>Request Parameters</h3></p>
- <p>
- <table border="0">
- <tbody>
- <xsp:logic>{
- Enumeration e=request.getParameterNames();
- while ( e.hasMoreElements() ) {
- String attribute = (String) e.nextElement();
- Object[] value = request.getParameterValues(attribute);
- for (int i=0; i < value.length; i++) {
- <tr>
- <td align="right"><xsp:expr>attribute</xsp:expr>[<xsp:expr>i</xsp:expr>]</td>
- <td>="<xsp:expr>value[i]</xsp:expr>"</td>
- </tr>
- }
- }
- }</xsp:logic>
- </tbody>
- </table><br/>
- </p>
-
- <hr/>
-
-
- </content>
+ </sqltblrow>
+
+ </esql:row-results>
+ </esql:results>
+ <esql:error-results>
+ <error><esql:get-message/></error>
+ </esql:error-results>
+ </esql:execute-query>
+ <form method="Get">
+ <sqltblrow>
+ <name>
+ <input type="text" name="user.name" size="20" maxsize="20">
+ <xsp:attribute name="value"><!-- <xsp-request:get-parameter default="" name="user.name"/> --></xsp:attribute>
+ </input>
+ </name>
+ <firstname>
+ <input type="text" name="user.firstname" size="20" maxsize="20">
+ <xsp:attribute name="value"><!-- <xsp-request:get-parameter default="" name="user.firstname"/> --></xsp:attribute>
+ </input>
+ </firstname>
+ <uname>
+ <input type="text" name="user.uname" size="20" maxsize="20">
+ <xsp:attribute name="value"><!-- <xsp-request:get-parameter default="" name="user.uname"/> --></xsp:attribute>
+ </input>
+ </uname>
+ <action>
+ <select multiple="1" name="user_groups.gid" size="4">
+ <esql:execute-query>
+ <esql:query>select gid, gname from groups order by gname</esql:query>
+ <esql:results>
+ <esql:row-results>
+ <option>
+ <xsp:attribute name="value"><esql:get-string column="gid"/></xsp:attribute>
+ <esql:get-string column="gname"/>
+ </option>
+ </esql:row-results>
+ </esql:results>
+ </esql:execute-query>
+ </select>
+ <input type="submit" name="add-user-groups" value="new user"/>
+ </action>
+ </sqltblrow>
+ </form>
+ </sqltbl>
+ </p>
+
+ <p>
+ <sqltbl>
+ <esql:execute-query>
+ <esql:query>select * from groups order by gname</esql:query>
+ <esql:results>
+ <esql:row-results>
+ <form>
+ <sqltblrow>
+ <gname>
+ <input type="text" name="groups.gname">
+ <xsp:attribute name="value"><esql:get-string column="gname"/></xsp:attribute>
+ </input>
+ <input type="hidden" name="groups.gid">
+ <xsp:attribute name="value"><esql:get-string column="gid"/></xsp:attribute>
+ </input>
+ <input type="submit" name="upd-group" value="update"/>
+ <input type="submit" name="del-group" value="delete"/>
+ </gname>
+ </sqltblrow>
+ </form>
+ </esql:row-results>
+ </esql:results>
+ <esql:error-results>
+ <error><esql:get-message/></error>
+ </esql:error-results>
+ </esql:execute-query>
+ <sqltblrow>
+ <gname>
+ <form>
+ <input type="text" name="groups.gname" size="20" maxsize="20">
+ <xsp:attribute name="value"><!-- <xsp-request:get-parameter default="" name="groups.gname"/> --></xsp:attribute>
+ </input>
+ <input type="submit" name="add-group" value="new group"/>
+ </form>
+ </gname>
+ </sqltblrow>
+ </sqltbl>
+ </p>
+
+ <p>
+ <form>
+ <esql:execute-query>
+ <esql:query>select user.uid, user.uname, groups.gid, groups.gname from user, user_groups, groups where user.uid=user_groups.uid and user_groups.gid=groups.gid order by user.uname, groups.gname</esql:query>
+ <esql:results>
+ <sqltbl>
+ <esql:row-results>
+ <form action="edit-groups">
+ <sqltblrow>
+ <uname>
+ <input type="hidden" name="user.uid">
+ <xsp:attribute name="value"><esql:get-string column="uid"/></xsp:attribute>
+ </input>
+ <esql:get-string column="uname"/>
+ </uname>
+ <gname><esql:get-string column="gname"/></gname>
+ <action>
+ <input value="edit groups" type="submit"/>
+ </action>
+ </sqltblrow>
+ </form>
+ </esql:row-results>
+ </sqltbl>
+ </esql:results>
+ <esql:error-results>
+ <error><esql:get-message/></error>
+ </esql:error-results>
+ </esql:execute-query>
+ </form>
+ </p>
+ </esql:connection>
+
+ <hr/>
+
+ <p><h3>Request Attributes</h3></p>
+ <p>
+ <table border="0">
+ <tbody>
+ <xsp:logic>{
+ Enumeration e=request.getAttributeNames();
+ while ( e.hasMoreElements() ) {
+ String attribute = (String) e.nextElement();
+ Object value = request.getAttribute(attribute);
+ <tr>
+ <td align="right"><xsp:expr>attribute</xsp:expr></td>
+ <td>="<xsp:expr>value</xsp:expr>"</td>
+ </tr>
+ }
+ }</xsp:logic>
+ </tbody>
+ </table>
+ </p>
+
+ <hr/>
+
+ <p><h3>Request Parameters</h3></p>
+ <p>
+ <table border="0">
+ <tbody>
+ <xsp:logic>{
+ Enumeration e=request.getParameterNames();
+ while ( e.hasMoreElements() ) {
+ String attribute = (String) e.nextElement();
+ Object[] value = request.getParameterValues(attribute);
+ for (int i=0; i < value.length; i++) {
+ <tr>
+ <td align="right"><xsp:expr>attribute</xsp:expr>[<xsp:expr>i</xsp:expr>]</td>
+ <td>="<xsp:expr>value[i]</xsp:expr>"</td>
+ </tr>
+ }
+ }
+ }</xsp:logic>
+ </tbody>
+ </table><br/>
+ </p>
+
+ <hr/>
+
+ </content>
</page>
</xsp:page>
1.2 +70 -951 xml-cocoon2/scratchpad/src/org/apache/cocoon/acting/ModularDatabaseAddAction.java
Index: ModularDatabaseAddAction.java
===================================================================
RCS file: /home/cvs/xml-cocoon2/scratchpad/src/org/apache/cocoon/acting/ModularDatabaseAddAction.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- ModularDatabaseAddAction.java 2001/11/19 16:28:33 1.1
+++ ModularDatabaseAddAction.java 2001/11/23 10:50:35 1.2
@@ -7,64 +7,19 @@
*****************************************************************************/
package org.apache.cocoon.acting;
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.Class;
-import java.net.URL;
+import java.util.Map;
import java.sql.Connection;
import java.sql.PreparedStatement;
-import java.sql.Statement;
-import java.sql.ResultSet;
import java.sql.SQLException;
-import java.sql.Timestamp;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.List;
-import java.util.LinkedList;
-import java.util.ListIterator;
-import java.util.Enumeration;
-import java.util.Collections;
-import java.util.Set;
-import java.util.SortedSet;
-import java.util.TreeSet;
-import java.io.IOException;
+import org.apache.cocoon.util.HashMap;
-import org.apache.avalon.framework.activity.Disposable;
-import org.apache.avalon.framework.component.Component;
import org.apache.avalon.framework.component.ComponentException;
-import org.apache.avalon.framework.component.ComponentManager;
-import org.apache.avalon.framework.configuration.Configurable;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
-import org.apache.avalon.framework.configuration.DefaultConfiguration;
-import org.apache.avalon.framework.context.Context;
-import org.apache.avalon.framework.context.ContextException;
-import org.apache.avalon.framework.context.Contextualizable;
-import org.apache.avalon.framework.parameters.Parameters;
-import org.apache.avalon.framework.thread.ThreadSafe;
-import org.apache.avalon.excalibur.component.ExcaliburComponentSelector;
-import org.apache.avalon.excalibur.component.ExcaliburComponentManager;
-import org.apache.avalon.excalibur.component.RoleManager;
-import org.apache.avalon.excalibur.component.DefaultRoleManager;
-import org.apache.avalon.excalibur.datasource.DataSourceComponent;
-
-import org.apache.cocoon.Constants;
-import org.apache.cocoon.ProcessingException;
-import org.apache.cocoon.components.classloader.RepositoryClassLoader;
-import org.apache.cocoon.components.url.URLFactory;
+
import org.apache.cocoon.environment.Request;
-import org.apache.cocoon.environment.Redirector;
-import org.apache.cocoon.environment.SourceResolver;
-import org.apache.cocoon.generation.ImageDirectoryGenerator;
-import org.apache.cocoon.util.ClassUtils;
-import org.apache.cocoon.util.HashMap;
-import org.apache.cocoon.selection.Selector;
-import org.apache.cocoon.acting.ModularDatabaseAccess.AccessHelper;
-import org.apache.cocoon.acting.ModularDatabaseAccess.KeyAttributeHelper;
-import org.apache.cocoon.acting.ModularDatabaseAccess.AttributeHelper;
-import org.apache.cocoon.acting.ModularDatabaseAccess.OutputHelper;
+import org.apache.cocoon.acting.ModularDatabaseAccess.AutoIncrementHelper;
/**
* Adds record in a database. The action can update one or more tables,
@@ -83,772 +38,101 @@
* components can utilize the helper components.
*
* @author <a href="mailto:haul@apache.org">Christian Haul</a>
- * @version CVS $Revision: 1.1 $ $Date: 2001/11/19 16:28:33 $
+ * @version CVS $Revision: 1.2 $ $Date: 2001/11/23 10:50:35 $
*/
public class ModularDatabaseAddAction
- extends AbstractDatabaseAction
- implements Disposable, ThreadSafe, Contextualizable
+ extends ModularDatabaseAction
{
-
- // ========================================================================
- // inner helper classes
- // ========================================================================
-
- protected class Column {
- boolean isKey = false;
- boolean isSet = false;
- String mode = null;
- Configuration modeConf = null;
- Configuration columnConf = null;
- }
-
- protected class CacheHelper {
- public String queryString = null;
- public int setMaster = -1;
- public boolean isSet = false;
- public int noOfKeys = 0;
- public Column[] columns = null;
-
- public CacheHelper( int cols ) {
- this(0,cols);
- }
-
- public CacheHelper( int keys, int cols ) {
- noOfKeys = keys;
- columns = new Column[cols];
- for ( int i=0; i<cols; i++ ) {
- columns[i] = new Column();
- }
- }
- }
-
-
- protected class LookUpKey {
- public Configuration tableConf = null;
- public Map modeTypes = null;
-
- public LookUpKey( Configuration tableConf, Map modeTypes ) {
- this.tableConf = tableConf;
- this.modeTypes = modeTypes;
- }
- }
-
-
-// /**
-// * This inner class stores extracted configuration data for a
-// * table column.
-// */
-// protected class SetHelper {
-// public int master = -1;
-// public String mode = null;
-// public Configuration conf = null;
-// public int numbKeys = 0;
-// public boolean[] isKey;
-// public boolean[] isSet;
-// public String[] modes = null;
-// public Configuration[] modeConf = null;
-
-// SetHelper( int cols ) {
-// this(0,cols);
-// }
-
-// SetHelper( int keys, int cols ) {
-// numbKeys = keys;
-// isKey = new boolean[cols];
-// isSet = new boolean[cols];
-// modes = new String[cols];
-// modeConf = new Configuration[cols];
-// }
-// }
-
- // ========================================================================
- // constants
- // ========================================================================
-
- private static final String LOCATION = "org.apache.cocoon.acting.ModularDatabaseAddAction";
- private static final int BYTE_ARRAY_SIZE = 1024;
-
- static final Integer MODE_INSERT = new Integer( 0 );
- static final Integer MODE_OTHERS = new Integer( 1 );
- static final Integer MODE_OUTPUT = new Integer( 2 );
-
- // ========================================================================
- // instance vars
- // ========================================================================
-
- // please ignore component management as I know this is ugly and I
- // hope that this duty is taken by the sitemap in short term.
- // please ignore ====>
- protected RoleManager roleManager;
- private Configuration defaultConfig;
-
- protected Context context;
-
- /** The component manager instance */
- protected ExcaliburComponentManager manager2;
-
- /** The URLFactory instance */
- protected URLFactory urlFactory;
-
- protected ExcaliburComponentSelector modeMapping = null;
- protected ExcaliburComponentSelector outputMapping = null;
-
- // default modes for other / insert operations
- protected HashMap defaultModeNames = new HashMap( 3 );
-
- // <==== please ignore
- //
-
- protected final Map cachedQueryData = new HashMap();
-
-
- //
- // please ignore ====>
-
- // ========================================================================
- // setup / class loading
- // (basically copied from AbstractSitemap)
- // This is ugly. Please ignore. Helpers should be handled at sitemap level
- // so that other components can share them.
- // ========================================================================
-
/**
- * Set the role manager
- */
- public void setRoleManager(
- RoleManager roles,
- Configuration config
- )
- {
- this.roleManager = roles;
- this.defaultConfig = config;
- }
-
- /**
- * Set the current <code>ComponentManager</code> instance used by this
- * <code>Composable</code>.
- */
- public void compose(
- ComponentManager manager
- )
- throws ComponentException
- {
- super.compose( manager );
- getLogger().debug("compose");
- this.manager2 = new ExcaliburComponentManager(manager);
- this.manager2.setLogger(getLogger());
- this.manager2.contextualize(this.context);
- this.manager2.setRoleManager(this.roleManager);
-
- try {
- if (this.defaultConfig != null) {
- this.manager2.configure(this.defaultConfig);
- }
- this.urlFactory = (URLFactory)manager.lookup(URLFactory.ROLE);
- this.modeMapping = new ExcaliburComponentSelector();
- this.outputMapping = new ExcaliburComponentSelector();
- this.setupSelector(this.modeMapping);
- this.setupSelector(this.outputMapping);
- this.manager2.addComponentInstance(Selector.ROLE + "Selector", this.modeMapping);
- this.manager2.addComponentInstance(Selector.ROLE + "Selector", this.outputMapping);
- } catch (Exception e) {
- getLogger().error("cannot obtain the Component", e);
- throw new ComponentException("cannot obtain the URLFactory", e);
- }
- }
-
- private void setupSelector(
- ExcaliburComponentSelector selector
- )
- throws Exception
- {
- selector.setLogger(getLogger());
- selector.contextualize(this.context);
- selector.setRoleManager(this.roleManager);
- selector.compose(this.manager2);
- }
-
- public void contextualize(
- Context context
- )
- throws ContextException
- {
- this.context = context;
- }
-
- /**
- * Return the component manager for this sitemap
- */
- public ComponentManager getComponentManager()
- {
- return this.manager2;
- }
-
- /**
- * Release all components.
- */
- public void dispose()
- {
- if (this.urlFactory != null) {
- manager.release((Component)this.urlFactory);
- }
- if (this.modeMapping != null) {
- manager2.release((Component)this.modeMapping);
- }
- if (this.outputMapping != null) {
- manager2.release((Component)this.outputMapping);
- }
- manager2.dispose();
- }
-
-
- /**
- * Configure modes that are used to delegate database specific methods
- * and other modes.
+ * set all necessary ?s and execute the query
*/
- public void configure(
- Configuration conf
- )
- throws ConfigurationException
+ protected void processRow (
+ Request request,
+ Connection conn,
+ PreparedStatement statement,
+ Configuration table,
+ CacheHelper queryData,
+ Object[][] columnValues,
+ int rowIndex,
+ Map results
+ )
+ throws SQLException,
+ ConfigurationException,
+ Exception
{
- try {
- getLogger().debug("MDAA: configure");
- LinkedList hints = new LinkedList();
- if (conf != null) {
- String val = null;
- String nodeName = null;
- Configuration[] parameters = conf.getChildren();
- this.settings = new HashMap(parameters.length);
- for ( int i = 0; i < parameters.length; i++) {
- nodeName= parameters[i].getName();
- getLogger().debug("configure -- " + nodeName);
- if ( nodeName != null ) {
- if ( "mode".equals(nodeName.trim()) || "output".equals(nodeName.trim())) {
- String modeName = parameters[i].getAttribute("name");
- String src = parameters[i].getAttribute("src");
- if (modeName!=null && src!=null) {
- Configuration modeConfig = parameters[i];
- if (modeConfig == null) {
- modeConfig = this.defaultConfig;
- }
- getLogger().debug("load -- " + modeName + " -> " + src);
- if ( "mode".equals(nodeName.trim())) {
- this.load_component(modeMapping, modeName, src, modeConfig);
- hints.add(modeName);
- } else {
- this.load_component(outputMapping, modeName, src, modeConfig);
- if ( !defaultModeNames.containsKey( MODE_OUTPUT ) ) {
- defaultModeNames.put( MODE_OUTPUT, modeName );
- }
- }
- }
- } else {
- val = parameters[i].getValue();
- this.settings.put(nodeName, val);
- }
- }
- }
- }
-
- this.modeMapping.initialize();
- this.outputMapping.initialize();
- this.manager2.initialize();
-
- ListIterator li = hints.listIterator();
- while ( li.hasNext() ) {
- String modeName = (String) li.next();
- Component helper = modeMapping.select( modeName );
- if ( !defaultModeNames.containsKey( MODE_OTHERS ) && helper instanceof AttributeHelper ) {
- defaultModeNames.put( MODE_OTHERS, modeName );
- getLogger().debug(modeName + " default mode for delete / update operations");
- }
-
- if ( !defaultModeNames.containsKey( MODE_INSERT ) && helper instanceof KeyAttributeHelper ) {
- defaultModeNames.put( MODE_INSERT, modeName );
- getLogger().debug(modeName + " default mode for insert operations");
- }
- modeMapping.release(helper);
- }
- if ( !defaultModeNames.containsKey( MODE_OTHERS ) ||
- !defaultModeNames.containsKey( MODE_INSERT ) ||
- !defaultModeNames.containsKey( MODE_OUTPUT )
- ) {
- throw new ConfigurationException("Not all default modes are configured:"
- + ( defaultModeNames.containsKey( MODE_INSERT ) ? " insert mode" : "" )
- + ( defaultModeNames.containsKey( MODE_OTHERS ) ? " others" : "" )
- + ( defaultModeNames.containsKey( MODE_OUTPUT ) ? " output" : "" )
- );
+ int currentIndex = 1;
+ for (int i = 0; i < queryData.columns.length; i++) {
+ Column col = queryData.columns[i];
+ if ( col.isAutoIncrement && col.isKey ) {
+ currentIndex += setKeyAuto( table, col, currentIndex, rowIndex,
+ conn, statement, request, results );
+ } else {
+ this.setColumn( statement, currentIndex, request, col.columnConf,
+ getOutputName( table, col.columnConf, rowIndex ),
+ columnValues[ i ][ ( col.isSet ? rowIndex : 0 ) ],
+ rowIndex);
+ currentIndex++;
}
-
- } catch (Exception e) {
- throw new ConfigurationException(e.toString());
}
- }
-
-
- /**
- * Load a component.
- *
- * @param hint Object to identify this component
- * @param classURL component's class name / URL
- * @param config configuration for this component
- */
- private void load_component(
- ExcaliburComponentSelector selector,
- Object hint,
- String classURL,
- Configuration config
- )
- throws Exception
- {
- Class clazz = null;
- //FIXME(GP): Is it true that a class name containing a colon should be an URL?
- if (classURL.indexOf(':') > 1) {
- URL url = urlFactory.getURL(classURL);
- byte[] b = getByteArrayFromStream(url.openStream());
- clazz = ((RepositoryClassLoader)ClassUtils.getClassLoader()).defineClass(b);
- } else {
- clazz = ClassUtils.loadClass(classURL);
- }
- if (!Component.class.isAssignableFrom(clazz)) {
- throw new IllegalAccessException("Object " + classURL + " is not a Component");
+ statement.execute();
+ // get resulting ids for autoincrement columns
+ for (int i = 0; i < queryData.columns.length; i++) {
+ if ( queryData.columns[i].isAutoIncrement && queryData.columns[i].isKey ) {
+ storeKeyValue( table, queryData.columns[i], rowIndex,
+ conn, statement, request, results );
+ }
}
- selector.addComponent(hint, clazz, config);
- }
-
- /**
- * Helper to read in a class
- */
- private byte[] getByteArrayFromStream(
- InputStream stream
- )
- {
- List list = new ArrayList();
- byte[] b = new byte[BYTE_ARRAY_SIZE];
- int last = 0;
- try {
- while ((last = stream.read(b)) == BYTE_ARRAY_SIZE) {
- list.add(b);
- b = new byte[BYTE_ARRAY_SIZE];
- }
- } catch (IOException ioe) {
- getLogger().error("cannot read class byte stream", ioe);
- }
- list.add(b);
- int listSize = list.size();
- b = new byte[(listSize - 1) * BYTE_ARRAY_SIZE + last];
- int i;
- for (i = 0; i < listSize - 1; i++) {
- System.arraycopy(list.get(i), 0, b, i * BYTE_ARRAY_SIZE, BYTE_ARRAY_SIZE);
- }
- System.arraycopy(list.get(i), 0, b, i * BYTE_ARRAY_SIZE, last);
- return b;
}
- // <==== please ignore
- //
-
- // ========================================================================
- // protected utility methods
- // ========================================================================
-
-
- /**
- * Returns the actual name of the parameter. If the name contains
- * no wildcard, the param is returned untouched, otherwise the
- * wildcard value is substituted for the * character. This probably
- * doesn't deserve a method unto itself, but I can imagine wanting
- * to use a more sophisticated matching and substitution algorithm.
- *
- * @param param the name of the parameter, possibly with a wildcard char
- * @param wildcard the wildcard value
- * @return the actual name of the parameter
- */
- String getActualParam(
- String param,
- String wildcard
- )
- {
- int index;
- if ((index = param.indexOf('*')) != -1) {
- return param.substring(0,index)+wildcard+param.substring(index+1);
- } else {
- return param;
- }
- }
-
-
/**
- * override super's method since we prefer to get the datasource
- * from defaults first or from sitemap parameters rather than from
- * descriptor file.
+ * determine which mode to use as default mode
+ * here: INSERT
+ * highly specific to operation INSERT / UPDATE / DELETE / SELECT
*/
- protected DataSourceComponent getDataSource( Configuration conf, Parameters parameters )
- throws ComponentException
+ protected String selectMode (
+ boolean isAutoIncrement,
+ HashMap modes
+ )
{
- String sourceName = parameters.getParameter("connection", (String) settings.get("connection"));
- if ( sourceName == null ) {
- return getDataSource( conf );
- } else {
- getLogger().debug("Using datasource: "+sourceName);
- return (DataSourceComponent) this.dbselector.select(sourceName);
- }
- }
-
- /**
- * Store a key/value pair in the request attributes. We prefix the key
- * with the name of this class to prevent potential name collisions.
- * This method overrides super class' method to allow an OutputHelper
- * to take care of what to do with the values.
- */
- void setRequestAttribute(Request request, String key, Object value) {
- try {
- OutputHelper oh = (OutputHelper) outputMapping.select( (String) defaultModeNames.get( MODE_OUTPUT ) );
- oh.setAttribute(request, key, value);
- outputMapping.release(oh);
- } catch (Exception e) {
- getLogger()
- .warn( "Could not select output mode "
- + (String) defaultModeNames.get( MODE_OUTPUT )
- + ":" + e.getMessage() );
- }
+ if ( isAutoIncrement )
+ return (String) modes.get( MODE_AUTOINCR );
+ else
+ return (String) modes.get( MODE_OTHERS );
}
/**
- * Retrieve a value from the request attributes.
- * This method overrides super class' method to allow an OutputHelper
- * to take care of where to get the values.
+ * determine whether autoincrement columns should be honoured by
+ * this operation. This is usually snsible only for INSERTs.
*/
- Object getRequestAttribute(Request request, String key) {
- Object value = null;
- try {
- OutputHelper oh = (OutputHelper) outputMapping.select( (String) defaultModeNames.get( MODE_OUTPUT ) );
- value = oh.getAttribute(request, key);
- outputMapping.release(oh);
- } catch (Exception e) {
- getLogger()
- .warn( "Could not select output mode "
- + (String) defaultModeNames.get( MODE_OUTPUT )
- + ":" + e.getMessage());
- }
- return value;
- }
+ protected boolean honourAutoIncrement() { return true; }
- // ========================================================================
- // main method
- // ========================================================================
-
-
/**
- * Add a record to the database. This action assumes that
- * the file referenced by the "descriptor" parameter conforms
- * to the AbstractDatabaseAction specifications.
+ * Fetch all values for all columns that are needed to do the
+ * database operation.
*/
- public Map act(
- Redirector redirector,
- SourceResolver resolver,
- Map objectModel,
- String source,
- Parameters param
- )
- throws Exception
- {
- DataSourceComponent datasource = null;
- Connection conn = null;
- Map results = new HashMap();
-
- // read global parameter settings
- boolean reloadable = Constants.DESCRIPTOR_RELOADABLE_DEFAULT;
- Request request = (Request) objectModel.get(Constants.REQUEST_OBJECT);
-
- getLogger().debug("MDAA: act");
- if (this.settings.containsKey("reloadable"))
- reloadable = Boolean.getBoolean((String) this.settings.get("reloadable"));
- // read local parameter settings
- try {
- Configuration conf =
- this.getConfiguration(param.getParameter("descriptor", (String) this.settings.get("descriptor")),
- param.getParameterAsBoolean("reloadable",reloadable));
-
- datasource = this.getDataSource(conf, param);
- conn = datasource.getConnection();
- if (conn.getAutoCommit() == true) {
- conn.setAutoCommit(false);
- }
-
- Configuration[] tables = conf.getChildren("table");
- String tablesetname = param.getParameter("table-set", (String) this.settings.get("table-set"));
- Map set_tables = null; // default to old behaviour
-
- HashMap modeTypes = null;
-
- if (tablesetname != null) {
- // new set based behaviour
- Configuration[] tablesets = conf.getChildren("table-set");
- String setname = null;
- boolean found = false;
-
- // find tables contained in tableset
- int j = 0;
- for (j=0; j<tablesets.length; j++) {
- setname = tablesets[j].getAttribute ("name", "");
- if (tablesetname.trim().equals (setname.trim ())) {
- found = true;
- break;
- }
- }
- if (!found) {
- throw new IOException(" given set " + tablesetname + " does not exists in a description file.");
- }
-
- Configuration[] set = tablesets[j].getChildren("table");
-
- // construct a Map that contains the names of the tables
- // contained in the requested tableset
- set_tables = new HashMap(set.length);
- for (int i=0; i<set.length; i++) {
- // look for alternative modes
- modeTypes = new HashMap(2);
- modeTypes.put( MODE_INSERT, set[i].getAttribute( "add-mode", "insert" ) );
- modeTypes.put( MODE_OTHERS, set[i].getAttribute( "others-mode", "others" ) );
- set_tables.put(set[i].getAttribute("name",""), modeTypes);
- }
- } else {
- modeTypes = new HashMap(2);
- modeTypes.put( MODE_INSERT, "insert" );
- modeTypes.put( MODE_OTHERS, "others" );
- };
- for (int i=0; i<tables.length; i++) {
- if (set_tables == null || set_tables.containsKey(tables[i].getAttribute("name"))) {
- if (tablesetname != null) {
- modeTypes = (HashMap) set_tables.get(tables[i].getAttribute("name"));
- }
- processTable( tables[i], conn, request, results, modeTypes );
- }
- }
-
- conn.commit();
- OutputHelper oh = (OutputHelper) outputMapping.select( (String) defaultModeNames.get( MODE_OUTPUT ) );
- oh.commit(request);
- outputMapping.release(oh);
- } catch (Exception e) {
- if (conn != null) {
- try {
- getLogger().debug( "Rolling back transaction. Caused by " + e.getMessage() );
- conn.rollback();
- OutputHelper oh = (OutputHelper) outputMapping.select( (String) defaultModeNames.get( MODE_OUTPUT ) );
- oh.rollback(request, e);
- outputMapping.release(oh);
- } catch (SQLException se) {
- getLogger().debug("There was an error rolling back the transaction", se);
- }
- }
-
- //throw new ProcessingException("Could not add record :position = " + currentIndex, e);
-
- // don't throw an exception, an error has been signalled, that should suffice
- //throw new ProcessingException("Could not add record",e);
- } finally {
- if (conn != null) {
- try {
- conn.close();
- } catch (SQLException sqe) {
- getLogger().warn("There was an error closing the datasource", sqe);
- }
- }
-
- if (datasource != null) this.dbselector.release(datasource);
- }
-
- return Collections.unmodifiableMap(results);
- }
-
- /**
- * Inserts a row or a set of rows into the given table based on the
- * request parameters
- *
- * @param table the table's configuration
- * @param conn the database connection
- * @param request the request
- */
- void processTable(
- Configuration table,
- Connection conn,
- Request request,
- Map results,
- HashMap modeTypes
- )
- throws SQLException,
- ConfigurationException,
- Exception
- {
- PreparedStatement statement = null;
- try {
- getLogger()
- .debug( "i-mode: " + (String) modeTypes.get( MODE_INSERT ) +" (" + (String) defaultModeNames.get( MODE_INSERT ) + ") " +
- "o-mode: " + (String) modeTypes.get( MODE_OTHERS ) +" (" + (String) defaultModeNames.get( MODE_OTHERS ) + ")" );
- CacheHelper queryData = this.getQuery( table, modeTypes, defaultModeNames );
- getLogger().debug("query: "+queryData.queryString);
- statement = conn.prepareStatement(queryData.queryString);
-
- if ( !queryData.isSet ) {
- getLogger().debug("=====> single row");
- processRow ( request, conn, statement, table, queryData, -1, null, results );
- } else {
- getLogger().debug("=====> multiple rows");
- if ( queryData.setMaster == -1 ) {
- throw new ConfigurationException( "Database description configuration error: Set mode without set master" );
- }
- AccessHelper dah = (AccessHelper) modeMapping.select( queryData.columns[ queryData.setMaster ].mode );
- Set vSet = dah.getAttributeSet( table.getAttribute( "name" )
- + "."
- + queryData.columns[ queryData.setMaster ].columnConf.getAttribute( "name" ),
- queryData.columns[ queryData.setMaster ].modeConf,
- request );
- Iterator vIter = vSet.iterator();
- getLogger().debug("=====> set size is " + vSet.size());
- getLogger().debug("=====> set is empty? " + vSet.isEmpty());
- int rowIndex = 0;
- while( vIter.hasNext() ) {
- Object idx = vIter.next();
- getLogger().debug("=====> idx="+idx);
- processRow ( request, conn, statement, table, queryData, rowIndex, idx, results );
- rowIndex++;
- }
- modeMapping.release(dah);
- }
-
- } finally {
- try {
- if (statement != null) {
- statement.close();
- }
- } catch (SQLException e) {}
- }
- }
-
- /**
- * Put key values to to request attributes.
- */
-
- void storeKeyValue(
- Configuration tableConf,
- Column key,
- Object idx,
- int rowIndex,
- Connection conn,
- Statement statement,
- Request request,
- Map results
- )
- throws SQLException,
- ConfigurationException,
- ComponentException
- {
- KeyAttributeHelper dah = (KeyAttributeHelper) modeMapping.select( key.mode );
- if (!dah.includeAsValue()) {
- String keyname = getOutputName( tableConf, key.columnConf, rowIndex );
- Object value = dah.getPostValue( tableConf, key.columnConf, key.modeConf, conn, statement, request );
- getLogger().debug( "Retrieving autoincrement as " + value );
- setRequestAttribute( request, keyname, value );
- results.put( key.columnConf.getAttribute("name"), String.valueOf( value ) );
+ Object[][] getColumnValues(
+ Configuration tableConf,
+ CacheHelper queryData,
+ Request request
+ )
+ throws ConfigurationException,
+ ComponentException
+ {
+ Object[][] columnValues = new Object[ queryData.columns.length ][];
+ for ( int i = 0; i < queryData.columns.length; i++ ){
+ columnValues[i] = this.getColumnValue( tableConf, queryData.columns[i], request );
}
- modeMapping.release(dah);
- }
-
- /**
- * compose name for output a long the lines of "table.column[row]"
- * or "table.column" if rowIndex is -1
- */
- String getOutputName (
- Configuration tableConf,
- Configuration columnConf,
- int rowIndex
- )
- throws ConfigurationException
- {
- return tableConf.getAttribute("name")+"."+columnConf.getAttribute("name")+(rowIndex==-1?"": "["+rowIndex+"]");
+ return columnValues;
}
-
- /**
- * Sets the key value on the prepared statement. There are four modes:
- *
- * <dl>
- * <dt>automatic (default)</dt>
- * <dd>let the database automatically create the key. note this
- * prohibits the action from storing the key value anywhere.</dd>
- * <dt>manual</dt>
- * <dd>create the key value using SELECT(dbcol)+1 from TABLE</dd>
- * <dt>form</dt>
- * <dd>look for the key value in the request parameters</dd>
- * <dt>request-attribute</dt>
- * <dd>look for the key value in the request attributes</dd>
- * </dl>
- *
- * This method has a couple of side effects. If the mode is manual,
- * the key value is stored in the request object's attributes for use
- * by other inserts. The key is the string "key:TABLENAME:DBCOL".
- * This method also puts the value of manually created keys in the results
- * map. That key is simply the value of the dbcol attribute. Note this
- * stuff is definitely up in the air.
- *
- * @param table the table's configuration object
- * @param key the key's configuration object
- * @param conn the database connection
- * @param statement the insert statement
- * @param currentIndex the position of the key column
- * @param request the request object
- * @param param the actual name of the request parameter
- * @return the number of columns by which to increment the currentIndex
- */
- int setKey(
- Configuration table,
- Column column,
- int currentIndex,
- Object idx,
- int rowIndex,
- Connection conn,
- PreparedStatement statement,
- Request request,
- Map results
- )
- throws ConfigurationException,
- SQLException,
- ComponentException,
- Exception
- {
- KeyAttributeHelper dah = (KeyAttributeHelper) modeMapping.select( column.mode );
- String keyname = table.getAttribute( "name" ) + '.' +
- column.columnConf.getAttribute( "name" ) +
- ( rowIndex == -1 ? "" : "[" + rowIndex + "]" );
-
- int columnCount = 0;
- if ( dah.includeInQuery() ) {
- if ( dah.includeAsValue() ) {
- Object value = dah.getPreValue( table, column.columnConf, column.modeConf, conn, request, ( column.isSet ? idx : null ) );
- getLogger().debug( "Setting key " + keyname + " to " + value );
- statement.setObject( currentIndex, value );
- setRequestAttribute( request, keyname, value );
- results.put( column.columnConf.getAttribute( "name" ), String.valueOf( value ) );
- columnCount = 1;
- }
- } else {
- getLogger().debug( "Automatically setting key" );
- }
- modeMapping.release( dah );
- return columnCount;
- }
-
/**
* Get the String representation of the PreparedStatement. This is
* mapped to the Configuration object itself, so if it doesn't exist,
* it will be created.
- *
* @param table the table's configuration object
* @return the insert query as a string
*/
@@ -875,7 +159,7 @@
StringBuffer queryBuffer = new StringBuffer("INSERT INTO ");
StringBuffer valueBuffer = new StringBuffer(") VALUES (");
- KeyAttributeHelper dah;
+ AutoIncrementHelper dah;
queryBuffer.append(table.getAttribute("name"));
queryBuffer.append(" (");
@@ -886,8 +170,8 @@
queryBuffer.append( ", " );
valueBuffer.append( ", " );
}
- if ( queryData.columns[i].isKey ) {
- dah = (KeyAttributeHelper) modeMapping.select( queryData.columns[i].mode );
+ if ( queryData.columns[i].isKey && queryData.columns[i].isAutoIncrement ) {
+ dah = (AutoIncrementHelper) modeMapping.select( queryData.columns[i].mode );
if ( dah.includeInQuery() ) {
actualColumns++;
queryBuffer.append( queryData.columns[i].columnConf.getAttribute( "name" ) );
@@ -917,170 +201,5 @@
return queryData;
}
-
- /**
- * Set a column based in a prepared statement by asking an AttributeHelper.
- * Delegates 'real' work to similar method in super class.
- */
- protected void setColumn(
- Configuration table,
- Column column,
- int index,
- Object idx,
- int rowIndex,
- PreparedStatement stmt,
- Request request
- )
- throws ConfigurationException,
- Exception
- {
- AttributeHelper dph = (AttributeHelper) modeMapping.select( column.mode );
- Object value = dph.getValue( table.getAttribute( "name" ) + "." + column.columnConf.getAttribute( "name" ),
- column.modeConf, request, ( column.isSet ? idx : null ) );
- modeMapping.release( dph );
- String cname = getOutputName( table, column.columnConf, rowIndex );
- getLogger().debug( "Setting column " + cname + " to " + value +" using index " + idx );
- this.setColumn( stmt, index, request, column.columnConf, cname, value, rowIndex );
- }
-
-
- /**
- * set all necessary ?s and execute the query
- */
- protected void processRow (
- Request request,
- Connection conn,
- PreparedStatement statement,
- Configuration table,
- CacheHelper queryData,
- int rowIndex,
- Object idx,
- Map results
- )
- throws SQLException,
- ConfigurationException,
- Exception
- {
-
- int currentIndex = 1;
- for (int i = 0; i < queryData.columns.length; i++) {
- if ( queryData.columns[i].isKey ) {
- currentIndex += setKey( table, queryData.columns[i], currentIndex, idx, rowIndex,
- conn, statement, request, results );
- } else {
- this.setColumn( table, queryData.columns[i], currentIndex, idx, rowIndex,
- statement, request );
- currentIndex++;
- }
- }
- statement.execute();
- // get resulting ids
- for (int i = 0; i < queryData.columns.length; i++) {
- if ( queryData.columns[i].isKey ) {
- storeKeyValue( table, queryData.columns[i], idx, rowIndex,
- conn, statement, request, results );
- }
- }
- }
-
-
-
- /**
- * Setup parsed attribute configuration object
- */
- protected void fillModes ( Configuration[] conf,
- boolean isKey,
- HashMap defaultModeNames,
- HashMap modeTypes,
- CacheHelper set
- )
- throws ConfigurationException
- {
- String setMode = null;
- int setMaster = -1;
- String setMastersMode = null;
- boolean manyrows = false;
- int offset = ( isKey ? 0: set.noOfKeys);
-
- getLogger().debug("isKey="+(isKey?"true":"false")+" set.columns.length="+set.columns.length);
- getLogger().debug(set.columns[0].getClass().getName());
-
- for ( int i = offset; i < conf.length + offset; i++ ) {
- getLogger().debug("i="+i);
- set.columns[i].columnConf = conf[ i - offset ];
- set.columns[i].modeConf = getMode( set.columns[i].columnConf, selectMode( isKey, modeTypes ) );
- set.columns[i].mode = ( set.columns[i].modeConf != null ?
- set.columns[i].modeConf.getAttribute( "name", selectMode( isKey, defaultModeNames ) ) : selectMode( isKey, defaultModeNames ) );
- set.columns[i].isSet = false;
- set.columns[i].isKey = isKey;
- // Determine set mode for a whole column ...
- setMode = set.columns[i].columnConf.getAttribute("set", null); // master vs slave vs null
- if ( setMode == null && set.columns[i].modeConf != null ) {
- // ... or for each mode individually
- setMode = set.columns[i].modeConf.getAttribute("set", null);
- }
- if ( setMode != null ) {
- manyrows = true;
- set.columns[i].isSet = true;
- set.isSet = true;
- if ( setMode.equals("master") ) {
- set.setMaster = i;
- }
- }
- }
- }
-
-
- /**
- * determine which mode to use as default mode
- * here: INSERT
- * highly specific to operation INSERT / UPDATE / DELETE / SELECT
- */
-
- protected String selectMode (
- boolean isKeyColumns,
- HashMap modes
- )
- {
- if (isKeyColumns)
- return (String) modes.get( MODE_INSERT );
- else
- return (String) modes.get( MODE_OTHERS );
- }
-
-
-
- /**
- * Choose a mode configuration based on its name.
- * @param conf Configuration (i.e. a column's configuration) that might have
- * several children configurations named "mode".
- * @param type desired type (i.e. every mode has a type attribute), find the first
- * mode that has a compatible type. Known types are "insert", used for key columns
- * when new data is inserted, "others" used for all other situations (i.e. non key
- * columns or non insert operations with key columns). Special mode "all" matches
- * all queried types.
- * @return configuration that has desired type or type "all" or null.
- */
- protected Configuration getMode(
- Configuration conf,
- String type
- ) throws ConfigurationException
- {
- String modeAll = "all";
- Configuration[] modes = conf.getChildren("mode");
- Configuration modeConfig = null;;
-
- for ( int i=0; i<modes.length; i++ ) {
- String modeType = modes[i].getAttribute("type", "others");
- getLogger().debug("requested mode is \""+type+"\" found \""+modeType+"\"");
- if ( modeType.equals(type) || modeType.equals(modeAll)) {
- getLogger().debug("returning "+modeType);
- modeConfig = modes[i];
- break;
- };
- }
-
- return modeConfig;
- }
}
1.2 +42 -14 xml-cocoon2/scratchpad/src/org/apache/cocoon/acting/ModularDatabaseDeleteAction.java
Index: ModularDatabaseDeleteAction.java
===================================================================
RCS file: /home/cvs/xml-cocoon2/scratchpad/src/org/apache/cocoon/acting/ModularDatabaseDeleteAction.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- ModularDatabaseDeleteAction.java 2001/11/19 16:28:33 1.1
+++ ModularDatabaseDeleteAction.java 2001/11/23 10:50:35 1.2
@@ -28,10 +28,10 @@
* @author <a href="mailto:bloritsch@apache.org">Berin Loritsch</a>
* @author <a href="mailto:balld@apache.org">Donald Ball</a>
* @author <a href="mailto:haul@apache.org">Christian Haul</a>
- * @version CVS $Revision: 1.1 $ $Date: 2001/11/19 16:28:33 $
+ * @version CVS $Revision: 1.2 $ $Date: 2001/11/23 10:50:35 $
*/
public class ModularDatabaseDeleteAction
- extends ModularDatabaseAddAction
+ extends ModularDatabaseAction
{
/**
@@ -41,7 +41,7 @@
*/
protected String selectMode (
- boolean isKeyColumns,
+ boolean isAutoIncrement,
HashMap modes
)
{
@@ -49,7 +49,38 @@
}
+ /**
+ * determine whether autoincrement columns should be honoured by
+ * this operation. This is usually snsible only for INSERTs.
+ */
+ protected boolean honourAutoIncrement() { return false; }
+
+
+ /**
+ * Fetch all values for all key columns that are needed to do the
+ * database operation.
+ */
+ Object[][] getColumnValues(
+ Configuration tableConf,
+ CacheHelper queryData,
+ Request request
+ )
+ throws ConfigurationException,
+ ComponentException
+ {
+ Object[][] columnValues = new Object[ queryData.columns.length ][];
+ for ( int i = 0; i < queryData.columns.length; i++ ){
+ if ( queryData.columns[i].isKey ) {
+ columnValues[i] = this.getColumnValue( tableConf, queryData.columns[i], request );
+ } else {
+ // columnValues[i] = new Object[1]; // this should not be needed
+ }
+ }
+ return columnValues;
+ }
+
+
/**
* Get the String representation of the PreparedStatement. This is
* mapped to the Configuration object itself, so if it doesn't exist,
@@ -106,8 +137,8 @@
PreparedStatement statement,
Configuration table,
CacheHelper queryData,
+ Object[][] columnValues,
int rowIndex,
- Object idx,
Map results
)
throws SQLException,
@@ -119,19 +150,16 @@
// ordering is different for DELETE just needs keys
for (int i = 0; i < queryData.columns.length; i++) {
- if ( queryData.columns[i].isKey ) {
- currentIndex += setKey( table, queryData.columns[i], currentIndex, idx, rowIndex,
- conn, statement, request, results );
+ Column col = queryData.columns[i];
+ if ( col.isKey ) {
+ this.setColumn( statement, currentIndex, request, col.columnConf,
+ getOutputName( table, col.columnConf, rowIndex ),
+ columnValues[ i ][ ( col.isSet ? rowIndex : 0 ) ],
+ rowIndex);
+ currentIndex++;
}
}
statement.execute();
- // get resulting ids
- for (int i = 0; i < queryData.columns.length; i++) {
- if ( queryData.columns[i].isKey ) {
- storeKeyValue( table, queryData.columns[i], idx, rowIndex,
- conn, statement, request, results );
- }
- }
}
}
1.2 +41 -12 xml-cocoon2/scratchpad/src/org/apache/cocoon/acting/ModularDatabaseSelectAction.java
Index: ModularDatabaseSelectAction.java
===================================================================
RCS file: /home/cvs/xml-cocoon2/scratchpad/src/org/apache/cocoon/acting/ModularDatabaseSelectAction.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- ModularDatabaseSelectAction.java 2001/11/19 16:28:33 1.1
+++ ModularDatabaseSelectAction.java 2001/11/23 10:50:35 1.2
@@ -36,10 +36,10 @@
* @author <a href="mailto:bloritsch@apache.org">Berin Loritsch</a>
* @author <a href="mailto:balld@apache.org">Donald Ball</a>
* @author <a href="mailto:haul@apache.org">Christian Haul</a>
- * @version CVS $Revision: 1.1 $ $Date: 2001/11/19 16:28:33 $
+ * @version CVS $Revision: 1.2 $ $Date: 2001/11/23 10:50:35 $
*/
public class ModularDatabaseSelectAction
- extends ModularDatabaseAddAction
+ extends ModularDatabaseAction
{
/**
@@ -49,7 +49,7 @@
*/
protected String selectMode (
- boolean isKeyColumns,
+ boolean isAutoIncrement,
HashMap modes
)
{
@@ -57,7 +57,13 @@
}
+ /**
+ * determine whether autoincrement columns should be honoured by
+ * this operation. This is usually snsible only for INSERTs.
+ */
+ protected boolean honourAutoIncrement() { return false; }
+
/**
* Get the String representation of the PreparedStatement. This is
* mapped to the Configuration object itself, so if it doesn't exist,
@@ -122,6 +128,30 @@
/**
+ * Fetch all values for all key columns that are needed to do the
+ * database operation.
+ */
+ Object[][] getColumnValues(
+ Configuration tableConf,
+ CacheHelper queryData,
+ Request request
+ )
+ throws ConfigurationException,
+ ComponentException
+ {
+ Object[][] columnValues = new Object[ queryData.columns.length ][];
+ for ( int i = 0; i < queryData.columns.length; i++ ){
+ if ( queryData.columns[i].isKey ) {
+ columnValues[i] = this.getColumnValue( tableConf, queryData.columns[i], request );
+ } else {
+ // columnValues[i] = new Object[1]; // this should not be needed
+ }
+ }
+ return columnValues;
+ }
+
+
+ /**
* set all necessary ?s and execute the query
*/
protected void processRow (
@@ -130,8 +160,8 @@
PreparedStatement statement,
Configuration table,
CacheHelper queryData,
+ Object[][] columnValues,
int rowIndex,
- Object idx,
Map results
)
throws SQLException,
@@ -143,17 +173,16 @@
// ordering is different for SELECT just needs keys
for (int i = 0; i < queryData.columns.length; i++) {
- if ( queryData.columns[i].isKey ) {
- currentIndex += setKey( table, queryData.columns[i], currentIndex, idx, rowIndex,
- conn, statement, request, results );
+ Column col = queryData.columns[i];
+ if ( col.isKey ) {
+ this.setColumn( statement, currentIndex, request, col.columnConf,
+ getOutputName( table, col.columnConf, rowIndex ),
+ columnValues[ i ][ ( col.isSet ? rowIndex : 0 ) ],
+ rowIndex);
+ currentIndex++;
}
}
statement.execute();
- // get resulting ids
- for (int i = 0; i < queryData.columns.length; i++) {
- storeKeyValue( table, queryData.columns[i], idx, rowIndex,
- conn, statement, request, results );
- }
// retrieve values
ResultSet resultset = statement.getResultSet();
rowIndex = -1;
1.2 +43 -17 xml-cocoon2/scratchpad/src/org/apache/cocoon/acting/ModularDatabaseUpdateAction.java
Index: ModularDatabaseUpdateAction.java
===================================================================
RCS file: /home/cvs/xml-cocoon2/scratchpad/src/org/apache/cocoon/acting/ModularDatabaseUpdateAction.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- ModularDatabaseUpdateAction.java 2001/11/19 16:28:33 1.1
+++ ModularDatabaseUpdateAction.java 2001/11/23 10:50:35 1.2
@@ -28,10 +28,10 @@
* @author <a href="mailto:bloritsch@apache.org">Berin Loritsch</a>
* @author <a href="mailto:balld@apache.org">Donald Ball</a>
* @author <a href="mailto:haul@apache.org">Christian Haul</a>
- * @version CVS $Revision: 1.1 $ $Date: 2001/11/19 16:28:33 $
+ * @version CVS $Revision: 1.2 $ $Date: 2001/11/23 10:50:35 $
*/
public class ModularDatabaseUpdateAction
- extends ModularDatabaseAddAction
+ extends ModularDatabaseAction
{
/**
@@ -41,7 +41,7 @@
*/
protected String selectMode (
- boolean isKeyColumns,
+ boolean isAutoIncrement,
HashMap modes
)
{
@@ -49,7 +49,33 @@
}
+ /**
+ * determine whether autoincrement columns should be honoured by
+ * this operation. This is usually snsible only for INSERTs.
+ */
+ protected boolean honourAutoIncrement() { return false; }
+
+
+ /**
+ * Fetch all values for all columns that are needed to do the
+ * database operation.
+ */
+ Object[][] getColumnValues(
+ Configuration tableConf,
+ CacheHelper queryData,
+ Request request
+ )
+ throws ConfigurationException,
+ ComponentException
+ {
+ Object[][] columnValues = new Object[ queryData.columns.length ][];
+ for ( int i = 0; i < queryData.columns.length; i++ ){
+ columnValues[i] = this.getColumnValue( tableConf, queryData.columns[i], request );
+ }
+ return columnValues;
+ }
+
/**
* Get the String representation of the PreparedStatement. This is
* mapped to the Configuration object itself, so if it doesn't exist,
@@ -125,8 +151,8 @@
PreparedStatement statement,
Configuration table,
CacheHelper queryData,
+ Object[][] columnValues,
int rowIndex,
- Object idx,
Map results
)
throws SQLException,
@@ -138,26 +164,26 @@
// ordering is different for UPDATE than for INSERT: values, keys
for (int i = 0; i < queryData.columns.length; i++) {
- if ( !queryData.columns[i].isKey ) {
- this.setColumn( table, queryData.columns[i], currentIndex, idx, rowIndex,
- statement, request );
+ Column col = queryData.columns[i];
+ if ( !col.isKey ) {
+ this.setColumn( statement, currentIndex, request, col.columnConf,
+ getOutputName( table, col.columnConf, rowIndex ),
+ columnValues[ i ][ ( col.isSet ? rowIndex : 0 ) ],
+ rowIndex);
currentIndex++;
}
}
for (int i = 0; i < queryData.columns.length; i++) {
- if ( queryData.columns[i].isKey ) {
- currentIndex += setKey( table, queryData.columns[i], currentIndex, idx, rowIndex,
- conn, statement, request, results );
+ Column col = queryData.columns[i];
+ if ( col.isKey ) {
+ this.setColumn( statement, currentIndex, request, col.columnConf,
+ getOutputName( table, col.columnConf, rowIndex ),
+ columnValues[ i ][ ( col.isSet ? rowIndex : 0 ) ],
+ rowIndex);
+ currentIndex++;
}
}
statement.execute();
- // get resulting ids
- for (int i = 0; i < queryData.columns.length; i++) {
- if ( queryData.columns[i].isKey ) {
- storeKeyValue( table, queryData.columns[i], idx, rowIndex,
- conn, statement, request, results );
- }
- }
}
}
1.1 xml-cocoon2/scratchpad/src/org/apache/cocoon/acting/ModularDatabaseAction.java
Index: ModularDatabaseAction.java
===================================================================
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
* ------------------------------------------------------------------------- *
* This software is published under the terms of the Apache Software License *
* version 1.1, a copy of which has been included with this distribution in *
* the LICENSE file. *
*****************************************************************************/
package org.apache.cocoon.acting;
import java.io.IOException;
import java.io.InputStream;
import java.lang.Class;
import java.net.URL;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.Statement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
import java.util.List;
import java.util.LinkedList;
import java.util.ListIterator;
import java.util.Enumeration;
import java.util.Collections;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.io.IOException;
import org.apache.avalon.framework.activity.Disposable;
import org.apache.avalon.framework.component.Component;
import org.apache.avalon.framework.component.ComponentException;
import org.apache.avalon.framework.component.ComponentManager;
import org.apache.avalon.framework.configuration.Configurable;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.configuration.DefaultConfiguration;
import org.apache.avalon.framework.context.Context;
import org.apache.avalon.framework.context.ContextException;
import org.apache.avalon.framework.context.Contextualizable;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.avalon.framework.thread.ThreadSafe;
import org.apache.avalon.excalibur.component.ExcaliburComponentSelector;
import org.apache.avalon.excalibur.component.ExcaliburComponentManager;
import org.apache.avalon.excalibur.component.RoleManager;
import org.apache.avalon.excalibur.component.DefaultRoleManager;
import org.apache.avalon.excalibur.datasource.DataSourceComponent;
import org.apache.cocoon.Constants;
import org.apache.cocoon.ProcessingException;
import org.apache.cocoon.components.classloader.RepositoryClassLoader;
import org.apache.cocoon.components.url.URLFactory;
import org.apache.cocoon.environment.Request;
import org.apache.cocoon.environment.Redirector;
import org.apache.cocoon.environment.SourceResolver;
import org.apache.cocoon.generation.ImageDirectoryGenerator;
import org.apache.cocoon.util.ClassUtils;
import org.apache.cocoon.util.HashMap;
import org.apache.cocoon.selection.Selector;
import org.apache.cocoon.acting.ModularDatabaseAccess.AutoIncrementHelper;
import org.apache.cocoon.acting.ModularDatabaseAccess.AttributeHelper;
import org.apache.cocoon.acting.ModularDatabaseAccess.OutputHelper;
/**
* Adds record in a database. The action can update one or more tables,
* and can add more than one row to a table at a time. The form descriptor
* semantics for this are still in a bit of a state of flux.
*
* The difference to the other Database*Actions is, that it uses
* additional components for reading and writing parameters. In
* addition the descriptor format has changed to accomodate the new
* features.
*
* This action is heavily based upon the DatabaseAddAction and relies
* on the AbstractDatabaseAction.
*
* Configuration options:
* descriptor file containing database description
* throw-exception throw an exception when an error occurs (default: false)
*
* Note: Component management will move to sitemap so that other
* components can utilize the helper components.
*
* @author <a href="mailto:haul@apache.org">Christian Haul</a>
* @version CVS $Revision: 1.1 $ $Date: 2001/11/23 10:50:35 $
*/
public abstract class ModularDatabaseAction
extends AbstractDatabaseAction
implements Disposable, ThreadSafe, Contextualizable
{
// ========================================================================
// inner helper classes
// ========================================================================
protected class Column {
boolean isKey = false;
boolean isSet = false;
boolean isAutoIncrement = false;
String mode = null;
Configuration modeConf = null;
Configuration columnConf = null;
}
protected class CacheHelper {
public String queryString = null;
public int setMaster = -1;
public boolean isSet = false;
public int noOfKeys = 0;
public Column[] columns = null;
public CacheHelper( int cols ) {
this(0,cols);
}
public CacheHelper( int keys, int cols ) {
noOfKeys = keys;
columns = new Column[cols];
for ( int i=0; i<cols; i++ ) {
columns[i] = new Column();
}
}
}
protected class LookUpKey {
public Configuration tableConf = null;
public Map modeTypes = null;
public LookUpKey( Configuration tableConf, Map modeTypes ) {
this.tableConf = tableConf;
this.modeTypes = modeTypes;
}
}
// ========================================================================
// constants
// ========================================================================
private static final String LOCATION = "org.apache.cocoon.acting.ModularDatabaseAddAction";
private static final int BYTE_ARRAY_SIZE = 1024;
static final Integer MODE_AUTOINCR = new Integer( 0 );
static final Integer MODE_OTHERS = new Integer( 1 );
static final Integer MODE_OUTPUT = new Integer( 2 );
// ========================================================================
// instance vars
// ========================================================================
// please ignore component management as I know this is ugly and I
// hope that this duty is taken by the sitemap in short term.
// please ignore ====>
protected RoleManager roleManager;
private Configuration defaultConfig;
protected Context context;
/** The component manager instance */
protected ExcaliburComponentManager manager2;
/** The URLFactory instance */
protected URLFactory urlFactory;
protected ExcaliburComponentSelector modeMapping = null;
protected ExcaliburComponentSelector outputMapping = null;
// default modes for other / insert operations
protected HashMap defaultModeNames = new HashMap( 3 );
// <==== please ignore
//
protected final Map cachedQueryData = new HashMap();
//
// please ignore ====>
// ========================================================================
// setup / class loading
// (basically copied from AbstractSitemap)
// This is ugly. Please ignore. Helpers should be handled at sitemap level
// so that other components can share them.
// ========================================================================
/**
* Set the role manager
*/
public void setRoleManager(
RoleManager roles,
Configuration config
)
{
this.roleManager = roles;
this.defaultConfig = config;
}
/**
* Set the current <code>ComponentManager</code> instance used by this
* <code>Composable</code>.
*/
public void compose(
ComponentManager manager
)
throws ComponentException
{
super.compose( manager );
getLogger().debug("compose");
this.manager2 = new ExcaliburComponentManager(manager);
this.manager2.setLogger(getLogger());
this.manager2.contextualize(this.context);
this.manager2.setRoleManager(this.roleManager);
try {
if (this.defaultConfig != null) {
this.manager2.configure(this.defaultConfig);
}
this.urlFactory = (URLFactory)manager.lookup(URLFactory.ROLE);
this.modeMapping = new ExcaliburComponentSelector();
this.outputMapping = new ExcaliburComponentSelector();
this.setupSelector(this.modeMapping);
this.setupSelector(this.outputMapping);
this.manager2.addComponentInstance(Selector.ROLE + "Selector", this.modeMapping);
this.manager2.addComponentInstance(Selector.ROLE + "Selector", this.outputMapping);
} catch (Exception e) {
getLogger().error("cannot obtain the Component", e);
throw new ComponentException("cannot obtain the URLFactory", e);
}
}
private void setupSelector(
ExcaliburComponentSelector selector
)
throws Exception
{
selector.setLogger(getLogger());
selector.contextualize(this.context);
selector.setRoleManager(this.roleManager);
selector.compose(this.manager2);
}
public void contextualize(
Context context
)
throws ContextException
{
this.context = context;
}
/**
* Return the component manager for this sitemap
*/
public ComponentManager getComponentManager()
{
return this.manager2;
}
/**
* Release all components.
*/
public void dispose()
{
if (this.urlFactory != null) {
manager.release((Component)this.urlFactory);
}
if (this.modeMapping != null) {
manager2.release((Component)this.modeMapping);
}
if (this.outputMapping != null) {
manager2.release((Component)this.outputMapping);
}
manager2.dispose();
}
/**
* Configure modes that are used to delegate database specific methods
* and other modes.
*/
public void configure(
Configuration conf
)
throws ConfigurationException
{
try {
getLogger().debug("MDAA: configure");
LinkedList hints = new LinkedList();
if (conf != null) {
String val = null;
String nodeName = null;
Configuration[] parameters = conf.getChildren();
this.settings = new HashMap(parameters.length);
for ( int i = 0; i < parameters.length; i++) {
nodeName= parameters[i].getName();
getLogger().debug("configure -- " + nodeName);
if ( nodeName != null ) {
if ( "mode".equals(nodeName.trim()) || "output".equals(nodeName.trim())) {
String modeName = parameters[i].getAttribute("name");
String src = parameters[i].getAttribute("src");
if (modeName!=null && src!=null) {
Configuration modeConfig = parameters[i];
if (modeConfig == null) {
modeConfig = this.defaultConfig;
}
getLogger().debug("load -- " + modeName + " -> " + src);
if ( "mode".equals(nodeName.trim())) {
this.load_component(modeMapping, modeName, src, modeConfig);
hints.add(modeName);
} else {
this.load_component(outputMapping, modeName, src, modeConfig);
if ( !defaultModeNames.containsKey( MODE_OUTPUT ) ) {
defaultModeNames.put( MODE_OUTPUT, modeName );
}
}
}
} else {
val = parameters[i].getValue();
this.settings.put(nodeName, val);
}
}
}
}
this.modeMapping.initialize();
this.outputMapping.initialize();
this.manager2.initialize();
ListIterator li = hints.listIterator();
while ( li.hasNext() ) {
String modeName = (String) li.next();
Component helper = modeMapping.select( modeName );
if ( !defaultModeNames.containsKey( MODE_OTHERS ) && helper instanceof AttributeHelper ) {
defaultModeNames.put( MODE_OTHERS, modeName );
getLogger().debug(modeName + " default mode for normal columns");
}
if ( !defaultModeNames.containsKey( MODE_AUTOINCR ) && helper instanceof AutoIncrementHelper ) {
defaultModeNames.put( MODE_AUTOINCR, modeName );
getLogger().debug(modeName + " default mode for autoincrement columns");
}
modeMapping.release(helper);
}
if ( !defaultModeNames.containsKey( MODE_OTHERS ) ||
!defaultModeNames.containsKey( MODE_AUTOINCR ) ||
!defaultModeNames.containsKey( MODE_OUTPUT )
) {
throw new ConfigurationException("Not all default modes are configured:"
+ ( defaultModeNames.containsKey( MODE_AUTOINCR ) ? " insert mode" : "" )
+ ( defaultModeNames.containsKey( MODE_OTHERS ) ? " others" : "" )
+ ( defaultModeNames.containsKey( MODE_OUTPUT ) ? " output" : "" )
);
}
} catch (Exception e) {
throw new ConfigurationException(e.toString());
}
}
/**
* Load a component.
*
* @param hint Object to identify this component
* @param classURL component's class name / URL
* @param config configuration for this component
*/
private void load_component(
ExcaliburComponentSelector selector,
Object hint,
String classURL,
Configuration config
)
throws Exception
{
Class clazz = null;
//FIXME(GP): Is it true that a class name containing a colon should be an URL?
if (classURL.indexOf(':') > 1) {
URL url = urlFactory.getURL(classURL);
byte[] b = getByteArrayFromStream(url.openStream());
clazz = ((RepositoryClassLoader)ClassUtils.getClassLoader()).defineClass(b);
} else {
clazz = ClassUtils.loadClass(classURL);
}
if (!Component.class.isAssignableFrom(clazz)) {
throw new IllegalAccessException("Object " + classURL + " is not a Component");
}
selector.addComponent(hint, clazz, config);
}
/**
* Helper to read in a class
*/
private byte[] getByteArrayFromStream(
InputStream stream
)
{
List list = new ArrayList();
byte[] b = new byte[BYTE_ARRAY_SIZE];
int last = 0;
try {
while ((last = stream.read(b)) == BYTE_ARRAY_SIZE) {
list.add(b);
b = new byte[BYTE_ARRAY_SIZE];
}
} catch (IOException ioe) {
getLogger().error("cannot read class byte stream", ioe);
}
list.add(b);
int listSize = list.size();
b = new byte[(listSize - 1) * BYTE_ARRAY_SIZE + last];
int i;
for (i = 0; i < listSize - 1; i++) {
System.arraycopy(list.get(i), 0, b, i * BYTE_ARRAY_SIZE, BYTE_ARRAY_SIZE);
}
System.arraycopy(list.get(i), 0, b, i * BYTE_ARRAY_SIZE, last);
return b;
}
// <==== please ignore
//
// ========================================================================
// protected utility methods
// ========================================================================
/**
* override super's method since we prefer to get the datasource
* from defaults first or from sitemap parameters rather than from
* descriptor file.
*/
protected DataSourceComponent getDataSource( Configuration conf, Parameters parameters )
throws ComponentException
{
String sourceName = parameters.getParameter( "connection", (String) settings.get( "connection" ) );
if ( sourceName == null ) {
return getDataSource( conf );
} else {
getLogger().debug("Using datasource: "+sourceName);
return (DataSourceComponent) this.dbselector.select(sourceName);
}
}
/**
* Store a key/value pair in the request attributes. We prefix the key
* with the name of this class to prevent potential name collisions.
* This method overrides super class' method to allow an OutputHelper
* to take care of what to do with the values.
*/
void setRequestAttribute(Request request, String key, Object value) {
try {
OutputHelper oh = (OutputHelper) outputMapping.select( (String) defaultModeNames.get( MODE_OUTPUT ) );
oh.setAttribute( null, request, key, value );
outputMapping.release( oh );
} catch (Exception e) {
getLogger()
.warn( "Could not select output mode "
+ (String) defaultModeNames.get( MODE_OUTPUT )
+ ":" + e.getMessage() );
}
}
/**
* Retrieve a value from the request attributes.
* This method overrides super class' method to allow an OutputHelper
* to take care of where to get the values.
*/
Object getRequestAttribute(Request request, String key) {
Object value = null;
try {
OutputHelper oh = (OutputHelper) outputMapping.select( (String) defaultModeNames.get( MODE_OUTPUT ) );
value = oh.getAttribute( null, request, key );
outputMapping.release( oh );
} catch (Exception e) {
getLogger()
.warn( "Could not select output mode "
+ (String) defaultModeNames.get( MODE_OUTPUT )
+ ":" + e.getMessage());
}
return value;
}
// ========================================================================
// main method
// ========================================================================
/**
* Add a record to the database. This action assumes that
* the file referenced by the "descriptor" parameter conforms
* to the AbstractDatabaseAction specifications.
*/
public Map act(
Redirector redirector,
SourceResolver resolver,
Map objectModel,
String source,
Parameters param
)
throws Exception
{
DataSourceComponent datasource = null;
Connection conn = null;
Map results = new HashMap();
// read global parameter settings
boolean reloadable = Constants.DESCRIPTOR_RELOADABLE_DEFAULT;
Request request = (Request) objectModel.get(Constants.REQUEST_OBJECT);
if (this.settings.containsKey("reloadable"))
reloadable = Boolean.getBoolean((String) this.settings.get("reloadable"));
// read local parameter settings
try {
Configuration conf =
this.getConfiguration(param.getParameter("descriptor", (String) this.settings.get("descriptor")),
param.getParameterAsBoolean("reloadable",reloadable));
datasource = this.getDataSource(conf, param);
conn = datasource.getConnection();
if (conn.getAutoCommit() == true) {
conn.setAutoCommit(false);
}
Configuration[] tables = conf.getChildren("table");
String tablesetname = param.getParameter("table-set", (String) this.settings.get("table-set"));
Map set_tables = null; // default to old behaviour
HashMap modeTypes = null;
if (tablesetname != null) {
// new set based behaviour
Configuration[] tablesets = conf.getChildren("table-set");
String setname = null;
boolean found = false;
// find tables contained in tableset
int j = 0;
for (j=0; j<tablesets.length; j++) {
setname = tablesets[j].getAttribute ("name", "");
if (tablesetname.trim().equals (setname.trim ())) {
found = true;
break;
}
}
if (!found) {
throw new IOException(" given set " + tablesetname + " does not exists in a description file.");
}
Configuration[] set = tablesets[j].getChildren("table");
// construct a Map that contains the names of the tables
// contained in the requested tableset
set_tables = new HashMap(set.length);
for (int i=0; i<set.length; i++) {
// look for alternative modes
modeTypes = new HashMap(2);
modeTypes.put( MODE_AUTOINCR, set[i].getAttribute( "autoincr-mode", "autoincr" ) );
modeTypes.put( MODE_OTHERS, set[i].getAttribute( "others-mode", "others" ) );
set_tables.put(set[i].getAttribute("name",""), modeTypes);
}
} else {
modeTypes = new HashMap(2);
modeTypes.put( MODE_AUTOINCR, "autoincr" );
modeTypes.put( MODE_OTHERS, "others" );
};
for (int i=0; i<tables.length; i++) {
if (set_tables == null || set_tables.containsKey(tables[i].getAttribute("name"))) {
if (tablesetname != null) {
modeTypes = (HashMap) set_tables.get(tables[i].getAttribute("name"));
}
processTable( tables[i], conn, request, results, modeTypes );
}
}
conn.commit();
OutputHelper oh = (OutputHelper) outputMapping.select( (String) defaultModeNames.get( MODE_OUTPUT ) );
oh.commit( null, request );
outputMapping.release( oh );
} catch (Exception e) {
if ( conn != null ) {
try {
getLogger().debug( "Rolling back transaction. Caused by " + e.getMessage() );
conn.rollback();
OutputHelper oh = (OutputHelper) outputMapping.select( (String) defaultModeNames.get( MODE_OUTPUT ) );
oh.rollback( null, request, e );
outputMapping.release( oh );
} catch (SQLException se) {
getLogger().debug("There was an error rolling back the transaction", se);
}
}
//throw new ProcessingException("Could not add record :position = " + currentIndex, e);
// don't throw an exception, an error has been signalled, that should suffice
String throwException = (String) this.settings.get( "throw-exception", param.getParameter( "throw-exception", null ) );
if ( throwException != null &&
( throwException.equalsIgnoreCase( "true" ) || throwException.equalsIgnoreCase( "yes" ) ) ) {
throw new ProcessingException("Could not add record",e);
}
} finally {
if (conn != null) {
try {
conn.close();
} catch (SQLException sqe) {
getLogger().warn("There was an error closing the datasource", sqe);
}
}
if (datasource != null) this.dbselector.release(datasource);
}
return Collections.unmodifiableMap(results);
}
/**
* Inserts a row or a set of rows into the given table based on the
* request parameters
*
* @param table the table's configuration
* @param conn the database connection
* @param request the request
*/
void processTable(
Configuration table,
Connection conn,
Request request,
Map results,
HashMap modeTypes
)
throws SQLException,
ConfigurationException,
Exception
{
PreparedStatement statement = null;
try {
CacheHelper queryData = this.getQuery( table, modeTypes, defaultModeNames );
getLogger().debug("query: "+queryData.queryString);
statement = conn.prepareStatement(queryData.queryString);
Object[][] columnValues = this.getColumnValues( table, queryData, request );
int setLength = 1;
if ( queryData.isSet ) {
if ( columnValues[ queryData.setMaster ] != null ) {
setLength = columnValues[ queryData.setMaster ].length;
} else {
setLength = 0;
}
}
for ( int rowIndex = 0; rowIndex < setLength; rowIndex++ ) {
getLogger().debug( "====> row no. " + rowIndex );
processRow( request, conn, statement, table, queryData, columnValues, rowIndex, results );
}
} finally {
try {
if (statement != null) {
statement.close();
}
} catch (SQLException e) {}
}
}
/**
* Choose a mode configuration based on its name.
* @param conf Configuration (i.e. a column's configuration) that might have
* several children configurations named "mode".
* @param type desired type (i.e. every mode has a type
* attribute), find the first mode that has a compatible type.
* Special mode "all" matches all queried types.
* @return configuration that has desired type or type "all" or null.
*/
protected Configuration getMode(
Configuration conf,
String type
) throws ConfigurationException
{
String modeAll = "all";
Configuration[] modes = conf.getChildren("mode");
Configuration modeConfig = null;;
for ( int i=0; i<modes.length; i++ ) {
String modeType = modes[i].getAttribute("type", "others");
if ( modeType.equals(type) || modeType.equals(modeAll)) {
getLogger().debug("requested mode was \""+type+"\" returning \""+modeType+"\"");
modeConfig = modes[i];
break;
};
}
return modeConfig;
}
/**
* compose name for output a long the lines of "table.column"
*/
String getOutputName (
Configuration tableConf,
Configuration columnConf
)
throws ConfigurationException
{
return getOutputName( tableConf, columnConf, -1 );
}
/**
* compose name for output a long the lines of "table.column[row]" or
* "table.column" if rowIndex is -1.
*/
String getOutputName (
Configuration tableConf,
Configuration columnConf,
int rowIndex
)
throws ConfigurationException
{
return ( tableConf.getAttribute("alias", tableConf.getAttribute("name") )
+ "." + columnConf.getAttribute("name")
+ ( rowIndex == -1 ? "" : "[" + rowIndex + "]" ) );
}
/*
* Read all values for a column from an AttributeHelper
*
* If the given column is an autoincrement column, an empty array
* is returned, otherwise if it is part of a set, all available
* values are fetched, or only the first one if it is not part of
* a set.
*
*/
Object[] getColumnValue(
Configuration tableConf,
Column column,
Request request
)
throws ConfigurationException,
ComponentException
{
if ( column.isAutoIncrement ) {
return new Object[1];
} else {
Object[] values;
AttributeHelper dph = (AttributeHelper) modeMapping.select( column.mode );
String cname = getOutputName( tableConf, column.columnConf );
if ( column.isSet ){
getLogger().debug( "Trying to set column " + cname +" using getAttributeValues method");
values = dph.getAttributeValues( cname, column.modeConf, request );
} else {
getLogger().debug( "Trying to set column " + cname +" using getAttribute method");
values = new Object[1];
values[0] = dph.getAttribute( cname, column.modeConf, request );
}
modeMapping.release( dph );
if ( values != null ) {
for ( int i = 0; i < values.length; i++ ) {
getLogger().debug( "Setting column " + cname + " [" + i + "] " + values[i] );
}
}
return values;
}
}
/**
* Setup parsed attribute configuration object
*/
protected void fillModes ( Configuration[] conf,
boolean isKey,
HashMap defaultModeNames,
HashMap modeTypes,
CacheHelper set
)
throws ConfigurationException
{
String setMode = null;
int setMaster = -1;
String setMastersMode = null;
boolean manyrows = false;
int offset = ( isKey ? 0: set.noOfKeys);
for ( int i = offset; i < conf.length + offset; i++ ) {
getLogger().debug("i="+i);
set.columns[i].columnConf = conf[ i - offset ];
set.columns[i].isSet = false;
set.columns[i].isKey = isKey;
set.columns[i].isAutoIncrement = false;
if ( isKey & this.honourAutoIncrement() ) {
String autoIncrement = set.columns[i].columnConf.getAttribute("autoincrement","false");
if ( autoIncrement.equalsIgnoreCase("yes") || autoIncrement.equalsIgnoreCase("true") ) {
set.columns[i].isAutoIncrement = true;
}
}
set.columns[i].modeConf = getMode( set.columns[i].columnConf,
selectMode( set.columns[i].isAutoIncrement, modeTypes ) );
set.columns[i].mode = ( set.columns[i].modeConf != null ?
set.columns[i].modeConf.getAttribute( "name", selectMode( isKey, defaultModeNames ) ) : selectMode( isKey, defaultModeNames ) );
// Determine set mode for a whole column ...
setMode = set.columns[i].columnConf.getAttribute("set", null); // master vs slave vs null
if ( setMode == null && set.columns[i].modeConf != null ) {
// ... or for each mode individually
setMode = set.columns[i].modeConf.getAttribute("set", null);
}
if ( setMode != null ) {
manyrows = true;
set.columns[i].isSet = true;
set.isSet = true;
if ( setMode.equals("master") ) {
set.setMaster = i;
}
}
}
}
/**
* Put key values into request attributes.
*/
void storeKeyValue(
Configuration tableConf,
Column key,
int rowIndex,
Connection conn,
Statement statement,
Request request,
Map results
)
throws SQLException,
ConfigurationException,
ComponentException
{
AutoIncrementHelper dah = (AutoIncrementHelper) modeMapping.select( key.mode );
if (!dah.includeAsValue()) {
String keyname = getOutputName( tableConf, key.columnConf, rowIndex );
Object value = dah.getPostValue( tableConf, key.columnConf, key.modeConf, conn, statement, request );
getLogger().debug( "Retrieving autoincrement for " + keyname + "as " + value );
setRequestAttribute( request, keyname, value );
results.put( keyname, String.valueOf( value ) );
}
modeMapping.release(dah);
}
/**
* Sets the key value on the prepared statement for an autoincrement type.
*
* @param table the table's configuration object
* @param column the key's configuration object
* @param currentIndex the position of the key column
* @param rowIndex the position in the current row set
* @param conn the database connection
* @param statement the insert statement
* @param request the request object
* @param result sitemap result object
* @return the number of columns by which to increment the currentIndex
*/
int setKeyAuto (
Configuration table,
Column column,
int currentIndex,
int rowIndex,
Connection conn,
PreparedStatement statement,
Request request,
Map results
)
throws ConfigurationException,
SQLException,
ComponentException,
Exception
{
int columnCount = 0;
AutoIncrementHelper dah = (AutoIncrementHelper) modeMapping.select( column.mode );
if ( dah.includeInQuery() ) {
if ( dah.includeAsValue() ) {
Object value = dah.getPreValue( table, column.columnConf, column.modeConf, conn, request );
String keyname = this.getOutputName( table, column.columnConf, rowIndex );
getLogger().debug( "Setting key " + keyname + " to " + value );
statement.setObject( currentIndex, value );
setRequestAttribute( request, keyname, value );
results.put( keyname, String.valueOf( value ) );
columnCount = 1;
}
} else {
getLogger().debug( "Automatically setting key" );
}
modeMapping.release( dah );
return columnCount;
}
// ========================================================================
// abstract methods
// ========================================================================
/**
* set all necessary ?s and execute the query
*
* This method is intended to be overridden by classes that
* implement other operations e.g. delete
*/
protected abstract void processRow(
Request request,
Connection conn,
PreparedStatement statement,
Configuration table,
CacheHelper queryData,
Object[][] columnValues,
int rowIndex,
Map results
)
throws SQLException,
ConfigurationException,
Exception;
/**
* determine which mode to use as default mode
*
* This method is intended to be overridden by classes that
* implement other operations e.g. delete
*/
protected abstract String selectMode(
boolean isAutoIncrement,
HashMap modes
);
/**
* determine whether autoincrement columns should be honoured by
* this operation. This is usually snsible only for INSERTs.
*
* This method is intended to be overridden by classes that
* implement other operations e.g. delete
*/
protected abstract boolean honourAutoIncrement();
/**
* Fetch all values for all columns that are needed to do the
* database operation.
*
* This method is intended to be overridden by classes that
* implement other operations e.g. delete
*/
abstract Object[][] getColumnValues(
Configuration tableConf,
CacheHelper queryData,
Request request
)
throws ConfigurationException,
ComponentException;
/**
* Get the String representation of the PreparedStatement. This is
* mapped to the Configuration object itself, so if it doesn't exist,
* it will be created.
*
* This method is intended to be overridden by classes that
* implement other operations e.g. delete
*
* @param table the table's configuration object
* @return the insert query as a string
*/
protected abstract CacheHelper getQuery(
Configuration table,
HashMap modeTypes,
HashMap defaultModeNames
)
throws ConfigurationException,
ComponentException;
}
1.2 +3 -3 xml-cocoon2/scratchpad/src/org/apache/cocoon/acting/ModularDatabaseAccess/AbstractAttributeHelper.java
Index: AbstractAttributeHelper.java
===================================================================
RCS file: /home/cvs/xml-cocoon2/scratchpad/src/org/apache/cocoon/acting/ModularDatabaseAccess/AbstractAttributeHelper.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- AbstractAttributeHelper.java 2001/11/19 16:28:33 1.1
+++ AbstractAttributeHelper.java 2001/11/23 10:50:36 1.2
@@ -13,15 +13,15 @@
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.logger.AbstractLoggable;
-import java.util.HashMap;
+import org.apache.cocoon.util.HashMap;
/**
* AbstractDatabaseHelper gives you the infrastructure for easily
- * deploying more database access helpers. In order to get at the
+ * deploying more Attributehelpers. In order to get at the
* Logger, use getLogger().
*
* @author <a href="mailto:haul@apache.org">Christian Haul</a>
- * @version CVS $Revision: 1.1 $ $Date: 2001/11/19 16:28:33 $ */
+ * @version CVS $Revision: 1.2 $ $Date: 2001/11/23 10:50:36 $ */
public abstract class AbstractAttributeHelper extends AbstractLoggable
implements AttributeHelper, Configurable, Disposable {
1.2 +53 -16 xml-cocoon2/scratchpad/src/org/apache/cocoon/acting/ModularDatabaseAccess/AttributeHelper.java
Index: AttributeHelper.java
===================================================================
RCS file: /home/cvs/xml-cocoon2/scratchpad/src/org/apache/cocoon/acting/ModularDatabaseAccess/AttributeHelper.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- AttributeHelper.java 2001/11/19 16:28:33 1.1
+++ AttributeHelper.java 2001/11/23 10:50:36 1.2
@@ -7,38 +7,75 @@
*****************************************************************************/
package org.apache.cocoon.acting.ModularDatabaseAccess;
+import java.util.SortedSet;
+import java.util.Enumeration;
+
import org.apache.cocoon.environment.Request;
+import org.apache.avalon.framework.component.Component;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
/**
* AttributeHelper specifies an interface for components that provide
- * access to individual parameters e.g. request parameters, request
+ * access to individual attributes e.g. request parameters, request
* attributes, session attributes &c.
*
* @author <a href="mailto:haul@apache.org">Christian Haul</a>
- * @version CVS $Id: AttributeHelper.java,v 1.1 2001/11/19 16:28:33 haul Exp $
+ * @version CVS $Id: AttributeHelper.java,v 1.2 2001/11/23 10:50:36 haul Exp $
* */
-public interface AttributeHelper extends AccessHelper {
+public interface AttributeHelper
+ extends Component
+{
String ROLE = "org.apache.cocoon.acting.ModularDatabaseAccess.AttributeHelper";
-
+
+ /**
+ * Standard access to an attribute's value. If more than one value
+ * exists, the first is returned. If the value does not exist,
+ * null is returned. To get all values, use {@link
+ * getAttributeValues} or {@link getAttributeSet} and {@link
+ * getValue} to get them one by one.
+ * @param name a String that specifies what the caller thinks
+ * would identify an attribute. This is mainly a fallback if no
+ * modeConf is present.
+ * @param modeConf column's mode configuration from resource
+ * description. This argument is optional.
+ * @param request the request object
+ */
+ public Object getAttribute( String name,
+ Configuration modeConf,
+ Request request
+ )
+ throws ConfigurationException;
+
+ /**
+ * Returns an Enumeration of String objects containing the names
+ * of the attributes available. If no attributes are available,
+ * the method returns an empty Enumeration.
+ * @param modeConf column's mode configuration from resource
+ * description. This argument is optional.
+ * @param request the request object
+ */
+ public Enumeration getAttributeNames( Configuration modeConf,
+ Request request
+ )
+ throws ConfigurationException;
+
/**
- * Return an object that is to be taken for insertion.
+ * Returns an array of String objects containing all of the values
+ * the given attribute has, or null if the attribute does not
+ * exist. As an alternative, {@link getAttributeSet} together with
+ * {@link getValue} can be used to get the values one by one.
* @param name a String that specifies what the caller thinks
- * would identify a set of parameters. This is mainly a fallback
+ * would identify an attributes. This is mainly a fallback
* if no modeConf is present.
* @param modeConf column's mode configuration from resource
- * description.
+ * description. This argument is optional.
* @param request the request object
- * @param index Element from the getParameterSet() to identify an
- * instance in a set of similar parameters, when multiple rows are
- * inserted.
- * */
- public Object getValue( String name,
- Configuration modeConf,
- Request request,
- Object index
- )
+ */
+ public Object[] getAttributeValues( String name,
+ Configuration modeConf,
+ Request request
+ )
throws ConfigurationException;
}
1.2 +16 -19 xml-cocoon2/scratchpad/src/org/apache/cocoon/acting/ModularDatabaseAccess/HsqlIdentityKeyAttributeHelper.java
Index: HsqlIdentityKeyAttributeHelper.java
===================================================================
RCS file: /home/cvs/xml-cocoon2/scratchpad/src/org/apache/cocoon/acting/ModularDatabaseAccess/HsqlIdentityKeyAttributeHelper.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- HsqlIdentityKeyAttributeHelper.java 2001/11/19 16:28:33 1.1
+++ HsqlIdentityKeyAttributeHelper.java 2001/11/23 10:50:36 1.2
@@ -7,7 +7,7 @@
*****************************************************************************/
package org.apache.cocoon.acting.ModularDatabaseAccess;
-import java.lang.Long;
+import java.lang.Integer;
import java.util.SortedSet;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
@@ -28,10 +28,10 @@
* {@link http://hsqldb.sourceforge.net}
*
* @author <a href="mailto:haul@apache.org">Christian Haul</a>
- * @version CVS $Id: HsqlIdentityKeyAttributeHelper.java,v 1.1 2001/11/19 16:28:33 haul Exp $
+ * @version CVS $Id: HsqlIdentityKeyAttributeHelper.java,v 1.2 2001/11/23 10:50:36 haul Exp $
*/
public class HsqlIdentityKeyAttributeHelper
- implements KeyAttributeHelper, ThreadSafe
+ implements AutoIncrementHelper, ThreadSafe
{
public Object getPostValue( Configuration tableConf,
@@ -40,9 +40,11 @@
Connection conn,
Statement stmt,
Request request
- ) throws SQLException, ConfigurationException
+ )
+ throws SQLException,
+ ConfigurationException
{
- Long id = null;
+ Integer id = null;
/*
CallableStatement callStmt = conn.prepareCall("? = {CALL IDENTITY()}");
callStmt.registerOutParameter(1, Types.INTEGER);
@@ -53,7 +55,7 @@
PreparedStatement pstmt = conn.prepareStatement("CALL IDENTITY()");
ResultSet resultSet = pstmt.executeQuery();
while ( resultSet.next() ) {
- id = new Long(resultSet.getInt(1));
+ id = new Integer(resultSet.getInt(1));
}
resultSet.close();
@@ -71,25 +73,20 @@
Configuration columnConf,
Configuration modeConf,
Connection conn,
- Request request,
- Object idx
- ) throws SQLException, ConfigurationException {
+ Request request
+ )
+ throws SQLException,
+ ConfigurationException
+ {
return null;
};
public String getSubquery( Configuration tableConf,
Configuration columnConf,
Configuration modeConf
- ) throws ConfigurationException {
- return null;
- };
-
- public SortedSet getAttributeSet( String name,
- Configuration modeConf,
- Request request
- )
- throws ConfigurationException
+ )
+ throws ConfigurationException
{
return null;
- }
+ };
}
1.2 +14 -17 xml-cocoon2/scratchpad/src/org/apache/cocoon/acting/ModularDatabaseAccess/IfxSerialKeyAttributeHelper.java
Index: IfxSerialKeyAttributeHelper.java
===================================================================
RCS file: /home/cvs/xml-cocoon2/scratchpad/src/org/apache/cocoon/acting/ModularDatabaseAccess/IfxSerialKeyAttributeHelper.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- IfxSerialKeyAttributeHelper.java 2001/11/19 16:28:33 1.1
+++ IfxSerialKeyAttributeHelper.java 2001/11/23 10:50:36 1.2
@@ -7,7 +7,7 @@
*****************************************************************************/
package org.apache.cocoon.acting.ModularDatabaseAccess;
-import java.lang.Long;
+import java.lang.Integer;
import java.util.SortedSet;
import java.sql.Connection;
import java.sql.Statement;
@@ -25,10 +25,10 @@
* (need another one for SERIAL8 ones!)
*
* @author <a href="mailto:haul@apache.org">Christian Haul</a>
- * @version CVS $Id: IfxSerialKeyAttributeHelper.java,v 1.1 2001/11/19 16:28:33 haul Exp $
+ * @version CVS $Id: IfxSerialKeyAttributeHelper.java,v 1.2 2001/11/23 10:50:36 haul Exp $
*/
public class IfxSerialKeyAttributeHelper
- implements KeyAttributeHelper, ThreadSafe
+ implements AutoIncrementHelper, ThreadSafe
{
public Object getPostValue( Configuration tableConf,
@@ -37,9 +37,11 @@
Connection conn,
Statement stmt,
Request request
- ) throws SQLException, ConfigurationException
+ )
+ throws SQLException,
+ ConfigurationException
{
- return new Long(((com.informix.jdbc.IfxStatement) stmt).getSerial());
+ return new Integer(((com.informix.jdbc.IfxStatement) stmt).getSerial());
};
public boolean includeInQuery() {
@@ -53,25 +55,20 @@
Configuration columnConf,
Configuration modeConf,
Connection conn,
- Request request,
- Object idx
- ) throws SQLException, ConfigurationException {
+ Request request
+ )
+ throws SQLException,
+ ConfigurationException
+ {
return null;
};
public String getSubquery( Configuration tableConf,
Configuration columnConf,
Configuration modeConf
- ) throws ConfigurationException {
- return null;
- };
-
- public SortedSet getAttributeSet( String name,
- Configuration modeConf,
- Request request
- )
+ )
throws ConfigurationException
{
return null;
- }
+ };
}
1.2 +27 -37 xml-cocoon2/scratchpad/src/org/apache/cocoon/acting/ModularDatabaseAccess/ManualKeyAttributeHelper.java
Index: ManualKeyAttributeHelper.java
===================================================================
RCS file: /home/cvs/xml-cocoon2/scratchpad/src/org/apache/cocoon/acting/ModularDatabaseAccess/ManualKeyAttributeHelper.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- ManualKeyAttributeHelper.java 2001/11/19 16:28:33 1.1
+++ ManualKeyAttributeHelper.java 2001/11/23 10:50:36 1.2
@@ -16,7 +16,7 @@
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.thread.ThreadSafe;
-import java.lang.Long;
+import java.lang.Integer;
import java.util.Map;
import java.util.HashMap;
import java.util.SortedSet;
@@ -34,42 +34,43 @@
* requires only shared locks. C.f. "Phantom Problem"
*
* @author <a href="mailto:haul@apache.org">Christian Haul</a>
- * @version CVS $Id: ManualKeyAttributeHelper.java,v 1.1 2001/11/19 16:28:33 haul Exp $
+ * @version CVS $Id: ManualKeyAttributeHelper.java,v 1.2 2001/11/23 10:50:36 haul Exp $
*/
public class ManualKeyAttributeHelper
- extends AbstractKeyAttributeHelper
+ extends AbstractAutoIncrementHelper
implements ThreadSafe
{
private Map selectStatements = new HashMap();
- public Object getPostValue ( Configuration tableConf,
- Configuration columnConf,
- Configuration modenConf,
- Connection conn,
- Statement stmt,
- Request request
- )
- throws SQLException, ConfigurationException
+ public Object getPostValue( Configuration tableConf,
+ Configuration columnConf,
+ Configuration modenConf,
+ Connection conn,
+ Statement stmt,
+ Request request
+ )
+ throws SQLException,
+ ConfigurationException
{
return null;
};
- public boolean includeInQuery ( ) {
+ public boolean includeInQuery( ) {
return true;
};
- public boolean includeAsValue ( ) {
+ public boolean includeAsValue( ) {
return true;
};
- public Object getPreValue ( Configuration tableConf,
- Configuration columnConf,
- Configuration modeConf,
- Connection conn,
- Request request,
- Object idx
- )
- throws SQLException, ConfigurationException
+ public Object getPreValue( Configuration tableConf,
+ Configuration columnConf,
+ Configuration modeConf,
+ Connection conn,
+ Request request
+ )
+ throws SQLException,
+ ConfigurationException
{
/** Set the key value using SELECT MAX(keyname)+1 **/
String tableName = tableConf.getAttribute("name","");
@@ -81,28 +82,17 @@
set.close();
select_statement.close();
getLogger().debug("autoincrementValue " + (maxid+1));
- return new Long(maxid + 1);
+ return new Integer(maxid + 1);
};
- public String getSubquery ( Configuration tableConf,
- Configuration columnConf,
- Configuration modeConf
- )
+ public String getSubquery( Configuration tableConf,
+ Configuration columnConf,
+ Configuration modeConf
+ )
throws ConfigurationException
{
return null;
};
-
-
- public SortedSet getAttributeSet( String name,
- Configuration modeConf,
- Request request
- )
- throws ConfigurationException
- {
- return null;
- }
-
/**
* Set the String representation of the MaxID lookup statement. This is
1.2 +14 -5 xml-cocoon2/scratchpad/src/org/apache/cocoon/acting/ModularDatabaseAccess/OutputHelper.java
Index: OutputHelper.java
===================================================================
RCS file: /home/cvs/xml-cocoon2/scratchpad/src/org/apache/cocoon/acting/ModularDatabaseAccess/OutputHelper.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- OutputHelper.java 2001/11/19 16:28:33 1.1
+++ OutputHelper.java 2001/11/23 10:50:36 1.2
@@ -9,6 +9,7 @@
import org.apache.cocoon.environment.Request;
import org.apache.avalon.framework.component.Component;
+import org.apache.avalon.framework.configuration.Configuration;
/**
* Communicate results to other components. This could be done via
@@ -18,7 +19,7 @@
* the transaction completes successfully.
*
* @author <a href="mailto:haul@apache.org">Christian Haul</a>
- * @version CVS $Id: OutputHelper.java,v 1.1 2001/11/19 16:28:33 haul Exp $
+ * @version CVS $Id: OutputHelper.java,v 1.2 2001/11/23 10:50:36 haul Exp $
* */
public interface OutputHelper extends Component {
String ROLE = "org.apache.cocoon.acting.ModularDatabaseAccess.OutputHelper";
@@ -26,13 +27,16 @@
/**
* communicate an attribute value to further processing logic.
+ * @param modeConf column's mode configuration from resource
+ * description. This argument is optional.
* @param request The request object
* @param name The attribute's label, consisting of "table.column"
* or "table.column[index]" in case of multiple attributes of the
* same spec.
* @param value The attriute's value.
* */
- public void setAttribute( Request request,
+ public void setAttribute( Configuration modeConf,
+ Request request,
String name,
Object value
);
@@ -41,13 +45,18 @@
/**
* retrieve an attribute from other processing steps. <em>Do we
* really need this thingy?</em>
+ * @param modeConf column's mode configuration from resource
+ * description. This argument is optional.
* @param request The request object
* @param name The attribute's label, consisting of "table.column"
* or "table.column[index]" in case of multiple attributes of the
* same spec.
* @return requested object.
+ *
+ * Really necessary?
* */
- public Object getAttribute( Request request,
+ public Object getAttribute( Configuration modeConf,
+ Request request,
String name );
/**
@@ -59,13 +68,13 @@
* your data straight to some beans or other entities could result
* in data corruption!</em>
* */
- public void rollback( Request request, Exception e );
+ public void rollback( Configuration modeConf, Request request, Exception e );
/**
* Signal that the database transaction completed
* successfully. See notes on @link{rollback}.
* */
- public void commit( Request request );
+ public void commit( Configuration modeConf, Request request );
}
1.2 +65 -102 xml-cocoon2/scratchpad/src/org/apache/cocoon/acting/ModularDatabaseAccess/RequestAttributeHelper.java
Index: RequestAttributeHelper.java
===================================================================
RCS file: /home/cvs/xml-cocoon2/scratchpad/src/org/apache/cocoon/acting/ModularDatabaseAccess/RequestAttributeHelper.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- RequestAttributeHelper.java 2001/11/19 16:28:33 1.1
+++ RequestAttributeHelper.java 2001/11/23 10:50:36 1.2
@@ -8,11 +8,8 @@
package org.apache.cocoon.acting.ModularDatabaseAccess;
import java.util.Enumeration;
-import java.util.SortedSet;
-import java.util.TreeSet;
-import java.sql.Connection;
-import java.sql.Statement;
-import java.sql.SQLException;
+import java.util.List;
+import java.util.LinkedList;
import org.apache.cocoon.environment.Request;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
@@ -23,124 +20,90 @@
* RequestAttributeHelper accesses request attributes.
*
* @author <a href="mailto:haul@apache.org">Christian Haul</a>
- * @version CVS $Id: RequestAttributeHelper.java,v 1.1 2001/11/19 16:28:33 haul Exp $
+ * @version CVS $Id: RequestAttributeHelper.java,v 1.2 2001/11/23 10:50:36 haul Exp $
*/
public class RequestAttributeHelper
extends AbstractAttributeHelper
- implements KeyAttributeHelper, ThreadSafe
+ implements ThreadSafe
{
- // AccessHelper methods
-
- /**
- * Return a sorted set of wildcard matches.
- * @param name String identifying the parameter
- * @param modeConf mode's configuration from resource description.
- * @param request the request object
- */
- public SortedSet getAttributeSet( String name,
- Configuration modeConf,
- Request request
- )
- throws ConfigurationException
- {
- // split the parameter's name so that the "*" could be determined
- // by looking at the parameters' names that start with the prefix
- // and end with the suffix
- String wildcard = name;
- if ( modeConf != null ) {
- wildcard = modeConf.getAttribute( "parameter", wildcard );
- }
- int wildcardIndex = wildcard.indexOf( "*" );
- String prefix = wildcard.substring( 0, wildcardIndex );
- String suffix;
- if ( wildcard.length() >= wildcardIndex + 1 ) {
- suffix = wildcard.substring( wildcardIndex + 1 );
- } else {
- suffix = "";
- }
-
- Enumeration names = request.getAttributeNames();
- SortedSet matchset = new TreeSet();
-
- while (names.hasMoreElements()) {
- String pname = (String) names.nextElement();
- if ( pname.startsWith( prefix ) && pname.endsWith( suffix ) ) {
- String _wildcard = pname.substring( prefix.length() );
- _wildcard = _wildcard.substring( 0, _wildcard.length() - suffix.length() );
- matchset.add( _wildcard );
- }
- }
- return matchset;
- }
-
- // AttributeHelper methods
-
- public Object getValue( String name,
- Configuration modeConf,
- Request request,
- Object index
- )
+ public Object getAttribute( String name,
+ Configuration modeConf,
+ Request request
+ )
throws ConfigurationException
{
- int idx;
String pname = name;
if ( modeConf != null ) {
pname = modeConf.getAttribute( "parameter", pname );
- }
- if ( index != null && ( idx = pname.indexOf( '*' ) ) != -1 ) {
- return request.getAttribute( pname.substring( 0, idx ) + index + pname.substring( idx + 1 ) );
- } else {
- return request.getAttribute( pname );
}
+ return request.getAttribute( pname );
}
-
- // KeyAttributeHelper methods
-
- public Object getPostValue( Configuration tableConf,
- Configuration columnConf,
- Configuration modeConf,
- Connection conn,
- Statement stmt,
- Request request
- )
- throws SQLException, ConfigurationException
+ public Enumeration getAttributeNames( Configuration modeConf,
+ Request request
+ )
+ throws ConfigurationException
{
- return null;
+ return request.getAttributeNames();
}
- public boolean includeInQuery()
+ public Object[] getAttributeValues( String name,
+ Configuration modeConf,
+ Request request
+ )
+ throws ConfigurationException
{
- return true;
- }
+ String wildcard = name;
+ if ( modeConf != null ) {
+ wildcard = modeConf.getAttribute( "parameter", wildcard );
+ }
+ int wildcardIndex = wildcard.indexOf( "*" );
+ if ( wildcardIndex != -1 ) {
+ // "*" contained in attribute name => combine all
+ // attributes' values that match prefix, suffix
+
+ // split the attribute's name so that the "*" could be
+ // determined by looking at the attributes' names that
+ // start with the prefix and end with the suffix
+ //
+ String prefix = wildcard.substring( 0, wildcardIndex );
+ String suffix;
+ if ( wildcard.length() >= wildcardIndex + 1 ) {
+ suffix = wildcard.substring( wildcardIndex + 1 );
+ } else {
+ suffix = "";
+ }
+ List values = new LinkedList();
+ Enumeration names = request.getAttributeNames();
+
+ while (names.hasMoreElements()) {
+ String pname = (String) names.nextElement();
+ if ( pname.startsWith( prefix ) && pname.endsWith( suffix ) ) {
+ values.add( request.getAttribute( pname ) );
+ }
+ }
- public boolean includeAsValue()
- {
- return true;
- }
+ return values.toArray();
- public Object getPreValue( Configuration tableConf,
- Configuration columnConf,
- Configuration modeConf,
- Connection conn,
- Request request,
- Object idx
- )
- throws SQLException, ConfigurationException
- {
- return this.getValue( tableConf.getAttribute( "name" ) + "." + columnConf.getAttribute( "name" ),
- modeConf, request, idx );
- }
+ } else {
+ // no "*" in attribute name => just return all values of
+ // this one attribute. Make sure, it's an array.
+
+ Object value = request.getAttribute( wildcard );
+ if ( value != null && !value.getClass().isArray() ) {
+ Object[] values = new Object[1];
+ values[0] = value;
+ return values;
+ } else {
+ return (Object[]) value;
+ }
- public String getSubquery( Configuration tableConf,
- Configuration columnConf,
- Configuration modeConf
- )
- throws ConfigurationException
- {
- return null;
+ }
+
}
+
+
}
1.2 +25 -11 xml-cocoon2/scratchpad/src/org/apache/cocoon/acting/ModularDatabaseAccess/RequestAttributeOutputHelper.java
Index: RequestAttributeOutputHelper.java
===================================================================
RCS file: /home/cvs/xml-cocoon2/scratchpad/src/org/apache/cocoon/acting/ModularDatabaseAccess/RequestAttributeOutputHelper.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- RequestAttributeOutputHelper.java 2001/11/19 16:28:33 1.1
+++ RequestAttributeOutputHelper.java 2001/11/23 10:50:36 1.2
@@ -10,48 +10,60 @@
import java.util.Enumeration;
import org.apache.cocoon.environment.Request;
import org.apache.avalon.framework.logger.AbstractLoggable;
+import org.apache.avalon.framework.configuration.Configuration;
/**
- * Abstraction layer to encapsulate different DBMS behaviour for
- * normal i.e. non key columns.
+ * Abstraction layer to encapsulate different output
+ * destinations. Configuration option <key-prefix> defaults to
+ * "org.apache.cocoon.acting.ModularDatabaseAccess.OutputHelper"+":"
*
* @author <a href="mailto:haul@apache.org">Christian Haul</a>
- * @version CVS $Id: RequestAttributeOutputHelper.java,v 1.1 2001/11/19 16:28:33 haul Exp $
+ * @version CVS $Id: RequestAttributeOutputHelper.java,v 1.2 2001/11/23 10:50:36 haul Exp $
* */
public class RequestAttributeOutputHelper
- extends AbstractLoggable
+ extends AbstractOutputHelper
implements OutputHelper {
/**
* communicate an attribute value to further processing logic.
+ * @param modeConf column's mode configuration from resource
+ * description. This argument is optional.
* @param request The request object
* @param name The attribute's label, consisting of "table.column"
* or "table.column[index]" in case of multiple attributes of the
* same spec.
* @param value The attriute's value.
* */
- public void setAttribute( Request request,
+ public void setAttribute( Configuration modeConf,
+ Request request,
String name,
Object value
)
{
- request.setAttribute("org.apache.cocoon.acting.ModularDatabaseAccess.OutputHelper:"+name,value);
+ request.setAttribute( ( (String) this.settings.get("key-prefix",
+ "org.apache.cocoon.acting.ModularDatabaseAccess.OutputHelper" ) )
+ + ":" + name, value);
}
/**
* retrieve an attribute from other processing steps. <em>Do we
* really need this thingy?</em>
+ * @param modeConf column's mode configuration from resource
+ * description. This argument is optional.
* @param request The request object
* @param name The attribute's label, consisting of "table.column"
* or "table.column[index]" in case of multiple attributes of the
* same spec.
* @return requested object.
* */
- public Object getAttribute( Request request,
+ public Object getAttribute( Configuration modeConf,
+ Request request,
String name )
{
- return request.getAttribute("org.apache.cocoon.acting.ModularDatabaseAccess.OutputHelper:"+name);
+ return request.getAttribute( ( (String) this.settings.get("key-prefix",
+ "org.apache.cocoon.acting.ModularDatabaseAccess.OutputHelper" ) )
+ + ":" + name );
}
/**
@@ -63,7 +75,7 @@
* your data straight to some beans or other entities could result
* in data corruption!</em>
* */
- public void rollback( Request request, Exception e )
+ public void rollback( Configuration modeConf, Request request, Exception e )
{
/*
Enumeration attributes = request.getAttributeNames();
@@ -74,7 +86,9 @@
}
}
*/
- request.setAttribute("org.apache.cocoon.acting.ModularDatabaseAccess.OutputHelper.Exception",e.getMessage());
+ request.setAttribute( ( (String) this.settings.get("key-prefix",
+ "org.apache.cocoon.acting.ModularDatabaseAccess.OutputHelper" ) ) + ":",
+ e.getMessage());
};
@@ -82,7 +96,7 @@
* Signal that the database transaction completed
* successfully. See notes on @link{rollback}.
* */
- public void commit( Request request )
+ public void commit( Configuration modeConf, Request request )
{
// empty method
}
1.2 +48 -120 xml-cocoon2/scratchpad/src/org/apache/cocoon/acting/ModularDatabaseAccess/RequestParameterHelper.java
Index: RequestParameterHelper.java
===================================================================
RCS file: /home/cvs/xml-cocoon2/scratchpad/src/org/apache/cocoon/acting/ModularDatabaseAccess/RequestParameterHelper.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- RequestParameterHelper.java 2001/11/19 16:28:33 1.1
+++ RequestParameterHelper.java 2001/11/23 10:50:36 1.2
@@ -8,11 +8,8 @@
package org.apache.cocoon.acting.ModularDatabaseAccess;
import java.util.Enumeration;
-import java.util.SortedSet;
-import java.util.TreeSet;
-import java.sql.Connection;
-import java.sql.Statement;
-import java.sql.SQLException;
+import java.util.List;
+import java.util.LinkedList;
import org.apache.cocoon.environment.Request;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
@@ -23,38 +20,53 @@
* RequestParameterHelper accesses request parameters.
*
* @author <a href="mailto:haul@apache.org">Christian Haul</a>
- * @version CVS $Id: RequestParameterHelper.java,v 1.1 2001/11/19 16:28:33 haul Exp $
+ * @version CVS $Id: RequestParameterHelper.java,v 1.2 2001/11/23 10:50:36 haul Exp $
*/
public class RequestParameterHelper
extends AbstractAttributeHelper
- implements KeyAttributeHelper, ThreadSafe
+ implements ThreadSafe
{
-
- // AccessHelper methods
+ public Object getAttribute( String name,
+ Configuration modeConf,
+ Request request
+ )
+ throws ConfigurationException
+ {
+ String pname = name;
+ if ( modeConf != null ) {
+ pname = modeConf.getAttribute( "parameter", pname );
+ }
+ return request.getParameter( pname );
+ }
- /**
- * Return a sorted set of wildcard matches.
- * @param name String identifying the parameter
- * @param modeConf mode's configuration from resource description.
- * @param request the request object
- */
- public SortedSet getAttributeSet( String name,
- Configuration modeConf,
- Request request
- )
+
+ public Enumeration getAttributeNames( Configuration modeConf,
+ Request request
+ )
throws ConfigurationException
{
- // split the parameter's name so that the "*" could be determined
- // by looking at the parameters' names that start with the prefix
- // and end with the suffix
- String wildcard = name;
- SortedSet matchset = new TreeSet();
+ return request.getParameterNames();
+ }
+ public Object[] getAttributeValues( String name,
+ Configuration modeConf,
+ Request request
+ )
+ throws ConfigurationException
+ {
+ String wildcard = name;
if ( modeConf != null ) {
- wildcard = modeConf.getAttribute( "parameter" );
+ wildcard = modeConf.getAttribute( "parameter", wildcard );
}
int wildcardIndex = wildcard.indexOf( "*" );
if ( wildcardIndex != -1 ) {
+ // "*" contained in parameter name => combine all
+ // parameters' values that match prefix, suffix
+
+ // split the parameter's name so that the "*" could be
+ // determined by looking at the parameters' names that
+ // start with the prefix and end with the suffix
+ //
String prefix = wildcard.substring( 0, wildcardIndex );
String suffix;
if ( wildcard.length() >= wildcardIndex + 1 ) {
@@ -62,110 +74,26 @@
} else {
suffix = "";
}
-
+ List values = new LinkedList();
Enumeration names = request.getParameterNames();
-
- while ( names.hasMoreElements() ) {
+
+ while (names.hasMoreElements()) {
String pname = (String) names.nextElement();
if ( pname.startsWith( prefix ) && pname.endsWith( suffix ) ) {
- String _wildcard = pname.substring( prefix.length() );
- _wildcard = _wildcard.substring( 0, _wildcard.length() - suffix.length() );
- matchset.add( _wildcard );
- }
- }
- } else {
- // no wildcard, this might be an array, though
- Object[] parameterValues = request.getParameterValues( wildcard );
- if ( parameterValues != null ) {
- for ( int i = 0; i < parameterValues.length; i++ ) {
- matchset.add( new Integer(i) );
+ values.add( request.getParameter( pname ) );
}
}
- }
-
- return matchset;
- }
-
- // AttributeHelper methods
- public Object getValue( String name,
- Configuration modeConf,
- Request request,
- Object index
- )
- throws ConfigurationException
- {
- int idx;
- String pname = name;
- Object result = null;
- if ( modeConf != null ) {
- pname = modeConf.getAttribute( "parameter", pname );
- }
+ return values.toArray();
- if (index != null && (idx = pname.indexOf('*')) != -1) {
- // index is wildcard match
- result = request.getParameter( pname.substring( 0, idx ) + index + pname.substring( idx + 1 ) );
} else {
- if ( index != null ) {
- // index to array of multiple parameter values
- Object[] parameterValues = request.getParameterValues( pname );
- if ( parameterValues != null ) {
- result = parameterValues[((Integer) index).intValue()];
- }
- } else {
- // no index present
- result = request.getParameter( pname );
- }
+ // no "*" in parameter name => just return all values of
+ // this one parameter.
+
+ return request.getParameterValues( wildcard );
+
}
- return result;
+
}
-
-
- // KeyAttributeHelper methods
-
- public Object getPostValue( Configuration tableConf,
- Configuration columnConf,
- Configuration modeConf,
- Connection conn,
- Statement stmt,
- Request request
- )
- throws SQLException, ConfigurationException
- {
- return null;
- }
-
- public boolean includeInQuery()
- {
- return true;
- }
-
- public boolean includeAsValue()
- {
- return true;
- }
-
- public Object getPreValue( Configuration tableConf,
- Configuration columnConf,
- Configuration modeConf,
- Connection conn,
- Request request,
- Object idx
- )
- throws SQLException, ConfigurationException
- {
- return this.getValue( tableConf.getAttribute("name") + "." + columnConf.getAttribute("name"),
- modeConf, request, idx );
- }
-
- public String getSubquery( Configuration tableConf,
- Configuration columnConf,
- Configuration modeConf
- )
- throws ConfigurationException
- {
- return null;
- }
-
}
1.1 xml-cocoon2/scratchpad/src/org/apache/cocoon/acting/ModularDatabaseAccess/AbstractAutoIncrementHelper.java
Index: AbstractAutoIncrementHelper.java
===================================================================
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
* ------------------------------------------------------------------------- *
* This software is published under the terms of the Apache Software License *
* version 1.1, a copy of which has been included with this distribution in *
* the LICENSE file. *
*****************************************************************************/
package org.apache.cocoon.acting.ModularDatabaseAccess;
import org.apache.avalon.framework.activity.Disposable;
import org.apache.avalon.framework.configuration.Configurable;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.logger.AbstractLoggable;
import org.apache.cocoon.util.HashMap;
/**
* AbstractDatabaseHelper gives you the infrastructure for easily
* deploying more AutoIncrementHelpers. In order to get at the Logger, use
* getLogger().
*
* @author <a href="mailto:haul@apache.org">Christian Haul</a>
* @version CVS $Revision: 1.1 $ $Date: 2001/11/23 10:50:36 $ */
public abstract class AbstractAutoIncrementHelper extends AbstractLoggable
implements AutoIncrementHelper, Configurable, Disposable {
/**
* Stores (global) configuration parameters as <code>key</code> /
* <code>value</code> pairs.
*/
protected HashMap settings = null;
/**
* Configures the database access helper.
*
* Takes all elements nested in component declaration and stores
* them as key-value pairs in <code>settings</code>. Nested
* configuration option are not catered for. This way global
* configuration options can be used.
*
* For nested configurations override this function.
* */
public void configure(Configuration conf) throws ConfigurationException {
getLogger().debug("ADBH: configure");
if (conf != null) {
String key = null;
String val = null;
Configuration[] parameters = conf.getChildren();
this.settings = new HashMap(parameters.length);
for ( int i = 0; i < parameters.length; i++) {
key = parameters[i].getName();
val = parameters[i].getValue();
if ( key != null )
this.settings.put(key, val);
}
}
}
/**
* dispose
*/
public void dispose() {
// Purposely empty so that we don't need to implement it in every
// class.
}
}
1.1 xml-cocoon2/scratchpad/src/org/apache/cocoon/acting/ModularDatabaseAccess/AbstractOutputHelper.java
Index: AbstractOutputHelper.java
===================================================================
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
* ------------------------------------------------------------------------- *
* This software is published under the terms of the Apache Software License *
* version 1.1, a copy of which has been included with this distribution in *
* the LICENSE file. *
*****************************************************************************/
package org.apache.cocoon.acting.ModularDatabaseAccess;
import org.apache.avalon.framework.activity.Disposable;
import org.apache.avalon.framework.configuration.Configurable;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.logger.AbstractLoggable;
import org.apache.cocoon.util.HashMap;
/**
* AbstractOutputHelper gives you the infrastructure for easily
* deploying more output helpers. In order to get at the
* Logger, use getLogger().
*
* @author <a href="mailto:haul@apache.org">Christian Haul</a>
* @version CVS $Revision: 1.1 $ $Date: 2001/11/23 10:50:36 $ */
public abstract class AbstractOutputHelper extends AbstractLoggable
implements OutputHelper, Configurable, Disposable {
/**
* Stores (global) configuration parameters as <code>key</code> /
* <code>value</code> pairs.
*/
protected HashMap settings = null;
/**
* Configures the database access helper.
*
* Takes all elements nested in component declaration and stores
* them as key-value pairs in <code>settings</code>. Nested
* configuration option are not catered for. This way global
* configuration options can be used.
*
* For nested configurations override this function.
* */
public void configure(Configuration conf) throws ConfigurationException {
if (conf != null) {
String key = null;
String val = null;
Configuration[] parameters = conf.getChildren();
this.settings = new HashMap(parameters.length);
for ( int i = 0; i < parameters.length; i++) {
key = parameters[i].getName();
val = parameters[i].getValue();
if ( key != null )
this.settings.put(key, val);
}
}
}
/**
* dispose
*/
public void dispose() {
// Purposely empty so that we don't need to implement it in every
// class.
}
}
1.1 xml-cocoon2/scratchpad/src/org/apache/cocoon/acting/ModularDatabaseAccess/AutoIncrementHelper.java
Index: AutoIncrementHelper.java
===================================================================
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
* ------------------------------------------------------------------------- *
* This software is published under the terms of the Apache Software License *
* version 1.1, a copy of which has been included with this distribution in *
* the LICENSE file. *
*****************************************************************************/
package org.apache.cocoon.acting.ModularDatabaseAccess;
import java.sql.Connection;
import java.sql.Statement;
import java.sql.SQLException;
import org.apache.cocoon.environment.Request;
import org.apache.avalon.framework.component.Component;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
/**
* Abstraction layer to encapsulate different DBMS behaviour for key
* attribute columns.
*
* @author <a href="mailto:haul@apache.org">Christian Haul</a>
* @version CVS $Id: AutoIncrementHelper.java,v 1.1 2001/11/23 10:50:36 haul Exp $
* */
public interface AutoIncrementHelper
extends Component
{
String ROLE = "org.apache.cocoon.acting.ModularDatabaseAccess.AutoIncrementHelper";
/**
* Return key attribute value of last inserted row.
*
* @param name a String that specifies what the caller thinks
* would identify a set of parameters. This is mainly a fallback
* if no modeConf is present.
* @param tableConf Table's configuration from resource description.
* @param columnConf column's configuration from resource description.
* @param mdoeConf this mode's configuration from resource description.
* @param conn Connection
* @param stmt Statement that was executed to insert the last row.
* @param request The request object
* @return value representing the last key value value.
* */
public Object getPostValue( Configuration tableConf,
Configuration columnConf,
Configuration modeConf,
Connection conn,
Statement stmt,
Request request
)
throws SQLException, ConfigurationException;
/**
* Boolean whether the key attribute column needs to be included
* in the insert query.
*
* @return true if the column is needed, false if the column
* should be skipped.
* */
public boolean includeInQuery( );
/**
* Boolean whether the key attribute needs to be included in the
* insert query as an attribute value (no subquery).
*
* @return true if a value is needed, false if a subquery
* expression is used or the column is skipped altogether.
* */
public boolean includeAsValue( );
/**
* Provide the value for the key attribute column.
*
* If a value for the key value column is needed (i.e. the column
* is not skipped), this value is computed here.
*
* @param tableConf Table's configuration from resource description.
* @param columnConf column's configuration from resource description.
* @param mdoeConf this mode's configuration from resource description.
* @param conn Connection
* @param request The request object
* @param idx In case of multiple rows to be inserted, index to the desired row
* @return exact value for key attribute column
* */
public Object getPreValue( Configuration tableConf,
Configuration columnConf,
Configuration modeConf,
Connection conn,
Request request
)
throws SQLException, ConfigurationException;
/**
* Provide subquery string for the key attribute column.
*
* If a value for the autoincrement column is needed (i.e. the
* column is not skipped), and the value can be determined through
* a nested subquery, this function provides the subquery as a
* string.
*
* @return subquery string for autoincrement column.
*/
public String getSubquery( Configuration tableConf,
Configuration columnConf,
Configuration modeConf
)
throws ConfigurationException;
}
----------------------------------------------------------------------
In case of troubles, e-mail: webmaster@xml.apache.org
To unsubscribe, e-mail: cocoon-cvs-unsubscribe@xml.apache.org
For additional commands, e-mail: cocoon-cvs-help@xml.apache.org