Adding JMCR-Stable version
[Benchmarks_CSolver.git] / JMCR-Stable / real-world application / derby-10.3.2.1 / java / engine / org / apache / derby / impl / store / raw / RawStore.java
diff --git a/JMCR-Stable/real-world application/derby-10.3.2.1/java/engine/org/apache/derby/impl/store/raw/RawStore.java b/JMCR-Stable/real-world application/derby-10.3.2.1/java/engine/org/apache/derby/impl/store/raw/RawStore.java
new file mode 100644 (file)
index 0000000..c496ec0
--- /dev/null
@@ -0,0 +1,2563 @@
+/*\r
+\r
+   Derby - Class org.apache.derby.impl.store.raw.RawStore\r
+\r
+   Licensed to the Apache Software Foundation (ASF) under one or more\r
+   contributor license agreements.  See the NOTICE file distributed with\r
+   this work for additional information regarding copyright ownership.\r
+   The ASF licenses this file to you under the Apache License, Version 2.0\r
+   (the "License"); you may not use this file except in compliance with\r
+   the License.  You may obtain a copy of the License at\r
+\r
+      http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+   Unless required by applicable law or agreed to in writing, software\r
+   distributed under the License is distributed on an "AS IS" BASIS,\r
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+   See the License for the specific language governing permissions and\r
+   limitations under the License.\r
+\r
+ */\r
+\r
+package org.apache.derby.impl.store.raw;\r
+\r
+import org.apache.derby.iapi.services.daemon.DaemonFactory;\r
+import org.apache.derby.iapi.services.daemon.DaemonService;\r
+import org.apache.derby.iapi.services.context.ContextManager;\r
+import org.apache.derby.iapi.services.context.ContextService;\r
+import org.apache.derby.iapi.services.crypto.CipherFactoryBuilder;\r
+import org.apache.derby.iapi.services.crypto.CipherFactory;\r
+import org.apache.derby.iapi.services.crypto.CipherProvider;\r
+import org.apache.derby.iapi.services.locks.CompatibilitySpace;\r
+import org.apache.derby.iapi.services.locks.LockFactory;\r
+import org.apache.derby.iapi.services.monitor.Monitor;\r
+import org.apache.derby.iapi.services.monitor.ModuleControl;\r
+import org.apache.derby.iapi.services.monitor.ModuleSupportable;\r
+import org.apache.derby.iapi.services.monitor.PersistentService;\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+\r
+import org.apache.derby.iapi.error.StandardException;\r
+import org.apache.derby.iapi.services.i18n.MessageService;\r
+\r
+import org.apache.derby.iapi.services.property.PersistentSet;\r
+import org.apache.derby.iapi.store.access.TransactionInfo;\r
+import org.apache.derby.iapi.store.access.AccessFactoryGlobals;\r
+import org.apache.derby.iapi.store.access.FileResource;\r
+import org.apache.derby.iapi.store.raw.ScanHandle;\r
+import org.apache.derby.iapi.store.raw.RawStoreFactory;\r
+import org.apache.derby.iapi.store.raw.Transaction;\r
+import org.apache.derby.iapi.store.raw.xact.RawTransaction;\r
+import org.apache.derby.iapi.store.raw.xact.TransactionFactory;\r
+import org.apache.derby.iapi.store.raw.data.DataFactory;\r
+import org.apache.derby.iapi.store.raw.log.LogFactory;\r
+import org.apache.derby.iapi.store.raw.log.LogInstant;\r
+import org.apache.derby.impl.services.monitor.UpdateServiceProperties;\r
+\r
+import org.apache.derby.io.StorageFactory;\r
+import org.apache.derby.io.WritableStorageFactory;\r
+import org.apache.derby.io.StorageFile;\r
+import org.apache.derby.iapi.store.access.DatabaseInstant;\r
+import org.apache.derby.catalog.UUID;\r
+import org.apache.derby.iapi.services.property.PropertyUtil;\r
+import org.apache.derby.iapi.services.io.FileUtil;\r
+import org.apache.derby.iapi.util.ReuseFactory;\r
+import org.apache.derby.iapi.util.StringUtil;\r
+import org.apache.derby.iapi.reference.Attribute;\r
+import org.apache.derby.iapi.reference.SQLState;\r
+import org.apache.derby.iapi.reference.MessageId;\r
+import org.apache.derby.iapi.reference.Property;\r
+\r
+import java.security.AccessController;\r
+import java.security.PrivilegedActionException;\r
+import java.security.PrivilegedExceptionAction;\r
+import java.security.SecureRandom;\r
+\r
+import java.util.Date;\r
+import java.util.Properties;\r
+import java.io.Serializable;\r
+import java.io.File;\r
+import java.io.FileOutputStream;\r
+import java.io.FileInputStream;\r
+import java.io.IOException;\r
+import java.io.FileNotFoundException;\r
+import java.io.OutputStreamWriter;\r
+\r
+import java.net.MalformedURLException;\r
+import java.net.URL;\r
+\r
+import java.security.PrivilegedExceptionAction;\r
+import java.lang.SecurityException;\r
+\r
+\r
+/**\r
+       A Raw store that implements the RawStoreFactory module by delegating all the\r
+       work to the lower modules TransactionFactory, LogFactory and DataFactory.\r
+       <PRE>\r
+       String TransactionFactoryId=<moduleIdentifier>\r
+       </PRE>\r
+       \r
+       <P>\r
+       Class is final as it has methods with privilege blocks\r
+       and implements PrivilegedExceptionAction.\r
+*/\r
+\r
+public final class RawStore implements RawStoreFactory, ModuleControl, ModuleSupportable, PrivilegedExceptionAction\r
+{\r
+       private static final String BACKUP_HISTORY = "BACKUP.HISTORY";\r
+       protected TransactionFactory    xactFactory;\r
+       protected DataFactory                   dataFactory;\r
+       protected LogFactory                    logFactory;\r
+    private StorageFactory storageFactory;\r
+\r
+       private SecureRandom random;\r
+       private boolean databaseEncrypted;\r
+    private boolean encryptDatabase;\r
+       private CipherProvider encryptionEngine;\r
+       private CipherProvider decryptionEngine;\r
+    private CipherProvider newEncryptionEngine;\r
+       private CipherProvider newDecryptionEngine;\r
+       private CipherFactory  currentCipherFactory;\r
+    private CipherFactory newCipherFactory = null;\r
+       private int counter_encrypt;\r
+       private int counter_decrypt;\r
+       private int encryptionBlockSize = RawStoreFactory.DEFAULT_ENCRYPTION_BLOCKSIZE;\r
+\r
+       String dataDirectory;                                   // where files are stored       \r
+\r
+       // this daemon takes care of all daemon work for this raw store\r
+       protected DaemonService                 rawStoreDaemon;\r
+\r
+    private int actionCode;\r
+    private static final int FILE_WRITER_ACTION = 1;\r
+    private StorageFile actionStorageFile;\r
+    private StorageFile actionToStorageFile;\r
+    private boolean actionAppend;\r
+    private static final int REGULAR_FILE_EXISTS_ACTION = 2;\r
+    private File actionRegularFile;\r
+    private static final int STORAGE_FILE_EXISTS_ACTION = 3;\r
+    private static final int REGULAR_FILE_DELETE_ACTION = 4;\r
+    private static final int REGULAR_FILE_MKDIRS_ACTION = 5;\r
+    private static final int REGULAR_FILE_IS_DIRECTORY_ACTION = 6;\r
+    private static final int REGULAR_FILE_REMOVE_DIRECTORY_ACTION = 7;\r
+    private static final int REGULAR_FILE_RENAME_TO_ACTION = 8;\r
+    private File actionRegularFile2;\r
+    private static final int COPY_STORAGE_DIRECTORY_TO_REGULAR_ACTION = 9;\r
+    private byte[] actionBuffer;\r
+    private String[] actionFilter;\r
+    private boolean actionCopySubDirs;\r
+    private static final int COPY_REGULAR_DIRECTORY_TO_STORAGE_ACTION = 10;\r
+    private static final int COPY_REGULAR_FILE_TO_STORAGE_ACTION = 11;\r
+    private static final int REGULAR_FILE_LIST_DIRECTORY_ACTION = 12;\r
+    private static final int STORAGE_FILE_LIST_DIRECTORY_ACTION = 13;\r
+    private static final int COPY_STORAGE_FILE_TO_REGULAR_ACTION = 14;\r
+    private static final int REGULAR_FILE_GET_CANONICALPATH_ACTION = 15;\r
+    private static final int STORAGE_FILE_GET_CANONICALPATH_ACTION = 16;\r
+    private static final int COPY_STORAGE_FILE_TO_STORAGE_ACTION = 17;\r
+    private static final int STORAGE_FILE_DELETE_ACTION = 18;\r
+\r
+       public RawStore() {\r
+       }\r
+\r
+       /*\r
+       ** Methods of ModuleControl\r
+       */\r
+\r
+       /**\r
+         We use this RawStore for all databases.\r
+         */\r
+       public boolean canSupport(Properties startParams) {\r
+               return true;\r
+       }\r
+\r
+       public void     boot(boolean create, Properties properties)\r
+               throws StandardException\r
+       {\r
+               dataDirectory = properties.getProperty(PersistentService.ROOT);\r
+               DaemonFactory daemonFactory =\r
+                       (DaemonFactory)Monitor.startSystemModule(org.apache.derby.iapi.reference.Module.DaemonFactory);\r
+               //Commented by Jeff Huang\r
+               //rawStoreDaemon = daemonFactory.createNewDaemon("rawStoreDaemon");\r
+               xactFactory = (TransactionFactory)\r
+                                       Monitor.bootServiceModule(\r
+                                               create, this, getTransactionFactoryModule(), properties);\r
+\r
+               dataFactory = (DataFactory)\r
+                                       Monitor.bootServiceModule(\r
+                                         create, this, getDataFactoryModule(), properties);\r
+               storageFactory = dataFactory.getStorageFactory();\r
+\r
+        String restoreFromBackup = null;\r
+\r
+               if (properties != null)\r
+               {\r
+            // check if this is a restore from a backup copy. \r
+            restoreFromBackup = properties.getProperty(Attribute.CREATE_FROM);\r
+            if(restoreFromBackup == null)\r
+                restoreFromBackup = properties.getProperty(Attribute.RESTORE_FROM);\r
+            if(restoreFromBackup == null)\r
+                restoreFromBackup =\r
+                    properties.getProperty(Attribute.ROLL_FORWARD_RECOVERY_FROM);\r
+\r
+        }\r
+\r
+        // setup database encryption engines.\r
+        if (create) \r
+            setupEncryptionEngines(create, properties);\r
+\r
+\r
+               // let everyone knows who their rawStoreFactory is and they can use it\r
+               // to get to other modules\r
+               // pass in create and properties to dataFactory so it can boot the log\r
+               // factory\r
+\r
+               dataFactory.setRawStoreFactory(this, create, properties);\r
+               xactFactory.setRawStoreFactory(this);\r
+\r
+        if( properties instanceof UpdateServiceProperties)\r
+        {\r
+            if( storageFactory instanceof WritableStorageFactory)\r
+                ((UpdateServiceProperties)properties).setStorageFactory( (WritableStorageFactory) storageFactory);\r
+        }\r
+        \r
+               // log factory is booted by the data factory\r
+               logFactory =(LogFactory) Monitor.findServiceModule(this, getLogFactoryModule());\r
+\r
+               // if this is a restore from backup, restore the jar files.\r
+               if(restoreFromBackup !=null)\r
+               {\r
+                       restoreRemainingFromBackup(restoreFromBackup);\r
+               }\r
+\r
+               // If the log is at another location, make sure  service.properties\r
+               // file has it.\r
+               String logDevice = properties.getProperty(Attribute.LOG_DEVICE);\r
+               if (logDevice !=null)\r
+               {\r
+            if (!isReadOnly() // We do not care about log location if read only\r
+                && (create \r
+                    || !logDevice.equals(logFactory.getCanonicalLogPath()) \r
+                    || restoreFromBackup!=null))\r
+                       {\r
+                               // get the real location from the log factory\r
+                               properties.put(Attribute.LOG_DEVICE, logFactory.getCanonicalLogPath());\r
+                               //make the log device param stored in backup is same as current log device.\r
+                               properties.put(Property.LOG_DEVICE_AT_BACKUP, logFactory.getCanonicalLogPath());\r
+                       }\r
+       \r
+               }else{\r
+                       //when we restore from a backup logDevice param does not exists \r
+                       //in service.properties to support restore using OS commands to work. \r
+                       //Instead of logDevice, we user logDeviceWhenBackedUp parameter to\r
+                       //identify the log location while restoring createFrom/restoreFrom/rollForwardRecoveryFrom\r
+                       //attribute , following make sures the logDevice parameter gets \r
+                       //into service.propertues in such cases.\r
+                       if(restoreFromBackup!=null && logFactory.getCanonicalLogPath()!=null)\r
+                       {\r
+                               //logdevice might have got changed because of backup restore. \r
+                               properties.put(Attribute.LOG_DEVICE,  logFactory.getCanonicalLogPath());\r
+                       }\r
+                       else{\r
+                               //might have been OS copy restore. We default log to db home\r
+                               properties.remove(Property.LOG_DEVICE_AT_BACKUP);\r
+                       }\r
+               }\r
+\r
+               \r
+               // save the service properties to a file if we are doing a \r
+               // restore from. This marks the end of restore from backup.\r
+               if (restoreFromBackup !=null)\r
+               {\r
+                       ((UpdateServiceProperties)properties).saveServiceProperties();\r
+               }\r
+\r
+\r
+               /**\r
+                * Note: service.properties file acts as flags to indicate\r
+                * that the copy from backup is successful.\r
+                * If we reached so far while restoring from backup means\r
+                * we copied all the necessary data from backup. Only thing\r
+                * that remains is roll forwarding the logs. Incase if we crash at this\r
+                * point and user re boots the datbase again without any restore flags\r
+                * it shoud boot without any problem.\r
+                **/\r
+\r
+\r
+        // setup database encryption engine\r
+        if (!create) \r
+        {\r
+            // check if the engine crashed while re-encrypting an \r
+            // encrypted database or while encryption and \r
+            // existing database.\r
+            if(properties.getProperty(\r
+                              RawStoreFactory.DB_ENCRYPTION_STATUS) !=null) \r
+            {   \r
+                handleIncompleteDatabaseEncryption(properties);\r
+            }\r
+\r
+            setupEncryptionEngines(create, properties);\r
+        }\r
+\r
+        if (databaseEncrypted) {\r
+            // let log factory know if the database is encrypted . \r
+            logFactory.setDatabaseEncrypted(false);\r
+            // let data factory know if the database is encrypted. \r
+            dataFactory.setDatabaseEncrypted();\r
+        }\r
+\r
+               // no need to tell log factory which raw store factory it belongs to\r
+               // since this is passed into the log factory for recovery\r
+               // after the factories are loaded, recover the database\r
+               logFactory.recover(this, dataFactory, xactFactory);\r
+\r
+        // if user requested to encrpty an unecrypted database or encrypt with\r
+        // new alogorithm then do that now.  \r
+        if (encryptDatabase) {\r
+            configureDatabaseForEncryption(properties, \r
+                                           newCipherFactory);\r
+        }\r
+       }\r
+\r
+       public void     stop() {\r
+\r
+               if (SanityManager.DEBUG)\r
+               {\r
+                       if (databaseEncrypted)\r
+                               SanityManager.DEBUG_PRINT("encryption statistics",\r
+                                               "Encryption called " + counter_encrypt + " times, " +\r
+                                               "decryption called " + counter_decrypt + " times");\r
+               }\r
+\r
+               if (rawStoreDaemon != null)\r
+                       rawStoreDaemon.stop();\r
+\r
+               if (logFactory == null)\r
+                       return;\r
+\r
+               try {\r
+\r
+                       if (logFactory.checkpoint(this, dataFactory, xactFactory, false))\r
+                       {\r
+                               if (dataFactory != null)\r
+                                       dataFactory.removeStubsOK();\r
+                       }\r
+\r
+               } catch (StandardException se) {\r
+                       // checkpoint failed, stop all factory from shutting down normally\r
+                       markCorrupt(se);\r
+               }\r
+       }\r
+\r
+       /*\r
+       ** Methods of RawStoreFactory\r
+       */\r
+\r
+       /**\r
+               Is the store read-only.\r
+               @see RawStoreFactory#isReadOnly\r
+       */\r
+       public boolean isReadOnly() {\r
+               return dataFactory.isReadOnly();\r
+       }\r
+\r
+       public LockFactory getLockFactory() {\r
+               return xactFactory.getLockFactory();\r
+       }\r
+\r
+    \r
+    /**\r
+               Get the Transaction Factory to use with this store.\r
+       */\r
+       public TransactionFactory getXactFactory() {\r
+        return xactFactory;  \r
+    }\r
+\r
+       /*\r
+        * Return the module providing XAresource interface to the transaction\r
+     * table.\r
+     *\r
+        * @exception StandardException Standard Derby exception policy.\r
+        */\r
+       public /* XAResourceManager */ Object getXAResourceManager()\r
+        throws StandardException\r
+    {\r
+        return(xactFactory.getXAResourceManager());\r
+    }\r
+\r
+\r
+       public Transaction startGlobalTransaction(\r
+    ContextManager  contextMgr,\r
+    int             format_id,\r
+    byte[]          global_id,\r
+    byte[]          branch_id)\r
+        throws StandardException\r
+    {\r
+               return xactFactory.startGlobalTransaction(\r
+                    this, contextMgr, format_id, global_id, branch_id);\r
+       }\r
+\r
+       public Transaction startTransaction(ContextManager contextMgr, String transName)\r
+        throws StandardException\r
+    {\r
+               return xactFactory.startTransaction(this, contextMgr, transName);\r
+       }\r
+\r
+       public Transaction startNestedReadOnlyUserTransaction(\r
+    CompatibilitySpace compatibilitySpace,\r
+    ContextManager  contextMgr,\r
+    String          transName)\r
+        throws StandardException\r
+    {\r
+               return(\r
+            xactFactory.startNestedReadOnlyUserTransaction(\r
+                this, compatibilitySpace, contextMgr, transName));\r
+       }\r
+\r
+       public Transaction startNestedUpdateUserTransaction(\r
+    ContextManager  contextMgr,\r
+    String          transName)\r
+        throws StandardException\r
+    {\r
+               return(\r
+            xactFactory.startNestedUpdateUserTransaction(\r
+                this, contextMgr, transName));\r
+       }\r
+\r
+       public Transaction findUserTransaction(\r
+        ContextManager contextMgr,\r
+        String transName)\r
+                throws StandardException\r
+       {\r
+               return xactFactory.findUserTransaction(this, contextMgr, transName);\r
+       }\r
+\r
+\r
+       public Transaction startInternalTransaction(ContextManager contextMgr) throws StandardException {\r
+\r
+               return xactFactory.startInternalTransaction(this, contextMgr);\r
+       }\r
+\r
+       public void checkpoint() throws StandardException\r
+       {\r
+               logFactory.checkpoint(this, dataFactory, xactFactory, false);\r
+       }\r
+\r
+       public void freeze() throws StandardException\r
+       {\r
+               logFactory.checkpoint(this, dataFactory, xactFactory, true);\r
+               dataFactory.freezePersistentStore();\r
+               logFactory.freezePersistentStore();\r
+       }\r
+\r
+       public void unfreeze() throws StandardException\r
+       {\r
+               logFactory.unfreezePersistentStore();\r
+               dataFactory.unfreezePersistentStore();\r
+       }\r
+\r
+    /**\r
+     * Backup the database to a backup directory.\r
+     *\r
+     * @param backupDir the name of the directory where the backup should be\r
+     *                  stored. This directory will be created if it \r
+     *                  does not exist.\r
+     * @param wait if <tt>true</tt>, waits for  all the backup blocking \r
+     *             operations in progress to finish.\r
+     * @exception StandardException thrown on error\r
+     */\r
+    public void backup(String backupDir, boolean wait) \r
+        throws StandardException \r
+    {\r
+               if (backupDir == null || backupDir.equals(""))\r
+        {\r
+                       throw StandardException.newException(\r
+                SQLState.RAWSTORE_CANNOT_CREATE_BACKUP_DIRECTORY, (File)null);\r
+        }\r
+\r
+               // in case this is an URL form\r
+               String backupDirURL = null;\r
+               try {\r
+                       URL url = new URL(backupDir);\r
+                       backupDirURL = url.getFile();\r
+               } catch (MalformedURLException ex) {}\r
+\r
+               if (backupDirURL != null)\r
+                       backupDir = backupDirURL;\r
+\r
+\r
+               // find the user transaction, it is necessary for online backup \r
+               // to open the container through page cache\r
+               RawTransaction t = \r
+            xactFactory.findUserTransaction(this,\r
+                ContextService.getFactory().getCurrentContextManager(), \r
+                AccessFactoryGlobals.USER_TRANS_NAME);\r
+\r
+               try {\r
+\r
+            // check if  any backup blocking operations are in progress\r
+            // in the same transaction backup is being executed? Backup is \r
+            // not allowed if the transaction has uncommitted\r
+            // unlogged operations that are blocking the backup.\r
+            \r
+            if (t.isBlockingBackup())\r
+            {\r
+                throw StandardException.newException(\r
+                      SQLState.BACKUP_OPERATIONS_NOT_ALLOWED);  \r
+            }\r
+\r
+\r
+            // check if any backup blocking operations are in progress\r
+            // and stop new ones from starting until the backup is completed.\r
+            if (!xactFactory.blockBackupBlockingOperations(wait))\r
+            {\r
+                throw StandardException.newException(\r
+                      SQLState.BACKUP_BLOCKING_OPERATIONS_IN_PROGRESS);  \r
+            }\r
+\r
+            // perform backup\r
+            backup(t, new File(backupDir));\r
+        }finally {\r
+            // let the xactfatory know that backup is done, so that\r
+            // it can allow backup blocking operations. \r
+            xactFactory.unblockBackupBlockingOperations();\r
+        }\r
+       }\r
+\r
+\r
+       /*\r
+        * Backup the database.\r
+        * Online backup copies all the database files (log, seg0  ...Etc) to the\r
+        * specified backup location without blocking any user operation for the \r
+        * duration of the backup. Stable copy is made of each page using \r
+     * page level latches and in some cases with the help of monitors.  \r
+     * Transaction log is also backed up, this is used to bring the database to \r
+     * the consistent state on restore.\r
+        * \r
+     * <P> MT- only one thread  is allowed to perform backup at any given time. \r
+     *  Synchronized on this. Parallel backups are not supported. \r
+        */\r
+       public synchronized void backup(Transaction t, File backupDir) \r
+        throws StandardException\r
+       {\r
+        if (!privExists(backupDir))\r
+               {\r
+            // if backup dir does not exist, go ahead and create it.\r
+\r
+            if (!privMkdirs(backupDir))\r
+            {\r
+                throw StandardException.newException(\r
+                    SQLState.RAWSTORE_CANNOT_CREATE_BACKUP_DIRECTORY,\r
+                    (File) backupDir);\r
+            }\r
+               }\r
+               else\r
+               {\r
+            // entity with backup name exists, make sure it is a directory.\r
+\r
+            if (!privIsDirectory(backupDir))\r
+            {\r
+                               throw StandardException.newException(\r
+                    SQLState.RAWSTORE_CANNOT_BACKUP_TO_NONDIRECTORY,\r
+                    (File) backupDir);\r
+            }\r
+\r
+            // check if a user has given the backup as a database directory by\r
+            // mistake, backup path can not be a derby database directory. \r
+            // If a directory contains PersistentService.PROPERTIES_NAME, it \r
+            // is assumed to be a derby database directory because derby \r
+            // databases always have this file. \r
\r
+            if (privExists(\r
+                    new File(backupDir, PersistentService.PROPERTIES_NAME))) \r
+            { \r
+                throw StandardException.newException(\r
+                    SQLState.RAWSTORE_CANNOT_BACKUP_INTO_DATABASE_DIRECTORY,\r
+                    (File) backupDir); \r
+            }\r
+               }\r
+               \r
+               boolean error = true;\r
+               boolean renamed = false;\r
+               boolean renameFailed = false;\r
+               File oldbackup = null;\r
+               File backupcopy = null;\r
+               OutputStreamWriter historyFile = null;\r
+        StorageFile dbHistoryFile = null;\r
+        File backupHistoryFile = null;\r
+               LogInstant backupInstant = logFactory.getFirstUnflushedInstant();\r
+        \r
+               try\r
+               {\r
+                       // get name of the current db, ie. database directory of current db.\r
+                       StorageFile dbase           = storageFactory.newStorageFile(null); \r
+            String      canonicalDbName = storageFactory.getCanonicalName();\r
+            int         lastSep         = \r
+                canonicalDbName.lastIndexOf(storageFactory.getSeparator());\r
+                       String      dbname          = \r
+                canonicalDbName.substring(lastSep + 1);\r
+\r
+                       // append to end of history file\r
+                       historyFile = \r
+                privFileWriter(\r
+                    storageFactory.newStorageFile(BACKUP_HISTORY), true);\r
+            \r
+                       backupcopy = new File(backupDir, dbname);\r
+\r
+                       logHistory(\r
+                historyFile,\r
+                MessageService.getTextMessage(\r
+                    MessageId.STORE_BACKUP_STARTED, \r
+                    canonicalDbName, \r
+                    getFilePath(backupcopy)));\r
+\r
+            \r
+            // check if a backup copy of this database already exists,\r
+            if (privExists(backupcopy))\r
+                       {\r
+                               // first make a backup of the backup\r
+                               oldbackup = new File(backupDir, dbname+".OLD");\r
+                if (privExists(oldbackup))\r
+                               {\r
+                    if (privIsDirectory(oldbackup))\r
+                        privRemoveDirectory(oldbackup);\r
+                                       else\r
+                        privDelete(oldbackup);\r
+                               }\r
+\r
+                if (!privRenameTo(backupcopy,oldbackup))\r
+                {\r
+                    renameFailed = true;\r
+                    throw StandardException.\r
+                        newException(SQLState.RAWSTORE_ERROR_RENAMING_FILE,\r
+                                     backupcopy, oldbackup);\r
+                }\r
+                               else\r
+                               {\r
+                                       logHistory(\r
+                        historyFile,\r
+                        MessageService.getTextMessage(\r
+                            MessageId.STORE_MOVED_BACKUP,\r
+                            getFilePath(backupcopy),\r
+                            getFilePath(oldbackup)));\r
+                                       renamed = true;\r
+                               }\r
+                       }\r
+\r
+            // create the backup database directory\r
+            if (!privMkdirs(backupcopy))\r
+            {\r
+                throw StandardException.newException(\r
+                    SQLState.RAWSTORE_CANNOT_CREATE_BACKUP_DIRECTORY,\r
+                    (File) backupcopy);\r
+            }\r
+\r
+            dbHistoryFile = storageFactory.newStorageFile(BACKUP_HISTORY);\r
+            backupHistoryFile = new File(backupcopy, BACKUP_HISTORY); \r
+\r
+            // copy the history file into the backup. \r
+            if(!privCopyFile(dbHistoryFile, backupHistoryFile))\r
+                throw StandardException. \r
+                    newException(SQLState.RAWSTORE_ERROR_COPYING_FILE,\r
+                                 dbHistoryFile, backupHistoryFile);  \r
+\r
+\r
+            // if they are any jar file stored in the database, copy them into\r
+            // the backup. \r
+            StorageFile jarDir = \r
+                storageFactory.newStorageFile(FileResource.JAR_DIRECTORY_NAME);\r
+\r
+            if (privExists(jarDir)) \r
+            {\r
+                // find the list of schema directories under the jar dir and\r
+                // then copy only the plain files under those directories. One \r
+                // could just use the recursive copy of directory to copy all \r
+                // the files under the jar dir, but the problem with that is if\r
+                // a user gives jar directory as the backup path by mistake, \r
+                // copy will fail while copying the backup dir onto itself in \r
+                // recursion\r
+\r
+                String [] jarSchemaList = privList(jarDir);\r
+                File backupJarDir = new File(backupcopy, \r
+                                             FileResource.JAR_DIRECTORY_NAME);\r
+                // Create the backup jar directory\r
+                if (!privMkdirs(backupJarDir))\r
+                {\r
+                    throw StandardException.newException(\r
+                          SQLState.RAWSTORE_CANNOT_CREATE_BACKUP_DIRECTORY,\r
+                          (File) backupJarDir);\r
+                }\r
+\r
+                for (int i = 0; i < jarSchemaList.length; i++)\r
+                {\r
+                    StorageFile jarSchemaDir = \r
+                        storageFactory.newStorageFile(jarDir, jarSchemaList[i]);\r
+                    File backupJarSchemaDir = \r
+                        new File(backupJarDir, jarSchemaList[i]);\r
+\r
+                    if (!privCopyDirectory(jarSchemaDir, backupJarSchemaDir, \r
+                                           (byte[])null, null, false)) \r
+                    {\r
+                        throw StandardException.\r
+                            newException(SQLState.RAWSTORE_ERROR_COPYING_FILE,\r
+                                         jarSchemaDir, backupJarSchemaDir);  \r
+                    }\r
+                }\r
+            }\r
+\r
+\r
+            // save service properties into the backup, Read in property \r
+            // from service.properties file, remove logDevice from it, \r
+            // then write it to the backup.\r
+\r
+            StorageFile logdir = logFactory.getLogDirectory();\r
+            \r
+            try \r
+            {\r
+                String name = Monitor.getMonitor().getServiceName(this);\r
+                PersistentService ps = \r
+                    Monitor.getMonitor().getServiceType(this);\r
+                String fullName = ps.getCanonicalServiceName(name);\r
+                Properties prop = \r
+                    ps.getServiceProperties(fullName, (Properties)null);\r
+\r
+                StorageFile defaultLogDir = \r
+                    storageFactory.newStorageFile(\r
+                        LogFactory.LOG_DIRECTORY_NAME);\r
+\r
+                if (!logdir.equals(defaultLogDir))  \r
+                {\r
+                    prop.remove(Attribute.LOG_DEVICE);\r
+                    if (SanityManager.DEBUG)\r
+                    {\r
+                        SanityManager.ASSERT(\r
+                            prop.getProperty(Attribute.LOG_DEVICE) == null,\r
+                            "cannot get rid of logDevice property");\r
+                    }\r
+\r
+                    logHistory(historyFile,\r
+                               MessageService.getTextMessage(\r
+                               MessageId.STORE_EDITED_SERVICEPROPS));\r
+                }\r
+            \r
+                // save the service properties into the backup.\r
+                ps.saveServiceProperties(backupcopy.getPath(), prop, false);\r
+\r
+            }\r
+            catch(StandardException se) \r
+            {\r
+                logHistory(\r
+                   historyFile,\r
+                   MessageService.getTextMessage(\r
+                       MessageId.STORE_ERROR_EDIT_SERVICEPROPS) + se);\r
+\r
+                return; // skip the rest and let finally block clean up\r
+            }\r
+\r
+            // Incase of encrypted database and the key is an external \r
+            // encryption key, there is an extra file with name  \r
+            // Attribute.CRYPTO_EXTERNAL_KEY_VERIFY_FILE, this file should be\r
+            // copied in to the backup.\r
+            StorageFile verifyKeyFile = \r
+                storageFactory.newStorageFile(\r
+                                 Attribute.CRYPTO_EXTERNAL_KEY_VERIFY_FILE);\r
+            if (privExists(verifyKeyFile)) \r
+            {\r
+                File backupVerifyKeyFile = \r
+                    new File(\r
+                        backupcopy, Attribute.CRYPTO_EXTERNAL_KEY_VERIFY_FILE);\r
+\r
+                if(!privCopyFile(verifyKeyFile, backupVerifyKeyFile))\r
+                   throw StandardException.\r
+                       newException(SQLState.RAWSTORE_ERROR_COPYING_FILE,\r
+                                    verifyKeyFile, backupVerifyKeyFile);  \r
+            }\r
+                \r
+                       File logBackup = \r
+                new File(backupcopy, LogFactory.LOG_DIRECTORY_NAME);\r
+\r
+                       // this is wierd, delete it\r
+            if (privExists(logBackup))\r
+                       {\r
+                privRemoveDirectory(logBackup);\r
+                       }\r
+\r
+                       // Create the log directory\r
+            if (!privMkdirs(logBackup))\r
+            {\r
+                throw StandardException.newException(\r
+                    SQLState.RAWSTORE_CANNOT_CREATE_BACKUP_DIRECTORY,\r
+                    (File) logBackup);\r
+            }\r
+\r
+                       // do a checkpoint to get the persistent store up to date.\r
+                       logFactory.checkpoint(this, dataFactory, xactFactory, true);\r
+                       \r
+                       // start the transaction log  backup. \r
+            logFactory.startLogBackup(logBackup);\r
+\r
+                       File segBackup = new File(backupcopy, "seg0");\r
+                       \r
+                       // Create the data segment directory\r
+            if (!privMkdirs(segBackup))\r
+            {\r
+                throw StandardException.newException(\r
+                    SQLState.RAWSTORE_CANNOT_CREATE_BACKUP_DIRECTORY,\r
+                    (File) segBackup);\r
+            }\r
+\r
+                       // backup all the information in the data segment.\r
+                       dataFactory.backupDataFiles(t, segBackup);\r
+\r
+            logHistory(historyFile,\r
+                   MessageService.getTextMessage(\r
+                   MessageId.STORE_DATA_SEG_BACKUP_COMPLETED,\r
+                   getFilePath(segBackup)));\r
+\r
+\r
+            // copy the log that got generated after the backup started to\r
+                       // backup location and tell the logfactory that backup has come \r
+            // to end.\r
+                       logFactory.endLogBackup(logBackup);\r
+                                                                                                                                                 \r
+                       logHistory(historyFile,\r
+                MessageService.getTextMessage(\r
+                    MessageId.STORE_COPIED_LOG,\r
+                    getFilePath(logdir),\r
+                    getFilePath(logBackup)));\r
+\r
+                       error = false;\r
+               }\r
+               catch (IOException ioe)\r
+               {\r
+                       throw StandardException.newException(\r
+                    SQLState.RAWSTORE_UNEXPECTED_EXCEPTION, ioe);\r
+               }\r
+               finally\r
+               {\r
+\r
+                       try\r
+                       {\r
+                               if (error)\r
+                               {\r
+                                       \r
+                                       // Abort all activity related to backup in the log factory.\r
+                                       logFactory.abortLogBackup();\r
+\r
+                                       // remove the half backed up copy\r
+                                       // unless the error occured during  rename process;\r
+                                       // inwhich case 'backupcopy' refers to the previous backup\r
+                                       // not an half backed one.\r
+                                       if(!renameFailed)\r
+                                               privRemoveDirectory(backupcopy);\r
+\r
+                                       if (renamed)\r
+                                               // recover the old backup\r
+                        privRenameTo(oldbackup,backupcopy);\r
+\r
+                                       logHistory(historyFile,\r
+                        MessageService.getTextMessage(\r
+                            MessageId.STORE_BACKUP_ABORTED));\r
+\r
+                               }\r
+                               else\r
+                               {\r
+                                       // success, remove the old backup copy\r
+                    if (renamed && privExists(oldbackup))\r
+                                       {\r
+                                               // get rid of the old backup\r
+                        privRemoveDirectory(oldbackup);\r
+                                               logHistory(historyFile,\r
+                            MessageService.getTextMessage(\r
+                                MessageId.STORE_REMOVED_BACKUP,\r
+                                getFilePath(oldbackup)));\r
+                                       }\r
+                                       logHistory(historyFile,\r
+                        MessageService.getTextMessage(\r
+                            MessageId.STORE_BACKUP_COMPLETED,\r
+                            backupInstant));\r
+\r
+                    // copy the updated version of history file with current\r
+                    // backup information into the backup.\r
+                    if(!privCopyFile(dbHistoryFile, backupHistoryFile))\r
+                        throw StandardException. \r
+                            newException(SQLState.RAWSTORE_ERROR_COPYING_FILE,\r
+                                         dbHistoryFile, backupHistoryFile);  \r
+                               }\r
+\r
+                               historyFile.close();\r
+                       }\r
+                       catch (IOException ioe)\r
+                       {\r
+                try\r
+                {\r
+                    historyFile.close();\r
+                }\r
+                catch (IOException ioe2){};\r
+                throw StandardException.newException(\r
+                        SQLState.RAWSTORE_UNEXPECTED_EXCEPTION, ioe);\r
+                       }\r
+               }\r
+\r
+       }\r
+\r
+    /**\r
+     * Backup the database to a backup directory and enable the log archive\r
+        * mode that will keep the archived log files required for roll-forward\r
+        * from this version backup.\r
+     *\r
+     * @param backupDir the name of the directory where the backup should be\r
+     *                  stored. This directory will be created if it \r
+     *                  does not exist.   \r
+     *\r
+     * @param deleteOnlineArchivedLogFiles  \r
+     *                  If true deletes online archived \r
+     *                  log files that exist before this backup, delete \r
+     *                  will occur  only after the backup is  complete.\r
+     *\r
+     * @param wait      if <tt>true</tt>, waits for  all the backup blocking \r
+     *                  operations in progress to finish.\r
+     *\r
+     * @exception StandardException thrown on error.\r
+     */\r
+    public void backupAndEnableLogArchiveMode(\r
+    String backupDir,\r
+    boolean deleteOnlineArchivedLogFiles,\r
+    boolean wait) \r
+               throws StandardException\r
+       {\r
+        boolean enabledLogArchive = false;\r
+        try {\r
+            // Enable the log archive mode, if it is not already enabled.\r
+            if(!logFactory.logArchived()) {\r
+                logFactory.enableLogArchiveMode();\r
+                enabledLogArchive = true ;\r
+            }\r
+\r
+            backup(backupDir, wait);\r
+            \r
+            // After successful backup delete the archived log files\r
+            // that are not necessary to do a roll-forward recovery\r
+            // from this backup if requested.\r
+            if (deleteOnlineArchivedLogFiles)\r
+            {\r
+                logFactory.deleteOnlineArchivedLogFiles();\r
+            }\r
+        }catch (Throwable error) {\r
+            // On any errors , disable the log archive, if it \r
+            // is enabled on this call. \r
+            if (enabledLogArchive)\r
+                logFactory.disableLogArchiveMode();\r
+            throw StandardException.plainWrapException(error);\r
+        }\r
+       }\r
+\r
+\r
+    /*\r
+     * Disable the log archive mode and delete the archived log files \r
+     * if requested. \r
+     *\r
+     * @param deleteOnlineArchivedLogFiles  \r
+     *              If true deletes online archived \r
+     *              log files that exist before this backup, delete \r
+     *              will occur  only after the backup is  complete.\r
+     * @exception StandardException thrown on error.\r
+     */\r
+       public void disableLogArchiveMode(boolean deleteOnlineArchivedLogFiles)\r
+               throws StandardException\r
+       {\r
+               logFactory.disableLogArchiveMode();\r
+               if(deleteOnlineArchivedLogFiles)\r
+               {\r
+            logFactory.deleteOnlineArchivedLogFiles();\r
+        }\r
+       }\r
+\r
+       \r
+       /*\r
+        * Restore any remaining files from backup that are not \r
+        * restored by the individual factories.  \r
+        *  1) copy jar files from backup..\r
+        *  2) copy backup history file. \r
+        */\r
+       private void restoreRemainingFromBackup(String backupPath) \r
+               throws StandardException \r
+       {\r
+       \r
+               // if they are any jar files in the backup copy, \r
+               // copy them into the database directory, if they\r
+               // are not already there. \r
+\r
+               File backupJarDir = new File(backupPath, \r
+                                                                        FileResource.JAR_DIRECTORY_NAME);\r
+\r
+               StorageFile dbJarDir = \r
+                       storageFactory.newStorageFile(FileResource.JAR_DIRECTORY_NAME);\r
+               \r
+               if (!privExists(dbJarDir) && privExists(backupJarDir)) \r
+               {\r
+                       if (!privCopyDirectory(backupJarDir, dbJarDir)) {\r
+                               throw StandardException.newException(\r
+                         SQLState.UNABLE_TO_COPY_FILE_FROM_BACKUP, \r
+                         backupJarDir, dbJarDir);\r
+                       }\r
+               }\r
+\r
+               // copy the backup history file from the backup. \r
+               StorageFile dbHistoryFile = \r
+                       storageFactory.newStorageFile(BACKUP_HISTORY);\r
+               File backupHistoryFile = new File(backupPath, BACKUP_HISTORY);\r
+       \r
+               // if this is a roll-forward recovery, backup history file \r
+               // will already there in the database and will be the latest \r
+               // copy; if it exists, do not copy from backup.\r
+               if (!privExists(dbHistoryFile))\r
+                       if (!privCopyFile(backupHistoryFile, dbHistoryFile))\r
+                               throw StandardException. \r
+                                       newException(SQLState.RAWSTORE_ERROR_COPYING_FILE,\r
+                                                                backupHistoryFile, dbHistoryFile);  \r
+       }\r
+\r
+\r
+       public void idle() throws StandardException {\r
+               dataFactory.idle();\r
+       }\r
+\r
+\r
+       public TransactionInfo[] getTransactionInfo()\r
+       {\r
+               return xactFactory.getTransactionInfo();\r
+       }\r
+\r
+\r
+       public ScanHandle openFlushedScan(DatabaseInstant start, int groupsIWant)\r
+                throws StandardException\r
+       {\r
+               return logFactory.openFlushedScan(start,groupsIWant);\r
+       }\r
+\r
+       public DaemonService getDaemon()\r
+       {\r
+               return rawStoreDaemon;\r
+       }\r
+\r
+       public void createFinished() throws StandardException\r
+       {\r
+               xactFactory.createFinished();\r
+               dataFactory.createFinished();\r
+       }\r
+\r
+       /**\r
+        * Get JBMS properties relavent to raw store\r
+        * @exception StandardException Standard Derby Error Policy\r
+        */\r
+       public void getRawStoreProperties(PersistentSet set)\r
+                throws StandardException\r
+       {\r
+               logFactory.getLogFactoryProperties(set);\r
+       }\r
+\r
+\r
+       /*\r
+       ** backup restore\r
+       */\r
+       /**\r
+               Freeze persistent store.  Reads can still happen, only cannot write.\r
+               @exception StandardException Standard Derby Error Policy\r
+        */\r
+       public void freezePersistentStore() throws StandardException\r
+       {\r
+               // do a checkpoint to get the persistent store up to date.\r
+               logFactory.checkpoint(this, dataFactory, xactFactory,true);\r
+               logFactory.freezePersistentStore();\r
+\r
+       }\r
+\r
+       /**\r
+               Freeze persistent store.  Reads can still happen, only cannot write.\r
+               @exception StandardException Standard Derby Error Policy\r
+        */\r
+       public void unfreezePersistentStore() throws StandardException\r
+       {\r
+               logFactory.unfreezePersistentStore();\r
+       }\r
+\r
+\r
+       /*\r
+       ** data encryption/decryption support\r
+       */\r
+\r
+\r
+    /*\r
+     * Setup Encryption Engines. \r
+     */\r
+    private void setupEncryptionEngines(boolean create, Properties properties)\r
+        throws StandardException\r
+    {\r
+                    \r
+            // check if user has requested to encrypt the database or it is an\r
+            // encrypted database.\r
+\r
+            String dataEncryption = \r
+                properties.getProperty(Attribute.DATA_ENCRYPTION);\r
+            databaseEncrypted = Boolean.valueOf(dataEncryption).booleanValue(); \r
+\r
+            boolean reEncrypt = false;\r
+\r
+            if (!create) {\r
+                // check if database is already encrypted, by directly peeking at the\r
+                // database service propertes instead of the properties passed \r
+                // to this method. By looking at properties to the boot method ,\r
+                // one can not differentiate if user is requesting for database\r
+                // encryption or the database is already encrypted because \r
+                // Attribute.DATA_ENCRYPTION is used  to store in the \r
+                // service properties to indicate that database\r
+                // is encrypted and also users can specify it as URL attribute \r
+                // to encrypt and existing database. \r
+                               \r
+                String name = Monitor.getMonitor().getServiceName(this);\r
+                PersistentService ps = Monitor.getMonitor().getServiceType(this);\r
+                String canonicalName = ps.getCanonicalServiceName(name);\r
+                Properties serviceprops = ps.getServiceProperties(canonicalName, \r
+                                                                  (Properties)null);\r
+                dataEncryption = serviceprops.getProperty(Attribute.DATA_ENCRYPTION);\r
+                boolean encryptedDatabase = Boolean.valueOf(dataEncryption).booleanValue();\r
+\r
+                if (!encryptedDatabase  && databaseEncrypted) {\r
+                    // it it not an encrypted database, user is asking to \r
+                    // encrypt an un-encrypted database. \r
+                    encryptDatabase = true;\r
+                    // set database as un-encrypted, we will set it as encrypted \r
+                    // after encrypting the existing data. \r
+                    databaseEncrypted = false;\r
+                } else {\r
+                    // check if the user has requested to renecrypt  an\r
+                    // encrypted datbase with new encryption password/key.\r
+                    if (encryptedDatabase) {\r
+                        if (properties.getProperty(\r
+                                       Attribute.NEW_BOOT_PASSWORD) != null) {\r
+                            reEncrypt = true;\r
+                        }\r
+                        else if (properties.getProperty(\r
+                                       Attribute.NEW_CRYPTO_EXTERNAL_KEY) != null){\r
+                            reEncrypt = true;\r
+                        };\r
+                        encryptDatabase = reEncrypt;\r
+                    }\r
+\r
+                }\r
+                \r
+                \r
+                // NOTE: if user specifies Attribute.DATA_ENCRYPTION on the\r
+                // connection URL by mistake on an already encrypted database, \r
+                // it is ignored.\r
+\r
+\r
+                // prevent attempt to (re)encrypt of a read-only database\r
+                if (encryptDatabase) \r
+                {\r
+                    if (isReadOnly()) \r
+                    {\r
+                        if (reEncrypt) \r
+                            throw StandardException.newException(\r
+                                     SQLState.CANNOT_REENCRYPT_READONLY_DATABASE);\r
+                        else\r
+                            throw StandardException.newException(\r
+                                     SQLState.CANNOT_ENCRYPT_READONLY_DATABASE);\r
+                    }\r
+                }\r
+            }\r
+\r
+            // setup encryption engines. \r
+                       if (databaseEncrypted || encryptDatabase)\r
+                       {\r
+                // check if database is configured for encryption, during\r
+                // configuration  some of the properties database; so that\r
+                // user does not have to specify them on the URL everytime.\r
+                // Incase of re-encryption of an already of encrypted database\r
+                // only some information needs to updated; it is not treated \r
+                // like the configuring the database for encryption first time. \r
+                boolean setupEncryption = create || (encryptDatabase &&  !reEncrypt);\r
+\r
+                // start the cipher factory module, that is is used to create \r
+                // instances of the cipher factory with specific enctyption \r
+                // properties. \r
+\r
+                CipherFactoryBuilder cb =  (CipherFactoryBuilder)\r
+                    Monitor.startSystemModule(org.apache.derby.iapi.reference.Module.CipherFactoryBuilder);\r
+\r
+                // create instance of the cipher factory with the \r
+                // specified encryption properties. \r
+                currentCipherFactory = cb.createCipherFactory(setupEncryption, \r
+                                                              properties, \r
+                                                              false);\r
+\r
+                // The database can be encrypted using an encryption key that is given at\r
+                 // connection url. For security reasons, this key is not made persistent\r
+                // in the database. But it is necessary to verify the encryption key \r
+                // whenever booting the database if it is similar to the key that was used\r
+                // during creation time. This needs to happen before we access the data/logs to \r
+                // avoid the risk of corrupting the database because of a wrong encryption key.\r
+                \r
+                // Please note this verification process does not provide any added security\r
+                // but is intended to allow to fail gracefully if a wrong encryption key \r
+                // is used during boot time\r
+  \r
+\r
+                currentCipherFactory.verifyKey(setupEncryption, storageFactory, properties);\r
+\r
+                // Initializes the encryption and decryption engines\r
+                encryptionEngine = currentCipherFactory.\r
+                    createNewCipher(CipherFactory.ENCRYPT);\r
+                \r
+                // At creation time of an encrypted database, store the encryption block size\r
+                // for the algorithm. Store this value as property given by  \r
+                // RawStoreFactory.ENCRYPTION_BLOCKSIZE. This value\r
+                // is made persistent by storing it in service.properties\r
+                // To connect to an existing database, retrieve the value and use it for\r
+                // appropriate padding.\r
+                // The  default value of encryption block size is 8,\r
+                // to allow for downgrade issues\r
+                // Before support for AES (beetle6023), default encryption block size supported\r
+                // was 8\r
+\r
+                if(setupEncryption) \r
+                {\r
+                    encryptionBlockSize = encryptionEngine.getEncryptionBlockSize();\r
+                    // in case of database create, store the encryption block\r
+                    // size. Incase of reconfiguring the existing datbase, this\r
+                    // will be saved after encrypting the exisiting data. \r
+                    if (create)\r
+                        properties.put(RawStoreFactory.ENCRYPTION_BLOCKSIZE,\r
+                                       String.valueOf(encryptionBlockSize));\r
+                }\r
+                else\r
+                {\r
+                    if(properties.getProperty(RawStoreFactory.ENCRYPTION_BLOCKSIZE) != null)\r
+                        encryptionBlockSize = Integer.parseInt(properties.getProperty\r
+                                                               (RawStoreFactory.ENCRYPTION_BLOCKSIZE));\r
+                    else\r
+                        encryptionBlockSize = encryptionEngine.getEncryptionBlockSize();\r
+                }   \r
+\r
+                decryptionEngine = currentCipherFactory.\r
+                    createNewCipher(CipherFactory.DECRYPT);\r
+\r
+                random = currentCipherFactory.getSecureRandom();\r
+                    \r
+                if (encryptDatabase) {\r
+\r
+                    if (reEncrypt) {\r
+                        // create new cipher factory with the new encrytpion\r
+                        // properties specified by the user. This cipher factory\r
+                        // is used to create the new encryption/decryption\r
+                        // engines to reencrypt the database with the new\r
+                        // encryption keys. \r
+                        newCipherFactory = \r
+                            cb.createCipherFactory(setupEncryption, \r
+                                                   properties, \r
+                                                   true);\r
+                        newDecryptionEngine = \r
+                            newCipherFactory.createNewCipher(CipherFactory.DECRYPT);\r
+                        newEncryptionEngine = \r
+                            newCipherFactory.createNewCipher(CipherFactory.ENCRYPT);\r
+                    } else {\r
+                        // there is only one engine when configuring an \r
+                        // unencrypted database for encryption \r
+                        newDecryptionEngine = decryptionEngine;\r
+                        newEncryptionEngine = encryptionEngine;\r
+\r
+                    }\r
+                }\r
+\r
+                // save the encryption properties if encryption is enabled \r
+                // at database creation time. \r
+                if(create)\r
+                    currentCipherFactory.saveProperties(properties) ;\r
+                       }\r
+    }\r
+    \r
+\r
+       /**\r
+               Encrypt cleartext into ciphertext.\r
+\r
+               @see CipherProvider#encrypt\r
+\r
+               @exception StandardException Standard Derby Error Policy\r
+        */\r
+       public int encrypt(byte[] cleartext, int offset, int length,\r
+                                          byte[] ciphertext, int outputOffset, \r
+                       boolean newEngine)\r
+                throws StandardException\r
+       {\r
+               if ((databaseEncrypted == false && encryptDatabase == false) || \r
+            (encryptionEngine == null && newEncryptionEngine == null))\r
+        {\r
+            throw StandardException.newException(\r
+                        SQLState.STORE_FEATURE_NOT_IMPLEMENTED);\r
+        }\r
+\r
+               counter_encrypt++;\r
+\r
+        if (newEngine) {\r
+            return newEncryptionEngine.encrypt(cleartext, offset, length,\r
+                                            ciphertext, outputOffset);\r
+        } else {\r
+            return encryptionEngine.encrypt(cleartext, offset, length,\r
+                                            ciphertext, outputOffset);\r
+        }\r
+       }\r
+\r
+       /**\r
+               Decrypt cleartext from ciphertext.\r
+\r
+               @see CipherProvider#decrypt\r
+\r
+               @exception StandardException Standard Derby Error Policy\r
+        */\r
+       public int decrypt(byte[] ciphertext, int offset, int length,\r
+                                          byte[] cleartext, int outputOffset) \r
+                throws StandardException\r
+       {\r
+               if (databaseEncrypted == false || decryptionEngine == null)\r
+        {\r
+            throw StandardException.newException(\r
+                        SQLState.STORE_FEATURE_NOT_IMPLEMENTED);\r
+        }\r
+\r
+               counter_decrypt++;\r
+        return decryptionEngine.decrypt(ciphertext, offset, length,\r
+                                            cleartext, outputOffset);\r
+       }\r
+\r
+       /**\r
+               Returns the encryption block size used by the algorithm at time of\r
+               creation of an encrypted database\r
+        */\r
+       public int getEncryptionBlockSize()\r
+       {\r
+               return encryptionBlockSize;\r
+       }\r
+\r
+       public int random()\r
+       {\r
+               // don't synchronize it, the more random the better.\r
+               return databaseEncrypted ? random.nextInt() : 0;\r
+       }\r
+\r
+       public Serializable changeBootPassword(Properties properties, Serializable changePassword)\r
+                throws StandardException\r
+       {\r
+               if (isReadOnly())\r
+                       throw StandardException.newException(SQLState.DATABASE_READ_ONLY);\r
+\r
+               if (!databaseEncrypted)\r
+                       throw StandardException.newException(SQLState.DATABASE_NOT_ENCRYPTED);\r
+\r
+               if (changePassword == null)\r
+                       throw StandardException.newException(SQLState.NULL_BOOT_PASSWORD);\r
+\r
+               if (!(changePassword instanceof String))\r
+                       throw StandardException.newException(SQLState.NON_STRING_BP);\r
+\r
+               // the new bootPassword is expected to be of the form\r
+               // oldkey , newkey.\r
+               String changeString = (String)changePassword;\r
+\r
+               return currentCipherFactory.changeBootPassword((String)changePassword, properties, encryptionEngine);\r
+\r
+       }\r
+\r
+\r
+    /**\r
+     * (re) encryption testing debug flags that are used to \r
+     * simulate error/crash conditions for testing purposes.\r
+     * When any one of the following flags are set to true\r
+     * in the debug mode, re-encryption will fail at that point.\r
+     */\r
+\r
+       public static final String TEST_REENCRYPT_CRASH_BEFORE_COMMT  = \r
+        SanityManager.DEBUG ? "TEST_REENCRYPT_CRASH_BEFORE_COMMT" : null ;\r
+    public static final String TEST_REENCRYPT_CRASH_AFTER_COMMT  = \r
+        SanityManager.DEBUG ? "TEST_REENCRYPT_CRASH_AFTER_COMMT" : null ;\r
+    public static final String TEST_REENCRYPT_CRASH_AFTER_SWITCH_TO_NEWKEY  = \r
+        SanityManager.DEBUG ? "TEST_REENCRYPT_CRASH_AFTER_SWITCH_TO_NEWKEY" : null ;\r
+    public static final String TEST_REENCRYPT_CRASH_AFTER_CHECKPOINT  = \r
+        SanityManager.DEBUG ? "TEST_REENCRYPT_CRASH_AFTER_CHECKPOINT" : null ;\r
+    public static final String \r
+        TEST_REENCRYPT_CRASH_AFTER_RECOVERY_UNDO_LOGFILE_DELETE =\r
+        SanityManager.DEBUG ?\r
+        "TEST_REENCRYPT_CRASH_AFTER_RECOVERY_UNDO_LOGFILE_DELETE" : null;\r
+    public static final String \r
+        TEST_REENCRYPT_CRASH_AFTER_RECOVERY_UNDO_REVERTING_KEY =\r
+        SanityManager.DEBUG ?\r
+        "TEST_REENCRYPT_CRASH_AFTER_RECOVERY_UNDO_REVERTING_KEY" : null;\r
+    public static final String \r
+        TEST_REENCRYPT_CRASH_BEFORE_RECOVERY_FINAL_CLEANUP =\r
+        SanityManager.DEBUG ?\r
+        "TEST_REENCRYPT_CRASH_BEFORE_RECOVERY_FINAL_CLEANUP" : null;\r
+    \r
+    \r
+\r
+    /** \r
+     * when the input debug flag is set, an expception \r
+     * is throw when run in the debug mode.\r
+     */\r
+    private void crashOnDebugFlag(String debugFlag, \r
+                                  boolean reEncrypt) \r
+        throws StandardException\r
+    {\r
+        if (SanityManager.DEBUG)\r
+        {\r
+            // if the test debug flag is set, throw an \r
+            // exception to simulate error cases.\r
+            if (SanityManager.DEBUG_ON(debugFlag))\r
+            {\r
+               StandardException se = StandardException.newException(\r
+                                      (reEncrypt ? SQLState.DATABASE_REENCRYPTION_FAILED :\r
+                                      SQLState.DATABASE_ENCRYPTION_FAILED),\r
+                                      debugFlag);\r
+               markCorrupt(se);\r
+               throw se;\r
+            }\r
+        }\r
+    }\r
+\r
+    /*\r
+     * Configure the database for encryption, with the  specified \r
+     * encryption  properties.\r
+     *\r
+     * Basic idea is to encrypt all the containers with new password/key \r
+     * specified by the user and keep old versions of the data to \r
+     * rollback the database to the state before the configuration of database \r
+     * with new encryption attributes. Users can configure the database with \r
+     * new encryption  attributes at boot time only; advantage of this approach\r
+     * is that there will not be any concurrency issues to handle because\r
+     * no users will be modifying the data. \r
+     *\r
+     * First step is to encrypt the existing data with new encryption \r
+     * attributes  and then update the encryption properties for \r
+     * the database. Configuring  an un-encrypted database for \r
+     * encryption problem is a minor variation of  re-encrypting an \r
+     * encrypted database with new encryption key. The database \r
+     * reconfiguration with new encryption attributes is done under one\r
+     * transaction, if there is a crash/error before it is committed, \r
+     * then it  is rolled back and the database will be brought back to the\r
+     * state it was before the encryption.  \r
+     *\r
+     * One trickey case in (re) encrypion of database is \r
+     * unlike standard protocol transaction  commit means all done, \r
+     * database (re) encryption process has to perform a checkpoint\r
+     *  with a newly generated key then only database  (re) encrption \r
+     * is complete, Otherwise the problem  is recovery has to deal \r
+     * with transaction log that is encrypted with old encryption key and \r
+     * the new encryption key. This probelm is avoided  writing COMMIT\r
+     * and new  CHECKPOINT log record  to a new log file and encrypt the \r
+     * with a new key, if there is  crash before checkpoint records \r
+     * are updated , then on next boot the log file after the checkpoint \r
+     * is deleted before reovery,  which will be the one that is  \r
+     * written with new encryption key and also contains COMMIT record, \r
+     * so the COMMIT record is also gone when  log file is deleted. \r
+     * Recovery will not see the commit , so it will  rollback the (re)\r
+     * encryption and revert all the containers to the \r
+     * original versions. \r
+     * \r
+     * Old container versions are deleted only when the check point \r
+     * with new encryption key is successful, not on post-commit. \r
+     *\r
+     * @param properties  properties related to this database.\r
+     * @exception StandardException Standard Derby Error Policy\r
+     */\r
+    public void configureDatabaseForEncryption(Properties properties,\r
+                                               CipherFactory newCipherFactory) \r
+        throws StandardException \r
+    {\r
+\r
+        boolean reEncrypt = (databaseEncrypted && encryptDatabase);\r
+\r
+        // check if the database can be encrypted.\r
+        canEncryptDatabase(reEncrypt);\r
+\r
+        boolean externalKeyEncryption = false;\r
+        if (properties.getProperty(Attribute.CRYPTO_EXTERNAL_KEY) != null)\r
+        {\r
+                externalKeyEncryption = true;\r
+        }\r
+\r
+        // check point the datase, so that encryption does not have\r
+        // to encrypt the existing transactions logs. \r
\r
+        logFactory.checkpoint(this, dataFactory, xactFactory, true);\r
+\r
+        // start a transaction that is to be used for encryting the database\r
+        RawTransaction transaction =\r
+            xactFactory.startTransaction(\r
+                   this,\r
+                    ContextService.getFactory().getCurrentContextManager(),\r
+                    AccessFactoryGlobals.USER_TRANS_NAME);\r
+\r
+        try \r
+               {\r
+                       \r
+            dataFactory.encryptAllContainers(transaction);\r
+\r
+            // all the containers are (re) encrypted, now mark the database as\r
+            // encrypted if a plain database is getting configured for encryption\r
+            // or update the encryption the properties, in the \r
+            // service.properties ..etc.\r
+\r
+            \r
+            if (SanityManager.DEBUG) {\r
+                crashOnDebugFlag(TEST_REENCRYPT_CRASH_BEFORE_COMMT, reEncrypt);\r
+            }\r
+\r
+            // check if the checkpoint is currently in the last log file, \r
+            // otherwise force a checkpoint and then do a log switch, \r
+            // after setting up a new encryption key\r
+            if (!logFactory.isCheckpointInLastLogFile()) \r
+            {\r
+                // perfrom a checkpoint, this is a reference checkpoint \r
+                // to find if the re(encryption) is complete. \r
+                logFactory.checkpoint(this, dataFactory, xactFactory, true);\r
+            }\r
+                \r
+\r
+            encryptDatabase = false;\r
+\r
+            // let the log factory know that database is \r
+            // (re) encrypted and ask it to flush the log, \r
+            // before enabling encryption of the log with \r
+            // the new key.\r
+            logFactory.setDatabaseEncrypted(true);\r
+            \r
+            // let the log factory and data factory know that \r
+            // database is encrypted.\r
+            if (!reEncrypt) {\r
+                // mark in the raw store that the database is \r
+                // encrypted. \r
+                databaseEncrypted = true;\r
+                dataFactory.setDatabaseEncrypted();\r
+            } else {\r
+                // switch the encryption/decryption engine to the new ones.\r
+                decryptionEngine = newDecryptionEngine;  \r
+                encryptionEngine = newEncryptionEngine;\r
+                currentCipherFactory = newCipherFactory;\r
+            }\r
+\r
+            \r
+            // make the log factory ready to encrypt\r
+            // the transaction log with the new encryption \r
+            // key by switching to a new log file. \r
+            // If re-encryption is aborted for any reason, \r
+            // this new log file will be deleted, during\r
+            // recovery.\r
+\r
+            logFactory.startNewLogFile();\r
+\r
+            // mark that re-encryption is in progress in the \r
+            // service.properties, so that (re) encryption \r
+            // changes that can not be undone using the transaction \r
+            // log can be un-done before recovery starts.\r
+            // (like the changes to service.properties and \r
+            // any log files the can not be understood by the\r
+            // old encryption key), incase engine crashes\r
+            // after this point. \r
+\r
+            // if the crash occurs before this point, recovery\r
+            // will rollback the changes using the transaction \r
+            // log.\r
+\r
+            properties.put(RawStoreFactory.DB_ENCRYPTION_STATUS,\r
+                           String.valueOf(\r
+                               RawStoreFactory.DB_ENCRYPTION_IN_PROGRESS));\r
+\r
+            if (reEncrypt) \r
+            {\r
+                // incase re-encryption, save the old \r
+                // encryption related properties, before\r
+                // doing updates with new values.\r
+\r
+                if (externalKeyEncryption) \r
+                {\r
+                    // save the current copy of verify key file.\r
+                    StorageFile verifyKeyFile = \r
+                        storageFactory.newStorageFile(\r
+                                 Attribute.CRYPTO_EXTERNAL_KEY_VERIFY_FILE);\r
+                    StorageFile oldVerifyKeyFile = \r
+                        storageFactory.newStorageFile(\r
+                          RawStoreFactory.CRYPTO_OLD_EXTERNAL_KEY_VERIFY_FILE);\r
+\r
+                    if(!privCopyFile(verifyKeyFile, oldVerifyKeyFile))\r
+                        throw StandardException.\r
+                            newException(SQLState.RAWSTORE_ERROR_COPYING_FILE,\r
+                                         verifyKeyFile, oldVerifyKeyFile); \r
+\r
+                    // update the verify key file with the new key info.\r
+                    currentCipherFactory.verifyKey(reEncrypt, \r
+                                                   storageFactory, \r
+                                                   properties);\r
+                } else \r
+                {\r
+                    // save the current generated encryption key \r
+                    String keyString = \r
+                        properties.getProperty(\r
+                                               RawStoreFactory.ENCRYPTED_KEY);\r
+                    if (keyString != null)\r
+                        properties.put(RawStoreFactory.OLD_ENCRYPTED_KEY,\r
+                                       keyString);\r
+                }\r
+            } else \r
+            {\r
+                // save the encryption block size;\r
+                properties.put(RawStoreFactory.ENCRYPTION_BLOCKSIZE,\r
+                               String.valueOf(encryptionBlockSize));\r
+            }\r
+\r
+            // save the new encryption properties into service.properties\r
+            currentCipherFactory.saveProperties(properties) ;\r
\r
+            if (SanityManager.DEBUG) {\r
+                crashOnDebugFlag(\r
+                                 TEST_REENCRYPT_CRASH_AFTER_SWITCH_TO_NEWKEY,\r
+                                 reEncrypt);\r
+            }\r
+\r
+            // commit the transaction that is used to \r
+            // (re) encrypt the database. Note that \r
+            // this will be logged with newly generated \r
+            // encryption key in the new log file created \r
+            // above.\r
+            transaction.commit();\r
+\r
+            if (SanityManager.DEBUG) {\r
+                crashOnDebugFlag(TEST_REENCRYPT_CRASH_AFTER_COMMT, \r
+                                 reEncrypt);\r
+            }\r
+\r
+            // force the checkpoint with new encryption key.\r
+            logFactory.checkpoint(this, dataFactory, xactFactory, true);\r
+\r
+            if (SanityManager.DEBUG) {\r
+                crashOnDebugFlag(TEST_REENCRYPT_CRASH_AFTER_CHECKPOINT, \r
+                                 reEncrypt);\r
+            }\r
+\r
+            // once the checkpont makes it to the log, re-encrption \r
+            // is complete. only cleanup is remaining ; update the \r
+            // re-encryption status flag to cleanup. \r
+            properties.put(RawStoreFactory.DB_ENCRYPTION_STATUS,\r
+                           String.valueOf(\r
+                               RawStoreFactory.DB_ENCRYPTION_IN_CLEANUP));\r
+\r
+            // database is (re)encrypted successfuly, \r
+            // remove the old version of the container files.\r
+            dataFactory.removeOldVersionOfContainers(false);\r
+                \r
+            if (reEncrypt) \r
+            {\r
+                if (externalKeyEncryption)\r
+                {\r
+                    // remove the saved copy of the verify.key file\r
+                    StorageFile oldVerifyKeyFile = \r
+                        storageFactory.newStorageFile(\r
+                          RawStoreFactory.CRYPTO_OLD_EXTERNAL_KEY_VERIFY_FILE);\r
+                    if (!privDelete(oldVerifyKeyFile))\r
+                        throw StandardException.newException(\r
+                                    SQLState.UNABLE_TO_DELETE_FILE, \r
+                                    oldVerifyKeyFile);\r
+                } else \r
+                {\r
+                    // remove the old encryption key property.\r
+                    properties.remove(RawStoreFactory.OLD_ENCRYPTED_KEY);\r
+                }\r
+            }\r
+\r
+            // (re) encrypion is done,  remove the (re) \r
+            // encryption status property. \r
+\r
+            properties.remove(RawStoreFactory.DB_ENCRYPTION_STATUS);\r
+\r
+            // close the transaction. \r
+            transaction.close(); \r
+\r
+        } catch (StandardException se) {\r
+\r
+            throw StandardException.newException(\r
+                      (reEncrypt ? SQLState.DATABASE_REENCRYPTION_FAILED :\r
+                      SQLState.DATABASE_ENCRYPTION_FAILED),\r
+                      se,\r
+                      se.getMessage()); \r
+        } finally {\r
+            // clear the new encryption engines.\r
+            newDecryptionEngine = null;   \r
+            newEncryptionEngine = null;\r
+        }\r
+    }\r
+\r
+\r
+    /**\r
+     * Engine might have crashed during encryption of un-encrypted datbase\r
+     * or while re-encryptin an already encrypted database with a new key\r
+     * after all the containers or (re) encrypted. If crash has occured\r
+     * before all containers are encrypted, recovery wil un-do re-encryption\r
+     * using the transaction log, nothing to be done here.\r
+     *\r
+     * If crash has occured after database encryption status flag \r
+     * (RawStoreFactory.DB_ENCRYPTION_STATUS) is set, this method \r
+     * will do any cleanup necessary for the recovery to correctly\r
+     * perform the rollback if required. \r
+     *\r
+     *\r
+     *\r
+     * @param properties  properties related to this database.\r
+     * @exception StandardException Standard Derby Error Policy\r
+     *\r
+     */\r
+    public void handleIncompleteDatabaseEncryption(Properties properties) \r
+        throws StandardException\r
+    {\r
+        // find what was the encryption status before database crashed. \r
+        int dbEncryptionStatus = 0; \r
+        String dbEncryptionStatusStr = \r
+            properties.getProperty(RawStoreFactory.DB_ENCRYPTION_STATUS);\r
+        if ( dbEncryptionStatusStr != null) \r
+            dbEncryptionStatus = Integer.parseInt(dbEncryptionStatusStr);\r
+\r
+        boolean reEncryption = false;\r
+        // check if engine crashed when (re) encryption was in progress.\r
+        if (dbEncryptionStatus == RawStoreFactory.DB_ENCRYPTION_IN_PROGRESS)\r
+        {\r
+\r
+            // check if it crashed immediately after completion or\r
+            // before. if the checkpoint is in the last log file \r
+            // encrypted with new encryption key, it is as good \r
+            // as complete. In this case just cleanup any uncleared\r
+            // flags and mark that database is encrypted.\r
+\r
+            if(logFactory.isCheckpointInLastLogFile()) \r
+            {\r
+                // database (re)encryption was successful, only \r
+                // cleanup is remaining. change the status to cleanup. \r
+                dbEncryptionStatus = RawStoreFactory.DB_ENCRYPTION_IN_CLEANUP;\r
+            }else {\r
+\r
+                // crash occured before re-encrytion was completed. \r
+                // update the db re-encryption status and write to \r
+                // the service.properties that re-encryption \r
+                // needs to be undone. The reason this status need \r
+                // to be made persistent, it will help to correctly \r
+                // handle a crash in this routine after the log file \r
+                // encrypted with new key is deleted. If this flag\r
+                // is not set, on next reboot, above check \r
+                // will find checkpoint in the last log file and \r
+                // incorrecly assume (re) encryption is\r
+                // successful.\r
+\r
+                dbEncryptionStatus =  RawStoreFactory.DB_ENCRYPTION_IN_UNDO;\r
+                properties.put(RawStoreFactory.DB_ENCRYPTION_STATUS,\r
+                               String.valueOf(dbEncryptionStatus));\r
+            }\r
+        }\r
+\r
+        \r
+        if (dbEncryptionStatus == RawStoreFactory.DB_ENCRYPTION_IN_UNDO)\r
+        {\r
+            // delete the log file after the log file that has the checkpoint , \r
+            // it has the data encrypted with the new key, including the commit\r
+            // record for the transaction that was used to (re)encrypt \r
+            // the database. By Deleting the log file, we are forcing the\r
+            // recovery to rollback the (re)encryption of the database. \r
+\r
+            logFactory.deleteLogFileAfterCheckpointLogFile();\r
+                \r
+            if (SanityManager.DEBUG) {\r
+                crashOnDebugFlag(\r
+                   TEST_REENCRYPT_CRASH_AFTER_RECOVERY_UNDO_LOGFILE_DELETE, \r
+                   reEncryption);\r
+            }\r
+\r
+            // Note : If a crash occurs at this point, then on reboot \r
+            // it will again be in the DB_ENRYPTION_IN__UNDO state, \r
+            // there will not be a file after the checkpoint log file, \r
+            // so no file will be deleted. \r
+\r
+            // check if this is a external key encryption and \r
+            // if it replace the current verify key file with \r
+            // the old copy. \r
+\r
+            StorageFile verifyKeyFile = \r
+                storageFactory.newStorageFile(\r
+                                 Attribute.CRYPTO_EXTERNAL_KEY_VERIFY_FILE);\r
+            \r
+            if (privExists(verifyKeyFile))\r
+            {\r
+                StorageFile oldVerifyKeyFile = \r
+                    storageFactory.newStorageFile(\r
+                      RawStoreFactory.CRYPTO_OLD_EXTERNAL_KEY_VERIFY_FILE);\r
+            \r
+                if (privExists(oldVerifyKeyFile)) \r
+                {\r
+                    if(!privCopyFile(oldVerifyKeyFile, verifyKeyFile))\r
+                        throw StandardException.\r
+                            newException(SQLState.RAWSTORE_ERROR_COPYING_FILE,\r
+                                         oldVerifyKeyFile, verifyKeyFile);  \r
+                    \r
+                    // only incase of re-encryption there should\r
+                    // be old verify key file. \r
+                    reEncryption = true;\r
+                }else \r
+                {\r
+                    // remove the verify key file. \r
+                    if (!privDelete(verifyKeyFile))\r
+                        throw StandardException.newException(\r
+                             SQLState.UNABLE_TO_DELETE_FILE, \r
+                             verifyKeyFile);\r
+                }\r
+\r
+            } else \r
+            {\r
+                // database enrypted with boot password. \r
+                \r
+                // replace the current encryption key with the old key\r
+                // in the service.properties file. \r
+                // retreive the old encryption key \r
+\r
+                String OldKeyString = \r
+                    properties.getProperty(RawStoreFactory.OLD_ENCRYPTED_KEY);\r
+\r
+                if (OldKeyString != null) {\r
+                    // set the current encrypted key to the old one. \r
+                    properties.put(RawStoreFactory.ENCRYPTED_KEY,\r
+                                   OldKeyString);\r
+                    \r
+                    // only incase of re-encryption there should\r
+                    // be old encryted key . \r
+                    reEncryption = true;\r
+                }\r
+            }\r
+\r
+            if (!reEncryption) {\r
+                // crash occured when database was getting reconfigured \r
+                // for encryption , all encryption properties should be \r
+                // removed from service.properties\r
+                \r
+                // common props for external key or password.\r
+                properties.remove(Attribute.DATA_ENCRYPTION);\r
+                properties.remove(RawStoreFactory.LOG_ENCRYPT_ALGORITHM_VERSION);\r
+                properties.remove(RawStoreFactory.DATA_ENCRYPT_ALGORITHM_VERSION);\r
+                properties.remove(RawStoreFactory.ENCRYPTION_BLOCKSIZE);\r
+\r
+                // properties specific to password based encryption.\r
+                properties.remove(Attribute.CRYPTO_KEY_LENGTH);\r
+                properties.remove(Attribute.CRYPTO_PROVIDER);\r
+                properties.remove(Attribute.CRYPTO_ALGORITHM);\r
+                properties.remove(RawStoreFactory.ENCRYPTED_KEY);\r
+\r
+            }\r
+\r
+            if (SanityManager.DEBUG) {\r
+                crashOnDebugFlag(\r
+                    TEST_REENCRYPT_CRASH_AFTER_RECOVERY_UNDO_REVERTING_KEY, \r
+                    reEncryption);\r
+            }\r
+\r
+        } // end of UNDO\r
+\r
+\r
+        if (dbEncryptionStatus == RawStoreFactory.DB_ENCRYPTION_IN_CLEANUP)\r
+        {\r
+            // remove all the old versions of the  containers. \r
+            dataFactory.removeOldVersionOfContainers(true);\r
+        }\r
+        \r
+        if (SanityManager.DEBUG) {\r
+                crashOnDebugFlag(\r
+                   TEST_REENCRYPT_CRASH_BEFORE_RECOVERY_FINAL_CLEANUP, \r
+                   reEncryption);\r
+        }\r
+\r
+        // either the (re) encryption was complete , \r
+        // or undone (except for rollback that needs to be \r
+        // done by the recovery). Remove re-encryption specific\r
+        // flags from the service.properties and old copy \r
+        // of the verify key file.\r
+        \r
+        // delete the old verify key file , if it exists. \r
+        StorageFile oldVerifyKeyFile = \r
+            storageFactory.newStorageFile(\r
+                      RawStoreFactory.CRYPTO_OLD_EXTERNAL_KEY_VERIFY_FILE);\r
+        if (privExists(oldVerifyKeyFile)) \r
+        {\r
+            if (!privDelete(oldVerifyKeyFile))\r
+                throw StandardException.newException(\r
+                        SQLState.UNABLE_TO_DELETE_FILE, \r
+                        oldVerifyKeyFile);\r
+        } else \r
+        {\r
+            // remove the old encryption key property.\r
+            properties.remove(RawStoreFactory.OLD_ENCRYPTED_KEY);\r
+        }\r
+\r
+        // remove the re-encryptin status flag. \r
+        properties.remove(RawStoreFactory.DB_ENCRYPTION_STATUS);\r
+    }\r
+\r
+\r
+\r
+\r
+    /**\r
+     * checks if the database is in the right state to (re)encrypt it.\r
+     *\r
+     * @param  reEncrypt true if the database getting encrypted \r
+     *                   with new password/key.\r
+     * @exception  StandardException  \r
+     *             if there is global transaction in the prepared state or\r
+     *             if the database is not at the version 10.2 or above, this\r
+     *             feature is not supported or  \r
+     *             if the log is archived for the database.\r
+     */\r
+    private void canEncryptDatabase(boolean reEncrypt) \r
+        throws StandardException \r
+    {\r
+\r
+        String feature = (reEncrypt ? \r
+                          "newBootPassword/newEncryptionKey attribute" : \r
+                          "dataEncryption attribute on an existing database");\r
+\r
+        // check if the database version is at 10.2 or above.\r
+        // encrytpion or re-encryption of the database \r
+        // is supported  only in version 10.2 or above. \r
+               logFactory.checkVersion(\r
+                       RawStoreFactory.DERBY_STORE_MAJOR_VERSION_10, \r
+                       RawStoreFactory.DERBY_STORE_MINOR_VERSION_2, \r
+                       feature);\r
+\r
+        // database can not be (re)encrypted if there \r
+        // are any global transactions in the prepared state \r
+        // after the recovery. The reason for this restriction \r
+        // is that any transaction log before the encryption can not \r
+        // be read once database is reconfigure with new encryption \r
+        // key.\r
+        if (xactFactory.hasPreparedXact()) {\r
+            if(reEncrypt) \r
+                throw StandardException.newException(\r
+                       SQLState.REENCRYPTION_PREPARED_XACT_EXIST);\r
+            else \r
+                throw StandardException.newException(\r
+                       SQLState.ENCRYPTION_PREPARED_XACT_EXIST);\r
+        }\r
+\r
+\r
+        // check if the database has the log archived. \r
+        // database can not be congured of encryption or\r
+        // or re-encrypt it with a new key when the database \r
+        // log is being archived. The reason for this restriction is \r
+        // it will create a scenarion where users will \r
+        // have some logs encrypted with new key and some with old key \r
+        // when rollforward recovery is performed. \r
+    \r
+        if (logFactory.logArchived()) \r
+        {\r
+            if(reEncrypt) \r
+                throw StandardException.newException(\r
+                       SQLState.CANNOT_REENCRYPT_LOG_ARCHIVED_DATABASE);\r
+            else \r
+                throw StandardException.newException(\r
+                       SQLState.CANNOT_ENCRYPT_LOG_ARCHIVED_DATABASE);\r
+            \r
+        }\r
+    }\r
+\r
+\r
+       /*\r
+       **\r
+       */\r
+\r
+       public StandardException markCorrupt(StandardException originalError) {\r
+\r
+               logFactory.markCorrupt(originalError);\r
+               dataFactory.markCorrupt(originalError);\r
+               xactFactory.markCorrupt(originalError);\r
+\r
+               return originalError;\r
+       }\r
+\r
+       /*\r
+        * class specific methods\r
+        */\r
+\r
+       /* subclass can override this method to load different submodules */\r
+       public String getTransactionFactoryModule()\r
+       {\r
+               return TransactionFactory.MODULE;\r
+       }\r
+\r
+       public String getDataFactoryModule()\r
+       {\r
+               return DataFactory.MODULE;\r
+       }\r
+\r
+       public String getLogFactoryModule()\r
+       {\r
+               return LogFactory.MODULE;\r
+       }\r
+\r
+\r
+       private void logHistory(OutputStreamWriter historyFile, String msg) throws IOException\r
+       {\r
+               Date d = new Date();\r
+               historyFile.write(d.toString() + ":" + msg + "\n");\r
+               historyFile.flush();\r
+       }\r
+\r
+    /*\r
+     * Get the file path. If the canonical path can be obtained then return the \r
+     * canonical path, otherwise just return the abstract path. Typically if\r
+     * there are no permission to read user.dir when  running under security\r
+     * manager canonical path can not be obtained.\r
+     *\r
+     * This method is used to a write path name to error/status log file, where it\r
+     * would be nice to print full paths but not esstential that the user \r
+     * grant permissions to read user.dir property.\r
+     */\r
+    private String getFilePath(StorageFile file) {\r
+        String path = privGetCanonicalPath(file);\r
+        if(path != null ) {\r
+            return path;\r
+        }else {\r
+            //can not get the canoncal path, \r
+            // return the abstract path\r
+            return file.getPath();\r
+        }\r
+    }\r
+\r
+    /*\r
+     * Get the file path.  If the canonical path can be obtained then return the \r
+     * canonical path, otherwise just return the abstract path. Typically if\r
+     * there are no permission to read user.dir when  running under security\r
+     * manager canonical path can not be obtained.\r
+     *\r
+     * This method is used to a write a file path name to error/status log file, \r
+     * where it would be nice to print full paths but not esstential that the user\r
+     * grant permissions to read user.dir property.\r
+     *\r
+     */\r
+    private String getFilePath(File file) {\r
+        String path = privGetCanonicalPath(file);\r
+        if(path != null ) {\r
+            return path;\r
+        }else {\r
+            // can not get the canoncal path, \r
+            // return the abstract path\r
+            return file.getPath();\r
+        }\r
+    }\r
+\r
+       protected boolean privCopyDirectory(StorageFile from, File to)\r
+       {\r
+               return privCopyDirectory(from, to, (byte[])null, \r
+                                 (String[])null, true);\r
+       }\r
+\r
+       protected boolean privCopyDirectory(File from, StorageFile to)\r
+       {\r
+               return privCopyDirectory(from, to, (byte[])null, (String[])null);\r
+       }\r
+\r
+    /**\r
+     * Return an id which can be used to create a container.\r
+     * <p>\r
+     * Return an id number with is greater than any existing container\r
+     * in the current database.  Caller will use this to allocate future\r
+     * container numbers - most likely caching the value and then incrementing\r
+     * it as it is used.\r
+     * <p>\r
+     *\r
+        * @return The an id which can be used to create a container.\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     **/\r
+    public long getMaxContainerId()\r
+               throws StandardException\r
+    {\r
+        return(dataFactory.getMaxContainerId());\r
+    }\r
+\r
+    /**\r
+     *  Check to see if a database has been upgraded to the required\r
+     *  level in order to use a store feature.\r
+     *\r
+     * @param requiredMajorVersion  required database Engine major version\r
+     * @param requiredMinorVersion  required database Engine minor version\r
+     * @param feature               Non-null to throw an exception, null to \r
+     *                              return the state of the version match.\r
+     *\r
+     * @return <code> true </code> if the database has been upgraded to \r
+     *         the required level, <code> false </code> otherwise.\r
+     *\r
+     * @exception  StandardException \r
+     *             if the database is not at the require version \r
+     *             when <code>feature</code> feature is \r
+     *             not <code> null </code>. \r
+     */\r
+       public boolean checkVersion(\r
+    int     requiredMajorVersion, \r
+    int     requiredMinorVersion, \r
+    String  feature) \r
+        throws StandardException\r
+    {\r
+        return(\r
+            logFactory.checkVersion(\r
+                requiredMajorVersion, requiredMinorVersion, feature));\r
+    }\r
+\r
+       \r
+    /*\r
+        These methods require Priv Blocks when run under a security manager.\r
+    */\r
+\r
+       private synchronized OutputStreamWriter privFileWriter( StorageFile fileName, boolean append) throws IOException\r
+       {\r
+        actionCode = FILE_WRITER_ACTION;\r
+        actionStorageFile = fileName;\r
+        actionAppend = append;\r
+               try{\r
+                       return (OutputStreamWriter) java.security.AccessController.doPrivileged( this);\r
+               }catch (java.security.PrivilegedActionException pae)\r
+        {\r
+            throw (IOException) pae.getException();\r
+        }\r
+        finally\r
+        {\r
+            actionStorageFile = null;\r
+        }\r
+       }\r
+\r
+       private synchronized boolean privExists( File file)\r
+    {\r
+        actionCode = REGULAR_FILE_EXISTS_ACTION;\r
+        actionRegularFile = file;\r
+\r
+        try\r
+        {\r
+            Object ret = AccessController.doPrivileged( this);\r
+            return ((Boolean) ret).booleanValue();\r
+        }\r
+        catch( PrivilegedActionException pae) { return false;} // does not throw an exception\r
+        finally\r
+        {\r
+            actionRegularFile = null;\r
+        }\r
+    }\r
+\r
+       private synchronized boolean privExists(final StorageFile file)\r
+    {\r
+        actionCode = STORAGE_FILE_EXISTS_ACTION;\r
+        actionStorageFile = file;\r
+\r
+        try\r
+        {\r
+            Object ret = AccessController.doPrivileged( this);\r
+            return ((Boolean) ret).booleanValue();\r
+        }\r
+        catch( PrivilegedActionException pae) { return false;} // does not throw an exception\r
+        finally\r
+        {\r
+            actionStorageFile = null;\r
+        }\r
+    }\r
+\r
+\r
+    private synchronized boolean privDelete( File file)\r
+    {\r
+        actionCode = REGULAR_FILE_DELETE_ACTION;\r
+        actionRegularFile = file;\r
+\r
+        try\r
+        {\r
+            Object ret = AccessController.doPrivileged( this);\r
+            return ((Boolean) ret).booleanValue();\r
+        }\r
+        catch( PrivilegedActionException pae) { return false;} // does not throw an exception\r
+        finally\r
+        {\r
+            actionRegularFile = null;\r
+        }\r
+    }\r
+\r
+    private synchronized boolean privDelete(StorageFile file)\r
+    {\r
+        actionCode = STORAGE_FILE_DELETE_ACTION;\r
+        actionStorageFile = file;\r
+\r
+        try\r
+        {\r
+            Object ret = AccessController.doPrivileged( this);\r
+            return ((Boolean) ret).booleanValue();\r
+        }\r
+        catch( PrivilegedActionException pae) { return false;} // does not throw an exception\r
+        finally\r
+        {\r
+            actionStorageFile = null;\r
+        }\r
+    }\r
+\r
+\r
+\r
+    private synchronized boolean privMkdirs( File file)\r
+    {\r
+        actionCode = REGULAR_FILE_MKDIRS_ACTION;\r
+        actionRegularFile = file;\r
+\r
+        try\r
+        {\r
+            Object ret = AccessController.doPrivileged( this);\r
+            return ((Boolean) ret).booleanValue();\r
+        }\r
+        catch( PrivilegedActionException pae) { return false;} // does not throw an exception\r
+        finally\r
+        {\r
+            actionRegularFile = null;\r
+        }\r
+    }\r
+\r
+\r
+    private synchronized boolean privIsDirectory( File file)\r
+    {\r
+        actionCode = REGULAR_FILE_IS_DIRECTORY_ACTION;\r
+        actionRegularFile = file;\r
+\r
+        try\r
+        {\r
+            Object ret = AccessController.doPrivileged( this);\r
+            return ((Boolean) ret).booleanValue();\r
+        }\r
+        catch( PrivilegedActionException pae) { return false;} // does not throw an exception\r
+        finally\r
+        {\r
+            actionRegularFile = null;\r
+        }\r
+    }\r
+\r
+    private synchronized boolean privRemoveDirectory( File file)\r
+    {\r
+        actionCode = REGULAR_FILE_REMOVE_DIRECTORY_ACTION;\r
+        actionRegularFile = file;\r
+\r
+        try\r
+        {\r
+            Object ret = AccessController.doPrivileged( this);\r
+            return ((Boolean) ret).booleanValue();\r
+        }\r
+        catch( PrivilegedActionException pae) { return false;} // does not throw an exception\r
+        finally\r
+        {\r
+            actionRegularFile = null;\r
+        }\r
+    }\r
+\r
+    private synchronized boolean privRenameTo( File file1, File file2)\r
+    {\r
+        actionCode = REGULAR_FILE_RENAME_TO_ACTION;\r
+        actionRegularFile = file1;\r
+        actionRegularFile2 = file2;\r
+\r
+        try\r
+        {\r
+            Object ret = AccessController.doPrivileged( this);\r
+            return ((Boolean) ret).booleanValue();\r
+        }\r
+        catch( PrivilegedActionException pae) { return false;} // does not throw an exception\r
+        finally\r
+        {\r
+            actionRegularFile = null;\r
+            actionRegularFile2 = null;\r
+        }\r
+    }\r
+\r
+    private synchronized boolean privCopyDirectory(StorageFile from, \r
+                                                   File to, \r
+                                                   byte[] buffer, \r
+                                                   String[] filter,\r
+                                                   boolean copySubdirs)\r
+    {\r
+        actionCode = COPY_STORAGE_DIRECTORY_TO_REGULAR_ACTION;\r
+        actionStorageFile = from;\r
+        actionRegularFile = to;\r
+        actionBuffer = buffer;\r
+        actionFilter = filter;\r
+        actionCopySubDirs = copySubdirs;\r
+\r
+        try\r
+        {\r
+            Object ret = AccessController.doPrivileged( this);\r
+            return ((Boolean) ret).booleanValue();\r
+        }\r
+        catch( PrivilegedActionException pae) { return false;} // does not throw an exception\r
+        finally\r
+        {\r
+            actionStorageFile = null;\r
+            actionRegularFile = null;\r
+            actionBuffer = null;\r
+            actionFilter = null;\r
+        }\r
+    }\r
+\r
+\r
+    private synchronized boolean privCopyDirectory( File from, StorageFile to, byte[] buffer, String[] filter)\r
+    {\r
+        actionCode = COPY_REGULAR_DIRECTORY_TO_STORAGE_ACTION;\r
+        actionStorageFile = to;\r
+        actionRegularFile = from;\r
+        actionBuffer = buffer;\r
+        actionFilter = filter;\r
+\r
+        try\r
+        {\r
+            Object ret = AccessController.doPrivileged( this);\r
+            return ((Boolean) ret).booleanValue();\r
+        }\r
+        catch( PrivilegedActionException pae) { return false;} // does not throw an exception\r
+        finally\r
+        {\r
+            actionStorageFile = null;\r
+            actionRegularFile = null;\r
+            actionBuffer = null;\r
+            actionFilter = null;\r
+        }\r
+    }\r
+\r
+       \r
+    private synchronized boolean privCopyFile( File from, StorageFile to)\r
+    {\r
+        actionCode = COPY_REGULAR_FILE_TO_STORAGE_ACTION;\r
+        actionStorageFile = to;\r
+        actionRegularFile = from;\r
+\r
+        try\r
+        {\r
+            Object ret = AccessController.doPrivileged( this);\r
+            return ((Boolean) ret).booleanValue();\r
+        }\r
+        catch( PrivilegedActionException pae) { return false;} // does not throw an exception\r
+        finally\r
+        {\r
+            actionStorageFile = null;\r
+            actionRegularFile = null;\r
+        }\r
+    }\r
+\r
+    private synchronized boolean privCopyFile( StorageFile from, File to)\r
+    {\r
+        actionCode = COPY_STORAGE_FILE_TO_REGULAR_ACTION;\r
+        actionStorageFile = from;\r
+        actionRegularFile = to;\r
+\r
+        try\r
+        {\r
+            Object ret = AccessController.doPrivileged( this);\r
+            return ((Boolean) ret).booleanValue();\r
+        }\r
+        catch( PrivilegedActionException pae) { return false;} // does not throw an exception\r
+        finally\r
+        {\r
+            actionStorageFile = null;\r
+            actionRegularFile = null;\r
+        }\r
+    }\r
+\r
+\r
+    \r
+    private synchronized boolean privCopyFile( StorageFile from, StorageFile to)\r
+    {\r
+        actionCode = COPY_STORAGE_FILE_TO_STORAGE_ACTION;\r
+        actionStorageFile = from;\r
+        actionToStorageFile = to;\r
+\r
+        try\r
+        {\r
+            Object ret = AccessController.doPrivileged( this);\r
+            return ((Boolean) ret).booleanValue();\r
+        }\r
+        catch( PrivilegedActionException pae) { return false;} // does not throw an exception\r
+        finally\r
+        {\r
+            actionStorageFile = null;\r
+            actionToStorageFile = null;\r
+        }\r
+    }\r
+\r
+\r
+    private synchronized String[] privList(final File file)\r
+    {\r
+        actionCode = REGULAR_FILE_LIST_DIRECTORY_ACTION;\r
+        actionRegularFile = file;\r
+\r
+        try\r
+        {\r
+            return (String[]) AccessController.doPrivileged( this);\r
+        }\r
+        catch( PrivilegedActionException pae) { return null;} // does not throw an exception\r
+        finally\r
+        {\r
+            actionRegularFile = null;\r
+        }\r
+    }\r
+\r
+    private synchronized String[] privList(final StorageFile file)\r
+    {\r
+        actionCode = STORAGE_FILE_LIST_DIRECTORY_ACTION;\r
+        actionStorageFile = file;\r
+\r
+        try\r
+        {\r
+            return (String[]) AccessController.doPrivileged( this);\r
+        }\r
+        catch( PrivilegedActionException pae) { return null;} // does not throw an exception\r
+        finally\r
+        {\r
+            actionStorageFile = null;\r
+        }\r
+    }\r
+\r
+\r
+    private synchronized String privGetCanonicalPath(final StorageFile file)\r
+    {\r
+        actionCode = STORAGE_FILE_GET_CANONICALPATH_ACTION;\r
+        actionStorageFile = file;\r
+\r
+        try\r
+        {\r
+            return (String) AccessController.doPrivileged( this);\r
+        }\r
+        catch( PrivilegedActionException pae) { \r
+            return null;\r
+        } // does not throw an exception\r
+        catch(SecurityException se) {\r
+            // there are no permission to get canonical path \r
+            // just return null.\r
+            return null;\r
+        }\r
+        finally\r
+        {\r
+            actionStorageFile = null;\r
+        }\r
+    }\r
+\r
+\r
+    private synchronized String privGetCanonicalPath(final File file)\r
+    {\r
+        actionCode = REGULAR_FILE_GET_CANONICALPATH_ACTION;\r
+        actionRegularFile = file;\r
+\r
+        try\r
+        {\r
+            return (String) AccessController.doPrivileged( this);\r
+        }\r
+        catch( PrivilegedActionException pae) { \r
+            return null;\r
+        } // does not throw an exception\r
+        catch(SecurityException se) { \r
+            // there are no permission to get canonical path \r
+            // just return null.\r
+            return null;\r
+        }\r
+        finally\r
+        {\r
+            actionRegularFile = null;\r
+        }\r
+    }\r
+\r
+\r
+    // PrivilegedExceptionAction method\r
+    public final Object run() throws IOException\r
+    {\r
+        switch(actionCode)\r
+        {\r
+        case FILE_WRITER_ACTION:\r
+            // SECURITY PERMISSION - MP1\r
+            return new OutputStreamWriter( actionStorageFile.getOutputStream( actionAppend));\r
+\r
+        case REGULAR_FILE_EXISTS_ACTION:\r
+            return ReuseFactory.getBoolean(actionRegularFile.exists());\r
+\r
+        case STORAGE_FILE_EXISTS_ACTION:\r
+            return ReuseFactory.getBoolean(actionStorageFile.exists());\r
+\r
+        case REGULAR_FILE_DELETE_ACTION:\r
+            return ReuseFactory.getBoolean(actionRegularFile.delete());\r
+\r
+        case STORAGE_FILE_DELETE_ACTION:\r
+            return ReuseFactory.getBoolean(actionStorageFile.delete());\r
+\r
+        case REGULAR_FILE_MKDIRS_ACTION:\r
+            // SECURITY PERMISSION - OP4\r
+            return ReuseFactory.getBoolean(actionRegularFile.mkdirs());\r
+\r
+        case REGULAR_FILE_IS_DIRECTORY_ACTION:\r
+            // SECURITY PERMISSION - MP1\r
+            return ReuseFactory.getBoolean(actionRegularFile.isDirectory());\r
+\r
+        case REGULAR_FILE_REMOVE_DIRECTORY_ACTION:\r
+            // SECURITY PERMISSION - MP1, OP5\r
+            return ReuseFactory.getBoolean(FileUtil.removeDirectory(actionRegularFile));\r
+\r
+        case REGULAR_FILE_RENAME_TO_ACTION:\r
+            // SECURITY PERMISSION - OP4\r
+            return ReuseFactory.getBoolean(actionRegularFile.renameTo(actionRegularFile2));\r
+\r
+        case COPY_STORAGE_DIRECTORY_TO_REGULAR_ACTION:\r
+            // SECURITY PERMISSION - MP1, OP4\r
+            return ReuseFactory.getBoolean(FileUtil.copyDirectory(storageFactory,\r
+                                                                  actionStorageFile,\r
+                                                                  actionRegularFile,\r
+                                                                  actionBuffer,\r
+                                                                  actionFilter,\r
+                                                                  actionCopySubDirs));\r
+\r
+        case COPY_REGULAR_DIRECTORY_TO_STORAGE_ACTION:\r
+            // SECURITY PERMISSION - MP1, OP4\r
+            return ReuseFactory.getBoolean(FileUtil.copyDirectory((WritableStorageFactory)storageFactory,\r
+                                                                  actionRegularFile,\r
+                                                                  actionStorageFile,\r
+                                                                  actionBuffer,\r
+                                                                  actionFilter));\r
+\r
+        case COPY_REGULAR_FILE_TO_STORAGE_ACTION:\r
+            // SECURITY PERMISSION - MP1, OP4\r
+            return ReuseFactory.getBoolean(FileUtil.copyFile((WritableStorageFactory) storageFactory,\r
+                                                             actionRegularFile,\r
+                                                             actionStorageFile));\r
+\r
+        case REGULAR_FILE_LIST_DIRECTORY_ACTION:\r
+            // SECURITY PERMISSION - MP1\r
+            return (String[])(actionRegularFile.list());\r
+\r
+        case STORAGE_FILE_LIST_DIRECTORY_ACTION:\r
+            // SECURITY PERMISSION - MP1\r
+            return (String[])(actionStorageFile.list());\r
+\r
+        case COPY_STORAGE_FILE_TO_REGULAR_ACTION:\r
+            // SECURITY PERMISSION - MP1, OP4\r
+            return ReuseFactory.getBoolean(FileUtil.copyFile(\r
+                                           (WritableStorageFactory) storageFactory,\r
+                                           actionStorageFile,\r
+                                           actionRegularFile));\r
+\r
+            \r
+        case COPY_STORAGE_FILE_TO_STORAGE_ACTION:\r
+            // SECURITY PERMISSION - MP1, OP4\r
+            return ReuseFactory.getBoolean(FileUtil.copyFile(\r
+                                           (WritableStorageFactory) storageFactory,\r
+                                           actionStorageFile,\r
+                                           actionToStorageFile));\r
+\r
+        case REGULAR_FILE_GET_CANONICALPATH_ACTION:\r
+            // SECURITY PERMISSION - MP1\r
+            return (String)(actionRegularFile.getCanonicalPath());\r
+            \r
+        case STORAGE_FILE_GET_CANONICALPATH_ACTION:\r
+            // SECURITY PERMISSION - MP1\r
+            return (String)(actionStorageFile.getCanonicalPath());\r
+        }\r
+        return null;\r
+    } // end of run\r
+}\r