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 rh...@apache.org on 2014/03/23 01:17:58 UTC

svn commit: r1580387 [2/3] - in /db/derby/code/trunk: ./ java/engine/org/apache/derby/catalog/ java/engine/org/apache/derby/impl/ java/engine/org/apache/derby/impl/optional/ java/engine/org/apache/derby/impl/optional/lucene/ java/engine/org/apache/derb...

Modified: db/derby/code/trunk/java/engine/org/apache/derby/vti/VTITemplate.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/vti/VTITemplate.java?rev=1580387&r1=1580386&r2=1580387&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/vti/VTITemplate.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/vti/VTITemplate.java Sun Mar 23 00:17:56 2014
@@ -28,6 +28,8 @@ import java.net.URL;
 import java.sql.Array;
 import java.sql.Blob;
 import java.sql.Clob;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
 import java.sql.Date;
 import java.sql.NClob;
 import java.sql.Ref;
@@ -45,6 +47,8 @@ import java.sql.Statement;
 import java.sql.Struct;
 import java.sql.Time;
 import java.sql.Timestamp;
+import java.util.Arrays;
+import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.Map;
 
@@ -303,4 +307,94 @@ public abstract class VTITemplate   impl
         return new SQLFeatureNotSupportedException( "Unimplemented method: " + methodName );
     }
     
+    /**
+     * <p>
+     * Get an array of descriptors for the return table shape declared for this
+     * AwareVTI by its CREATE FUNCTION statement.
+     * </p>
+     */
+    public  ColumnDescriptor[]  getReturnTableSignature( Connection currentConnection )
+        throws SQLException
+    {
+        ArrayList<ColumnDescriptor> columns = new ArrayList<ColumnDescriptor>();
+        VTIContext  context = getContext();
+        String      schema = context.vtiSchema();
+        String      function = context.vtiTable();
+        ResultSet   rs = currentConnection.getMetaData().getFunctionColumns( null, schema, function, "%" );
+
+        try {
+            while ( rs.next() )
+            {
+                if ( rs.getInt( "COLUMN_TYPE" ) == DatabaseMetaData.functionColumnResult )
+                {
+                    ColumnDescriptor    cd = new ColumnDescriptor
+                        (
+                         rs.getString( "COLUMN_NAME" ),
+                         rs.getInt( "DATA_TYPE" ),
+                         rs.getInt( "PRECISION" ),
+                         rs.getInt( "SCALE" ),
+                         rs.getString( "TYPE_NAME" ),
+                         rs.getInt( "ORDINAL_POSITION" )
+                         );
+                    columns.add( cd );
+                }
+            }
+        }
+        finally { rs.close(); }
+
+        ColumnDescriptor[]  result = new ColumnDescriptor[ columns.size() ];
+        columns.toArray( result );
+        Arrays.sort( result );
+
+        return result;
+    }
+
+    ///////////////////////////////////////////////////////////////////////////////////
+    //
+    // NESTED CLASSES
+    //
+    ///////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * <p>
+     * A struct class which is useful for describing columns and parameters.
+     * </p>
+     */
+    public  static  final   class   ColumnDescriptor   implements  Comparable<ColumnDescriptor>
+    {
+        public  final   String  columnName;
+        public  final   int jdbcType;
+        public  final   int precision;
+        public  final   int scale;
+        public  final   String  typeName;
+        public  final   int ordinalPosition;
+
+        public  ColumnDescriptor
+            (
+             String columnName,
+             int    jdbcType,
+             int    precision,
+             int    scale,
+             String typeName,
+             int    ordinalPosition
+             )
+        {
+            this.columnName = columnName;
+            this.jdbcType = jdbcType;
+            this.precision = precision;
+            this.scale = scale;
+            this.typeName =typeName;
+            this.ordinalPosition = ordinalPosition;
+        }
+
+        public  int compareTo( ColumnDescriptor that ) { return this.ordinalPosition - that.ordinalPosition; }
+        public  boolean equals( Object other )
+        {
+            if ( other == null ) { return false; }
+            else if ( !(other instanceof ColumnDescriptor) ) { return false; }
+            else { return (compareTo( (ColumnDescriptor) other ) == 0); }
+        }
+        public  int hashCode()  { return columnName.hashCode(); }
+    }
+
 }

Modified: db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/SQLState.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/SQLState.java?rev=1580387&r1=1580386&r2=1580387&view=diff
==============================================================================
--- db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/SQLState.java (original)
+++ db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/SQLState.java Sun Mar 23 00:17:56 2014
@@ -1173,6 +1173,17 @@ public interface SQLState {
 	//following 1 does not match the DB2 sql state, it is a Derby specific behavior which is not compatible with DB2
 	String LANG_OPERATION_NOT_ALLOWED_ON_SESSION_SCHEMA_TABLES = "XCL51.S";
 
+    // error messages for the Lucene plugin
+    String LUCENE_NOT_A_STRING_TYPE                                  = "42XBA";
+    String LUCENE_NO_PRIMARY_KEY                                  = "42XBB";
+    String LUCENE_UNSUPPORTED_TYPE                                  = "42XBC";
+    String LUCENE_INVALID_CHARACTER                                  = "42XBD";
+    String LUCENE_INDEX_DOES_NOT_EXIST                                  = "42XBE";
+    String LUCENE_MUST_OWN_SCHEMA                                  = "42XBF";
+    String LUCENE_ALREADY_LOADED                                  = "42XBG";
+    String LUCENE_ALREADY_UNLOADED                                  = "42XBH";
+    String LUCENE_BAD_INDEX                                               = "42XBI";
+    
 	// org.apache.derby.impl.sql.execute.rts
 	String RTS_ATTACHED_TO											   = "43X00.U";
 	String RTS_BEGIN_SQ_NUMBER										   = "43X01.U";

Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LuceneCollationTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LuceneCollationTest.java?rev=1580387&view=auto
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LuceneCollationTest.java (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LuceneCollationTest.java Sun Mar 23 00:17:56 2014
@@ -0,0 +1,254 @@
+/*
+
+   Derby - Class org.apache.derbyTesting.functionTests.tests.lang.LuceneCollationTest
+
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to you 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.tests.lang;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.util.ArrayList;
+import java.util.Arrays;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+import org.apache.derbyTesting.junit.BaseJDBCTestCase;
+import org.apache.derbyTesting.junit.CleanDatabaseTestSetup;
+import org.apache.derbyTesting.junit.Decorator;
+import org.apache.derbyTesting.junit.JDBC;
+import org.apache.derbyTesting.junit.SecurityManagerSetup;
+import org.apache.derbyTesting.junit.TestConfiguration;
+
+/**
+ * <p>
+ * Test that the Lucene plugin works on databases with territory based collation enabled.
+ * </p>
+ */
+public class LuceneCollationTest extends GeneratedColumnsHelper
+{
+    ///////////////////////////////////////////////////////////////////////////////////
+    //
+    // CONSTANTS
+    //
+    ///////////////////////////////////////////////////////////////////////////////////
+
+    private static  final   String      RUTH = "RUTH";
+
+    private static  final   String      LOAD_TOOL = "call syscs_util.syscs_register_tool( 'luceneSupport', true )";
+    private static  final   String      UNLOAD_TOOL = "call syscs_util.syscs_register_tool( 'luceneSupport', false )";
+    private static  final   String      INDEX_POEMS = "call LuceneSupport.createIndex( 'ruth', 'poems', 'poemText' )";
+    private static  final   String      UPDATE_POEMS_INDEX = "call LuceneSupport.updateIndex( 'ruth', 'poems', 'poemText' )";
+    private static  final   String      DROP_POEMS_INDEX = "call LuceneSupport.dropIndex( 'ruth', 'poems', 'poemText' )";
+
+    ///////////////////////////////////////////////////////////////////////////////////
+    //
+    // STATE
+    //
+    ///////////////////////////////////////////////////////////////////////////////////
+
+    ///////////////////////////////////////////////////////////////////////////////////
+    //
+    // CONSTRUCTOR
+    //
+    ///////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Create a new instance.
+     */
+
+    public LuceneCollationTest(String name)
+    {
+        super(name);
+    }
+
+    ///////////////////////////////////////////////////////////////////////////////////
+    //
+    // JUnit BEHAVIOR
+    //
+    ///////////////////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Construct top level suite in this JUnit test
+     */
+    public static Test suite()
+    {
+        Test        collationTest = Decorator.territoryCollatedDatabase
+            (
+             TestConfiguration.embeddedSuite( LuceneCollationTest.class ),
+             "en"
+             );
+
+        //
+        // Turn off the security manager. trying to override the default security manager
+        // with a lucene-specific policy file fails because the decorators don't compose correctly.
+        //
+        return SecurityManagerSetup.noSecurityManager( collationTest );
+    }
+
+    ///////////////////////////////////////////////////////////////////////////////////
+    //
+    // TESTS
+    //
+    ///////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * <p>
+     * Verify that the collation is what we expect.
+     * </p>
+     */
+    public  void    test_001_collation()
+        throws Exception
+    {
+        Connection  conn = getConnection();
+
+        assertResults
+            (
+             conn,
+             "values syscs_util.syscs_get_database_property( 'derby.database.collation' )",
+             new String[][]
+             {
+                 { "TERRITORY_BASED" },
+             },
+             true
+             );
+    }
+
+    /**
+     * <p>
+     * Verify that basic operations work with collation turned on.
+     * </p>
+     */
+    public  void    test_002_basic()
+        throws Exception
+    {
+        Connection  conn = openUserConnection( RUTH );
+
+        createSchema( conn );
+
+        goodStatement( conn, LOAD_TOOL );
+        goodStatement( conn, INDEX_POEMS );
+        goodStatement( conn, UPDATE_POEMS_INDEX );
+
+        assertResults
+            (
+             conn,
+             "select * from table ( ruth.poems__poemText( 'star', 0 ) ) luceneResults",
+             new String[][]
+             {
+                 { "5", "5", "4", "0.3304931" },
+                 { "3", "3", "2", "0.2832798" },
+             },
+             false
+             );
+
+        assertResults
+            (
+             conn,
+             "select id, schemaName, tableName, columnName from table ( LuceneSupport.listIndexes() ) listindexes",
+             new String[][]
+             {
+                 { "1", "RUTH", "POEMS", "POEMTEXT" },
+             },
+             false
+             );
+        
+        goodStatement( conn, DROP_POEMS_INDEX );
+        goodStatement( conn, UNLOAD_TOOL );
+
+        dropSchema( conn );
+    }
+
+    ///////////////////////////////////////////////////////////////////////////////////
+    //
+    // MINIONS
+    //
+    ///////////////////////////////////////////////////////////////////////////////////
+
+    private void    createSchema( Connection conn )  throws Exception
+    {
+        createPoemsTable( conn );
+    }
+    private void    createPoemsTable( Connection conn )
+        throws Exception
+    {
+        goodStatement
+            (
+             conn,
+             "create table poems\n" +
+             "(\n" +
+             "    poemID int,\n" +
+             "    versionStamp int not null,\n" +
+             "    originalAuthor       varchar( 50 ),\n" +
+             "    lastEditor           varchar( 50 ),\n" +
+             "    poemText            clob,\n" +
+             "    constraint poemsKey primary key( poemID, versionStamp )\n" +
+             ")\n"
+             );
+
+        PreparedStatement   ps = conn.prepareStatement( "insert into poems values ( ?, ?, ?, ?, ? )" );
+
+        int     poemID = 1;
+        int     versionStamp = 1;
+
+        ps.setInt( 1, poemID++ );
+        ps.setInt( 2, versionStamp++ );
+        ps.setString( 3, "Geoffrey Chaucer" );
+        ps.setString( 4, "Geoffrey Chaucer" );
+        ps.setString( 5, "Whan that Aprill, with his shoures soote The droghte of March hath perced to the roote And bathed every veyne in swich licour, Of which vertu engendred is the flour;" );
+        ps.executeUpdate();
+
+        ps.setInt( 1, poemID++ );
+        ps.setInt( 2, versionStamp++ );
+        ps.setString( 3, "Andrew Marvell" );
+        ps.setString( 4, "Andrew Marvell" );
+        ps.setString( 5, "Had we but world enough, and time, This coyness, lady, were no crime." );
+        ps.executeUpdate();
+
+        ps.setInt( 1, poemID++ );
+        ps.setInt( 2, versionStamp++ );
+        ps.setString( 3, "John Milton" );
+        ps.setString( 4, "John Milton" );
+        ps.setString( 5, "From morn to noon he fell, from noon to dewy eve, a summers day, and with the setting sun dropped from the ze4ith like a falling star on Lemnos, the Aegean isle" );
+        ps.executeUpdate();
+
+        ps.setInt( 1, poemID++ );
+        ps.setInt( 2, versionStamp++ );
+        ps.setString( 3, "Lord Byron" );
+        ps.setString( 4, "Lord Byron" );
+        ps.setString( 5, "The Assyrian came down like the wolf on the fold, And his cohorts were gleaming in purple and gold; And the sheen of their spears was like stars on the sea, When the blue wave rolls nightly on deep Galilee." );
+        ps.executeUpdate();
+
+        ps.setInt( 1, poemID++ );
+        ps.setInt( 2, versionStamp++ );
+        ps.setString( 3, "Walt Whitman" );
+        ps.setString( 4, "Walt Whitman" );
+        ps.setString( 5, "When lilacs last in the dooryard bloomd, And the great star early droopd in the western sky in the night, I mournd, and yet shall mourn with ever-returning spring." );
+        ps.executeUpdate();
+
+        ps.close();
+    }
+
+    private void    dropSchema( Connection conn )    throws Exception
+    {
+        goodStatement( conn, "drop table poems" );
+    }
+    
+}

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

Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LuceneSuite.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LuceneSuite.java?rev=1580387&view=auto
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LuceneSuite.java (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LuceneSuite.java Sun Mar 23 00:17:56 2014
@@ -0,0 +1,51 @@
+/*
+
+   Derby - Class org.apache.derbyTesting.functionTests.tests.lang.LuceneSuite
+
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you 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.tests.lang;
+
+import org.apache.derbyTesting.junit.BaseTestCase;
+
+import junit.framework.Test; 
+import junit.framework.TestSuite;
+
+/**
+ * Suite holding all of the tests for the Lucene plugin.
+ *
+ */
+public class LuceneSuite extends BaseTestCase
+{
+
+	/**
+	 * Use suite method instead.
+	 */
+	private LuceneSuite(String name) { super(name); }
+
+	public static Test suite()
+    {
+		TestSuite suite = new TestSuite("LuceneSuite");
+        
+        suite.addTest(LuceneSupportTest.suite());
+        suite.addTest(LuceneSupportPermsTest.suite());
+        suite.addTest(LuceneCollationTest.suite());
+
+        return suite;
+	}
+}

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

Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LuceneSupportPermsTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LuceneSupportPermsTest.java?rev=1580387&view=auto
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LuceneSupportPermsTest.java (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LuceneSupportPermsTest.java Sun Mar 23 00:17:56 2014
@@ -0,0 +1,750 @@
+/*
+
+   Derby - Class org.apache.derbyTesting.functionTests.tests.lang.LuceneSupportPermsTest
+
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to you 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.tests.lang;
+
+import java.io.File;
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.sql.SQLException;
+import java.sql.SQLWarning;
+import java.sql.Connection;
+import java.sql.Date;
+import java.sql.Statement;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.sql.Types;
+import java.util.ArrayList;
+import java.util.Arrays;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+import org.apache.derbyTesting.junit.BaseJDBCTestCase;
+import org.apache.derbyTesting.junit.JDBC;
+import org.apache.derbyTesting.junit.DatabasePropertyTestSetup;
+import org.apache.derbyTesting.junit.SecurityManagerSetup;
+import org.apache.derbyTesting.junit.TestConfiguration;
+import org.apache.derbyTesting.junit.CleanDatabaseTestSetup;
+
+/**
+ * <p>
+ * Test permissions on objects created by the optional Lucene support tool.
+ * </p>
+ */
+public class LuceneSupportPermsTest extends GeneratedColumnsHelper
+{
+    ///////////////////////////////////////////////////////////////////////////////////
+    //
+    // CONSTANTS
+    //
+    ///////////////////////////////////////////////////////////////////////////////////
+
+    private static  final   String      TEST_DBO = "TEST_DBO";
+    private static  final   String      RUTH = "RUTH";
+    private static  final   String      ALICE = "ALICE";
+    private static  final   String      FRANK = "FRANK";
+    private static  final   String[]    LEGAL_USERS = { TEST_DBO, ALICE, RUTH, FRANK  };
+
+	private static  final   String      AUTH_NO_ACCESS_NOT_OWNER    = "42507";
+	private static  final   String      DBO_ONLY                                = "4251D";
+    private static  final   String      FUNCTION_EXISTS                 = "X0Y68";
+
+    private static  final   String      NOT_INDEXABLE                   = "42XBA";
+    private static  final   String      NO_PRIMARY_KEY              = "42XBB";
+    // LUCENE_UNSUPPORTED_TYPE = "42XBC": only raised if key type is unsupported. but all indexable types are supported.
+    // LUCENE_INVALID_CHARACTER = "42XBD" is tested by LuceneSupportTest.
+    private static  final   String      NONEXISTENT_INDEX           = "42XBE";
+	private static  final   String      NO_DDL_PRIV                    = "42XBF";
+	private static  final   String      DOUBLE_LOAD_ILLEGAL         = "42XBG";
+	private static  final   String      DOUBLE_UNLOAD_ILLEGAL       = "42XBH";
+	private static  final   String      BAD_DIRECTORY                      = "42XBI";
+
+    private static  final   String      POLICY_FILE = "org/apache/derbyTesting/functionTests/tests/lang/luceneSupport.policy";
+
+    private static  final   String      LOAD_TOOL = "call syscs_util.syscs_register_tool( 'luceneSupport', true )";
+    private static  final   String      UNLOAD_TOOL = "call syscs_util.syscs_register_tool( 'luceneSupport', false )";
+    private static  final   String      INDEX_POEMS = "call LuceneSupport.createIndex( 'ruth', 'poems', 'poemText' )";
+    private static  final   String      UPDATE_POEMS_INDEX = "call LuceneSupport.updateIndex( 'ruth', 'poems', 'poemText' )";
+    private static  final   String      DROP_POEMS_INDEX = "call LuceneSupport.dropIndex( 'ruth', 'poems', 'poemText' )";
+
+    private static  final   long        MILLIS_IN_HOUR = 1000L * 60L * 60L;
+    private static  final   long        MILLIS_IN_DAY = MILLIS_IN_HOUR * 24L;
+
+    ///////////////////////////////////////////////////////////////////////////////////
+    //
+    // STATE
+    //
+    ///////////////////////////////////////////////////////////////////////////////////
+
+    ///////////////////////////////////////////////////////////////////////////////////
+    //
+    // CONSTRUCTOR
+    //
+    ///////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Create a new instance.
+     */
+
+    public LuceneSupportPermsTest(String name)
+    {
+        super(name);
+    }
+
+    ///////////////////////////////////////////////////////////////////////////////////
+    //
+    // JUnit BEHAVIOR
+    //
+    ///////////////////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Construct top level suite in this JUnit test
+     */
+    public static Test suite()
+    {
+        TestSuite suite = (TestSuite) TestConfiguration.embeddedSuite(LuceneSupportPermsTest.class);
+
+        Test        secureTest = new SecurityManagerSetup( suite, POLICY_FILE );
+        Test        authenticatedTest = DatabasePropertyTestSetup.builtinAuthentication
+            ( secureTest, LEGAL_USERS, "LuceneSupportPermissions" );
+        Test        authorizedTest = TestConfiguration.sqlAuthorizationDecorator( authenticatedTest );
+
+        return authorizedTest;
+    }
+
+    ///////////////////////////////////////////////////////////////////////////////////
+    //
+    // TESTS
+    //
+    ///////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * <p>
+     * Test baseline permissions where no grants are made.
+     * </p>
+     */
+    public  void    test_001_basicNoGrant()
+        throws Exception
+    {
+        Connection  dboConnection = openUserConnection( TEST_DBO );
+        Connection  ruthConnection = openUserConnection( RUTH );
+        Connection  aliceConnection = openUserConnection( ALICE );
+
+        createSchema( ruthConnection, Types.INTEGER );
+
+        // ruth does not have permission to load the tool
+        expectExecutionError( ruthConnection, LACK_EXECUTE_PRIV, LOAD_TOOL );
+
+        // but the dbo has permission
+        goodStatement( dboConnection, LOAD_TOOL );
+
+        // can't update a non-existent index
+        expectExecutionError( ruthConnection, NONEXISTENT_INDEX, "call LuceneSupport.updateIndex( 'ruth', 'poems', 'poemText' )" );
+
+        // alice does not have permission to index a table owned by ruth
+        expectExecutionError( aliceConnection, LACK_COLUMN_PRIV, INDEX_POEMS );
+
+        // but ruth can
+        goodStatement( ruthConnection, INDEX_POEMS );
+
+        // redundant index creation fails
+        expectExecutionError( ruthConnection, FUNCTION_EXISTS, INDEX_POEMS );
+
+        // can't update a non-existent index
+        expectExecutionError( ruthConnection, NONEXISTENT_INDEX, "call LuceneSupport.updateIndex( 'ruth', 'poems', 'foo' )" );
+        expectExecutionError( ruthConnection, NONEXISTENT_INDEX, "call LuceneSupport.updateIndex( 'ruth', 'poems', 'originalAuthor' )" );
+
+        // alice can't view an index created by ruth
+        String  viewPoemsIndex = "select * from table ( ruth.poems__poemText( 'star', 0 ) ) luceneResults";
+        expectExecutionError( aliceConnection, LACK_EXECUTE_PRIV, viewPoemsIndex );
+
+        // but ruth can
+        assertResults
+            (
+             ruthConnection,
+             viewPoemsIndex,
+             new String[][]
+             {
+                 { "5", "5", "4", "0.3304931" },
+                 { "3", "3", "2", "0.2832798" },
+             },
+             false
+             );
+
+        // alice can list indexes even on tables owned by ruth
+        String  listIndexes = "select id, schemaName, tableName, columnName from table ( LuceneSupport.listIndexes() ) listindexes";
+        assertResults
+            (
+             aliceConnection,
+             listIndexes,
+             new String[][]
+             {
+                 { "1", "RUTH", "POEMS", "POEMTEXT" },
+             },
+             false
+             );
+
+        // alice cannot update an index owned by ruth
+        expectExecutionError( aliceConnection, NO_DDL_PRIV, UPDATE_POEMS_INDEX );
+        
+        // alice cannot drop an index owned by ruth
+        expectExecutionError( aliceConnection, AUTH_NO_ACCESS_NOT_OWNER, DROP_POEMS_INDEX );
+
+        // ruth can update the index
+        goodStatement( ruthConnection, UPDATE_POEMS_INDEX );
+
+        // dropping the key prevents you from re-indexing
+        goodStatement( ruthConnection, "alter table poems drop constraint poemsKey" );
+        expectExecutionError( ruthConnection, NO_PRIMARY_KEY, UPDATE_POEMS_INDEX );
+        
+        // ruth can drop the index
+        goodStatement( ruthConnection, DROP_POEMS_INDEX );
+        assertResults
+            (
+             ruthConnection,
+             listIndexes,
+             new String[][] {},
+             false
+             );
+
+        // redundant drop fails, however
+        expectExecutionError( ruthConnection, NONEXISTENT_OBJECT, DROP_POEMS_INDEX );
+
+        // ruth cannot unload the tool
+        expectExecutionError( ruthConnection, LACK_EXECUTE_PRIV, UNLOAD_TOOL );
+
+        // but the dbo can
+        goodStatement( dboConnection, UNLOAD_TOOL );
+
+        dropSchema( ruthConnection );
+    }
+
+    /**
+     * <p>
+     * Test that a user can grant access to her indexes.
+     * </p>
+     */
+    public  void    test_002_userGrant()
+        throws Exception
+    {
+        Connection  dboConnection = openUserConnection( TEST_DBO );
+        Connection  ruthConnection = openUserConnection( RUTH );
+        Connection  aliceConnection = openUserConnection( ALICE );
+
+        createSchema( ruthConnection, Types.INTEGER );
+
+        // load the Lucene plugin
+        goodStatement( dboConnection, LOAD_TOOL );
+
+        // ruth indexes her table and grants alice privilege to run the index reading function
+        goodStatement( ruthConnection, INDEX_POEMS );
+
+        Permission[]    permissions = new Permission[]
+        {
+            new Permission( "execute on function poems__poemText", NO_GENERIC_PERMISSION ),
+            new Permission( "select ( poemID ) on poems", NO_SELECT_OR_UPDATE_PERMISSION ),
+            new Permission( "select ( versionStamp ) on poems", NO_SELECT_OR_UPDATE_PERMISSION ),
+            new Permission( "select ( poemText ) on poems", NO_SELECT_OR_UPDATE_PERMISSION ),
+        };
+        for ( Permission permission : permissions )
+        {
+            grantPermission( ruthConnection, permission.text, ALICE );
+        }
+
+        // but alice still needs select privilege on the base table columns
+        String  viewPoemsIndex = "select * from table ( ruth.poems__poemText( 'star', 0 ) ) luceneResults";
+        String[][]  viewPoemsIndexResults = new String[][]
+            {
+                { "5", "5", "4", "0.3304931" },
+                { "3", "3", "2", "0.2832798" },
+            };
+
+        // now alice can view the index
+        assertResults( aliceConnection, viewPoemsIndex, viewPoemsIndexResults, false );
+
+        // now revoke each permission and verify that it is needed
+        for ( Permission permission : permissions )
+        {
+            vetPermission_002( permission, ruthConnection, aliceConnection, viewPoemsIndex, viewPoemsIndexResults );
+        }
+
+        // but alice still can't drop an index owned by ruth
+        expectExecutionError( aliceConnection, AUTH_NO_ACCESS_NOT_OWNER, DROP_POEMS_INDEX );
+
+        // unload the plugin
+        goodStatement( dboConnection, UNLOAD_TOOL );
+
+        dropSchema( ruthConnection );
+    }
+    private void    vetPermission_002
+        (
+         Permission permission,
+         Connection ruthConnection,
+         Connection aliceConnection,
+         String statement,
+         String[][] expectedResults
+         )
+        throws Exception
+    {
+        revokePermission( ruthConnection, permission.text, ALICE );
+        expectExecutionError( aliceConnection, permission.sqlStateWhenMissing, statement );
+        grantPermission( ruthConnection, permission.text, ALICE );
+        assertResults( aliceConnection, statement, expectedResults, false );
+    }
+    private void    grantPermission( Connection conn, String permission, String grantee )
+        throws Exception
+    {
+        String  command = "grant " + permission + " to " + grantee;
+
+        goodStatement( conn, command );
+    }
+    private void    revokePermission( Connection conn, String permission, String grantee )
+        throws Exception
+    {
+        String  command = "revoke " + permission + " from " + grantee;
+        if ( permission.startsWith( "execute" ) || permission.startsWith( "usage" ) )   { command += " restrict"; }
+
+        goodStatement( conn, command );
+    }
+
+    /**
+     * <p>
+     * Test that only the DBO can (un)load the tool and the tool
+     * can't be (un)loaded twice.
+     * </p>
+     */
+    public  void    test_003_loading()
+        throws Exception
+    {
+        Connection  dboConnection = openUserConnection( TEST_DBO );
+        Connection  ruthConnection = openUserConnection( RUTH );
+
+        goodStatement( dboConnection, "grant execute on procedure syscs_util.syscs_register_tool to public" );
+
+        // only the DBO can load the tool
+        expectExecutionError( ruthConnection, DBO_ONLY, LOAD_TOOL );
+
+        goodStatement( dboConnection, LOAD_TOOL );
+        expectExecutionError( dboConnection, DOUBLE_LOAD_ILLEGAL, LOAD_TOOL );
+
+        // cannot index non-existent table or column
+        expectExecutionError( ruthConnection, NOT_INDEXABLE, "call LuceneSupport.createIndex( 'ruth', 'foo', 'poemText' )" );
+        expectExecutionError( ruthConnection, NOT_INDEXABLE, "call LuceneSupport.createIndex( 'ruth', 'poems', 'fooText' )" );
+        expectExecutionError( ruthConnection, NOT_INDEXABLE, "call LuceneSupport.createIndex( 'ruth', 'poems', 'versionStamp' )" );
+
+        // cannot drop non-existent index
+        expectExecutionError( ruthConnection, NONEXISTENT_OBJECT, "call LuceneSupport.dropIndex( 'ruth', 'foo', 'poemText' )" );
+        expectExecutionError( ruthConnection, NONEXISTENT_OBJECT, "call LuceneSupport.dropIndex( 'ruth', 'poems', 'versionStamp' )" );
+        
+        // only the DBO can unload the tool
+        expectExecutionError( ruthConnection, DBO_ONLY, UNLOAD_TOOL );
+
+        goodStatement( dboConnection, "revoke execute on procedure syscs_util.syscs_register_tool from public restrict" );
+
+        goodStatement( dboConnection, UNLOAD_TOOL );
+        expectExecutionError( dboConnection, DOUBLE_UNLOAD_ILLEGAL, UNLOAD_TOOL );
+
+        // try loading and unloading again for good measure
+        goodStatement( dboConnection, LOAD_TOOL );
+        goodStatement( dboConnection, UNLOAD_TOOL );
+    }
+    
+    /**
+     * <p>
+     * Test all datatypes as key types.
+     * </p>
+     */
+    public  void    test_004_datatypes()
+        throws Exception
+    {
+        Connection  dboConnection = openUserConnection( TEST_DBO );
+        Connection  ruthConnection = openUserConnection( RUTH );
+
+        goodStatement( dboConnection, LOAD_TOOL );
+
+        vet_004( ruthConnection, Types.BIGINT );
+        vet_004( ruthConnection, Types.BOOLEAN );
+        vet_004( ruthConnection, Types.CHAR );
+        vet_004( ruthConnection, Types.BINARY );
+        vet_004( ruthConnection, Types.DATE );
+        vet_004( ruthConnection, Types.DECIMAL );
+        vet_004( ruthConnection, Types.DOUBLE );
+        vet_004( ruthConnection, Types.FLOAT );
+        vet_004( ruthConnection, Types.INTEGER );
+        vet_004( ruthConnection, Types.NUMERIC );
+        vet_004( ruthConnection, Types.REAL );
+        vet_004( ruthConnection, Types.SMALLINT );
+        vet_004( ruthConnection, Types.TIME );
+        vet_004( ruthConnection, Types.TIMESTAMP );
+        vet_004( ruthConnection, Types.VARCHAR );
+        vet_004( ruthConnection, Types.VARBINARY );
+
+        goodStatement( dboConnection, UNLOAD_TOOL );
+    }
+    private void    vet_004( Connection ruthConnection, int jdbcType )
+        throws Exception
+    {
+        createSchema( ruthConnection, jdbcType );
+        goodStatement( ruthConnection, INDEX_POEMS );
+
+        // make sure that we can de-serialize the key
+        assertResults
+            (
+             ruthConnection,
+             "select p.originalAuthor, i.rank\n" +
+             "from ruth.poems p, table ( ruth.poems__poemText( 'star', 0 ) ) i\n" +
+             "where p.poemID = i.poemID and p.versionStamp = i.versionStamp\n" +
+             "order by i.rank desc\n",
+             new String[][]
+             {
+                 { "Walt Whitman", "0.3304931" },
+                 { "John Milton", "0.2832798" },
+             },
+             false
+             );
+
+        goodStatement( ruthConnection, DROP_POEMS_INDEX );
+        dropSchema( ruthConnection );
+    }
+
+    /**
+     * <p>
+     * Test error messages when a lucene directory has been deleted.
+     * </p>
+     */
+    public  void    test_005_deleteDirectory()
+        throws Exception
+    {
+        Connection  dboConnection = openUserConnection( TEST_DBO );
+        Connection  ruthConnection = openUserConnection( RUTH );
+
+        createSchema( ruthConnection, Types.INTEGER );
+        goodStatement( dboConnection, LOAD_TOOL );
+        goodStatement( ruthConnection, INDEX_POEMS );
+
+        TestConfiguration   config = getTestConfiguration();
+
+        String  dbName = config.getDefaultDatabaseName();
+        String  physicalDBName = config.getPhysicalDatabaseName( dbName );
+        String  dbPath = config.getDatabasePath( physicalDBName );
+        File    dbDirectory = new File( dbPath );
+        File    luceneDirectory = new File( dbDirectory, "lucene" );
+        File    ruthDirectory = new File( luceneDirectory, "RUTH" );
+        File    poemsDirectory = new File( ruthDirectory, "POEMS" );
+        File    poemTextIndexDirectory = new File( poemsDirectory, "POEMTEXT" );
+
+        assertTrue( deleteFile( poemTextIndexDirectory ) );
+
+        // can't update the index if the directory has disappeared
+        expectExecutionError( ruthConnection, BAD_DIRECTORY, UPDATE_POEMS_INDEX );
+        expectExecutionError( ruthConnection, BAD_DIRECTORY, DROP_POEMS_INDEX );
+
+        goodStatement( dboConnection, UNLOAD_TOOL );
+        dropSchema( ruthConnection );
+    }
+    
+    ///////////////////////////////////////////////////////////////////////////////////
+    //
+    // MINIONS
+    //
+    ///////////////////////////////////////////////////////////////////////////////////
+
+    private void    createSchema( Connection ruthConnection, int jdbcType )  throws Exception
+    {
+        createPoemsTable( ruthConnection, jdbcType );
+    }
+    private void    createPoemsTable( Connection conn, int jdbcType )
+        throws Exception
+    {
+        goodStatement
+            (
+             conn,
+             "create table poems\n" +
+             "(\n" +
+             "    poemID " + getType( jdbcType ) + ",\n" +
+             "    versionStamp int not null,\n" +
+             "    originalAuthor       varchar( 50 ),\n" +
+             "    lastEditor           varchar( 50 ),\n" +
+             "    poemText            clob,\n" +
+             "    constraint poemsKey primary key( poemID, versionStamp )\n" +
+             ")\n"
+             );
+
+        PreparedStatement   ps = conn.prepareStatement( "insert into poems values ( ?, ?, ?, ?, ? )" );
+
+        int     poemID = 1;
+        int     versionStamp = 1;
+
+        setNextPoemID( ps, jdbcType, poemID++ );
+        ps.setInt( 2, versionStamp++ );
+        ps.setString( 3, "Geoffrey Chaucer" );
+        ps.setString( 4, "Geoffrey Chaucer" );
+        ps.setString( 5, "Whan that Aprill, with his shoures soote The droghte of March hath perced to the roote And bathed every veyne in swich licour, Of which vertu engendred is the flour;" );
+        ps.executeUpdate();
+
+        setNextPoemID( ps, jdbcType, poemID++ );
+        ps.setInt( 2, versionStamp++ );
+        ps.setString( 3, "Andrew Marvell" );
+        ps.setString( 4, "Andrew Marvell" );
+        ps.setString( 5, "Had we but world enough, and time, This coyness, lady, were no crime." );
+        ps.executeUpdate();
+
+        setNextPoemID( ps, jdbcType, poemID++ );
+        ps.setInt( 2, versionStamp++ );
+        ps.setString( 3, "John Milton" );
+        ps.setString( 4, "John Milton" );
+        ps.setString( 5, "From morn to noon he fell, from noon to dewy eve, a summers day, and with the setting sun dropped from the ze4ith like a falling star on Lemnos, the Aegean isle" );
+        ps.executeUpdate();
+
+        setNextPoemID( ps, jdbcType, poemID++ );
+        ps.setInt( 2, versionStamp++ );
+        ps.setString( 3, "Lord Byron" );
+        ps.setString( 4, "Lord Byron" );
+        ps.setString( 5, "The Assyrian came down like the wolf on the fold, And his cohorts were gleaming in purple and gold; And the sheen of their spears was like stars on the sea, When the blue wave rolls nightly on deep Galilee." );
+        ps.executeUpdate();
+
+        setNextPoemID( ps, jdbcType, poemID++ );
+        ps.setInt( 2, versionStamp++ );
+        ps.setString( 3, "Walt Whitman" );
+        ps.setString( 4, "Walt Whitman" );
+        ps.setString( 5, "When lilacs last in the dooryard bloomd, And the great star early droopd in the western sky in the night, I mournd, and yet shall mourn with ever-returning spring." );
+        ps.executeUpdate();
+
+        ps.close();
+    }
+
+    private String  getType( int jdbcType ) throws Exception
+    {
+        switch( jdbcType )
+        {
+        case Types.BINARY: return "char( 100 ) for bit data";
+        case Types.BOOLEAN: return "boolean";
+        case Types.DECIMAL: return "decimal";
+        case Types.INTEGER: return "int";
+        case Types.BIGINT: return "bigint";
+        case Types.SMALLINT: return "smallint";
+        case Types.DOUBLE: return "double";
+        case Types.FLOAT: return "real";
+        case Types.NUMERIC: return "numeric";
+        case Types.CHAR: return "char( 5 )";
+        case Types.REAL: return "real";
+        case Types.VARCHAR: return "varchar( 5 )";
+        case Types.VARBINARY: return "varchar( 256 ) for bit data";
+        case Types.DATE: return "date";
+        case Types.TIME: return "time";
+        case Types.TIMESTAMP: return "timestamp";
+
+        default:    throw new Exception( "Unsupported datatype: " + jdbcType );
+        }
+    }
+
+    private void    setNextPoemID( PreparedStatement ps, int jdbcType, int intPoemID )
+        throws Exception
+    {
+        switch( jdbcType )
+        {
+        case Types.BINARY:
+            ps.setBytes( 1, makeBytes( intPoemID ) );
+            break;
+
+        case Types.BOOLEAN:
+            ps.setBoolean( 1, (intPoemID % 2 == 0) ? true : false );
+            break;
+
+        case Types.DECIMAL:
+        case Types.NUMERIC:
+            ps.setBigDecimal( 1, new BigDecimal( intPoemID ) );
+            break;
+
+        case Types.INTEGER:
+            ps.setInt( 1, intPoemID );
+            break;
+
+        case Types.BIGINT:
+            ps.setLong( 1, (long) intPoemID + (long) Integer.MAX_VALUE );
+            break;
+
+        case Types.SMALLINT:
+            ps.setShort( 1, (short) intPoemID );
+            break;
+
+        case Types.DOUBLE:
+            ps.setDouble( 1, (double) intPoemID );
+            break;
+
+        case Types.FLOAT:
+        case Types.REAL:
+            ps.setFloat( 1, (float) intPoemID );
+            break;
+
+        case Types.CHAR:
+        case Types.VARCHAR:
+            ps.setString( 1, makeStringKey( intPoemID ) );
+            break;
+
+        case Types.VARBINARY:
+            ps.setBytes( 1, makeAllBytes( intPoemID ) );
+            break;
+
+        case Types.DATE:
+            ps.setDate( 1, new Date( MILLIS_IN_DAY * (long)(500 + intPoemID) ) );
+            break;
+
+        case Types.TIME:
+            ps.setTime( 1, new Time( MILLIS_IN_HOUR * (long)(intPoemID) ) );
+            break;
+
+        case Types.TIMESTAMP:
+            ps.setTimestamp( 1, new Timestamp( MILLIS_IN_DAY * (long)(500 + intPoemID) ) );
+            break;
+
+        default:    throw new Exception( "Unsupported datatype: " + jdbcType );
+        }
+    }
+    private String  makeStringKey( int key )
+    {
+        String  digit = Integer.toString( key );
+        return digit + digit + digit + digit + digit;
+    }
+
+    private void    dropSchema( Connection ruthConnection )    throws Exception
+    {
+        goodStatement( ruthConnection, "drop table poems" );
+    }
+    
+    ///////////////////////////////////////////////////////////////////////////////////
+    //
+    // PROCEDURES AND FUNCTIONS
+    //
+    ///////////////////////////////////////////////////////////////////////////////////
+
+    public  static  String  toString( byte[] value )
+    {
+        if ( value == null ) { return null; }
+
+        return Arrays.toString( value );
+    }
+
+    /** Make a byte array with all possible byte values in it */
+    public  static  byte[]  makeAllBytes( int initialValue )
+    {
+        int     size = 2 * ( -Byte.MIN_VALUE );
+        byte[]  result = new byte[ size ];
+        int     value = initialValue;
+
+        if ( value < Byte.MIN_VALUE ) { value = Byte.MIN_VALUE; }
+        if ( value > Byte.MAX_VALUE ) { value = Byte.MAX_VALUE; }
+
+        for ( int idx = 0; idx < size; idx++ )
+        {
+            result[ idx ] = (byte) (value++);
+
+            if ( value > Byte.MAX_VALUE ) { value = Byte.MIN_VALUE; }
+        }
+
+        return result;
+    }
+    
+    /** Make a byte array starting with the given byte */
+    public  static  byte[]  makeBytes( int initialValue )
+    {
+        byte[]  result = new byte[ initialValue ];
+
+        for ( int idx = 0; idx < initialValue; idx++ )
+        {
+            result[ idx ] = (byte) initialValue;
+        }
+
+        return result;
+    }
+    
+    /**
+     * Delete a file. If it's a directory, recursively delete all directories
+     * and files underneath it first.
+     */
+    private boolean deleteFile( File file )
+        throws IOException, PrivilegedActionException
+    {
+        boolean retval = true;
+        
+        if ( isDirectory( file ) )
+        {
+            for ( File child : listFiles( file ) ) { retval = retval && deleteFile( child ); }
+        }
+
+        return retval && clobberFile( file );
+    }
+
+    /** Return true if the file is a directory */
+    private boolean isDirectory( final File file )
+        throws IOException, PrivilegedActionException
+    {
+        return AccessController.doPrivileged
+            (
+             new PrivilegedExceptionAction<Boolean>()
+             {
+                public Boolean run() throws IOException
+                {
+                    if ( file == null ) { return false; }
+                    else { return file.isDirectory(); }
+                }
+             }
+             ).booleanValue();
+    }
+
+    /** Really delete a file */
+    private boolean clobberFile( final File file )
+        throws IOException, PrivilegedActionException
+    {
+        return AccessController.doPrivileged
+            (
+             new PrivilegedExceptionAction<Boolean>()
+             {
+                public Boolean run() throws IOException
+                {
+                    return file.delete();
+                }
+             }
+             ).booleanValue();
+    }
+
+    /** List files */
+    private File[]  listFiles( final File file )
+        throws IOException, PrivilegedActionException
+    {
+        return AccessController.doPrivileged
+            (
+             new PrivilegedExceptionAction<File[]>()
+             {
+                public File[] run() throws IOException
+                {
+                    return file.listFiles();
+                }
+             }
+             );
+    }
+
+}

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

Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LuceneSupportTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LuceneSupportTest.java?rev=1580387&view=auto
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LuceneSupportTest.java (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LuceneSupportTest.java Sun Mar 23 00:17:56 2014
@@ -0,0 +1,275 @@
+/**
+ *  Derby - Class org.apache.derbyTesting.functionTests.tests.lang.LuceneSupportTest
+ *  
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.tests.lang;
+
+import java.sql.CallableStatement;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.apache.derby.shared.common.reference.SQLState;
+import org.apache.derbyTesting.junit.BaseJDBCTestCase;
+import org.apache.derbyTesting.junit.JDBC;
+import org.apache.derbyTesting.junit.SecurityManagerSetup;
+import org.apache.derbyTesting.junit.TestConfiguration;
+
+/**
+ * <p>
+ * Basic test of the optional tool which provides Lucene indexing of
+ * columns in Derby tables.
+ * </p>
+ */
+public class LuceneSupportTest extends BaseJDBCTestCase {
+
+    private static  final   String  ILLEGAL_CHARACTER = "42XBD";
+    
+	public LuceneSupportTest(String name) {
+		super(name);
+	}
+	
+	public static Test suite() {
+		TestSuite suite = new TestSuite("LuceneSupportTest");
+		
+		suite.addTest(SecurityManagerSetup.noSecurityManager(TestConfiguration.embeddedSuite(LuceneSupportTest.class)));
+ 
+		return suite;
+	}
+	
+	public void testCreateAndQueryIndex() throws Exception {
+		CallableStatement cSt;
+		Statement s = createStatement();
+	    
+		cSt = prepareCall
+            ( "call LuceneSupport.createIndex('lucenetest','titles','title')" );
+	    assertUpdateCount(cSt, 0);
+	    
+	    String[][] expectedRows = new String[][]
+            {
+                { "1","0","0.8048013" },
+	    		{ "3","2","0.643841" }
+            };
+	    JDBC.assertFullResultSet
+            (
+             s.executeQuery
+             (
+              "select * from table ( lucenetest.titles__title( 'grapes', 0 ) ) luceneResults"
+              ),
+             expectedRows
+             );
+
+	    expectedRows = new String[][]
+            {
+	    		{ "3","2","0.643841" }
+            };
+	    JDBC.assertFullResultSet
+            (
+             s.executeQuery
+             (
+              "select * from table ( lucenetest.titles__title( 'grapes', .75 ) ) luceneResults"
+              ),
+             expectedRows
+             );
+
+	    JDBC.assertEmpty
+            (
+             s.executeQuery
+             (
+              "select * from table ( lucenetest.titles__title( 'grapes',  0.5) ) luceneResults"
+              )
+             );
+
+	    expectedRows = new String[][]
+            {
+                { "The Grapes Of Wrath", "John Steinbeck", "The Viking Press", "0"},
+	    		{"Vines, Grapes, and Wines", "Jancis Robinson", "Alfred A. Knopf", "2"}
+            };
+	    JDBC.assertFullResultSet
+            (
+             s.executeQuery
+             (
+              "select title, author, publisher, documentID\n" +
+              "from lucenetest.titles t, table ( lucenetest.titles__title( 'grapes', 0 ) ) l\n" +
+              "where t.id = l.id\n" 
+              ),
+             expectedRows
+             );
+	   
+		cSt = prepareCall
+            ( "call LuceneSupport.dropIndex('lucenetest','titles','title')" );
+	    assertUpdateCount(cSt, 0);
+
+	}
+	
+	public void testUpdateIndex() throws Exception {
+		CallableStatement cSt;
+		Statement s = createStatement();
+		
+		cSt = prepareCall
+            ( "call LuceneSupport.createIndex('lucenetest','titles','title')" );
+	    assertUpdateCount(cSt, 0);
+
+	    JDBC.assertEmpty
+            (
+             s.executeQuery
+             (
+              "select *\n" +
+              "from table ( lucenetest.titles__title( 'mice', 0 ) ) luceneResults\n"
+              )
+             );
+	    
+	    cSt = prepareCall( "update TITLES SET TITLE='Of Mice and Men' WHERE ID=1" );
+	    assertUpdateCount(cSt, 1);
+	    
+	    JDBC.assertEmpty
+            (
+             s.executeQuery
+             (
+              "select *\n" +
+              "from table ( lucenetest.titles__title( 'mice', 0 ) ) luceneResults\n"
+              )
+             );
+	    
+		cSt = prepareCall
+            ( "call LuceneSupport.updateIndex('lucenetest','titles','title')" );
+	    assertUpdateCount(cSt, 0);
+
+	    String[][] expectedRows = new String[][]
+            {
+                { "1","0","1.058217" }
+            };
+	    JDBC.assertFullResultSet
+            (
+             s.executeQuery
+             (
+              "select *\n" +
+              "from table ( lucenetest.titles__title( 'mice', 0 ) ) luceneResults\n"
+              ),
+             expectedRows
+             );
+
+		cSt = prepareCall
+            ( "call LuceneSupport.dropIndex('lucenetest','titles','title')" );
+	    assertUpdateCount(cSt, 0);
+
+	}
+	
+	public void testListIndex() throws Exception {
+		CallableStatement cSt;
+		Statement s = createStatement();
+
+	    cSt = prepareCall
+            ( "call LuceneSupport.createIndex('lucenetest','titles','title')" );
+	    assertUpdateCount(cSt, 0);
+	    
+		cSt = prepareCall
+            ( "call LuceneSupport.createIndex('lucenetest','titles','author')" );
+	    assertUpdateCount(cSt, 0);
+	    
+	    // leave out lastmodified as the date will change
+	    String[][] expectedRows = new String[][]
+            {
+                { "1", "LUCENETEST", "TITLES", "AUTHOR" },
+	    		{ "2", "LUCENETEST", "TITLES", "TITLE" }
+            };
+	    JDBC.assertFullResultSet
+            (
+             s.executeQuery
+             (
+              "select id, schemaname, tablename, columnname from table ( LuceneSupport.listIndexes() ) listindexes"
+              ),
+             expectedRows
+             );
+
+		cSt = prepareCall
+            ( "call LuceneSupport.dropIndex('lucenetest','titles','title')" );
+	    assertUpdateCount(cSt, 0);
+
+	    expectedRows = new String[][]
+            {
+                { "1", "LUCENETEST", "TITLES", "AUTHOR" },
+            };
+	    JDBC.assertFullResultSet
+            (
+             s.executeQuery
+             (
+              "select id, schemaname, tablename, columnname from table ( LuceneSupport.listIndexes() ) listindexes"
+              ),
+             expectedRows
+             );
+
+		cSt = prepareCall
+            ( "call LuceneSupport.dropIndex('lucenetest','titles','author')" );
+	    assertUpdateCount(cSt, 0);
+	    
+	    JDBC.assertEmpty
+            (
+             s.executeQuery
+             (
+              "select id, schemaname, tablename, columnname from table ( LuceneSupport.listIndexes() ) listindexes"
+              )
+             );
+
+	}
+	
+	public void testDropIndexBadCharacters() throws Exception {
+		CallableStatement st;
+	    
+		assertCallError( ILLEGAL_CHARACTER, "call LuceneSupport.dropIndex('../','','')");
+		assertCallError( ILLEGAL_CHARACTER, "call LuceneSupport.dropIndex('','../','')");
+		assertCallError( ILLEGAL_CHARACTER, "call LuceneSupport.dropIndex('','','../')");
+		
+	}
+	
+	protected void setUp() throws SQLException {
+		CallableStatement cSt;			    
+		Statement st = createStatement();
+		
+		try {
+			st.executeUpdate("create schema lucenetest");
+		} catch (Exception e) {
+		}
+		st.executeUpdate("set schema lucenetest");	
+		st.executeUpdate("create table titles (ID int generated always as identity primary key, ISBN varchar(16), PRINTISBN varchar(16), title varchar(1024), subtitle varchar(1024), author varchar(1024), series varchar(1024), publisher varchar(1024), collections varchar(128), collections2 varchar(128))");
+		st.executeUpdate("insert into titles (ISBN, PRINTISBN, TITLE, SUBTITLE, AUTHOR, SERIES, PUBLISHER, COLLECTIONS, COLLECTIONS2) values ('9765087650324','9765087650324','The Grapes Of Wrath','The Great Depression in Oklahoma','John Steinbeck','Noble Winners','The Viking Press','National Book Award','Pulitzer Prize')");
+		st.executeUpdate("insert into titles (ISBN, PRINTISBN, TITLE, SUBTITLE, AUTHOR, SERIES, PUBLISHER, COLLECTIONS, COLLECTIONS2) values ('6754278542987','6754278542987','Identical: Portraits of Twins','Best Photo Book 2012 by American Photo Magazine','Martin Schoeller','Portraits','teNeues','Photography','')");
+		st.executeUpdate("insert into titles (ISBN, PRINTISBN, TITLE, SUBTITLE, AUTHOR, SERIES, PUBLISHER, COLLECTIONS, COLLECTIONS2) values ('2747583475882','2747583475882','Vines, Grapes, and Wines','The wine drinker''s guide to grape varieties','Jancis Robinson','Reference','Alfred A. Knopf','Wine','')");	
+		st.executeUpdate("insert into titles (ISBN, PRINTISBN, TITLE, SUBTITLE, AUTHOR, SERIES, PUBLISHER, COLLECTIONS, COLLECTIONS2) values ('4356123483483','4356123483483','A Tale of Two Cities','A fictional account of events leading up to the French revolution','Charles Dickens','Classics','Chapman & Hall','Fiction','Social Criticism')");	
+
+		cSt = prepareCall
+            ( "call syscs_util.syscs_register_tool('luceneSupport',true)" );
+	    assertUpdateCount(cSt, 0);
+
+	}
+	
+	protected void tearDown() throws Exception {
+		CallableStatement cSt;
+		Statement st = createStatement();
+		
+		st.executeUpdate("drop table titles");
+		
+		cSt = prepareCall
+            ( "call syscs_util.syscs_register_tool('luceneSupport',false)" );
+	    assertUpdateCount(cSt, 0);
+	    super.tearDown();
+	}
+}

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

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/_Suite.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/_Suite.java?rev=1580387&r1=1580386&r2=1580387&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/_Suite.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/_Suite.java Sun Mar 23 00:17:56 2014
@@ -254,6 +254,7 @@ public class _Suite extends BaseTestCase
         suite.addTest(Test_6496.suite());
         suite.addTest(ConstraintCharacteristicsTest.suite());
         suite.addTest(DB2IsolationLevelsTest.suite());
+        suite.addTest(LuceneSuite.suite());
         suite.addTest(ConsistencyCheckerTest.suite());
         suite.addTest(Derby5866TriggerOrderTest.suite());
         return suite;

Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/luceneSupport.policy
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/luceneSupport.policy?rev=1580387&view=auto
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/luceneSupport.policy (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/luceneSupport.policy Sun Mar 23 00:17:56 2014
@@ -0,0 +1,465 @@
+//
+// *  Derby - Class org.apache.derbyTesting.functionTests.util.derby_tests.policy
+// *  
+// * Licensed to the Apache Software Foundation (ASF) under one
+// * or more contributor license agreements.  See the NOTICE file
+// * distributed with this work for additional information
+// * regarding copyright ownership.  The ASF licenses this file
+// * to you 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.
+// *
+
+//
+// Policy file with minimal set of permissions to run derby's
+// functional tests.
+//
+// The test harness sets up four variables used by this policy file
+//
+// derbyTesting.codejar - URL to the jar files when they are in the classpath
+// derbyTesting.codeclasses - URL to the classes directory when it is in the classpath
+//
+// Only one of derbyTesting.codejar and derbyTesting.codeclasses will be valid, the
+// other will be set to a bogus URL like file://unused
+//
+// derbyTesting.codedir - File location of either derbyTesting.codejar or derbyTesting.codeclasses.
+// Only required due to a BUG (see below for more info).
+//
+// derbyTesting.jaxpjar - URL to the jar file containing the JAXP implementation
+//     for XML-based tests (ex. lang/XMLBindingTest.java).
+//
+// derbyTesting.serverhost - Host name or ip where network server is started 
+// derbyTesting.clienthost - specifies the clients ip address/hostName. 
+//     when testing with networkserver on a remote host, this needs to be passed in 
+//     with the NetworkServerControl start command
+
+//
+// Permissions for the embedded engine (derby.jar)
+//
+grant codeBase "${derbyTesting.codejar}derby.jar" {
+  permission java.util.PropertyPermission "derby.*", "read";
+  permission java.util.PropertyPermission "derby.storage.jvmInstanceId", 
+      "write"; 
+  // The next two properties are used to determine if the VM is 32 or 64 bit.
+  permission java.util.PropertyPermission "sun.arch.data.model", "read";
+  permission java.util.PropertyPermission "os.arch", "read";
+  permission java.util.PropertyPermission "java.class.path", "read";//sysinfo
+  permission java.util.PropertyPermission "java.runtime.version", "read";//sysinfo
+  permission java.util.PropertyPermission "java.fullversion", "read";//sysinfo
+  
+  // unit tests (e.g. store/T_RecoverFullLog) set this property 
+  // (called from derbyTesting.jar through code in derby.jar)
+  permission java.util.PropertyPermission "derbyTesting.unittest.*", "write";
+
+  permission java.lang.RuntimePermission "createClassLoader";
+
+  // getProtectionDomain is an optional permission needed for printing classpath
+  // information to derby.log
+  permission java.lang.RuntimePermission "getProtectionDomain";
+
+  // permissions so that we can set the context class loader to
+  // null for daemon threads to avoid class loader leak.
+  // DERBY-3745
+  permission java.lang.RuntimePermission "getClassLoader";
+  permission java.lang.RuntimePermission "setContextClassLoader";
+
+  permission java.security.SecurityPermission "getPolicy";
+  
+  permission java.io.FilePermission "${derby.system.home}${/}derby.properties", "read";
+  permission java.io.FilePermission "${derby.system.home}${/}derby.log", "read, write, delete";
+  // [DERBY-2000] The write permission was added to allow creation of the
+  // derby.system.home directory when running tests under a security manager.
+  permission java.io.FilePermission "${derby.system.home}", "read, write";
+  
+  // all databases under derby.system.home 
+  permission java.io.FilePermission "${derby.system.home}${/}-", "read, write, delete";
+
+  // Import/export and other support files from these locations in tests
+  permission java.io.FilePermission "${user.dir}${/}extin${/}-", "read";
+  permission java.io.FilePermission "${user.dir}${/}extinout${/}-", "read,  write, delete";
+  permission java.io.FilePermission "${user.dir}${/}extout${/}-", "read,write";
+  permission java.io.FilePermission "${user.dir}${/}extinout", "read,write";
+
+  // needed to create a temp file in order to open a database in a jar file
+  permission java.io.FilePermission "${java.io.tmpdir}${/}-", "read,write,delete";
+  
+  // These permissions are needed to load the JCE for encryption with Sun and IBM JDK131.
+  // JDK14 has the JCE  preloaded
+  permission java.security.SecurityPermission "insertProvider.SunJCE";
+  permission java.security.SecurityPermission "insertProvider.IBMJCE";
+  
+//
+// Permissions needed for JMX based management and monitoring, which is only
+// available for JVMs supporting "platform management", that is J2SE 5.0 or better.
+//
+// Allows this code to create an MBeanServer:
+//
+  permission javax.management.MBeanServerPermission "createMBeanServer";
+//
+// Allows access to Derby's built-in MBeans, within the domain org.apache.derby.
+// Derby must be allowed to register and unregister these MBeans.
+// To fine tune this permission, see the javadoc of javax.management.MBeanPermission
+// or the JMX Instrumentation and Agent Specification.
+//
+  permission javax.management.MBeanPermission "org.apache.derby.*#[org.apache.derby:*]","registerMBean,unregisterMBean";
+//
+// Trusts Derby code to be a source of MBeans and to register these in the MBean server.
+//
+  permission javax.management.MBeanTrustPermission "register";
+
+  // Gives permission for jmx to be used against Derby but
+  // only if JMX authentication is not being used.
+  // In that case the application would need to create
+  // a whole set of fine-grained permissions to allow specific
+  // users access to MBeans and actions they perform.
+  permission org.apache.derby.security.SystemPermission "jmx", "control";
+  permission org.apache.derby.security.SystemPermission "engine", "monitor";
+  permission org.apache.derby.security.SystemPermission "server", "monitor";  
+ 
+  // These permissions are needed by AssertFailure to dump the thread stack
+  // traces upon failure.
+  permission java.lang.RuntimePermission "getStackTrace";
+  permission java.lang.RuntimePermission "modifyThreadGroup";
+
+  // Needed by FileUtil#limitAccessToOwner
+  permission java.lang.RuntimePermission "accessUserInformation";
+  permission java.lang.RuntimePermission "getFileStoreAttributes";
+
+  // This permission is needed to call the Connection.abort(Executor) method added by JDBC 4.1
+  permission java.sql.SQLPermission "callAbort";
+
+  // This permission is needed to call DriverManager.deregisterDriver()
+  // on Java SE 8 and later.
+  permission java.sql.SQLPermission "deregisterDriver";
+
+  // extra permissions needed for the Lucene plugin
+  permission java.io.FilePermission "${derbyTesting.lucene.core.jar.file}", "read";
+  permission java.util.PropertyPermission "user.dir", "read";
+};
+
+//
+// Permissions for the network server (derbynet.jar)
+//
+grant codeBase "${derbyTesting.codejar}derbynet.jar" {
+  permission java.util.PropertyPermission "java.class.path", "read";//sysinfo
+  permission java.util.PropertyPermission "java.runtime.version", "read";//sysinfo
+  permission java.util.PropertyPermission "java.fullversion", "read";//sysinfo
+  permission java.util.PropertyPermission "derby.__serverStartedFromCmdLine", "write";
+  
+  // accept is needed for the server accepting connections
+  // connect is needed for ping command (which is in the server jar)
+  // listen is needed for the server listening on the network port
+  permission java.net.SocketPermission "127.0.0.1", "accept,connect";
+  permission java.net.SocketPermission "localhost", "accept,connect,listen";
+  permission java.net.SocketPermission "${derbyTesting.clienthost}", "accept,connect";
+  permission java.net.SocketPermission "${derbyTesting.serverhost}", "accept,connect";
+
+  // Need to be able to write to trace file for NetworkServerControlApiTest
+  permission java.io.FilePermission "${user.dir}${/}system${/}trace", "read,write";
+  permission java.io.FilePermission "${user.dir}${/}system${/}trace${/}-", "read,write";
+
+  // Need read/write to trace file for RestrictiveFilePermissionsTest
+  permission java.io.FilePermission "${user.dir}${/}system${/}RFPT_db_tracefiles_restr", "read,write";
+  permission java.io.FilePermission "${user.dir}${/}system${/}RFPT_db_tracefiles_lax", "read,write";
+  permission java.io.FilePermission "${user.dir}${/}system${/}RFPT_db_tracefiles_restr${/}-", "read,write";
+  permission java.io.FilePermission "${user.dir}${/}system${/}RFPT_db_tracefiles_lax${/}-", "read,write";
+
+    // Needed for NetworkServerMBean access (see JMX section above)
+  permission org.apache.derby.security.SystemPermission "server", "control,monitor";
+
+  // For NetworkServerControlApiTest:
+  // Needed by FileUtil#limitAccessToOwner
+  permission java.lang.RuntimePermission "accessUserInformation";
+  permission java.lang.RuntimePermission "getFileStoreAttributes";
+};
+
+//
+// Permissions for the network client (derbyclient.jar)
+//
+grant codeBase "${derbyTesting.clientjar}derbyclient.jar" {
+  permission java.net.SocketPermission "127.0.0.1", "connect,resolve";
+  permission java.net.SocketPermission "localhost", "connect,resolve";
+  permission java.net.SocketPermission "${derbyTesting.serverhost}", "connect,resolve";
+
+  // DERBY-1883: Since some classes that are included in both derby.jar and
+  // derbyclient.jar read properties, derbyclient.jar needs permission to read
+  // derby.* properties to avoid failures when it is listed before derby.jar in
+  // the classpath.
+  permission java.util.PropertyPermission "derby.*", "read";
+
+  // DERBY-2302: derbyclient.jar needs to be able to read the user.dir property in order to
+  // do tracing in that directory. Also, it needs read/write permissions in user.dir in order
+  // to create the trace files in that directory.
+  permission java.util.PropertyPermission "user.dir", "read";
+  permission java.io.FilePermission "${user.dir}${/}-", "read, write"; 
+  
+  // These permissions are needed by AssertFailure to dump the thread stack
+  // traces upon failure.
+  permission java.lang.RuntimePermission "getStackTrace";
+  permission java.lang.RuntimePermission "modifyThreadGroup";
+
+  // This permission is needed to call the Connection.abort(Executor) method added by JDBC 4.1
+  permission java.sql.SQLPermission "callAbort";
+  
+};
+
+//
+// Permissions for the tools (derbytools.jar)
+// Ideally this would be more secure, for now the
+// focus is on getting the engine & network server secure.
+//
+grant codeBase "${derbyTesting.codejar}derbytools.jar" {
+  // Access all properties using System.getProperties -
+  // ij enumerates the properties in order to open connections
+  // for any property set in ij.connection.* and set protocols
+  // for any property in ij.protocol.*
+  permission java.util.PropertyPermission "*", "read, write";
+  
+  // Read all files under ${user.dir}
+  permission java.io.FilePermission "${user.dir}${/}-", "read";
+  
+  // IjTestCases read, write, and delete ij's output in the extinout dir
+  permission java.io.FilePermission "${user.dir}${/}extinout${/}-", "read, write, delete";
+ 
+  // ij needs permission to read the sql files in this jar
+  permission java.io.FilePermission "${derbyTesting.testjarpath}", "read";
+  
+
+};
+
+//
+// Permissions for the tests (derbyTesting.jar)
+// We are liberal here, it's not a goal to make the test harness
+// or tests secure.
+//
+grant codeBase "${derbyTesting.testjar}derbyTesting.jar" {
+  // Access all properties using System.getProperties
+  permission java.util.PropertyPermission "*", "read, write";
+  
+  // Access all files under ${user.dir}to write the test directory structure
+  permission java.io.FilePermission "${user.dir}${/}-", "read,write,delete"; 
+
+  // Tests need to be able to exec a java program. DERBY-6295: Also give them
+  // read permission so that detailed error message is shown.
+  permission java.io.FilePermission "${java.home}${/}-", "execute, read";
+
+  // When running with useprocess=false need to install and uninstall
+  // the security manager and allow setIO to change the system err and out
+  // streams. Currently the nist suite runs with useprocess=false.
+  permission java.lang.RuntimePermission "setSecurityManager";
+  permission java.security.SecurityPermission "getPolicy";
+  permission java.lang.RuntimePermission "setIO";  
+
+  // Needed by ClasspathSetup to change the classloader
+  permission java.lang.RuntimePermission "createClassLoader";
+  permission java.lang.RuntimePermission "setContextClassLoader";
+
+  // These permissions are needed to dump the thread stack
+  // traces upon failure.
+  permission java.lang.RuntimePermission "getStackTrace";
+  permission java.lang.RuntimePermission "modifyThreadGroup";
+  
+  // Allow MBeanTest to register the application management MBean.
+  permission javax.management.MBeanServerPermission "createMBeanServer";
+  permission javax.management.MBeanPermission "org.apache.derby.mbeans.Management#[org.apache.derby:type=Management]","registerMBean,unregisterMBean";
+  permission javax.management.MBeanPermission "org.apache.derby.mbeans.Management#-[-]", "instantiate";
+  permission javax.management.MBeanTrustPermission "register";
+   
+  // And to find and use Derby's MBeans
+  permission javax.management.MBeanPermission "org.apache.derby.mbeans.*#[org.apache.derby:*]", "getAttribute,invoke";
+  permission javax.management.MBeanPermission "org.apache.derby.mbeans.*#-[org.apache.derby:*]", "getMBeanInfo";
+  permission javax.management.MBeanPermission "-#-[-]", "queryNames";
+  permission javax.management.MBeanPermission "org.apache.derby.mbeans.*#-[org.apache.derby:*]", "queryNames";
+  
+  // Test code needs this as well for the platform MBeanServer
+  // tests where the testing code is in the stack frame.
+  permission org.apache.derby.security.SystemPermission "jmx", "control";
+  permission org.apache.derby.security.SystemPermission "engine", "monitor";
+  permission org.apache.derby.security.SystemPermission "server", "control,monitor";
+
+  // useful for debugging
+  //permission java.lang.RuntimePermission "getProtectionDomain";
+
+  // This permission is needed to call the Connection.abort(Executor) method added by JDBC 4.1
+  permission java.sql.SQLPermission "callAbort";
+  
+  // Needed by FileUtil#limitAccessToOwner
+  permission java.lang.RuntimePermission "accessUserInformation";
+  permission java.lang.RuntimePermission "getFileStoreAttributes";
+
+  // Needed by NetworkServerTestSetup when probing ports.
+  permission java.net.SocketPermission "localhost", "listen";
+};
+
+//
+// super-set of the jar permissions for running out of the classes directory
+//
+grant codeBase "${derbyTesting.codeclasses}" {
+  // Access all properties using System.getProperties
+  permission java.util.PropertyPermission "*", "read, write";
+  
+  permission java.util.PropertyPermission "derby.*", "read";
+  permission java.lang.RuntimePermission "createClassLoader";
+
+  // permissions so that we can set the context class loader to
+  // null for daemon threads to avoid class loader leak.
+  // DERBY-3745
+  permission java.lang.RuntimePermission "getClassLoader";
+  permission java.lang.RuntimePermission "setContextClassLoader";
+
+  permission java.security.SecurityPermission "getPolicy";
+   
+  permission java.io.FilePermission "${derby.system.home}${/}derby.properties", "read";
+  permission java.io.FilePermission "${derby.system.home}${/}derby.log", "read, write, delete";
+  permission java.io.FilePermission "${derby.system.home}", "read";
+  permission java.io.FilePermission "${derby.system.home}${/}-", "read, write, delete";
+
+  // combination of client and server side.
+  permission java.net.SocketPermission "127.0.0.1", "accept,connect,resolve";
+  permission java.net.SocketPermission "localhost", "accept,connect,resolve,listen";
+  permission java.net.SocketPermission "${derbyTesting.clienthost}", "accept,connect";
+  permission java.net.SocketPermission "${derbyTesting.serverhost}", "connect,resolve";
+  
+  // Access all files under ${user.dir}to write the test directory structure
+  // Also covers extin, extout and extinout locations
+  permission java.io.FilePermission "${user.dir}${/}-", "read,write,delete"; 
+   
+  // Tests need to be able to exec a java program. DERBY-6295: Also give them
+  // read permission so that detailed error message is shown.
+  permission java.io.FilePermission "${java.home}${/}-", "execute, read";
+ 
+  // These permissions are needed to load the JCE for encryption with Sun and IBM JDK131.
+  // JDK14 has the JCE  preloaded
+  permission java.security.SecurityPermission "insertProvider.SunJCE";
+  permission java.security.SecurityPermission "insertProvider.IBMJCE";
+
+  // When running with useprocess=false need to install and uninstall
+  // the security manager and allow setIO to change the system err and out
+  // streams. Currently the nist suite runs with useprocess=false.
+  permission java.lang.RuntimePermission "setSecurityManager";
+  permission java.lang.RuntimePermission "setIO"; 
+
+  // These permissions are needed by stress.multi to dump the thread stack
+  // traces upon failure.
+  permission java.lang.RuntimePermission "getStackTrace";
+  permission java.lang.RuntimePermission "modifyThreadGroup";
+  
+    // Allow MBeanTest to register the application management MBean.
+  permission javax.management.MBeanServerPermission "createMBeanServer";
+  permission javax.management.MBeanPermission "org.apache.derby.mbeans.Management#[org.apache.derby:type=Management]","registerMBean,unregisterMBean";
+  permission javax.management.MBeanPermission "org.apache.derby.mbeans.Management#-[-]", "instantiate";
+  permission javax.management.MBeanTrustPermission "register";
+  
+  // Allows access to Derby's built-in MBeans, within the domain org.apache.derby.
+  permission javax.management.MBeanPermission "org.apache.derby.*#[org.apache.derby:*]","registerMBean,unregisterMBean";
+  
+   
+  // And to find and use Derby's MBeans
+  permission javax.management.MBeanPermission "org.apache.derby.mbeans.*#[org.apache.derby:*]", "getAttribute,invoke";
+  permission javax.management.MBeanPermission "org.apache.derby.mbeans.*#-[org.apache.derby:*]", "getMBeanInfo";
+  permission javax.management.MBeanPermission "-#-[-]", "queryNames";
+  permission javax.management.MBeanPermission "org.apache.derby.mbeans.*#-[org.apache.derby:*]", "queryNames";
+  
+  // Test code needs this as well for the platform MBeanServer
+  // tests where the testing code is in the stack frame.
+  permission org.apache.derby.security.SystemPermission "jmx", "control";
+  permission org.apache.derby.security.SystemPermission "engine", "monitor";
+  permission org.apache.derby.security.SystemPermission "server", "control,monitor";
+
+  // Needed by FileUtil#limitAccessToOwner
+  permission java.lang.RuntimePermission "accessUserInformation";
+  permission java.lang.RuntimePermission "getFileStoreAttributes";
+
+  // This permission is needed to call DriverManager.deregisterDriver()
+  // on Java SE 8 and later.
+  permission java.sql.SQLPermission "deregisterDriver";
+};
+
+// JUnit jar file tries to read junit.properties in the user's
+// home directory and seems to require permission to read the
+// property user.home as well.
+// junit.swingui.TestRunner writes to .junitsession on exit.
+grant codeBase "${derbyTesting.junit}" {
+    permission java.util.PropertyPermission "user.home", "read";
+    permission java.io.FilePermission "${user.home}${/}junit.properties", "read";
+    permission java.io.FilePermission "${user.home}${/}.junitsession", "write";
+
+    // This permission is needed when running the tests using ant 1.7
+    permission java.io.FilePermission "${user.dir}${/}*", "write";
+};
+
+// Ant's junit runner requires setOut to redirect the System output streams
+// to the forked JVM used when running junit tests inside Ant. Ant requires
+// forking the JVM if you want to run tests in a different directory than the
+// current one.
+grant codeBase "${derbyTesting.antjunit}" {
+    permission java.lang.RuntimePermission "setIO";
+
+    // This permission is needed when running the tests using ant 1.7
+    permission java.io.FilePermission "${user.dir}${/}*", "write";
+};
+
+// functionTests.tests.lang.RoutineSecurityTest requires this grant
+// to check to see if permissions are granted through generated code
+// through this mechanism.
+grant {
+    permission java.util.PropertyPermission "derbyRoutineSecurityTest.yes", "read";
+};
+
+// These permissions are needed when testing code instrumented with EMMA.
+// They will only be used if the emma.active system property property is
+// set, which should be set to "" for the permissions to be correct. Must
+// be granted to all code bases because EMMA doesn't use doPrivileged
+// blocks around the code that needs the permissions.
+grant {
+  permission java.util.PropertyPermission "${emma.active}user.dir", "read";
+  permission java.io.FilePermission "${emma.active}${user.dir}${/}coverage.ec", "read, write";
+  permission java.lang.RuntimePermission "${emma.active}writeFileDescriptor";
+};
+
+// Grant the required permissions for JaCoCo (code coverage tool).
+grant {
+  permission java.io.FilePermission "${jacoco.active}${user.dir}${/}*", "read, write";
+};
+
+// When inserting XML values that use external DTD's, the JAXP parser
+// needs permission to read the DTD files.  We assume that all DTD
+// files will be copied to extin/ by whichever tests need them.  So
+// grant the JAXP parser permissions to read that directory.
+grant codeBase "${derbyTesting.jaxpjar}" {
+  permission java.io.FilePermission "${user.dir}${/}extin${/}-", "read";
+};
+
+// Permissions for package-private tests run from 'classes.pptesting'
+grant codeBase "${derbyTesting.ppcodeclasses}" {
+
+  // Needed for ProtocolTest - allows connection to a server
+  permission java.net.SocketPermission "127.0.0.1", "connect,resolve";
+  permission java.net.SocketPermission "localhost", "connect,resolve";
+  permission java.net.SocketPermission "${derbyTesting.serverhost}", "connect,resolve";
+
+  // Allows reading support files in 'extin'
+  permission java.io.FilePermission "${user.dir}${/}extin${/}-", "read";
+};
+
+// Permissions for the Lucene plugin
+grant codeBase "${derbyTesting.lucene.core}"
+{
+  // permissions for file access, write access only to sandbox:
+  permission java.io.FilePermission "${derby.system.home}${/}dbsqlauth${/}lucene", "read,write,delete";
+  permission java.io.FilePermission "${derby.system.home}${/}dbsqlauth${/}lucene${/}-", "read,write,delete";
+  
+  // Basic permissions needed for Lucene to work:
+  permission java.util.PropertyPermission "user.dir", "read";
+  permission java.util.PropertyPermission "sun.arch.data.model", "read";
+};
+

Propchange: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/luceneSupport.policy
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/junit/SecurityManagerSetup.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/junit/SecurityManagerSetup.java?rev=1580387&r1=1580386&r2=1580387&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/junit/SecurityManagerSetup.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/junit/SecurityManagerSetup.java Sun Mar 23 00:17:56 2014
@@ -354,6 +354,14 @@ public final class SecurityManagerSetup 
         if (antjunit != null)
             classPathSet.setProperty("derbyTesting.antjunit", antjunit.toExternalForm());
 
+        // variables for lucene jar files
+        URL luceneCore = getURL( "org.apache.lucene.store.FSDirectory" );
+        if ( luceneCore != null )
+        {
+            classPathSet.setProperty( "derbyTesting.lucene.core", luceneCore.toExternalForm() );
+            classPathSet.setProperty( "derbyTesting.lucene.core.jar.file", luceneCore.getFile() );
+        }
+
         // Load indirectly, normally no EMMA jars in the classpath.
         // This property is needed to set correct permissions in policy files.
         URL emma = getURL("com.vladium.emma.EMMAException");

Modified: db/derby/code/trunk/tools/ant/properties/extrapath.properties
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/tools/ant/properties/extrapath.properties?rev=1580387&r1=1580386&r2=1580387&view=diff
==============================================================================
--- db/derby/code/trunk/tools/ant/properties/extrapath.properties (original)
+++ db/derby/code/trunk/tools/ant/properties/extrapath.properties Sun Mar 23 00:17:56 2014
@@ -30,8 +30,11 @@ javacc=${javatools.dir}/javacc.jar
 junit=${javatools.dir}/junit.jar
 emma=${javatools.dir}/emma.jar
 emma_ant=${javatools.dir}/emma_ant.jar
+lucene_core=${javatools.dir}/lucene-core-4.5.0.jar
+lucene_a_co=${javatools.dir}/lucene-analyzers-common-4.5.0.jar
+lucene_qp=${javatools.dir}/lucene-queryparser-4.5.0.jar
 
 #
 # Base JavaDoc collection, used for both product and test JavaDocs.
 #
-jars.javadoc=${xmlApis};${osgi};${oro};${servlet24}
+jars.javadoc=${xmlApis};${osgi};${oro};${servlet24}:${lucene_core}:${lucene_a_co}:${lucene_qp}

Modified: db/derby/code/trunk/tools/jar/extraDBMSclasses.properties
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/tools/jar/extraDBMSclasses.properties?rev=1580387&r1=1580386&r2=1580387&view=diff
==============================================================================
--- db/derby/code/trunk/tools/jar/extraDBMSclasses.properties (original)
+++ db/derby/code/trunk/tools/jar/extraDBMSclasses.properties Sun Mar 23 00:17:56 2014
@@ -113,3 +113,4 @@ derby.module.logging.stream=org.apache.d
 # optional tools
 derby.module.opttrace=org.apache.derby.impl.sql.compile.OptimizerTracer
 derby.module.opttraceviewer=org.apache.derby.impl.sql.compile.OptTraceViewer
+derby.module.lucenespt=org.apache.derby.impl.optional.lucene.LuceneSupport

Added: db/derby/code/trunk/tools/java/lucene-analyzers-common-4.5.0.jar
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/tools/java/lucene-analyzers-common-4.5.0.jar?rev=1580387&view=auto
==============================================================================
Binary file - no diff available.

Propchange: db/derby/code/trunk/tools/java/lucene-analyzers-common-4.5.0.jar
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: db/derby/code/trunk/tools/java/lucene-core-4.5.0.jar
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/tools/java/lucene-core-4.5.0.jar?rev=1580387&view=auto
==============================================================================
Binary file - no diff available.

Propchange: db/derby/code/trunk/tools/java/lucene-core-4.5.0.jar
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: db/derby/code/trunk/tools/java/lucene-queryparser-4.5.0.jar
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/tools/java/lucene-queryparser-4.5.0.jar?rev=1580387&view=auto
==============================================================================
Binary file - no diff available.

Propchange: db/derby/code/trunk/tools/java/lucene-queryparser-4.5.0.jar
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream