proxool-cvs Mailing List for Proxool: Proxy JDBC Connection Pool (Page 6)
UNMAINTAINED!
Brought to you by:
billhorsman
You can subscribe to this list here.
| 2002 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(2) |
Dec
(9) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2003 |
Jan
(12) |
Feb
(17) |
Mar
(20) |
Apr
(22) |
May
(4) |
Jun
(3) |
Jul
(11) |
Aug
(23) |
Sep
(60) |
Oct
(41) |
Nov
(15) |
Dec
(29) |
| 2004 |
Jan
|
Feb
|
Mar
|
Apr
(1) |
May
(5) |
Jun
(29) |
Jul
(6) |
Aug
(1) |
Sep
(2) |
Oct
|
Nov
|
Dec
|
| 2005 |
Jan
|
Feb
|
Mar
|
Apr
|
May
(8) |
Jun
|
Jul
(1) |
Aug
|
Sep
(8) |
Oct
(19) |
Nov
|
Dec
|
| 2006 |
Jan
(17) |
Feb
|
Mar
(5) |
Apr
(1) |
May
(2) |
Jun
(2) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(3) |
Dec
|
| 2007 |
Jan
(9) |
Feb
|
Mar
|
Apr
|
May
(4) |
Jun
(4) |
Jul
(1) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(3) |
| 2008 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
(4) |
Sep
|
Oct
|
Nov
|
Dec
|
|
From: <bil...@us...> - 2004-06-02 20:36:12
|
Update of /cvsroot/proxool/proxool/src/java/org/logicalcobwebs/proxool/proxy In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv16425/src/java/org/logicalcobwebs/proxool/proxy Log Message: Directory /cvsroot/proxool/proxool/src/java/org/logicalcobwebs/proxool/proxy added to the repository |
|
From: <bil...@us...> - 2004-06-02 20:19:23
|
Update of /cvsroot/proxool/proxool/src/java/org/logicalcobwebs/proxool In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12645/src/java/org/logicalcobwebs/proxool Modified Files: ConnectionPoolDefinition.java ConnectionPoolDefinitionIF.java Log Message: Added injectable interface properties Index: ConnectionPoolDefinition.java =================================================================== RCS file: /cvsroot/proxool/proxool/src/java/org/logicalcobwebs/proxool/ConnectionPoolDefinition.java,v retrieving revision 1.31 retrieving revision 1.32 diff -C2 -d -r1.31 -r1.32 *** ConnectionPoolDefinition.java 18 Mar 2004 17:08:14 -0000 1.31 --- ConnectionPoolDefinition.java 2 Jun 2004 20:19:14 -0000 1.32 *************** *** 17,20 **** --- 17,21 ---- import java.util.Set; import java.util.StringTokenizer; + import java.lang.reflect.Modifier; /** *************** *** 114,119 **** --- 115,129 ---- private boolean jmx; + private String jmxAgentId; + private Class injectableConnectionInterface; + + private Class injectableStatementInterface; + + private Class injectablePreparedStatementInterface; + + private Class injectableCallableStatementInterface; + /** * So we can set the values one by one if we want *************** *** 261,264 **** --- 271,275 ---- changed = changed || setHouseKeeperProperty(key, value, pretend); changed = changed || setLoggingProperty(key, value, pretend); + changed = changed || setInjectableProperty(key, value, pretend); changed = changed || setJndiProperty(key, value, pretend); *************** *** 447,450 **** --- 458,499 ---- /** + * Subset of {@link #setAnyProperty} to avoid overly long method + * @see #setAnyProperty + */ + private boolean setInjectableProperty(String key, String value, boolean pretend) { + boolean changed = false; + if (key.equals(ProxoolConstants.INJECTABLE_CONNECTION_INTERFACE_NAME_PROPERTY)) { + if (isChanged(getInjectableConnectionInterfaceName(), value)) { + changed = true; + if (!pretend) { + setInjectableConnectionInterfaceName(value.length() > 0 ? value : null); + } + } + } else if (key.equals(ProxoolConstants.INJECTABLE_STATEMENT_INTERFACE_NAME_PROPERTY)) { + if (isChanged(getInjectableStatementInterfaceName(), value)) { + changed = true; + if (!pretend) { + setInjectableStatementInterfaceName(value.length() > 0 ? value : null); + } + } + } else if (key.equals(ProxoolConstants.INJECTABLE_PREPARED_STATEMENT_INTERFACE_NAME_PROPERTY)) { + if (isChanged(getInjectablePreparedStatementInterfaceName(), value)) { + changed = true; + if (!pretend) { + setInjectablePreparedStatementInterfaceName(value.length() > 0 ? value : null); + } + } + } else if (key.equals(ProxoolConstants.INJECTABLE_CALLABLE_STATEMENT_INTERFACE_NAME_PROPERTY)) { + if (isChanged(getInjectableCallableStatememtInterfaceName(), value)) { + changed = true; + if (!pretend) { + setInjectableCallableStatementInterfaceName(value.length() > 0 ? value : null); + } + } + } + return changed; + } + + /** * Subset of {@link #setAnyProperty} to avoid overly long method. * @see #setAnyProperty *************** *** 1089,1092 **** --- 1138,1263 ---- /** + * @see ConnectionPoolDefinitionIF#getInjectableConnectionInterface() + */ + public Class getInjectableConnectionInterface() { + return injectableConnectionInterface; + } + + /** + * @see ConnectionPoolDefinitionIF#getInjectableConnectionInterface() + */ + public String getInjectableConnectionInterfaceName() { + if (getInjectableConnectionInterface() != null) { + return getInjectableConnectionInterface().getName(); + } else { + return null; + } + } + + /** + * @param injectableConnectionInterfaceName the fully qualified class name + * @see ConnectionPoolDefinitionIF#getInjectableConnectionInterface() + */ + public void setInjectableConnectionInterfaceName(String injectableConnectionInterfaceName) { + this.injectableConnectionInterface = getInterface(injectableConnectionInterfaceName); + } + + /** + * @see ConnectionPoolDefinitionIF#getInjectableStatementInterface() + */ + public Class getInjectableStatementInterface() { + return injectableStatementInterface; + } + + /** + * @see ConnectionPoolDefinitionIF#getInjectableStatementInterface() + */ + public String getInjectableStatementInterfaceName() { + if (getInjectableStatementInterface() != null) { + return getInjectableStatementInterface().getName(); + } else { + return null; + } + } + + /** + * @param injectableStatementInterfaceName the fully qualified class name + * @see ConnectionPoolDefinitionIF#getInjectableStatementInterface() + */ + public void setInjectableStatementInterfaceName(String injectableStatementInterfaceName) { + this.injectableStatementInterface = getInterface(injectableStatementInterfaceName); + } + + /** + * @see ConnectionPoolDefinitionIF#getInjectablePreparedStatementInterface() + */ + public Class getInjectablePreparedStatementInterface() { + return injectablePreparedStatementInterface; + } + + /** + * @see ConnectionPoolDefinitionIF#getInjectablePreparedStatementInterface() + */ + public String getInjectablePreparedStatementInterfaceName() { + if (getInjectablePreparedStatementInterface() != null) { + return getInjectablePreparedStatementInterface().getName(); + } else { + return null; + } + } + + /** + * @param injectablePreparedStatementInterfaceName the fully qualified class name + * @see ConnectionPoolDefinitionIF#getInjectablePreparedStatementInterface() + */ + public void setInjectablePreparedStatementInterfaceName(String injectablePreparedStatementInterfaceName) { + this.injectablePreparedStatementInterface = getInterface(injectablePreparedStatementInterfaceName); + } + + /** + * @see ConnectionPoolDefinitionIF#getInjectableCallableStatementInterface() + */ + public String getInjectableCallableStatememtInterfaceName() { + if (getInjectableCallableStatementInterface() != null) { + return getInjectableCallableStatementInterface().getName(); + } else { + return null; + } + } + + /** + * @see ConnectionPoolDefinitionIF#getInjectableCallableStatementInterface() + */ + public Class getInjectableCallableStatementInterface() { + return injectableCallableStatementInterface; + } + + /** + * @param injectableCallableStatementInterfaceName the fully qualified class name + * @see ConnectionPoolDefinitionIF#getInjectableCallableStatementInterface() + */ + public void setInjectableCallableStatementInterfaceName(String injectableCallableStatementInterfaceName) { + this.injectableCallableStatementInterface = getInterface(injectableCallableStatementInterfaceName); + } + + private Class getInterface(String className) { + try { + Class clazz = null; + if (className != null && className.length() > 0) { + clazz = Class.forName(className); + if (!clazz.isInterface()) { + throw new IllegalArgumentException(className + " is a class. It must be an interface."); + } + if (!Modifier.isPublic(clazz.getModifiers())) { + throw new IllegalArgumentException(className + " is a protected interface. It must be public."); + } + } + return clazz; + } catch (ClassNotFoundException e) { + throw new IllegalArgumentException(className + " couldn't be found"); + } + } + + /** * Returns true if {@link #redefine redefining} the pool using * these parameters would not change the definition. You can *************** *** 1127,1130 **** --- 1298,1304 ---- Revision history: $Log$ + Revision 1.32 2004/06/02 20:19:14 billhorsman + Added injectable interface properties + Revision 1.31 2004/03/18 17:08:14 chr32 Added jmx* properties. Index: ConnectionPoolDefinitionIF.java =================================================================== RCS file: /cvsroot/proxool/proxool/src/java/org/logicalcobwebs/proxool/ConnectionPoolDefinitionIF.java,v retrieving revision 1.21 retrieving revision 1.22 diff -C2 -d -r1.21 -r1.22 *** ConnectionPoolDefinitionIF.java 18 Mar 2004 17:08:14 -0000 1.21 --- ConnectionPoolDefinitionIF.java 2 Jun 2004 20:19:14 -0000 1.22 *************** *** 303,306 **** --- 303,347 ---- */ String getJmxAgentId(); + + /** + * The class name of an interface that should be injected everytime we make a Connection. + * Use this when you want to access methods on a concrete class in the vendor's Connection + * object that aren't declared in a public interface. Without this, the connection that + * gets served will only give you access to public interfaces (like Connection and any + * other vendor provided ones) + * @return the interface + */ + Class getInjectableConnectionInterface(); + + /** + * The class name of an interface that should be injected everytime we make a Statement. + * Use this when you want to access methods on a concrete class in the vendor's Statement + * object that aren't declared in a public interface. Without this, the statement that + * is provided will only give you access to public interfaces (like Statement and any + * other vendor provided ones) + * @return the interface + */ + Class getInjectableStatementInterface(); + + /** + * The class name of an interface that should be injected everytime we make a PreparedStatement. + * Use this when you want to access methods on a concrete class in the vendor's PreparedStatement + * object that aren't declared in a public interface. Without this, the PreparedStatement that + * is provided will only give you access to public interfaces (like PreparedStatement and any + * other vendor provided ones) + * @return the interface + */ + Class getInjectablePreparedStatementInterface(); + + /** + * The class name of an interface that should be injected everytime we make a CallableStatement. + * Use this when you want to access methods on a concrete class in the vendor's CallableStatement + * object that aren't declared in a public interface. Without this, the CallableStatement that + * is provided will only give you access to public interfaces (like CallableStatement and any + * other vendor provided ones) + * @return the interface + */ + Class getInjectableCallableStatementInterface(); + } *************** *** 308,311 **** --- 349,355 ---- Revision history: $Log$ + Revision 1.22 2004/06/02 20:19:14 billhorsman + Added injectable interface properties + Revision 1.21 2004/03/18 17:08:14 chr32 Added jmx* properties. |
|
From: <bil...@us...> - 2004-06-02 20:05:04
|
Update of /cvsroot/proxool/proxool/src/java/org/logicalcobwebs/proxool In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv9327/src/java/org/logicalcobwebs/proxool Modified Files: AbstractProxyStatement.java Log Message: Fixed sql log: boolean and date now supported, and last parameter is included Index: AbstractProxyStatement.java =================================================================== RCS file: /cvsroot/proxool/proxool/src/java/org/logicalcobwebs/proxool/AbstractProxyStatement.java,v retrieving revision 1.17 retrieving revision 1.18 diff -C2 -d -r1.17 -r1.18 *** AbstractProxyStatement.java 4 Nov 2003 13:54:02 -0000 1.17 --- AbstractProxyStatement.java 2 Jun 2004 20:04:54 -0000 1.18 *************** *** 11,18 **** import java.sql.SQLException; import java.sql.Statement; ! import java.util.Comparator; ! import java.util.Map; ! import java.util.StringTokenizer; ! import java.util.TreeMap; /** --- 11,17 ---- import java.sql.SQLException; import java.sql.Statement; ! import java.util.*; ! import java.text.DateFormat; ! import java.text.SimpleDateFormat; /** *************** *** 29,32 **** --- 28,33 ---- private static final Log LOG = LogFactory.getLog(ProxyStatement.class); + private static final DateFormat DATE_FORMAT = new SimpleDateFormat("dd-MMM-yyyy.HH:mm:ss"); + private Statement statement; *************** *** 152,155 **** --- 153,160 ---- } else if (value instanceof Number) { parameters.put(key, value); + } else if (value instanceof Boolean) { + parameters.put(key, ((Boolean) value).toString()); + } else if (value instanceof Date) { + parameters.put(key, "'" + getDateAsString((Date) value) + "'"); } else { String className = value.getClass().getName(); *************** *** 214,218 **** sqlLog.append(st.nextToken()); } ! sqlLog.append("; "); } if (parameters != null) { --- 219,239 ---- sqlLog.append(st.nextToken()); } ! if (sqlStatement.endsWith("?")) { ! if (parameterIndex > 0) { ! if (parameters != null) { ! final Object value = parameters.get(new Integer(parameterIndex)); ! if (value != null) { ! sqlLog.append(value); ! } else { ! sqlLog.append("?"); ! } ! } else { ! sqlLog.append("?"); ! } ! } ! } ! if (sqlStatement != null && !sqlStatement.trim().endsWith(";")) { ! sqlLog.append("; "); ! } } if (parameters != null) { *************** *** 235,238 **** --- 256,263 ---- } } + + protected static String getDateAsString(Date date) { + return DATE_FORMAT.format(date); + } } *************** *** 241,244 **** --- 266,272 ---- Revision history: $Log$ + Revision 1.18 2004/06/02 20:04:54 billhorsman + Fixed sql log: boolean and date now supported, and last parameter is included + Revision 1.17 2003/11/04 13:54:02 billhorsman checkstyle |
|
From: <bil...@us...> - 2004-06-02 20:04:09
|
Update of /cvsroot/proxool/proxool/src/java-test/org/logicalcobwebs/proxool In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv9091/src/java-test/org/logicalcobwebs/proxool Modified Files: ConnectionListenerTest.java Log Message: Added test for onExecute command Index: ConnectionListenerTest.java =================================================================== RCS file: /cvsroot/proxool/proxool/src/java-test/org/logicalcobwebs/proxool/ConnectionListenerTest.java,v retrieving revision 1.12 retrieving revision 1.13 diff -C2 -d -r1.12 -r1.13 *** ConnectionListenerTest.java 26 May 2004 17:19:10 -0000 1.12 --- ConnectionListenerTest.java 2 Jun 2004 20:04:00 -0000 1.13 *************** *** 6,12 **** --- 6,18 ---- package org.logicalcobwebs.proxool; + import org.logicalcobwebs.logging.Log; + import org.logicalcobwebs.logging.LogFactory; + import java.sql.Connection; + import java.sql.Date; import java.sql.DriverManager; + import java.sql.PreparedStatement; import java.sql.SQLException; + import java.util.Calendar; import java.util.Properties; *************** *** 22,25 **** --- 28,33 ---- public class ConnectionListenerTest extends AbstractProxoolTest { + private static final Log LOG = LogFactory.getLog(ConnectionListenerTest.class); + private int onBirthCalls; private int onDeathCalls; *************** *** 84,87 **** --- 92,155 ---- /** + * See whether the command parameter passed to {@link ConnectionListenerIF#onFail(java.lang.String, java.lang.Exception)} + * is correct. And assume it is also right for onExecute. + * @throws Exception if the test fails. + */ + public void testExecuteCommand() throws Exception { + clear(); + String alias = "executeCommand"; + String url = TestHelper.buildProxoolUrl(alias, + TestConstants.HYPERSONIC_DRIVER, + TestConstants.HYPERSONIC_TEST_URL); + Properties info = new Properties(); + info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); + info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); + Connection connection1 = DriverManager.getConnection(url, info); + final TestConnectionListener tcl = new TestConnectionListener(); + ProxoolFacade.addConnectionListener(alias, tcl); + + // provoke execution error + java.util.Date date = null; + try { + PreparedStatement ps = connection1.prepareStatement("select * from NOTHING where a = ? and b = ? and c = ? and d = ? and e = ?"); + ps.setBoolean(1, true); + Calendar c = Calendar.getInstance(); + date = c.getTime(); + ps.setDate(2, new Date(c.getTime().getTime())); + ps.setInt(3, 3); + ps.setDouble(4, 4.0); + ps.setString(5, "test"); + ps.execute(); + } catch (SQLException e) { + // we expect this + } + LOG.debug(tcl.getCommand()); + assertEquals("command", "select * from NOTHING where a = true and b = '" + AbstractProxyStatement.getDateAsString(date) + "' and c = 3 and d = 4.0 and e = 'test';", tcl.getCommand().trim()); + + // Check that it works with no parameters + final String s2 = "select * from NOTHING;"; + try { + tcl.clear(); + PreparedStatement ps = connection1.prepareStatement(s2); + ps.execute(); + } catch (SQLException e) { + // we expect this + } + LOG.debug(tcl.getCommand()); + assertEquals("command", s2, tcl.getCommand().trim()); + + try { + tcl.clear(); + PreparedStatement ps = connection1.prepareStatement(s2); + ps.execute(); + } catch (SQLException e) { + // we expect this + } + LOG.debug(tcl.getCommand()); + assertEquals("command", s2, tcl.getCommand().trim()); + + } + + /** * Test that multiple connection listeners can be added through ProxoolFacade, * and then removed, and that they do not receive events after they have been removed. *************** *** 154,157 **** --- 222,228 ---- class TestConnectionListener implements ConnectionListenerIF { + + String command; + public void onBirth(Connection connection) throws SQLException { onBirthCalls++; *************** *** 164,171 **** --- 235,252 ---- public void onExecute(String command, long elapsedTime) { onExecuteCalls++; + this.command = command; } public void onFail(String command, Exception exception) { onFailCalls++; + this.command = command; + } + + public String getCommand() { + return command; + } + + public void clear() { + command = null; } } *************** *** 175,178 **** --- 256,262 ---- Revision history: $Log$ + Revision 1.13 2004/06/02 20:04:00 billhorsman + Added test for onExecute command + Revision 1.12 2004/05/26 17:19:10 brenuart Allow JUnit tests to be executed against another database. |
|
From: <bre...@us...> - 2004-05-26 23:07:00
|
Update of /cvsroot/proxool/proxool In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv16018 Modified Files: build.xml Log Message: Index: build.xml =================================================================== RCS file: /cvsroot/proxool/proxool/build.xml,v retrieving revision 1.70 retrieving revision 1.71 diff -C2 -d -r1.70 -r1.71 *** build.xml 26 May 2004 22:43:42 -0000 1.70 --- build.xml 26 May 2004 23:06:45 -0000 1.71 *************** *** 231,234 **** --- 231,235 ---- <copy todir="${build-dir}/src/java" preservelastmodified="yes"> <fileset dir="src/java" includes="**/*.java"/> + <fileset dir="src/java" includes="**/*.dtd"/> </copy> </target> *************** *** 255,259 **** <copy todir="${build-dir}/src/java"> <fileset dir="src/java-test" includes="**/*.java"/> - <fileset dir="src/java-test" includes="**/*.properties"/> </copy> </target> --- 256,259 ---- *************** *** 266,269 **** --- 266,273 ---- <antcall target="build-src"/> <antcall target="compile"/> + + <copy todir="${build-dir}/classes"> + <fileset dir="src/java-test" includes="**/*.properties"/> + </copy> </target> |
|
From: <bre...@us...> - 2004-05-26 22:44:00
|
Update of /cvsroot/proxool/proxool In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv11579 Modified Files: build.xml Log Message: Index: build.xml =================================================================== RCS file: /cvsroot/proxool/proxool/build.xml,v retrieving revision 1.69 retrieving revision 1.70 diff -C2 -d -r1.69 -r1.70 *** build.xml 13 Dec 2003 12:39:08 -0000 1.69 --- build.xml 26 May 2004 22:43:42 -0000 1.70 *************** *** 255,258 **** --- 255,259 ---- <copy todir="${build-dir}/src/java"> <fileset dir="src/java-test" includes="**/*.java"/> + <fileset dir="src/java-test" includes="**/*.properties"/> </copy> </target> |
|
From: <bre...@us...> - 2004-05-26 22:30:33
|
Update of /cvsroot/proxool/proxool/src/java-test/org/logicalcobwebs/proxool In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv9231/src/java-test/org/logicalcobwebs/proxool Modified Files: GlobalTest.java Log Message: Fix issue where testConfig env property was not correctly handled Index: GlobalTest.java =================================================================== RCS file: /cvsroot/proxool/proxool/src/java-test/org/logicalcobwebs/proxool/GlobalTest.java,v retrieving revision 1.19 retrieving revision 1.20 diff -C2 -d -r1.19 -r1.20 *** GlobalTest.java 26 May 2004 17:19:09 -0000 1.19 --- GlobalTest.java 26 May 2004 22:30:21 -0000 1.20 *************** *** 63,67 **** // initialise test configuration ! initTestConstants(defaultConfig); // remember we are correctly initialized --- 63,67 ---- // initialise test configuration ! initTestConstants(); // remember we are correctly initialized *************** *** 76,88 **** private static void initTestConstants() throws Exception { ! String resourceName = System.getProperty("testConfig"); ! if( resourceName==null || resourceName.length()==0 ) ! { ! LOG.info("Test configuration set to default value"); ! } ! else ! { ! initTestConstants(resourceName); ! } } --- 76,81 ---- private static void initTestConstants() throws Exception { ! String resourceName = System.getProperty("testConfig", defaultConfig); ! initTestConstants(resourceName); } *************** *** 136,140 **** public static synchronized void globalTeardown(String alias) { ! ProxoolFacade.shutdown(alias + ":teardown", 10000); } --- 129,133 ---- public static synchronized void globalTeardown(String alias) { ! ProxoolFacade.shutdown(alias + ":teardown", 0); //, 10000); } *************** *** 172,175 **** --- 165,171 ---- Revision history: $Log$ + Revision 1.20 2004/05/26 22:30:21 brenuart + Fix issue where testConfig env property was not correctly handled + Revision 1.19 2004/05/26 17:19:09 brenuart Allow JUnit tests to be executed against another database. |
Update of /cvsroot/proxool/proxool/src/java-test/org/logicalcobwebs/proxool In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv8632/src/java-test/org/logicalcobwebs/proxool Modified Files: ProxyStatementTest.java GlobalTest.java FatalSqlExceptionTest.java ManyPoolsTest.java TestConstants.java PropertyTest.java PrototyperTest.java ConfigurationListenerTest.java ConnectionListenerTest.java UpdateDefinitionTest.java Added Files: testconfig-hsqldb.properties Log Message: Allow JUnit tests to be executed against another database. By default the test configuration will be taken from the 'testconfig-hsqldb.properties' file located in the org.logicalcobwebs.proxool package. This behavior can be overriden by setting the 'testConfig' environment property to another location. --- NEW FILE: testconfig-hsqldb.properties --- HYPERSONIC_DRIVER = org.hsqldb.jdbcDriver HYPERSONIC_USER = sa HYPERSONIC_PASSWORD = HYPERSONIC_TEST_SQL = SELECT COUNT(1) FROM SYSTEM_CATALOGS HYPERSONIC_URL_PREFIX = jdbc:hsqldb:db/ HYPERSONIC_TEST_URL = jdbc:hsqldb:db/test HYPERSONIC_TEST_URL2 = jdbc:hsqldb:db/2 FATAL_SQL_STATEMENT = drop table Z FATAL_SQL_EXCEPTION = Table not found Index: ProxyStatementTest.java =================================================================== RCS file: /cvsroot/proxool/proxool/src/java-test/org/logicalcobwebs/proxool/ProxyStatementTest.java,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** ProxyStatementTest.java 23 Mar 2004 21:17:23 -0000 1.9 --- ProxyStatementTest.java 26 May 2004 17:19:09 -0000 1.10 *************** *** 6,19 **** package org.logicalcobwebs.proxool; ! import org.logicalcobwebs.logging.Log; ! import org.logicalcobwebs.logging.LogFactory; ! import java.sql.Connection; import java.sql.DriverManager; - import java.sql.Statement; import java.sql.PreparedStatement; ! import java.sql.CallableStatement; import java.util.Properties; /** * Test whether ProxyStatement works --- 6,19 ---- package org.logicalcobwebs.proxool; ! import java.sql.CallableStatement; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; ! import java.sql.Statement; import java.util.Properties; + import org.logicalcobwebs.logging.Log; + import org.logicalcobwebs.logging.LogFactory; + /** * Test whether ProxyStatement works *************** *** 35,61 **** * That we can get the delegate driver's Statement from the one given by Proxool */ ! public void testDelegateStatement() throws Exception { ! String testName = "delegateStatement"; - String alias = testName; - Connection c = null; // Register pool ! String url = TestHelper.buildProxoolUrl(alias, ! TestConstants.HYPERSONIC_DRIVER, ! TestConstants.HYPERSONIC_TEST_URL); ! Properties info = new Properties(); ! info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); ! info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); ! ProxoolFacade.registerConnectionPool(url, info); ! c = DriverManager.getConnection(url); ! Statement s = c.createStatement(); ! Statement delegateStatement = ProxoolFacade.getDelegateStatement(s); ! LOG.debug("Statement " + s.getClass() + " is delegating to " + delegateStatement.getClass()); ! assertTrue("Delegate statement isn't a Hypersonic one as expected.", delegateStatement instanceof org.hsqldb.jdbcStatement); } /** * Test what interfaces are supported when getting a PreparedStatement --- 35,67 ---- * That we can get the delegate driver's Statement from the one given by Proxool */ ! public void testDelegateStatement() throws Exception ! { String testName = "delegateStatement"; // Register pool ! String url = registerPool(testName); ! // get a connection from the pool and create a statement with it ! Connection c = DriverManager.getConnection(url); ! Statement s = c.createStatement(); ! Statement delegateStatement = ProxoolFacade.getDelegateStatement(s); ! Class delegateStatementClass = delegateStatement.getClass(); ! s.close(); ! ! LOG.debug("Statement " + s.getClass() + " is delegating to " + delegateStatementClass); ! ! // get a *real* connection directly from the native driver (bypassing the pool) ! Connection realConnection = TestHelper.getDirectConnection(); ! Statement realStatement = realConnection.createStatement(); ! Class realStatementClass = realStatement.getClass(); ! ! realStatement.close(); ! realConnection.close(); + // are they of the same type ? + assertEquals("Delegate statement isn't of the expected type.", realStatementClass, delegateStatementClass); } + /** * Test what interfaces are supported when getting a PreparedStatement *************** *** 64,87 **** String testName = "preparedStatement"; - String alias = testName; - Connection c = null; // Register pool ! String url = TestHelper.buildProxoolUrl(alias, ! TestConstants.HYPERSONIC_DRIVER, ! TestConstants.HYPERSONIC_TEST_URL); ! Properties info = new Properties(); ! info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); ! info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); ! ProxoolFacade.registerConnectionPool(url, info); ! c = DriverManager.getConnection(url); PreparedStatement s = c.prepareStatement(TestConstants.HYPERSONIC_TEST_SQL); Statement delegateStatement = ProxoolFacade.getDelegateStatement(s); ! LOG.debug("Statement " + s.getClass() + " is delegating to " + delegateStatement.getClass()); ! assertTrue("Delegate statement isn't a Hypersonic one as expected.", delegateStatement instanceof org.hsqldb.jdbcPreparedStatement); ! } /** * Test what interfaces are supported when getting a CallableStatement --- 70,99 ---- String testName = "preparedStatement"; // Register pool ! String url = registerPool(testName); ! // get a connection from the pool and create a prepare statement with it ! Connection c = DriverManager.getConnection(url); PreparedStatement s = c.prepareStatement(TestConstants.HYPERSONIC_TEST_SQL); Statement delegateStatement = ProxoolFacade.getDelegateStatement(s); ! Class delegateStatementClass = delegateStatement.getClass(); ! s.close(); ! ! LOG.debug("Statement " + s.getClass() + " is delegating to " + delegateStatementClass); ! ! // get a *real* connection directly from the native driver (bypassing the pool) ! Connection realConnection = TestHelper.getDirectConnection(); ! Statement realStatement = realConnection.prepareStatement(TestConstants.HYPERSONIC_TEST_SQL); ! Class realStatementClass = realStatement.getClass(); ! ! realStatement.close(); ! realConnection.close(); ! ! // are they of the same type ? ! assertEquals("Delegate statement isn't of the expected type.", realStatementClass, delegateStatementClass); } + /** * Test what interfaces are supported when getting a CallableStatement *************** *** 90,112 **** String testName = "callableStatement"; - String alias = testName; - Connection c = null; // Register pool ! String url = TestHelper.buildProxoolUrl(alias, ! TestConstants.HYPERSONIC_DRIVER, ! TestConstants.HYPERSONIC_TEST_URL); ! Properties info = new Properties(); ! info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); ! info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); ! ProxoolFacade.registerConnectionPool(url, info); ! c = DriverManager.getConnection(url); CallableStatement s = c.prepareCall(TestConstants.HYPERSONIC_TEST_SQL); - s = c.prepareCall(TestConstants.HYPERSONIC_TEST_SQL); Statement delegateStatement = ProxoolFacade.getDelegateStatement(s); ! LOG.debug("Statement " + s.getClass() + " is delegating to " + delegateStatement.getClass()); ! assertTrue("Delegate statement isn't a Hypersonic one as expected.", delegateStatement instanceof org.hsqldb.jdbcPreparedStatement); ! } --- 102,128 ---- String testName = "callableStatement"; // Register pool ! String url = registerPool(testName); ! // get a connection from the pool and create a callable statement with it ! Connection c = DriverManager.getConnection(url); CallableStatement s = c.prepareCall(TestConstants.HYPERSONIC_TEST_SQL); Statement delegateStatement = ProxoolFacade.getDelegateStatement(s); ! Class delegateStatementClass = delegateStatement.getClass(); ! s.close(); ! ! LOG.debug("Statement " + s.getClass() + " is delegating to " + delegateStatementClass); ! ! // get a *real* connection directly from the native driver (bypassing the pool) ! Connection realConnection = TestHelper.getDirectConnection(); ! Statement realStatement = realConnection.prepareCall(TestConstants.HYPERSONIC_TEST_SQL); ! Class realStatementClass = realStatement.getClass(); ! ! realStatement.close(); ! realConnection.close(); ! ! // are they of the same type ? ! assertEquals("Delegate statement isn't of the expected type.", realStatementClass, delegateStatementClass ); } *************** *** 118,125 **** String testName = "delegateConnection"; - String alias = testName; - Connection c = null; // Register pool String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, --- 134,165 ---- String testName = "delegateConnection"; // Register pool + String url = registerPool(testName); + + // get a connection from the pool + Connection c = DriverManager.getConnection(url); + Connection delegateConnection = ProxoolFacade.getDelegateConnection(c); + Class delegateConnectionClass = delegateConnection.getClass(); + + LOG.debug("Connection " + c + " is delegating to " + delegateConnectionClass); + c.close(); + + // get a *real* connection directly from the native driver (bypassing the pool) + Connection realConnection = TestHelper.getDirectConnection(); + Class realConnectionClass = realConnection.getClass(); + realConnection.close(); + + assertEquals("Connection isn't of the expected.", realConnectionClass, delegateConnectionClass); + } + + + /** + * + * @param alias + * @throws Exception + */ + private String registerPool(String alias) throws Exception + { String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, *************** *** 129,140 **** info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); ProxoolFacade.registerConnectionPool(url, info); ! ! c = DriverManager.getConnection(url); ! Connection delegateConnection = ProxoolFacade.getDelegateConnection(c); ! LOG.debug("Conneciton " + c.getClass() + " is delegating to " + delegateConnection.getClass()); ! assertTrue("Connection isn't a Hypersonic one as expected.", delegateConnection instanceof org.hsqldb.jdbcConnection); ! ! } ! } --- 169,175 ---- info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); ProxoolFacade.registerConnectionPool(url, info); ! ! return url; ! } } *************** *** 143,146 **** --- 178,186 ---- Revision history: $Log$ + Revision 1.10 2004/05/26 17:19:09 brenuart + Allow JUnit tests to be executed against another database. + By default the test configuration will be taken from the 'testconfig-hsqldb.properties' file located in the org.logicalcobwebs.proxool package. + This behavior can be overriden by setting the 'testConfig' environment property to another location. + Revision 1.9 2004/03/23 21:17:23 billhorsman added preparedStatement and callableStatement tests Index: GlobalTest.java =================================================================== RCS file: /cvsroot/proxool/proxool/src/java-test/org/logicalcobwebs/proxool/GlobalTest.java,v retrieving revision 1.18 retrieving revision 1.19 diff -C2 -d -r1.18 -r1.19 *** GlobalTest.java 26 Oct 2003 16:23:20 -0000 1.18 --- GlobalTest.java 26 May 2004 17:19:09 -0000 1.19 *************** *** 6,12 **** --- 6,17 ---- package org.logicalcobwebs.proxool; + import java.io.InputStream; + import java.lang.reflect.Field; + import java.util.Properties; + import junit.extensions.TestSetup; import junit.framework.Test; import junit.framework.TestSuite; + import org.apache.log4j.xml.DOMConfigurator; import org.logicalcobwebs.logging.Log; *************** *** 16,19 **** --- 21,26 ---- * Provides a suite of all tests. And some utility methods for setting * up the logging. + * + * The test configuration can be specified using the env property "testConfig" * * @version $Revision$, $Date$ *************** *** 24,53 **** public class GlobalTest { private static final Log LOG = LogFactory.getLog(GlobalTest.class); private static boolean initialised; ! public static synchronized void globalSetup() throws ClassNotFoundException { ! if (!initialised) { ! String log4jPath = System.getProperty("log4jPath"); ! if (log4jPath != null && log4jPath.length() > 0) { ! try { ! DOMConfigurator.configureAndWatch(log4jPath); ! } catch (Exception e) { ! LOG.debug("Can't configure logging using " + log4jPath); ! } ! } else { ! // Well, at least switch on debugging ! System.setProperty("org.apache.commons.logging.simplelog.defaultlog", "debug"); ! org.apache.log4j.BasicConfigurator.resetConfiguration(); ! org.apache.log4j.BasicConfigurator.configure(); } ! Class.forName(ProxoolDriver.class.getName()); ! initialised = true; ! } } public static synchronized void globalTeardown(String alias) { ProxoolFacade.shutdown(alias + ":teardown", 10000); --- 31,138 ---- public class GlobalTest { + private static final String defaultConfig = "/org/logicalcobwebs/proxool/testconfig-hsqldb.properties"; + private static final Log LOG = LogFactory.getLog(GlobalTest.class); private static boolean initialised; ! public static synchronized void globalSetup() throws Exception ! { ! // return immediately if we are already initialised ! if (initialised) { ! return; ! } ! ! // configure log4j ! String log4jPath = System.getProperty("log4jPath"); ! if (log4jPath != null && log4jPath.length() > 0) { ! try { ! DOMConfigurator.configureAndWatch(log4jPath); ! } catch (Exception e) { ! LOG.debug("Can't configure logging using " + log4jPath); } + } else { + // Well, at least switch on debugging + System.setProperty("org.apache.commons.logging.simplelog.defaultlog", "debug"); + org.apache.log4j.BasicConfigurator.resetConfiguration(); + org.apache.log4j.BasicConfigurator.configure(); + } ! // Load ProxoolDriver class into DriverManager ! Class.forName(ProxoolDriver.class.getName()); ! // initialise test configuration ! initTestConstants(defaultConfig); ! ! // remember we are correctly initialized ! initialised = true; } + + /** + * + * @throws Exception + */ + private static void initTestConstants() throws Exception + { + String resourceName = System.getProperty("testConfig"); + if( resourceName==null || resourceName.length()==0 ) + { + LOG.info("Test configuration set to default value"); + } + else + { + initTestConstants(resourceName); + } + } + + /** + * + * @param resourceName + */ + private static void initTestConstants(String resourceName) throws Exception + { + // locate and read resource file + InputStream resourceStream = null; + Properties props = new Properties(); + try { + LOG.info("Loading test configuration from "+resourceName); + resourceStream = resourceName.getClass().getResourceAsStream(resourceName); + props.load(resourceStream); + } + catch(Exception e) + { + LOG.error("Problem while loading test configuration", e); + throw e; + } + finally { + if( resourceStream != null ) { + resourceStream.close(); + } + } + + // parse resource file and initialize TestConstants + Field[] fields = TestConstants.class.getDeclaredFields(); + for(int i=0; i<fields.length; i++) + { + Field field = fields[i]; + + // locate value in property file + String propertyName = field.getName(); + String value = props.getProperty(propertyName); + + if( value==null ) + { + LOG.info("Set "+propertyName+" to default value"); + } + else + { + LOG.info("Set " + propertyName+ " to '" + value + "'"); + field.set(null, value); + } + } + } + + public static synchronized void globalTeardown(String alias) { ProxoolFacade.shutdown(alias + ":teardown", 10000); *************** *** 80,83 **** --- 165,169 ---- return wrapper; } + } *************** *** 86,89 **** --- 172,180 ---- Revision history: $Log$ + Revision 1.19 2004/05/26 17:19:09 brenuart + Allow JUnit tests to be executed against another database. + By default the test configuration will be taken from the 'testconfig-hsqldb.properties' file located in the org.logicalcobwebs.proxool package. + This behavior can be overriden by setting the 'testConfig' environment property to another location. + Revision 1.18 2003/10/26 16:23:20 billhorsman Fixed up test suites Index: FatalSqlExceptionTest.java =================================================================== RCS file: /cvsroot/proxool/proxool/src/java-test/org/logicalcobwebs/proxool/FatalSqlExceptionTest.java,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** FatalSqlExceptionTest.java 23 Mar 2004 21:16:05 -0000 1.6 --- FatalSqlExceptionTest.java 26 May 2004 17:19:09 -0000 1.7 *************** *** 41,49 **** TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); ! info.setProperty(ProxoolConstants.FATAL_SQL_EXCEPTION_PROPERTY, "Table not found"); ! info.setProperty(ProxoolConstants.VERBOSE_PROPERTY, String.valueOf(Boolean.TRUE)); ! info.setProperty(ProxoolConstants.TRACE_PROPERTY, String.valueOf(Boolean.TRUE)); ! info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); ! info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); ProxoolFacade.registerConnectionPool(url, info); --- 41,49 ---- TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); ! info.setProperty(ProxoolConstants.FATAL_SQL_EXCEPTION_PROPERTY, TestConstants.FATAL_SQL_EXCEPTION); ! info.setProperty(ProxoolConstants.VERBOSE_PROPERTY, String.valueOf(Boolean.TRUE)); ! info.setProperty(ProxoolConstants.TRACE_PROPERTY, String.valueOf(Boolean.TRUE)); ! info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); ! info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); ProxoolFacade.registerConnectionPool(url, info); *************** *** 67,76 **** Statement s = c2.createStatement(); // Doing it twice will guarantee a failure. Even if it exists ! s.execute("drop table Z"); ! s.execute("drop table Z"); } catch (SQLException e) { assertTrue("Didn't expect a " + FatalSQLException.class.getName(), !(e instanceof FatalSQLException)); // Expected exception (foo doesn't exist) ! LOG.debug("Expected exception (safe to ignore)", e); } finally { if (c2 != null) { --- 67,76 ---- Statement s = c2.createStatement(); // Doing it twice will guarantee a failure. Even if it exists ! s.execute(TestConstants.FATAL_SQL_STATEMENT); ! s.execute(TestConstants.FATAL_SQL_STATEMENT); } catch (SQLException e) { assertTrue("Didn't expect a " + FatalSQLException.class.getName(), !(e instanceof FatalSQLException)); // Expected exception (foo doesn't exist) ! //LOG.debug("Expected exception (safe to ignore)", e); } finally { if (c2 != null) { *************** *** 93,96 **** --- 93,97 ---- } + public void testWrappedFatalSqlException() throws Exception { *************** *** 102,109 **** TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); ! info.setProperty(ProxoolConstants.FATAL_SQL_EXCEPTION_PROPERTY, "Table not found"); ! info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.FATAL_SQL_EXCEPTION_WRAPPER_CLASS_PROPERTY, FatalSQLException.class.getName()); ! info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); ProxoolFacade.registerConnectionPool(url, info); --- 103,110 ---- TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); ! info.setProperty(ProxoolConstants.FATAL_SQL_EXCEPTION_PROPERTY, TestConstants.FATAL_SQL_EXCEPTION); ! info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.FATAL_SQL_EXCEPTION_WRAPPER_CLASS_PROPERTY, FatalSQLException.class.getName()); ! info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); ProxoolFacade.registerConnectionPool(url, info); *************** *** 112,120 **** c = DriverManager.getConnection(url); Statement s = c.createStatement(); ! s.execute("drop table Z"); } catch (SQLException e) { assertTrue("Expected a " + FatalSQLException.class.getName() + " but got a " + e.getClass().getName() + " instead", e instanceof FatalSQLException); // Expected exception (foo doesn't exist) ! LOG.debug("Expected exception (safe to ignore)", e); } --- 113,121 ---- c = DriverManager.getConnection(url); Statement s = c.createStatement(); ! s.execute(TestConstants.FATAL_SQL_STATEMENT); } catch (SQLException e) { assertTrue("Expected a " + FatalSQLException.class.getName() + " but got a " + e.getClass().getName() + " instead", e instanceof FatalSQLException); // Expected exception (foo doesn't exist) ! //LOG.debug("Expected exception (safe to ignore)", e); } *************** *** 143,150 **** TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); ! info.setProperty(ProxoolConstants.FATAL_SQL_EXCEPTION_PROPERTY, "Table not found"); ! info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.FATAL_SQL_EXCEPTION_WRAPPER_CLASS_PROPERTY, FatalRuntimeException.class.getName()); ! info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); ProxoolFacade.registerConnectionPool(url, info); --- 144,151 ---- TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); ! info.setProperty(ProxoolConstants.FATAL_SQL_EXCEPTION_PROPERTY, TestConstants.FATAL_SQL_EXCEPTION); ! info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.FATAL_SQL_EXCEPTION_WRAPPER_CLASS_PROPERTY, FatalRuntimeException.class.getName()); ! info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); ProxoolFacade.registerConnectionPool(url, info); *************** *** 153,157 **** c = DriverManager.getConnection(url); Statement s = c.createStatement(); ! s.execute("drop table Z"); } catch (RuntimeException e) { assertTrue("Expected a " + FatalRuntimeException.class.getName() + " but got a " + e.getClass().getName() + " instead", e instanceof FatalRuntimeException); --- 154,158 ---- c = DriverManager.getConnection(url); Statement s = c.createStatement(); ! s.execute(TestConstants.FATAL_SQL_STATEMENT); } catch (RuntimeException e) { assertTrue("Expected a " + FatalRuntimeException.class.getName() + " but got a " + e.getClass().getName() + " instead", e instanceof FatalRuntimeException); *************** *** 184,191 **** TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); ! info.setProperty(ProxoolConstants.FATAL_SQL_EXCEPTION_PROPERTY, "Table not found"); ! info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.FATAL_SQL_EXCEPTION_WRAPPER_CLASS_PROPERTY, "org.does.not.Exist"); ! info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); try { ProxoolFacade.registerConnectionPool(url, info); --- 185,192 ---- TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); ! info.setProperty(ProxoolConstants.FATAL_SQL_EXCEPTION_PROPERTY, TestConstants.FATAL_SQL_EXCEPTION); ! info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.FATAL_SQL_EXCEPTION_WRAPPER_CLASS_PROPERTY, "org.does.not.Exist"); ! info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); try { ProxoolFacade.registerConnectionPool(url, info); *************** *** 207,215 **** TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); ! info.setProperty(ProxoolConstants.FATAL_SQL_EXCEPTION_PROPERTY, "Table not found"); ! info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); // ProxoolException isn't a RuntimeException or an SQLException info.setProperty(ProxoolConstants.FATAL_SQL_EXCEPTION_WRAPPER_CLASS_PROPERTY, ProxoolException.class.getName()); ! info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); try { ProxoolFacade.registerConnectionPool(url, info); --- 208,216 ---- TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); ! info.setProperty(ProxoolConstants.FATAL_SQL_EXCEPTION_PROPERTY, TestConstants.FATAL_SQL_EXCEPTION); ! info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); // ProxoolException isn't a RuntimeException or an SQLException info.setProperty(ProxoolConstants.FATAL_SQL_EXCEPTION_WRAPPER_CLASS_PROPERTY, ProxoolException.class.getName()); ! info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); try { ProxoolFacade.registerConnectionPool(url, info); *************** *** 227,230 **** --- 228,236 ---- Revision history: $Log$ + Revision 1.7 2004/05/26 17:19:09 brenuart + Allow JUnit tests to be executed against another database. + By default the test configuration will be taken from the 'testconfig-hsqldb.properties' file located in the org.logicalcobwebs.proxool package. + This behavior can be overriden by setting the 'testConfig' environment property to another location. + Revision 1.6 2004/03/23 21:16:05 billhorsman make use of new getId() to compare connections Index: ManyPoolsTest.java =================================================================== RCS file: /cvsroot/proxool/proxool/src/java-test/org/logicalcobwebs/proxool/ManyPoolsTest.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** ManyPoolsTest.java 5 Mar 2003 18:49:27 -0000 1.1 --- ManyPoolsTest.java 26 May 2004 17:19:09 -0000 1.2 *************** *** 41,45 **** info.setProperty(ProxoolConstants.PROTOTYPE_COUNT_PROPERTY, "2"); info.setProperty(ProxoolConstants.HOUSE_KEEPING_SLEEP_TIME_PROPERTY, "30000"); ! final int poolCount = 100; String alias[] = new String[poolCount]; --- 41,46 ---- info.setProperty(ProxoolConstants.PROTOTYPE_COUNT_PROPERTY, "2"); info.setProperty(ProxoolConstants.HOUSE_KEEPING_SLEEP_TIME_PROPERTY, "30000"); ! info.setProperty(ProxoolConstants.HOUSE_KEEPING_TEST_SQL_PROPERTY, TestConstants.HYPERSONIC_TEST_SQL); ! final int poolCount = 100; String alias[] = new String[poolCount]; *************** *** 74,77 **** --- 75,83 ---- Revision history: $Log$ + Revision 1.2 2004/05/26 17:19:09 brenuart + Allow JUnit tests to be executed against another database. + By default the test configuration will be taken from the 'testconfig-hsqldb.properties' file located in the org.logicalcobwebs.proxool package. + This behavior can be overriden by setting the 'testConfig' environment property to another location. + Revision 1.1 2003/03/05 18:49:27 billhorsman moved test to right tree Index: TestConstants.java =================================================================== RCS file: /cvsroot/proxool/proxool/src/java-test/org/logicalcobwebs/proxool/TestConstants.java,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** TestConstants.java 30 Sep 2003 18:39:39 -0000 1.5 --- TestConstants.java 26 May 2004 17:19:09 -0000 1.6 *************** *** 7,11 **** /** ! * Some useful constants for testing * * @version $Revision$, $Date$ --- 7,13 ---- /** ! * Some useful constants for testing. ! * ! * Note: these values will be overriden at startup by the GlobalTest init procedure. * * @version $Revision$, $Date$ *************** *** 14,33 **** * @since Proxool 0.5 */ ! public interface TestConstants { ! ! static final String PROXOOL_DRIVER = "org.logicalcobwebs.proxool.ProxoolDriver"; ! static final String HYPERSONIC_DRIVER = "org.hsqldb.jdbcDriver"; ! static final String HYPERSONIC_URL_PREFIX = "jdbc:hsqldb:db/"; ! static final String HYPERSONIC_TEST_URL = HYPERSONIC_URL_PREFIX + "test"; ! static final String HYPERSONIC_USER = "sa"; ! static final String HYPERSONIC_PASSWORD = ""; ! static final String HYPERSONIC_TEST_SQL = "SELECT COUNT(1) FROM SYSTEM_CATALOGS"; } --- 16,70 ---- * @since Proxool 0.5 */ ! public class TestConstants { ! /** ! * Proxool Driver class ! */ ! public static String PROXOOL_DRIVER = "org.logicalcobwebs.proxool.ProxoolDriver"; ! /** ! * JDBC driver class ! */ ! public static String HYPERSONIC_DRIVER = "org.hsqldb.jdbcDriver"; ! /** ! * URL connection base (without database) ! */ ! public static String HYPERSONIC_URL_PREFIX = "jdbc:hsqldb:db/"; ! /** ! * URL to a first test database. User should have rw access ! */ ! public static String HYPERSONIC_TEST_URL = HYPERSONIC_URL_PREFIX + "test"; ! ! /** ! * URL to a second test database ! */ ! public static String HYPERSONIC_TEST_URL2 = HYPERSONIC_URL_PREFIX + "2"; ! ! /** ! * Connection credentials ! */ ! public static String HYPERSONIC_USER = "sa"; ! /** ! * Connection credentials ! */ ! public static String HYPERSONIC_PASSWORD = ""; ! /** ! * SQL statement that should always succeed ! */ ! public static String HYPERSONIC_TEST_SQL = "SELECT COUNT(1) FROM SYSTEM_CATALOGS"; + /** + * SQL statement that should always fail + */ + public static String FATAL_SQL_STATEMENT = "drop table Z"; + + /** + * SQLException message fragment used to detect fatal exceptions + */ + public static String FATAL_SQL_EXCEPTION = "Table not found"; } *************** *** 35,38 **** --- 72,80 ---- Revision history: $Log$ + Revision 1.6 2004/05/26 17:19:09 brenuart + Allow JUnit tests to be executed against another database. + By default the test configuration will be taken from the 'testconfig-hsqldb.properties' file located in the org.logicalcobwebs.proxool package. + This behavior can be overriden by setting the 'testConfig' environment property to another location. + Revision 1.5 2003/09/30 18:39:39 billhorsman New test sql syntax constant Index: PropertyTest.java =================================================================== RCS file: /cvsroot/proxool/proxool/src/java-test/org/logicalcobwebs/proxool/PropertyTest.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** PropertyTest.java 4 Nov 2003 13:22:43 -0000 1.1 --- PropertyTest.java 26 May 2004 17:19:09 -0000 1.2 *************** *** 49,52 **** --- 49,54 ---- info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); + info.setProperty(ProxoolConstants.HOUSE_KEEPING_TEST_SQL_PROPERTY, TestConstants.HYPERSONIC_TEST_SQL); + Connection c = null; try { *************** *** 58,62 **** // Probably because it doesn't exist. } ! s.execute("create table z (a int(4))"); s.execute("select * from z"); --- 60,64 ---- // Probably because it doesn't exist. } ! s.execute("create table z (a int)"); s.execute("select * from z"); *************** *** 95,98 **** --- 97,105 ---- Revision history: $Log$ + Revision 1.2 2004/05/26 17:19:09 brenuart + Allow JUnit tests to be executed against another database. + By default the test configuration will be taken from the 'testconfig-hsqldb.properties' file located in the org.logicalcobwebs.proxool package. + This behavior can be overriden by setting the 'testConfig' environment property to another location. + Revision 1.1 2003/11/04 13:22:43 billhorsman New test for delegate properties Index: PrototyperTest.java =================================================================== RCS file: /cvsroot/proxool/proxool/src/java-test/org/logicalcobwebs/proxool/PrototyperTest.java,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** PrototyperTest.java 10 Mar 2003 15:31:26 -0000 1.9 --- PrototyperTest.java 26 May 2004 17:19:09 -0000 1.10 *************** *** 47,50 **** --- 47,52 ---- info.setProperty(ProxoolConstants.PROTOTYPE_COUNT_PROPERTY, "2"); info.setProperty(ProxoolConstants.HOUSE_KEEPING_SLEEP_TIME_PROPERTY, "1000"); + info.setProperty(ProxoolConstants.HOUSE_KEEPING_TEST_SQL_PROPERTY, TestConstants.HYPERSONIC_TEST_SQL); + String url = ProxoolConstants.PROXOOL + ProxoolConstants.ALIAS_DELIMITER *************** *** 115,118 **** --- 117,121 ---- info.setProperty(ProxoolConstants.PROTOTYPE_COUNT_PROPERTY, "0"); info.setProperty(ProxoolConstants.HOUSE_KEEPING_SLEEP_TIME_PROPERTY, "1000"); + info.setProperty(ProxoolConstants.HOUSE_KEEPING_TEST_SQL_PROPERTY, TestConstants.HYPERSONIC_TEST_SQL); String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); ProxoolFacade.registerConnectionPool(url, info); *************** *** 136,139 **** --- 139,147 ---- Revision history: $Log$ + Revision 1.10 2004/05/26 17:19:09 brenuart + Allow JUnit tests to be executed against another database. + By default the test configuration will be taken from the 'testconfig-hsqldb.properties' file located in the org.logicalcobwebs.proxool package. + This behavior can be overriden by setting the 'testConfig' environment property to another location. + Revision 1.9 2003/03/10 15:31:26 billhorsman fixes Index: ConfigurationListenerTest.java =================================================================== RCS file: /cvsroot/proxool/proxool/src/java-test/org/logicalcobwebs/proxool/ConfigurationListenerTest.java,v retrieving revision 1.11 retrieving revision 1.12 diff -C2 -d -r1.11 -r1.12 *** ConfigurationListenerTest.java 27 Apr 2003 15:44:19 -0000 1.11 --- ConfigurationListenerTest.java 26 May 2004 17:19:09 -0000 1.12 *************** *** 136,141 **** // Register pool ! final String delegateUrl1 = TestConstants.HYPERSONIC_URL_PREFIX + "1"; ! final String delegateUrl2 = TestConstants.HYPERSONIC_URL_PREFIX + "2"; final String url1 = TestHelper.buildProxoolUrl(alias, --- 136,141 ---- // Register pool ! final String delegateUrl1 = TestConstants.HYPERSONIC_TEST_URL; ! final String delegateUrl2 = TestConstants.HYPERSONIC_TEST_URL2; final String url1 = TestHelper.buildProxoolUrl(alias, *************** *** 236,239 **** --- 236,244 ---- Revision history: $Log$ + Revision 1.12 2004/05/26 17:19:09 brenuart + Allow JUnit tests to be executed against another database. + By default the test configuration will be taken from the 'testconfig-hsqldb.properties' file located in the org.logicalcobwebs.proxool package. + This behavior can be overriden by setting the 'testConfig' environment property to another location. + Revision 1.11 2003/04/27 15:44:19 billhorsman better tests Index: ConnectionListenerTest.java =================================================================== RCS file: /cvsroot/proxool/proxool/src/java-test/org/logicalcobwebs/proxool/ConnectionListenerTest.java,v retrieving revision 1.11 retrieving revision 1.12 diff -C2 -d -r1.11 -r1.12 *** ConnectionListenerTest.java 10 Mar 2003 23:31:04 -0000 1.11 --- ConnectionListenerTest.java 26 May 2004 17:19:10 -0000 1.12 *************** *** 55,58 **** --- 55,60 ---- ProxoolFacade.addConnectionListener(alias, new TestConnectionListener()); Connection connection2 = DriverManager.getConnection(url); + + // provoke execution error boolean errorOccured = false; try { *************** *** 62,70 **** errorOccured = true; } ! assertTrue("We failed to proovoke a connection failure.", errorOccured); ! connection2.createStatement().executeQuery("CALL 1"); connection1.close(); connection2.close(); ProxoolFacade.removeConnectionPool(alias); assertTrue("Expected 2 onBirth calls, but got " + this.onBirthCalls + ".", this.onBirthCalls == 2); assertTrue("Expected 2 onExecute calls, but got " + this.onExecuteCalls + ".", this.onExecuteCalls == 2); --- 64,80 ---- errorOccured = true; } ! assertTrue("We failed to provoke a connection failure.", errorOccured); ! ! // following statement should be ok ! connection2.createStatement().executeQuery(TestConstants.HYPERSONIC_TEST_SQL); ! ! // close both connections connection1.close(); connection2.close(); + + // shutdown connection pool ProxoolFacade.removeConnectionPool(alias); + + // test results assertTrue("Expected 2 onBirth calls, but got " + this.onBirthCalls + ".", this.onBirthCalls == 2); assertTrue("Expected 2 onExecute calls, but got " + this.onExecuteCalls + ".", this.onExecuteCalls == 2); *************** *** 99,102 **** --- 109,114 ---- ProxoolFacade.removeConnectionListener(alias, testConnectionListener2); Connection connection2 = DriverManager.getConnection(url, info); + + // provoke execution error boolean errorOccured = false; try { *************** *** 107,114 **** } assertTrue("We failed to proovoke a connection failure.", errorOccured); ! connection2.createStatement().executeQuery("CALL 1"); connection1.close(); connection2.close(); ProxoolFacade.removeConnectionPool(alias); assertTrue("Expected 0 onBirth calls, but got " + this.onBirthCalls + ".", this.onBirthCalls == 0); assertTrue("Expected 0 onExecute calls, but got " + this.onExecuteCalls + ".", this.onExecuteCalls == 0); --- 119,134 ---- } assertTrue("We failed to proovoke a connection failure.", errorOccured); ! ! // following statement should be ok ! connection2.createStatement().executeQuery(TestConstants.HYPERSONIC_TEST_SQL); ! ! // close connections connection1.close(); connection2.close(); + + // shutdown connection pool ProxoolFacade.removeConnectionPool(alias); + + // validate results assertTrue("Expected 0 onBirth calls, but got " + this.onBirthCalls + ".", this.onBirthCalls == 0); assertTrue("Expected 0 onExecute calls, but got " + this.onExecuteCalls + ".", this.onExecuteCalls == 0); *************** *** 124,135 **** } ! /** ! * Calls {@link AbstractProxoolTest#setUp} ! * @see junit.framework.TestCase#setUp ! */ ! protected void setUp() throws Exception { ! super.setUp(); ! Class.forName("org.logicalcobwebs.proxool.ProxoolDriver"); ! } class TestConnectionListener implements ConnectionListenerIF { --- 144,155 ---- } ! // /** ! // * Calls {@link AbstractProxoolTest#setUp} ! // * @see junit.framework.TestCase#setUp ! // */ ! // protected void setUp() throws Exception { ! // super.setUp(); ! // Class.forName("org.logicalcobwebs.proxool.ProxoolDriver"); ! // } class TestConnectionListener implements ConnectionListenerIF { *************** *** 155,158 **** --- 175,183 ---- Revision history: $Log$ + Revision 1.12 2004/05/26 17:19:10 brenuart + Allow JUnit tests to be executed against another database. + By default the test configuration will be taken from the 'testconfig-hsqldb.properties' file located in the org.logicalcobwebs.proxool package. + This behavior can be overriden by setting the 'testConfig' environment property to another location. + Revision 1.11 2003/03/10 23:31:04 billhorsman fixed deprecated properties and doc Index: UpdateDefinitionTest.java =================================================================== RCS file: /cvsroot/proxool/proxool/src/java-test/org/logicalcobwebs/proxool/UpdateDefinitionTest.java,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** UpdateDefinitionTest.java 4 Mar 2003 12:50:44 -0000 1.6 --- UpdateDefinitionTest.java 26 May 2004 17:19:10 -0000 1.7 *************** *** 38,51 **** String url1 = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, ! TestConstants.HYPERSONIC_URL_PREFIX + "1"); String url2 = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, ! TestConstants.HYPERSONIC_URL_PREFIX + "2"); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); ! info.setProperty("proxool.minimum-connection-count", "2"); // register pool --- 38,51 ---- String url1 = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, ! TestConstants.HYPERSONIC_TEST_URL); String url2 = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, ! TestConstants.HYPERSONIC_TEST_URL2); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); ! info.setProperty(ProxoolConstants.MINIMUM_CONNECTION_COUNT_PROPERTY, "2"); // register pool *************** *** 120,124 **** + TestConstants.HYPERSONIC_DRIVER + ProxoolConstants.URL_DELIMITER ! + "jdbc:hsqldb:db/update"; --- 120,124 ---- + TestConstants.HYPERSONIC_DRIVER + ProxoolConstants.URL_DELIMITER ! + TestConstants.HYPERSONIC_TEST_URL2; //"jdbc:hsqldb:db/update"; *************** *** 151,154 **** --- 151,159 ---- Revision history: $Log$ + Revision 1.7 2004/05/26 17:19:10 brenuart + Allow JUnit tests to be executed against another database. + By default the test configuration will be taken from the 'testconfig-hsqldb.properties' file located in the org.logicalcobwebs.proxool package. + This behavior can be overriden by setting the 'testConfig' environment property to another location. + Revision 1.6 2003/03/04 12:50:44 billhorsman fix |
|
From: <bre...@us...> - 2004-05-14 21:16:00
|
Update of /cvsroot/proxool/proxool/src/java/org/logicalcobwebs/proxool/configuration In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv6000/src/java/org/logicalcobwebs/proxool/configuration Modified Files: JAXPConfigurator.java Log Message: Fix type in method name Index: JAXPConfigurator.java =================================================================== RCS file: /cvsroot/proxool/proxool/src/java/org/logicalcobwebs/proxool/configuration/JAXPConfigurator.java,v retrieving revision 1.10 retrieving revision 1.11 diff -C2 -d -r1.10 -r1.11 *** JAXPConfigurator.java 10 Mar 2003 23:43:15 -0000 1.10 --- JAXPConfigurator.java 14 May 2004 21:15:47 -0000 1.11 *************** *** 83,88 **** final XMLConfigurator xmlConfigurator = new XMLConfigurator(); xmlReader.setErrorHandler(xmlConfigurator); ! setSAXFeauture(xmlReader, "http://xml.org/sax/features/namespaces", NAMESPACE_AWARE); ! setSAXFeauture(xmlReader, "http://xml.org/sax/features/namespace-prefixes", !NAMESPACE_AWARE); saxParser.parse(inputSource, xmlConfigurator); } catch (ParserConfigurationException pce) { --- 83,88 ---- final XMLConfigurator xmlConfigurator = new XMLConfigurator(); xmlReader.setErrorHandler(xmlConfigurator); ! setSAXFeature(xmlReader, "http://xml.org/sax/features/namespaces", NAMESPACE_AWARE); ! setSAXFeature(xmlReader, "http://xml.org/sax/features/namespace-prefixes", !NAMESPACE_AWARE); saxParser.parse(inputSource, xmlConfigurator); } catch (ParserConfigurationException pce) { *************** *** 110,114 **** // only log warning on problems with recognition and support of features // we'll probably pull through anyway... ! private static void setSAXFeauture(XMLReader xmlReader, String feature, boolean state) { if (LOG.isDebugEnabled()) { LOG.debug("Setting sax feature: '" + feature + "'. State: " + state + "."); --- 110,114 ---- // only log warning on problems with recognition and support of features // we'll probably pull through anyway... ! private static void setSAXFeature(XMLReader xmlReader, String feature, boolean state) { if (LOG.isDebugEnabled()) { LOG.debug("Setting sax feature: '" + feature + "'. State: " + state + "."); *************** *** 127,130 **** --- 127,133 ---- Revision history: $Log$ + Revision 1.11 2004/05/14 21:15:47 brenuart + Fix type in method name + Revision 1.10 2003/03/10 23:43:15 billhorsman reapplied checkstyle that i'd inadvertently let |
|
From: <bil...@us...> - 2004-04-22 07:58:48
|
Update of /cvsroot/proxool/proxool In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv7764 Modified Files: CHANGES.txt Log Message: test cvs-mail Index: CHANGES.txt =================================================================== RCS file: /cvsroot/proxool/proxool/CHANGES.txt,v retrieving revision 1.34 retrieving revision 1.35 diff -C2 -d -r1.34 -r1.35 *** CHANGES.txt 25 Mar 2004 12:29:40 -0000 1.34 --- CHANGES.txt 22 Apr 2004 07:11:06 -0000 1.35 *************** *** 10,14 **** - New DataSource implementation. TODO more ! - All connections are now wrapped in disposable wrappers. TODO more - Connections, Statements, PreparedStatements, and CallableStatements now implement --- 10,14 ---- - New DataSource implementation. TODO more ! - All connections are now wrapped in disposable wrappers. TODO more - Connections, Statements, PreparedStatements, and CallableStatements now implement |
|
From: <bil...@us...> - 2003-12-19 18:45:36
|
Update of /cvsroot/proxool/proxool/lib In directory sc8-pr-cvs1:/tmp/cvs-serv13221 Removed Files: jndi.jar Log Message: Stupid me. We're not allowed to distribute JNDI --- jndi.jar DELETED --- |
|
From: <bil...@us...> - 2003-12-17 21:12:20
|
Update of /cvsroot/proxool/proxool/lib In directory sc8-pr-cvs1:/tmp/cvs-serv15110/lib Added Files: jndi.jar Log Message: JNDI classes for use with JDK 1.2 --- NEW FILE: jndi.jar --- (This appears to be a binary file; contents omitted.) |
Update of /cvsroot/proxool/proxool/src/java/org/logicalcobwebs/cglib/proxy
In directory sc8-pr-cvs1:/tmp/cvs-serv14833/proxy
Modified Files:
CallbackFilter.java CallbackGenerator.java Enhancer.java
EnhancerEmitter.java MethodProxy.java NoOp.java
NoOpGenerator.java
Log Message:
Fixes to compile under JDK 1.2
Index: CallbackFilter.java
===================================================================
RCS file: /cvsroot/proxool/proxool/src/java/org/logicalcobwebs/cglib/proxy/CallbackFilter.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -d -r1.1 -r1.2
*** CallbackFilter.java 12 Dec 2003 19:28:11 -0000 1.1
--- CallbackFilter.java 17 Dec 2003 21:10:35 -0000 1.2
***************
*** 63,78 ****
*/
public interface CallbackFilter {
! static final CallbackFilter ALL_ZERO = new CallbackFilter() {
! public int accept(Method method) {
! return 0;
! }
! public String toString() {
! return "ALL_ZERO";
! }
! public int hashCode() {
! return 999;
! }
! };
!
/**
* Map a method to a callback.
--- 63,67 ----
*/
public interface CallbackFilter {
!
/**
* Map a method to a callback.
Index: CallbackGenerator.java
===================================================================
RCS file: /cvsroot/proxool/proxool/src/java/org/logicalcobwebs/cglib/proxy/CallbackGenerator.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -d -r1.1 -r1.2
*** CallbackGenerator.java 12 Dec 2003 19:28:11 -0000 1.1
--- CallbackGenerator.java 17 Dec 2003 21:10:35 -0000 1.2
***************
*** 54,61 ****
package org.logicalcobwebs.cglib.proxy;
- import java.lang.reflect.Method;
- import java.util.Iterator;
import org.logicalcobwebs.cglib.core.ClassEmitter;
import org.logicalcobwebs.cglib.core.CodeEmitter;
interface CallbackGenerator
--- 54,60 ----
package org.logicalcobwebs.cglib.proxy;
import org.logicalcobwebs.cglib.core.ClassEmitter;
import org.logicalcobwebs.cglib.core.CodeEmitter;
+ import org.logicalcobwebs.cglib.core.Context;
interface CallbackGenerator
***************
*** 64,74 ****
void generateStatic(CodeEmitter e, Context context) throws Exception;
- interface Context
- {
- Iterator getMethods();
- int getIndex(Method method);
- void emitCallback(CodeEmitter e, int index);
- int getModifiers(Method method);
- String getUniqueName(Method method);
- }
}
--- 63,65 ----
Index: Enhancer.java
===================================================================
RCS file: /cvsroot/proxool/proxool/src/java/org/logicalcobwebs/cglib/proxy/Enhancer.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -d -r1.1 -r1.2
*** Enhancer.java 12 Dec 2003 19:28:11 -0000 1.1
--- Enhancer.java 17 Dec 2003 21:10:35 -0000 1.2
***************
*** 93,96 ****
--- 93,109 ----
public class Enhancer extends AbstractClassGenerator
{
+
+ static final CallbackFilter ALL_ZERO = new CallbackFilter() {
+ public int accept(Method method) {
+ return 0;
+ }
+ public String toString() {
+ return "ALL_ZERO";
+ }
+ public int hashCode() {
+ return 999;
+ }
+ };
+
private static final Source SOURCE = new Source(Enhancer.class.getName());
private static final EnhancerKey KEY_FACTORY =
***************
*** 319,323 ****
throw new IllegalStateException("Multiple callback types possible but no filter specified");
}
! filter = CallbackFilter.ALL_ZERO;
}
--- 332,336 ----
throw new IllegalStateException("Multiple callback types possible but no filter specified");
}
! filter = ALL_ZERO;
}
Index: EnhancerEmitter.java
===================================================================
RCS file: /cvsroot/proxool/proxool/src/java/org/logicalcobwebs/cglib/proxy/EnhancerEmitter.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -d -r1.1 -r1.2
*** EnhancerEmitter.java 12 Dec 2003 19:28:11 -0000 1.1
--- EnhancerEmitter.java 17 Dec 2003 21:10:35 -0000 1.2
***************
*** 403,407 ****
seenGen.add(gen);
final List fmethods = (List)groups.get(gen);
! CallbackGenerator.Context context = new CallbackGenerator.Context() {
public Iterator getMethods() {
return fmethods.iterator();
--- 403,407 ----
seenGen.add(gen);
final List fmethods = (List)groups.get(gen);
! Context context = new Context() {
public Iterator getMethods() {
return fmethods.iterator();
Index: MethodProxy.java
===================================================================
RCS file: /cvsroot/proxool/proxool/src/java/org/logicalcobwebs/cglib/proxy/MethodProxy.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -d -r1.1 -r1.2
*** MethodProxy.java 12 Dec 2003 19:28:11 -0000 1.1
--- MethodProxy.java 17 Dec 2003 21:10:35 -0000 1.2
***************
*** 77,119 ****
private int i2;
- /**
- * For internal use by {@link Enhancer} only; see the {@link org.logicalcobwebs.cglib.reflect.FastMethod} class
- * for similar functionality.
- */
- public static MethodProxy create(ClassLoader loader, Class c1, Class c2, String desc, String name1, String name2) {
- final Signature sig1 = new Signature(name1, desc);
- Signature sig2 = new Signature(name2, desc);
- FastClass f1 = helper(loader, c1);
- FastClass f2 = helper(loader, c2);
- int i1 = f1.getIndex(sig1);
- int i2 = f2.getIndex(sig2);
-
- MethodProxy proxy;
- if (i1 < 0) {
- proxy = new MethodProxy() {
- public Object invoke(Object obj, Object[] args) throws Throwable {
- throw new IllegalArgumentException("Protected method: " + sig1);
- }
- };
- } else {
- proxy = new MethodProxy();
- }
-
- proxy.f1 = f1;
- proxy.f2 = f2;
- proxy.i1 = i1;
- proxy.i2 = i2;
- proxy.sig = sig1;
- proxy.superName = name2;
- return proxy;
- }
-
- private static FastClass helper(ClassLoader loader, Class type) {
- FastClass.Generator g = new FastClass.Generator();
- g.setType(type);
- g.setClassLoader(loader);
- return g.create();
- }
-
private MethodProxy() {
}
--- 77,80 ----
Index: NoOp.java
===================================================================
RCS file: /cvsroot/proxool/proxool/src/java/org/logicalcobwebs/cglib/proxy/NoOp.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -d -r1.1 -r1.2
*** NoOp.java 12 Dec 2003 19:28:11 -0000 1.1
--- NoOp.java 17 Dec 2003 21:10:35 -0000 1.2
***************
*** 60,66 ****
public interface NoOp extends Callback
{
- /**
- * A thread-safe singleton instance of the <code>NoOp</code> callback.
- */
- public static final NoOp INSTANCE = new NoOp() { };
}
--- 60,62 ----
Index: NoOpGenerator.java
===================================================================
RCS file: /cvsroot/proxool/proxool/src/java/org/logicalcobwebs/cglib/proxy/NoOpGenerator.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -d -r1.1 -r1.2
*** NoOpGenerator.java 12 Dec 2003 19:28:11 -0000 1.1
--- NoOpGenerator.java 17 Dec 2003 21:10:35 -0000 1.2
***************
*** 60,63 ****
--- 60,64 ----
import org.logicalcobwebs.cglib.core.CodeEmitter;
import org.logicalcobwebs.cglib.core.ReflectUtils;
+ import org.logicalcobwebs.cglib.core.Context;
class NoOpGenerator
|
|
From: <bil...@us...> - 2003-12-17 21:10:37
|
Update of /cvsroot/proxool/proxool/src/java/org/logicalcobwebs/cglib/core In directory sc8-pr-cvs1:/tmp/cvs-serv14833/core Added Files: Context.java Log Message: Fixes to compile under JDK 1.2 --- NEW FILE: Context.java --- /* * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact ap...@ap.... * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.logicalcobwebs.cglib.core; import java.util.Iterator; import java.lang.reflect.Method; public interface Context { Iterator getMethods(); int getIndex(Method method); void emitCallback(CodeEmitter e, int index); int getModifiers(Method method); String getUniqueName(Method method); } /* $Log: Context.java,v $ Revision 1.1 2003/12/17 21:10:34 billhorsman Fixes to compile under JDK 1.2 */ |
|
From: <bil...@us...> - 2003-12-16 09:09:39
|
Update of /cvsroot/proxool/proxool/src/java/org/logicalcobwebs/proxool
In directory sc8-pr-cvs1:/tmp/cvs-serv15405/src/java/org/logicalcobwebs/proxool
Modified Files:
ShutdownHook.java
Log Message:
Switched from getCause() to getTargetException() so that we can trap the IllegalStateException in all JDKs.
Index: ShutdownHook.java
===================================================================
RCS file: /cvsroot/proxool/proxool/src/java/org/logicalcobwebs/proxool/ShutdownHook.java,v
retrieving revision 1.10
retrieving revision 1.11
diff -C2 -d -r1.10 -r1.11
*** ShutdownHook.java 16 Nov 2003 18:19:14 -0000 1.10
--- ShutdownHook.java 16 Dec 2003 09:09:32 -0000 1.11
***************
*** 14,19 ****
/**
* This is instantiated statically by ProxoolFacade. It will automatically
! * close down all the connections when teh JVM stops.
! *
* @version $Revision$, $Date$
* @author bill
--- 14,18 ----
/**
* This is instantiated statically by ProxoolFacade. It will automatically
! * close down all the connections when the JVM stops.
* @version $Revision$, $Date$
* @author bill
***************
*** 49,64 ****
LOG.error("Problem removing shutdownHook", e);
} catch (InvocationTargetException e) {
! final Object o;
! try {
! final Method getCauseMethod = Runtime.class.getMethod("getCause", null);
! o = getCauseMethod.invoke(e, null);
! if (o != null && o instanceof IllegalStateException) {
! // This is probably because a shutdown is in progress. We can
! // safely ignore that.
! } else {
! LOG.error("Problem removing shutdownHook", e);
! }
! } catch (Exception ex) {
! LOG.error("Problem calling \"get cause\" on IllegalStateException.", e);
}
}
--- 48,58 ----
LOG.error("Problem removing shutdownHook", e);
} catch (InvocationTargetException e) {
! // Use getTargetException() because getCause() is only supported in JDK 1.4 and later
! Throwable cause = ((InvocationTargetException) e).getTargetException();
! if (cause instanceof IllegalStateException) {
! // This is probably because a shutdown is in progress. We can
! // safely ignore that.
! } else {
! LOG.error("Problem removing shutdownHook", e);
}
}
***************
*** 106,109 ****
--- 100,106 ----
Revision history:
$Log$
+ Revision 1.11 2003/12/16 09:09:32 billhorsman
+ Switched from getCause() to getTargetException() so that we can trap the IllegalStateException in all JDKs.
+
Revision 1.10 2003/11/16 18:19:14 chr32
Started calling to Exception.getCause() via refletion to maintain compilability with < jdk 1.4 compilers.
|
|
From: <bil...@us...> - 2003-12-13 12:39:11
|
Update of /cvsroot/proxool/proxool
In directory sc8-pr-cvs1:/tmp/cvs-serv17947
Modified Files:
build.xml
Log Message:
Don't bother checkstyling asm and cglib
Index: build.xml
===================================================================
RCS file: /cvsroot/proxool/proxool/build.xml,v
retrieving revision 1.68
retrieving revision 1.69
diff -C2 -d -r1.68 -r1.69
*** build.xml 13 Dec 2003 12:21:54 -0000 1.68
--- build.xml 13 Dec 2003 12:39:08 -0000 1.69
***************
*** 129,133 ****
<checkstyle>
! <fileset dir="src/java" includes="**/*.java" excludes="**/concurrent/*"/>
<fileset dir="src/java-examples" includes="**/*.java"/>
<fileset dir="src/java-sandbox" includes="**/*.java"/>
--- 129,133 ----
<checkstyle>
! <fileset dir="src/java" includes="**/*.java" excludes="**/concurrent/*,**/asm/**,**/cglib/**"/>
<fileset dir="src/java-examples" includes="**/*.java"/>
<fileset dir="src/java-sandbox" includes="**/*.java"/>
|
|
From: <bil...@us...> - 2003-12-13 12:21:57
|
Update of /cvsroot/proxool/proxool/src/java/org/logicalcobwebs/proxool
In directory sc8-pr-cvs1:/tmp/cvs-serv15376/src/java/org/logicalcobwebs/proxool
Modified Files:
Version.java
Log Message:
Release 0.8.3
Index: Version.java
===================================================================
RCS file: /cvsroot/proxool/proxool/src/java/org/logicalcobwebs/proxool/Version.java,v
retrieving revision 1.17
retrieving revision 1.18
diff -C2 -d -r1.17 -r1.18
*** Version.java 5 Nov 2003 00:19:48 -0000 1.17
--- Version.java 13 Dec 2003 12:21:54 -0000 1.18
***************
*** 40,44 ****
private static final String BUILD_DATE = null;
! private static final String CVS = "0.8.2+";
public static String getVersion() {
--- 40,44 ----
private static final String BUILD_DATE = null;
! private static final String CVS = "0.8.3+";
public static String getVersion() {
***************
*** 77,80 ****
--- 77,83 ----
Revision history:
$Log$
+ Revision 1.18 2003/12/13 12:21:54 billhorsman
+ Release 0.8.3
+
Revision 1.17 2003/11/05 00:19:48 billhorsman
new revision
|
|
From: <bil...@us...> - 2003-12-13 12:21:57
|
Update of /cvsroot/proxool/proxool
In directory sc8-pr-cvs1:/tmp/cvs-serv15376
Modified Files:
CHANGES.txt build.xml
Log Message:
Release 0.8.3
Index: CHANGES.txt
===================================================================
RCS file: /cvsroot/proxool/proxool/CHANGES.txt,v
retrieving revision 1.31
retrieving revision 1.32
diff -C2 -d -r1.31 -r1.32
*** CHANGES.txt 5 Nov 2003 11:22:41 -0000 1.31
--- CHANGES.txt 13 Dec 2003 12:21:54 -0000 1.32
***************
*** 6,9 ****
--- 6,21 ----
$Author$
+ 0.8.3 - 14 December 2003
+
+ - Switched to Cglib 2.0 and ASM 1.4. Repackaged them both to org.logicalcobwebs.clgib and
+ org.logicalcobwebs.asm respectively. This means that you no longer need to include
+ cglib in your classpath. (Note: other projects may still require it - the repackaged
+ version is just for use by Proxool). This removes our dependency on any version of Cglib
+ or ASM and avoids any potential Jar conflicts.
+
+ - Made house keeper connection test more robust - credit John Hume
+
+ - Removed JDK 1.4 specific code in ShutdownHook
+
0.8.2 - 5 November 2003
Index: build.xml
===================================================================
RCS file: /cvsroot/proxool/proxool/build.xml,v
retrieving revision 1.67
retrieving revision 1.68
diff -C2 -d -r1.67 -r1.68
*** build.xml 5 Nov 2003 00:19:48 -0000 1.67
--- build.xml 13 Dec 2003 12:21:54 -0000 1.68
***************
*** 27,31 ****
<!-- Currect release, e.g. 0.6 -->
! <property name="release" value="0.8.2"/>
<!-- Currect release, e.g. 0.6 -->
--- 27,31 ----
<!-- Currect release, e.g. 0.6 -->
! <property name="release" value="0.8.3"/>
<!-- Currect release, e.g. 0.6 -->
|
|
From: <bil...@us...> - 2003-12-13 12:21:00
|
Update of /cvsroot/proxool/proxool/lib In directory sc8-pr-cvs1:/tmp/cvs-serv15159/lib Modified Files: hibernate2.jar Added Files: cglib2.jar ehcache.jar jta.jar Removed Files: cglib-asm-1.0.jar Log Message: upgrade to Hibernate 2.1 (with additional dependencies) --- NEW FILE: cglib2.jar --- (This appears to be a binary file; contents omitted.) --- NEW FILE: ehcache.jar --- (This appears to be a binary file; contents omitted.) --- NEW FILE: jta.jar --- (This appears to be a binary file; contents omitted.) Index: hibernate2.jar =================================================================== RCS file: /cvsroot/proxool/proxool/lib/hibernate2.jar,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 Binary files /tmp/cvsKlQYYT and /tmp/cvschI4lL differ --- cglib-asm-1.0.jar DELETED --- |
Update of /cvsroot/proxool/proxool/src/java/org/logicalcobwebs/proxool
In directory sc8-pr-cvs1:/tmp/cvs-serv25985/src/java/org/logicalcobwebs/proxool
Modified Files:
ProxyConnection.java ProxyDatabaseMetaData.java
ProxyFactory.java ProxyStatement.java
Log Message:
Now uses Cglib 2.0
Index: ProxyConnection.java
===================================================================
RCS file: /cvsroot/proxool/proxool/src/java/org/logicalcobwebs/proxool/ProxyConnection.java,v
retrieving revision 1.28
retrieving revision 1.29
diff -C2 -d -r1.28 -r1.29
*** ProxyConnection.java 30 Sep 2003 18:39:08 -0000 1.28
--- ProxyConnection.java 12 Dec 2003 19:29:47 -0000 1.29
***************
*** 9,13 ****
import org.logicalcobwebs.logging.LogFactory;
! import net.sf.cglib.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
--- 9,16 ----
import org.logicalcobwebs.logging.LogFactory;
! import org.logicalcobwebs.cglib.proxy.MethodProxy;
! import org.logicalcobwebs.cglib.proxy.MethodInterceptor;
! import org.logicalcobwebs.cglib.proxy.InvocationHandler;
!
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
***************
*** 23,27 ****
* @author $Author$ (current maintainer)
*/
! class ProxyConnection extends AbstractProxyConnection implements InvocationHandler {
private static final Log LOG = LogFactory.getLog(ProxyConnection.class);
--- 26,30 ----
* @author $Author$ (current maintainer)
*/
! class ProxyConnection extends AbstractProxyConnection implements InvocationHandler, MethodInterceptor {
private static final Log LOG = LogFactory.getLog(ProxyConnection.class);
***************
*** 41,64 ****
}
! public Object invoke(Object proxy, Method m, Object[] args)
! throws Throwable {
Object result = null;
int argCount = args != null ? args.length : 0;
try {
! if (m.getName().equals(CLOSE_METHOD)) {
close();
! } else if (m.getName().equals(EQUALS_METHOD) && argCount == 1) {
result = new Boolean(equals(args[0]));
! } else if (m.getName().equals(IS_CLOSED_METHOD) && argCount == 0) {
result = new Boolean(isClosed());
! } else if (m.getName().equals(GET_META_DATA_METHOD) && argCount == 0) {
result = getMetaData();
! } else if (m.getName().equals(FINALIZE_METHOD)) {
super.finalize();
} else {
! if (m.getName().startsWith(ConnectionResetter.MUTATOR_PREFIX)) {
setNeedToReset(true);
}
! result = m.invoke(getConnection(), args);
}
--- 44,70 ----
}
! public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
! return invoke(proxy, method, args);
! }
!
! public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
int argCount = args != null ? args.length : 0;
try {
! if (method.getName().equals(CLOSE_METHOD)) {
close();
! } else if (method.getName().equals(EQUALS_METHOD) && argCount == 1) {
result = new Boolean(equals(args[0]));
! } else if (method.getName().equals(IS_CLOSED_METHOD) && argCount == 0) {
result = new Boolean(isClosed());
! } else if (method.getName().equals(GET_META_DATA_METHOD) && argCount == 0) {
result = getMetaData();
! } else if (method.getName().equals(FINALIZE_METHOD)) {
super.finalize();
} else {
! if (method.getName().startsWith(ConnectionResetter.MUTATOR_PREFIX)) {
setNeedToReset(true);
}
! result = method.invoke(getConnection(), args);
}
***************
*** 106,109 ****
--- 112,118 ----
Revision history:
$Log$
+ Revision 1.29 2003/12/12 19:29:47 billhorsman
+ Now uses Cglib 2.0
+
Revision 1.28 2003/09/30 18:39:08 billhorsman
New test-before-use, test-after-use and fatal-sql-exception-wrapper-class properties.
Index: ProxyDatabaseMetaData.java
===================================================================
RCS file: /cvsroot/proxool/proxool/src/java/org/logicalcobwebs/proxool/ProxyDatabaseMetaData.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -C2 -d -r1.5 -r1.6
*** ProxyDatabaseMetaData.java 10 Sep 2003 22:21:04 -0000 1.5
--- ProxyDatabaseMetaData.java 12 Dec 2003 19:29:47 -0000 1.6
***************
*** 9,13 ****
import org.logicalcobwebs.logging.LogFactory;
! import net.sf.cglib.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
--- 9,16 ----
import org.logicalcobwebs.logging.LogFactory;
! import org.logicalcobwebs.cglib.proxy.MethodInterceptor;
! import org.logicalcobwebs.cglib.proxy.MethodProxy;
! import org.logicalcobwebs.cglib.proxy.InvocationHandler;
!
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
***************
*** 22,26 ****
* @author $Author$ (current maintainer)
*/
! class ProxyDatabaseMetaData extends AbstractDatabaseMetaData implements InvocationHandler {
private static final Log LOG = LogFactory.getLog(ProxyDatabaseMetaData.class);
--- 25,29 ----
* @author $Author$ (current maintainer)
*/
! class ProxyDatabaseMetaData extends AbstractDatabaseMetaData implements MethodInterceptor, InvocationHandler {
private static final Log LOG = LogFactory.getLog(ProxyDatabaseMetaData.class);
***************
*** 36,52 ****
}
! public Object invoke(Object proxy, Method m, Object[] args)
! throws Throwable {
Object result = null;
int argCount = args != null ? args.length : 0;
try {
! if (m.getName().equals(GET_CONNECTION_METHOD)) {
result = getConnection();
! } else if (m.getName().equals(EQUALS_METHOD) && argCount == 1) {
result = new Boolean(equals(args[0]));
! } else if (m.getName().equals(FINALIZE_METHOD)) {
super.finalize();
} else {
! result = m.invoke(getDatabaseMetaData(), args);
}
} catch (InvocationTargetException e) {
--- 39,58 ----
}
! public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
! return invoke(proxy, method, args);
! }
!
! public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
int argCount = args != null ? args.length : 0;
try {
! if (method.getName().equals(GET_CONNECTION_METHOD)) {
result = getConnection();
! } else if (method.getName().equals(EQUALS_METHOD) && argCount == 1) {
result = new Boolean(equals(args[0]));
! } else if (method.getName().equals(FINALIZE_METHOD)) {
super.finalize();
} else {
! result = method.invoke(getDatabaseMetaData(), args);
}
} catch (InvocationTargetException e) {
***************
*** 66,69 ****
--- 72,78 ----
Revision history:
$Log$
+ Revision 1.6 2003/12/12 19:29:47 billhorsman
+ Now uses Cglib 2.0
+
Revision 1.5 2003/09/10 22:21:04 chr32
Removing > jdk 1.2 dependencies.
Index: ProxyFactory.java
===================================================================
RCS file: /cvsroot/proxool/proxool/src/java/org/logicalcobwebs/proxool/ProxyFactory.java,v
retrieving revision 1.24
retrieving revision 1.25
diff -C2 -d -r1.24 -r1.25
*** ProxyFactory.java 30 Sep 2003 18:39:08 -0000 1.24
--- ProxyFactory.java 12 Dec 2003 19:29:47 -0000 1.25
***************
*** 9,14 ****
import org.logicalcobwebs.logging.LogFactory;
! import net.sf.cglib.InvocationHandler;
! import net.sf.cglib.Proxy;
import java.sql.CallableStatement;
import java.sql.Connection;
--- 9,15 ----
import org.logicalcobwebs.logging.LogFactory;
! import org.logicalcobwebs.cglib.proxy.Proxy;
! import org.logicalcobwebs.cglib.proxy.InvocationHandler;
!
import java.sql.CallableStatement;
import java.sql.Connection;
***************
*** 23,30 ****
* A central place to build proxy objects ({@link ProxyConnection connections}
* and {@link ProxyStatement statements}).
! *
! * @version $Revision$, $Date$
* @author Bill Horsman (bi...@lo...)
* @author $Author$ (current maintainer)
* @since Proxool 0.5
*/
--- 24,31 ----
* A central place to build proxy objects ({@link ProxyConnection connections}
* and {@link ProxyStatement statements}).
! *
* @author Bill Horsman (bi...@lo...)
* @author $Author$ (current maintainer)
+ * @version $Revision$, $Date$
* @since Proxool 0.5
*/
***************
*** 41,47 ****
Object delegate = Proxy.newProxyInstance(
! null,
! realConnection.getClass().getInterfaces(),
! new ProxyConnection(realConnection, id, url, connectionPool, status));
return (ProxyConnection) Proxy.getInvocationHandler(delegate);
--- 42,48 ----
Object delegate = Proxy.newProxyInstance(
! realConnection.getClass().getClassLoader(),
! realConnection.getClass().getInterfaces(),
! new ProxyConnection(realConnection, id, url, connectionPool, status));
return (ProxyConnection) Proxy.getInvocationHandler(delegate);
***************
*** 50,60 ****
/**
* Get a Connection from the ProxyConnection
! *
* @param proxyConnection where to find the connection
! * @return
*/
protected static Connection getConnection(ProxyConnectionIF proxyConnection) {
return (Connection) Proxy.newProxyInstance(
! null,
new Class[]{Connection.class},
(InvocationHandler) proxyConnection);
--- 51,61 ----
/**
* Get a Connection from the ProxyConnection
! *
* @param proxyConnection where to find the connection
! * @return
*/
protected static Connection getConnection(ProxyConnectionIF proxyConnection) {
return (Connection) Proxy.newProxyInstance(
! Connection.class.getClassLoader(),
new Class[]{Connection.class},
(InvocationHandler) proxyConnection);
***************
*** 63,66 ****
--- 64,68 ----
/**
* Gets the real Statement that we got from the delegate driver
+ *
* @param statement proxy statement
* @return delegate statement
***************
*** 75,78 ****
--- 77,81 ----
/**
* Gets the real Connection that we got from the delegate driver
+ *
* @param connection proxy connection
* @return deletgate connection
***************
*** 85,89 ****
}
! protected static Statement createProxyStatement(Statement delegate, ConnectionPool connectionPool, ProxyConnectionIF proxyConnection, String sqlStatement) {
// We can't use Class#getInterfaces since that doesn't take
// into account superclass interfaces. We could, laboriously,
--- 88,92 ----
}
! protected static Statement createProxyStatement(Statement delegate, ConnectionPool connectionPool, ProxyConnectionIF proxyConnection, String sqlStatement) {
// We can't use Class#getInterfaces since that doesn't take
// into account superclass interfaces. We could, laboriously,
***************
*** 103,111 ****
}
*/
! return (Statement) Proxy.newProxyInstance(null, interfaces, new ProxyStatement(delegate, connectionPool, proxyConnection, sqlStatement));
}
/**
* Create a new DatabaseMetaData from a connection
* @param connection the proxy connection we are using
* @return databaseMetaData
--- 106,115 ----
}
*/
! return (Statement) Proxy.newProxyInstance(delegate.getClass().getClassLoader(), interfaces, new ProxyStatement(delegate, connectionPool, proxyConnection, sqlStatement));
}
/**
* Create a new DatabaseMetaData from a connection
+ *
* @param connection the proxy connection we are using
* @return databaseMetaData
***************
*** 114,124 ****
protected static DatabaseMetaData getDatabaseMetaData(Connection connection, ProxyConnectionIF proxyConnection) throws SQLException {
return (DatabaseMetaData) Proxy.newProxyInstance(
! null,
new Class[]{DatabaseMetaData.class},
new ProxyDatabaseMetaData(connection, proxyConnection)
);
}
-
-
}
--- 118,126 ----
protected static DatabaseMetaData getDatabaseMetaData(Connection connection, ProxyConnectionIF proxyConnection) throws SQLException {
return (DatabaseMetaData) Proxy.newProxyInstance(
! DatabaseMetaData.class.getClassLoader(),
new Class[]{DatabaseMetaData.class},
new ProxyDatabaseMetaData(connection, proxyConnection)
);
}
}
***************
*** 126,129 ****
--- 128,134 ----
Revision history:
$Log$
+ Revision 1.25 2003/12/12 19:29:47 billhorsman
+ Now uses Cglib 2.0
+
Revision 1.24 2003/09/30 18:39:08 billhorsman
New test-before-use, test-after-use and fatal-sql-exception-wrapper-class properties.
Index: ProxyStatement.java
===================================================================
RCS file: /cvsroot/proxool/proxool/src/java/org/logicalcobwebs/proxool/ProxyStatement.java,v
retrieving revision 1.24
retrieving revision 1.25
diff -C2 -d -r1.24 -r1.25
*** ProxyStatement.java 19 Oct 2003 09:50:33 -0000 1.24
--- ProxyStatement.java 12 Dec 2003 19:29:47 -0000 1.25
***************
*** 9,13 ****
import org.logicalcobwebs.logging.LogFactory;
! import net.sf.cglib.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
--- 9,16 ----
import org.logicalcobwebs.logging.LogFactory;
! import org.logicalcobwebs.cglib.proxy.MethodInterceptor;
! import org.logicalcobwebs.cglib.proxy.MethodProxy;
! import org.logicalcobwebs.cglib.proxy.InvocationHandler;
!
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
***************
*** 23,27 ****
* @author $Author$ (current maintainer)
*/
! class ProxyStatement extends AbstractProxyStatement implements InvocationHandler {
private static final Log LOG = LogFactory.getLog(ProxyStatement.class);
--- 26,30 ----
* @author $Author$ (current maintainer)
*/
! class ProxyStatement extends AbstractProxyStatement implements InvocationHandler, MethodInterceptor {
private static final Log LOG = LogFactory.getLog(ProxyStatement.class);
***************
*** 45,50 ****
}
! public Object invoke(Object proxy, Method method, Object[] args)
! throws Throwable {
Object result = null;
long startTime = System.currentTimeMillis();
--- 48,56 ----
}
! public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
! return invoke(proxy, method, args);
! }
!
! public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
long startTime = System.currentTimeMillis();
***************
*** 130,133 ****
--- 136,142 ----
Revision history:
$Log$
+ Revision 1.25 2003/12/12 19:29:47 billhorsman
+ Now uses Cglib 2.0
+
Revision 1.24 2003/10/19 09:50:33 billhorsman
Drill down into InvocationTargetException during execution debug.
|
Update of /cvsroot/proxool/proxool/src/java/org/logicalcobwebs/cglib/core In directory sc8-pr-cvs1:/tmp/cvs-serv25673/src/java/org/logicalcobwebs/cglib/core Added Files: AbstractClassGenerator.java Block.java ClassEmitter.java ClassGenerator.java ClassNameReader.java ClassesKey.java CodeEmitter.java CodeGenerationException.java CollectionUtils.java Constants.java Converter.java Customizer.java DebuggingClassWriter.java DefaultGeneratorStrategy.java DefaultNamingPolicy.java DuplicatesPredicate.java EmitUtils.java GeneratorStrategy.java KeyFactory.java Local.java MethodWrapper.java NamingPolicy.java ObjectSwitchCallback.java Predicate.java ProcessArrayCallback.java ProcessSwitchCallback.java ReflectUtils.java RemappingCodeVisitor.java Signature.java TinyBitSet.java Transformer.java TypeUtils.java VisibilityPredicate.java Log Message: Repackaged Cglib project --- NEW FILE: AbstractClassGenerator.java --- /* * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact ap...@ap.... * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.logicalcobwebs.cglib.core; import java.io.*; import java.lang.reflect.*; import java.util.*; import org.logicalcobwebs.asm.ClassReader; import org.logicalcobwebs.asm.ClassVisitor; import org.logicalcobwebs.asm.ClassWriter; import org.logicalcobwebs.asm.Type; /** * Abstract class for all code-generating CGLIB utilities. * In addition to caching generated classes for performance, it provides hooks for * customizing the <code>ClassLoader</code>, name of the generated class, and transformations * applied before generation. */ abstract public class AbstractClassGenerator implements ClassGenerator { private static final Object NAME_KEY = new Object(); private GeneratorStrategy strategy = DefaultGeneratorStrategy.INSTANCE; private NamingPolicy namingPolicy; private Source source; private ClassLoader classLoader; private String namePrefix; private Object key; private boolean useCache = true; protected static class Source { String name; Map cache = new WeakHashMap(); public Source(String name) { this.name = name; } } protected AbstractClassGenerator(Source source) { this.source = source; } protected void setNamePrefix(String namePrefix) { this.namePrefix = namePrefix; } final protected String getClassName() { return getClassName(getClassLoader()); } private String getClassName(ClassLoader loader) { NamingPolicy np = (namingPolicy != null) ? namingPolicy : DefaultNamingPolicy.INSTANCE; final Set nameCache = getClassNameCache(loader); return np.getClassName(namePrefix, source.name, key, new Predicate() { public boolean evaluate(Object arg) { return nameCache.contains(arg); } }); } private Set getClassNameCache(ClassLoader loader) { return (Set)((Map)source.cache.get(loader)).get(NAME_KEY); } /** * Set the <code>ClassLoader</code> in which the class will be generated. * Concrete subclasses of <code>AbstractClassGenerator</code> (such as <code>Enhancer</code>) * will try to choose an appropriate default if this is unset. * <p> * Classes are cached per-<code>ClassLoader</code> using a <code>WeakHashMap</code>, to allow * the generated classes to be removed when the associated loader is garbage collected. * @param classLoader the loader to generate the new class with, or null to use the default */ public void setClassLoader(ClassLoader classLoader) { this.classLoader = classLoader; } /** * Override the default naming policy. * @see DefaultNamingPolicy * @param namingPolicy the custom policy, or null to use the default */ public void setNamingPolicy(NamingPolicy namingPolicy) { this.namingPolicy = namingPolicy; } /** * Whether use and update the static cache of generated classes * for a class with the same properties. Default is <code>true</code>. */ public void setUseCache(boolean useCache) { this.useCache = useCache; } /** * Set the strategy to use to create the bytecode from this generator. * By default an instance of {@see DefaultGeneratorStrategy} is used. */ public void setStrategy(GeneratorStrategy strategy) { this.strategy = strategy; } // TODO: pluggable policy? protected ClassLoader getClassLoader() { ClassLoader t = classLoader; if (t == null) { t = getDefaultClassLoader(); } if (t == null) { t = getClass().getClassLoader(); } if (t == null) { throw new IllegalStateException("Cannot determine classloader"); } return t; } abstract protected ClassLoader getDefaultClassLoader(); protected Object create(Object key) { try { Object instance = null; synchronized (source) { ClassLoader loader = getClassLoader(); Map cache2 = null; if (useCache) { cache2 = (Map)source.cache.get(loader); if (cache2 != null) { instance = cache2.get(key); } else { cache2 = new HashMap(); cache2.put(NAME_KEY, new HashSet()); source.cache.put(loader, cache2); } } if (instance == null) { this.key = key; byte[] b = strategy.generate(this); String className = ClassNameReader.getClassName(new ClassReader(b)); getClassNameCache(loader).add(className); instance = firstInstance(ReflectUtils.defineClass(className, b, loader)); if (useCache) { cache2.put(key, instance); } return instance; } } return nextInstance(instance); } catch (RuntimeException e) { throw e; } catch (Error e) { throw e; } catch (Exception e) { throw new CodeGenerationException(e); } } abstract protected Object firstInstance(Class type) throws Exception; abstract protected Object nextInstance(Object instance) throws Exception; } --- NEW FILE: Block.java --- /* * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact ap...@ap.... * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.logicalcobwebs.cglib.core; import org.logicalcobwebs.asm.Label; public class Block { private CodeEmitter e; private Label start; private Label end; public Block(CodeEmitter e) { this.e = e; start = e.mark(); } public CodeEmitter getCodeEmitter() { return e; } public void end() { if (end != null) { throw new IllegalStateException("end of label already set"); } end = e.mark(); } public Label getStart() { return start; } public Label getEnd() { return end; } } --- NEW FILE: ClassEmitter.java --- /* * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact ap...@ap.... * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.logicalcobwebs.cglib.core; import java.io.*; import java.util.*; import org.logicalcobwebs.asm.*; /** * @author Juozas Baliuka, Chris Nokleberg */ public class ClassEmitter extends ClassAdapter { private static final Signature STATIC_HOOK = TypeUtils.parseSignature("void CGLIB$STATIC_HOOK()"); private static final String STATIC_HOOK_FLAG = "CGLIB$STATIC_HOOK_FLAG"; private int access; private Type classType; private Type superType; private Map fieldInfo; private boolean seenStatic; private CodeEmitter hook; private boolean ended; private ClassVisitor outer; public ClassEmitter(ClassVisitor cv) { super(null); setTarget(cv, this); } public ClassEmitter() { super(null); } public void setTarget(ClassVisitor cv, ClassVisitor outer) { this.cv = cv; this.outer = outer; fieldInfo = new HashMap(); seenStatic = false; hook = null; ended = false; } public void begin_class(int access, String className, Type superType, Type[] interfaces, String sourceFile) { this.access = access; this.classType = Type.getType("L" + className.replace('.', '/') + ";"); this.superType = (superType != null) ? superType : Constants.TYPE_OBJECT; cv.visit(access, this.classType.getInternalName(), this.superType.getInternalName(), TypeUtils.toInternalNames(interfaces), sourceFile); init(); } public CodeEmitter getStaticHook() { if (TypeUtils.isInterface(access)) { throw new IllegalStateException("static hook is invalid for this class"); } if (hook == null) { ClassEmitter oe = new ClassEmitter(outer); oe.declare_field(Constants.PRIVATE_FINAL_STATIC, STATIC_HOOK_FLAG, Type.BOOLEAN_TYPE, null, null); CodeEmitter e = oe.begin_method(Constants.ACC_STATIC, STATIC_HOOK, null, null); Label ok = e.make_label(); e.getstatic(classType, STATIC_HOOK_FLAG, Type.BOOLEAN_TYPE); e.if_jump(e.EQ, ok); e.return_value(); e.mark(ok); e.push(true); e.putstatic(classType, STATIC_HOOK_FLAG, Type.BOOLEAN_TYPE); } return hook; } protected void init() { } public int getAccess() { return access; } public Type getClassType() { return classType; } public Type getSuperType() { return superType; } public void end_class() { if (seenStatic && hook == null) { getStaticHook(); // force hook method creation } if (hook != null) { if (!seenStatic) { CodeVisitor v = outer.visitMethod(Constants.ACC_STATIC, Constants.SIG_STATIC.getName(), Constants.SIG_STATIC.getDescriptor(), null, null); v.visitInsn(Constants.RETURN); v.visitMaxs(0, 0); } ended = true; hook.return_value(); hook.end_method(); } cv.visitEnd(); } public CodeEmitter begin_method(int access, Signature sig, Type[] exceptions, Attribute attrs) { CodeVisitor v = cv.visitMethod(access, sig.getName(), sig.getDescriptor(), TypeUtils.toInternalNames(exceptions), attrs); if (sig.equals(STATIC_HOOK)) { hook = new CodeEmitter(this, v, access, sig, exceptions) { public boolean isStaticHook() { return true; } public void visitMaxs(int maxStack, int maxLocals) { if (ended) { super.visitMaxs(maxStack, maxLocals); } } public void visitInsn(int insn) { if (insn != Constants.RETURN || ended) { super.visitInsn(insn); } } }; return hook; } else { CodeEmitter e = new CodeEmitter(this, v, access, sig, exceptions); if (sig.equals(Constants.SIG_STATIC) && !TypeUtils.isInterface(this.access)) { seenStatic = true; e.invoke_static_this(STATIC_HOOK); } return e; } } public CodeEmitter begin_static() { return begin_method(Constants.ACC_STATIC, Constants.SIG_STATIC, null, null); } public void declare_field(int access, String name, Type type, Object value, Attribute attrs) { FieldInfo existing = (FieldInfo)fieldInfo.get(name); FieldInfo info = new FieldInfo(access, name, type, value); if (existing != null) { if (!info.equals(existing)) { throw new IllegalArgumentException("Field \"" + name + "\" has been declared differently"); } } else { fieldInfo.put(name, info); cv.visitField(access, name, type.getDescriptor(), value, attrs); } } public void define_attribute(Attribute attrs) { cv.visitAttribute(attrs); } // TODO: make public? boolean isFieldDeclared(String name) { return fieldInfo.get(name) != null; } FieldInfo getFieldInfo(String name) { FieldInfo field = (FieldInfo)fieldInfo.get(name); if (field == null) { throw new IllegalArgumentException("Field " + name + " is not declared in " + classType.getClassName()); } return field; } static class FieldInfo { int access; String name; Type type; Object value; public FieldInfo(int access, String name, Type type, Object value) { this.access = access; this.name = name; this.type = type; this.value = value; } public boolean equals(Object o) { if (o == null) return false; if (!(o instanceof FieldInfo)) return false; FieldInfo other = (FieldInfo)o; if (access != other.access || !name.equals(other.name) || !type.equals(other.type)) { return false; } if ((value == null) ^ (other.value == null)) return false; if (value != null && !value.equals(other.value)) return false; return true; } public int hashCode() { return access ^ name.hashCode() ^ type.hashCode() ^ ((value == null) ? 0 : value.hashCode()); } } public void visit(int access, String name, String superName, String[] interfaces, String sourceFile) { begin_class(access, name.replace('/', '.'), TypeUtils.fromInternalName(superName), TypeUtils.fromInternalNames(interfaces), sourceFile); } public void visitEnd() { end_class(); } public void visitField(int access, String name, String desc, Object value, Attribute attrs) { declare_field(access, name, Type.getType(desc), value, attrs); } // TODO: handle visitInnerClass? public CodeVisitor visitMethod(int access, String name, String desc, String[] exceptions, Attribute attrs) { return begin_method(access, new Signature(name, desc), TypeUtils.fromInternalNames(exceptions), attrs); } public void visitAttribute(Attribute attrs) { define_attribute(attrs); } } --- NEW FILE: ClassGenerator.java --- /* * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact ap...@ap.... * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.logicalcobwebs.cglib.core; import org.logicalcobwebs.asm.ClassVisitor; public interface ClassGenerator { void generateClass(ClassVisitor v) throws Exception; } --- NEW FILE: ClassNameReader.java --- /* * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact ap...@ap.... * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.logicalcobwebs.cglib.core; import org.logicalcobwebs.asm.ClassAdapter; import org.logicalcobwebs.asm.ClassReader; // TODO: optimize (ClassReader buffers entire class before accept) public class ClassNameReader { private ClassNameReader() { } private static final EarlyExitException EARLY_EXIT = new EarlyExitException(); private static class EarlyExitException extends RuntimeException { } public static String getClassName(ClassReader r) { final String[] array = new String[1]; try { r.accept(new ClassAdapter(null) { public void visit(int access, String name, String superName, String[] interfaces, String sourceFile) { array[0] = name.replace('/', '.'); throw EARLY_EXIT; } }, true); } catch (EarlyExitException e) { } return array[0]; } } --- NEW FILE: ClassesKey.java --- /* * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact ap...@ap.... * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.logicalcobwebs.cglib.core; public class ClassesKey { private static final Key FACTORY = (Key)KeyFactory.create(Key.class, KeyFactory.OBJECT_BY_CLASS); interface Key { Object newInstance(Object[] array); } private ClassesKey() { } public static Object create(Object[] array) { return FACTORY.newInstance(array); } } --- NEW FILE: CodeEmitter.java --- /* * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact ap...@ap.... * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.logicalcobwebs.cglib.core; import java.io.*; import java.lang.reflect.Method; import java.util.*; import org.logicalcobwebs.asm.*; /** * @author Juozas Baliuka, Chris Nokleberg */ public class CodeEmitter extends RemappingCodeVisitor { private static final Signature BOOLEAN_VALUE = TypeUtils.parseSignature("boolean booleanValue()"); private static final Signature CHAR_VALUE = TypeUtils.parseSignature("char charValue()"); private static final Signature LONG_VALUE = TypeUtils.parseSignature("long longValue()"); private static final Signature DOUBLE_VALUE = TypeUtils.parseSignature("double doubleValue()"); private static final Signature FLOAT_VALUE = TypeUtils.parseSignature("float floatValue()"); private static final Signature INT_VALUE = TypeUtils.parseSignature("int intValue()"); private static final Signature CSTRUCT_NULL = TypeUtils.parseConstructor(""); private static final Signature CSTRUCT_STRING = TypeUtils.parseConstructor("String"); public static final int ADD = Constants.IADD; public static final int MUL = Constants.IMUL; public static final int XOR = Constants.IXOR; public static final int USHR = Constants.IUSHR; public static final int SUB = Constants.ISUB; public static final int DIV = Constants.IDIV; public static final int NEG = Constants.INEG; public static final int REM = Constants.IREM; public static final int AND = Constants.IAND; public static final int OR = Constants.IOR; public static final int GT = Constants.IFGT; public static final int LT = Constants.IFLT; public static final int GE = Constants.IFGE; public static final int LE = Constants.IFLE; public static final int NE = Constants.IFNE; public static final int EQ = Constants.IFEQ; private ClassEmitter ce; private State state; private static class State { int access; Signature sig; Type[] argumentTypes; int localOffset; Type[] exceptionTypes; State(int access, Signature sig, Type[] exceptionTypes) { this.access = access; this.sig = sig; this.exceptionTypes = exceptionTypes; localOffset = TypeUtils.isStatic(access) ? 0 : 1; argumentTypes = sig.getArgumentTypes(); } } CodeEmitter(ClassEmitter ce, CodeVisitor cv, int access, Signature sig, Type[] exceptionTypes) { super(cv, access, sig.getArgumentTypes()); this.ce = ce; state = new State(access, sig, exceptionTypes); } public CodeEmitter(CodeEmitter wrap) { super(wrap); this.ce = wrap.ce; this.state = wrap.state; } public boolean isStaticHook() { return false; } public Signature getSignature() { return state.sig; } public Type getReturnType() { return state.sig.getReturnType(); } /* wait until these are needed public Type[] getArgumentTypes() { return state.argumentTypes; } public Type[] getExceptionTypes() { return state.getExceptionTypes(); } */ public ClassEmitter getClassEmitter() { return ce; } public void end_method() { visitMaxs(0, 0); } public Block begin_block() { return new Block(this); } public void catch_exception(Block block, Type exception) { if (block.getEnd() == null) { throw new IllegalStateException("end of block is unset"); } cv.visitTryCatchBlock(block.getStart(), block.getEnd(), mark(), exception.getInternalName()); } public void goTo(Label label) { cv.visitJumpInsn(Constants.GOTO, label); } public void ifnull(Label label) { cv.visitJumpInsn(Constants.IFNULL, label); } public void ifnonnull(Label label) { cv.visitJumpInsn(Constants.IFNONNULL, label); } public void if_jump(int mode, Label label) { cv.visitJumpInsn(mode, label); } public void if_icmp(int mode, Label label) { if_cmp(Type.INT_TYPE, mode, label); } public void if_cmp(Type type, int mode, Label label) { int intOp = -1; int jumpmode = mode; switch (mode) { case GE: jumpmode = LT; break; case LE: jumpmode = GT; break; } switch (type.getSort()) { case Type.LONG: cv.visitInsn(Constants.LCMP); break; case Type.DOUBLE: cv.visitInsn(Constants.DCMPG); break; case Type.FLOAT: cv.visitInsn(Constants.FCMPG); break; case Type.ARRAY: case Type.OBJECT: switch (mode) { case EQ: cv.visitJumpInsn(Constants.IF_ACMPEQ, label); return; case NE: cv.visitJumpInsn(Constants.IF_ACMPNE, label); return; } throw new IllegalArgumentException("Bad comparison for type " + type); default: switch (mode) { case EQ: intOp = Constants.IF_ICMPEQ; break; case NE: intOp = Constants.IF_ICMPNE; break; case GE: swap(); /* fall through */ case LT: intOp = Constants.IF_ICMPLT; break; case LE: swap(); /* fall through */ case GT: intOp = Constants.IF_ICMPGT; break; } cv.visitJumpInsn(intOp, label); return; } if_jump(jumpmode, label); } public void pop() { cv.visitInsn(Constants.POP); } public void pop2() { cv.visitInsn(Constants.POP2); } public void dup() { cv.visitInsn(Constants.DUP); } public void dup2() { cv.visitInsn(Constants.DUP2); } public void dup_x1() { cv.visitInsn(Constants.DUP_X1); } public void dup_x2() { cv.visitInsn(Constants.DUP_X2); } public void dup2_x1() { cv.visitInsn(Constants.DUP2_X1); } public void dup2_x2() { cv.visitInsn(Constants.DUP2_X2); } public void swap() { cv.visitInsn(Constants.SWAP); } public void aconst_null() { cv.visitInsn(Constants.ACONST_NULL); } public void swap(Type prev, Type type) { if (type.getSize() == 1) { if (prev.getSize() == 1) { swap(); // same as dup_x1(), pop(); } else { dup_x2(); pop(); } } else { if (prev.getSize() == 1) { dup2_x1(); pop2(); } else { dup2_x2(); pop2(); } } } public void monitorenter() { cv.visitInsn(Constants.MONITORENTER); } public void monitorexit() { cv.visitInsn(Constants.MONITOREXIT); } public void math(int op, Type type) { cv.visitInsn(type.getOpcode(op)); } public void array_load(Type type) { cv.visitInsn(type.getOpcode(Constants.IALOAD)); } public void array_store(Type type) { cv.visitInsn(type.getOpcode(Constants.IASTORE)); } /** * Casts from one primitive numeric type to another */ public void cast_numeric(Type from, Type to) { if (from != to) { if (from == Type.DOUBLE_TYPE) { if (to == Type.FLOAT_TYPE) { cv.visitInsn(Constants.D2F); } else if (to == Type.LONG_TYPE) { cv.visitInsn(Constants.D2L); } else { cv.visitInsn(Constants.D2I); cast_numeric(Type.INT_TYPE, to); } } else if (from == Type.FLOAT_TYPE) { if (to == Type.DOUBLE_TYPE) { cv.visitInsn(Constants.F2D); } else if (to == Type.LONG_TYPE) { cv.visitInsn(Constants.F2L); } else { cv.visitInsn(Constants.F2I); cast_numeric(Type.INT_TYPE, to); } } else if (from == Type.LONG_TYPE) { if (to == Type.DOUBLE_TYPE) { cv.visitInsn(Constants.L2D); } else if (to == Type.FLOAT_TYPE) { cv.visitInsn(Constants.L2F); } else { cv.visitInsn(Constants.L2I); cast_numeric(Type.INT_TYPE, to); } } else { if (to == Type.BYTE_TYPE) { cv.visitInsn(Constants.I2B); } else if (to == Type.CHAR_TYPE) { cv.visitInsn(Constants.I2C); } else if (to == Type.DOUBLE_TYPE) { cv.visitInsn(Constants.I2D); } else if (to == Type.FLOAT_TYPE) { cv.visitInsn(Constants.I2F); } else if (to == Type.LONG_TYPE) { cv.visitInsn(Constants.I2L); } else if (to == Type.SHORT_TYPE) { cv.visitInsn(Constants.I2S); } } } } public void push(int i) { if (i < -1) { cv.visitLdcInsn(new Integer(i)); } else if (i <= 5) { cv.visitInsn(TypeUtils.ICONST(i)); } else if (i <= Byte.MAX_VALUE) { cv.visitIntInsn(Constants.BIPUSH, i); } else if (i <= Short.MAX_VALUE) { cv.visitIntInsn(Constants.SIPUSH, i); } else { cv.visitLdcInsn(new Integer(i)); } } public void push(long value) { if (value == 0L || value == 1L) { cv.visitInsn(TypeUtils.LCONST(value)); } else { cv.visitLdcInsn(new Long(value)); } } public void push(float value) { if (value == 0f || value == 1f || value == 2f) { cv.visitInsn(TypeUtils.FCONST(value)); } else { cv.visitLdcInsn(new Float(value)); } } public void push(double value) { if (value == 0d || value == 1d) { cv.visitInsn(TypeUtils.DCONST(value)); } else { cv.visitLdcInsn(new Double(value)); } } public void push(String value) { cv.visitLdcInsn(value); } public void newarray() { newarray(Constants.TYPE_OBJECT); } public void newarray(Type type) { if (TypeUtils.isPrimitive(type)) { cv.visitIntInsn(Constants.NEWARRAY, TypeUtils.NEWARRAY(type)); } else { emit_type(Constants.ANEWARRAY, type); } } public void arraylength() { cv.visitInsn(Constants.ARRAYLENGTH); } public void load_this() { if (TypeUtils.isStatic(state.access)) { throw new IllegalStateException("no 'this' pointer within static method"); } cv.visitVarInsn(Constants.ALOAD, 0); } /** * Pushes all of the arguments of the current method onto the stack. */ public void load_args() { load_args(0, state.argumentTypes.length); } /** * Pushes the specified argument of the current method onto the stack. * @param index the zero-based index into the argument list */ public void load_arg(int index) { load_local(state.argumentTypes[index], state.localOffset + skipArgs(index)); } // zero-based (see load_this) public void load_args(int fromArg, int count) { int pos = state.localOffset + skipArgs(fromArg); for (int i = 0; i < count; i++) { Type t = state.argumentTypes[fromArg + i]; load_local(t, pos); pos += t.getSize(); } } private int skipArgs(int numArgs) { int amount = 0; for (int i = 0; i < numArgs; i++) { amount += state.argumentTypes[i].getSize(); } return amount; } private void load_local(Type t, int pos) { // TODO: make t == null ok? cv.visitVarInsn(t.getOpcode(Constants.ILOAD), pos); } private void store_local(Type t, int pos) { // TODO: make t == null ok? cv.visitVarInsn(t.getOpcode(Constants.ISTORE), pos); } public void iinc(Local local, int amount) { cv.visitIincInsn(local.getIndex(), amount); } public void store_local(Local local) { store_local(local.getType(), local.getIndex()); } public void load_local(Local local) { load_local(local.getType(), local.getIndex()); } public void return_value() { cv.visitInsn(state.sig.getReturnType().getOpcode(Constants.IRETURN)); } public void getfield(String name) { ClassEmitter.FieldInfo info = ce.getFieldInfo(name); int opcode = TypeUtils.isStatic(info.access) ? Constants.GETSTATIC : Constants.GETFIELD; emit_field(opcode, ce.getClassType(), name, info.type); } public void putfield(String name) { ClassEmitter.FieldInfo info = ce.getFieldInfo(name); int opcode = TypeUtils.isStatic(info.access) ? Constants.PUTSTATIC : Constants.PUTFIELD; emit_field(opcode, ce.getClassType(), name, info.type); } public void super_getfield(String name, Type type) { emit_field(Constants.GETFIELD, ce.getSuperType(), name, type); } public void super_putfield(String name, Type type) { emit_field(Constants.PUTFIELD, ce.getSuperType(), name, type); } public void super_getstatic(String name, Type type) { emit_field(Constants.GETSTATIC, ce.getSuperType(), name, type); } public void super_putstatic(String name, Type type) { emit_field(Constants.PUTSTATIC, ce.getSuperType(), name, type); } public void getfield(Type owner, String name, Type type) { emit_field(Constants.GETFIELD, owner, name, type); } public void putfield(Type owner, String name, Type type) { emit_field(Constants.PUTFIELD, owner, name, type); } public void getstatic(Type owner, String name, Type type) { emit_field(Constants.GETSTATIC, owner, name, type); } public void putstatic(Type owner, String name, Type type) { emit_field(Constants.PUTSTATIC, owner, name, type); } // package-protected for EmitUtils, try to fix void emit_field(int opcode, Type ctype, String name, Type ftype) { cv.visitFieldInsn(opcode, ctype.getInternalName(), name, ftype.getDescriptor()); } public void super_invoke() { super_invoke(state.sig); } public void super_invoke(Signature sig) { emit_invoke(Constants.INVOKESPECIAL, ce.getSuperType(), sig); } public void invoke_constructor(Type type) { invoke_constructor(type, CSTRUCT_NULL); } public void super_invoke_constructor() { invoke_constructor(ce.getSuperType()); } public void invoke_constructor_this() { invoke_constructor(ce.getClassType()); } private void emit_invoke(int opcode, Type type, Signature sig) { if (sig.getName().equals(Constants.CONSTRUCTOR_NAME) && ((opcode == Constants.INVOKEVIRTUAL) || (opcode == Constants.INVOKESTATIC))) { // TODO: error } cv.visitMethodInsn(opcode, type.getInternalName(), sig.getName(), sig.getDescriptor()); } public void invoke_interface(Type owner, Signature sig) { emit_invoke(Constants.INVOKEINTERFACE, owner, sig); } public void invoke_virtual(Type owner, Signature sig) { emit_invoke(Constants.INVOKEVIRTUAL, owner, sig); } public void invoke_static(Type owner, Signature sig) { emit_invoke(Constants.INVOKESTATIC, owner, sig); } public void invoke_virtual_this(Signature sig) { invoke_virtual(ce.getClassType(), sig); } public void invoke_static_this(Signature sig) { invoke_static(ce.getClassType(), sig); } public void invoke_constructor(Type type, Signature sig) { emit_invoke(Constants.INVOKESPECIAL, type, sig); } public void invoke_constructor_this(Signature sig) { invoke_constructor(ce.getClassType(), sig); } public void super_invoke_constructor(Signature sig) { invoke_constructor(ce.getSuperType(), sig); } public void new_instance_this() { new_instance(ce.getClassType()); } public void new_instance(Type type) { emit_type(Constants.NEW, type); } private void emit_type(int opcode, Type type) { String desc; if (TypeUtils.isArray(type)) { desc = type.getDescriptor(); } else { desc = type.getInternalName(); } cv.visitTypeInsn(opcode, desc); } public void aaload(int index) { push(index); aaload(); } public void aaload() { cv.visitInsn(Constants.AALOAD); } public void aastore() { cv.visitInsn(Constants.AASTORE); } public void athrow() { cv.visitInsn(Constants.ATHROW); } public Label make_label() { return new Label(); } public Local make_local() { return make_local(Constants.TYPE_OBJECT); } public Local make_local(Type type) { return new Local(nextLocal(type.getSize()), type); } public void checkcast_this() { checkcast(ce.getClassType()); } public void checkcast(Type type) { if (!type.equals(Constants.TYPE_OBJECT)) { emit_type(Constants.CHECKCAST, type); } } public void instance_of(Type type) { emit_type(Constants.INSTANCEOF, type); } public void instance_of_this() { instance_of(ce.getClassType()); } public void process_switch(int[] keys, ProcessSwitchCallback callback) { float density; if (keys.length == 0) { density = 0; } else { density = (float)keys.length / (keys[keys.length - 1] - keys[0] + 1); } process_switch(keys, callback, density >= 0.5f); } public void process_switch(int[] keys, ProcessSwitchCallback callback, boolean useTable) { if (!isSorted(keys)) throw new IllegalArgumentException("keys to switch must be sorted ascending"); Label def = make_label(); Label end = make_label(); try { if (keys.length > 0) { int len = keys.length; int min = keys[0]; int max = keys[len - 1]; int range = max - min + 1; if (useTable) { Label[] labels = new Label[range]; Arrays.fill(labels, def); for (int i = 0; i < len; i++) { labels[keys[i] - min] = make_label(); } cv.visitTableSwitchInsn(min, max, def, labels); for (int i = 0; i < range; i++) { Label label = labels[i]; if (label != def) { mark(label); callback.processCase(i + min, end); } } } else { Label[] labels = new Label[len]; for (int i = 0; i < len; i++) { labels[i] = make_label(); } cv.visitLookupSwitchInsn(def, keys, labels); for (int i = 0; i < len; i++) { mark(labels[i]); callback.processCase(keys[i], end); } } } mark(def); callback.processDefault(); mark(end); } catch (RuntimeException e) { throw e; } catch (Error e) { throw e; } catch (Exception e) { throw new CodeGenerationException(e); } } private static boolean isSorted(int[] keys) { for (int i = 1; i < keys.length; i++) { if (keys[i] < keys[i - 1]) return false; } return true; } public void mark(Label label) { cv.visitLabel(label); } Label mark() { Label label = make_label(); cv.visitLabel(label); return label; } public void push(boolean value) { push(value ? 1 : 0); } /** * Toggles the integer on the top of the stack from 1 to 0 or vice versa */ public void not() { push(1); math(XOR, Type.INT_TYPE); } public void throw_exception(Type type, String msg) { new_instance(type); dup(); push(msg); invoke_constructor(type, CSTRUCT_STRING); athrow(); } /** * If the argument is a primitive class, replaces the primitive value * on the top of the stack with the wrapped (Object) equivalent. For * example, char -> Character. * If the class is Void, a null is pushed onto the stack instead. * @param type the class indicating the current type of the top stack value */ public void box(Type type) { if (TypeUtils.isPrimitive(type)) { if (type == Type.VOID_TYPE) { aconst_null(); } else { Type boxed = TypeUtils.getBoxedType(type); new_instance(boxed); if (type.getSize() == 2) { // Pp -> Ppo -> oPpo -> ooPpo -> ooPp -> o dup_x2(); dup_x2(); pop(); } else { // p -> po -> opo -> oop -> o dup_x1(); swap(); } invoke_constructor(boxed, new Signature(Constants.CONSTRUCTOR_NAME, Type.VOID_TYPE, new Type[]{ type })); } } } /** * If the argument is a primitive class, replaces the object * on the top of the stack with the unwrapped (primitive) * equivalent. For example, Character -> char. * @param type the class indicating the desired type of the top stack value * @return true if the value was unboxed */ public void unbox(Type type) { Type t = Constants.TYPE_NUMBER; Signature sig = null; switch (type.getSort()) { case Type.VOID: return; case Type.CHAR: t = Constants.TYPE_CHARACTER; sig = CHAR_VALUE; break; case Type.BOOLEAN: t = Constants.TYPE_BOOLEAN; sig = BOOLEAN_VALUE; break; case Type.DOUBLE: sig = DOUBLE_VALUE; break; case Type.FLOAT: sig = FLOAT_VALUE; break; case Type.LONG: sig = LONG_VALUE; break; case Type.INT: case Type.SHORT: case Type.BYTE: sig = INT_VALUE; } if (sig == null) { checkcast(type); } else { checkcast(t); invoke_virtual(t, sig); } } /** * Allocates and fills an Object[] array with the arguments to the * current method. Primitive values are inserted as their boxed * (Object) equivalents. */ public void create_arg_array() { /* generates: Object[] args = new Object[]{ arg1, new Integer(arg2) }; */ push(state.argumentTypes.length); newarray(); for (int i = 0; i < state.argumentTypes.length; i++) { dup(); push(i); load_arg(i); box(state.argumentTypes[i]); aastore(); } } /** * Pushes a zero onto the stack if the argument is a primitive class, or a null otherwise. */ public void zero_or_null(Type type) { if (TypeUtils.isPrimitive(type)) { switch (type.getSort()) { case Type.DOUBLE: push(0d); break; case Type.LONG: push(0L); break; case Type.FLOAT: push(0f); break; case Type.VOID: aconst_null(); default: push(0); } } else { aconst_null(); } } /** * Unboxes the object on the top of the stack. If the object is null, the * unboxed primitive value becomes zero. */ public void unbox_or_zero(Type type) { if (TypeUtils.isPrimitive(type)) { if (type != Type.VOID_TYPE) { Label nonNull = make_label(); Label end = make_label(); dup(); ifnonnull(nonNull); pop(); zero_or_null(type); goTo(end); mark(nonNull); unbox(type); mark(end); } } else { checkcast(type); } } public void visitMaxs(int maxStack, int maxLocals) { if (!TypeUtils.isAbstract(state.access)) { cv.visitMaxs(0, 0); } } public void invoke(Method method) { Class declaring = method.getDeclaringClass(); Type owner = Type.getType(declaring); Signature sig = TypeUtils.getSignature(method); if (declaring.isInterface()) { invoke_interface(owner, sig); } else if (TypeUtils.isStatic(method.getModifiers())) { invoke_static(owner, sig); } else { invoke_virtual(owner, sig); } } public void define_attribute(Attribu... [truncated message content] |
Update of /cvsroot/proxool/proxool/src/java/org/logicalcobwebs/cglib/proxy In directory sc8-pr-cvs1:/tmp/cvs-serv25673/src/java/org/logicalcobwebs/cglib/proxy Added Files: Callback.java CallbackFilter.java CallbackGenerator.java CallbackUtils.java Dispatcher.java DispatcherGenerator.java Enhancer.java EnhancerEmitter.java Factory.java FixedValue.java FixedValueGenerator.java InvocationHandler.java InvocationHandlerGenerator.java LazyLoader.java LazyLoaderGenerator.java MethodInterceptor.java MethodInterceptorGenerator.java MethodProxy.java Mixin.java MixinBeanEmitter.java MixinEmitter.java NoOp.java NoOpGenerator.java Proxy.java UndeclaredThrowableException.java Log Message: Repackaged Cglib project --- NEW FILE: Callback.java --- /* * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact ap...@ap.... * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.logicalcobwebs.cglib.proxy; /** * All callback interfaces used by {@link Enhancer} extend this interface. * @see MethodInterceptor * @see NoOp * @see LazyLoader * @see Dispatcher * @see InvocationHandler * @see FixedValue */ public interface Callback { } --- NEW FILE: CallbackFilter.java --- /* * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact ap...@ap.... * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.logicalcobwebs.cglib.proxy; import java.lang.reflect.Method; /** * Map methods of subclasses generated by {@link Enhancer} to a particular * callback. The type of the callbacks chosen for each method affects * the bytecode generated for that method in the subclass, and cannot * change for the life of the class. */ public interface CallbackFilter { static final CallbackFilter ALL_ZERO = new CallbackFilter() { public int accept(Method method) { return 0; } public String toString() { return "ALL_ZERO"; } public int hashCode() { return 999; } }; /** * Map a method to a callback. * @param method the intercepted method * @return the index into the array of callbacks (as specified by {@link Enhancer#setCallbacks}) to use for the method, */ int accept(Method method); /** * The <code>CallbackFilter</code> in use affects which cached class * the <code>Enhancer</code> will use, so this is a reminder that * you should correctly implement <code>equals</code> and * <code>hashCode</code> for custom <code>CallbackFilter</code> * implementations in order to improve performance. */ boolean equals(Object o); } --- NEW FILE: CallbackGenerator.java --- /* * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact ap...@ap.... * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.logicalcobwebs.cglib.proxy; import java.lang.reflect.Method; import java.util.Iterator; import org.logicalcobwebs.cglib.core.ClassEmitter; import org.logicalcobwebs.cglib.core.CodeEmitter; interface CallbackGenerator { void generate(ClassEmitter e, Context context) throws Exception; void generateStatic(CodeEmitter e, Context context) throws Exception; interface Context { Iterator getMethods(); int getIndex(Method method); void emitCallback(CodeEmitter e, int index); int getModifiers(Method method); String getUniqueName(Method method); } } --- NEW FILE: CallbackUtils.java --- /* * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact ap...@ap.... * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.logicalcobwebs.cglib.proxy; import org.logicalcobwebs.asm.Type; class CallbackUtils { private CallbackUtils() { } static Class determineType(Callback callback) { Class test = typeHelper(callback, null, NoOp.class); test = typeHelper(callback, test, MethodInterceptor.class); test = typeHelper(callback, test, InvocationHandler.class); test = typeHelper(callback, test, LazyLoader.class); test = typeHelper(callback, test, Dispatcher.class); test = typeHelper(callback, test, FixedValue.class); if (test == null) { throw new IllegalStateException("Unknown callback " + callback.getClass()); } return test; } private static Class typeHelper(Callback callback, Class cur, Class callbackType) { if (callback == null) { throw new IllegalStateException("Callback is null"); } if (callbackType.isAssignableFrom(callback.getClass())) { if (cur != null) { throw new IllegalStateException("Callback implements both " + cur + " and " + callbackType + "; use setCallbackTypes to distinguish"); } return callbackType; } else { return cur; } } static CallbackGenerator getGenerator(Class type) { if (type.equals(NoOp.class)) { return NoOpGenerator.INSTANCE; } else if (type.equals(MethodInterceptor.class)) { return MethodInterceptorGenerator.INSTANCE; } else if (type.equals(InvocationHandler.class)) { return InvocationHandlerGenerator.INSTANCE; } else if (type.equals(LazyLoader.class)) { return LazyLoaderGenerator.INSTANCE; } else if (type.equals(Dispatcher.class)) { return DispatcherGenerator.INSTANCE; } else if (type.equals(FixedValue.class)) { return FixedValueGenerator.INSTANCE; } else { throw new IllegalStateException("Unknown callback " + type); } } } --- NEW FILE: Dispatcher.java --- /* * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact ap...@ap.... * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.logicalcobwebs.cglib.proxy; /** * Dispatching {@link Enhancer} callback. This is identical to the * {@link LazyLoader} interface but needs to be separate so that <code>Enhancer</code> * knows which type of code to generate. */ public interface Dispatcher extends Callback { /** * Return the object which the original method invocation should * be dispatched. This method is called for <b>every</b> method invocation. * @return an object that can invoke the method */ Object loadObject() throws Exception; } --- NEW FILE: DispatcherGenerator.java --- /* * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact ap...@ap.... * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.logicalcobwebs.cglib.proxy; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.*; import org.logicalcobwebs.cglib.core.*; import org.logicalcobwebs.asm.Type; class DispatcherGenerator implements CallbackGenerator { public static final DispatcherGenerator INSTANCE = new DispatcherGenerator(); private static final Type DISPATCHER = TypeUtils.parseType("org.logicalcobwebs.cglib.proxy.Dispatcher"); private static final Signature LOAD_OBJECT = TypeUtils.parseSignature("Object loadObject()"); public void generate(ClassEmitter ce, final Context context) { for (Iterator it = context.getMethods(); it.hasNext();) { Method method = (Method)it.next(); if (Modifier.isProtected(method.getModifiers())) { // ignore protected methods } else { CodeEmitter e = ce.begin_method(context.getModifiers(method), ReflectUtils.getSignature(method), ReflectUtils.getExceptionTypes(method), null); context.emitCallback(e, context.getIndex(method)); e.invoke_interface(DISPATCHER, LOAD_OBJECT); e.checkcast(Type.getType(method.getDeclaringClass())); e.load_args(); e.invoke(method); e.return_value(); e.end_method(); } } } public void generateStatic(CodeEmitter e, Context context) { } } --- NEW FILE: Enhancer.java --- /* * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact ap...@ap.... * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.logicalcobwebs.cglib.proxy; import org.logicalcobwebs.cglib.core.*; import java.lang.reflect.Method; import java.util.*; import org.logicalcobwebs.asm.ClassVisitor; /** * Generates dynamic subclasses to enable method interception. This * class started as a substitute for the standard Dynamic Proxy support * included with JDK 1.3, but one that allowed the proxies to extend a * concrete base class, in addition to implementing interfaces. The dynamically * generated subclasses override the non-final methods of the superclass and * have hooks which callback to user-defined interceptor * implementations. * <p> * The original and most general callback type is the {@link MethodInterceptor}, which * in AOP terms enables "around advice"--that is, you can invoke custom code both before * and after the invocation of the "super" method. In addition you can modify the * arguments before calling the super method, or not call it at all. * <p> * Although <code>MethodInterceptor</code> is generic enough to meet any * interception need, it is often overkill. For simplicity and performance, additional * specialized callback types, such as {@link LazyLoader} are also available. * Often a single callback will be used per enhanced class, but you can control * which callback is used on a per-method basis with a {@link CallbackFilter}. * <p> * The most common uses of this class are embodied in the static helper methods. For * advanced needs, such as customizing the <code>ClassLoader</code> to use, you should create * a new instance of <code>Enhancer</code>. Other classes within CGLIB follow a similar pattern. * <p> * All enhanced objects implement the {@link Factory} interface, unless {@link #setUseFactory} is * used to explicitly disable this feature. The <code>Factory</code> interface provides an API * to change the callbacks of an existing object, as well as a faster and easier way to create * new instances of the same type. * <p> * For an almost drop-in replacement for * <code>java.lang.reflect.Proxy</code>, see the {@link Proxy} class. */ public class Enhancer extends AbstractClassGenerator { private static final Source SOURCE = new Source(Enhancer.class.getName()); private static final EnhancerKey KEY_FACTORY = (EnhancerKey)KeyFactory.create(EnhancerKey.class, KeyFactory.CLASS_BY_NAME); interface EnhancerKey { public Object newInstance(Class type, Class[] interfaces, CallbackFilter filter, Class[] callbackTypes, boolean useFactory); } private Class[] interfaces; private CallbackFilter filter; private Callback[] callbacks; private Class[] callbackTypes; private boolean classOnly; private Class superclass; private Class[] argumentTypes; private Object[] arguments; private boolean useFactory = true; /** * Create a new <code>Enhancer</code>. A new <code>Enhancer</code> * object should be used for each generated object, and should not * be shared across threads. To create additional instances of a * generated class, use the <code>Factory</code> interface. * @see Factory */ public Enhancer() { super(SOURCE); } /** * Set the class which the generated class will extend. As a convenience, * if the supplied superclass is actually an interface, <code>setInterfaces</code> * will be called with the appropriate argument instead. * A non-interface argument must not be declared as final, and must have an * accessible constructor. * @param superclass class to extend or interface to implement * @see #setInterfaces(Class[]) */ public void setSuperclass(Class superclass) { if (superclass != null && superclass.isInterface()) { setInterfaces(new Class[]{ superclass }); } else if (superclass != null && superclass.equals(Object.class)) { // affects choice of ClassLoader this.superclass = null; } else { this.superclass = superclass; } } /** * Set the interfaces to implement. The <code>Factory</code> interface will * always be implemented regardless of what is specified here. * @param interfaces array of interfaces to implement, or null * @see Factory */ public void setInterfaces(Class[] interfaces) { this.interfaces = interfaces; } /** * Set the {@link CallbackFilter} used to map the generated class' methods * to a particular callback index. * New object instances will always use the same mapping, but may use different * actual callback objects. * @param filter the callback filter to use when generating a new class * @see #setCallbacks */ public void setCallbackFilter(CallbackFilter filter) { this.filter = filter; } /** * Set the single {@link Callback} to use. * Ignored if you use {@link #createClass}. * @param callback the callback to use for all methods * @see #setCallbacks */ public void setCallback(final Callback callback) { setCallbacks(new Callback[]{ callback }); } /** * Set the array of callbacks to use. * Ignored if you use {@link #createClass}. * You must use a {@link CallbackFilter} to specify the index into this * array for each method in the proxied class. * @param callbacks the callback array * @see #setCallbackFilter * @see #setCallback */ public void setCallbacks(Callback[] callbacks) { if (callbacks != null && callbacks.length == 0) { throw new IllegalArgumentException("Array cannot be empty"); } this.callbacks = callbacks; } /** * Set whether the enhanced object instances should implement * the {@link Factory} interface. * This was added for tools that need for proxies to be more * indistinguishable from their targets. Also, in some cases it may * be necessary to disable the <code>Factory</code> interface to * prevent code from changing the underlying callbacks. * @param useFactory whether to implement <code>Factory</code>; default is <code>true</code> */ public void setUseFactory(boolean useFactory) { this.useFactory = useFactory; } /** * Set the single type of {@link Callback} to use. * This may be used instead of {@link #setCallback} when calling * {@link #createClass}, since it may not be possible to have * an array of actual callback instances. * @param callbackType the type of callback to use for all methods * @see #setCallbackTypes */ public void setCallbackType(Class callbackType) { setCallbackTypes(new Class[]{ callbackType }); } /** * Set the array of callback types to use. * This may be used instead of {@link #setCallbacks} when calling * {@link #createClass}, since it may not be possible to have * an array of actual callback instances. * You must use a {@link CallbackFilter} to specify the index into this * array for each method in the proxied class. * @param callbackTypes the array of callback types */ public void setCallbackTypes(Class[] callbackTypes) { if (callbackTypes != null && callbackTypes.length == 0) { throw new IllegalArgumentException("Array cannot be empty"); } this.callbackTypes = callbackTypes; } /** * Generate a new class if necessary and uses the specified * callbacks (if any) to create a new object instance. * Uses the no-arg constructor of the superclass. * @return a new instance */ public Object create() { classOnly = false; argumentTypes = null; return createHelper(); } /** * Generate a new class if necessary and uses the specified * callbacks (if any) to create a new object instance. * Uses the constructor of the superclass matching the <code>argumentTypes</code> * parameter, with the given arguments. * @param argumentTypes constructor signature * @param arguments compatible wrapped arguments to pass to constructor * @return a new instance */ public Object create(Class[] argumentTypes, Object[] arguments) { classOnly = false; if (argumentTypes == null || arguments == null || argumentTypes.length != arguments.length) { throw new IllegalArgumentException("Arguments must be non-null and of equal length"); } this.argumentTypes = argumentTypes; this.arguments = arguments; return createHelper(); } /** * Generate a new class if necessary and return it without creating a new instance. * This ignores any callbacks that have been set. * To create a new instance you will have to use reflection, and methods * called during the constructor will not be intercepted. To avoid this problem, * use the multi-arg <code>create</code> method. * @see #create(Class[], Object[]) */ public Class createClass() { classOnly = true; return (Class)createHelper(); } private Object createHelper() { if (classOnly ^ (callbacks == null)) { if (classOnly) { throw new IllegalStateException("createClass does not accept callbacks"); } else { throw new IllegalStateException("callbacks are required unless using createClass"); } } if (callbacks == null && callbackTypes == null) { throw new IllegalStateException("Either callbacks or callback types are always required"); } if (callbacks != null && callbackTypes != null) { if (callbacks.length != callbackTypes.length) { throw new IllegalStateException("Lengths of callback and callback types array must be the same"); } for (int i = 0; i < callbacks.length; i++) { // make sure all classes are callbacks CallbackUtils.getGenerator(callbackTypes[i]); if (callbacks[i] == null) { throw new IllegalStateException("Callback cannot be null"); } if (!callbackTypes[i].isAssignableFrom(callbacks[i].getClass())) { throw new IllegalStateException("Callback " + callbacks[i] + " is not assignable to " + callbackTypes[i]); } } } else if (callbacks != null) { callbackTypes = new Class[callbacks.length]; for (int i = 0; i < callbacks.length; i++) { callbackTypes[i] = CallbackUtils.determineType(callbacks[i]); } } else { for (int i = 0; i < callbackTypes.length; i++) { // make sure all classes are callbacks CallbackUtils.getGenerator(callbackTypes[i]); } } if (filter == null) { if (callbackTypes.length > 1) { throw new IllegalStateException("Multiple callback types possible but no filter specified"); } filter = CallbackFilter.ALL_ZERO; } if (superclass != null) { setNamePrefix(superclass.getName()); } else if (interfaces != null) { setNamePrefix(interfaces[ReflectUtils.findPackageProtected(interfaces)].getName()); } Object key = KEY_FACTORY.newInstance(superclass, interfaces, filter, callbackTypes, useFactory); return super.create(key); } protected ClassLoader getDefaultClassLoader() { if (superclass != null) { return superclass.getClassLoader(); } else if (interfaces != null) { return interfaces[0].getClassLoader(); } else { return null; } } public void generateClass(ClassVisitor v) throws Exception { new EnhancerEmitter(v, getClassName(), superclass, interfaces, filter, callbackTypes, useFactory); } protected Object firstInstance(Class type) throws Exception { if (classOnly) { return type; } else { return createUsingReflection(type); } } protected Object nextInstance(Object instance) { Class protoclass = (instance instanceof Class) ? (Class)instance : instance.getClass(); if (classOnly) { return protoclass; } else if (instance instanceof Factory) { if (argumentTypes != null) { return ((Factory)instance).newInstance(argumentTypes, arguments, callbacks); } else { return ((Factory)instance).newInstance(callbacks); } } else { return createUsingReflection(protoclass); } } private Object createUsingReflection(Class type) { EnhancerEmitter.setThreadCallbacks(type, callbacks); if (argumentTypes != null) { return ReflectUtils.newInstance(type, argumentTypes, arguments); } else { return ReflectUtils.newInstance(type); } } /** * Helper method to create an intercepted object. * For finer control over the generated instance, use a new instance of <code>Enhancer</code> * instead of this static method. * @param type class to extend or interface to implement * @param callback the callback to use for all methods */ public static Object create(Class type, Callback callback) { Enhancer e = new Enhancer(); e.setSuperclass(type); e.setCallback(callback); return e.create(); } /** * Helper method to create an intercepted object. * For finer control over the generated instance, use a new instance of <code>Enhancer</code> * instead of this static method. * @param type class to extend or interface to implement * @param interfaces array of interfaces to implement, or null * @param callback the callback to use for all methods */ public static Object create(Class superclass, Class interfaces[], Callback callback) { Enhancer e = new Enhancer(); e.setSuperclass(superclass); e.setInterfaces(interfaces); e.setCallback(callback); return e.create(); } /** * Helper method to create an intercepted object. * For finer control over the generated instance, use a new instance of <code>Enhancer</code> * instead of this static method. * @param type class to extend or interface to implement * @param interfaces array of interfaces to implement, or null * @param filter the callback filter to use when generating a new class * @param callbacks callback implementations to use for the enhanced object */ public static Object create(Class superclass, Class[] interfaces, CallbackFilter filter, Callback[] callbacks) { Enhancer e = new Enhancer(); e.setSuperclass(superclass); e.setInterfaces(interfaces); e.setCallbackFilter(filter); e.setCallbacks(callbacks); return e.create(); } } --- NEW FILE: EnhancerEmitter.java --- /* * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact ap...@ap.... * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.logicalcobwebs.cglib.proxy; import java.io.ObjectStreamException; import java.lang.reflect.*; import java.util.*; import org.logicalcobwebs.cglib.core.*; import org.logicalcobwebs.asm.ClassVisitor; import org.logicalcobwebs.asm.Label; import org.logicalcobwebs.asm.Type; class EnhancerEmitter extends ClassEmitter { private static final String CONSTRUCTED_FIELD = "CGLIB$CONSTRUCTED"; private static final String SET_THREAD_CALLBACKS_NAME = "CGLIB$SET_THREAD_CALLBACKS"; private static final Type ILLEGAL_STATE_EXCEPTION = TypeUtils.parseType("IllegalStateException"); private static final Type ILLEGAL_ARGUMENT_EXCEPTION = TypeUtils.parseType("IllegalArgumentException"); private static final Type THREAD_LOCAL = TypeUtils.parseType("ThreadLocal"); private static final Type FACTORY = TypeUtils.parseType("org.logicalcobwebs.cglib.proxy.Factory"); private static final Signature CSTRUCT_NULL = TypeUtils.parseConstructor(""); private static final Signature SET_THREAD_CALLBACKS = TypeUtils.parseSignature("void " + SET_THREAD_CALLBACKS_NAME + "(org.logicalcobwebs.cglib.proxy.Callback[])"); private static final Signature NEW_INSTANCE = TypeUtils.parseSignature("Object newInstance(org.logicalcobwebs.cglib.proxy.Callback[])"); private static final Signature MULTIARG_NEW_INSTANCE = TypeUtils.parseSignature("Object newInstance(Class[], Object[], org.logicalcobwebs.cglib.proxy.Callback[])"); private static final Signature SINGLE_NEW_INSTANCE = TypeUtils.parseSignature("Object newInstance(org.logicalcobwebs.cglib.proxy.Callback)"); private static final Signature COPY_NEW_INSTANCE = TypeUtils.parseSignature("Object newInstance()"); private static final Signature COPY_MULTIARG_NEW_INSTANCE = TypeUtils.parseSignature("Object newInstance(Class[], Object[])"); private static final Signature SET_CALLBACK = TypeUtils.parseSignature("void setCallback(int, org.logicalcobwebs.cglib.proxy.Callback)"); private static final Signature GET_CALLBACK = TypeUtils.parseSignature("org.logicalcobwebs.cglib.proxy.Callback getCallback(int)"); private static final Signature SET_CALLBACKS = TypeUtils.parseSignature("void setCallbacks(org.logicalcobwebs.cglib.proxy.Callback[])"); private static final Signature THREAD_LOCAL_GET = TypeUtils.parseSignature("Object get()"); private static final Signature THREAD_LOCAL_SET = TypeUtils.parseSignature("void set(Object)"); private Class[] callbackTypes; public EnhancerEmitter(ClassVisitor v, String className, Class superclass, Class[] interfaces, CallbackFilter filter, Class[] callbackTypes, boolean useFactory) throws Exception { super(v); if (superclass == null) { superclass = Object.class; } this.callbackTypes = callbackTypes; begin_class(Constants.ACC_PUBLIC, className, Type.getType(superclass), (useFactory ? TypeUtils.add(TypeUtils.getTypes(interfaces), FACTORY) : TypeUtils.getTypes(interfaces)), Constants.SOURCE_FILE); List clist = new ArrayList(Arrays.asList(superclass.getDeclaredConstructors())); CollectionUtils.filter(clist, new VisibilityPredicate(superclass, true)); if (clist.size() == 0) { throw new IllegalArgumentException("No visible constructors in " + superclass); } Constructor[] constructors = (Constructor[])clist.toArray(new Constructor[clist.size()]); // Order is very important: must add superclass, then // its superclass chain, then each interface and // its superinterfaces. List methods = new ArrayList(); ReflectUtils.addAllMethods(superclass, methods); List interfaceMethods = new ArrayList(); if (interfaces != null) { for (int i = 0; i < interfaces.length; i++) { if (interfaces[i] != Factory.class) { ReflectUtils.addAllMethods(interfaces[i], interfaceMethods); } } } Set forcePublic = MethodWrapper.createSet(interfaceMethods); methods.addAll(interfaceMethods); CollectionUtils.filter(methods, new VisibilityPredicate(superclass, true)); CollectionUtils.filter(methods, new DuplicatesPredicate()); removeFinal(methods); Map groups = new HashMap(); Map indexes = new HashMap(); for (Iterator it = methods.iterator(); it.hasNext();) { Method method = (Method)it.next(); int index = filter.accept(method); if (index >= callbackTypes.length) { throw new IllegalArgumentException("Callback filter returned an index that is too large: " + index); } indexes.put(method, new Integer(index)); Object gen = CallbackUtils.getGenerator(callbackTypes[index]); List group = (List)groups.get(gen); if (group == null) { groups.put(gen, group = new ArrayList(methods.size())); } group.add(method); } declare_field(Constants.ACC_PRIVATE, CONSTRUCTED_FIELD, Type.BOOLEAN_TYPE, null, null); emitMethods(groups, indexes, forcePublic); emitConstructors(constructors); emitSetThreadCallbacks(); if (useFactory) { int[] keys = getCallbackKeys(); emitNewInstanceCallbacks(); emitNewInstanceCallback(); emitNewInstanceMultiarg(constructors); emitNewInstanceCopy(); emitNewInstanceMultiargCopy(constructors); emitGetCallback(keys); emitSetCallback(keys); emitSetCallbacks(); } end_class(); } static void setThreadCallbacks(Class type, Callback[] callbacks) { // TODO: optimize try { Method setter = type.getDeclaredMethod(SET_THREAD_CALLBACKS_NAME, new Class[]{ Callback[].class }); setter.invoke(null, new Object[]{ callbacks }); } catch (NoSuchMethodException e) { throw new IllegalArgumentException(type + " is not an enhanced class"); } catch (IllegalAccessException e) { throw new CodeGenerationException(e); } catch (InvocationTargetException e) { throw new CodeGenerationException(e); } } private void emitConstructors(Constructor[] constructors) { for (int i = 0; i < constructors.length; i++) { Signature sig = ReflectUtils.getSignature(constructors[i]); CodeEmitter e = begin_method(Constants.ACC_PUBLIC, sig, ReflectUtils.getExceptionTypes(constructors[i]), null); e.load_this(); e.dup(); e.load_args(); e.super_invoke_constructor(sig); e.push(1); e.putfield(CONSTRUCTED_FIELD); for (int j = 0; j < callbackTypes.length; j++) { e.load_this(); e.dup(); e.getfield(getThreadLocal(j)); e.invoke_virtual(THREAD_LOCAL, THREAD_LOCAL_GET); e.checkcast(Type.getType(callbackTypes[j])); e.putfield(getCallbackField(j)); // clear thread-locals; TODO: test! e.getfield(getThreadLocal(j)); e.aconst_null(); e.invoke_virtual(THREAD_LOCAL, THREAD_LOCAL_SET); } e.return_value(); e.end_method(); } } private int[] getCallbackKeys() { int[] keys = new int[callbackTypes.length]; for (int i = 0; i < callbackTypes.length; i++) { keys[i] = i; } return keys; } private void emitGetCallback(int[] keys) { final CodeEmitter e = begin_method(Constants.ACC_PUBLIC, GET_CALLBACK, null, null); e.load_this(); e.load_arg(0); e.process_switch(keys, new ProcessSwitchCallback() { public void processCase(int key, Label end) { e.getfield(getCallbackField(key)); e.goTo(end); } public void processDefault() { e.pop(); // stack height e.aconst_null(); } }); e.return_value(); e.end_method(); } private void emitSetCallback(int[] keys) { final CodeEmitter e = begin_method(Constants.ACC_PUBLIC, SET_CALLBACK, null, null); e.load_this(); e.load_arg(1); e.dup(); e.load_arg(0); e.process_switch(keys, new ProcessSwitchCallback() { public void processCase(int key, Label end) { // we set thread locals too in case this method is called from within constructor (as Proxy does) e.getfield(getThreadLocal(key)); e.swap(); e.invoke_virtual(THREAD_LOCAL, THREAD_LOCAL_SET); e.checkcast(Type.getType(callbackTypes[key])); e.putfield(getCallbackField(key)); e.goTo(end); } public void processDefault() { // stack height e.pop2(); e.pop(); } }); e.return_value(); e.end_method(); } private void emitSetCallbacks() { CodeEmitter e = begin_method(Constants.ACC_PUBLIC, SET_CALLBACKS, null, null); emitSetThreadCallbacks(e); e.load_this(); e.load_arg(0); for (int i = 0; i < callbackTypes.length; i++) { e.dup2(); e.aaload(i); e.checkcast(Type.getType(callbackTypes[i])); e.putfield(getCallbackField(i)); } e.return_value(); e.end_method(); } private void emitNewInstanceCallbacks() { CodeEmitter e = begin_method(Constants.ACC_PUBLIC, NEW_INSTANCE, null, null); e.load_arg(0); e.invoke_static_this(SET_THREAD_CALLBACKS); emitCommonNewInstance(e); } private void emitNewInstanceCopy() { CodeEmitter e = begin_method(Constants.ACC_PUBLIC, COPY_NEW_INSTANCE, null, null); emitCopyCallbacks(e); emitCommonNewInstance(e); } private void emitCopyCallbacks(CodeEmitter e) { for (int i = 0; i < callbackTypes.length; i++) { e.getfield(getThreadLocal(i)); e.load_this(); e.getfield(getCallbackField(i)); e.invoke_virtual(THREAD_LOCAL, THREAD_LOCAL_SET); } } private void emitCommonNewInstance(CodeEmitter e) { e.new_instance_this(); e.dup(); e.invoke_constructor_this(); e.return_value(); e.end_method(); } private void emitNewInstanceCallback() { CodeEmitter e = begin_method(Constants.ACC_PUBLIC, SINGLE_NEW_INSTANCE, null, null); switch (callbackTypes.length) { case 0: // TODO: make sure Callback is null break; case 1: e.getfield(getThreadLocal(0)); e.load_arg(0); e.invoke_virtual(THREAD_LOCAL, THREAD_LOCAL_SET); break; default: e.throw_exception(ILLEGAL_STATE_EXCEPTION, "More than one callback object required"); } emitCommonNewInstance(e); } private void emitNewInstanceMultiarg(Constructor[] constructors) { CodeEmitter e = begin_method(Constants.ACC_PUBLIC, MULTIARG_NEW_INSTANCE, null, null); e.load_arg(2); e.invoke_static_this(SET_THREAD_CALLBACKS); emitCommonMultiarg(constructors, e); } private void emitNewInstanceMultiargCopy(Constructor[] constructors) { CodeEmitter e = begin_method(Constants.ACC_PUBLIC, COPY_MULTIARG_NEW_INSTANCE, null, null); emitCopyCallbacks(e); emitCommonMultiarg(constructors, e); } private void emitCommonMultiarg(Constructor[] constructors, final CodeEmitter e) { e.new_instance_this(); e.dup(); e.load_arg(0); EmitUtils.constructor_switch(e, constructors, new ObjectSwitchCallback() { public void processCase(Object key, Label end) { Constructor constructor = (Constructor)key; Type types[] = TypeUtils.getTypes(constructor.getParameterTypes()); for (int i = 0; i < types.length; i++) { e.load_arg(1); e.push(i); e.aaload(); e.unbox(types[i]); } e.invoke_constructor_this(ReflectUtils.getSignature(constructor)); e.goTo(end); } public void processDefault() { e.throw_exception(ILLEGAL_ARGUMENT_EXCEPTION, "Constructor not found"); } }); e.return_value(); e.end_method(); } private void emitMethods(Map groups, final Map indexes, final Set forcePublic) throws Exception { for (int i = 0; i < callbackTypes.length; i++) { declare_field(Constants.ACC_PRIVATE, getCallbackField(i), Type.getType(callbackTypes[i]), null, null); declare_field(Constants.PRIVATE_FINAL_STATIC, getThreadLocal(i), THREAD_LOCAL, null, null); } Set seenGen = new HashSet(); CodeEmitter e = begin_static(); for (int i = 0; i < callbackTypes.length; i++) { e.new_instance(THREAD_LOCAL); e.dup(); e.invoke_constructor(THREAD_LOCAL, CSTRUCT_NULL); e.putfield(getThreadLocal(i)); CallbackGenerator gen = CallbackUtils.getGenerator(callbackTypes[i]); if (!seenGen.contains(gen)) { seenGen.add(gen); final List fmethods = (List)groups.get(gen); CallbackGenerator.Context context = new CallbackGenerator.Context() { public Iterator getMethods() { return fmethods.iterator(); } public int getIndex(Method method) { return ((Integer)indexes.get(method)).intValue(); } public void emitCallback(CodeEmitter e, int index) { emitCurrentCallback(e, index); } public int getModifiers(Method method) { int modifiers = Constants.ACC_FINAL | (method.getModifiers() & ~Constants.ACC_ABSTRACT & ~Constants.ACC_NATIVE & ~Constants.ACC_SYNCHRONIZED); if (forcePublic.contains(MethodWrapper.create(method))) { modifiers = (modifiers & ~Constants.ACC_PROTECTED) | Constants.ACC_PUBLIC; } return modifiers; } // TODO: this is probably slow public String getUniqueName(Method method) { return method.getName() + "_" + fmethods.indexOf(method); } }; gen.generate(this, context); gen.generateStatic(e, context); } } e.return_value(); e.end_method(); } private void emitSetThreadCallbacks() { CodeEmitter e = begin_method(Constants.ACC_PUBLIC | Constants.ACC_STATIC, SET_THREAD_CALLBACKS, null, null); emitSetThreadCallbacks(e); e.return_value(); e.end_method(); } private void emitSetThreadCallbacks(CodeEmitter e) { for (int i = 0; i < callbackTypes.length; i++) { e.getfield(getThreadLocal(i)); e.load_arg(0); e.aaload(i); e.invoke_virtual(THREAD_LOCAL, THREAD_LOCAL_SET); } } private void emitCurrentCallback(CodeEmitter e, int index) { e.load_this(); e.getfield(getCallbackField(index)); e.dup(); Label end = e.make_label(); e.ifnonnull(end); e.load_this(); e.getfield(CONSTRUCTED_FIELD); e.if_jump(e.NE, end); e.pop(); e.getfield(getThreadLocal(index)); e.invoke_virtual(THREAD_LOCAL, THREAD_LOCAL_GET); e.checkcast(Type.getType(callbackTypes[index])); e.mark(end); } private static String getCallbackField(int index) { return "CGLIB$CALLBACK_" + index; } private static String getThreadLocal(int index) { return "CGLIB$TL_CALLBACK_" + index; } private static void removeFinal(List list) { CollectionUtils.filter(list, new Predicate() { public boolean evaluate(Object arg) { return !Modifier.isFinal(((Method)arg).getModifiers()); } }); } } --- NEW FILE: Factory.java --- /* *... [truncated message content] |
|
From: <bil...@us...> - 2003-12-12 19:28:17
|
Update of /cvsroot/proxool/proxool/src/java/org/logicalcobwebs/cglib/reflect In directory sc8-pr-cvs1:/tmp/cvs-serv25673/src/java/org/logicalcobwebs/cglib/reflect Added Files: ConstructorDelegate.java FastClass.java FastClassEmitter.java FastConstructor.java FastMember.java FastMethod.java MethodDelegate.java MulticastDelegate.java Log Message: Repackaged Cglib project --- NEW FILE: ConstructorDelegate.java --- /* * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact ap...@ap.... * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.logicalcobwebs.cglib.reflect; import java.lang.reflect.*; import org.logicalcobwebs.cglib.core.*; import org.logicalcobwebs.asm.ClassVisitor; import org.logicalcobwebs.asm.Type; /** * @author Chris Nokleberg * @version $Id: ConstructorDelegate.java,v 1.1 2003/12/12 19:28:13 billhorsman Exp $ */ abstract public class ConstructorDelegate { private static final ConstructorKey KEY_FACTORY = (ConstructorKey)KeyFactory.create(ConstructorKey.class, KeyFactory.CLASS_BY_NAME); interface ConstructorKey { public Object newInstance(Class declaring, Class iface); } protected ConstructorDelegate() { } public static ConstructorDelegate create(Class targetClass, Class iface) { Generator gen = new Generator(); gen.setTargetClass(targetClass); gen.setInterface(iface); return gen.create(); } public static class Generator extends AbstractClassGenerator { private static final Source SOURCE = new Source(ConstructorDelegate.class.getName()); private static final Type CONSTRUCTOR_DELEGATE = TypeUtils.parseType("org.logicalcobwebs.cglib.reflect.ConstructorDelegate"); private Class iface; private Class targetClass; public Generator() { super(SOURCE); } public void setInterface(Class iface) { this.iface = iface; } public void setTargetClass(Class targetClass) { this.targetClass = targetClass; } public ConstructorDelegate create() { setNamePrefix(targetClass.getName()); Object key = KEY_FACTORY.newInstance(iface, targetClass); return (ConstructorDelegate)super.create(key); } protected ClassLoader getDefaultClassLoader() { return targetClass.getClassLoader(); } public void generateClass(ClassVisitor v) { setNamePrefix(targetClass.getName()); final Method newInstance = ReflectUtils.findNewInstance(iface); if (!newInstance.getReturnType().isAssignableFrom(targetClass)) { throw new IllegalArgumentException("incompatible return type"); } final Constructor constructor; try { constructor = targetClass.getDeclaredConstructor(newInstance.getParameterTypes()); } catch (NoSuchMethodException e) { throw new IllegalArgumentException("interface does not match any known constructor"); } ClassEmitter ce = new ClassEmitter(v); ce.begin_class(Constants.ACC_PUBLIC, getClassName(), CONSTRUCTOR_DELEGATE, new Type[]{ Type.getType(iface) }, Constants.SOURCE_FILE); Type declaring = Type.getType(constructor.getDeclaringClass()); EmitUtils.null_constructor(ce); CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, ReflectUtils.getSignature(newInstance), ReflectUtils.getExceptionTypes(newInstance), null); e.new_instance(declaring); e.dup(); e.load_args(); e.invoke_constructor(declaring, ReflectUtils.getSignature(constructor)); e.return_value(); e.end_method(); ce.end_class(); } protected Object firstInstance(Class type) { return ReflectUtils.newInstance(type); } protected Object nextInstance(Object instance) { return instance; } } } --- NEW FILE: FastClass.java --- /* * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact ap...@ap.... * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.logicalcobwebs.cglib.reflect; import org.logicalcobwebs.cglib.core.*; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import org.logicalcobwebs.asm.ClassVisitor; import org.logicalcobwebs.asm.Type; abstract public class FastClass { private Class type; protected FastClass(Class type) { this.type = type; } public static FastClass create(Class type) { Generator gen = new Generator(); gen.setType(type); return gen.create(); } public static class Generator extends AbstractClassGenerator { private static final Source SOURCE = new Source(FastClass.class.getName()); private Class type; public Generator() { super(SOURCE); } public void setType(Class type) { this.type = type; } public FastClass create() { setNamePrefix(type.getName()); return (FastClass)super.create(type.getName()); } protected ClassLoader getDefaultClassLoader() { return type.getClassLoader(); } public void generateClass(ClassVisitor v) throws Exception { new FastClassEmitter(v, getClassName(), type); } protected Object firstInstance(Class type) { return ReflectUtils.newInstance(type, new Class[]{ Class.class }, new Object[]{ this.type }); } protected Object nextInstance(Object instance) { return instance; } } public Object invoke(String name, Class[] parameterTypes, Object obj, Object[] args) throws InvocationTargetException { return invoke(getIndex(name, parameterTypes), obj, args); } public Object newInstance() throws InvocationTargetException { return newInstance(getIndex(Constants.EMPTY_CLASS_ARRAY), null); } public Object newInstance(Class[] parameterTypes, Object[] args) throws InvocationTargetException { return newInstance(getIndex(parameterTypes), args); } public FastMethod getMethod(Method method) { return new FastMethod(this, method); } public FastConstructor getConstructor(Constructor constructor) { return new FastConstructor(this, constructor); } public FastMethod getMethod(String name, Class[] parameterTypes) { try { return getMethod(type.getMethod(name, parameterTypes)); } catch (NoSuchMethodException e) { throw new NoSuchMethodError(e.getMessage()); } } public FastConstructor getConstructor(Class[] parameterTypes) { try { return getConstructor(type.getConstructor(parameterTypes)); } catch (NoSuchMethodException e) { throw new NoSuchMethodError(e.getMessage()); } } public String getName() { return type.getName(); } public Class getJavaClass() { return type; } public String toString() { return type.toString(); } public int hashCode() { return type.hashCode(); } public boolean equals(Object o) { if (o == null || !(o instanceof FastClass)) { return false; } return type.equals(((FastClass)o).type); } /** * Return the index of the matching method. The index may be used * later to invoke the method with less overhead. If more than one * method matches (i.e. they differ by return type only), one is * chosen arbitrarily. * @see #invoke(int, Object, Object[]) * @param name the method name * @param parameterTypes the parameter array * @return the index, or <code>-1</code> if none is found. */ abstract public int getIndex(String name, Class[] parameterTypes); /** * Return the index of the matching constructor. The index may be used * later to create a new instance with less overhead. * @see #newInstance(int, Object[]) * @param parameterTypes the parameter array * @return the constructor index, or <code>-1</code> if none is found. */ abstract public int getIndex(Class[] parameterTypes); /** * Invoke the method with the specified index. * @see getIndex(name, Class[]) * @param index the method index * @param obj the object the underlying method is invoked from * @param args the arguments used for the method call * @throws java.lang.reflect.InvocationTargetException if the underlying method throws an exception */ abstract public Object invoke(int index, Object obj, Object[] args) throws InvocationTargetException; /** * Create a new instance using the specified constructor index and arguments. * @see getIndex(Class[]) * @param index the constructor index * @param args the arguments passed to the constructor * @throws java.lang.reflect.InvocationTargetException if the constructor throws an exception */ abstract public Object newInstance(int index, Object[] args) throws InvocationTargetException; abstract public int getIndex(Signature sig); /** * Returns the maximum method index for this class. */ abstract public int getMaxIndex(); protected static String getSignatureWithoutReturnType(String name, Class[] parameterTypes) { StringBuffer sb = new StringBuffer(); sb.append(name); sb.append('('); for (int i = 0; i < parameterTypes.length; i++) { sb.append(Type.getDescriptor(parameterTypes[i])); } sb.append(')'); return sb.toString(); } } --- NEW FILE: FastClassEmitter.java --- /* * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact ap...@ap.... * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.logicalcobwebs.cglib.reflect; import java.lang.reflect.*; import java.util.*; import org.logicalcobwebs.cglib.core.*; import org.logicalcobwebs.asm.ClassVisitor; import org.logicalcobwebs.asm.Label; import org.logicalcobwebs.asm.Type; class FastClassEmitter extends ClassEmitter { private static final Signature CSTRUCT_CLASS = TypeUtils.parseConstructor("Class"); private static final Signature METHOD_GET_INDEX = TypeUtils.parseSignature("int getIndex(String, Class[])"); private static final Signature SIGNATURE_GET_INDEX = TypeUtils.parseSignature("int getIndex(org.logicalcobwebs.cglib.core.Signature)"); private static final Signature TO_STRING = TypeUtils.parseSignature("String toString()"); private static final Signature CONSTRUCTOR_GET_INDEX = TypeUtils.parseSignature("int getIndex(Class[])"); private static final Signature INVOKE = TypeUtils.parseSignature("Object invoke(int, Object, Object[])"); private static final Signature NEW_INSTANCE = TypeUtils.parseSignature("Object newInstance(int, Object[])"); private static final Signature GET_MAX_INDEX = TypeUtils.parseSignature("int getMaxIndex()"); private static final Signature GET_SIGNATURE_WITHOUT_RETURN_TYPE = TypeUtils.parseSignature("String getSignatureWithoutReturnType(String, Class[])"); private static final Type FAST_CLASS = TypeUtils.parseType("org.logicalcobwebs.cglib.reflect.FastClass"); private static final Type ILLEGAL_ARGUMENT_EXCEPTION = TypeUtils.parseType("IllegalArgumentException"); private static final Type INVOCATION_TARGET_EXCEPTION = TypeUtils.parseType("java.lang.reflect.InvocationTargetException"); private static final Type[] INVOCATION_TARGET_EXCEPTION_ARRAY = { INVOCATION_TARGET_EXCEPTION }; public FastClassEmitter(ClassVisitor v, String className, Class type) { super(v); begin_class(Constants.ACC_PUBLIC, className, FAST_CLASS, null, Constants.SOURCE_FILE); // constructor CodeEmitter e = begin_method(Constants.ACC_PUBLIC, CSTRUCT_CLASS, null, null); e.load_this(); e.load_args(); e.super_invoke_constructor(CSTRUCT_CLASS); e.return_value(); e.end_method(); VisibilityPredicate vp = new VisibilityPredicate(type, false); List methodList = ReflectUtils.addAllMethods(type, new ArrayList()); CollectionUtils.filter(methodList, vp); CollectionUtils.filter(methodList, new DuplicatesPredicate()); final Method[] methods = (Method[])methodList.toArray(new Method[methodList.size()]); final Constructor[] constructors = (Constructor[])CollectionUtils.filter(type.getDeclaredConstructors(), vp); // getIndex(String) emitIndexBySignature(methods); // getIndex(String, Class[]) emitIndexByClassArray(methods); // getIndex(Class[]) e = begin_method(Constants.ACC_PUBLIC, CONSTRUCTOR_GET_INDEX, null, null); e.load_args(); EmitUtils.constructor_switch(e, constructors, new GetIndexCallback(e, constructors)); e.end_method(); // invoke(int, Object, Object[]) e = begin_method(Constants.ACC_PUBLIC, INVOKE, INVOCATION_TARGET_EXCEPTION_ARRAY, null); e.load_arg(1); e.checkcast(Type.getType(type)); e.load_arg(0); invokeSwitchHelper(e, methods, 2); e.end_method(); // newInstance(int, Object[]) e = begin_method(Constants.ACC_PUBLIC, NEW_INSTANCE, INVOCATION_TARGET_EXCEPTION_ARRAY, null); e.new_instance(Type.getType(type)); e.dup(); e.load_arg(0); invokeSwitchHelper(e, constructors, 1); e.end_method(); // getMaxIndex() e = begin_method(Constants.ACC_PUBLIC, GET_MAX_INDEX, null, null); e.push(methods.length - 1); e.return_value(); e.end_method(); end_class(); } // TODO: support constructor indices ("<init>") private void emitIndexBySignature(Method[] methods) { CodeEmitter e = begin_method(Constants.ACC_PUBLIC, SIGNATURE_GET_INDEX, null, null); List signatures = CollectionUtils.transform(Arrays.asList(methods), new Transformer() { public Object transform(Object obj) { return ReflectUtils.getSignature((Method)obj).toString(); } }); e.load_arg(0); e.invoke_virtual(Constants.TYPE_OBJECT, TO_STRING); signatureSwitchHelper(e, signatures); e.end_method(); } private static final int TOO_MANY_METHODS = 100; // TODO private void emitIndexByClassArray(Method[] methods) { CodeEmitter e = begin_method(Constants.ACC_PUBLIC, METHOD_GET_INDEX, null, null); if (methods.length > TOO_MANY_METHODS) { // hack for big classes List signatures = CollectionUtils.transform(Arrays.asList(methods), new Transformer() { public Object transform(Object obj) { String s = ReflectUtils.getSignature((Method)obj).toString(); return s.substring(0, s.lastIndexOf(')') + 1); } }); e.load_args(); e.invoke_static(FAST_CLASS, GET_SIGNATURE_WITHOUT_RETURN_TYPE); signatureSwitchHelper(e, signatures); } else { e.load_args(); EmitUtils.method_switch(e, methods, new GetIndexCallback(e, methods)); } e.end_method(); } private void signatureSwitchHelper(final CodeEmitter e, final List signatures) { ObjectSwitchCallback callback = new ObjectSwitchCallback() { public void processCase(Object key, Label end) { // TODO: remove linear indexOf e.push(signatures.indexOf(key)); e.return_value(); } public void processDefault() { e.push(-1); e.return_value(); } }; EmitUtils.string_switch(e, (String[])signatures.toArray(new String[signatures.size()]), Constants.SWITCH_STYLE_HASH, callback); } private static void invokeSwitchHelper(final CodeEmitter e, final Object[] members, final int arg) { final Label illegalArg = e.make_label(); Block block = e.begin_block(); e.process_switch(getIntRange(members.length), new ProcessSwitchCallback() { public void processCase(int key, Label end) { Member member = (Member)members[key]; Signature sig = ReflectUtils.getSignature(member); Type[] types = sig.getArgumentTypes(); for (int i = 0; i < types.length; i++) { e.load_arg(arg); e.aaload(i); e.unbox(types[i]); } if (member instanceof Method) { e.invoke((Method)member); e.box(Type.getType(((Method)member).getReturnType())); } else { e.invoke_constructor(Type.getType(member.getDeclaringClass()), sig); } e.return_value(); } public void processDefault() { e.goTo(illegalArg); } }); block.end(); EmitUtils.wrap_throwable(block, INVOCATION_TARGET_EXCEPTION); e.mark(illegalArg); e.throw_exception(ILLEGAL_ARGUMENT_EXCEPTION, "Cannot find matching method/constructor"); } private static class GetIndexCallback implements ObjectSwitchCallback { private CodeEmitter e; private Map indexes = new HashMap(); public GetIndexCallback(CodeEmitter e, Object[] members) { this.e = e; for (int i = 0; i < members.length; i++) { indexes.put(members[i], new Integer(i)); } } public void processCase(Object key, Label end) { e.push(((Integer)indexes.get(key)).intValue()); e.return_value(); } public void processDefault() { e.push(-1); e.return_value(); } } private static int[] getIntRange(int length) { int[] range = new int[length]; for (int i = 0; i < length; i++) { range[i] = i; } return range; } } --- NEW FILE: FastConstructor.java --- /* * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact ap...@ap.... * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.logicalcobwebs.cglib.reflect; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; public class FastConstructor extends FastMember { FastConstructor(FastClass fc, Constructor constructor) { super(fc, constructor, fc.getIndex(constructor.getParameterTypes())); } public Class[] getParameterTypes() { return ((Constructor)member).getParameterTypes(); } public Class[] getExceptionTypes() { return ((Constructor)member).getExceptionTypes(); } public Object newInstance() throws InvocationTargetException { return fc.newInstance(index, null); } public Object newInstance(Object[] args) throws InvocationTargetException { return fc.newInstance(index, args); } public Constructor getJavaConstructor() { return (Constructor)member; } } --- NEW FILE: FastMember.java --- /* * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact ap...@ap.... * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.logicalcobwebs.cglib.reflect; import java.lang.reflect.Member; abstract public class FastMember { protected FastClass fc; protected Member member; protected int index; protected FastMember(FastClass fc, Member member, int index) { this.fc = fc; this.member = member; this.index = index; } abstract public Class[] getParameterTypes(); abstract public Class[] getExceptionTypes(); public int getIndex() { return index; } public String getName() { return member.getName(); } public Class getDeclaringClass() { return fc.getJavaClass(); } public int getModifiers() { return member.getModifiers(); } public String toString() { return member.toString(); } public int hashCode() { return member.hashCode(); } public boolean equals(Object o) { if (o == null || !(o instanceof FastMember)) { return false; } return member.equals(((FastMember)o).member); } } --- NEW FILE: FastMethod.java --- /* * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact ap...@ap.... * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.logicalcobwebs.cglib.reflect; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class FastMethod extends FastMember { FastMethod(FastClass fc, Method method) { super(fc, method, helper(fc, method)); } private static int helper(FastClass fc, Method method) { try { return fc.getIndex(method.getName(), method.getParameterTypes()); } catch (Error e) { System.err.println("Caught error " + e + " LOOKING UP INDEX name=" + method.getName() + " types=" + java.util.Arrays.asList(method.getParameterTypes()) + " in class " + fc.getClass().getName()); throw e; } } public Class getReturnType() { return ((Method)member).getReturnType(); } public Class[] getParameterTypes() { return ((Method)member).getParameterTypes(); } public Class[] getExceptionTypes() { return ((Method)member).getExceptionTypes(); } public Object invoke(Object obj, Object[] args) throws InvocationTargetException { return fc.invoke(index, obj, args); } public Method getJavaMethod() { return (Method)member; } } --- NEW FILE: MethodDelegate.java --- /* * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact ap...@ap.... * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.logicalcobwebs.cglib.reflect; import java.lang.reflect.*; import org.logicalcobwebs.cglib.*; import org.logicalcobwebs.cglib.core.*; import org.logicalcobwebs.asm.ClassVisitor; import org.logicalcobwebs.asm.Type; // TODO: don't require exact match for return type /** * <b>DOCUMENTATION FROM APACHE AVALON DELEGATE CLASS</b> * * <p> * Delegates are a typesafe pointer to another method. Since Java does not * have language support for such a construct, this utility will construct * a proxy that forwards method calls to any method with the same signature. * This utility is inspired in part by the C# delegate mechanism. We * implemented it in a Java-centric manner. * </p> * * <h2>Delegate</h2> * <p> * Any interface with one method can become the interface for a delegate. * Consider the example below: * </p> * * <pre> * public interface MainDelegate { * int main(String[] args); * } * </pre> * * <p> * The interface above is an example of an interface that can become a * delegate. It has only one method, and the interface is public. In * order to create a delegate for that method, all we have to do is * call <code>MethodDelegate.create(this, "alternateMain", MainDelegate.class)</code>. * The following program will show how to use it: * </p> * * <pre> * public class Main { * public static int main( String[] args ) { * Main newMain = new Main(); * MainDelegate start = (MainDelegate) * MethodDelegate.create(newMain, "alternateMain", MainDelegate.class); * return start.main( args ); * } * * public int alternateMain( String[] args ) { * for (int i = 0; i < args.length; i++) { * System.out.println( args[i] ); * } * return args.length; * } * } * </pre> * * <p> * By themselves, delegates don't do much. Their true power lies in the fact that * they can be treated like objects, and passed to other methods. In fact that is * one of the key building blocks of building Intelligent Agents which in tern are * the foundation of artificial intelligence. In the above program, we could have * easily created the delegate to match the static <code>main</code> method by * substituting the delegate creation call with this: * <code>MethodDelegate.createStatic(getClass(), "main", MainDelegate.class)</code>. * </p> * <p> * Another key use for Delegates is to register event listeners. It is much easier * to have all the code for your events separated out into methods instead of individual * classes. One of the ways Java gets around that is to create anonymous classes. * They are particularly troublesome because many Debuggers do not know what to do * with them. Anonymous classes tend to duplicate alot of code as well. We can * use any interface with one declared method to forward events to any method that * matches the signature (although the method name can be different). * </p> * * <h3>Equality</h3> * The criteria that we use to test if two delegates are equal are: * <ul> * <li> * They both refer to the same instance. That is, the <code>instance</code> * parameter passed to the newDelegate method was the same for both. The * instances are compared with the identity equality operator, <code>==</code>. * </li> * <li>They refer to the same method as resolved by <code>Method.equals</code>.</li> * </ul> * * @version $Id: MethodDelegate.java,v 1.1 2003/12/12 19:28:13 billhorsman Exp $ */ abstract public class MethodDelegate { private static final MethodDelegateKey KEY_FACTORY = (MethodDelegateKey)KeyFactory.create(MethodDelegateKey.class, KeyFactory.CLASS_BY_NAME); protected Object target; protected String eqMethod; interface MethodDelegateKey { Object newInstance(Class delegateClass, String methodName, Class iface); } public static MethodDelegate createStatic(Class targetClass, String methodName, Class iface) { Generator gen = new Generator(); gen.setTargetClass(targetClass); gen.setMethodName(methodName); gen.setInterface(iface); return gen.create(); } public static MethodDelegate create(Object target, String methodName, Class iface) { Generator gen = new Generator(); gen.setTarget(target); gen.setMethodName(methodName); gen.setInterface(iface); return gen.create(); } public boolean equals(Object obj) { MethodDelegate other = (MethodDelegate)obj; return target == other.target && eqMethod.equals(other.eqMethod); } public int hashCode() { return target.hashCode() ^ eqMethod.hashCode(); } public Object getTarget() { return target; } abstract public MethodDelegate newInstance(Object target); public static class Generator extends AbstractClassGenerator { private static final Source SOURCE = new Source(MethodDelegate.class.getName()); private static final Signature NEW_INSTANCE = TypeUtils.parseSignature("org.logicalcobwebs.cglib.reflect.MethodDelegate newInstance(Object)"); private static final Type METHOD_DELEGATE = TypeUtils.parseType("org.logicalcobwebs.cglib.reflect.MethodDelegate"); private Object target; private Class targetClass; private String methodName; private Class iface; public Generator() { super(SOURCE); } public void setTarget(Object target) { this.target = target; this.targetClass = target.getClass(); } public void setTargetClass(Class targetClass) { this.targetClass = targetClass; } public void setMethodName(String methodName) { this.methodName = methodName; } public void setInterface(Class iface) { this.iface = iface; } protected ClassLoader getDefaultClassLoader() { return targetClass.getClassLoader(); } public MethodDelegate create() { setNamePrefix(targetClass.getName()); Object key = KEY_FACTORY.newInstance(targetClass, methodName, iface); return (MethodDelegate)super.create(key); } protected Object firstInstance(Class type) { return ((MethodDelegate)ReflectUtils.newInstance(type)).newInstance(target); } protected Object nextInstance(Object instance) { return ((MethodDelegate)instance).newInstance(target); } public void generateClass(ClassVisitor v) throws NoSuchMethodException { Method proxy = ReflectUtils.findInterfaceMethod(iface); final Method method = targetClass.getMethod(methodName, proxy.getParameterTypes()); if (!proxy.getReturnType().isAssignableFrom(method.getReturnType())) { throw new IllegalArgumentException("incompatible return types"); } boolean isStatic = Modifier.isStatic(method.getModifiers()); if ((target == null) ^ isStatic) { throw new IllegalArgumentException("Static method " + (isStatic ? "not " : "") + "expected"); } ClassEmitter ce = new ClassEmitter(v); CodeEmitter e; ce.begin_class(Constants.ACC_PUBLIC, getClassName(), METHOD_DELEGATE, new Type[]{ Type.getType(iface) }, Constants.SOURCE_FILE); ce.declare_field(Constants.PRIVATE_FINAL_STATIC, "eqMethod", Constants.TYPE_STRING, null, null); EmitUtils.null_constructor(ce); // generate proxied method Method proxied = iface.getDeclaredMethods()[0]; e = ce.begin_method(Constants.ACC_PUBLIC, ReflectUtils.getSignature(proxied), ReflectUtils.getExceptionTypes(proxied), null); e.load_this(); e.super_getfield("target", Constants.TYPE_OBJECT); e.checkcast(Type.getType(method.getDeclaringClass())); e.load_args(); e.invoke(method); e.return_value(); e.end_method(); // newInstance e = ce.begin_method(Constants.ACC_PUBLIC, NEW_INSTANCE, null, null); e.new_instance_this(); e.dup(); e.dup2(); e.invoke_constructor_this(); e.getfield("eqMethod"); e.super_putfield("eqMethod", Constants.TYPE_STRING); e.load_arg(0); e.super_putfield("target", Constants.TYPE_OBJECT); e.return_value(); e.end_method(); // static initializer e = ce.begin_static(); Signature sig = ReflectUtils.getSignature(method); e.push(sig.getName() + sig.getDescriptor()); e.putfield("eqMethod"); e.return_value(); e.end_method(); ce.end_class(); } } } --- NEW FILE: MulticastDelegate.java --- /* * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact ap...@ap.... * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.logicalcobwebs.cglib.reflect; import java.lang.reflect.*; import java.util.*; import org.logicalcobwebs.cglib.core.*; import org.logicalcobwebs.asm.ClassVisitor; import org.logicalcobwebs.asm.CodeVisitor; import org.logicalcobwebs.asm.Type; abstract public class MulticastDelegate implements Cloneable { protected Object[] targets = {}; protected MulticastDelegate() { } public List getTargets() { return new ArrayList(Arrays.asList(targets)); } abstract public MulticastDelegate add(Object target); protected MulticastDelegate addHelper(Object target) { MulticastDelegate copy = newInstance(); copy.targets = new Object[targets.length + 1]; System.arraycopy(targets, 0, copy.targets, 0, targets.length); copy.targets[targets.length] = target; return copy; } public MulticastDelegate remove(Object target) { for (int i = targets.length - 1; i >= 0; i--) { if (targets[i].equals(target)) { MulticastDelegate copy = newInstance(); copy.targets = new Object[targets.length - 1]; System.arraycopy(targets, 0, copy.targets, 0, i); System.arraycopy(targets, i + 1, copy.targets, i, targets.length - i - 1); return copy; } } return this; } abstract public MulticastDelegate newInstance(); public static MulticastDelegate create(Class iface) { Generator gen = new Generator(); gen.setInterface(iface); return gen.create(); } public static class Generator extends AbstractClassGenerator { private static final Source SOURCE = new Source(MulticastDelegate.class.getName()); private static final Signature NEW_INSTANCE = TypeUtils.parseSignature("org.logicalcobwebs.cglib.reflect.MulticastDelegate newInstance()"); private static final Signature ADD_DELEGATE = TypeUtils.parseSignature("org.logicalcobwebs.cglib.reflect.MulticastDelegate add(Object)"); private static final Signature ADD_HELPER = TypeUtils.parseSignature("org.logicalcobwebs.cglib.reflect.MulticastDelegate addHelper(Object)"); private static final Type MULTICAST_DELEGATE = TypeUtils.parseType("org.logicalcobwebs.cglib.reflect.MulticastDelegate"); private Class iface; public Generator() { super(SOURCE); } protected ClassLoader getDefaultClassLoader() { return iface.getClassLoader(); } public void setInterface(Class iface) { this.iface = iface; } public MulticastDelegate create() { setNamePrefix(MulticastDelegate.class.getName()); return (MulticastDelegate)super.create(iface.getName()); } public void generateClass(ClassVisitor cv) { final Method method = ReflectUtils.findInterfaceMethod(iface); ClassEmitter ce = new ClassEmitter(cv); ce.begin_class(Constants.ACC_PUBLIC, getClassName(), MULTICAST_DELEGATE, new Type[]{ Type.getType(iface) }, Constants.SOURCE_FILE); EmitUtils.null_constructor(ce); // generate proxied method emitProxy(ce, method); // newInstance CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, NEW_INSTANCE, null, null); e.new_instance_this(); e.dup(); e.invoke_constructor_this(); e.return_value(); e.end_method(); // add e = ce.begin_method(Constants.ACC_PUBLIC, ADD_DELEGATE, null, null); e.load_this(); e.load_arg(0); e.checkcast(Type.getType(iface)); e.invoke_virtual_this(ADD_HELPER); e.return_value(); e.end_method(); ce.end_class(); } private void emitProxy(ClassEmitter ce, final Method method) { final CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, ReflectUtils.getSignature(method), ReflectUtils.getExceptionTypes(method), null); Type returnType = e.getReturnType(); final boolean returns = returnType != Type.VOID_TYPE; Local result = null; if (returns) { result = e.make_local(returnType); e.zero_or_null(returnType); e.store_local(result); } e.load_this(); e.super_getfield("targets", Constants.TYPE_OBJECT_ARRAY); final Local result2 = result; EmitUtils.process_array(e, Constants.TYPE_OBJECT_ARRAY, new ProcessArrayCallback() { public void processElement(Type type) { e.checkcast(Type.getType(iface)); e.load_args(); e.invoke(method); if (returns) { e.store_local(result2); } } }); if (returns) { e.load_local(result); } e.return_value(); e.end_method(); } protected Object firstInstance(Class type) { // make a new instance in case first object is used with a long list of targets return ((MulticastDelegate)ReflectUtils.newInstance(type)).newInstance(); } protected Object nextInstance(Object instance) { return ((MulticastDelegate)instance).newInstance(); } } } |
Update of /cvsroot/proxool/proxool/src/java/org/logicalcobwebs/cglib/util In directory sc8-pr-cvs1:/tmp/cvs-serv25673/src/java/org/logicalcobwebs/cglib/util Added Files: ParallelSorter.java ParallelSorterEmitter.java SorterTemplate.java StringSwitcher.java Log Message: Repackaged Cglib project --- NEW FILE: ParallelSorter.java --- /* * The Apache Software License, Version 1.1 * * Copyright (c) 2003 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact ap...@ap.... * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.logicalcobwebs.cglib.util; import java.lang.reflect.*; import java.util.Comparator; import org.logicalcobwebs.cglib.core.*; import org.logicalcobwebs.asm.ClassVisitor; /** * For the efficient sorting of multiple arrays in parallel. * <p> * Given two arrays of equal length and varying types, the standard * technique for sorting them in parallel is to create a new temporary * object for each row, store the objects in a temporary array, sort the * array using a custom comparator, and the extract the original values * back into their respective arrays. This is wasteful in both time and * memory. * <p> * This class generates bytecode customized to the particular set of * arrays you need to sort, in such a way that both arrays are sorted * in-place, simultaneously. * <p> * Two sorting algorithms are provided. * Quicksort is best when you only need to sort by a single column, as * it requires very few comparisons and swaps. Mergesort is best used * when sorting multiple columns, as it is a "stable" sort--that is, it * does not affect the relative order of equal objects from previous sorts. * <p> * The mergesort algorithm here is an "in-place" variant, which while * slower, does not require a temporary array. * * @author Chris Nokleberg */ abstract public class ParallelSorter extends SorterTemplate { protected Object[] a; private Comparer comparer; protected ParallelSorter() { } abstract public ParallelSorter newInstance(Object[] arrays); /** * Create a new ParallelSorter object for a set of arrays. You may * sort the arrays multiple times via the same ParallelSorter object. * @param arrays An array of arrays to sort. The arrays may be a mix * of primitive and non-primitive types, but should all be the same * length. * @param loader ClassLoader for generated class, uses "current" if null */ public static ParallelSorter create(Object[] arrays) { Generator gen = new Generator(); gen.setArrays(arrays); return gen.create(); } private int len() { return ((Object[])a[0]).length; } /** * Sort the arrays using the quicksort algorithm. * @param index array (column) to sort by */ public void quickSort(int index) { quickSort(index, 0, len(), null); } /** * Sort the arrays using the quicksort algorithm. * @param index array (column) to sort by * @param lo starting array index (row), inclusive * @param hi ending array index (row), exclusive */ public void quickSort(int index, int lo, int hi) { quickSort(index, lo, hi, null); } /** * Sort the arrays using the quicksort algorithm. * @param index array (column) to sort by * @param cmp Comparator to use if the specified column is non-primitive */ public void quickSort(int index, Comparator cmp) { quickSort(index, 0, len(), cmp); } /** * Sort the arrays using the quicksort algorithm. * @param index array (column) to sort by * @param lo starting array index (row), inclusive * @param hi ending array index (row), exclusive * @param cmp Comparator to use if the specified column is non-primitive */ public void quickSort(int index, int lo, int hi, Comparator cmp) { chooseComparer(index, cmp); super.quickSort(lo, hi - 1); } /** * @param index array (column) to sort by */ public void mergeSort(int index) { mergeSort(index, 0, len(), null); } /** * Sort the arrays using an in-place merge sort. * @param index array (column) to sort by * @param lo starting array index (row), inclusive * @param hi ending array index (row), exclusive */ public void mergeSort(int index, int lo, int hi) { mergeSort(index, lo, hi, null); } /** * Sort the arrays using an in-place merge sort. * @param index array (column) to sort by * @param lo starting array index (row), inclusive * @param hi ending array index (row), exclusive */ public void mergeSort(int index, Comparator cmp) { mergeSort(index, 0, len(), cmp); } /** * Sort the arrays using an in-place merge sort. * @param index array (column) to sort by * @param lo starting array index (row), inclusive * @param hi ending array index (row), exclusive * @param cmp Comparator to use if the specified column is non-primitive */ public void mergeSort(int index, int lo, int hi, Comparator cmp) { chooseComparer(index, cmp); super.mergeSort(lo, hi - 1); } private void chooseComparer(int index, Comparator cmp) { Object array = a[index]; Class type = array.getClass().getComponentType(); if (type.equals(Integer.TYPE)) { comparer = new IntComparer((int[])array); } else if (type.equals(Long.TYPE)) { comparer = new LongComparer((long[])array); } else if (type.equals(Double.TYPE)) { comparer = new DoubleComparer((double[])array); } else if (type.equals(Float.TYPE)) { comparer = new FloatComparer((float[])array); } else if (type.equals(Short.TYPE)) { comparer = new ShortComparer((short[])array); } else if (type.equals(Byte.TYPE)) { comparer = new ByteComparer((byte[])array); } else if (cmp != null) { comparer = new ComparatorComparer((Object[])array, cmp); } else { comparer = new ObjectComparer((Object[])array); } } protected int compare(int i, int j) { return comparer.compare(i, j); } interface Comparer { int compare(int i, int j); } static class ComparatorComparer implements Comparer { private Object[] a; private Comparator cmp; public ComparatorComparer(Object[] a, Comparator cmp) { this.a = a; this.cmp = cmp; } public int compare(int i, int j) { return cmp.compare(a[i], a[j]); } } static class ObjectComparer implements Comparer { private Object[] a; public ObjectComparer(Object[] a) { this.a = a; } public int compare(int i, int j) { return ((Comparable)a[i]).compareTo(a[j]); } } static class IntComparer implements Comparer { private int[] a; public IntComparer(int[] a) { this.a = a; } public int compare(int i, int j) { return a[i] - a[j]; } } static class LongComparer implements Comparer { private long[] a; public LongComparer(long[] a) { this.a = a; } public int compare(int i, int j) { long vi = a[i]; long vj = a[j]; return (vi == vj) ? 0 : (vi > vj) ? 1 : -1; } } static class FloatComparer implements Comparer { private float[] a; public FloatComparer(float[] a) { this.a = a; } public int compare(int i, int j) { float vi = a[i]; float vj = a[j]; return (vi == vj) ? 0 : (vi > vj) ? 1 : -1; } } static class DoubleComparer implements Comparer { private double[] a; public DoubleComparer(double[] a) { this.a = a; } public int compare(int i, int j) { double vi = a[i]; double vj = a[j]; return (vi == vj) ? 0 : (vi > vj) ? 1 : -1; } } static class ShortComparer implements Comparer { private short[] a; public ShortComparer(short[] a) { this.a = a; } public int compare(int i, int j) { return a[i] - a[j]; } } static class ByteComparer implements Comparer { private byte[] a; public ByteComparer(byte[] a) { this.a = a; } public int compare(int i, int j) { return a[i] - a[j]; } } public static class Generator extends AbstractClassGenerator { private static final Source SOURCE = new Source(ParallelSorter.class.getName()); private Object[] arrays; public Generator() { super(SOURCE); } protected ClassLoader getDefaultClassLoader() { return null; // TODO } public void setArrays(Object[] arrays) { this.arrays = arrays; } public ParallelSorter create() { return (ParallelSorter)super.create(ClassesKey.create(arrays)); } public void generateClass(ClassVisitor v) throws Exception { if (arrays.length == 0) { throw new IllegalArgumentException("No arrays specified to sort"); } for (int i = 0; i < arrays.length; i++) { if (!arrays[i].getClass().isArray()) { throw new IllegalArgumentException(arrays[i].getClass() + " is not an array"); } } new ParallelSorterEmitter(v, getClassName(), arrays); } protected Object firstInstance(Class type) { return ((ParallelSorter)ReflectUtils.newInstance(type)).newInstance(arrays); } protected Object nextInstance(Object instance) { return ((ParallelSorter)instance).newInstance(arrays); } } } --- NEW FILE: ParallelSorterEmitter.java --- /* * The Apache Software License, Version 1.1 * * Copyright (c) 2003 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact ap...@ap.... * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.logicalcobwebs.cglib.util; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import org.logicalcobwebs.cglib.core.*; import org.logicalcobwebs.asm.ClassVisitor; import org.logicalcobwebs.asm.Type; class ParallelSorterEmitter extends ClassEmitter { private static final Signature CSTRUCT_OBJECT_ARRAY = TypeUtils.parseConstructor("Object[]"); private static final Signature NEW_INSTANCE = TypeUtils.parseSignature("org.logicalcobwebs.cglib.util.ParallelSorter newInstance(Object[])"); private static final Signature SWAP = TypeUtils.parseSignature("void swap(int, int)"); private static final Type PARALLEL_SORTER = TypeUtils.parseType("org.logicalcobwebs.cglib.util.ParallelSorter"); public ParallelSorterEmitter(ClassVisitor v, String className, Object[] arrays) { super(v); begin_class(Constants.ACC_PUBLIC, className, PARALLEL_SORTER, null, Constants.SOURCE_FILE); EmitUtils.null_constructor(this); EmitUtils.factory_method(this, NEW_INSTANCE); generateConstructor(arrays); generateSwap(arrays); end_class(); } private String getFieldName(int index) { return "FIELD_" + index; } private void generateConstructor(Object[] arrays) { CodeEmitter e = begin_method(Constants.ACC_PUBLIC, CSTRUCT_OBJECT_ARRAY, null, null); e.load_this(); e.super_invoke_constructor(); e.load_this(); e.load_arg(0); e.super_putfield("a", Constants.TYPE_OBJECT_ARRAY); for (int i = 0; i < arrays.length; i++) { Type type = Type.getType(arrays[i].getClass()); declare_field(Constants.ACC_PRIVATE, getFieldName(i), type, null, null); e.load_this(); e.load_arg(0); e.push(i); e.aaload(); e.checkcast(type); e.putfield(getFieldName(i)); } e.return_value(); e.end_method(); } private void generateSwap(final Object[] arrays) { CodeEmitter e = begin_method(Constants.ACC_PUBLIC, SWAP, null, null); for (int i = 0; i < arrays.length; i++) { Type type = Type.getType(arrays[i].getClass()); Type component = TypeUtils.getComponentType(type); Local T = e.make_local(type); e.load_this(); e.getfield(getFieldName(i)); e.store_local(T); e.load_local(T); e.load_arg(0); e.load_local(T); e.load_arg(1); e.array_load(component); e.load_local(T); e.load_arg(1); e.load_local(T); e.load_arg(0); e.array_load(component); e.array_store(component); e.array_store(component); } e.return_value(); e.end_method(); } } --- NEW FILE: SorterTemplate.java --- /* * The Apache Software License, Version 1.1 * * Copyright (c) 2003 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact ap...@ap.... * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.logicalcobwebs.cglib.util; import java.util.*; abstract class SorterTemplate { private static final int MERGESORT_THRESHOLD = 12; private static final int QUICKSORT_THRESHOLD = 7; abstract protected void swap(int i, int j); abstract protected int compare(int i, int j); protected void quickSort(int lo, int hi) { quickSortHelper(lo, hi); insertionSort(lo, hi); } private void quickSortHelper(int lo, int hi) { for (;;) { int diff = hi - lo; if (diff <= QUICKSORT_THRESHOLD) { break; } int i = (hi + lo) / 2; if (compare(lo, i) > 0) { swap(lo, i); } if (compare(lo, hi) > 0) { swap(lo, hi); } if (compare(i, hi) > 0) { swap(i, hi); } int j = hi - 1; swap(i, j); i = lo; int v = j; for (;;) { while (compare(++i, v) < 0) { /* nothing */; } while (compare(--j, v) > 0) { /* nothing */; } if (j < i) { break; } swap(i, j); } swap(i, hi - 1); if (j - lo <= hi - i + 1) { quickSortHelper(lo, j); lo = i + 1; } else { quickSortHelper(i + 1, hi); hi = j; } } } private void insertionSort(int lo, int hi) { for (int i = lo + 1 ; i <= hi; i++) { for (int j = i; j > lo; j--) { if (compare(j - 1, j) > 0) { swap(j - 1, j); } else { break; } } } } protected void mergeSort(int lo, int hi) { int diff = hi - lo; if (diff <= MERGESORT_THRESHOLD) { insertionSort(lo, hi); return; } int mid = lo + diff / 2; mergeSort(lo, mid); mergeSort(mid, hi); merge(lo, mid, hi, mid - lo, hi - mid); } private void merge(int lo, int pivot, int hi, int len1, int len2) { if (len1 == 0 || len2 == 0) { return; } if (len1 + len2 == 2) { if (compare(pivot, lo) < 0) { swap(pivot, lo); } return; } int first_cut, second_cut; int len11, len22; if (len1 > len2) { len11 = len1 / 2; first_cut = lo + len11; second_cut = lower(pivot, hi, first_cut); len22 = second_cut - pivot; } else { len22 = len2 / 2; second_cut = pivot + len22; first_cut = upper(lo, pivot, second_cut); len11 = first_cut - lo; } rotate(first_cut, pivot, second_cut); int new_mid = first_cut + len22; merge(lo, first_cut, new_mid, len11, len22); merge(new_mid, second_cut, hi, len1 - len11, len2 - len22); } private void rotate(int lo, int mid, int hi) { int lot = lo; int hit = mid - 1; while (lot < hit) { swap(lot++, hit--); } lot = mid; hit = hi - 1; while (lot < hit) { swap(lot++, hit--); } lot = lo; hit = hi - 1; while (lot < hit) { swap(lot++, hit--); } } private int lower(int lo, int hi, int val) { int len = hi - lo; while (len > 0) { int half = len / 2; int mid= lo + half; if (compare(mid, val) < 0) { lo = mid + 1; len = len - half -1; } else { len = half; } } return lo; } private int upper(int lo, int hi, int val) { int len = hi - lo; while (len > 0) { int half = len / 2; int mid = lo + half; if (compare(val, mid) < 0) { len = half; } else { lo = mid + 1; len = len - half -1; } } return lo; } } --- NEW FILE: StringSwitcher.java --- /* * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact ap...@ap.... * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.logicalcobwebs.cglib.util; import java.util.*; import org.logicalcobwebs.cglib.core.*; import org.logicalcobwebs.asm.ClassVisitor; import org.logicalcobwebs.asm.Label; import org.logicalcobwebs.asm.Type; /** * This class implements a simple String->int mapping for a fixed set of keys. */ abstract public class StringSwitcher { private static final Type STRING_SWITCHER = TypeUtils.parseType("org.logicalcobwebs.cglib.util.StringSwitcher"); private static final Signature INT_VALUE = TypeUtils.parseSignature("int intValue(String)"); private static final StringSwitcherKey KEY_FACTORY = (StringSwitcherKey)KeyFactory.create(StringSwitcherKey.class); interface StringSwitcherKey { public Object newInstance(String[] strings, int[] ints, boolean fixedInput); } /** * Helper method to create a StringSwitcher. * For finer control over the generated instance, use a new instance of StringSwitcher.Generator * instead of this static method. * @param strings the array of String keys; must be the same length as the value array * @param ints the array of integer results; must be the same length as the key array * @param fixedInput if false, an unknown key will be returned from {@link #intValue} as <code>-1</code>; if true, * the result will be undefined, and the resulting code will be faster */ public static StringSwitcher create(String[] strings, int[] ints, boolean fixedInput) { Generator gen = new Generator(); gen.setStrings(strings); gen.setInts(ints); gen.setFixedInput(fixedInput); return gen.create(); } protected StringSwitcher() { } /** * Return the integer associated with the given key. * @param s the key * @return the associated integer value, or <code>-1</code> if the key is unknown (unless * <code>fixedInput</code> was specified when this <code>StringSwitcher</code> was created, * in which case the return value for an unknown key is undefined) */ abstract public int intValue(String s); public static class Generator extends AbstractClassGenerator { private static final Source SOURCE = new Source(StringSwitcher.class.getName()); private String[] strings; private int[] ints; private boolean fixedInput; public Generator() { super(SOURCE); } /** * Set the array of recognized Strings. * @param strings the array of String keys; must be the same length as the value array * @see #setInts */ public void setStrings(String[] strings) { this.strings = strings; } /** * Set the array of integer results. * @param ints the array of integer results; must be the same length as the key array * @see #setStrings */ public void setInts(int[] ints) { this.ints = ints; } /** * Configure how unknown String keys will be handled. * @param fixedInput if false, an unknown key will be returned from {@link #intValue} as <code>-1</code>; if true, * the result will be undefined, and the resulting code will be faster */ public void setFixedInput(boolean fixedInput) { this.fixedInput = fixedInput; } protected ClassLoader getDefaultClassLoader() { return getClass().getClassLoader(); } /** * Generate the <code>StringSwitcher</code>. */ public StringSwitcher create() { setNamePrefix(StringSwitcher.class.getName()); Object key = KEY_FACTORY.newInstance(strings, ints, fixedInput); return (StringSwitcher)super.create(key); } public void generateClass(ClassVisitor v) throws Exception { ClassEmitter ce = new ClassEmitter(v); ce.begin_class(Constants.ACC_PUBLIC, getClassName(), STRING_SWITCHER, null, Constants.SOURCE_FILE); EmitUtils.null_constructor(ce); final CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, INT_VALUE, null, null); e.load_arg(0); final List stringList = Arrays.asList(strings); int style = fixedInput ? Constants.SWITCH_STYLE_HASHONLY : Constants.SWITCH_STYLE_HASH; EmitUtils.string_switch(e, strings, style, new ObjectSwitchCallback() { public void processCase(Object key, Label end) { e.push(ints[stringList.indexOf(key)]); e.return_value(); } public void processDefault() { e.push(-1); e.return_value(); } }); e.end_method(); ce.end_class(); } protected Object firstInstance(Class type) { return (StringSwitcher)ReflectUtils.newInstance(type); } protected Object nextInstance(Object instance) { return instance; } } } |
|
From: <bil...@us...> - 2003-12-12 19:21:14
|
Update of /cvsroot/proxool/proxool/src/java/org/logicalcobwebs/cglib/util In directory sc8-pr-cvs1:/tmp/cvs-serv24315/src/java/org/logicalcobwebs/cglib/util Log Message: Directory /cvsroot/proxool/proxool/src/java/org/logicalcobwebs/cglib/util added to the repository |