You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@beehive.apache.org by ke...@apache.org on 2006/07/13 03:34:07 UTC
svn commit: r421473 [2/6] - in /beehive/sandbox/hornet: ./ controls/
controls/api/ controls/api/src/ controls/api/src/main/
controls/api/src/main/java/ controls/api/src/main/java/org/
controls/api/src/main/java/org/apache/ controls/api/src/main/java/or...
Added: beehive/sandbox/hornet/controls/samples/jdbc/src/main/java/org/apache/beehive/controls/system/jdbc/DefaultResultSetMapper.java
URL: http://svn.apache.org/viewvc/beehive/sandbox/hornet/controls/samples/jdbc/src/main/java/org/apache/beehive/controls/system/jdbc/DefaultResultSetMapper.java?rev=421473&view=auto
==============================================================================
--- beehive/sandbox/hornet/controls/samples/jdbc/src/main/java/org/apache/beehive/controls/system/jdbc/DefaultResultSetMapper.java (added)
+++ beehive/sandbox/hornet/controls/samples/jdbc/src/main/java/org/apache/beehive/controls/system/jdbc/DefaultResultSetMapper.java Wed Jul 12 18:34:03 2006
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Header:$
+ */
+
+package org.apache.beehive.controls.system.jdbc;
+
+import java.lang.reflect.Method;
+import java.sql.ResultSet;
+import java.util.Calendar;
+
+/**
+ * Default ResultSetMapper implementation for ResultSets.
+ */
+public class DefaultResultSetMapper extends ResultSetMapper {
+
+ /**
+ * Maps a ResultSet to a ResultSet. The default implementation is a NOOP.
+ *
+ * @param m Method assoicated with this call.
+ * @param resultSet Result set to map.
+ * @param cal A Calendar instance for resolving date/time values.
+ * @return An object.
+ */
+ public Object mapToResultType(Method m, ResultSet resultSet, Calendar cal) {
+ return resultSet;
+ }
+
+ /**
+ * Can the ResultSet which this mapper uses be closed by the database control?
+ * @return always false
+ */
+ public boolean canCloseResultSet() { return false; }
+}
Propchange: beehive/sandbox/hornet/controls/samples/jdbc/src/main/java/org/apache/beehive/controls/system/jdbc/DefaultResultSetMapper.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: beehive/sandbox/hornet/controls/samples/jdbc/src/main/java/org/apache/beehive/controls/system/jdbc/DefaultRowSetResultSetMapper.java
URL: http://svn.apache.org/viewvc/beehive/sandbox/hornet/controls/samples/jdbc/src/main/java/org/apache/beehive/controls/system/jdbc/DefaultRowSetResultSetMapper.java?rev=421473&view=auto
==============================================================================
--- beehive/sandbox/hornet/controls/samples/jdbc/src/main/java/org/apache/beehive/controls/system/jdbc/DefaultRowSetResultSetMapper.java (added)
+++ beehive/sandbox/hornet/controls/samples/jdbc/src/main/java/org/apache/beehive/controls/system/jdbc/DefaultRowSetResultSetMapper.java Wed Jul 12 18:34:03 2006
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Header:$
+ */
+
+package org.apache.beehive.controls.system.jdbc;
+
+import com.sun.rowset.CachedRowSetImpl;
+import org.apache.beehive.controls.api.ControlException;
+import org.apache.beehive.controls.api.PropertySetReader;
+import org.apache.beehive.controls.system.jdbc.JdbcControl.SQL;
+
+import javax.sql.RowSet;
+import java.lang.reflect.Method;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Calendar;
+
+/**
+ * Default ResultSetMapper implementation for RowSets.
+ */
+public class DefaultRowSetResultSetMapper extends ResultSetMapper {
+
+ /**
+ * Map a ResultSet to a RowSet. Type of RowSet is defined by the SQL annotation for the method.
+ *
+ * @param m Method assoicated with this call.
+ * @param resultSet Result set to map.
+ * @param cal A Calendar instance for resolving date/time values.
+ * @return A RowSet object.
+ */
+ public RowSet mapToResultType(Method m, ResultSet resultSet, Calendar cal) {
+ final SQL methodSQL = PropertySetReader.getMethodPropertySet(m, SQL.class);
+ final int maxrows = methodSQL.maxRows();
+
+ try {
+ CachedRowSetImpl rows = new CachedRowSetImpl();
+
+ if (maxrows > 0) {
+ rows.setMaxRows(maxrows);
+ }
+
+ rows.populate(resultSet);
+ return rows;
+ } catch (SQLException e) {
+ throw new ControlException(e.getMessage(), e);
+ }
+ }
+
+ /**
+ * Can the ResultSet which this mapper uses be closed by the database control?
+ *
+ * @return always false
+ */
+ public boolean canCloseResultSet() { return false; }
+}
Propchange: beehive/sandbox/hornet/controls/samples/jdbc/src/main/java/org/apache/beehive/controls/system/jdbc/DefaultRowSetResultSetMapper.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: beehive/sandbox/hornet/controls/samples/jdbc/src/main/java/org/apache/beehive/controls/system/jdbc/DefaultXmlObjectResultSetMapper.java
URL: http://svn.apache.org/viewvc/beehive/sandbox/hornet/controls/samples/jdbc/src/main/java/org/apache/beehive/controls/system/jdbc/DefaultXmlObjectResultSetMapper.java?rev=421473&view=auto
==============================================================================
--- beehive/sandbox/hornet/controls/samples/jdbc/src/main/java/org/apache/beehive/controls/system/jdbc/DefaultXmlObjectResultSetMapper.java (added)
+++ beehive/sandbox/hornet/controls/samples/jdbc/src/main/java/org/apache/beehive/controls/system/jdbc/DefaultXmlObjectResultSetMapper.java Wed Jul 12 18:34:03 2006
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Header:$
+ */
+
+package org.apache.beehive.controls.system.jdbc;
+
+import org.apache.beehive.controls.api.ControlException;
+import org.apache.beehive.controls.api.PropertySetReader;
+import org.apache.beehive.controls.system.jdbc.JdbcControl.SQL;
+
+import java.lang.reflect.Method;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Calendar;
+
+/**
+ * Default ResultSetMapper implementation for XmlObjects.
+ */
+public class DefaultXmlObjectResultSetMapper extends DefaultObjectResultSetMapper {
+
+ /**
+ * Map a ResultSet to an XmlObject. Object type is defined by the return type of the method.
+ *
+ * @param m Method associated with this call.
+ * @param resultSet Result set to map.
+ * @param cal A Calendar instance for resolving date/time values.
+ * @return An XmlObject
+ */
+ public Object mapToResultType(Method m, ResultSet resultSet, Calendar cal) {
+
+ final Class returnType = m.getReturnType();
+ final boolean isArray = returnType.isArray();
+
+ try {
+ if (isArray) {
+ final SQL methodSQL = PropertySetReader.getMethodPropertySet(m, SQL.class);
+ return arrayFromResultSet(resultSet, methodSQL.arrayMaxLength(), returnType, cal);
+ } else {
+
+ if (!resultSet.next()) {
+ return _tmf.fixNull(m.getReturnType());
+ }
+
+ return RowMapperFactory.getRowMapper(resultSet, returnType, cal).mapRowToReturnType();
+ }
+ } catch (SQLException e) {
+ throw new ControlException(e.getMessage(), e);
+ }
+ }
+}
Propchange: beehive/sandbox/hornet/controls/samples/jdbc/src/main/java/org/apache/beehive/controls/system/jdbc/DefaultXmlObjectResultSetMapper.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: beehive/sandbox/hornet/controls/samples/jdbc/src/main/java/org/apache/beehive/controls/system/jdbc/JdbcControl.java
URL: http://svn.apache.org/viewvc/beehive/sandbox/hornet/controls/samples/jdbc/src/main/java/org/apache/beehive/controls/system/jdbc/JdbcControl.java?rev=421473&view=auto
==============================================================================
--- beehive/sandbox/hornet/controls/samples/jdbc/src/main/java/org/apache/beehive/controls/system/jdbc/JdbcControl.java (added)
+++ beehive/sandbox/hornet/controls/samples/jdbc/src/main/java/org/apache/beehive/controls/system/jdbc/JdbcControl.java Wed Jul 12 18:34:03 2006
@@ -0,0 +1,643 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Header:$
+ */
+
+package org.apache.beehive.controls.system.jdbc;
+
+import org.apache.beehive.controls.api.PropertySet;
+
+import javax.naming.NamingException;
+import javax.naming.Context;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Types;
+import java.sql.SQLData;
+import java.util.Calendar;
+import java.util.List;
+import java.util.Arrays;
+
+/**
+ * Simplifies access to a relational database from your Java code using SQL commands.
+ * The Jdbc Control handles the work of connecting to, sending queries to, and ResultSet mapping from
+ * the database. You don't need to know how to use JDBC in order to use the Jdbc Control, just basic SQL.
+ * <p/>
+ * To use a Jdbc Control create a .jcx file (java file with a .jcx extension) which extends this interface.
+ * Add annotations to the jcx to tell the Jdbc Control how to connect to your database instance (either
+ * ConnectionDataSource or ConnectionDriver), then add methods which include SQL annotations to access the database.
+ */
+public interface JdbcControl {
+
+
+ /**
+ * Returns a database connection to the server associated
+ * with the control. It is typically not necessary to call this method
+ * when using the control.
+ *
+ * @return A Connection a database.
+ */
+ public Connection getConnection() throws SQLException;
+
+ /**
+ * Sets the Calendar instance that should be used when setting and getting
+ * {@link java.sql.Date Date}, {@link java.sql.Time Time}, and
+ * {@link java.sql.Timestamp Timestamp} values.
+ *
+ * @see java.sql.ResultSet#getDate(int, Calendar) java.sql.ResultSet#getDate(int, Calendar)
+ * @see java.sql.ResultSet#getTime(int, Calendar) java.sql.ResultSet#getTime(int, Calendar)
+ * @see java.sql.ResultSet#getTimestamp(int, Calendar) java.sql.ResultSet#getTimestamp(int, Calendar)
+ * @see java.sql.PreparedStatement#setDate(int, java.sql.Date, Calendar) java.sql.PreparedStatement#setDate(int, Date, Calendar)
+ * @see java.sql.PreparedStatement#setTime(int, java.sql.Time, Calendar) java.sql.PreparedStatement#setTime(int, Time, Calendar)
+ * @see java.sql.PreparedStatement#setTimestamp(int, java.sql.Timestamp, Calendar) java.sql.PreparedStatement#setTimestamp(int, Timestamp, Calendar)
+ */
+ public void setDataSourceCalendar(Calendar cal);
+
+ /**
+ * Gets the Calendar instance used when setting and getting
+ * {@link java.sql.Date Date}, {@link java.sql.Time Time}, and
+ * {@link java.sql.Timestamp Timestamp} values. This is the Calendar
+ * set by the setDataSourceCalendar method.
+ *
+ * @return The Calendar instance.
+ */
+ public Calendar getDataSourceCalendar();
+
+
+
+
+// ********************************************************************************************************************
+// ********************************************************************************************************************
+// Class-level Database Connection Annotations and Supporting Constructs
+// ********************************************************************************************************************
+// ********************************************************************************************************************
+
+
+ /**
+ * Abstract base class for a user defined Jndi Context factory which can be used
+ * as a value for the jndiContextFactory member of the ConnectionDataSource
+ * annotation.
+ */
+ public static abstract class JndiContextFactory {
+
+ /**
+ * Get a JNDI InitialContext instance.
+ *
+ * @return InitialContext instance
+ * @throws NamingException if context could not be found.
+ */
+ public abstract Context getContext() throws NamingException;
+ }
+
+ /**
+ * Class-level annotation for making a DataSource available for use with the Jdbc Control. Either this annotation or
+ * the ConnectionDriver annotation must be set for a jcx which extends the JdbcControl interface.
+ */
+ @PropertySet(prefix = "ConnectionDataSource")
+ @Inherited
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target({ElementType.TYPE, ElementType.FIELD})
+ public @interface ConnectionDataSource {
+
+ /**
+ * The jndi name of the DataSource. This is a required element for this annotation.
+ */
+ String jndiName();
+
+ /**
+ * The name of a class which implements the IJndiContextFactory interface. This is an optional element of this annotation.
+ */
+ Class<? extends JndiContextFactory> jndiContextFactory() default DefaultJndiContextFactory.class;
+ }
+
+ /* ConnectionDataSource( jndiName ) accessors */
+ public String getConnectionDataSourcejndiName();
+ public void setConnectionDataSourcejndiName(String s);
+
+ /* ConnectionDataSource( jndiContextFactory ) accessors */
+ public Class<? extends JndiContextFactory> getConnectionDataSourcejndiContextFactory();
+ public void setConnectionDataSourcejndiContextFactory(Class<? extends JndiContextFactory> jcf);
+
+ /**
+ * Class-level annotation for making a ConnectionDriver available for use with the Jdbc Control. Either this
+ * annotation or the ConnectionDataSource annotation must be set for a jcx which extends the JdbcControl interface.
+ * See java.sql.DatabaseConnection for additional information about the elements of this annotation.
+ */
+ @PropertySet(prefix = "ConnectionDriver")
+ @Inherited
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target({ElementType.TYPE, ElementType.FIELD})
+ public @interface ConnectionDriver {
+
+ /**
+ * A String containing the fully qualified name of the database driver class. Required element.
+ */
+ String databaseDriverClass();
+
+ /**
+ * A String containing the database URL to connect to. Required element.
+ */
+ String databaseURL();
+
+ /**
+ * A String containing the user name to connect to the database as. Optional element.
+ */
+ String userName() default "";
+
+ /**
+ * A String containing the password associated with userName. Optional element.
+ */
+ String password() default "";
+
+ /**
+ * A String containing a comma seperated list of name/value pairs for the DatabaseConnection. Optional element.
+ */
+ String properties() default "";
+ }
+
+ /* ConnectionDriver( databaseDriverClass ) */
+ public String getConnectionDriverdatabaseDriverClass();
+ public void setConnectionDriverdatabaseDriverClass(String s);
+
+ /* ConnectionDriver( databaseUrl ) */
+ public String getConnectionDriverdatabaseUrl();
+ public void setConnectionDriverdatabaseUrl(String s);
+
+ /* ConnectionDriver( userName ) */
+ public String getConnectionDriveruserName();
+ public void setConnectionDriveruserName(String s);
+
+ /* ConnectionDriver( password ) */
+ public String getConnectionDriverpassword();
+ public void setConnectionDriverpassword(String s);
+
+ /* ConnectionDriver( properties ) */
+ public String getConnectionDriverproperties();
+ public void setConnectionDriverproperties(String s);
+
+
+ /**
+ * Class level annotation used to set options on the JDBC connnection.
+ */
+ @PropertySet(prefix = "ConnectionOptions")
+ @Inherited
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target({ElementType.TYPE, ElementType.FIELD})
+ public @interface ConnectionOptions {
+
+ /**
+ * If set to true, database connection will optimize for read only queries, writes still permitted.
+ * Optional, defaults to false.
+ */
+ boolean readOnly() default false;
+
+ /**
+ * Specifies ResultSet holdability for the connection. May be overridden at method level.
+ * Optional, defaults to jdbc driver's default setting.
+ */
+ HoldabilityType resultSetHoldability() default HoldabilityType.DRIVER_DEFAULT;
+
+ /**
+ * Specifies type mappings for SQL user defined types (UDTs). Any type mappings set here will be used
+ * by the underlying JDBC Connection for UDT type mappings. These mappings can be overridden by using
+ * the SQL annotations methodTypeMappers element. Optional element.
+ */
+ TypeMapper[] typeMappers() default {};
+ }
+
+ /* ConnectionOptions( readOnly ) */
+ public boolean getConnectionOptionsreadOnly();
+ public void setConnectionOptionsreadOnly(boolean b);
+
+ /* ConnectionOptions( resultSetHoldability ) */
+ public HoldabilityType getConnectionOptionsresultSetHoldability();
+ public void setConnectionOptionsresultSetHoldability(HoldabilityType ht);
+
+ /* ConnectionOptions( typeMappers ) */
+ public TypeMapper[] getConnectionOptionstypeMappers();
+ public void setConnectionOptionstypeMappers(TypeMapper[] tm);
+
+ /**
+ * Class / method level annotation for mapping SQL user defined types (UDTs) to and from java objects.
+ * The mapper class element must implement the java.sql.SQLData interface.
+ */
+ @PropertySet(prefix = "TypeMapper")
+ @Inherited
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target({ElementType.TYPE, ElementType.METHOD})
+ public @interface TypeMapper {
+ String UDTName();
+ Class<? extends SQLData> mapperClass();
+ }
+
+ /* TypeMapper( UDTName ) */
+ public String getTypeMapperUDTName();
+ public void setTypeMapperUDTName(String n);
+
+ /* TypeMapper( mapperClass ) */
+ public Class<? extends SQLData> getTypeMappermapperClass();
+ public void setTypeMappermapperClass(Class<? extends SQLData> c);
+
+
+// ********************************************************************************************************************
+// ********************************************************************************************************************
+// SQL Method-level Annotation and Supporting Constructs
+// ********************************************************************************************************************
+// ********************************************************************************************************************
+
+ /**
+ * This constant can be used as the value for the maxRows element of the SQL annotation.
+ * It indicates that all rows should be returned (i.e. no limit)
+ */
+ public final int MAXROWS_ALL = 0;
+
+ /**
+ * The default fetch size for result sets, indicates the database should determine the fetch size.
+ */
+ public final int DEFAULT_FETCH_SIZE = 0;
+
+ /**
+ * Default value for the iteratorElementType element of the
+ * SQL annotation. It signals that no type has been defined for the method
+ * (common if the method return type isn't itself an iterator)
+ */
+ public interface UndefinedIteratorType {
+ }
+
+ /**
+ * Default value for the resultSetMapper element of the
+ * SQL annotation. It signals that no type has been defined for the method.
+ */
+ public interface UndefinedResultSetMapper {
+ }
+
+ /**
+ * Enumeration of supported types of scrolling ResultSets
+ */
+ public enum ScrollType {
+ DRIVER_DEFAULT (-1, -1),
+ FORWARD_ONLY (ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY),
+ SCROLL_INSENSITIVE (ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY),
+ SCROLL_SENSITIVE (ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY),
+ FORWARD_ONLY_UPDATABLE (ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE),
+ SCROLL_INSENSITIVE_UPDATABLE (ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE),
+ SCROLL_SENSITIVE_UPDATABLE (ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
+
+ private final int _type;
+ private final int _concurrencyType;
+
+ ScrollType(int scrollType, int concurrencyType) {
+ _type = scrollType;
+ _concurrencyType = concurrencyType;
+ }
+
+ public int getType() { return _type; }
+
+ public int getConcurrencyType() { return _concurrencyType; }
+
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ if (_type == ResultSet.TYPE_FORWARD_ONLY) {
+ sb.append("Foward Only, ");
+ } else if (_type == ResultSet.TYPE_SCROLL_INSENSITIVE) {
+ sb.append("Scroll Insensitive, ");
+ } else if (_type == ResultSet.TYPE_SCROLL_SENSITIVE) {
+ sb.append("Scroll Sensitive, ");
+ } else {
+ sb.append("Jdbc Driver Default Direction");
+ }
+
+ if (_concurrencyType == ResultSet.CONCUR_READ_ONLY) {
+ sb.append("Read Only");
+ } else if (_concurrencyType == ResultSet.CONCUR_UPDATABLE) {
+ sb.append("Updatable");
+ } else {
+ sb.append("Jdbc Driver Default");
+ }
+ return sb.toString();
+ }
+ }
+
+ /**
+ * Enumeration of supported fetch directions.
+ */
+ public enum FetchDirection {
+ FORWARD (ResultSet.FETCH_FORWARD),
+ REVERSE (ResultSet.FETCH_REVERSE),
+ UNKNOWN (ResultSet.FETCH_UNKNOWN);
+
+ private final int _direction;
+
+ FetchDirection(int direction) {
+ _direction = direction;
+ }
+
+ public int getDirection() { return _direction; }
+ }
+
+ /**
+ * Enumeration of supported fetch directions.
+ */
+ public enum HoldabilityType {
+ DRIVER_DEFAULT (0),
+ HOLD_CURSORS (ResultSet.HOLD_CURSORS_OVER_COMMIT),
+ CLOSE_CURSORS (ResultSet.CLOSE_CURSORS_AT_COMMIT);
+
+ private final int _holdability;
+
+ HoldabilityType(int holdability) {
+ _holdability = holdability;
+ }
+
+ public int getHoldability() { return _holdability; }
+
+ public String toString() {
+ if (_holdability == ResultSet.HOLD_CURSORS_OVER_COMMIT) {
+ return "HOLD_CURSORS_OVER_COMMIT";
+ } else if (_holdability == ResultSet.CLOSE_CURSORS_AT_COMMIT) {
+ return "CLOSE_CURSORS_AT_COMMIT";
+ } else {
+ return "Default driver holdability";
+ }
+ }
+ }
+
+ /**
+ * Method-level annotation for methods in a jcx which wish to access a database instance.
+ */
+ @PropertySet(prefix = "SQL")
+ @Inherited
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target({ElementType.METHOD})
+ public @interface SQL {
+
+ /**
+ * The SQL statement to send to the database. Required annotation element.
+ */
+ String statement();
+
+
+ /**
+ * Maximum array length.
+ * This element has no effect on the call unless the method return type is an array.
+ * Optional element.
+ */
+ int arrayMaxLength() default 1024;
+
+
+ /**
+ * Max number of ResultSet rows to return.
+ * If used with arrayMaxLength the smaller value is used.
+ * Optional element, default value is no limit on number of rows returned.
+ */
+ int maxRows() default MAXROWS_ALL;
+
+
+ /**
+ * Execute the SQL statement as a batch update.
+ * Methods which have this element set to true must return an array of ints.
+ * Optional element, defaults to false.
+ */
+ boolean batchUpdate() default false;
+
+
+ /**
+ * Specify the fetch size for the ResultSet. Optional element, defaults to 0.
+ */
+ int fetchSize() default DEFAULT_FETCH_SIZE;
+
+
+ /**
+ * Specify the fetch direction for the ResultSEt. Optional element, defaults to FORWARD.
+ */
+ FetchDirection fetchDirection() default FetchDirection.FORWARD;
+
+
+ /**
+ * Return the generated key values generated by the SQL statement. Optional element, defaults to false.
+ */
+ boolean getGeneratedKeys() default false;
+
+
+ /**
+ * Specify generated key columns by column names to return when the getGeneratedKeys element is true.
+ * May only be set if getGeneratedKeys is set to true, otherwise a compile time error is generated.
+ * Optional element.
+ */
+ String[] generatedKeyColumnNames() default {};
+
+
+ /**
+ * Specify generated key columns by column number to return when the getGeneratedKeys element is true.
+ * May only be set if getGeneratedKeys is set to true, otherwise a compile time error is generated
+ * Optional element.
+ */
+ int[] generatedKeyColumnIndexes() default {};
+
+
+ /**
+ * Specify the holdability type for the annotated method. Overrides the holability annotation element
+ * of the ConnectionOptions annotation. The holdability type will be in effect for the duration of this
+ * method call. Optional, defaults to DRIVER_DEFAULT.
+ */
+ HoldabilityType resultSetHoldabilityOverride() default HoldabilityType.DRIVER_DEFAULT;
+
+
+ /**
+ * Specifies type mappings for SQL user defined types (UDTs). Any type mappings set here will be used
+ * by the underlying JDBC Connection for UDT type mappings. These type mappings will REPLACE any set on
+ * the JDBC connection for the duration of the method call. Optional element.
+ */
+ TypeMapper[] typeMappersOverride() default {};
+
+
+ /**
+ * Specify the type of element to be interated over when the method's return type is java.util.Iterator.
+ * Optional element.
+ */
+ Class iteratorElementType() default UndefinedIteratorType.class;
+
+
+ /**
+ * Specify a custom result set mapper for the ResultSet generated by the SQL statement.
+ * ResultSet mappers must extend the ResultSetMapper abstract base class. If a value is specified
+ * it will be used to map the ResultSet of the query to the return type of the method.
+ * See org.apache.beehive.controls.system.jdbc.ResultSetMapper for additional information.
+ * Optional element.
+ */
+ Class resultSetMapper() default UndefinedResultSetMapper.class;
+
+
+ /**
+ * Specify that the ResultSet returned by the method is scrollable. Valid only for methods which
+ * return a ResultSet, otherwise a compile-time error will occur. Valid element values
+ * are defined by the ScrollType enumeration.
+ * Optional element, defaults to JDBC driver's default setting.
+ */
+ ScrollType scrollableResultSet() default ScrollType.DRIVER_DEFAULT;
+ } // SQL annotation declaration
+
+
+// ********************************************************************************************************************
+// ********************************************************************************************************************
+// Inner Classes
+// ********************************************************************************************************************
+// ********************************************************************************************************************
+
+ /**
+ * Nested class used for specifing parameters for a callable statement. If a method in a control extension takes an array of
+ * SQLParameter, the JdbcControl treats the SQL as a CallableStatement and inserts values into the statement from
+ * the SQLParameter array. After the CallableStatement executes, results are mapped into OUT type parameters found
+ * int the SQLParameter array.
+ * NOTE: To invoke a callable statement which does not take any arguments, an SQLParameter array of size zero must
+ * be passed to the JDBCControl method.
+ */
+ public static class SQLParameter {
+ /**
+ * IN direction constant.
+ */
+ public static final int IN = 1;
+ /**
+ * OUT direction constant.
+ */
+ public static final int OUT = 2;
+ /**
+ * IN and OUT directions constant.
+ */
+ public static final int INOUT = IN | OUT;
+
+ /**
+ * Parameter value. For parameters of type OUT this value should be set to null.
+ */
+ public Object value = null;
+
+ /**
+ * Parameter SQL data type. See java.sql.Types.
+ */
+ public int type = Types.NULL;
+
+ /**
+ * Parameter direction.
+ */
+ public int dir = IN;
+
+ /**
+ * Create a new SQLParameter with the specified value.
+ *
+ * @param value The parameter value.
+ */
+ public SQLParameter(Object value) {
+ this.value = value;
+ }
+
+ /**
+ * Create a new SQLParameter with the specified value and SQL data type.
+ *
+ * @param value The parameter value.
+ * @param type SQL data type.
+ */
+ public SQLParameter(Object value, int type) {
+ this(value);
+ this.type = type;
+ }
+
+ /**
+ * Create a new SQLParameter with the specified value, SQL data type and direction.
+ *
+ * @param value The parameter value.
+ * @param type SQL data type.
+ * @param dir IN / OUT or INOUT
+ */
+ public SQLParameter(Object value, int type, int dir) {
+ this(value, type);
+ this.dir = dir;
+ }
+
+ /**
+ * Clone this parameter.
+ *
+ * @return A copy of this parameter.
+ */
+ public Object clone() {
+ return new SQLParameter(value, type, dir);
+ }
+ }
+
+ /**
+ * A ComplexSqlFragment can be used as a return value from a parameter reflection operation for
+ * return values which contain BOTH SQL text and parameters. For Example, the text portion
+ * could be something like 'where NAME = ?' and the parameter value is 'Fred'.
+ */
+ public static class ComplexSqlFragment {
+
+ protected CharSequence sql;
+ protected List<SQLParameter> parameters;
+
+ /**
+ * Create a new SQLFragment.
+ */
+ public ComplexSqlFragment() {
+ sql = null;
+ parameters = null;
+ }
+
+ /**
+ * Create a new SQLFragment with the specified SQL and parameter list.
+ *
+ * @param sql SQL contents of the fragment.
+ * @param parameters Substitution parameters.
+ */
+ public ComplexSqlFragment(String sql, SQLParameter[] parameters) {
+ this.sql = sql;
+ if (null != parameters)
+ this.parameters = Arrays.asList(parameters);
+ }
+
+ /**
+ * Get the SQL of this fragment.
+ *
+ * @return String.
+ */
+ public String getSQL() {
+ return sql.toString();
+ }
+
+ /**
+ * Get the parameters contained within this fragment.
+ * Returns a zero-based array.
+ *
+ * @return SQLParameter array.
+ */
+ public SQLParameter[] getParameters() {
+ if (null == parameters)
+ return new SQLParameter[0];
+ return parameters.toArray(new SQLParameter[parameters.size()]);
+ }
+
+ /**
+ * Get the SQL string contained within this fragment.
+ * @return String.
+ */
+ public String toString() {
+ return sql.toString();
+ }
+ }
+}
Propchange: beehive/sandbox/hornet/controls/samples/jdbc/src/main/java/org/apache/beehive/controls/system/jdbc/JdbcControl.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: beehive/sandbox/hornet/controls/samples/jdbc/src/main/java/org/apache/beehive/controls/system/jdbc/JdbcControlImpl.java
URL: http://svn.apache.org/viewvc/beehive/sandbox/hornet/controls/samples/jdbc/src/main/java/org/apache/beehive/controls/system/jdbc/JdbcControlImpl.java?rev=421473&view=auto
==============================================================================
--- beehive/sandbox/hornet/controls/samples/jdbc/src/main/java/org/apache/beehive/controls/system/jdbc/JdbcControlImpl.java (added)
+++ beehive/sandbox/hornet/controls/samples/jdbc/src/main/java/org/apache/beehive/controls/system/jdbc/JdbcControlImpl.java Wed Jul 12 18:34:03 2006
@@ -0,0 +1,544 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Header:$
+ */
+package org.apache.beehive.controls.system.jdbc;
+
+import java.lang.reflect.Method;
+import java.sql.*;
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Vector;
+import javax.naming.NamingException;
+import javax.naming.Context;
+import javax.sql.DataSource;
+
+import org.apache.beehive.controls.api.ControlException;
+import org.apache.beehive.controls.api.Extensible;
+import org.apache.beehive.controls.api.PropertySetReader;
+import org.apache.beehive.controls.system.jdbc.parser.SqlParser;
+import org.apache.beehive.controls.system.jdbc.parser.SqlStatement;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * The implementation class for the database controller.
+ */
+public class JdbcControlImpl implements JdbcControl, Extensible, java.io.Serializable {
+
+ protected transient Connection _connection;
+ protected transient DataSource _dataSource;
+
+ private Calendar _cal;
+ private transient Vector<PreparedStatement> _resources;
+
+ private static final String EMPTY_STRING = "";
+ private static final Log LOGGER = LogFactory.getLog(JdbcControlImpl.class);
+ private static final ResultSetMapper DEFAULT_MAPPER = new DefaultObjectResultSetMapper();
+ private static final SqlParser _sqlParser = new SqlParser();
+
+ protected static final HashMap<Class, ResultSetMapper> _resultMappers = new HashMap<Class, ResultSetMapper>();
+ protected static Class<?> _xmlObjectClass;
+
+ //
+ // initialize the result mapper table
+ //
+ static {
+ _resultMappers.put(ResultSet.class, new DefaultResultSetMapper());
+ _resultMappers.put(Iterator.class, new DefaultIteratorResultSetMapper());
+
+ try {
+ _xmlObjectClass = Class.forName("org.apache.xmlbeans.XmlObject");
+ _resultMappers.put(_xmlObjectClass, new DefaultXmlObjectResultSetMapper());
+ } catch (ClassNotFoundException e) {
+ // noop: OK if not found, just can't support mapping to an XmlObject
+ }
+ }
+
+ /**
+ * Constructor
+ */
+ public JdbcControlImpl() { }
+
+ /**
+ * Invoked by the controls runtime when a new instance of this class is aquired by the runtime
+ */
+ public void onAcquire() {
+
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Enter: onAquire()");
+ }
+
+ }
+
+ /**
+ * Invoked by the controls runtime when an instance of this class is released by the runtime
+ */
+ public void onRelease() {
+
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Enter: onRelease()");
+ }
+
+ for (PreparedStatement ps : getResources()) {
+ try {
+ ps.close();
+ } catch (SQLException sqe) {
+ }
+ }
+ getResources().clear();
+
+ if (_connection != null) {
+ try {
+ _connection.close();
+ } catch (SQLException e) {
+ throw new ControlException("SQL Exception while attempting to close database connection.", e);
+ }
+ }
+
+ _connection = null;
+ }
+
+ /**
+ * Returns a database connection to the server associated with the control.
+ * The connection type is specified by a ConnectionDataSource or ConnectionDriver annotation on the control class
+ * which extends this control.
+ * <p/>
+ * It is typically not necessary to call this method when using the control.
+ */
+ public Connection getConnection() throws SQLException {
+
+ if (_connection == null) {
+
+ if ( getConnectionDataSourcejndiName() != null) {
+ _connection = getConnectionFromDataSource( getConnectionDataSourcejndiName(),
+ getConnectionDataSourcejndiContextFactory());
+
+ } else if ( getConnectionDriverdatabaseDriverClass() != null) {
+ _connection = getConnectionFromDriverManager( getConnectionDriverdatabaseDriverClass(),
+ getConnectionDriverdatabaseUrl(),
+ getConnectionDriveruserName(),
+ getConnectionDriverpassword(),
+ getConnectionDriverproperties());
+ } else {
+ throw new ControlException("no @\'" + ConnectionDataSource.class.getName()
+ + "\' or \'" + ConnectionDriver.class.getName() + "\' property found.");
+ }
+
+ //
+ // set any specifed connection options
+ //
+ if (_connection.isReadOnly() != getConnectionOptionsreadOnly()) {
+ _connection.setReadOnly( getConnectionOptionsreadOnly());
+ }
+
+ DatabaseMetaData dbMetadata = _connection.getMetaData();
+
+ final HoldabilityType holdability = getConnectionOptionsresultSetHoldability();
+ if (holdability != HoldabilityType.DRIVER_DEFAULT) {
+ if (dbMetadata.supportsResultSetHoldability(holdability.getHoldability())) {
+ _connection.setHoldability(holdability.getHoldability());
+ } else {
+ throw new ControlException("Database does not support ResultSet holdability type: "
+ + holdability.toString());
+ }
+ }
+
+ if (getConnectionOptionstypeMappers() != null)
+ setTypeMappers(getConnectionOptionstypeMappers());
+ }
+
+ return _connection;
+ }
+
+
+ /**
+ * Called by the Controls runtime to handle calls to methods of an extensible control.
+ *
+ * @param method The extended operation that was called.
+ * @param args Parameters of the operation.
+ * @return The value that should be returned by the operation.
+ * @throws Throwable any exception declared on the extended operation may be
+ * thrown. If a checked exception is thrown from the implementation that is not declared
+ * on the original interface, it will be wrapped in a ControlException.
+ */
+ public Object invoke(Method method, Object[] args) throws Throwable {
+
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Enter: invoke()");
+ }
+ assert _connection.isClosed() == false : "invoke(): JDBC Connection has been closed!!!!";
+ return execPreparedStatement(method, args);
+ }
+
+ /**
+ * Sets the {@link Calendar} used when working with time/date types
+ */
+ public void setDataSourceCalendar(Calendar cal) {
+ _cal = (Calendar) cal.clone();
+ }
+
+ /**
+ * Returns the {@link Calendar} used when working with time/date types.
+ *
+ * @return the {@link Calendar} to use with this {@link DataSource}
+ */
+ public Calendar getDataSourceCalendar() {
+ return _cal;
+ }
+
+// /////////////////////////////////////////// Protected Methods ////////////////////////////////////////////
+
+
+ /**
+ * Create and exec a {@link PreparedStatement}
+ *
+ * @param method the method to invoke
+ * @param args the method's arguments
+ * @return the return value from the {@link PreparedStatement}
+ * @throws Throwable any exception that occurs; the caller should handle these appropriately
+ */
+ protected Object execPreparedStatement(Method method, Object[] args)
+ throws Throwable {
+
+ final SQL methodSQL = (SQL) PropertySetReader.getMethodPropertySet(method, SQL.class);
+ if (methodSQL == null || methodSQL.statement() == null) {
+ throw new ControlException("Method " + method.getName() + " is missing @SQL annotation");
+ }
+
+ setTypeMappers(methodSQL.typeMappersOverride());
+
+ //
+ // build the statement and execute it
+ //
+
+ PreparedStatement ps = null;
+ try {
+ Class returnType = method.getReturnType();
+
+ SqlStatement sqlStatement = _sqlParser.parse(methodSQL.statement());
+ ps = sqlStatement.createPreparedStatement(_connection, _cal, method, args);
+
+ if (LOGGER.isInfoEnabled()) {
+ LOGGER.info("PreparedStatement: "
+ + sqlStatement.createPreparedStatementString(_connection, method, args));
+ }
+
+ //
+ // special processing for batch updates
+ //
+ if (sqlStatement.isBatchUpdate()) {
+ return ps.executeBatch();
+ }
+
+ //
+ // execute the statement
+ //
+ boolean hasResults = ps.execute();
+
+
+ //
+ // callable statement processing
+ //
+ if (sqlStatement.isCallableStatement()) {
+ SQLParameter[] params = (SQLParameter[]) args[0];
+ for (int i = 0; i < params.length; i++) {
+ if (params[i].dir != SQLParameter.IN) {
+ params[i].value = ((CallableStatement) ps).getObject(i + 1);
+ }
+ }
+ return null;
+ }
+
+
+ //
+ // process returned data
+ //
+ ResultSet rs = null;
+ int updateCount = ps.getUpdateCount();
+
+ if (hasResults) {
+ rs = ps.getResultSet();
+ }
+
+ if (sqlStatement.getsGeneratedKeys()) {
+ rs = ps.getGeneratedKeys();
+ hasResults = true;
+ }
+
+ if (!hasResults && updateCount > -1) {
+ boolean moreResults = ps.getMoreResults();
+ int tempUpdateCount = ps.getUpdateCount();
+
+ while ((moreResults && rs == null) || tempUpdateCount > -1) {
+ if (moreResults) {
+ rs = ps.getResultSet();
+ hasResults = true;
+ moreResults = false;
+ tempUpdateCount = -1;
+ } else {
+ moreResults = ps.getMoreResults();
+ tempUpdateCount = ps.getUpdateCount();
+ }
+ }
+ }
+
+ Object returnObject = null;
+ if (hasResults) {
+
+ //
+ // if a result set mapper was specified in the methods annotation, use it
+ // otherwise find the mapper for the return type in the hashmap
+ //
+ final Class resultSetMapperClass = methodSQL.resultSetMapper();
+ final ResultSetMapper rsm;
+ if (!UndefinedResultSetMapper.class.isAssignableFrom(resultSetMapperClass)) {
+ if (ResultSetMapper.class.isAssignableFrom(resultSetMapperClass)) {
+ rsm = (ResultSetMapper) resultSetMapperClass.newInstance();
+ } else {
+ throw new ControlException("Result set mappers must be subclasses of ResultSetMapper.class!");
+ }
+ } else {
+ if (_resultMappers.containsKey(returnType)) {
+ rsm = _resultMappers.get(returnType);
+ } else {
+ if (_xmlObjectClass != null && _xmlObjectClass.isAssignableFrom(returnType)) {
+ rsm = _resultMappers.get(_xmlObjectClass);
+ } else {
+ rsm = DEFAULT_MAPPER;
+ }
+ }
+ }
+
+ returnObject = rsm.mapToResultType(method, rs, _cal);
+ if (rsm.canCloseResultSet() == false) {
+ getResources().add(ps);
+ }
+
+ //
+ // empty ResultSet
+ //
+ } else {
+ if (returnType.equals(Void.TYPE)) {
+ returnObject = null;
+ } else if (returnType.equals(Integer.TYPE)) {
+ returnObject = new Integer(updateCount);
+ } else if (!sqlStatement.isCallableStatement()) {
+ throw new ControlException("Method " + method.getName() + "is DML but does not return void or int");
+ }
+ }
+ return returnObject;
+
+ } finally {
+ // Keep statements open that have in-use result sets
+ if (ps != null && !getResources().contains(ps)) {
+ ps.close();
+ }
+ }
+ }
+
+// /////////////////////////////////////////// Private Methods ////////////////////////////////////////////
+
+ /**
+ * Get a connection from a DataSource.
+ *
+ * @param jndiName Specifed in the subclasse's ConnectionDataSource annotation
+ * @param jndiFactory Specified in the subclasse's ConnectionDataSource Annotation.
+ * @return null if a connection cannot be established
+ * @throws SQLException
+ */
+ private Connection getConnectionFromDataSource(String jndiName,
+ Class<? extends JdbcControl.JndiContextFactory> jndiFactory)
+ throws SQLException
+ {
+
+ Connection con = null;
+ try {
+ JndiContextFactory jf = (JndiContextFactory) jndiFactory.newInstance();
+ Context jndiContext = jf.getContext();
+ _dataSource = (DataSource) jndiContext.lookup(jndiName);
+ con = _dataSource.getConnection();
+ } catch (IllegalAccessException iae) {
+ throw new ControlException("IllegalAccessException:", iae);
+ } catch (InstantiationException ie) {
+ throw new ControlException("InstantiationException:", ie);
+ } catch (NamingException ne) {
+ throw new ControlException("NamingException:", ne);
+ }
+ return con;
+ }
+
+ /**
+ * Get a JDBC connection from the DriverManager.
+ *
+ * @param dbDriverClassName Specified in the subclasse's ConnectionDriver annotation.
+ * @param dbUrlStr Specified in the subclasse's ConnectionDriver annotation.
+ * @param userName Specified in the subclasse's ConnectionDriver annotation.
+ * @param password Specified in the subclasse's ConnectionDriver annotation.
+ * @return null if a connection cannot be established.
+ * @throws SQLException
+ */
+ private Connection getConnectionFromDriverManager(String dbDriverClassName, String dbUrlStr,
+ String userName, String password, String propertiesString)
+ throws SQLException
+ {
+
+ Connection con = null;
+ try {
+ Class.forName(dbDriverClassName);
+ if (!EMPTY_STRING.equals(userName)) {
+ con = DriverManager.getConnection(dbUrlStr, userName, password);
+ } else if (!EMPTY_STRING.equals(propertiesString)) {
+ Properties props = parseProperties(propertiesString);
+ if (props == null) {
+ throw new ControlException("Invalid properties annotation value: " + propertiesString);
+ }
+ con = DriverManager.getConnection(dbUrlStr, props);
+ } else {
+ con = DriverManager.getConnection(dbUrlStr);
+ }
+ } catch (ClassNotFoundException e) {
+ throw new ControlException("Database driver class not found!", e);
+ }
+ return con;
+ }
+
+ /**
+ * Get the Vector of Statements which we need to keep open.
+ * @return Vector of PreparedStatement
+ */
+ private Vector<PreparedStatement> getResources() {
+ if (_resources == null) {
+ _resources = new Vector<PreparedStatement>();
+ }
+ return _resources;
+ }
+
+ /**
+ * Parse the propertiesString into a Properties object. The string must have the format of:
+ * propertyName=propertyValue;propertyName=propertyValue;...
+ *
+ * @param propertiesString
+ * @return A Properties instance or null if parse fails
+ */
+ private Properties parseProperties(String propertiesString) {
+ Properties properties = null;
+ String[] propPairs = propertiesString.split(";");
+ if (propPairs.length > 0) {
+ properties = new Properties();
+ for (String propPair : propPairs) {
+ int eq = propPair.indexOf('=');
+ assert eq > -1 : "Invalid properties syntax: " + propertiesString;
+ properties.put(propPair.substring(0, eq), propPair.substring(eq + 1, propPair.length()));
+ }
+ }
+ return properties;
+ }
+
+ /**
+ * Set any custom type mappers specifed in the annotation for the connection. Used for mapping SQL UDTs to
+ * java classes.
+ *
+ * @param typeMappers An array of TypeMapper.
+ */
+ private void setTypeMappers(TypeMapper[] typeMappers) throws SQLException {
+
+ if (typeMappers.length > 0) {
+ Map<String, Class<?>> mappers = _connection.getTypeMap();
+ for (TypeMapper t : typeMappers) {
+ mappers.put(t.UDTName(), t.mapperClass());
+ }
+ _connection.setTypeMap(mappers);
+ }
+ }
+
+// //////////////////////////////////// Class / Instance Property Accessors /////////////////////////////////////////
+
+ /* ConnectionDataSource( jndiName ) accessors */
+ public String getConnectionDataSourcejndiName() { return _connectionDataSourceJndiName; }
+ public void setConnectionDataSourcejndiName(String s) { _connectionDataSourceJndiName = s; }
+
+ private String _connectionDataSourceJndiName;
+
+ /* ConnectionDataSource( jndiContextFactory ) accessors */
+ public Class<? extends JndiContextFactory> getConnectionDataSourcejndiContextFactory() { return _connectionDataSourceJndiContextFactory; }
+ public void setConnectionDataSourcejndiContextFactory(Class<? extends JndiContextFactory> jcf) { _connectionDataSourceJndiContextFactory = jcf; }
+
+ public Class<? extends JndiContextFactory> _connectionDataSourceJndiContextFactory;
+
+ /* ConnectionDriver( databaseDriverClass ) */
+ public String getConnectionDriverdatabaseDriverClass() { return _connectionDriverDatabaseDriverClass; }
+ public void setConnectionDriverdatabaseDriverClass(String s) { _connectionDriverDatabaseDriverClass = s; }
+
+ private String _connectionDriverDatabaseDriverClass;
+
+ /* ConnectionDriver( databaseUrl ) */
+ public String getConnectionDriverdatabaseUrl() { return _connectionDriverDatabaseUrl; }
+ public void setConnectionDriverdatabaseUrl(String s) { _connectionDriverDatabaseUrl = s; }
+
+ private String _connectionDriverDatabaseUrl;
+
+ /* ConnectionDriver( userName ) */
+ public String getConnectionDriveruserName() { return _connectionDriverUserName; }
+ public void setConnectionDriveruserName(String s) { _connectionDriverUserName = s; }
+
+ private String _connectionDriverUserName;
+
+ /* ConnectionDriver( password ) */
+ public String getConnectionDriverpassword() { return _connectionDriverPassword; }
+ public void setConnectionDriverpassword(String s) { _connectionDriverPassword = s; }
+
+ private String _connectionDriverPassword;
+
+ /* ConnectionDriver( properties ) */
+ public String getConnectionDriverproperties() { return _connectionDriverProperties; }
+ public void setConnectionDriverproperties(String s) { _connectionDriverProperties = s; }
+
+ private String _connectionDriverProperties;
+
+ /* ConnectionOptions( readOnly ) */
+ public boolean getConnectionOptionsreadOnly() { return _connectionOptionsReadOnly; }
+ public void setConnectionOptionsreadOnly(boolean b) { _connectionOptionsReadOnly = b; }
+
+ private boolean _connectionOptionsReadOnly;
+
+ /* ConnectionOptions( resultSetHoldability ) */
+ public HoldabilityType getConnectionOptionsresultSetHoldability() { return _connectionOptionsResultSetHoldability; }
+ public void setConnectionOptionsresultSetHoldability(HoldabilityType ht) { _connectionOptionsResultSetHoldability = ht; }
+
+ private HoldabilityType _connectionOptionsResultSetHoldability;
+
+ /* ConnectionOptions( typeMappers ) */
+ public TypeMapper[] getConnectionOptionstypeMappers() { return _connectionOptionsTypeMappers; }
+ public void setConnectionOptionstypeMappers(TypeMapper[] tm) { _connectionOptionsTypeMappers = tm; }
+
+ private TypeMapper[] _connectionOptionsTypeMappers;
+
+ /* TypeMapper( UDTName ) */
+ public String getTypeMapperUDTName() { return _typeMapperUDTName; }
+ public void setTypeMapperUDTName(String n) { _typeMapperUDTName = n; }
+
+ private String _typeMapperUDTName;
+
+ /* TypeMapper( mapperClass ) */
+ public Class<? extends SQLData> getTypeMappermapperClass() { return _typeMappermapperClass; }
+ public void setTypeMappermapperClass(Class<? extends SQLData> c) { _typeMappermapperClass = c; }
+
+ private Class<? extends SQLData> _typeMappermapperClass;
+}
Propchange: beehive/sandbox/hornet/controls/samples/jdbc/src/main/java/org/apache/beehive/controls/system/jdbc/JdbcControlImpl.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: beehive/sandbox/hornet/controls/samples/jdbc/src/main/java/org/apache/beehive/controls/system/jdbc/ResultSetHashMap.java
URL: http://svn.apache.org/viewvc/beehive/sandbox/hornet/controls/samples/jdbc/src/main/java/org/apache/beehive/controls/system/jdbc/ResultSetHashMap.java?rev=421473&view=auto
==============================================================================
--- beehive/sandbox/hornet/controls/samples/jdbc/src/main/java/org/apache/beehive/controls/system/jdbc/ResultSetHashMap.java (added)
+++ beehive/sandbox/hornet/controls/samples/jdbc/src/main/java/org/apache/beehive/controls/system/jdbc/ResultSetHashMap.java Wed Jul 12 18:34:03 2006
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Header:$
+ */
+package org.apache.beehive.controls.system.jdbc;
+
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.util.HashMap;
+
+/**
+ * The ResultSetHashMap class extends a standard HashMap and populates it with data derived from a JDBC ResultSet.
+ * <p/>
+ * Note: the keys are treated case-insensitively, and therefore requests made on the map are
+ * case-insensitive. Any direct access to the keys will yield uppercase keys.
+ * <p/>
+ * Note: only the row associated with the current cursor position is used.
+ */
+public class ResultSetHashMap extends HashMap<String, Object> {
+
+ /**
+ * Default constructor.
+ */
+ ResultSetHashMap() {
+ super();
+ }
+
+ /**
+ * Constructor that initializes the map to a specific size.
+ * @param size the size
+ */
+ ResultSetHashMap(int size) {
+ super(size);
+ }
+
+ /**
+ * This constructor is optimized for being called in a loop. It also canonicalizes the
+ * column names into upper case so that values in a map can be looked up using either
+ * upper, lower, or mixed case strings.
+ *
+ * @param rs the ResultSet to map
+ * @param keys an array of key objects to store in the map
+ * @throws SQLException if an error occurs while reading from the ResultSet
+ */
+ ResultSetHashMap(ResultSet rs, String[] keys) throws SQLException {
+ super(keys.length);
+
+ assert keys.length == rs.getMetaData().getColumnCount() + 1;
+
+ for (int i = 1; i < keys.length; i++) {
+ assert keys[i].equals(keys[i].toUpperCase());
+ put(keys[i], rs.getObject(i));
+ }
+ }
+
+ ResultSetHashMap(ResultSet rs) throws SQLException {
+ super();
+ ResultSetMetaData md = rs.getMetaData();
+ for (int i = 1; i <= md.getColumnCount(); i++) {
+ put(md.getColumnName(i), rs.getObject(i));
+ }
+ }
+
+ public boolean containsKey(Object key) {
+ return super.containsKey(canonicalizeKey(key));
+ }
+
+ public Object get(Object key) {
+ return super.get(canonicalizeKey(key));
+ }
+
+ public Object put(String key, Object value) {
+ return super.put(canonicalizeKey(key), value);
+ }
+
+ public Object remove(Object key) {
+ return super.remove(canonicalizeKey(key));
+ }
+
+ private String canonicalizeKey(Object object) {
+ return object == null ? null : object.toString().toUpperCase();
+ }
+}
+
Propchange: beehive/sandbox/hornet/controls/samples/jdbc/src/main/java/org/apache/beehive/controls/system/jdbc/ResultSetHashMap.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: beehive/sandbox/hornet/controls/samples/jdbc/src/main/java/org/apache/beehive/controls/system/jdbc/ResultSetIterator.java
URL: http://svn.apache.org/viewvc/beehive/sandbox/hornet/controls/samples/jdbc/src/main/java/org/apache/beehive/controls/system/jdbc/ResultSetIterator.java?rev=421473&view=auto
==============================================================================
--- beehive/sandbox/hornet/controls/samples/jdbc/src/main/java/org/apache/beehive/controls/system/jdbc/ResultSetIterator.java (added)
+++ beehive/sandbox/hornet/controls/samples/jdbc/src/main/java/org/apache/beehive/controls/system/jdbc/ResultSetIterator.java Wed Jul 12 18:34:03 2006
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Header:$
+ */
+package org.apache.beehive.controls.system.jdbc;
+
+import org.apache.beehive.controls.api.ControlException;
+import org.apache.beehive.controls.api.PropertySetReader;
+
+import java.lang.reflect.Method;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Calendar;
+import java.util.NoSuchElementException;
+
+/**
+ * Used by DefaultIteratorResultSetMapper for mapping a ResultSet to an Iterator type.
+ */
+public class ResultSetIterator implements java.util.Iterator {
+
+ private final Class _returnClass;
+ private final ResultSet _rs;
+ private final RowMapper _rowMapper;
+
+ private boolean _primed = false;
+
+ /**
+ * Create a new ResultSetIterator.
+ * @param method The annotated method.
+ * @param rs The ResultSet to map.
+ * @param cal A Calendar instance for mapping date/time values.
+ */
+ ResultSetIterator(Method method, ResultSet rs, Calendar cal) {
+ _rs = rs;
+
+ JdbcControl.SQL methodSQL = PropertySetReader.getMethodPropertySet(method, JdbcControl.SQL.class);
+ _returnClass = methodSQL.iteratorElementType();
+
+ if (_returnClass == null) {
+ throw new ControlException("Invalid return class declared for Iterator:" + _returnClass.getName());
+ }
+
+ _rowMapper = RowMapperFactory.getRowMapper(rs, _returnClass, cal);
+ }
+
+ /**
+ * Does this iterater have more elements?
+ * @return true if there is another element
+ */
+ public boolean hasNext() {
+ if (_primed) {
+ return true;
+ }
+
+ try {
+ _primed = _rs.next();
+ } catch (SQLException sqle) {
+ return false;
+ }
+ return _primed;
+ }
+
+ /**
+ * Get the next element in the iteration.
+ * @return The next element in the iteration.
+ */
+ public Object next() {
+ try {
+ if (!_primed) {
+ _primed = _rs.next();
+ if (!_primed) {
+ throw new NoSuchElementException();
+ }
+ }
+ // reset upon consumption
+ _primed = false;
+ return _rowMapper.mapRowToReturnType();
+ } catch (SQLException e) {
+ // Since Iterator interface is locked, all we can do
+ // is put the real exception inside an expected one.
+ NoSuchElementException xNoSuch = new NoSuchElementException("ResultSet exception: " + e);
+ xNoSuch.initCause(e);
+ throw xNoSuch;
+ }
+ }
+
+ /**
+ * Remove is currently not supported.
+ */
+ public void remove() {
+ throw new UnsupportedOperationException("remove not supported");
+ }
+}
+
Propchange: beehive/sandbox/hornet/controls/samples/jdbc/src/main/java/org/apache/beehive/controls/system/jdbc/ResultSetIterator.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: beehive/sandbox/hornet/controls/samples/jdbc/src/main/java/org/apache/beehive/controls/system/jdbc/ResultSetMapper.java
URL: http://svn.apache.org/viewvc/beehive/sandbox/hornet/controls/samples/jdbc/src/main/java/org/apache/beehive/controls/system/jdbc/ResultSetMapper.java?rev=421473&view=auto
==============================================================================
--- beehive/sandbox/hornet/controls/samples/jdbc/src/main/java/org/apache/beehive/controls/system/jdbc/ResultSetMapper.java (added)
+++ beehive/sandbox/hornet/controls/samples/jdbc/src/main/java/org/apache/beehive/controls/system/jdbc/ResultSetMapper.java Wed Jul 12 18:34:03 2006
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Header:$
+ */
+package org.apache.beehive.controls.system.jdbc;
+
+import java.lang.reflect.Method;
+import java.sql.ResultSet;
+import java.util.Calendar;
+
+/**
+ * Extend this class to create new ResultSet mappers. The extended class will be invoked by the JdbcController
+ * when it is time to map a ResultSet to a method's return type.
+ *
+ * ResultSet mappers are specified on a per method basis using the SQL annotation's resultSetMapper field.
+ */
+public abstract class ResultSetMapper {
+
+ /**
+ * Map a ResultSet to an object type
+ *
+ * @param m Method assoicated with this call.
+ * @param resultSet Result set to map.
+ * @param cal A Calendar instance for time/date value resolution.
+ * @return The Object resulting from the ResultSet
+ */
+ public abstract Object mapToResultType(Method m, ResultSet resultSet, Calendar cal);
+
+ /**
+ * Can the ResultSet which this mapper uses be closed by the Jdbc control?
+ * @return true if the ResultSet can be closed by the JdbcControl
+ */
+ public boolean canCloseResultSet() { return true; }
+}
Propchange: beehive/sandbox/hornet/controls/samples/jdbc/src/main/java/org/apache/beehive/controls/system/jdbc/ResultSetMapper.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: beehive/sandbox/hornet/controls/samples/jdbc/src/main/java/org/apache/beehive/controls/system/jdbc/RowMapper.java
URL: http://svn.apache.org/viewvc/beehive/sandbox/hornet/controls/samples/jdbc/src/main/java/org/apache/beehive/controls/system/jdbc/RowMapper.java?rev=421473&view=auto
==============================================================================
--- beehive/sandbox/hornet/controls/samples/jdbc/src/main/java/org/apache/beehive/controls/system/jdbc/RowMapper.java (added)
+++ beehive/sandbox/hornet/controls/samples/jdbc/src/main/java/org/apache/beehive/controls/system/jdbc/RowMapper.java Wed Jul 12 18:34:03 2006
@@ -0,0 +1,241 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Header:$
+ */
+
+package org.apache.beehive.controls.system.jdbc;
+
+import org.apache.beehive.controls.api.ControlException;
+
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.util.Calendar;
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+/**
+ * Abstract base class for all row mappers.
+ *
+ * RowMappers are used to map the contents of a row in a ResultSet to the return type of an annotated method.
+ * Supported RowMapper types include: HashMap, Map, Object, XmlObject. When a ResultSetMapper is ready to
+ * map a ResultSet row to an object, it requests a RowMapper for the return type of the method from the
+ * RowMapperFactory.
+ *
+ */
+public abstract class RowMapper {
+
+ private static final String SETTER_NAME_REGEX = "^(set)([A-Z_]\\w*+)";
+ protected static final TypeMappingsFactory _tmf = TypeMappingsFactory.getInstance();
+ protected static final Pattern _setterRegex = Pattern.compile(SETTER_NAME_REGEX);
+
+ /** ResultSet to map. */
+ protected final ResultSet _resultSet;
+
+ /** Calendar instance for date/time mappings. */
+ protected final Calendar _cal;
+
+ /** Class to map ResultSet Rows to. */
+ protected final Class<?> _returnTypeClass;
+
+ /**
+ * Create a new RowMapper for the specified ResultSet and return type Class.
+ * @param resultSet ResultSet to map
+ * @param returnTypeClass Class to map ResultSet rows to.
+ * @param cal Calendar instance for date/time values.
+ */
+ protected RowMapper(ResultSet resultSet, Class<?> returnTypeClass, Calendar cal) {
+ _resultSet = resultSet;
+ _returnTypeClass = returnTypeClass;
+ _cal = cal;
+ }
+
+ /**
+ * Map a ResultSet row to the return type class
+ * @return An instance of class.
+ */
+ public abstract Object mapRowToReturnType();
+
+
+ /**
+ * Build a String array of column names from the ResultSet.
+ * @return A String array containing the column names contained within the ResultSet.
+ * @throws SQLException on error
+ */
+ protected String[] getKeysFromResultSet() throws SQLException {
+
+ String[] keys;
+ final ResultSetMetaData md = _resultSet.getMetaData();
+ final int columnCount = md.getColumnCount();
+
+ keys = new String[columnCount + 1];
+ for (int i = 1; i <= columnCount; i++) {
+ keys[i] = md.getColumnName(i).toUpperCase();
+ }
+ return keys;
+ }
+
+ /**
+ * Determine if the given method is a java bean setter method.
+ * @param method Method to check
+ * @return True if the method is a setter method.
+ */
+ protected boolean isSetterMethod(Method method) {
+ Matcher matcher = _setterRegex.matcher(method.getName());
+ if (matcher.matches()) {
+
+ if (Modifier.isStatic(method.getModifiers())) return false;
+ if (!Modifier.isPublic(method.getModifiers())) return false;
+ if (!Void.TYPE.equals(method.getReturnType())) return false;
+
+ // method parameter checks
+ Class[] params = method.getParameterTypes();
+ if (params.length != 1) return false;
+ if (TypeMappingsFactory.TYPE_UNKNOWN == _tmf.getTypeId(params[0])) return false;
+
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Extract a column value from the ResultSet and return it as resultType.
+ *
+ * @param index The column index of the value to extract from the ResultSet.
+ * @param resultType The return type. Defined in TypeMappingsFactory.
+ * @return The extracted value
+ * @throws java.sql.SQLException on error.
+ */
+ protected Object extractColumnValue(int index, int resultType) throws SQLException {
+
+ switch (resultType) {
+ case TypeMappingsFactory.TYPE_INT:
+ return new Integer(_resultSet.getInt(index));
+ case TypeMappingsFactory.TYPE_LONG:
+ return new Long(_resultSet.getLong(index));
+ case TypeMappingsFactory.TYPE_FLOAT:
+ return new Float(_resultSet.getFloat(index));
+ case TypeMappingsFactory.TYPE_DOUBLE:
+ return new Double(_resultSet.getDouble(index));
+ case TypeMappingsFactory.TYPE_BYTE:
+ return new Byte(_resultSet.getByte(index));
+ case TypeMappingsFactory.TYPE_SHORT:
+ return new Short(_resultSet.getShort(index));
+ case TypeMappingsFactory.TYPE_BOOLEAN:
+ return _resultSet.getBoolean(index) ? Boolean.TRUE : Boolean.FALSE;
+ case TypeMappingsFactory.TYPE_INT_OBJ:
+ {
+ int i = _resultSet.getInt(index);
+ return _resultSet.wasNull() ? null : new Integer(i);
+ }
+ case TypeMappingsFactory.TYPE_LONG_OBJ:
+ {
+ long i = _resultSet.getLong(index);
+ return _resultSet.wasNull() ? null : new Long(i);
+ }
+ case TypeMappingsFactory.TYPE_FLOAT_OBJ:
+ {
+ float i = _resultSet.getFloat(index);
+ return _resultSet.wasNull() ? null : new Float(i);
+ }
+ case TypeMappingsFactory.TYPE_DOUBLE_OBJ:
+ {
+ double i = _resultSet.getDouble(index);
+ return _resultSet.wasNull() ? null : new Double(i);
+ }
+ case TypeMappingsFactory.TYPE_BYTE_OBJ:
+ {
+ byte i = _resultSet.getByte(index);
+ return _resultSet.wasNull() ? null : new Byte(i);
+ }
+ case TypeMappingsFactory.TYPE_SHORT_OBJ:
+ {
+ short i = _resultSet.getShort(index);
+ return _resultSet.wasNull() ? null : new Short(i);
+ }
+ case TypeMappingsFactory.TYPE_BOOLEAN_OBJ:
+ {
+ boolean i = _resultSet.getBoolean(index);
+ return _resultSet.wasNull() ? null : (i ? Boolean.TRUE : Boolean.FALSE);
+ }
+ case TypeMappingsFactory.TYPE_STRING:
+ case TypeMappingsFactory.TYPE_XMLBEAN_ENUM:
+ return _resultSet.getString(index);
+ case TypeMappingsFactory.TYPE_BIG_DECIMAL:
+ return _resultSet.getBigDecimal(index);
+ case TypeMappingsFactory.TYPE_BYTES:
+ return _resultSet.getBytes(index);
+ case TypeMappingsFactory.TYPE_TIMESTAMP:
+ {
+ if (null == _cal)
+ return _resultSet.getTimestamp(index);
+ else
+ return _resultSet.getTimestamp(index, _cal);
+ }
+ case TypeMappingsFactory.TYPE_TIME:
+ {
+ if (null == _cal)
+ return _resultSet.getTime(index);
+ else
+ return _resultSet.getTime(index, _cal);
+ }
+ case TypeMappingsFactory.TYPE_SQLDATE:
+ {
+ if (null == _cal)
+ return _resultSet.getDate(index);
+ else
+ return _resultSet.getDate(index, _cal);
+ }
+ case TypeMappingsFactory.TYPE_DATE:
+ {
+ // convert explicity to java.util.Date
+ // 12918 | knex does not return java.sql.Date properly from web service
+ java.sql.Timestamp ts = (null == _cal) ? _resultSet.getTimestamp(index) : _resultSet.getTimestamp(index, _cal);
+ if (null == ts)
+ return null;
+ return new java.util.Date(ts.getTime());
+ }
+ case TypeMappingsFactory.TYPE_CALENDAR:
+ {
+ java.sql.Timestamp ts = (null == _cal) ? _resultSet.getTimestamp(index) : _resultSet.getTimestamp(index, _cal);
+ if (null == ts)
+ return null;
+ Calendar c = (null == _cal) ? Calendar.getInstance() : (Calendar) _cal.clone();
+ c.setTimeInMillis(ts.getTime());
+ return c;
+ }
+ case TypeMappingsFactory.TYPE_REF:
+ return _resultSet.getRef(index);
+ case TypeMappingsFactory.TYPE_BLOB:
+ return _resultSet.getBlob(index);
+ case TypeMappingsFactory.TYPE_CLOB:
+ return _resultSet.getClob(index);
+ case TypeMappingsFactory.TYPE_ARRAY:
+ return _resultSet.getArray(index);
+ case TypeMappingsFactory.TYPE_READER:
+ case TypeMappingsFactory.TYPE_STREAM:
+ throw new ControlException("streaming return types are not supported by the JdbcControl; use ResultSet instead");
+ case TypeMappingsFactory.TYPE_STRUCT:
+ case TypeMappingsFactory.TYPE_UNKNOWN:
+ // JAVA_TYPE (could be any), or REF
+ return _resultSet.getObject(index);
+ default:
+ throw new ControlException("internal error: unknown type ID: " + Integer.toString(resultType));
+ }
+ }
+}
Propchange: beehive/sandbox/hornet/controls/samples/jdbc/src/main/java/org/apache/beehive/controls/system/jdbc/RowMapper.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: beehive/sandbox/hornet/controls/samples/jdbc/src/main/java/org/apache/beehive/controls/system/jdbc/RowMapperFactory.java
URL: http://svn.apache.org/viewvc/beehive/sandbox/hornet/controls/samples/jdbc/src/main/java/org/apache/beehive/controls/system/jdbc/RowMapperFactory.java?rev=421473&view=auto
==============================================================================
--- beehive/sandbox/hornet/controls/samples/jdbc/src/main/java/org/apache/beehive/controls/system/jdbc/RowMapperFactory.java (added)
+++ beehive/sandbox/hornet/controls/samples/jdbc/src/main/java/org/apache/beehive/controls/system/jdbc/RowMapperFactory.java Wed Jul 12 18:34:03 2006
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Header:$
+ */
+
+package org.apache.beehive.controls.system.jdbc;
+
+import org.apache.beehive.controls.api.ControlException;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.sql.ResultSet;
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Factory for creating row mappers.
+ * <p/>
+ * Row mapper types supported by this factory include: HashMap, Map, Object, XmlObject. The factory determines the
+ * proper row mapper to use by checking its List of RowMappers against the type of mapping requested. When performing
+ * the lookup, the factory attempts to find the most specific type match. If a match can't be found the most general
+ * type of RowMapper is returned, RowToObjectMapper.
+ */
+public final class RowMapperFactory {
+
+ private static final HashMap<Class, Class<? extends RowMapper>> _rowMappings
+ = new HashMap<Class, Class<? extends RowMapper>>();
+
+ private static Class<? extends RowMapper> DEFAULT_OBJ_ROWMAPPING = RowToObjectMapper.class;
+
+ private static Class XMLOBJ_CLASS = null;
+ private static Class<? extends RowMapper> DEFAULT_XMLOBJ_ROWMAPPING = null;
+ private final static Class[] _params = {ResultSet.class, Class.class, Calendar.class};
+
+ static {
+
+ _rowMappings.put(HashMap.class, RowToHashMapMapper.class);
+ _rowMappings.put(Map.class, RowToMapMapper.class);
+
+ try {
+ XMLOBJ_CLASS = Class.forName("org.apache.xmlbeans.XmlObject");
+ DEFAULT_XMLOBJ_ROWMAPPING = RowToXmlObjectMapper.class;
+ } catch (ClassNotFoundException e) {
+ // NOOP if apache xml beans not present
+ }
+ }
+
+ /**
+ * Get a RowMapper instance which knows how to map a ResultSet row to the given return type.
+ *
+ * @param rs The ResultSet to map.
+ * @param returnTypeClass The class to map a ResultSet row to.
+ * @param cal Calendar instance for mapping date/time values.
+ * @return A RowMapper instance.
+ */
+ public static RowMapper getRowMapper(ResultSet rs, Class returnTypeClass, Calendar cal) {
+
+ Class<? extends RowMapper> rm = _rowMappings.get(returnTypeClass);
+ if (rm != null) {
+ return getMapper(rm, rs, returnTypeClass, cal);
+ }
+
+ //
+ // if we made it to here, check if the default XMLObject Mapper can be used,
+ // otherwise use the default object mapper
+ //
+ if (XMLOBJ_CLASS != null && XMLOBJ_CLASS.isAssignableFrom(returnTypeClass)) {
+ return getMapper(DEFAULT_XMLOBJ_ROWMAPPING, rs, returnTypeClass, cal);
+ } else {
+ return getMapper(DEFAULT_OBJ_ROWMAPPING, rs, returnTypeClass, cal);
+ }
+ }
+
+ /**
+ * Add a new row mapper to the list of available row mappers. The getRowMapper method traverses the
+ * list of mappers from beginning to end, checking to see if a mapper can handle the specified
+ * returnTypeClass. There is a default mapper which is used if a match cannot be found in the list.
+ *
+ * @param returnTypeClass Class which this mapper maps a row to.
+ * @param rowMapperClass The row mapper class.
+ */
+ public static void addRowMapping(Class returnTypeClass, Class<? extends RowMapper> rowMapperClass) {
+ _rowMappings.put(returnTypeClass, rowMapperClass);
+ }
+
+ /**
+ * Replace a row mapping.
+ *
+ * @param returnTypeClass Class which this mapper maps a row to.
+ * @param rowMapperClass The row mapper class.
+ * @return if the mapper was replaced, false mapper for returnTypeClass was not found, no action taken.
+ */
+ public static Class<? extends RowMapper> replaceRowMapping(Class returnTypeClass, Class<? extends RowMapper> rowMapperClass) {
+ return _rowMappings.put(returnTypeClass, rowMapperClass);
+ }
+
+ /**
+ * remove the row mapping for the specified class type.
+ *
+ * @param returnTypeClass
+ * @return the RowMapper class which was removed, null if returnTypeClass did not match any of the registered
+ * row mappers.
+ */
+ public static Class<? extends RowMapper> removeRowMapping(Class returnTypeClass) {
+ return _rowMappings.remove(returnTypeClass);
+ }
+
+ /**
+ * Sets the rowmapper for Object.class
+ *
+ * @param rowMapperClass
+ */
+ public static Class <? extends RowMapper> setDefaultRowMapping(Class<? extends RowMapper> rowMapperClass) {
+ Class<? extends RowMapper> ret = DEFAULT_OBJ_ROWMAPPING;
+ DEFAULT_OBJ_ROWMAPPING = rowMapperClass;
+ return ret;
+ }
+
+ /**
+ * Sets the rowmapper for XmlObject.class
+ *
+ * @param rowMapperClass
+ */
+ public static Class<? extends RowMapper> setDefaultXmlRowMapping(Class mapToClass, Class<? extends RowMapper> rowMapperClass) {
+ Class<? extends RowMapper> ret = DEFAULT_XMLOBJ_ROWMAPPING;
+ DEFAULT_XMLOBJ_ROWMAPPING = rowMapperClass;
+ XMLOBJ_CLASS = mapToClass;
+ return ret;
+ }
+
+ /**
+ * Create an instance of the RowMapper class.
+ *
+ * @param rowMapper
+ * @param rs ResultSet we are mapping from.
+ * @param returnType Class to map rows to.
+ * @param cal Calendar instance for date/time values.
+ * @return A RowMapper instance.
+ */
+ private static RowMapper getMapper(Class<? extends RowMapper> rowMapper, ResultSet rs, Class returnType, Calendar cal)
+ {
+ Constructor c = null;
+ try {
+ c = rowMapper.getDeclaredConstructor(_params);
+ return (RowMapper) c.newInstance(new Object[]{rs, returnType, cal});
+ } catch (NoSuchMethodException e) {
+ throw new ControlException("Failure creating new instance of RowMapper, " + e.toString(), e);
+ } catch (InstantiationException e) {
+ throw new ControlException("Failure creating new instance of RowMapper, " + e.toString(), e);
+ } catch (IllegalAccessException e) {
+ throw new ControlException("Failure creating new instance of RowMapper, " + e.toString(), e);
+ } catch (InvocationTargetException e) {
+ throw new ControlException("Failure creating new instance of RowMapper, " + e.getCause().toString(), e);
+ }
+ }
+}
Propchange: beehive/sandbox/hornet/controls/samples/jdbc/src/main/java/org/apache/beehive/controls/system/jdbc/RowMapperFactory.java
------------------------------------------------------------------------------
svn:eol-style = native