You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by dj...@apache.org on 2006/01/19 19:43:00 UTC

svn commit: r370570 - in /db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests: master/ master/j9_foundation/ tests/jdbcapi/ util/

Author: djd
Date: Thu Jan 19 10:42:56 2006
New Revision: 370570

URL: http://svn.apache.org/viewcvs?rev=370570&view=rev
Log:
DERBY-467 Add intial framework for security checking of returned JDBC objects to
try and catch code that allows complete access to internal Derby objects, such
as the page cache.

Added:
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/util/SecurityCheck.java   (with props)
Modified:
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/checkDataSource.out
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/checkDataSource30.out
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/j9_foundation/resultset.out
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/resultset.out
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/checkDataSource.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/checkDataSource30.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/resultset.java

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/checkDataSource.out
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/checkDataSource.out?rev=370570&r1=370569&r2=370570&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/checkDataSource.out (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/checkDataSource.out Thu Jan 19 10:42:56 2006
@@ -670,4 +670,12 @@
   getXAConnection(fred, databaseName=wombat) - 08004:Connection refused : Invalid authentication.
   getXAConnection(fred, databaseName=wombat;password=wilma) - OK
   getXAConnection(fred, databaseName=wombat;password=betty) - 08004:Connection refused : Invalid authentication.
+Checked class declared as: java.sql.CallableStatement
+Checked class declared as: java.sql.Connection
+Checked class declared as: java.sql.DatabaseMetaData
+Checked class declared as: java.sql.ResultSet
+Checked class declared as: java.sql.Statement
+Checked class declared as: javax.sql.DataSource
+Checked class declared as: javax.sql.PooledConnection
+Checked class declared as: javax.sql.XAConnection
 Completed checkDataSource

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/checkDataSource30.out
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/checkDataSource30.out?rev=370570&r1=370569&r2=370570&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/checkDataSource30.out (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/checkDataSource30.out Thu Jan 19 10:42:56 2006
@@ -854,4 +854,12 @@
 Expected SQLException (local CallableStatement hold) Cannot set holdability ResultSet.HOLD_CURSORS_OVER_COMMIT for a global transaction.
 CONNECTION(held) HOLDABILITY true
 PASS XA HOLDABILITY TEST
+Checked class declared as: java.sql.CallableStatement
+Checked class declared as: java.sql.Connection
+Checked class declared as: java.sql.DatabaseMetaData
+Checked class declared as: java.sql.ResultSet
+Checked class declared as: java.sql.Statement
+Checked class declared as: javax.sql.DataSource
+Checked class declared as: javax.sql.PooledConnection
+Checked class declared as: javax.sql.XAConnection
 Completed checkDataSource30

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/j9_foundation/resultset.out
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/j9_foundation/resultset.out?rev=370570&r1=370569&r2=370570&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/j9_foundation/resultset.out (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/j9_foundation/resultset.out Thu Jan 19 10:42:56 2006
@@ -1991,4 +1991,6 @@
 ERROR 42818: Comparisons between 'BLOB' and 'BLOB' are not supported.
 Single RS auto-commit test: PASS.
 SingleRSCloseCursorsAtCommit: PASS.
+Checked class declared as: java.sql.ResultSet
+Checked class declared as: java.sql.ResultSetMetaData
 Test resultset finished

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/resultset.out
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/resultset.out?rev=370570&r1=370569&r2=370570&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/resultset.out (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/resultset.out Thu Jan 19 10:42:56 2006
@@ -1995,4 +1995,6 @@
 ERROR 42818: Comparisons between 'BLOB' and 'BLOB' are not supported.
 Single RS auto-commit test: PASS.
 SingleRSCloseCursorsAtCommit: PASS.
+Checked class declared as: java.sql.ResultSet
+Checked class declared as: java.sql.ResultSetMetaData
 Test resultset finished

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/checkDataSource.java
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/checkDataSource.java?rev=370570&r1=370569&r2=370570&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/checkDataSource.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/checkDataSource.java Thu Jan 19 10:42:56 2006
@@ -24,8 +24,6 @@
 import org.apache.derby.jdbc.EmbeddedSimpleDataSource;
 import org.apache.derby.jdbc.EmbeddedConnectionPoolDataSource;
 import org.apache.derby.jdbc.EmbeddedXADataSource;
-import org.apache.derby.iapi.jdbc.BrokeredConnection;
-import org.apache.derby.impl.jdbc.EmbedConnection;
 
 import java.sql.Connection;
 import java.sql.ResultSet;
@@ -47,6 +45,7 @@
 import javax.sql.ConnectionEvent;
 import org.apache.derby.tools.JDBCDisplayUtil;
 import org.apache.derby.tools.ij;
+import org.apache.derbyTesting.functionTests.util.SecurityCheck;
 
 import java.io.*;
 import java.util.Hashtable;
@@ -55,6 +54,16 @@
 import javax.naming.*;
 import javax.naming.directory.*;
 
+/**
+ * Test the various embedded DataSource implementations of Derby.
+ * 
+ * Performs SecurityCheck analysis on the JDBC objects returned.
+ * This is because this test returns to the client a number of
+ * different implementations of Connection, Statement etc.
+ * 
+ * @see org.apache.derbyTesting.functionTests.util.SecurityCheck
+ *
+ */
 public class checkDataSource
 { 
     /**
@@ -78,13 +87,26 @@
     private static final String CONNSTRING_FORMAT = "\\S+@[0-9]+ " +
         "\\(XID = .*\\), \\(SESSIONID = [0-9]+\\), " +
         "\\(DATABASE = [A-Za-z]+\\), \\(DRDAID = .+\\)";
+    
+	/**
+	 * Hang onto the SecurityCheck class while running the
+	 * tests so that it is not garbage collected during the
+	 * test and lose the information it has collected.
+	 */
+	private final Object nogc = SecurityCheck.class;
+  
 
 	public static void main(String[] args) throws Exception {
 
         try
         {
 			new checkDataSource().runTest(args);
-        }
+			
+			// Print a report on System.out of the issues
+			// found with the security checks. 
+			SecurityCheck.report();
+
+	    }
         catch ( Exception e )
         {
             e.printStackTrace();
@@ -94,7 +116,6 @@
 
 	}
 
-
 	public checkDataSource() throws Exception {
 	}
 
@@ -136,6 +157,7 @@
 		checkToString(dsp);
 
 		PooledConnection pc = dsp.getPooledConnection();
+		SecurityCheck.inspect(pc, "javax.sql.PooledConnection");
 		pc.addConnectionEventListener(new EventCatcher(1));
 
 		checkConnection("EmbeddedConnectionPoolDataSource", pc.getConnection());
@@ -195,6 +217,7 @@
 		checkToString(dsx);
 
 		XAConnection xac = dsx.getXAConnection();
+		SecurityCheck.inspect(xac, "javax.sql.XAConnection");
 		xac.addConnectionEventListener(new EventCatcher(3));
 
 		checkConnection("EmbeddedXADataSource", xac.getConnection());
@@ -238,6 +261,7 @@
 		dmc = ij.startJBMS();
 
 		cs = dmc.prepareCall("call checkConn2(?)");
+		SecurityCheck.inspect(cs, "java.sql.CallableStatement");
 		cs.setString(1,"Nested");
 		cs.execute();
 		
@@ -268,6 +292,7 @@
 		xac = dsx.getXAConnection();
 		xac.addConnectionEventListener(new EventCatcher(5));
 		XAResource xar = xac.getXAResource();
+		SecurityCheck.inspect(xar, "javax.transaction.xa.XAResource");
 		Xid xid = new cdsXid(1, (byte) 35, (byte) 47);
 		xar.start(xid, XAResource.TMNOFLAGS);
 		Connection xacc = xac.getConnection();
@@ -659,7 +684,6 @@
 		}
 
 		testDSRequestAuthentication();
-		
 	}
 
 	protected void showXAException(String tag, XAException xae) {
@@ -792,6 +816,7 @@
 
 	private static void resultSetQuery(String tag, ResultSet rs) throws SQLException {
 		System.out.print(tag + ": ru(" + rs.getCursorName() + ") contents");
+		SecurityCheck.inspect(rs, "java.sql.ResultSet");
 		while (rs.next()) {
 			System.out.print(" {" + rs.getInt(1) + "}");
 		}
@@ -822,6 +847,9 @@
 	public static void checkConnectionS(String dsName, Connection conn) throws SQLException {
 
 		System.out.println("Running connection checks on " + dsName);
+		
+		SecurityCheck.inspect(conn, "java.sql.Connection");
+		SecurityCheck.inspect(conn.getMetaData(), "java.sql.DatabaseMetaData");
 
 		//System.out.println("  url             " + conn.getMetaData().getURL());
 		System.out.println("  isolation level " + conn.getTransactionIsolation());
@@ -847,6 +875,9 @@
 
 		System.out.println("Running connection checks on " + dsName);
 
+		SecurityCheck.inspect(conn, "java.sql.Connection");
+		SecurityCheck.inspect(conn.getMetaData(), "java.sql.DatabaseMetaData");
+
 		//System.out.println("  url             " + conn.getMetaData().getURL());
 		System.out.println("  isolation level " + conn.getTransactionIsolation());
 		System.out.println("  auto commit     " + conn.getAutoCommit());
@@ -946,27 +977,6 @@
               "does not match expected format (" + format + ")");
         }
     }
-    
-    /**
-     * Check the format for the toString() of a Connection that is an
-     * instance of BrokeredConnection.  This is different, as the Brokered
-     * Connection prints out its class name and then the toString() value
-     * of the underlying, wrapped connection.
-     */
-    protected static void checkStringFormat(BrokeredConnection conn) throws Exception
-    {
-        String connstr = conn.toString();
-        String prefix = checkStringPrefix(connstr);
-        
-        String format = "/" + prefix + ", Wrapped Connection = " + 
-            "<none>|" + CONNSTRING_FORMAT + "/";
-
-        if ( ! p5u.match(format, connstr) )
-        {
-            throw new Exception( "Connection.toString() (" + connstr + ") " +
-                "does not match expected format (" + format + ")");
-        }
-    }
         
      /**
      * Check the format of the connection string.  This is the default test
@@ -1184,6 +1194,8 @@
 
 	protected static void checkStatementS(Connection conn, Statement s) throws SQLException {
 
+		SecurityCheck.inspect(s, "java.sql.Statement");
+		
 		Connection c1 = s.getConnection();
 		if (c1 != conn)
 			System.out.println("FAIL incorrect connection object returned for Statement.getConnection()");
@@ -1199,7 +1211,7 @@
 		s.close();
 	}
 	protected void checkStatement(Connection conn, Statement s) throws SQLException {
-
+		
 		Connection c1 = s.getConnection();
 		if (c1 != conn)
 			System.out.println("FAIL incorrect connection object returned for Statement.getConnection()");
@@ -1342,6 +1354,9 @@
 	}
 
 	private static void dsConnectionRequests(DataSource ds) {
+		
+		SecurityCheck.inspect(ds, "javax.sql.DataSource");
+		
 		try {
 			Connection c1 = ds.getConnection();
 			System.out.println("  getConnection() - OK");

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/checkDataSource30.java
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/checkDataSource30.java?rev=370570&r1=370569&r2=370570&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/checkDataSource30.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/checkDataSource30.java Thu Jan 19 10:42:56 2006
@@ -45,6 +45,7 @@
 import javax.sql.ConnectionEvent;
 import org.apache.derby.tools.JDBCDisplayUtil;
 import org.apache.derby.tools.ij;
+import org.apache.derbyTesting.functionTests.util.SecurityCheck;
 
 import java.io.*;
 import java.util.Hashtable;
@@ -52,6 +53,12 @@
 import javax.naming.*;
 import javax.naming.directory.*;
 
+/**
+ * Extends checkDataSource to provide testing of JDBC 3.0 specific
+ * methods for the embedded DataSource implementations.
+ * @author djd
+ *
+ */
 public class checkDataSource30 extends checkDataSource
 { 
 
@@ -62,6 +69,11 @@
 
 		tester.runTest(args);
 		tester.checkXAHoldability();
+		
+		// Print a report on System.out of the issues
+		// found with the security checks.
+		SecurityCheck.report();
+		
 		System.out.println("Completed checkDataSource30");
 
 	}

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/resultset.java
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/resultset.java?rev=370570&r1=370569&r2=370570&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/resultset.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/resultset.java Thu Jan 19 10:42:56 2006
@@ -37,6 +37,7 @@
 import java.lang.reflect.*;
 
 import org.apache.derby.tools.ij;
+import org.apache.derbyTesting.functionTests.util.SecurityCheck;
 import org.apache.derbyTesting.functionTests.util.TestUtil;
 import org.apache.derbyTesting.functionTests.util.JDBCTestDisplayUtil;
 import org.apache.derby.iapi.reference.JDBC30Translation;
@@ -51,7 +52,11 @@
  * discern whether it passes or not.
  *
  * Test is only touching on known result set hot-spots at present.
- *
+
+ * Performs SecurityCheck analysis on the JDBC ResultSet and
+ * ResultSetMetaData objects returned.
+ * 
+ * @see org.apache.derbyTesting.functionTests.util.SecurityCheck
  * @author ames
  */
 
@@ -132,6 +137,13 @@
 		{NULL_VALUE,NULL_VALUE,NULL_VALUE,NULL_VALUE}                 // BLOB
 	};
 
+ /**
+	 * Hang onto the SecurityCheck class while running the
+	 * tests so that it is not garbage collected during the
+	 * test and lose the information it has collected.
+	 */
+	private final Object nogc = SecurityCheck.class;
+
 	public static void main(String[] args) throws Throwable {
 
 		isDerbyNet = TestUtil.isNetFramework();
@@ -627,6 +639,9 @@
 			e.printStackTrace();
 		}
 
+		// Print a report on System.out of the issues
+		// found with the security checks. 
+		SecurityCheck.report();
 		System.out.println("Test resultset finished");
     }
 
@@ -755,6 +770,8 @@
 
 	public static void dumpRS(ResultSet s) throws SQLException
 	{
+		SecurityCheck.inspect(s, "java.sql.ResultSet");
+		
 		if (s == null)
 		{
 			System.out.println("<NULL>");
@@ -762,6 +779,7 @@
 		}
 
 		ResultSetMetaData rsmd = s.getMetaData();
+		SecurityCheck.inspect(rsmd, "java.sql.ResultSetMetaData");
 
 		// Get the number of columns in the result set
 		int numCols = rsmd.getColumnCount();

Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/util/SecurityCheck.java
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/util/SecurityCheck.java?rev=370570&view=auto
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/util/SecurityCheck.java (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/util/SecurityCheck.java Thu Jan 19 10:42:56 2006
@@ -0,0 +1,324 @@
+/*
+
+   Derby - Class org.apache.derbyTesting.functionTests.util.SecurityCheck
+
+   Copyright 2006 The Apache Software Foundation or its licensors, as applicable.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+ */
+
+package org.apache.derbyTesting.functionTests.util;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Iterator;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+
+/**
+ * Code to aid in checking the Security of Derby.
+ * This initial implementation only handles the emebdded code.
+ * Future work could expand to the client driver and network server.
+ */
+public class SecurityCheck {
+	
+	/**
+	 * List of classes in the public api for the embedded engine.
+	 */
+	private static final String[] EMBEDDED_PUBLIC_API =
+	{
+		"org.apache.derby.jdbc.EmbeddedDriver",
+		"org.apache.derby.jdbc.EmbeddedDataSource",
+		"org.apache.derby.jdbc.EmbeddedSimpleDataSource",
+		"org.apache.derby.jdbc.EmbeddedConnectionPoolDataSource",
+		"org.apache.derby.jdbc.EmbeddedXADataSource",
+		"org.apache.derby.authentication.UserAuthenticator",
+	};
+	
+	/**
+	 * Is the passed in class part of the declared public api.
+	 * Currently only the emebdded public api
+	 * @param c class to be checked
+	 * @return true if the class is part of the public api, false otherwise.
+	 */
+	private static boolean isPublicApi(Class c)
+	{
+		for (int i = 0; i < EMBEDDED_PUBLIC_API.length; i++)
+		{
+			if (EMBEDDED_PUBLIC_API[i].equals(c.getName()))
+				return true;
+		}
+		return false;
+	}
+	
+	/**
+	 * Map of all classes that have been inspected.
+	 * The key is the class name, if the value is null then
+	 * the class is being inspected. Otherwise the value is
+	 * a String description of the risks.
+	 */
+	private static final SortedMap allInspectedClasses = new TreeMap();
+	
+	/**
+	 * Perform security analysis of the public api for the embedded engine.
+	 * Prints a report to System.out on completion.
+	 * @throws ClassNotFoundException
+	 */
+	public static void checkEmbeddedPublicApi() throws ClassNotFoundException
+	{
+		System.out.println("SecurityCheck: embedded public api classes");
+		allInspectedClasses.clear();
+		for (int i = 0; i < EMBEDDED_PUBLIC_API.length; i++)
+			SecurityCheck.inspectClass(EMBEDDED_PUBLIC_API[i]);
+
+		SecurityCheck.report(true);
+	}
+	
+	/**
+	 * Produce a report on System.out of all inspected classes
+	 * that have risks associated with them.
+	 *
+	 */
+	public static void report()
+	{
+        SecurityCheck.report(false);
+	}
+	
+	/**
+	 * Produce a report on System.out of all inspected classes
+	 * that have risks associated with them. If reportClear is
+	 * true then additionally all classes that have been inspected
+	 * will be returned.
+	 *
+	 */
+	private static void report(boolean reportClear)
+	{
+		synchronized (allInspectedClasses)
+		{
+		for (Iterator it = allInspectedClasses.keySet().iterator(); it.hasNext(); )
+		{
+			Object key = it.next();
+			Object value = allInspectedClasses.get(key);
+			if (value == null)
+			{
+				if (reportClear)
+				    System.out.println("CLEAR: " + key);
+			}
+			else
+			{
+				System.out.print(value);
+			}
+		}
+		}
+	}
+	
+	/**
+	 * Inspect a class for security risks. No output is generated
+	 * by this call, the caller must call report() to obtain the risks.
+	 * @param className
+	 * @throws ClassNotFoundException
+	 */
+	public static void inspectClass(String className) throws ClassNotFoundException
+	{			
+		SecurityCheck.inspectClass(Class.forName(className), null);
+	}	
+	
+	/**
+	 * Inspect the class of the passed in Object for security risks.
+	 * This inspects, at this level only, the actual type of
+	 * the object, not the declared type. E.g. for DriverManager.getConnection
+	 * the declared type is java.sql.Connection which has no security risks,
+	 * but the implementation type returned may have many.
+	 * 
+	 * <code>
+	 * Connection conn = DriverManager.getConnection(url);
+	 * // will inspect the implementation call, eg. EmbedConnection30
+	 * SecurityManager.inspect(conn);
+	 * </code>
+	 * No output is generated by this call,
+	 * the caller must call report() to obtain the risks.
+	 * @param o Obejct to be inspected
+	 * @param declared the declared type of the object. 
+	 */
+	public static void inspect(Object o, String declared)
+	{
+		if (o == null)
+			return;
+				
+		SecurityCheck.inspectClass(o.getClass(), declared);
+	}
+	
+	/**
+	 * Inspect a Derby class for security risks. This includes following potential
+	 * references exposed through the class.
+	 * <P>
+	 * Risks looked at:
+	 * <UL>
+	 * <LI> public constructors in non-public class - 
+	 * No justification for the constructor to be public.
+	 * <LI> public constructors in non-final class and non-sealed package -
+	 * Allows the class to be sub-classes through a injected class in
+	 * the same package.
+	 * <LI> public non-final field - Allows any one with a handle to
+	 * the object to change the field.
+     * </UL>
+	 * <P>
+	 * The type of any public field or return type of any public method
+	 * is also inspected. The assumption is that if such a field or method
+	 * exists they have the potential to be called and return a valid object.
+	 * <P>
+	 * Note that this inspection is through the declared type of exposed
+	 * references, not the actual runtime type. The actual runtime type
+	 * might expose other classes that should be inspected.
+	 * @param className
+	 * @throws ClassNotFoundException
+	 */
+	private static boolean inspectClass(Class c, String declared)
+	{		
+		if (!c.getName().startsWith("org.apache.derby."))
+			return false;
+		
+		// Initial focus on embedded engine
+		if (c.getName().startsWith("org.apache.derby.client."))
+			return false;
+		
+		synchronized (allInspectedClasses)
+		{
+		if (allInspectedClasses.containsKey(c.getName()))
+			return true;
+		
+		allInspectedClasses.put(c.getName(), null);
+				
+		StringBuffer sb = new StringBuffer();
+		
+		sb.append("Class ");
+		sb.append(c.getName());
+		sb.append('\n');
+		
+		if (declared != null)
+		{
+			allInspectedClasses.put(declared, "Checked class declared as: " + declared + "\n");
+			
+		}
+
+		boolean isPublicApi = SecurityCheck.isPublicApi(c);
+	
+		boolean hasIssues = false;
+		
+		boolean isSealed = c.getPackage().isSealed();
+		boolean isFinal = Modifier.isFinal(c.getModifiers());
+		boolean isPublic = Modifier.isPublic(c.getModifiers());
+		boolean isAbstract = Modifier.isAbstract(c.getModifiers());
+		
+		Constructor[] constructors = c.getConstructors();
+		
+		boolean hasPublicConstructor = constructors.length != 0;
+		
+		if (hasPublicConstructor && !isPublic)
+		{
+			hasIssues = true;
+			
+			// No reason for a public constructor in a non-public class
+			sb.append("..public constructors in non-public class\n");
+			
+			// class can be sub-classed even though it is not public
+			if (!isFinal && !isSealed)
+				sb.append("..public constructors in non-final class and non-sealed package\n");
+		}
+		
+		if (hasPublicConstructor && isPublic)
+		{
+			// TODO: Need to work on these checks.
+			if (!isPublicApi)
+			{
+			    //hasIssues = true;
+			
+			    // anyone can create instances of this class
+			    //sb.append("..public constructors in public class\n");
+			}
+
+			// and anyone can sub-class this class
+			if (!isFinal)
+			{
+				//hasIssues = true;
+				//sb.append("..public constructors in public non-final class\n");
+			}
+		}
+		
+		for (int i = 0; i < constructors.length; i++)
+		{
+			if (hasIssues)
+			{
+				sb.append("..public constructor: ");
+				sb.append(constructors[i].toString());
+				sb.append('\n');
+			}
+		}
+		
+		Field[] fields = c.getFields();
+		for (int i = 0; i < fields.length; i++)
+		{
+			Field f = fields[i];
+			boolean isStatic = Modifier.isStatic(f.getModifiers());
+						
+			Class fieldType = f.getType();
+			SecurityCheck.inspectClass(fieldType, null);
+			
+			if (Modifier.isFinal(f.getModifiers()))
+			{
+				// TODO: Should this be a concern if non-static?
+				continue;
+			}
+			
+			hasIssues = true;
+			sb.append("..public non-final field: ");
+			sb.append(f.toString());
+			sb.append('\n');
+		}
+
+		Method[] methods = c.getMethods();
+		for (int i = 0; i < methods.length; i++)
+		{
+			Method m = methods[i];
+						
+			Class methodType = m.getReturnType();
+			if (SecurityCheck.inspectClass(methodType, null))
+			{
+				// method returns a class of interest to us.
+				
+				// just a method returning a public api
+				if (SecurityCheck.isPublicApi(methodType))
+					continue;
+				
+				/*
+				 * Not sure this is a vaild risk.
+				hasIssues = true;
+				sb.append("..public method returning non-public api class: ");
+				sb.append(m.toString());
+				sb.append("\n");
+				*/
+			}
+			
+		}		
+		if (hasIssues)
+			allInspectedClasses.put(c.getName(), sb.toString());
+		}
+		
+		return true;
+		
+	}
+}
\ No newline at end of file

Propchange: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/util/SecurityCheck.java
------------------------------------------------------------------------------
    svn:eol-style = native