Return-Path:
Delivered-To: apmail-cocoon-dev-archive@www.apache.org
Received: (qmail 79891 invoked from network); 18 Nov 2006 18:57:06 -0000
Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2)
by minotaur.apache.org with SMTP; 18 Nov 2006 18:57:06 -0000
Received: (qmail 33714 invoked by uid 500); 18 Nov 2006 18:57:14 -0000
Delivered-To: apmail-cocoon-dev-archive@cocoon.apache.org
Received: (qmail 33660 invoked by uid 500); 18 Nov 2006 18:57:14 -0000
Mailing-List: contact dev-help@cocoon.apache.org; run by ezmlm
Precedence: bulk
list-help:
list-unsubscribe:
List-Post:
Reply-To: dev@cocoon.apache.org
List-Id:
Delivered-To: mailing list dev@cocoon.apache.org
Received: (qmail 33649 invoked by uid 99); 18 Nov 2006 18:57:14 -0000
Received: from herse.apache.org (HELO herse.apache.org) (140.211.11.133)
by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 18 Nov 2006 10:57:14 -0800
X-ASF-Spam-Status: No, hits=2.0 required=10.0
tests=RCVD_IN_BL_SPAMCOP_NET,SPF_PASS
X-Spam-Check-By: apache.org
Received-SPF: pass (herse.apache.org: domain of gwk@home.nl designates
213.51.146.200 as permitted sender)
Received: from [213.51.146.200] (HELO smtpq1.tilbu1.nb.home.nl)
(213.51.146.200)
by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 18 Nov 2006 10:56:58 -0800
Received: from [213.51.146.189] (port=40346 helo=smtp2.tilbu1.nb.home.nl)
by smtpq1.tilbu1.nb.home.nl with esmtp (Exim 4.30)
id 1GlVMi-0001dt-Op; Sat, 18 Nov 2006 19:56:36 +0100
Received: from cp412192-b.dbsch1.nb.home.nl ([84.27.64.39]:51249 helo=jannet1)
by smtp2.tilbu1.nb.home.nl with esmtp (Exim 4.30)
id 1GlVMg-0001my-9U; Sat, 18 Nov 2006 19:56:34 +0100
From: "Geurt Wisselink"
To: ,
References: <455F303A.6080907@danhertz.com>
In-Reply-To: <455F303A.6080907@danhertz.com>
Subject: RE: SQL Transformer Bug?
Date: Sat, 18 Nov 2006 19:56:32 +0100
Message-ID:
MIME-Version: 1.0
Content-Type: multipart/mixed;
boundary="----=_NextPart_000_002B_01C70B4B.A5080F10"
X-Mailer: Microsoft Office Outlook 12.0
Thread-Index: AccLK/oMQLp/HrIyRbi1cjv8UqTR3gAFbfUQ
Content-Language: en-gb
X-AtHome-MailScanner-Information: Neem contact op met support@home.nl voor
meer informatie
X-AtHome-MailScanner: Found to be clean
X-Virus-Checked: Checked by ClamAV on apache.org
This is a multipart message in MIME format.
------=_NextPart_000_002B_01C70B4B.A5080F10
Content-Type: text/plain;
charset="us-ascii"
Content-Transfer-Encoding: 7bit
Dear Dan,
I ran into the same problem and ended up modifying the transformer.
I returned the modified version to the cocoon development group.
I added two options to work with xml.
The first was the original foreseen sql:xml construct.
Basically it works like this:
INSERT INTO mytable (nodeset)
VALUES ('John
SmithLondon');
In this way a string is created with the XML content in side.
The second thing I added was the capability to work with xml variables by
means of the sql:in-xml-parameter.
It works like the standard in-parameter but is tailored to work with XML
content.
This works like:
John
SmithLondon
INSERT INTO mytable (nodeset)
VALUES (?);
The modified SQLTransformer is added as attachment to this mail.
Just put it src\blocks\databases\java\org\apache\cocoon\transformation, and
rerun build.
This last option is the best for last XML blocks, because the data is
streamed to the database engine, instead of embedding it into a SQL query.
I hope this helps.
Kind regards,
Geurt Wisselink
-----Original Message-----
From: Dan Hertz [mailto:dan@danhertz.com]
Sent: 18 November 2006 17:10
To: dev@cocoon.apache.org
Subject: SQL Transformer Bug?
I'm hoping someone can help me troubleshoot why I can't insert an xml
nodeset into my database using the SQL Transformer. All I end up with is
the text() values concatenated together -- no elements or attribute
nodes. For example:
INSERT INTO mytable (nodeset)
VALUES ('John
SmithLondon');
would insert: 1JohnSmithLondon into my database.
If I plug this query into my sql editor, I correctly get:
John
SmithLondon
inserted into the database.
What am I doing wrong?
Thanks!
------=_NextPart_000_002B_01C70B4B.A5080F10
Content-Type: text/java;
name="SQLTransformer.java"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
filename="SQLTransformer.java"
/*=0A=
* Licensed to the Apache Software Foundation (ASF) under one or more=0A=
* contributor license agreements. See the NOTICE file distributed with=0A=
* this work for additional information regarding copyright ownership.=0A=
* The ASF licenses this file to You under the Apache License, Version =
2.0=0A=
* (the "License"); you may not use this file except in compliance with=0A=
* the License. You may obtain a copy of the License at=0A=
*=0A=
* http://www.apache.org/licenses/LICENSE-2.0=0A=
*=0A=
* Unless required by applicable law or agreed to in writing, software=0A=
* distributed under the License is distributed on an "AS IS" BASIS,=0A=
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or =
implied.=0A=
* See the License for the specific language governing permissions and=0A=
* limitations under the License.=0A=
*/=0A=
package org.apache.cocoon.transformation;=0A=
=0A=
import java.io.InputStream;=0A=
import java.io.IOException;=0A=
import java.io.Reader;=0A=
import java.io.StringReader;=0A=
import java.lang.reflect.Field;=0A=
import java.sql.CallableStatement;=0A=
import java.sql.Clob;=0A=
import java.sql.Connection;=0A=
import java.sql.DriverManager;=0A=
import java.sql.PreparedStatement;=0A=
import java.sql.ResultSet;=0A=
import java.sql.ResultSetMetaData;=0A=
import java.sql.SQLException;=0A=
import java.util.HashMap;=0A=
import java.util.Iterator;=0A=
import java.util.Map;=0A=
import java.util.Properties;=0A=
import java.util.TreeMap;=0A=
import java.util.List;=0A=
import java.util.ArrayList;=0A=
=0A=
import org.apache.avalon.excalibur.datasource.DataSourceComponent;=0A=
import org.apache.avalon.framework.configuration.Configuration;=0A=
import org.apache.avalon.framework.configuration.ConfigurationException;=0A=
import org.apache.avalon.framework.logger.AbstractLogEnabled;=0A=
import org.apache.avalon.framework.parameters.Parameters;=0A=
import org.apache.avalon.framework.service.ServiceException;=0A=
import org.apache.avalon.framework.service.ServiceManager;=0A=
import org.apache.avalon.framework.service.ServiceSelector;=0A=
import org.apache.cocoon.ProcessingException;=0A=
import org.apache.cocoon.components.sax.XMLDeserializer;=0A=
import org.apache.cocoon.components.sax.XMLSerializer;=0A=
import org.apache.cocoon.environment.SourceResolver;=0A=
import org.apache.cocoon.transformation.helpers.TextRecorder;=0A=
import org.apache.cocoon.xml.IncludeXMLConsumer;=0A=
import org.apache.commons.lang.StringEscapeUtils;=0A=
import org.apache.commons.lang.StringUtils;=0A=
import org.apache.excalibur.xml.sax.SAXParser;=0A=
import org.xml.sax.Attributes;=0A=
import org.xml.sax.InputSource;=0A=
import org.xml.sax.SAXException;=0A=
import org.xml.sax.helpers.AttributesImpl;=0A=
=0A=
/**=0A=
* The SQLTransformer
can be plugged into a pipeline to =
transform=0A=
* SAX events into updated or queries and responses to/from a SQL =
interface.=0A=
*=0A=
* =0A=
* It is declared and configured as follows:=0A=
*
=0A=
* <map:transformers default=3D"...">=0A=
* <map:transformer name=3D"sql" =
src=3D"org.apache.cocoon.transformation.SQLTransformer">=0A=
* <old-driver>false</old-driver>=0A=
* <connection-attempts>5</connection-attempts>=0A=
* <connection-waittime>5000</connection-waittime>=0A=
* </map:transformer>=0A=
* </map:transformers>=0A=
*
=0A=
*
=0A=
*=0A=
* =0A=
* It can be used in the sitemap pipeline as follows:=0A=
* =0A=
* <map:transform type=3D"sql">=0A=
* =0A=
* <map:parameter name=3D"own-connection" value=3D"..."/>=0A=
* =0A=
* <map:parameter name=3D"use-connection" value=3D"..."/>=0A=
* =0A=
* <map:parameter name=3D"dburl" value=3D"..."/>=0A=
* <map:parameter name=3D"username" value=3D"..."/>=0A=
* <map:parameter name=3D"password" value=3D"..."/>=0A=
*=0A=
* =0A=
* <map:parameter name=3D"show-nr-or-rows" value=3D"false"/>=0A=
* <map:parameter name=3D"doc-element" value=3D"rowset"/>=0A=
* <map:parameter name=3D"row-element" value=3D"row"/>=0A=
* <map:parameter name=3D"namespace-uri" =
value=3D"http://apache.org/cocoon/SQL/2.0"/>=0A=
* <map:parameter name=3D"namespace-prefix" value=3D"sql"/>=0A=
* <map:parameter name=3D"clob-encoding" value=3D""/>=0A=
* </map:transform>=0A=
* =0A=
*
=0A=
*=0A=
* =0A=
* The following DTD is valid:=0A=
* =0A=
* <!ENTITY % param =
"(own-connection?,(use-connection|(dburl,username,password))?,show-nr-or-=
rows?,doc-element?,row-element?,namespace-uri?,namespace-prefix?,clob-enc=
oding?)">
=0A=
* <!ELEMENT execute-query =
(query,(in-parameter|in-xml-parameter|out-parameter)*,execute-query?, =
%param;)>
=0A=
* <!ELEMENT own-connection (#PCDATA)>
=0A=
* <!ELEMENT use-connection (#PCDATA)>
=0A=
* <!ELEMENT query (#PCDATA | substitute-value | ancestor-value | =
escape-string| xml)*>
=0A=
* <!ATTLIST query name CDATA #IMPLIED isstoredprocedure (true|false) =
"false" isupdate (true|false) "false">
=0A=
* <!ELEMENT substitute-value EMPTY>
=0A=
* <!ATTLIST substitute-value name CDATA #REQUIRED>
=0A=
* <!ELEMENT ancestor-value EMPTY>
=0A=
* <!ATTLIST ancestor-value name CDATA #REQUIRED level CDATA =
#REQUIRED>
=0A=
* <!ELEMENT in-parameter EMPTY>
=0A=
* <!ATTLIST in-parameter nr CDATA #REQUIRED type CDATA =
#REQUIRED>
=0A=
* <!ELEMENT in-xml-parameter EMPTY>
=0A=
* <!ATTLIST in-xml-parameter nr CDATA #REQUIRED type CDATA =
#REQUIRED>
=0A=
* <!ELEMENT out-parameter EMPTY>
=0A=
* <!ATTLIST out-parameter nr CDATA #REQUIRED name CDATA #REQUIRED =
type CDATA #REQUIRED>
=0A=
* <!ELEMENT escape-string (#PCDATA)>
=0A=
* <!ELEMENT xml (#PCDATA)>
=0A=
*
=0A=
*
=0A=
*=0A=
* =0A=
* Each query can override default transformer parameters. Nested =
queries do not inherit parent=0A=
* query parameters, but only transformer parameters. Each query can =
have connection to different=0A=
* database, directly or using the connection pool. If database =
connection parameters are the same=0A=
* as for any of the ancestor queries, nested query will re-use ancestor =
query connection.=0A=
*
=0A=
*=0A=
* =0A=
* Connection sharing between queries can be disabled, globally or on =
per-query basis, using=0A=
* own-connection
parameter.=0A=
*
=0A=
*=0A=
* =0A=
* By default, CLOBs are read from the database using getSubString, so =
that character=0A=
* decoding is performed by the database. Using =
clob-encoding
parameter,=0A=
* this behavior can be overrided, so that data is read as byte stream =
and decoded using=0A=
* specified character encoding.=0A=
*
=0A=
*=0A=
* =0A=
* Inserting of XML data can be done by using the new sql:xml or =
SQL:in-xml-parameter tags.=0A=
* - sql:xml must be used like sql:escape-string=0A=
* - sql:in-xml-parameter must be used like sql:in-parameter.=0A=
*
=0A=
*=0A=
* @author Carsten Ziegeler=0A=
* @author Donald Ball=0A=
* @author Giacomo Pati=0A=
* (PWR Organisation & Entwicklung)=0A=
* @author Sven =
Beauprez=0A=
* @author Alfio =
Saglimbeni=0A=
* @author Philipp Hahn=0A=
* @author Vadim Gritsenko=0A=
* @version $Id: SQLTransformer.java 433543 2006-08-22 06:22:54Z =
crossley $=0A=
*/=0A=
public class SQLTransformer extends AbstractSAXTransformer {=0A=
=0A=
private static final int BUFFER_SIZE =3D 1024;=0A=
=0A=
/** The SQL transformer namespace */=0A=
public static final String NAMESPACE =3D =
"http://apache.org/cocoon/SQL/2.0";=0A=
=0A=
// The SQL trasformer namespace element names=0A=
public static final String MAGIC_EXECUTE_QUERY =3D "execute-query";=0A=
private static final String MAGIC_OWN_CONNECTION =3D =
"own-connection";=0A=
public static final String MAGIC_CONNECTION =3D "use-connection";=0A=
public static final String MAGIC_DBURL =3D "dburl";=0A=
public static final String MAGIC_USERNAME =3D "username";=0A=
public static final String MAGIC_PROP =3D "prop";=0A=
public static final String MAGIC_PASSWORD =3D "password";=0A=
public static final String MAGIC_NR_OF_ROWS =3D "show-nr-of-rows";=0A=
public static final String MAGIC_QUERY =3D "query";=0A=
public static final String MAGIC_VALUE =3D "value";=0A=
public static final String MAGIC_COLUMN_CASE =3D "column-case";=0A=
public static final String MAGIC_DOC_ELEMENT =3D "doc-element";=0A=
public static final String MAGIC_ROW_ELEMENT =3D "row-element";=0A=
public static final String MAGIC_IN_PARAMETER =3D "in-parameter";=0A=
public static final String MAGIC_IN_PARAMETER_NR_ATTRIBUTE =3D "nr";=0A=
public static final String MAGIC_IN_PARAMETER_VALUE_ATTRIBUTE =3D =
"value";=0A=
public static final String MAGIC_OUT_PARAMETER =3D "out-parameter";=0A=
public static final String MAGIC_OUT_PARAMETER_NAME_ATTRIBUTE =3D =
"name";=0A=
public static final String MAGIC_OUT_PARAMETER_NR_ATTRIBUTE =3D "nr";=0A=
public static final String MAGIC_OUT_PARAMETER_TYPE_ATTRIBUTE =3D =
"type";=0A=
public static final String MAGIC_ESCAPE_STRING =3D "escape-string";=0A=
public static final String MAGIC_XML =3D "xml";=0A=
public static final String MAGIC_IN_XML_PARAMETER =3D =
"in-xml-parameter";=0A=
public static final String MAGIC_ERROR =3D "error";=0A=
=0A=
public static final String MAGIC_NS_URI_ELEMENT =3D "namespace-uri";=0A=
public static final String MAGIC_NS_PREFIX_ELEMENT =3D =
"namespace-prefix";=0A=
=0A=
public static final String MAGIC_ANCESTOR_VALUE =3D "ancestor-value";=0A=
public static final String MAGIC_ANCESTOR_VALUE_LEVEL_ATTRIBUTE =3D =
"level";=0A=
public static final String MAGIC_ANCESTOR_VALUE_NAME_ATTRIBUTE =3D =
"name";=0A=
public static final String MAGIC_SUBSTITUTE_VALUE =3D =
"substitute-value";=0A=
public static final String MAGIC_SUBSTITUTE_VALUE_NAME_ATTRIBUTE =3D =
"name";=0A=
public static final String MAGIC_NAME_ATTRIBUTE =3D "name";=0A=
public static final String MAGIC_STORED_PROCEDURE_ATTRIBUTE =3D =
"isstoredprocedure";=0A=
public static final String MAGIC_UPDATE_ATTRIBUTE =3D "isupdate";=0A=
public static final String CLOB_ENCODING =3D "clob-encoding";=0A=
=0A=
// The states we are allowed to be in=0A=
protected static final int STATE_OUTSIDE =3D 0;=0A=
protected static final int STATE_INSIDE_EXECUTE_QUERY_ELEMENT =3D 1;=0A=
protected static final int STATE_INSIDE_VALUE_ELEMENT =3D 2;=0A=
protected static final int STATE_INSIDE_QUERY_ELEMENT =3D 3;=0A=
protected static final int STATE_INSIDE_ANCESTOR_VALUE_ELEMENT =3D 4;=0A=
protected static final int STATE_INSIDE_SUBSTITUTE_VALUE_ELEMENT =3D =
5;=0A=
protected static final int STATE_INSIDE_IN_PARAMETER_ELEMENT =3D 6;=0A=
protected static final int STATE_INSIDE_OUT_PARAMETER_ELEMENT =3D 7;=0A=
protected static final int STATE_INSIDE_ESCAPE_STRING =3D 8;=0A=
protected static final int STATE_INSIDE_XML =3D 9;=0A=
protected static final int STATE_INSIDE_IN_XML_PARAMETER_ELEMENT =3D =
10;=0A=
=0A=
//=0A=
// Configuration=0A=
//=0A=
=0A=
/** Is the old-driver turned on? (default is off) */=0A=
protected boolean oldDriver;=0A=
=0A=
/** How many connection attempts to do? (default is 5 times) */=0A=
protected int connectAttempts;=0A=
=0A=
/** How long wait between connection attempts? (default is 5000 ms) =
*/=0A=
protected int connectWaittime;=0A=
=0A=
//=0A=
// State=0A=
//=0A=
=0A=
/** The current query we are working on */=0A=
protected Query query;=0A=
=0A=
/** The current state of the event receiving FSM */=0A=
protected int state;=0A=
=0A=
/** The datasource component selector */=0A=
protected ServiceSelector datasources;=0A=
=0A=
/** The "name" of the connection shared by top level queries (if =
configuration allows) */=0A=
protected String connName;=0A=
=0A=
/** The connection shared by top level queries (if configuration =
allows) */=0A=
protected Connection conn;=0A=
=0A=
// Used to parse XML from database.=0A=
protected XMLSerializer compiler;=0A=
protected XMLDeserializer interpreter;=0A=
protected SAXParser parser;=0A=
=0A=
/**=0A=
* Constructor=0A=
*/=0A=
public SQLTransformer() {=0A=
super.defaultNamespaceURI =3D NAMESPACE;=0A=
}=0A=
=0A=
//=0A=
// Lifecycle Methods=0A=
//=0A=
=0A=
/**=0A=
* Serviceable=0A=
*/=0A=
public void service(ServiceManager manager) throws ServiceException {=0A=
super.service(manager);=0A=
try {=0A=
this.datasources =3D (ServiceSelector) =
manager.lookup(DataSourceComponent.ROLE + "Selector");=0A=
} catch (ServiceException e) {=0A=
getLogger().warn("DataSource component selector is not =
available.", e);=0A=
}=0A=
}=0A=
=0A=
/**=0A=
* Configure transformer. Supported configuration elements:=0A=
* =0A=
* - old-driver
=0A=
* - connect-attempts
=0A=
* - connect-waittime
=0A=
*
=0A=
*/=0A=
public void configure(Configuration conf) throws =
ConfigurationException {=0A=
super.configure(conf);=0A=
=0A=
this.oldDriver =3D =
conf.getChild("old-driver").getValueAsBoolean(false);=0A=
if (getLogger().isDebugEnabled()) {=0A=
getLogger().debug("Value for old-driver is " + =
this.oldDriver);=0A=
}=0A=
=0A=
this.connectAttempts =3D =
conf.getChild("connect-attempts").getValueAsInteger(5);=0A=
this.connectWaittime =3D =
conf.getChild("connect-waittime").getValueAsInteger(5000);=0A=
}=0A=
=0A=
/**=0A=
* Setup for the current request.=0A=
*/=0A=
public void setup(SourceResolver resolver, Map objectModel,=0A=
String source, Parameters parameters)=0A=
throws ProcessingException, SAXException, IOException {=0A=
super.setup(resolver, objectModel, source, parameters);=0A=
=0A=
// Setup instance variables=0A=
this.state =3D SQLTransformer.STATE_OUTSIDE;=0A=
this.connName =3D name(super.parameters);=0A=
}=0A=
=0A=
/**=0A=
* Recycle this component=0A=
*/=0A=
public void recycle() {=0A=
this.query =3D null;=0A=
try {=0A=
// Close the connection used by all top level queries=0A=
if (this.conn !=3D null) {=0A=
this.conn.close();=0A=
this.conn =3D null;=0A=
}=0A=
} catch (SQLException e) {=0A=
getLogger().info("Could not close connection", e);=0A=
}=0A=
this.connName =3D null;=0A=
=0A=
this.manager.release(this.parser);=0A=
this.parser =3D null;=0A=
this.manager.release(this.compiler);=0A=
this.compiler =3D null;=0A=
this.manager.release(this.interpreter);=0A=
this.interpreter =3D null;=0A=
=0A=
super.recycle();=0A=
}=0A=
=0A=
/**=0A=
* Dispose=0A=
*/=0A=
public void dispose() {=0A=
if (this.datasources !=3D null) {=0A=
this.manager.release(this.datasources);=0A=
this.datasources =3D null;=0A=
}=0A=
super.dispose();=0A=
}=0A=
=0A=
/**=0A=
* Return attribute value.=0A=
* First try non-namespaced attribute, then try this transformer =
namespace.=0A=
* @param name local attribute name=0A=
*/=0A=
private String getAttributeValue(Attributes attr, String name) {=0A=
String value =3D attr.getValue("", name);=0A=
if (value =3D=3D null) {=0A=
value =3D attr.getValue(this.namespaceURI, name);=0A=
}=0A=
=0A=
return value;=0A=
}=0A=
=0A=
//=0A=
// SAX Events Handlers=0A=
//=0A=
=0A=
protected static void throwIllegalStateException(String message) {=0A=
throw new IllegalStateException("Illegal state: " + message);=0A=
}=0A=
=0A=
/** <execute-query> */=0A=
protected void startExecuteQueryElement() {=0A=
switch (state) {=0A=
case SQLTransformer.STATE_OUTSIDE:=0A=
case SQLTransformer.STATE_INSIDE_EXECUTE_QUERY_ELEMENT:=0A=
// Create root query (if query =3D=3D null), or child =
query=0A=
this.query =3D new Query(this.query);=0A=
=
this.query.enableLogging(getLogger().getChildLogger("query"));=0A=
state =3D =
SQLTransformer.STATE_INSIDE_EXECUTE_QUERY_ELEMENT;=0A=
break;=0A=
=0A=
default:=0A=
throwIllegalStateException("Not expecting a start =
execute query element");=0A=
}=0A=
}=0A=
=0A=
/** <*> */=0A=
protected void startValueElement(String name)=0A=
throws SAXException {=0A=
switch (state) {=0A=
case SQLTransformer.STATE_INSIDE_EXECUTE_QUERY_ELEMENT:=0A=
this.stack.push(name);=0A=
startTextRecording();=0A=
state =3D SQLTransformer.STATE_INSIDE_VALUE_ELEMENT;=0A=
break;=0A=
=0A=
default:=0A=
throwIllegalStateException("Not expecting a start value =
element: " + name);=0A=
}=0A=
}=0A=
=0A=
/** <query> */=0A=
protected void startQueryElement(Attributes attributes)=0A=
throws SAXException {=0A=
switch (state) {=0A=
case SQLTransformer.STATE_INSIDE_EXECUTE_QUERY_ELEMENT:=0A=
startTextRecording();=0A=
state =3D SQLTransformer.STATE_INSIDE_QUERY_ELEMENT;=0A=
=0A=
String isUpdate =3D attributes.getValue("", =
SQLTransformer.MAGIC_UPDATE_ATTRIBUTE);=0A=
if (isUpdate !=3D null && =
!isUpdate.equalsIgnoreCase("false")) {=0A=
query.setUpdate(true);=0A=
}=0A=
=0A=
String isProcedure =3D attributes.getValue("", =
SQLTransformer.MAGIC_STORED_PROCEDURE_ATTRIBUTE);=0A=
if (isProcedure !=3D null && =
!isProcedure.equalsIgnoreCase("false")) {=0A=
query.setStoredProcedure(true);=0A=
}=0A=
=0A=
String name =3D attributes.getValue("", =
SQLTransformer.MAGIC_NAME_ATTRIBUTE);=0A=
if (name !=3D null) {=0A=
query.setName(name);=0A=
}=0A=
break;=0A=
=0A=
default:=0A=
throwIllegalStateException("Not expecting a start query =
element");=0A=
}=0A=
}=0A=
=0A=
/** </query> */=0A=
protected void endQueryElement()=0A=
throws ProcessingException, SAXException {=0A=
switch (state) {=0A=
case SQLTransformer.STATE_INSIDE_QUERY_ELEMENT:=0A=
final String value =3D endTextRecording();=0A=
if (value.length() > 0) {=0A=
query.addQueryPart(value);=0A=
}=0A=
state =3D =
SQLTransformer.STATE_INSIDE_EXECUTE_QUERY_ELEMENT;=0A=
break;=0A=
=0A=
default:=0A=
throwIllegalStateException("Not expecting a stop query =
element");=0A=
}=0A=
}=0A=
=0A=
/** </*> */=0A=
protected void endValueElement()=0A=
throws SAXException {=0A=
switch (state) {=0A=
case SQLTransformer.STATE_INSIDE_VALUE_ELEMENT:=0A=
final String name =3D (String) this.stack.pop();=0A=
final String value =3D endTextRecording();=0A=
query.setParameter(name, value);=0A=
this.state =3D =
SQLTransformer.STATE_INSIDE_EXECUTE_QUERY_ELEMENT;=0A=
break;=0A=
=0A=
default:=0A=
throwIllegalStateException("Not expecting an end value =
element");=0A=
}=0A=
}=0A=
=0A=
/** </execute-query> */=0A=
protected void endExecuteQueryElement() throws SAXException {=0A=
switch (state) {=0A=
case SQLTransformer.STATE_INSIDE_EXECUTE_QUERY_ELEMENT:=0A=
if (query.parent =3D=3D null) {=0A=
query.executeQuery();=0A=
query =3D null;=0A=
state =3D SQLTransformer.STATE_OUTSIDE;=0A=
} else {=0A=
query.parent.addNestedQuery(query);=0A=
query =3D query.parent;=0A=
state =3D =
SQLTransformer.STATE_INSIDE_EXECUTE_QUERY_ELEMENT;=0A=
}=0A=
break;=0A=
=0A=
default:=0A=
throwIllegalStateException("Not expecting an end execute =
query element");=0A=
}=0A=
}=0A=
=0A=
/** <ancestor-value> */=0A=
protected void startAncestorValueElement(Attributes attributes)=0A=
throws ProcessingException, SAXException {=0A=
switch (state) {=0A=
case SQLTransformer.STATE_INSIDE_QUERY_ELEMENT:=0A=
int level =3D 0;=0A=
try {=0A=
level =3D =
Integer.parseInt(getAttributeValue(attributes, =
SQLTransformer.MAGIC_ANCESTOR_VALUE_LEVEL_ATTRIBUTE));=0A=
} catch (Exception e) {=0A=
getLogger().debug("Invalid or missing value for " + =
SQLTransformer.MAGIC_ANCESTOR_VALUE_LEVEL_ATTRIBUTE + " attribute", e);=0A=
throwIllegalStateException("Ancestor value elements =
must have a " +=0A=
=
SQLTransformer.MAGIC_ANCESTOR_VALUE_LEVEL_ATTRIBUTE + " attribute");=0A=
}=0A=
=0A=
String name =3D getAttributeValue(attributes, =
SQLTransformer.MAGIC_ANCESTOR_VALUE_NAME_ATTRIBUTE);=0A=
if (name =3D=3D null) {=0A=
throwIllegalStateException("Ancestor value elements =
must have a " +=0A=
=
SQLTransformer.MAGIC_ANCESTOR_VALUE_NAME_ATTRIBUTE + " attribute");=0A=
}=0A=
=0A=
final String value =3D endTextRecording();=0A=
if (value.length() > 0) {=0A=
query.addQueryPart(value);=0A=
}=0A=
query.addQueryPart(new AncestorValue(level, name));=0A=
startTextRecording();=0A=
=0A=
state =3D =
SQLTransformer.STATE_INSIDE_ANCESTOR_VALUE_ELEMENT;=0A=
break;=0A=
default:=0A=
throwIllegalStateException("Not expecting a start =
ancestor value element");=0A=
}=0A=
}=0A=
=0A=
/** </ancestor-value> */=0A=
protected void endAncestorValueElement() {=0A=
state =3D SQLTransformer.STATE_INSIDE_QUERY_ELEMENT;=0A=
}=0A=
=0A=
/** <substitute-value> */=0A=
protected void startSubstituteValueElement(Attributes attributes)=0A=
throws ProcessingException, SAXException {=0A=
switch (state) {=0A=
case SQLTransformer.STATE_INSIDE_QUERY_ELEMENT:=0A=
String name =3D getAttributeValue(attributes, =
SQLTransformer.MAGIC_SUBSTITUTE_VALUE_NAME_ATTRIBUTE);=0A=
if (name =3D=3D null) {=0A=
throwIllegalStateException("Substitute value =
elements must have a " +=0A=
=
SQLTransformer.MAGIC_SUBSTITUTE_VALUE_NAME_ATTRIBUTE + " attribute");=0A=
}=0A=
String substitute =3D parameters.getParameter(name, =
null);=0A=
// Escape single quote=0A=
substitute =3D StringEscapeUtils.escapeSql(substitute);=0A=
=0A=
final String value =3D endTextRecording();=0A=
if (value.length() > 0) {=0A=
query.addQueryPart(value);=0A=
}=0A=
query.addQueryPart(substitute);=0A=
startTextRecording();=0A=
=0A=
state =3D =
SQLTransformer.STATE_INSIDE_SUBSTITUTE_VALUE_ELEMENT;=0A=
break;=0A=
=0A=
default:=0A=
throwIllegalStateException("Not expecting a start =
substitute value element");=0A=
}=0A=
}=0A=
=0A=
/** </substitute-value> */=0A=
protected void endSubstituteValueElement() {=0A=
state =3D SQLTransformer.STATE_INSIDE_QUERY_ELEMENT;=0A=
}=0A=
=0A=
/** <escape-string> */=0A=
protected void startEscapeStringElement(Attributes attributes)=0A=
throws ProcessingException, SAXException {=0A=
switch (state) {=0A=
case SQLTransformer.STATE_INSIDE_QUERY_ELEMENT:=0A=
final String value =3D endTextRecording();=0A=
if (value.length() > 0) {=0A=
query.addQueryPart(value);=0A=
}=0A=
startTextRecording();=0A=
=0A=
state =3D SQLTransformer.STATE_INSIDE_ESCAPE_STRING;=0A=
break;=0A=
=0A=
default:=0A=
throwIllegalStateException("Not expecting a start =
escape-string element");=0A=
}=0A=
}=0A=
=0A=
/** </escape-string> */=0A=
protected void endEscapeStringElement()=0A=
throws SAXException {=0A=
switch (state) {=0A=
case SQLTransformer.STATE_INSIDE_ESCAPE_STRING:=0A=
String value =3D endTextRecording();=0A=
if (value.length() > 0) {=0A=
value =3D StringEscapeUtils.escapeSql(value);=0A=
value =3D StringUtils.replace(value, "\\", "\\\\");=0A=
query.addQueryPart(value);=0A=
}=0A=
startTextRecording();=0A=
state =3D SQLTransformer.STATE_INSIDE_QUERY_ELEMENT;=0A=
break;=0A=
=0A=
default:=0A=
throwIllegalStateException("Not expecting a end =
escape-string element");=0A=
}=0A=
}=0A=
=0A=
/** <xml> */=0A=
protected void startXmlElement(Attributes attributes)=0A=
throws ProcessingException, SAXException {=0A=
switch (state) {=0A=
case SQLTransformer.STATE_INSIDE_QUERY_ELEMENT:=0A=
final String value =3D endTextRecording();=0A=
if (value.length() > 0) {=0A=
query.addQueryPart(value);=0A=
}=0A=
startSerializedXMLRecording( null);=0A=
=0A=
state =3D SQLTransformer.STATE_INSIDE_XML;=0A=
//this.getLogger().info("startXmlElement: ");=0A=
break;=0A=
=0A=
default:=0A=
throwIllegalStateException("Not expecting a start =
escape-string element");=0A=
}=0A=
}=0A=
=0A=
/** </xml> */=0A=
protected void endXmlElement()=0A=
throws ProcessingException, SAXException {=0A=
switch (state) {=0A=
case SQLTransformer.STATE_INSIDE_XML:=0A=
String value =3D endSerializedXMLRecording();=0A=
//this.getLogger().info("endXmlElement: "+value);=0A=
if (value.length() > 0) {=0A=
/*value =3D StringUtils.replace(value, "&", "&");=0A=
value =3D StringUtils.replace(value, "<", "<");=0A=
value =3D StringUtils.replace(value, ">", ">");*/=0A=
value =3D StringEscapeUtils.escapeSql(value);=0A=
query.addQueryPart(value);=0A=
}=0A=
startTextRecording();=0A=
state =3D SQLTransformer.STATE_INSIDE_QUERY_ELEMENT;=0A=
break;=0A=
=0A=
default:=0A=
throwIllegalStateException("Not expecting a end =
escape-string element");=0A=
}=0A=
}=0A=
=0A=
/** <xml> */=0A=
protected void startInXmlParameterElement(Attributes attributes)=0A=
throws ProcessingException, SAXException {=0A=
switch (state) {=0A=
case SQLTransformer.STATE_INSIDE_EXECUTE_QUERY_ELEMENT:=0A=
String nr =3D getAttributeValue(attributes, =
SQLTransformer.MAGIC_IN_PARAMETER_NR_ATTRIBUTE);=0A=
this.stack.push(nr);=0A=
startSerializedXMLRecording( null);=0A=
=0A=
state =3D =
SQLTransformer.STATE_INSIDE_IN_XML_PARAMETER_ELEMENT;=0A=
//this.getLogger().info("startXmlElement: ");=0A=
break;=0A=
=0A=
default:=0A=
throwIllegalStateException("Not expecting a start =
escape-string element");=0A=
}=0A=
}=0A=
=0A=
/** </xml> */=0A=
protected void endInXmlParameterElement()=0A=
throws ProcessingException, SAXException {=0A=
switch (state) {=0A=
case SQLTransformer.STATE_INSIDE_IN_XML_PARAMETER_ELEMENT:=0A=
String value =3D endSerializedXMLRecording();=0A=
//this.getLogger().info("endXmlElement: "+value);=0A=
if (value.length() > 0) {=0A=
int position =3D =
Integer.parseInt((String)this.stack.pop());=0A=
query.setInXmlParameter(position, value);=0A=
}=0A=
state =3D =
SQLTransformer.STATE_INSIDE_EXECUTE_QUERY_ELEMENT;=0A=
break;=0A=
=0A=
default:=0A=
throwIllegalStateException("Not expecting a end =
escape-string element");=0A=
}=0A=
}=0A=
=0A=
/** <in-parameter> */=0A=
protected void startInParameterElement(Attributes attributes) {=0A=
switch (state) {=0A=
case SQLTransformer.STATE_INSIDE_EXECUTE_QUERY_ELEMENT:=0A=
String nr =3D getAttributeValue(attributes, =
SQLTransformer.MAGIC_IN_PARAMETER_NR_ATTRIBUTE);=0A=
String value =3D getAttributeValue(attributes, =
SQLTransformer.MAGIC_IN_PARAMETER_VALUE_ATTRIBUTE);=0A=
if (getLogger().isDebugEnabled()) {=0A=
getLogger().debug("IN PARAMETER NR " + nr + "; VALUE =
" + value);=0A=
}=0A=
=0A=
int position =3D Integer.parseInt(nr);=0A=
query.setInParameter(position, value);=0A=
state =3D =
SQLTransformer.STATE_INSIDE_IN_PARAMETER_ELEMENT;=0A=
break;=0A=
=0A=
default:=0A=
throwIllegalStateException("Not expecting an =
in-parameter element");=0A=
}=0A=
}=0A=
=0A=
/** </in-parameter> */=0A=
protected void endInParameterElement() {=0A=
state =3D SQLTransformer.STATE_INSIDE_EXECUTE_QUERY_ELEMENT;=0A=
}=0A=
=0A=
/** <out-parameter> */=0A=
protected void startOutParameterElement(Attributes attributes) {=0A=
switch (state) {=0A=
case SQLTransformer.STATE_INSIDE_EXECUTE_QUERY_ELEMENT:=0A=
String name =3D getAttributeValue(attributes, =
SQLTransformer.MAGIC_OUT_PARAMETER_NAME_ATTRIBUTE);=0A=
String nr =3D getAttributeValue(attributes, =
SQLTransformer.MAGIC_OUT_PARAMETER_NR_ATTRIBUTE);=0A=
String type =3D getAttributeValue(attributes, =
SQLTransformer.MAGIC_OUT_PARAMETER_TYPE_ATTRIBUTE);=0A=
if (getLogger().isDebugEnabled()) {=0A=
getLogger().debug("OUT PARAMETER NAME" + name + ";NR =
" + nr + "; TYPE " + type);=0A=
}=0A=
=0A=
int position =3D Integer.parseInt(nr);=0A=
query.setOutParameter(position, type, name);=0A=
state =3D =
SQLTransformer.STATE_INSIDE_OUT_PARAMETER_ELEMENT;=0A=
break;=0A=
=0A=
default:=0A=
throwIllegalStateException("Not expecting an =
out-parameter element");=0A=
}=0A=
}=0A=
=0A=
/** </out-parameter> */=0A=
protected void endOutParameterElement() {=0A=
state =3D SQLTransformer.STATE_INSIDE_EXECUTE_QUERY_ELEMENT;=0A=
}=0A=
=0A=
/**=0A=
* ContentHandler method=0A=
*/=0A=
public void startTransformingElement(String uri, String name, String =
raw, Attributes attributes)=0A=
throws ProcessingException, SAXException {=0A=
if (name.equals(SQLTransformer.MAGIC_EXECUTE_QUERY)) {=0A=
startExecuteQueryElement();=0A=
} else if (name.equals(SQLTransformer.MAGIC_QUERY)) {=0A=
startQueryElement(attributes);=0A=
} else if (name.equals(SQLTransformer.MAGIC_ANCESTOR_VALUE)) {=0A=
startAncestorValueElement(attributes);=0A=
} else if (name.equals(SQLTransformer.MAGIC_SUBSTITUTE_VALUE)) {=0A=
startSubstituteValueElement(attributes);=0A=
} else if (name.equals(SQLTransformer.MAGIC_IN_PARAMETER)) {=0A=
startInParameterElement(attributes);=0A=
} else if (name.equals(SQLTransformer.MAGIC_OUT_PARAMETER)) {=0A=
startOutParameterElement(attributes);=0A=
} else if (name.equals(SQLTransformer.MAGIC_ESCAPE_STRING)) {=0A=
startEscapeStringElement(attributes);=0A=
} else if (name.equals(SQLTransformer.MAGIC_XML)) {=0A=
startXmlElement(attributes);=0A=
} else if (name.equals(SQLTransformer.MAGIC_IN_XML_PARAMETER)) {=0A=
startInXmlParameterElement(attributes);=0A=
} else {=0A=
startValueElement(name);=0A=
}=0A=
}=0A=
=0A=
/**=0A=
* ContentHandler method=0A=
*/=0A=
public void endTransformingElement(String uri, String name, String =
raw)=0A=
throws ProcessingException, IOException, SAXException {=0A=
if (name.equals(SQLTransformer.MAGIC_EXECUTE_QUERY)) {=0A=
endExecuteQueryElement();=0A=
} else if (name.equals(SQLTransformer.MAGIC_QUERY)) {=0A=
endQueryElement();=0A=
} else if (name.equals(SQLTransformer.MAGIC_ANCESTOR_VALUE)) {=0A=
endAncestorValueElement();=0A=
} else if (name.equals(SQLTransformer.MAGIC_SUBSTITUTE_VALUE)) {=0A=
endSubstituteValueElement();=0A=
} else if (name.equals(SQLTransformer.MAGIC_IN_PARAMETER)) {=0A=
endInParameterElement();=0A=
} else if (name.equals(SQLTransformer.MAGIC_OUT_PARAMETER)) {=0A=
endOutParameterElement();=0A=
} else if (name.equals(SQLTransformer.MAGIC_ESCAPE_STRING)) {=0A=
endEscapeStringElement();=0A=
} else if (name.equals(SQLTransformer.MAGIC_XML)) {=0A=
endXmlElement();=0A=
} else if (name.equals(SQLTransformer.MAGIC_IN_XML_PARAMETER)) {=0A=
endInXmlParameterElement();=0A=
} else {=0A=
endValueElement();=0A=
}=0A=
}=0A=
=0A=
//=0A=
// Helper methods for the Query=0A=
//=0A=
=0A=
/**=0A=
* Qualifies an element name by giving it a prefix.=0A=
* @param name the element name=0A=
* @param prefix the prefix to qualify with=0A=
* @return a namespace qualified name that is correct=0A=
*/=0A=
protected String nsQualify(String name, String prefix) {=0A=
if (StringUtils.isEmpty(name)) {=0A=
return name;=0A=
}=0A=
=0A=
if (StringUtils.isNotEmpty(prefix)) {=0A=
return prefix + ":" + name;=0A=
}=0A=
=0A=
return name;=0A=
}=0A=
=0A=
/**=0A=
* Helper method for generating SAX events=0A=
*/=0A=
protected void start(String uri, String prefix, String name, =
Attributes attr)=0A=
throws SAXException {=0A=
try {=0A=
super.startTransformingElement(uri, name, nsQualify(name, =
prefix), attr);=0A=
} catch (IOException e) {=0A=
throw new SAXException(e);=0A=
} catch (ProcessingException e) {=0A=
throw new SAXException(e);=0A=
}=0A=
}=0A=
=0A=
/**=0A=
* Helper method for generating SAX events=0A=
*/=0A=
protected void end(String uri, String prefix, String name) throws =
SAXException {=0A=
try {=0A=
super.endTransformingElement(uri, name, nsQualify(name, =
prefix));=0A=
} catch (IOException e) {=0A=
throw new SAXException(e);=0A=
} catch (ProcessingException e) {=0A=
throw new SAXException(e);=0A=
}=0A=
}=0A=
=0A=
/**=0A=
* Helper method for generating SAX events=0A=
*/=0A=
protected void data(String data) throws SAXException {=0A=
if (data !=3D null) {=0A=
super.characters(data.toCharArray(), 0, data.length());=0A=
}=0A=
}=0A=
=0A=
/**=0A=
* Get 'name' for the connection which can be obtained using provided=0A=
* connection parameters.=0A=
*/=0A=
private String name(Parameters params) {=0A=
final boolean ownConnection =3D =
params.getParameterAsBoolean(SQLTransformer.MAGIC_OWN_CONNECTION, false);=0A=
if (ownConnection) {=0A=
return null;=0A=
}=0A=
=0A=
final String datasourceName =3D =
params.getParameter(SQLTransformer.MAGIC_CONNECTION, null);=0A=
if (datasourceName !=3D null) {=0A=
return "ds:" + datasourceName;=0A=
}=0A=
=0A=
final String dburl =3D =
params.getParameter(SQLTransformer.MAGIC_DBURL, null);=0A=
if (dburl !=3D null) {=0A=
final String username =3D =
params.getParameter(SQLTransformer.MAGIC_USERNAME, null);=0A=
final String password =3D =
params.getParameter(SQLTransformer.MAGIC_PASSWORD, null);=0A=
=0A=
if (username =3D=3D null || password =3D=3D null) {=0A=
return "db:@" + dburl;=0A=
} else {=0A=
return "db:" + username + ":" + password + "@" + dburl;=0A=
}=0A=
}=0A=
=0A=
// Nothing configured=0A=
return "";=0A=
}=0A=
=0A=
/**=0A=
* Open database connection using provided parameters.=0A=
* Return null if neither datasource nor jndi URL configured.=0A=
*/=0A=
private Connection open(Parameters params) throws SQLException {=0A=
Connection result =3D null;=0A=
=0A=
// First check datasource name parameter=0A=
final String datasourceName =3D =
params.getParameter(SQLTransformer.MAGIC_CONNECTION, null);=0A=
if (datasourceName !=3D null) {=0A=
// Use datasource components=0A=
if (this.datasources =3D=3D null) {=0A=
throw new SQLException("Unable to get connection from =
datasource '" + datasourceName + "': " +=0A=
"No datasources configured in =
cocoon.xconf.");=0A=
}=0A=
=0A=
DataSourceComponent datasource =3D null;=0A=
try {=0A=
datasource =3D (DataSourceComponent) =
this.datasources.select(datasourceName);=0A=
for (int i =3D 0; i < this.connectAttempts && result =
=3D=3D null; i++) {=0A=
try {=0A=
result =3D datasource.getConnection();=0A=
} catch (SQLException e) {=0A=
if (i + 1 < this.connectAttempts) {=0A=
final long waittime =3D this.connectWaittime;=0A=
// Log exception if debug enabled.=0A=
if (getLogger().isDebugEnabled()) {=0A=
getLogger().info("Unable to get =
connection; waiting " +=0A=
waittime + "ms to try =
again.", e);=0A=
} else {=0A=
getLogger().info("Unable to get =
connection; waiting " +=0A=
waittime + "ms to try =
again.");=0A=
}=0A=
try {=0A=
Thread.sleep(waittime);=0A=
} catch (InterruptedException ex) {=0A=
/* ignored */=0A=
}=0A=
}=0A=
}=0A=
}=0A=
} catch (ServiceException e) {=0A=
throw new SQLException("Unable to get connection from =
datasource '" + datasourceName + "': " +=0A=
"No such datasource.");=0A=
} finally {=0A=
if (datasource !=3D null) {=0A=
this.datasources.release(datasource);=0A=
}=0A=
}=0A=
=0A=
if (result =3D=3D null) {=0A=
throw new SQLException("Failed to obtain connection from =
datasource '" + datasourceName + "'. " +=0A=
"Made " + this.connectAttempts + =
" attempts with "=0A=
+ this.connectWaittime + "ms =
interval");=0A=
}=0A=
} else {=0A=
// Then, check connection URL parameter=0A=
final String dburl =3D =
params.getParameter(SQLTransformer.MAGIC_DBURL, null);=0A=
if (dburl !=3D null) {=0A=
final String username =3D =
params.getParameter(SQLTransformer.MAGIC_USERNAME, null);=0A=
final String password =3D =
params.getParameter(SQLTransformer.MAGIC_PASSWORD, null);=0A=
final String prop =3D =
params.getParameter(SQLTransformer.MAGIC_PROP, null);=0A=
=0A=
if (username =3D=3D null || password =3D=3D null) {=0A=
result =3D DriverManager.getConnection(dburl);=0A=
} else {=0A=
if (prop =3D=3D null) {=0A=
result =3D DriverManager.getConnection(dburl, =
username, password);=0A=
} else {=0A=
Properties props =3D new Properties();=0A=
props.put("user", username );=0A=
props.put("password", password);=0A=
int proppos =3D prop.indexOf('=3D');=0A=
if (proppos > 0) {=0A=
String propname =3D prop.substring(0, proppos);=0A=
String propvalue =3D prop.substring(proppos+1);=0A=
props.put(propname, propvalue);=0A=
}=0A=
result =3D DriverManager.getConnection(dburl, props);=0A=
}=0A=
}=0A=
} else {=0A=
// Nothing configured=0A=
}=0A=
}=0A=
=0A=
return result;=0A=
}=0A=
=0A=
/**=0A=
* Attempt to parse string value=0A=
*/=0A=
private void stream(String value) throws ServiceException, =
SAXException, IOException {=0A=
try {=0A=
// Strip off the XML Declaration if there is one!=0A=
if (value.startsWith("") + 2);=0A=
}=0A=
=0A=
// Lookup components=0A=
if (this.parser =3D=3D null) {=0A=
this.parser =3D (SAXParser) =
manager.lookup(SAXParser.ROLE);=0A=
}=0A=
if (this.compiler =3D=3D null) {=0A=
this.compiler =3D (XMLSerializer) =
manager.lookup(XMLSerializer.ROLE);=0A=
}=0A=
if (this.interpreter =3D=3D null) {=0A=
this.interpreter =3D (XMLDeserializer) =
manager.lookup(XMLDeserializer.ROLE);=0A=
}=0A=
=0A=
this.parser.parse(new InputSource(new StringReader("" =
+ value + "")),=0A=
this.compiler);=0A=
=0A=
IncludeXMLConsumer filter =3D new IncludeXMLConsumer(this, =
this);=0A=
filter.setIgnoreRootElement(true);=0A=
=0A=
this.interpreter.setConsumer(filter);=0A=
this.interpreter.deserialize(this.compiler.getSAXFragment());=0A=
} finally {=0A=
// otherwise serializer won't be reset=0A=
if (this.compiler !=3D null) {=0A=
manager.release(this.compiler);=0A=
this.compiler =3D null;=0A=
}=0A=
}=0A=
}=0A=
=0A=
/**=0A=
* One of the queries in the query tree formed from nested queries.=0A=
*/=0A=
private class Query extends AbstractLogEnabled {=0A=
=0A=
/** Parent query, or null for top level query */=0A=
protected Query parent;=0A=
=0A=
/** Nested sub-queries we have. */=0A=
protected final List nested =3D new ArrayList();=0A=
=0A=
/** The parts of the query */=0A=
protected final List parts =3D new ArrayList();=0A=
=0A=
//=0A=
// Query Configuration=0A=
//=0A=
=0A=
/** Name of the query */=0A=
protected String name;=0A=
=0A=
/** If this query is actually an update (insert, update, delete) =
*/=0A=
protected boolean isUpdate;=0A=
=0A=
/** If this query is actually a stored procedure */=0A=
protected boolean isStoredProcedure;=0A=
=0A=
/** Query configuration parameters */=0A=
protected Parameters params;=0A=
=0A=
/** The namespace uri of the XML output. Defaults to {@link =
SQLTransformer#namespaceURI}. */=0A=
protected String outUri;=0A=
=0A=
/** The namespace prefix of the XML output. Defaults to 'sql'. */=0A=
protected String outPrefix;=0A=
=0A=
/** rowset element name */=0A=
protected String rowsetElement;=0A=
=0A=
/** row element name */=0A=
protected String rowElement;=0A=
=0A=
/** number of rows attribute name */=0A=
protected String nrOfRowsAttr =3D "nrofrows";=0A=
=0A=
/** Query name attribute name */=0A=
protected String nameAttr =3D "name";=0A=
=0A=
/** Handling of case of column names in results */=0A=
protected int columnCase;=0A=
=0A=
/** Registered IN parameters */=0A=
protected Map inParameters;=0A=
=0A=
/** Registered IN XML parameters */=0A=
protected Map inXmlParameters;=0A=
=0A=
/** Registered OUT parameters */=0A=
protected Map outParameters;=0A=
=0A=
/** Mapping out parameters - objectModel */=0A=
protected Map outParametersNames;=0A=
=0A=
/** Check if nr of rows need to be written out. */=0A=
protected boolean showNrOfRows;=0A=
=0A=
/** Encoding we use for CLOB field */=0A=
protected String clobEncoding;=0A=
=0A=
//=0A=
// Query State=0A=
//=0A=
=0A=
/** The connection */=0A=
protected Connection conn;=0A=
=0A=
/** The 'name' of the connection */=0A=
protected String connName;=0A=
=0A=
/** Is it our own connection? */=0A=
protected boolean ownConn;=0A=
=0A=
/** Prepared statement */=0A=
protected PreparedStatement pst;=0A=
=0A=
/** Callable statement */=0A=
protected CallableStatement cst;=0A=
=0A=
/** The results, of course */=0A=
protected ResultSet rs;=0A=
=0A=
/** And the results' metadata */=0A=
protected ResultSetMetaData md;=0A=
=0A=
/** If it is an update/etc, the return value (num rows modified) =
*/=0A=
protected int rv =3D -1;=0A=
=0A=
=0A=
protected Query(Query parent) {=0A=
this.parent =3D parent;=0A=
this.params =3D new Parameters();=0A=
this.params.merge(SQLTransformer.this.parameters);=0A=
}=0A=
=0A=
/** Add nested sub-query. */=0A=
protected void addNestedQuery(Query query) {=0A=
nested.add(query);=0A=
}=0A=
=0A=
protected void addQueryPart(Object value) {=0A=
if (getLogger().isDebugEnabled()) {=0A=
getLogger().debug("Adding query part \"" + value + "\"");=0A=
}=0A=
parts.add(value);=0A=
}=0A=
=0A=
protected String getName() {=0A=
return name;=0A=
}=0A=
=0A=
protected void setName(String name) {=0A=
this.name =3D name;=0A=
}=0A=
=0A=
protected void setParameter(String name, String value) {=0A=
if (getLogger().isDebugEnabled()) {=0A=
getLogger().debug("Adding parameter name {" + name + "} =
value {" + value + "}");=0A=
}=0A=
params.setParameter(name, value);=0A=
}=0A=
=0A=
protected void setUpdate(boolean flag) {=0A=
isUpdate =3D flag;=0A=
}=0A=
=0A=
protected void setStoredProcedure(boolean flag) {=0A=
isStoredProcedure =3D flag;=0A=
}=0A=
=0A=
protected void setInParameter(int pos, String val) {=0A=
if (inParameters =3D=3D null) {=0A=
inParameters =3D new HashMap();=0A=
}=0A=
inParameters.put(new Integer(pos), val);=0A=
}=0A=
=0A=
protected void setInXmlParameter(int pos, String val) {=0A=
if (inXmlParameters =3D=3D null) {=0A=
inXmlParameters =3D new HashMap();=0A=
}=0A=
inXmlParameters.put(new Integer(pos), val);=0A=
}=0A=
=0A=
protected void setOutParameter(int pos, String type, String =
name) {=0A=
if (outParameters =3D=3D null) {=0A=
// make sure output parameters are ordered=0A=
outParameters =3D new TreeMap();=0A=
outParametersNames =3D new HashMap();=0A=
}=0A=
outParameters.put(new Integer(pos), type);=0A=
outParametersNames.put(new Integer(pos), name);=0A=
}=0A=
=0A=
private void setColumnCase(String columnCase) {=0A=
if (columnCase.equals("lowercase")) {=0A=
this.columnCase =3D -1;=0A=
} else if (columnCase.equals("uppercase")) {=0A=
this.columnCase =3D +1;=0A=
} else if (columnCase.equals("preserve")) {=0A=
// Do nothing=0A=
this.columnCase =3D 0;=0A=
} else {=0A=
getLogger().warn("[" + columnCase + "] is not a valid =
value for . " +=0A=
"Column name retrieved from database =
will be used.");=0A=
}=0A=
}=0A=
=0A=
private void registerInParameters() throws SQLException {=0A=
if (inParameters =3D=3D null) {=0A=
return;=0A=
}=0A=
=0A=
Iterator i =3D inParameters.keySet().iterator();=0A=
while (i.hasNext()) {=0A=
Integer counter =3D (Integer) i.next();=0A=
String value =3D (String) inParameters.get(counter);=0A=
try {=0A=
pst.setObject(counter.intValue(), value);=0A=
} catch (SQLException e) {=0A=
getLogger().error("Caught a SQLException", e);=0A=
throw e;=0A=
}=0A=
}=0A=
}=0A=
=0A=
private void registerInXmlParameters() throws SQLException {=0A=
if (inXmlParameters =3D=3D null) {=0A=
return;=0A=
}=0A=
=0A=
Iterator i =3D inXmlParameters.keySet().iterator();=0A=
while (i.hasNext()) {=0A=
Integer counter =3D (Integer) i.next();=0A=
String value =3D (String) inXmlParameters.get(counter);=0A=
try {=0A=
//XMLType xt =3D XMLType.createXML(conn, value);=0A=
//pst.setObject(counter.intValue(), xt);=0A=
pst.setString(counter.intValue(), value);=0A=
} catch (SQLException e) {=0A=
getLogger().error("Caught a SQLException", e);=0A=
throw e;=0A=
}=0A=
}=0A=
}=0A=
=0A=
private void registerOutParameters(CallableStatement cst) throws =
SQLException {=0A=
if (outParameters =3D=3D null) {=0A=
return;=0A=
}=0A=
=0A=
Iterator i =3D outParameters.keySet().iterator();=0A=
while (i.hasNext()) {=0A=
Integer counter =3D (Integer) i.next();=0A=
String type =3D (String) outParameters.get(counter);=0A=
=0A=
int index =3D type.lastIndexOf(".");=0A=
String className, fieldName;=0A=
if (index =3D=3D -1) {=0A=
getLogger().error("Invalid SQLType: " + type, null);=0A=
throw new SQLException("Invalid SQLType: " + type);=0A=
}=0A=
className =3D type.substring(0, index);=0A=
fieldName =3D type.substring(index + 1, type.length());=0A=
=0A=
try {=0A=
Class clss =3D Class.forName(className);=0A=
Field fld =3D clss.getField(fieldName);=0A=
cst.registerOutParameter(counter.intValue(), =
fld.getInt(fieldName));=0A=
} catch (Exception e) {=0A=
// Lots of different exceptions to catch=0A=
getLogger().error("Invalid SQLType: " + className + =
"." + fieldName, e);=0A=
}=0A=
}=0A=
}=0A=
=0A=
/**=0A=
* Open database connection=0A=
*/=0A=
private void open() throws SQLException {=0A=
this.connName =3D SQLTransformer.this.name(this.params);=0A=
=0A=
// Check first if connection sharing disabled=0A=
if (this.connName =3D=3D null) {=0A=
this.conn =3D SQLTransformer.this.open(this.params);=0A=
this.ownConn =3D true;=0A=
return;=0A=
}=0A=
=0A=
// Iterate through parent queries and get appropriate =
connection=0A=
Query query =3D this.parent;=0A=
while (query !=3D null) {=0A=
if (this.connName.equals(query.connName)) {=0A=
this.conn =3D query.conn;=0A=
this.ownConn =3D false;=0A=
return;=0A=
}=0A=
query =3D query.parent;=0A=
}=0A=
=0A=
// Check 'global' connection=0A=
if (this.connName.equals(SQLTransformer.this.connName)) {=0A=
// Use SQLTransformer configuration: it has same =
connection parameters=0A=
if (SQLTransformer.this.conn =3D=3D null) {=0A=
SQLTransformer.this.conn =3D =
SQLTransformer.this.open(SQLTransformer.this.parameters);=0A=
}=0A=
=0A=
this.conn =3D SQLTransformer.this.conn;=0A=
this.ownConn =3D false;=0A=
return;=0A=
}=0A=
=0A=
// Create own connection=0A=
this.conn =3D SQLTransformer.this.open(this.params);=0A=
this.ownConn =3D true;=0A=
}=0A=
=0A=
/**=0A=
* This will be the meat of SQLTransformer, where the query is =
run.=0A=
*/=0A=
protected void executeQuery() throws SAXException {=0A=
if (getLogger().isDebugEnabled()) {=0A=
getLogger().debug("Executing query " + this);=0A=
}=0A=
=0A=
this.outUri =3D =
this.params.getParameter(SQLTransformer.MAGIC_NS_URI_ELEMENT, =
SQLTransformer.this.namespaceURI);=0A=
this.outPrefix =3D =
this.params.getParameter(SQLTransformer.MAGIC_NS_PREFIX_ELEMENT, "sql");=0A=
this.rowsetElement =3D =
this.params.getParameter(SQLTransformer.MAGIC_DOC_ELEMENT, "rowset");=0A=
this.rowElement =3D =
this.params.getParameter(SQLTransformer.MAGIC_ROW_ELEMENT, "row");=0A=
=0A=
this.showNrOfRows =3D =
parameters.getParameterAsBoolean(SQLTransformer.MAGIC_NR_OF_ROWS, false);=0A=
this.clobEncoding =3D =
parameters.getParameter(SQLTransformer.CLOB_ENCODING, "");=0A=
if (this.clobEncoding.length() =3D=3D 0) {=0A=
this.clobEncoding =3D null;=0A=
}=0A=
=0A=
// Start prefix mapping for output namespace, only if it's =
not mapped yet=0A=
final String prefix =3D =
SQLTransformer.this.findPrefixMapping(this.outUri);=0A=
if (prefix =3D=3D null) {=0A=
SQLTransformer.this.startPrefixMapping(this.outPrefix, =
this.outUri);=0A=
} else {=0A=
this.outPrefix =3D prefix;=0A=
}=0A=
=0A=
boolean success =3D false;=0A=
try {=0A=
try {=0A=
open();=0A=
execute();=0A=
success =3D true;=0A=
} catch (SQLException e) {=0A=
getLogger().info("Failed to execute query " + this, =
e);=0A=
start(this.rowsetElement, EMPTY_ATTRIBUTES);=0A=
start(MAGIC_ERROR, EMPTY_ATTRIBUTES);=0A=
data(e.getMessage());=0A=
end(MAGIC_ERROR);=0A=
end(this.rowsetElement);=0A=
}=0A=
=0A=
if (success) {=0A=
AttributesImpl attr =3D new AttributesImpl();=0A=
if (showNrOfRows) {=0A=
attr.addAttribute("", this.nrOfRowsAttr, =
this.nrOfRowsAttr, "CDATA", String.valueOf(getNrOfRows()));=0A=
}=0A=
String name =3D getName();=0A=
if (name !=3D null) {=0A=
attr.addAttribute("", this.nameAttr, =
this.nameAttr, "CDATA", name);=0A=
}=0A=
start(this.rowsetElement, attr);=0A=
=0A=
// Serialize stored procedure output parameters=0A=
if (isStoredProcedure) {=0A=
serializeStoredProcedure();=0A=
}=0A=
=0A=
// Serialize result set=0A=
while (next()) {=0A=
start(this.rowElement, EMPTY_ATTRIBUTES);=0A=
serializeRow();=0A=
for (Iterator i =3D this.nested.iterator(); =
i.hasNext();) {=0A=
((Query) i.next()).executeQuery();=0A=
}=0A=
end(this.rowElement);=0A=
}=0A=
=0A=
end(this.rowsetElement);=0A=
}=0A=
} catch (SQLException e) {=0A=
getLogger().debug("Exception in executeQuery()", e);=0A=
throw new SAXException(e);=0A=
} finally {=0A=
close();=0A=
}=0A=
=0A=
if (prefix =3D=3D null) {=0A=
SQLTransformer.this.endPrefixMapping(this.outPrefix);=0A=
}=0A=
}=0A=
=0A=
/**=0A=
* Execute the query. Connection must be set already.=0A=
*/=0A=
private void execute() throws SQLException {=0A=
=
setColumnCase(params.getParameter(SQLTransformer.MAGIC_COLUMN_CASE, =
"lowercase"));=0A=
=0A=
// Construct query string=0A=
StringBuffer sb =3D new StringBuffer();=0A=
for (Iterator i =3D parts.iterator(); i.hasNext();) {=0A=
Object object =3D i.next();=0A=
if (object instanceof String) {=0A=
sb.append((String) object);=0A=
} else if (object instanceof AncestorValue) {=0A=
// Do a lookup into the ancestors' result's values=0A=
AncestorValue av =3D (AncestorValue) object;=0A=
Query query =3D this;=0A=
for (int k =3D av.level; k > 0; k--) {=0A=
query =3D query.parent;=0A=
}=0A=
sb.append(query.getColumnValue(av.name));=0A=
}=0A=
}=0A=
=0A=
String query =3D StringUtils.replace(sb.toString().trim(), =
"\r", " ", -1);=0A=
// Test, if this is an update (by comparing with select)=0A=
if (!isStoredProcedure && !isUpdate) {=0A=
if (query.length() > 6 && !query.substring(0, =
6).equalsIgnoreCase("SELECT")) {=0A=
isUpdate =3D true;=0A=
}=0A=
}=0A=
=0A=
if (getLogger().isDebugEnabled()) {=0A=
getLogger().debug("Executing " + query);=0A=
}=0A=
if (!isStoredProcedure) {=0A=
if (oldDriver) {=0A=
pst =3D conn.prepareStatement(query);=0A=
} else {=0A=
pst =3D conn.prepareStatement(query,=0A=
=
ResultSet.TYPE_SCROLL_INSENSITIVE,=0A=
=
ResultSet.CONCUR_READ_ONLY);=0A=
}=0A=
} else {=0A=
if (oldDriver) {=0A=
cst =3D conn.prepareCall(query);=0A=
} else {=0A=
cst =3D conn.prepareCall(query,=0A=
=
ResultSet.TYPE_SCROLL_INSENSITIVE,=0A=
ResultSet.CONCUR_READ_ONLY);=0A=
}=0A=
registerOutParameters(cst);=0A=
pst =3D cst;=0A=
}=0A=
=0A=
registerInParameters();=0A=
registerInXmlParameters();=0A=
boolean result =3D pst.execute();=0A=
if (result) {=0A=
rs =3D pst.getResultSet();=0A=
md =3D rs.getMetaData();=0A=
} else {=0A=
rv =3D pst.getUpdateCount();=0A=
}=0A=
}=0A=
=0A=
protected int getNrOfRows() throws SQLException {=0A=
int nr =3D 0;=0A=
=0A=
if (rs !=3D null) {=0A=
if (oldDriver) {=0A=
nr =3D -1;=0A=
} else {=0A=
try {=0A=
rs.last();=0A=
nr =3D rs.getRow();=0A=
rs.beforeFirst();=0A=
} catch (NullPointerException e) {=0A=
// A NullPointerException here crashes a whole =
lot of C2 --=0A=
// catching it so it won't do any harm for now, =
but seems like it should be solved seriously=0A=
getLogger().error("NPE while getting the nr of =
rows", e);=0A=
}=0A=
}=0A=
} else {=0A=
if (outParameters !=3D null) {=0A=
nr =3D outParameters.size();=0A=
}=0A=
}=0A=
return nr;=0A=
}=0A=
=0A=
protected String getColumnValue(ResultSet rs, int i) throws =
SQLException {=0A=
final int type =3D rs.getMetaData().getColumnType(i);=0A=
if (type =3D=3D java.sql.Types.DOUBLE) {=0A=
return getStringValue(rs.getBigDecimal(i));=0A=
} else if (type =3D=3D java.sql.Types.CLOB) {=0A=
return getStringValue(rs.getClob(i));=0A=
} else {=0A=
return getStringValue(rs.getObject(i));=0A=
}=0A=
}=0A=
=0A=
// fix not applied here because there is no metadata from Name =
-> number and coltype=0A=
// for a given "name" versus number. That being said this =
shouldn't be an issue=0A=
// as this function is only called for ancestor lookups.=0A=
protected String getColumnValue(String name) throws SQLException =
{=0A=
//noinspection UnnecessaryLocalVariable=0A=
String retval =3D getStringValue(rs.getObject(name));=0A=
// if (rs.getMetaData().getColumnType( name ) =3D=3D =
java.sql.Types.DOUBLE)=0A=
// retval =3D transformer.getStringValue( rs.getBigDecimal( =
name ) );=0A=
return retval;=0A=
}=0A=
=0A=
protected boolean next() throws SQLException {=0A=
// If rv is not -1, then an SQL insert, update, etc, has=0A=
// happened (see JDBC docs - return codes for executeUpdate)=0A=
if (rv !=3D -1) {=0A=
// Output row with return code. Once.=0A=
return true;=0A=
}=0A=
=0A=
if (rs !=3D null && rs.next()) {=0A=
// Have next row=0A=
return true;=0A=
}=0A=
=0A=
while (pst.getMoreResults()) {=0A=
rs =3D pst.getResultSet();=0A=
md =3D rs.getMetaData();=0A=
if (rs.next()) {=0A=
// Have next row in next result set=0A=
return true;=0A=
}=0A=
}=0A=
=0A=
// Nothing left=0A=
return false;=0A=
}=0A=
=0A=
/**=0A=
* Closes all the resources, ignores (but logs) exceptions.=0A=
*/=0A=
protected void close() {=0A=
if (rs !=3D null) {=0A=
try {=0A=
rs.close();=0A=
} catch (SQLException e) {=0A=
getLogger().info("Unable to close the result set.", =
e);=0A=
}=0A=
// This prevents us from using the resultset again.=0A=
rs =3D null;=0A=
}=0A=
=0A=
if (pst !=3D null && pst !=3D cst) {=0A=
try {=0A=
pst.close();=0A=
} catch (SQLException e) {=0A=
getLogger().info("Unable to close the statement.", =
e);=0A=
}=0A=
}=0A=
// Prevent using pst again.=0A=
pst =3D null;=0A=
=0A=
if (cst !=3D null) {=0A=
try {=0A=
cst.close();=0A=
} catch (SQLException e) {=0A=
getLogger().info("Unable to close the statement.", =
e);=0A=
}=0A=
// Prevent using cst again.=0A=
cst =3D null;=0A=
}=0A=
=0A=
try {=0A=
if (ownConn && conn !=3D null) {=0A=
conn.close();=0A=
}=0A=
} catch (SQLException e) {=0A=
getLogger().info("Unable to close the connection", e);=0A=
}=0A=
// Prevent using conn again.=0A=
conn =3D null;=0A=
}=0A=
=0A=
protected void serializeData(String value)=0A=
throws SQLException, SAXException {=0A=
if (value !=3D null) {=0A=
value =3D value.trim();=0A=
// Could this be XML ?=0A=
if (value.length() > 0 && value.charAt(0) =3D=3D '<') {=0A=
try {=0A=
stream(value);=0A=
} catch (Exception ignored) {=0A=
// FIXME: bad coding "catch(Exception)"=0A=
// If an exception occured the data was not =
(valid) xml=0A=
data(value);=0A=
}=0A=
} else {=0A=
data(value);=0A=
}=0A=
}=0A=
}=0A=
=0A=
protected void serializeRow()=0A=
throws SQLException, SAXException {=0A=
if (rv !=3D -1) {=0A=
start("returncode", EMPTY_ATTRIBUTES);=0A=
serializeData(String.valueOf(rv));=0A=
end("returncode");=0A=
// We only want the return code shown once.=0A=
// Reset rv so next() returns false next time.=0A=
rv =3D -1;=0A=
} else {=0A=
for (int i =3D 1; i <=3D md.getColumnCount(); i++) {=0A=
String columnName =3D =
getColumnName(md.getColumnName(i));=0A=
start(columnName, EMPTY_ATTRIBUTES);=0A=
serializeData(getColumnValue(rs, i));=0A=
end(columnName);=0A=
}=0A=
}=0A=
}=0A=
=0A=
private void serializeResultSet(ResultSet rs) throws =
SQLException, SAXException {=0A=
final ResultSetMetaData md =3D rs.getMetaData();=0A=
final int n =3D md.getColumnCount();=0A=
=0A=
// Get column names=0A=
final String[] columns =3D new String[n + 1];=0A=
for (int i =3D 1; i <=3D n; i++) {=0A=
columns[i] =3D getColumnName(md.getColumnName(i));=0A=
}=0A=
=0A=
// Process rows=0A=
while (rs.next()) {=0A=
start(rowElement, EMPTY_ATTRIBUTES);=0A=
for (int i =3D 1; i <=3D n; i++) {=0A=
start(columns[i], EMPTY_ATTRIBUTES);=0A=
serializeData(getColumnValue(rs, i));=0A=
end(columns[i]);=0A=
}=0A=
end(this.rowElement);=0A=
}=0A=
}=0A=
=0A=
protected void serializeStoredProcedure()=0A=
throws SQLException, SAXException {=0A=
if (outParametersNames =3D=3D null || cst =3D=3D null) {=0A=
return;=0A=
}=0A=
=0A=
Iterator itOutKeys =3D outParameters.keySet().iterator();=0A=
while (itOutKeys.hasNext()) {=0A=
final Integer counter =3D (Integer) itOutKeys.next();=0A=
try {=0A=
final Object obj =3D =
cst.getObject(counter.intValue());=0A=
final String name =3D (String) =
outParametersNames.get(counter);=0A=
start(name, EMPTY_ATTRIBUTES);=0A=
=0A=
if (!(obj instanceof ResultSet)) {=0A=
serializeData(getStringValue(obj));=0A=
} else {=0A=
final ResultSet rs =3D (ResultSet) obj;=0A=
try {=0A=
serializeResultSet(rs);=0A=
} finally {=0A=
try {=0A=
rs.close();=0A=
} catch (SQLException e) { /* ignored */ }=0A=
}=0A=
}=0A=
=0A=
end(name);=0A=
} catch (SQLException e) {=0A=
getLogger().error("Caught a SQLException", e);=0A=
throw e;=0A=
}=0A=
}=0A=
}=0A=
=0A=
private String getColumnName(String columnName) {=0A=
switch (this.columnCase) {=0A=
case -1:=0A=
columnName =3D columnName.toLowerCase();=0A=
break;=0A=
case +1:=0A=
columnName =3D columnName.toUpperCase();=0A=
break;=0A=
default:=0A=
// Do nothing=0A=
}=0A=
return columnName;=0A=
}=0A=
=0A=
/**=0A=
* Convert object to string represenation=0A=
*/=0A=
private String getStringValue(Object object) throws SQLException =
{=0A=
if (object instanceof byte[]) {=0A=
// FIXME Encoding?=0A=
return new String((byte[]) object);=0A=
}=0A=
=0A=
if (object instanceof char[]) {=0A=
return new String((char[]) object);=0A=
}=0A=
=0A=
// Old behavior: Read bytes & decode=0A=
if (object instanceof Clob && this.clobEncoding !=3D null) {=0A=
Clob clob =3D (Clob) object;=0A=
StringBuffer buffer =3D new StringBuffer();=0A=
/*The original code (below) does not work correctly with =
bulgarian, russian, chinese, etc=0A=
InputStream is =3D clob.getAsciiStream();=0A=
try {=0A=
byte[] bytes =3D new byte[BUFFER_SIZE];=0A=
int n;=0A=
while ((n =3D is.read(bytes)) > -1) {=0A=
buffer.append(new String(bytes, 0, n, =
this.clobEncoding));=0A=
}=0A=
} catch (IOException e) {=0A=
throw new SQLException("Error reading stream from =
CLOB");=0A=
} */=0A=
try {=0A=
int blocksize =3D 10000;=0A=
long length =3D clob.length();=0A=
long nMax =3D length/blocksize;=0A=
int n;=0A=
for (n=3D0;n 0) {=0A=
String sText =3D clob.getSubString(nMax*blocksize+1, =
lastblocksize);=0A=
buffer.append( sText);=0A=
}=0A=
} catch (Exception e) {=0A=
throw new SQLException("Error reading stream from =
CLOB");=0A=
}=0A=
return buffer.toString();=0A=
}=0A=
=0A=
// Correct behavior: Read character data=0A=
if (object instanceof Clob) {=0A=
Clob clob =3D (Clob) object;=0A=
StringBuffer buffer =3D new StringBuffer();=0A=
Reader cs =3D clob.getCharacterStream();=0A=
try {=0A=
char[] chars =3D new char[BUFFER_SIZE];=0A=
int n;=0A=
while ((n =3D cs.read(chars)) > -1) {=0A=
buffer.append(chars, 0, n);=0A=
}=0A=
} catch (IOException e) {=0A=
throw new SQLException("Error reading stream from =
CLOB");=0A=
}=0A=
return buffer.toString();=0A=
}=0A=
=0A=
if (object !=3D null) {=0A=
return object.toString();=0A=
}=0A=
=0A=
return "";=0A=
}=0A=
=0A=
private void start(String name, Attributes attr)=0A=
throws SAXException {=0A=
SQLTransformer.this.start(this.outUri, this.outPrefix, name, =
attr);=0A=
}=0A=
=0A=
private void end(String name) throws SAXException {=0A=
SQLTransformer.this.end(this.outUri, this.outPrefix, name);=0A=
}=0A=
=0A=
private void data(String data) throws SAXException {=0A=
SQLTransformer.this.data(data);=0A=
}=0A=
}=0A=
=0A=
private static class AncestorValue {=0A=
protected int level;=0A=
protected String name;=0A=
=0A=
protected AncestorValue(int level, String name) {=0A=
this.level =3D level;=0A=
this.name =3D name;=0A=
}=0A=
=0A=
public String toString() {=0A=
return "";=0A=
}=0A=
}=0A=
=0A=
/**=0A=
* Stop recording of text and return the recorded information.=0A=
* @return The String, trimmed.=0A=
*=0A=
* NB. SQLTransformer needs to have a special version of this method=0A=
* It needs the TextRecorder to not trim whitespace from the queries =
it is building=0A=
*=0A=
*/=0A=
public String endTextRecording()=0A=
throws SAXException {=0A=
sendEndPrefixMapping();=0A=
=0A=
TextRecorder recorder =3D (TextRecorder) removeRecorder();=0A=
String text =3D recorder.getAllText();=0A=
if (getLogger().isDebugEnabled()) {=0A=
getLogger().debug("End text recording. Text=3D" + text);=0A=
}=0A=
return text;=0A=
}=0A=
=0A=
}=0A=
------=_NextPart_000_002B_01C70B4B.A5080F10--