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 mi...@apache.org on 2006/02/22 00:16:25 UTC

svn commit: r379620 - in /db/derby/code/trunk/java: engine/org/apache/derby/iapi/services/io/ engine/org/apache/derby/iapi/store/access/ engine/org/apache/derby/impl/sql/execute/ engine/org/apache/derby/impl/store/raw/ engine/org/apache/derby/loc/ shar...

Author: mikem
Date: Tue Feb 21 15:16:20 2006
New Revision: 379620

URL: http://svn.apache.org/viewcvs?rev=379620&view=rev
Log:
DERBY-304 submitted on behalf of Suresh Thalamati
Fix :

1) Do not allow backup path to be any derby database directory. A directory is
assumed to be a derby database directory if it has service.properties file in it.

2) copy files needed from the database home into the backup one by one
instead of recursive copy from the top directory.

3) while copying the directories under jar directory, copy each sub directory
separately without copying any subdirectories under them (There should not
be any unless if user has created explicitly or created backup at that location).

4) Log and Seg0 directory are NOT already copied recursively, this was changed as part of
online backup work (DERBY-239). 


Added:
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/BackupPathTests.out
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/BackupPathTests.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/BackupPathTests_app.properties
Modified:
    db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/FileUtil.java
    db/derby/code/trunk/java/engine/org/apache/derby/iapi/store/access/FileResource.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/JarDDL.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/RawStore.java
    db/derby/code/trunk/java/engine/org/apache/derby/loc/messages_en.properties
    db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/SQLState.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/storemore.runall
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/copyfiles.ant

Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/FileUtil.java
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/FileUtil.java?rev=379620&r1=379619&r2=379620&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/FileUtil.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/FileUtil.java Tue Feb 21 15:16:20 2006
@@ -223,14 +223,16 @@
                                          StorageFile from,
                                          File to)
     {
-        return copyDirectory( storageFactory, from, to, null, null);
+        return copyDirectory( storageFactory, from, to, null, null, true);
     }
     
+
     public static boolean copyDirectory( StorageFactory storageFactory,
                                          StorageFile from,
                                          File to,
                                          byte[] buffer,
-                                         String[] filter)
+                                         String[] filter, 
+                                         boolean copySubDirs)
     {
 		if (from == null)
 			return false;
@@ -275,8 +277,18 @@
 
 				if (entry.isDirectory())
 				{
-					if (!copyDirectory( storageFactory, entry, new File(to,fileName), buffer, filter))
-						return false;
+                    if(copySubDirs) {
+                        if (!copyDirectory( storageFactory, entry, 
+                                            new File(to,fileName), buffer, 
+                                            filter, copySubDirs))
+                            return false;
+                    }
+                    else {
+                        // the request is to not copy the directories, continue
+                        // to the next file in the list.
+                        continue nextFile;
+                    }
+
 				}
 				else
 				{

Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/store/access/FileResource.java
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/engine/org/apache/derby/iapi/store/access/FileResource.java?rev=379620&r1=379619&r2=379620&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/store/access/FileResource.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/store/access/FileResource.java Tue Feb 21 15:16:20 2006
@@ -57,7 +57,12 @@
 	useful when processing old transactions in the stage. 
 */
 public interface FileResource {
-	
+
+    /**
+       The name of the jar directory
+    */
+    public static final String JAR_DIRECTORY_NAME = "jar";
+
 	/**
 	  Add a file resource, copying from the input stream.
 	  

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/JarDDL.java
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/JarDDL.java?rev=379620&r1=379619&r2=379620&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/JarDDL.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/JarDDL.java Tue Feb 21 15:16:20 2006
@@ -25,6 +25,7 @@
 import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
 import org.apache.derby.iapi.sql.execute.ConstantAction;
 import org.apache.derby.iapi.sql.execute.ExecutionContext;
+import org.apache.derby.iapi.store.access.FileResource;
 
 public class JarDDL
 {
@@ -111,7 +112,7 @@
 	{
 		StringBuffer sb = new StringBuffer(30);
 
-		sb.append("jar");
+		sb.append(FileResource.JAR_DIRECTORY_NAME);
 		sb.append(separatorChar);
 		sb.append(schemaName);
 		sb.append(separatorChar);

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/RawStore.java
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/RawStore.java?rev=379620&r1=379619&r2=379620&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/RawStore.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/RawStore.java Tue Feb 21 15:16:20 2006
@@ -39,6 +39,7 @@
 import org.apache.derby.iapi.services.property.PersistentSet;
 import org.apache.derby.iapi.store.access.TransactionInfo;
 import org.apache.derby.iapi.store.access.AccessFactoryGlobals;
+import org.apache.derby.iapi.store.access.FileResource;
 import org.apache.derby.iapi.store.raw.ScanHandle;
 import org.apache.derby.iapi.store.raw.RawStoreFactory;
 import org.apache.derby.iapi.store.raw.Transaction;
@@ -98,17 +99,6 @@
 public final class RawStore implements RawStoreFactory, ModuleControl, ModuleSupportable, PrivilegedExceptionAction
 {
 	private static final String BACKUP_HISTORY = "BACKUP.HISTORY";
-    
-    // files that should not be copied into the backup using simple 
-    // directory copy or not needed in the backup at all. 
-	private static final String[] BACKUP_FILTER =
-	{ DataFactory.TEMP_SEGMENT_NAME,    // not required to be in the backup
-      DataFactory.DB_LOCKFILE_NAME,     // not required to be in the backup
-      DataFactory.DB_EX_LOCKFILE_NAME,  // not required to be in the backup
-      LogFactory.LOG_DIRECTORY_NAME,    // written to the backup using log factory
-      "seg0"                            // written to the backup using data factory
-    };
-
 	protected TransactionFactory	xactFactory;
 	protected DataFactory			dataFactory;
 	protected LogFactory			logFactory;
@@ -144,10 +134,13 @@
     private static final int COPY_STORAGE_DIRECTORY_TO_REGULAR_ACTION = 9;
     private byte[] actionBuffer;
     private String[] actionFilter;
+    private boolean actionCopySubDirs;
     private static final int COPY_REGULAR_DIRECTORY_TO_STORAGE_ACTION = 10;
     private static final int COPY_REGULAR_FILE_TO_STORAGE_ACTION = 11;
     private static final int REGULAR_FILE_LIST_DIRECTORY_ACTION = 12;
-    
+    private static final int STORAGE_FILE_LIST_DIRECTORY_ACTION = 13;
+    private static final int COPY_STORAGE_FILE_TO_REGULAR_ACTION = 14;
+
 	public RawStore() {
 	}
 
@@ -579,6 +572,18 @@
                     SQLState.RAWSTORE_CANNOT_BACKUP_TO_NONDIRECTORY,
                     (File) backupDir);
             }
+
+            // check if a user has given the backup as a database directory by
+            // mistake, backup path can not be a derby database directory. 
+            // If a directory contains PersistentService.PROPERTIES_NAME, it 
+            // is assumed as derby database directory because derby databases
+            // always has this file. 
+ 
+            if (privExists(new File(backupDir, PersistentService.PROPERTIES_NAME))) { 
+                throw StandardException.newException(
+                    SQLState.RAWSTORE_CANNOT_BACKUP_INTO_DATABASE_DIRECTORY,
+                    (File) backupDir); 
+            }
 		}
 		
 		boolean error = true;
@@ -638,61 +643,107 @@
 				}
 			}
 
-
-            // copy the files that does not need any special handling and are 
-            // needed to be in the database directory to the backup directory. 
-            // See BACKUP_FILTER for all the files that are not copied 
-            // to the database directory by the call below. After this copy 
-            // information from log(transaction log), seg0(data segment)   has 
-            // to be copied into the backup from the database.
-			
-            if (!privCopyDirectory(dbase, backupcopy, (byte[])null, BACKUP_FILTER))
+            // create the backup database directory
+            if (!privMkdirs(backupcopy))
             {
-                throw StandardException.
-                    newException(SQLState.RAWSTORE_ERROR_COPYING_FILE,
-                                 dbase, backupcopy);
+                throw StandardException.newException(
+                    SQLState.RAWSTORE_CANNOT_CREATE_BACKUP_DIRECTORY,
+                    (File) backupcopy);
             }
 
-			
-			StorageFile logdir = logFactory.getLogDirectory();
+            // if they are any jar file stored in the database, copy them into
+            // the backup. 
+            StorageFile jarDir = 
+                storageFactory.newStorageFile(FileResource.JAR_DIRECTORY_NAME);
+            if (privExists(jarDir)) {
+
+                // find the list of schema directories under the jar dir and
+                // then copy only the plain files under those directories. One could
+                // just use the recursive copy of directory to copy all the files
+                // under the jar dir, but the problem with that is if a user 
+                // gives jar directory as the backup path by mistake, copy will 
+                // fail while copying the backup dir onto itself in recursion
+
+                String [] jarSchemaList = privList(jarDir);
+                File backupJarDir = new File(backupcopy, 
+                                             FileResource.JAR_DIRECTORY_NAME);
+                // Create the backup jar directory
+                if (!privMkdirs(backupJarDir))
+                {
+                    throw StandardException.newException(
+                          SQLState.RAWSTORE_CANNOT_CREATE_BACKUP_DIRECTORY,
+                          (File) backupJarDir);
+                }
 
-			// munge service.properties file if necessary
-			StorageFile defaultLogDir = storageFactory.newStorageFile( LogFactory.LOG_DIRECTORY_NAME);
-			if (!logdir.equals(defaultLogDir))
-			{
-				// Read in property from service.properties file, remove
-				// logDevice from it, then write it out again.
-				try
-				{
-					String name = Monitor.getMonitor().getServiceName(this);
-					PersistentService ps = Monitor.getMonitor().getServiceType(this);
-					String fullName = ps.getCanonicalServiceName(name);
-					Properties prop = ps.getServiceProperties(fullName, (Properties)null);
-
-					prop.remove(Attribute.LOG_DEVICE);
-
-					if (SanityManager.DEBUG)
-						SanityManager.ASSERT(prop.getProperty(Attribute.LOG_DEVICE) == null,
-											 "cannot get rid of logDevice property");
+                for (int i = 0; i < jarSchemaList.length; i++)
+                {
+                    StorageFile jarSchemaDir = 
+                        storageFactory.newStorageFile(jarDir, jarSchemaList[i]);
+                    File backupJarSchemaDir = new File(backupJarDir, jarSchemaList[i]);
+                    if (!privCopyDirectory(jarSchemaDir, backupJarSchemaDir, 
+                                           (byte[])null, null, false)) {
+                        throw StandardException.
+                            newException(SQLState.RAWSTORE_ERROR_COPYING_FILE,
+                                         jarSchemaDir, backupJarSchemaDir);  
+                    }
+                }
+            }
 
-					ps.saveServiceProperties( backupcopy.getCanonicalPath(), prop, true);
 
-					logHistory(historyFile,
-                        MessageService.getTextMessage(
-                            MessageId.STORE_EDITED_SERVICEPROPS));
+            // save service properties into the backup, Read in property 
+            // from service.properties file, remove logDevice from it, 
+            // then write it to the backup.
 
-				}
-				catch(StandardException se)
-				{
-					logHistory(historyFile,
-                        MessageService.getTextMessage(
-                            MessageId.STORE_ERROR_EDIT_SERVICEPROPS)
-                            + se);
+            StorageFile logdir = logFactory.getLogDirectory();
+            
+            try {
+                
+                String name = Monitor.getMonitor().getServiceName(this);
+                PersistentService ps = Monitor.getMonitor().getServiceType(this);
+                String fullName = ps.getCanonicalServiceName(name);
+                Properties prop = ps.getServiceProperties(fullName, (Properties)null);
+                StorageFile defaultLogDir = 
+                    storageFactory.newStorageFile( LogFactory.LOG_DIRECTORY_NAME);
 
-					return; // skip the rest and let finally block clean up
-				}
-			}
+                if (!logdir.equals(defaultLogDir))  
+                {
+                    prop.remove(Attribute.LOG_DEVICE);
+                    if (SanityManager.DEBUG)
+                        SanityManager.ASSERT(prop.getProperty(Attribute.LOG_DEVICE) == null,
+                                             "cannot get rid of logDevice property");
+                    logHistory(historyFile,
+                               MessageService.getTextMessage(
+                               MessageId.STORE_EDITED_SERVICEPROPS));
+                }
+            
+                // save the service properties into the backup.
+                ps.saveServiceProperties( backupcopy.getPath(), prop, false);
+
+            }catch(StandardException se) {
+                logHistory(historyFile,
+                           MessageService.getTextMessage(
+                           MessageId.STORE_ERROR_EDIT_SERVICEPROPS)
+                           + se);
+
+                return; // skip the rest and let finally block clean up
+            }
 
+            // Incase of encrypted database and the key is an external 
+            // encryption key, there is an extra file with name  
+            // Attribute.CRYPTO_EXTERNAL_KEY_VERIFY_FILE , this file should be
+            // copied in to the backup.
+            StorageFile verifyKeyFile = 
+                storageFactory.newStorageFile(
+                                 Attribute.CRYPTO_EXTERNAL_KEY_VERIFY_FILE);
+            if (privExists(verifyKeyFile)) {
+                File backupVerifyKeyFile = 
+                    new File(backupcopy, Attribute.CRYPTO_EXTERNAL_KEY_VERIFY_FILE);
+                if(!privCopyFile(verifyKeyFile, backupVerifyKeyFile))
+                   throw StandardException.
+                       newException(SQLState.RAWSTORE_ERROR_COPYING_FILE,
+                                    verifyKeyFile, backupVerifyKeyFile);  
+            }
+                
 			File logBackup = new File(backupcopy, LogFactory.LOG_DIRECTORY_NAME);
 
 			// this is wierd, delete it
@@ -1124,7 +1175,8 @@
 
 	protected boolean privCopyDirectory(StorageFile from, File to)
 	{
-		return privCopyDirectory(from, to, (byte[])null, (String[])null);
+		return privCopyDirectory(from, to, (byte[])null, 
+                                 (String[])null, true);
 	}
 
 	protected boolean privCopyDirectory(File from, StorageFile to)
@@ -1297,13 +1349,18 @@
         }
     }
 
-    private synchronized boolean privCopyDirectory( StorageFile from, File to, byte[] buffer, String[] filter)
+    private synchronized boolean privCopyDirectory(StorageFile from, 
+                                                   File to, 
+                                                   byte[] buffer, 
+                                                   String[] filter,
+                                                   boolean copySubdirs)
     {
         actionCode = COPY_STORAGE_DIRECTORY_TO_REGULAR_ACTION;
         actionStorageFile = from;
         actionRegularFile = to;
         actionBuffer = buffer;
         actionFilter = filter;
+        actionCopySubDirs = copySubdirs;
 
         try
         {
@@ -1364,6 +1421,26 @@
         }
     }
 
+    private synchronized boolean privCopyFile( StorageFile from, File to)
+    {
+        actionCode = COPY_STORAGE_FILE_TO_REGULAR_ACTION;
+        actionStorageFile = from;
+        actionRegularFile = to;
+
+        try
+        {
+            Object ret = AccessController.doPrivileged( this);
+            return ((Boolean) ret).booleanValue();
+        }
+        catch( PrivilegedActionException pae) { return false;} // does not throw an exception
+        finally
+        {
+            actionStorageFile = null;
+            actionRegularFile = null;
+        }
+    }
+
+
     private synchronized String[] privList(final File file)
     {
         actionCode = REGULAR_FILE_LIST_DIRECTORY_ACTION;
@@ -1380,6 +1457,23 @@
         }
     }
 
+    private synchronized String[] privList(final StorageFile file)
+    {
+        actionCode = STORAGE_FILE_LIST_DIRECTORY_ACTION;
+        actionStorageFile = file;
+
+        try
+        {
+            return (String[]) AccessController.doPrivileged( this);
+        }
+        catch( PrivilegedActionException pae) { return null;} // does not throw an exception
+        finally
+        {
+            actionStorageFile = null;
+        }
+    }
+    
+
     // PrivilegedExceptionAction method
     public final Object run() throws IOException
     {
@@ -1420,7 +1514,8 @@
                                                                   actionStorageFile,
                                                                   actionRegularFile,
                                                                   actionBuffer,
-                                                                  actionFilter));
+                                                                  actionFilter,
+                                                                  actionCopySubDirs));
 
         case COPY_REGULAR_DIRECTORY_TO_STORAGE_ACTION:
             // SECURITY PERMISSION - MP1, OP4
@@ -1439,6 +1534,19 @@
         case REGULAR_FILE_LIST_DIRECTORY_ACTION:
             // SECURITY PERMISSION - MP1
             return (String[])(actionRegularFile.list());
+
+        case STORAGE_FILE_LIST_DIRECTORY_ACTION:
+            // SECURITY PERMISSION - MP1
+            return (String[])(actionStorageFile.list());
+
+        case COPY_STORAGE_FILE_TO_REGULAR_ACTION:
+            // SECURITY PERMISSION - MP1, OP4
+            return ReuseFactory.getBoolean(FileUtil.copyFile(
+                                           (WritableStorageFactory) storageFactory,
+                                           actionStorageFile,
+                                           actionRegularFile));
+
+
         }
         return null;
     } // end of run

Modified: db/derby/code/trunk/java/engine/org/apache/derby/loc/messages_en.properties
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/engine/org/apache/derby/loc/messages_en.properties?rev=379620&r1=379619&r2=379620&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/loc/messages_en.properties (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/loc/messages_en.properties Tue Feb 21 15:16:20 2006
@@ -190,6 +190,7 @@
 XSRS9.S=Record {0} no longer exists
 XSRSA.S=Cannot backup the database when unlogged operations are uncommitted. Please commit the transactions with backup blocking operations. 
 XSRSB.S=Backup cannot be performed in a transaction with uncommitted unlogged operations.
+XSRSC.S=Cannot backup the database to {0}, it is a database directory.
 
 # java/com/ibm/db2j/impl/Database/Storage/RawStore/Log/Generic
 # statement errors.

Modified: db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/SQLState.java
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/SQLState.java?rev=379620&r1=379619&r2=379620&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 Tue Feb 21 15:16:20 2006
@@ -358,7 +358,7 @@
     String RAWSTORE_RECORD_VANISHED                             = "XSRS9.S";
     String BACKUP_BLOCKING_OPERATIONS_IN_PROGRESS               = "XSRSA.S";
     String BACKUP_OPERATIONS_NOT_ALLOWED                        = "XSRSB.S";
-    
+    String RAWSTORE_CANNOT_BACKUP_INTO_DATABASE_DIRECTORY       = "XSRSC.S";
 
 	/*
 	** RawStore - Log.Generic statement exceptions

Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/BackupPathTests.out
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/BackupPathTests.out?rev=379620&view=auto
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/BackupPathTests.out (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/BackupPathTests.out Tue Feb 21 15:16:20 2006
@@ -0,0 +1,11 @@
+Begin Backup Path Tests
+case1 : try Backup with backup path as database dir
+Backup in to a database dir failed
+End test case1
+case2 : Backup with backup path as database jar dir
+End test case 2
+case 3: Backup again into the same db jar dir location
+End test case 3
+case 4: Backup using an absolute path
+End test case 4
+End Backup Path Tests

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/storemore.runall
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/storemore.runall?rev=379620&r1=379619&r2=379620&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/storemore.runall (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/storemore.runall Tue Feb 21 15:16:20 2006
@@ -33,3 +33,4 @@
 store/onlineBackupTest2.sql
 store/OnlineBackupTest3.java
 store/onlineBackupTest4.sql
+store/BackupPathTests.java

Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/BackupPathTests.java
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/BackupPathTests.java?rev=379620&view=auto
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/BackupPathTests.java (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/BackupPathTests.java Tue Feb 21 15:16:20 2006
@@ -0,0 +1,128 @@
+/*
+
+   Derby - Class org.apache.derbyTesting.functionTests.store.BackupPathTests
+
+   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.tests.store;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.CallableStatement;
+import java.io.File;
+import org.apache.derby.tools.ij;
+
+/*
+ * This class tests online backup with various types of paths.
+ * 1 ) backup path is same as a database directory. This should fail backup
+ *     can not be made onto a database directory. (DERBY-304 bug).
+ * 2 ) backup path is a sub directory in the database. 
+ * 3 ) Redo backup with same path as in second case.
+ * 4 ) backup path is absolute path.
+
+ * If the path refers to some sub directory inside a database, backup 
+ * will succeed because there is no easy way to catch this weird case,
+ * especially if the backup path refers to another database directory.  
+ *
+ *
+ * @author <a href="mailto:suresh.thalamati@gmail.com">Suresh Thalamati</a>
+ * @version 1.0
+ */
+
+public class BackupPathTests
+{
+    
+    public static void main(String[] argv) throws Throwable 
+    {
+        try {
+
+            ij.getPropertyArg(argv); 
+            Connection conn = ij.startJBMS();
+            conn.setAutoCommit(true);
+            
+            Statement stmt = conn.createStatement();
+            //install a jar, so that there is a jar directory under the db.
+            stmt.execute(
+                     "call sqlj.install_jar(" + 
+                     "'extin/brtestjar.jar', 'math_routines', 0)");
+
+            stmt.close();
+
+            logMsg("Begin Backup Path Tests");
+            String derbyHome = System.getProperty("derby.system.home");
+            String dbHome = derbyHome + File.separator + "wombat" ; 
+
+            logMsg("case1 : try Backup with backup path as database dir");
+            try {
+                performBackup(conn, dbHome);
+            } catch(SQLException sqle) {
+                // expected to fail with following error code. 
+                if (sqle.getSQLState() != null && 
+                    sqle.getSQLState().equals("XSRSC")) {
+                    logMsg("Backup in to a database dir failed");
+                } else {
+                    throw sqle;
+                }
+            }
+            
+            logMsg("End test case1");
+            logMsg("case2 : Backup with backup path as database jar dir");
+            String jarDir = dbHome + File.separator + "jar";
+            performBackup(conn, jarDir);
+            logMsg("End test case 2");
+
+            logMsg("case 3: Backup again into the same db jar dir location");
+            performBackup(conn, jarDir);
+            logMsg("End test case 3");
+
+            logMsg("case 4: Backup using an absolute path");
+            String absBackupPath = 
+                new File("extinout/backupPathTests").getAbsolutePath();
+            performBackup(conn, absBackupPath); 
+            logMsg("End test case 4");
+            conn.close();
+            logMsg("End Backup Path Tests");
+
+        } catch (SQLException sqle) {
+            org.apache.derby.tools.JDBCDisplayUtil.ShowSQLException(System.out, 
+                                                                    sqle);
+            sqle.printStackTrace(System.out);
+        }
+    }
+
+
+    private static void performBackup(Connection conn, 
+                                      String backupPath) 
+        throws SQLException
+    {
+        CallableStatement backupStmt = 	
+            conn.prepareCall("CALL SYSCS_UTIL.SYSCS_BACKUP_DATABASE(?)");
+        backupStmt.setString(1, backupPath);
+        backupStmt.execute();
+        backupStmt.close();
+    }
+
+    
+    /**
+     * Write message to the standard output.
+     */
+    private static void logMsg(String   str)	{
+        System.out.println(str);
+    }
+
+}

Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/BackupPathTests_app.properties
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/BackupPathTests_app.properties?rev=379620&view=auto
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/BackupPathTests_app.properties (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/BackupPathTests_app.properties Tue Feb 21 15:16:20 2006
@@ -0,0 +1,22 @@
+#
+# *** DO NOT PUT PROPERTIES FOR THE DERBY SYSTEM IN THIS FILE.  THEY BELONG
+# *** IN the _derby.properties file.
+#
+# It will get handed to the test on the command line in a -p <filename>
+# argument.
+#
+# This causes ij (or the GUI on ij) to load the driver and make an
+# initial connection to the database.
+#
+#
+
+ij.database=wombat
+usedefaults=true
+useextdirs=true
+supportfiles=tests/store/brtestjar.jar
+
+#Exclude for J2ME/Foundation - test uses procedure with server-side JDBC
+runwithfoundation=false
+
+#exclude with SecurityManager DERBY-709
+noSecurityManager=true

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/copyfiles.ant
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/copyfiles.ant?rev=379620&r1=379619&r2=379620&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/copyfiles.ant (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/copyfiles.ant Tue Feb 21 15:16:20 2006
@@ -150,3 +150,4 @@
 obtest_customer.jar
 onlineBackupTest4.sql
 onlineBackupTest4_app.properties
+BackupPathTests_app.properties