You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by ka...@apache.org on 2014/03/24 10:13:14 UTC

svn commit: r1580789 - in /db/derby/code/trunk: ./ java/drda/org/apache/derby/impl/drda/ java/engine/org/apache/derby/iapi/services/io/ java/engine/org/apache/derby/impl/io/ java/engine/org/apache/derby/impl/services/monitor/ java/engine/org/apache/der...

Author: kahatlen
Date: Mon Mar 24 09:13:13 2014
New Revision: 1580789

URL: http://svn.apache.org/r1580789
Log:
DERBY-6503: ClassCastException when network server cannot restrict file permissions

Make sure the underlying IOException is exposed if the network server
fails to restrict file permissions. The original exception used to be
shadowed by a ClassCastException.

Added:
    db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/FilePermissionService.java   (with props)
    db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/FilePermissionServiceImpl.java   (with props)
Modified:
    db/derby/code/trunk/build.xml
    db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DssTrace.java
    db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/FileUtil.java
    db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/build.xml
    db/derby/code/trunk/java/engine/org/apache/derby/impl/io/DirFile.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/services/monitor/FileMonitor.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/RawStore.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/RAFContainer.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/StreamFileContainer.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/log/LogToFile.java
    db/derby/code/trunk/java/engine/org/apache/derby/io/StorageFile.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/util/corruptio/CorruptFile.java
    db/derby/code/trunk/tools/jar/extraDBMSclasses.properties

Modified: db/derby/code/trunk/build.xml
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/build.xml?rev=1580789&r1=1580788&r2=1580789&view=diff
==============================================================================
--- db/derby/code/trunk/build.xml (original)
+++ db/derby/code/trunk/build.xml Mon Mar 24 09:13:13 2014
@@ -176,6 +176,7 @@
     <!-- The java.lang.ManagementFactory class was new in J2SE 5.0 -->
     <available classname="java.lang.management.ManagementFactory" property="vmLevelIsAtLeast1.5"/>
     <available classname="java.sql.Wrapper" property="vmLevelIsAtLeast1.6" value="true"/>
+    <available classname="java.sql.PseudoColumnUsage" property="vmLevelIsAtLeast1.7"/>
     <available classname="java.sql.SQLType" property="vmLevelIsAtLeast1.8" value="true"/>
   </target>
 
@@ -1370,7 +1371,7 @@
 
 <!-- - - - - - - - - - - - - - - derby.jar target - - - - - - - - - - - -->
 
-  <target name="derbyjar" depends="initjars">
+  <target name="derbyjar" depends="checkVMLevel,initjars">
 
     <echo level="info" message="Beginning derby.jar ${sanity.name} build"/>
 
@@ -1378,9 +1379,18 @@
     <delete>
       <fileset dir="${derby.jar.dir}/lists" includes="**/*"/>
     </delete>
-         
+
+    <!-- Classes that will only be compiled with JDK 7 and higher are
+         commented out. Determine here whether they should be included. -->
+    <condition property="derbyjar.jdk7.prefix" value="" else="#">
+        <isset property="vmLevelIsAtLeast1.7"/>
+    </condition>
+
     <concat destfile="${derby.jar.dir}/lists/otherDerbyClasses.properties">
       <fileset dir="${basedir}/tools/jar" includes="*DBMS*.properties"/>
+      <filterchain>
+          <replacestring from="#jdk7#" to="${derbyjar.jdk7.prefix}"/>
+      </filterchain>
     </concat>
 
     <mkdir dir="${derby.jar.dir}/lists/org/apache/derby"/>

Modified: db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DssTrace.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DssTrace.java?rev=1580789&r1=1580788&r2=1580789&view=diff
==============================================================================
--- db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DssTrace.java (original)
+++ db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DssTrace.java Mon Mar 24 09:13:13 2014
@@ -25,7 +25,6 @@ import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.security.AccessController;
-import java.security.PrivilegedAction;
 import java.security.PrivilegedActionException;
 import java.security.PrivilegedExceptionAction;
 import org.apache.derby.iapi.services.io.FileUtil;
@@ -213,8 +212,8 @@ public class DssTrace
                         final File traceDirectory = new File(fileName).getParentFile();
                         if (traceDirectory != null) {
                             AccessController.doPrivileged(
-                                    new PrivilegedAction<Void>() {
-                                        public Void run() {
+                                    new PrivilegedExceptionAction<Void>() {
+                                        public Void run() throws IOException {
                                             // DERBY-4128: First try to create the
                                             // directory with mkdir(), as that doesn't
                                             // require read permission for the parent

Added: db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/FilePermissionService.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/FilePermissionService.java?rev=1580789&view=auto
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/FilePermissionService.java (added)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/FilePermissionService.java Mon Mar 24 09:13:13 2014
@@ -0,0 +1,47 @@
+/*
+
+   Derby - Class org.apache.derby.iapi.services.io.FilePermissionService
+
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to you under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+ */
+
+package org.apache.derby.iapi.services.io;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Interface for changing file permissions using the java.nio.file.attribute
+ * package that is available on Java 7 and higher. The purpose of this
+ * interface is to provide an indirection layer between the FileUtil class and
+ * the java.nio.file.attribute package so that FileUtil can be compiled for
+ * older platforms than Java 7.
+ */
+interface FilePermissionService {
+
+    /**
+     * Change the permissions of a file so that only the owner can access it.
+     *
+     * @param file the file whose permissions should be changed
+     * @return {@code true} if the permissions were successfully changed, or
+     * {@code false} if the implementation does not support changing
+     * permissions on this file system
+     * @throws IOException if an error happens when changing the permissions
+     */
+    boolean limitAccessToOwner(File file) throws IOException;
+
+}

Propchange: db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/FilePermissionService.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/FilePermissionServiceImpl.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/FilePermissionServiceImpl.java?rev=1580789&view=auto
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/FilePermissionServiceImpl.java (added)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/FilePermissionServiceImpl.java Mon Mar 24 09:13:13 2014
@@ -0,0 +1,77 @@
+/*
+
+   Derby - Class org.apache.derby.iapi.services.io.FilePermissionServiceImpl
+
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to you under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+ */
+
+package org.apache.derby.iapi.services.io;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.FileStore;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.attribute.AclEntry;
+import java.nio.file.attribute.AclEntryPermission;
+import java.nio.file.attribute.AclEntryType;
+import java.nio.file.attribute.AclFileAttributeView;
+import java.nio.file.attribute.PosixFileAttributeView;
+import java.util.Collections;
+
+/**
+ * Class that limits file permissions using an {@code AclFileAttributeView}.
+ * For use by {@link FileUtil#limitAccessToOwner(File)}.
+ */
+final class FilePermissionServiceImpl implements FilePermissionService {
+    public boolean limitAccessToOwner(File file) throws IOException {
+        Path fileP = file.toPath();
+        FileStore fileStore = Files.getFileStore(fileP);
+
+        // If we have a posix view, just return and fall back on
+        // the JDK 6 approach.
+        if (fileStore.supportsFileAttributeView(PosixFileAttributeView.class)) {
+            return false;
+        }
+
+        if (!fileStore.supportsFileAttributeView(AclFileAttributeView.class)) {
+            return false;
+        }
+
+        AclFileAttributeView aclView =
+                Files.getFileAttributeView(fileP, AclFileAttributeView.class);
+        if (aclView == null) {
+            return false;
+        }
+
+        // Since we have an AclFileAttributeView which is not a
+        // PosixFileAttributeView, we probably have an NTFS file
+        // system.
+
+        // Remove existing ACEs, build a new one which simply
+        // gives all possible permissions to current owner.
+        AclEntry ace = AclEntry.newBuilder()
+                .setPrincipal(Files.getOwner(fileP))
+                .setType(AclEntryType.ALLOW)
+                .setPermissions(AclEntryPermission.values())
+                .build();
+
+        aclView.setAcl(Collections.singletonList(ace));
+
+        return true;
+    }
+}

Propchange: db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/FilePermissionServiceImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/FileUtil.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/FileUtil.java?rev=1580789&r1=1580788&r2=1580789&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/FileUtil.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/FileUtil.java Mon Mar 24 09:13:13 2014
@@ -27,21 +27,12 @@ import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
-import java.lang.reflect.Array;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Field;
 import org.apache.derby.io.StorageFactory;
 import org.apache.derby.io.WritableStorageFactory;
 import org.apache.derby.io.StorageFile;
 
 import java.net.MalformedURLException;
 import java.net.URL;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
 import org.apache.derby.iapi.reference.Property;
 import org.apache.derby.iapi.services.info.JVMInfo;
 import org.apache.derby.iapi.services.property.PropertyUtil;
@@ -176,7 +167,11 @@ public abstract class FileUtil {
 			return false;
 		}			
 
-        limitAccessToOwner(to);
+        try {
+            limitAccessToOwner(to);
+        } catch (IOException ioe) {
+            return false;
+        }
 
 		String[] list = from.list();
 
@@ -308,7 +303,11 @@ public abstract class FileUtil {
 			return false;
 		}			
 
-        to.limitAccessToOwner();
+        try {
+            to.limitAccessToOwner();
+        } catch (IOException ioe) {
+            return false;
+        }
 
         String[] list = from.list();
 
@@ -463,39 +462,24 @@ public abstract class FileUtil {
 
 
     // Members used by limitAccessToOwner
-    private static final Object region = new Object();
-    private static boolean initialized = false;
+    private final static FilePermissionService filePermissionService =
+            loadFilePermissionService();
 
-    // Reflection helper objects for calling into Java >= 7
-    private static Class<?> filesClz;
-    private static Class<?> pathClz;
-    private static Class<?> pathsClz;
-    private static Class<?> aclEntryClz;
-    private static Class<?> aclFileAttributeViewClz;
-    private static Class<?> posixFileAttributeViewClz;
-    private static Class<?> userPrincipalClz;
-    private static Class<?> linkOptionArrayClz;
-    private static Class<?> linkOptionClz;
-    private static Class<?> stringArrayClz;
-    private static Class<?> aclEntryBuilderClz;
-    private static Class<?> aclEntryTypeClz;
-    private static Class<?> fileStoreClz;
-    private static Class<?> aclEntryPermissionClz;
-
-    private static Method get;
-    private static Method getFileAttributeView;
-    private static Method supportsFileAttributeView;
-    private static Method getFileStore;
-    private static Method getOwner;
-    private static Method setAcl;
-    private static Method build;
-    private static Method newBuilder;
-    private static Method setPrincipal;
-    private static Method setType;
-    private static Method values;
-    private static Method setPermissions;
-    
-    private static Field allow;
+    private static FilePermissionService loadFilePermissionService() {
+        try {
+            Class cl = Class.forName(
+                    FilePermissionService.class.getName() + "Impl");
+            return (FilePermissionService) cl.newInstance();
+        } catch (ClassNotFoundException ex) {
+        } catch (InstantiationException ex) {
+        } catch (IllegalAccessException ex) {
+        }
+
+        // Could not create an instance. This most likely means we are
+        // not on Java 7 or higher. Just return null, and let
+        // limitAccessToOwner() choose another strategy on older platforms.
+        return null;
+    }
 
     /**
      * Use when creating new files. If running on Unix,
@@ -515,8 +499,10 @@ public abstract class FileUtil {
      * java.nio.file.attribute} package.
      *
      * @param file assumed to be just created
+     * @throws IOException if an I/O error happens when trying to change the
+     *   file permissions
      */
-    public static void limitAccessToOwner(File file) {
+    public static void limitAccessToOwner(File file) throws IOException {
 
         String value = PropertyUtil.getSystemProperty(
             Property.STORAGE_USE_DEFAULT_FILE_PERMISSIONS);
@@ -538,84 +524,6 @@ public abstract class FileUtil {
             }
         }
 
-        // lazy initialization, needs to be called in security context
-        synchronized (region) {
-            if (!initialized) {
-                initialized = true;
-
-                // >= Java 7
-                try {
-                    // If found, we have >= Java 7.
-                    filesClz = Class.forName(
-                        "java.nio.file.Files");
-                    pathClz = Class.forName(
-                        "java.nio.file.Path");
-                    pathsClz = Class.forName(
-                        "java.nio.file.Paths");
-                    aclEntryClz = Class.forName(
-                        "java.nio.file.attribute.AclEntry");
-                    aclFileAttributeViewClz = Class.forName(
-                        "java.nio.file.attribute.AclFileAttributeView");
-                    posixFileAttributeViewClz = Class.forName(
-                        "java.nio.file.attribute.PosixFileAttributeView");
-                    userPrincipalClz = Class.forName(
-                        "java.nio.file.attribute.UserPrincipal");
-                    linkOptionArrayClz = Class.forName(
-                        "[Ljava.nio.file.LinkOption;");
-                    linkOptionClz = Class.forName(
-                        "java.nio.file.LinkOption");
-                    stringArrayClz = Class.forName(
-                        "[Ljava.lang.String;");
-                    aclEntryBuilderClz = Class.forName(
-                        "java.nio.file.attribute.AclEntry$Builder");
-                    aclEntryTypeClz = Class.forName(
-                        "java.nio.file.attribute.AclEntryType");
-                    fileStoreClz = Class.forName(
-                        "java.nio.file.FileStore");
-                    aclEntryPermissionClz = Class.forName(
-                            "java.nio.file.attribute.AclEntryPermission");
-                    get = pathsClz.getMethod(
-                        "get",
-                        new Class[]{String.class, stringArrayClz});
-                    getFileAttributeView = filesClz.getMethod(
-                        "getFileAttributeView",
-                        new Class[]{pathClz, Class.class, linkOptionArrayClz});
-                    supportsFileAttributeView = fileStoreClz.getMethod(
-                        "supportsFileAttributeView",
-                        new Class[]{Class.class});
-                    getFileStore = filesClz.getMethod("getFileStore",
-                                                      new Class[]{pathClz});
-                    getOwner = filesClz.
-                        getMethod("getOwner",
-                                  new Class[]{pathClz, linkOptionArrayClz});
-                    setAcl = aclFileAttributeViewClz.
-                        getMethod("setAcl", new Class[]{List.class});
-                    build = aclEntryBuilderClz.
-                        getMethod("build", new Class[]{});
-                    newBuilder = aclEntryClz.
-                        getMethod("newBuilder", new Class[]{});
-                    setPrincipal = aclEntryBuilderClz.
-                        getMethod("setPrincipal",
-                                  new Class[]{userPrincipalClz});
-                    setType = aclEntryBuilderClz.
-                        getMethod("setType", new Class[]{aclEntryTypeClz});
-                    values = aclEntryPermissionClz.
-                        getMethod("values", (Class[]) null);
-                    setPermissions = aclEntryBuilderClz.
-                        getMethod("setPermissions", new Class[] { Set.class });
-
-                    allow = aclEntryTypeClz.getField("ALLOW");
-
-                } catch (NoSuchMethodException e) {
-                    // not Java 7 or higher
-                } catch (ClassNotFoundException e) {
-                    // not Java 7 or higher
-                } catch (NoSuchFieldException e) {
-                    // not Java 7 or higher
-                }
-            }
-        }
-
         if (limitAccessToOwnerViaACLs(file)) {
             return;
         }
@@ -674,120 +582,18 @@ public abstract class FileUtil {
         }
     }
 
-    private static boolean limitAccessToOwnerViaACLs(File file) {
+    private static boolean limitAccessToOwnerViaACLs(File file)
+            throws IOException {
 
         // See if we are running on JDK 7 so we can deny access
         // using the new java.nio.file.attribute package.
 
-        if (filesClz == null) {
+        if (filePermissionService == null) {
             // nope
             return false;
         }
 
-        // We have Java 7, so call. We need to call reflectively, since the
-        // source level isn't yet at Java 7.
-        try {
-            // Path fileP = Paths.get(file.getPath());
-            Object fileP = get.invoke(
-                null, new Object[]{file.getPath(), new String[]{}});
-
-            // ACLs supported on this platform, now check the current file
-            // system:
-            Object fileStore = getFileStore.invoke(
-                null,
-                new Object[]{fileP});
-
-            boolean supported =
-                ((Boolean)supportsFileAttributeView.invoke(
-                    fileStore,
-                    new Object[]{aclFileAttributeViewClz})).booleanValue();
-
-            if (!supported) {
-                return false;
-            }
-
-
-            // AclFileAttributeView view =
-            //     Files.getFileAttributeView(fileP,
-            //         AclFileAttributeView.class);
-            Object view = getFileAttributeView.invoke(
-                null,
-                new Object[]{fileP,
-                             aclFileAttributeViewClz,
-                             Array.newInstance(linkOptionClz, 0)});
-
-            if (view == null) {
-                return false;
-            }
-
-
-            // If we have a posix view, just return and fall back on
-            // the JDK 6 approach.
-            Object posixView = getFileAttributeView.invoke(
-                null,
-                new Object[]{fileP,
-                             posixFileAttributeViewClz,
-                             Array.newInstance(linkOptionClz, 0)});
-
-            if (posixView != null) {
-                return false;
-            }
-
-            // Since we have an AclFileAttributeView which is not a
-            // PosixFileAttributeView, we probably have a NTFS file
-            // system.
-
-            // UserPrincipal owner = Files.getOwner(fileP);
-            Object owner = getOwner.invoke(
-                null,
-                new Object[]{fileP, Array.newInstance(linkOptionClz, 0)});
-
-            //
-            // Remove existing ACEs, build a new one which simply
-            // gives all possible permissions to current owner.
-            //
-            // List<AclEntry>        newAcl = new ArrayList<>();
-            // AclEntryPermissions[] perms = AclEntryPermission.values();
-            // AclEntry.Builder      aceb = AclEntry.newBuilder();
-            //
-            // aceb.setType(AclEntryType.ALLOW);
-            // aceb.setPermissions(new HashSet(Arrays.asList(perms);
-            // newAcl.add(aceb);
-
-            List<Object> newAcl = new ArrayList<Object>();
-            Object[] perms = (Object[]) values.invoke(null, (Object[]) null);
-            Object aceb = newBuilder.invoke(null, (Object[]) null);
-            Object allowValue = allow.get(aclEntryTypeClz);
-            aceb = setPrincipal.invoke(aceb, new Object[]{owner});
-            aceb = setType.invoke(aceb, new Object[]{allowValue});
-            aceb = setPermissions.invoke(
-                aceb,
-                new Object[] {new HashSet<Object>(Arrays.asList(perms))});
-            newAcl.add(build.invoke(aceb, (Object[]) null));
-
-            // view.setAcl(newAcl);
-            setAcl.invoke(view, new Object[]{newAcl});
-
-        } catch (IllegalAccessException e) {
-            // coding error
-            if (SanityManager.DEBUG) {
-                SanityManager.THROWASSERT(e);
-            }
-        } catch (IllegalArgumentException e) {
-            // coding error
-            if (SanityManager.DEBUG) {
-                SanityManager.THROWASSERT(e);
-            }
-        } catch (InvocationTargetException e) {
-            // java.security.AccessControlException: access denied
-            // ("java.lang.RuntimePermission" "accessUserInformation") can
-            // happen, so throw.
-            //
-            // Should we get an IOException from getOwner, the cast below
-            // would throw which is fine, since it should not happen.
-            throw (RuntimeException)e.getCause();
-        }
-
-        return true;
+        // We have Java 7, so call.
+        return filePermissionService.limitAccessToOwner(file);
     }
 }

Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/build.xml
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/build.xml?rev=1580789&r1=1580788&r2=1580789&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/build.xml (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/build.xml Mon Mar 24 09:13:13 2014
@@ -16,7 +16,7 @@
   limitations under the License.
 -->
 
-<project default="compile_iapi_services_io" basedir="../../../../../../../..">
+<project default="compile" basedir="../../../../../../../..">
 
 <!-- Set Properties -->
   <!-- User settings -->
@@ -37,6 +37,8 @@
 
 <!-- Targets -->
 
+  <target name="compile" depends="checkVMLevel,compile_iapi_services_io,compile_iapi_services_io_jdk7"/>
+
   <target name="compile_iapi_services_io">
     <javac
       source="1.6"
@@ -55,9 +57,35 @@
         <pathelement path="${java16compile.classpath}"/>
       </classpath>
       <include name="${derby.dir}/iapi/services/io/*.java"/>
+      <exclude name="${derby.dir}/iapi/services/io/FilePermissionServiceImpl.java"/>
       <!-- <compilerarg value="-Xlint:unchecked"/> -->
     </javac>
   </target>
 
+<target name="compile_iapi_services_io_jdk7" if="vmLevelIsAtLeast1.7">
+    <javac
+      source="1.7"
+      target="1.7"
+      bootclasspath="${empty}"
+      nowarn="on"
+      debug="${debug}"
+      depend="${depend}"
+      deprecation="${deprecation}"
+      optimize="${optimize}"
+      proceed="${proceed}"
+      verbose="${verbose}"
+      srcdir="${derby.engine.src.dir}"
+      destdir="${out.dir}">
+      <classpath>
+        <pathelement path="${java17compile.classpath}"/>
+      </classpath>
+      <include name="${derby.dir}/iapi/services/io/FilePermissionServiceImpl.java"/>
+      <compilerarg value="-Xlint:unchecked"/>
+    </javac>
+  </target>
+
+  <target name="checkVMLevel">
+    <available classname="java.sql.PseudoColumnUsage" property="vmLevelIsAtLeast1.7"/>
+  </target>
 </project>
 

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/io/DirFile.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/io/DirFile.java?rev=1580789&r1=1580788&r2=1580789&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/io/DirFile.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/io/DirFile.java Mon Mar 24 09:13:13 2014
@@ -111,14 +111,7 @@ class DirFile extends File implements St
      */
     public OutputStream getOutputStream( ) throws FileNotFoundException
     {
-        boolean exists = exists();
-        OutputStream result = new FileOutputStream(this);
-
-        if (!exists) {
-            FileUtil.limitAccessToOwner(this);
-        }
-
-        return result;
+        return getOutputStream(false);
     }
     
     /**
@@ -140,7 +133,19 @@ class DirFile extends File implements St
         OutputStream result = new FileOutputStream(this, append);
 
         if (!exists) {
-            FileUtil.limitAccessToOwner(this);
+            try {
+                limitAccessToOwner();
+            } catch (FileNotFoundException fnfe) {
+                // Throw FileNotFoundException unchanged.
+                throw fnfe;
+            } catch (IOException ioe) {
+                // Other IOExceptions should be wrapped, since
+                // FileNotFoundException is the only one we are allowed
+                // to throw here.
+                FileNotFoundException e = new FileNotFoundException();
+                e.initCause(ioe);
+                throw e;
+            }
         }
 
         return result;
@@ -441,7 +446,7 @@ class DirFile extends File implements St
 		return toURI().toURL();
 	}
 
-    public void limitAccessToOwner() {
+    public void limitAccessToOwner() throws IOException {
         FileUtil.limitAccessToOwner(this);
     }
 }

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/services/monitor/FileMonitor.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/services/monitor/FileMonitor.java?rev=1580789&r1=1580788&r2=1580789&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/services/monitor/FileMonitor.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/services/monitor/FileMonitor.java Mon Mar 24 09:13:13 2014
@@ -151,12 +151,13 @@ public final class FileMonitor extends B
                     // but avoids requiring read permission on the parent
                     // directory if it exists.
                     created = home.mkdir() || home.mkdirs();
+                    if (created) {
+                        FileUtil.limitAccessToOwner(home);
+                    }
 				} catch (SecurityException se) {
 					return false;
-				}
-
-                if (created) {
-                    FileUtil.limitAccessToOwner(home);
+                } catch (IOException ioe) {
+                    return false;
                 }
 			}
 		}

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/RawStore.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/RawStore.java?rev=1580789&r1=1580788&r2=1580789&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/RawStore.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/RawStore.java Mon Mar 24 09:13:13 2014
@@ -675,13 +675,7 @@ public final class RawStore implements R
         if (!privExists(backupDir))
 		{
             // if backup dir does not exist, go ahead and create it.
-
-            if (!privMkdirs(backupDir))
-            {
-                throw StandardException.newException(
-                    SQLState.RAWSTORE_CANNOT_CREATE_BACKUP_DIRECTORY,
-                    (File) backupDir);
-            }
+            createBackupDirectory(backupDir);
 		}
 		else
 		{
@@ -777,12 +771,7 @@ public final class RawStore implements R
 			}
 
             // create the backup database directory
-            if (!privMkdirs(backupcopy))
-            {
-                throw StandardException.newException(
-                    SQLState.RAWSTORE_CANNOT_CREATE_BACKUP_DIRECTORY,
-                    (File) backupcopy);
-            }
+            createBackupDirectory(backupcopy);
 
             dbHistoryFile = storageFactory.newStorageFile(BACKUP_HISTORY);
             backupHistoryFile = new File(backupcopy, BACKUP_HISTORY); 
@@ -813,12 +802,7 @@ public final class RawStore implements R
                 File backupJarDir = new File(backupcopy, 
                                              FileResource.JAR_DIRECTORY_NAME);
                 // Create the backup jar directory
-                if (!privMkdirs(backupJarDir))
-                {
-                    throw StandardException.newException(
-                          SQLState.RAWSTORE_CANNOT_CREATE_BACKUP_DIRECTORY,
-                          (File) backupJarDir);
-                }
+                createBackupDirectory(backupJarDir);
 
                 LanguageConnectionContext lcc = 
                     (LanguageConnectionContext)ContextService.getContextOrNull(
@@ -953,12 +937,7 @@ public final class RawStore implements R
 			}
 
 			// Create the log directory
-            if (!privMkdirs(logBackup))
-            {
-                throw StandardException.newException(
-                    SQLState.RAWSTORE_CANNOT_CREATE_BACKUP_DIRECTORY,
-                    (File) logBackup);
-            }
+            createBackupDirectory(logBackup);
 
 			// do a checkpoint to get the persistent store up to date.
 			logFactory.checkpoint(this, dataFactory, xactFactory, true);
@@ -969,12 +948,7 @@ public final class RawStore implements R
 			File segBackup = new File(backupcopy, "seg0");
 			
 			// Create the data segment directory
-            if (!privMkdirs(segBackup))
-            {
-                throw StandardException.newException(
-                    SQLState.RAWSTORE_CANNOT_CREATE_BACKUP_DIRECTORY,
-                    (File) segBackup);
-            }
+            createBackupDirectory(segBackup);
 
 			// backup all the information in the data segment.
 			dataFactory.backupDataFiles(t, segBackup);
@@ -1072,6 +1046,30 @@ public final class RawStore implements R
 	}
 
     /**
+     * Create a directory for backup.
+     *
+     * @param dir the directory to create
+     * @throws StandardException if the directory could not be created
+     */
+    private void createBackupDirectory(File dir) throws StandardException {
+        boolean created = false;
+        IOException ex = null;
+
+        try {
+            created = privMkdirs(dir);
+        } catch (IOException ioe) {
+            ex = ioe;
+        }
+
+        // If the directory wasn't created, report it. Also include the
+        // underlying IOException, if there was one.
+        if (!created) {
+            throw StandardException.newException(
+                    SQLState.RAWSTORE_CANNOT_CREATE_BACKUP_DIRECTORY, ex, dir);
+        }
+    }
+
+    /**
      * Backup the database to a backup directory and enable the log archive
 	 * mode that will keep the archived log files required for roll-forward
 	 * from this version backup.
@@ -2423,7 +2421,7 @@ public final class RawStore implements R
 
 
 
-    private synchronized boolean privMkdirs( File file)
+    private synchronized boolean privMkdirs(File file) throws IOException
     {
         actionCode = REGULAR_FILE_MKDIRS_ACTION;
         actionRegularFile = file;
@@ -2433,7 +2431,9 @@ public final class RawStore implements R
             Object ret = AccessController.doPrivileged( this);
             return ((Boolean) ret).booleanValue();
         }
-        catch( PrivilegedActionException pae) { return false;} // does not throw an exception
+        catch (PrivilegedActionException pae) {
+            throw (IOException) pae.getCause();
+        }
         finally
         {
             actionRegularFile = null;

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/RAFContainer.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/RAFContainer.java?rev=1580789&r1=1580788&r2=1580789&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/RAFContainer.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/RAFContainer.java Mon Mar 24 09:13:13 2014
@@ -785,7 +785,17 @@ class RAFContainer extends FileContainer
                             }
                         }
 
-                        directory.limitAccessToOwner();
+                        try {
+                            directory.limitAccessToOwner();
+                        } catch (IOException ioe) {
+                            if (errorOK) {
+                                return null;
+                            } else {
+                                throw StandardException.newException(
+                                        SQLState.FILE_CANNOT_CREATE_SEGMENT,
+                                        ioe, directory);
+                            }
+                        }
                     }
                 }
             }
@@ -1311,13 +1321,14 @@ class RAFContainer extends FileContainer
      * @return a RandomAccessFile
      * @throws FileNotFoundException if {@code file} cannot be opened in
      * read-write mode
+     * @throws IOException if some other I/O error happens
      */
     private RandomAccessFile getRandomAccessFile(final File file)
-            throws FileNotFoundException {
+            throws IOException {
         try {
             return AccessController.doPrivileged(
                 new PrivilegedExceptionAction<RandomAccessFile>() {
-                    public RandomAccessFile run() throws FileNotFoundException {
+                    public RandomAccessFile run() throws IOException {
                         boolean preExisting = file.exists();
                         RandomAccessFile raf = new RandomAccessFile(file, "rw");
                         if (!preExisting) {
@@ -1327,7 +1338,7 @@ class RAFContainer extends FileContainer
                     }
                 });
         } catch (PrivilegedActionException pae) {
-            throw (FileNotFoundException) pae.getCause();
+            throw (IOException) pae.getCause();
         }
     }
 
@@ -1702,10 +1713,10 @@ class RAFContainer extends FileContainer
 
                  return result;
              }
-             catch (FileNotFoundException fnfe)
+             catch (IOException ioe)
              {
                  throw StandardException.newException(
-                     SQLState.FILE_CREATE, fnfe, actionFile.getPath());
+                     SQLState.FILE_CREATE, ioe, actionFile.getPath());
              }
 		 } // end of case BACKUP_CONTAINER_ACTION
 

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/StreamFileContainer.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/StreamFileContainer.java?rev=1580789&r1=1580788&r2=1580789&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/StreamFileContainer.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/StreamFileContainer.java Mon Mar 24 09:13:13 2014
@@ -1042,14 +1042,22 @@ public class StreamFileContainer impleme
                     {
 						if (!privExists(directory)) 
                         {
-							if (!privMkdirs(directory)) 
+                            boolean created = false;
+                            IOException ex = null;
+                            try {
+                                created = privMkdirs(directory);
+                            } catch (IOException ioe) {
+                                ex = ioe;
+                            }
+
+                            if (!created)
                             {
 								if (errorOK)
 									return null;
 								else
 									throw StandardException.newException(
                                             SQLState.FILE_CANNOT_CREATE_SEGMENT,
-                                            directory);
+                                            ex, directory);
 							}
 						}
 					}
@@ -1084,6 +1092,7 @@ public class StreamFileContainer impleme
     }
 
     private synchronized boolean privMkdirs(StorageFile file)
+            throws IOException
     {
         actionCode = STORAGE_FILE_MKDIRS_ACTION;
         actionStorageFile = file;
@@ -1095,8 +1104,8 @@ public class StreamFileContainer impleme
         }catch( PrivilegedActionException pae) 
         {
             // method executed under this priveleged block 
-            // does not throw an exception
-            return false;
+            // could throw IOException
+            throw (IOException) pae.getCause();
         } 
         finally
         {
@@ -1167,7 +1176,7 @@ public class StreamFileContainer impleme
 
 
     // PrivilegedAction method
-    public Object run() throws FileNotFoundException
+    public Object run() throws IOException
     {
         switch(actionCode)
         {

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/log/LogToFile.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/log/LogToFile.java?rev=1580789&r1=1580788&r2=1580789&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/log/LogToFile.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/log/LogToFile.java Mon Mar 24 09:13:13 2014
@@ -23,14 +23,6 @@ package org.apache.derby.impl.store.raw.
 
 import org.apache.derby.iapi.services.diag.Performance;
 
-import org.apache.derby.impl.store.raw.log.CheckpointOperation;
-import org.apache.derby.impl.store.raw.log.LogCounter;
-import org.apache.derby.impl.store.raw.log.LogRecord;
-import org.apache.derby.impl.store.raw.log.StreamLogScan;
-
-// need this to print nested exception that corrupts the database
-
-import org.apache.derby.iapi.services.info.ProductGenusNames;
 import org.apache.derby.iapi.services.info.ProductVersionHolder;
 
 import org.apache.derby.iapi.reference.MessageId;
@@ -47,12 +39,7 @@ import org.apache.derby.iapi.services.mo
 import org.apache.derby.iapi.services.monitor.PersistentService;
 import org.apache.derby.shared.common.sanity.SanityManager;
 import org.apache.derby.iapi.services.io.Formatable;
-import org.apache.derby.iapi.services.io.TypedFormat;
-import org.apache.derby.iapi.services.io.FormatIdUtil;
 import org.apache.derby.iapi.services.io.StoredFormatIds;
-import org.apache.derby.iapi.services.stream.HeaderPrintWriter;
-import org.apache.derby.iapi.services.stream.PrintWriterGetHeader;
-import org.apache.derby.iapi.services.stream.InfoStreams;
 import org.apache.derby.iapi.error.ErrorStringBuilder;
 import org.apache.derby.iapi.error.ShutdownException;
 import org.apache.derby.iapi.error.StandardException;
@@ -67,7 +54,6 @@ import org.apache.derby.iapi.store.raw.l
 import org.apache.derby.iapi.store.raw.log.Logger;
 import org.apache.derby.iapi.store.raw.log.LogInstant;
 import org.apache.derby.iapi.store.raw.log.LogScan;
-import org.apache.derby.iapi.store.raw.Transaction;
 import org.apache.derby.iapi.store.raw.xact.RawTransaction;
 import org.apache.derby.iapi.store.raw.xact.TransactionFactory;
 import org.apache.derby.iapi.store.raw.data.DataFactory;
@@ -79,20 +65,16 @@ import org.apache.derby.iapi.store.repli
 import org.apache.derby.iapi.services.io.ArrayInputStream;
 
 import org.apache.derby.iapi.store.access.DatabaseInstant;
-import org.apache.derby.catalog.UUID;
-import org.apache.derby.iapi.services.uuid.UUIDFactory;
 import org.apache.derby.iapi.services.property.PropertyUtil;
 import org.apache.derby.iapi.reference.Attribute;
 import org.apache.derby.iapi.services.io.FileUtil;
 import org.apache.derby.iapi.util.ReuseFactory;
 
-import org.apache.derby.io.StorageFactory;
 import org.apache.derby.io.WritableStorageFactory;
 import org.apache.derby.io.StorageFile;
 import org.apache.derby.io.StorageRandomAccessFile;
 
 import org.apache.derby.iapi.util.InterruptStatus;
-import org.apache.derby.iapi.util.InterruptDetectedException;
 
 import java.io.File; // Plain files are used for backups
 import java.io.IOException;
@@ -103,13 +85,13 @@ import java.io.DataOutputStream;
 import java.io.ByteArrayInputStream;
 import java.io.DataInputStream;
 import java.io.FileNotFoundException;
-import java.io.InterruptedIOException;
 
 import java.net.MalformedURLException;
 import java.net.URL;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
 
 import java.util.Properties;
-import java.util.Vector;
 import java.util.zip.CRC32;
 
 /**
@@ -2732,9 +2714,16 @@ public final class LogToFile implements 
             
         }else {
             // create the log directory.
-            if (!privMkdirs(logDir)) {
+            IOException ex = null;
+            boolean created = false;
+            try {
+                created = privMkdirs(logDir);
+            } catch (IOException ioe) {
+                ex = ioe;
+            }
+            if (!created) {
                 throw StandardException.newException(
-                    SQLState.LOG_SEGMENT_NOT_EXIST, logDir.getPath());
+                    SQLState.LOG_SEGMENT_NOT_EXIST, ex, logDir.getPath());
             }
             createDataWarningFile();
         }
@@ -5720,9 +5709,15 @@ public final class LogToFile implements 
 		return runBooleanAction(3, file);
     }
 
-    protected boolean privMkdirs(StorageFile file)
+    protected boolean privMkdirs(StorageFile file) throws IOException
     {
-		return runBooleanAction(4, file);
+        this.action = 4;
+        this.activeFile = file;
+        try {
+            return ((Boolean) AccessController.doPrivileged(this));
+        } catch (PrivilegedActionException pae) {
+            throw (IOException) pae.getCause();
+        }
     }
 
 	private synchronized String[] privList(File file)

Modified: db/derby/code/trunk/java/engine/org/apache/derby/io/StorageFile.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/io/StorageFile.java?rev=1580789&r1=1580788&r2=1580789&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/io/StorageFile.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/io/StorageFile.java Mon Mar 24 09:13:13 2014
@@ -290,5 +290,5 @@ public interface StorageFile
      * for the file owner unless the property {@code
      * derby.useDefaultFilePermissions} is set to {@code true}.
      */
-    public void limitAccessToOwner();
+    public void limitAccessToOwner() throws IOException;
 }

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/util/corruptio/CorruptFile.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/util/corruptio/CorruptFile.java?rev=1580789&r1=1580788&r2=1580789&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/util/corruptio/CorruptFile.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/util/corruptio/CorruptFile.java Mon Mar 24 09:13:13 2014
@@ -369,7 +369,7 @@ class CorruptFile implements StorageFile
 		throw new MalformedURLException(toString());
 	}
 
-    public void limitAccessToOwner() {
+    public void limitAccessToOwner() throws IOException {
         realFile.limitAccessToOwner();
     }
 

Modified: db/derby/code/trunk/tools/jar/extraDBMSclasses.properties
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/tools/jar/extraDBMSclasses.properties?rev=1580789&r1=1580788&r2=1580789&view=diff
==============================================================================
--- db/derby/code/trunk/tools/jar/extraDBMSclasses.properties (original)
+++ db/derby/code/trunk/tools/jar/extraDBMSclasses.properties Mon Mar 24 09:13:13 2014
@@ -110,6 +110,10 @@ derby.module.engine.threaddump=org.apach
 derby.module.logging.provider=org.apache.derby.impl.services.stream.RollingFileStreamProvider
 derby.module.logging.stream=org.apache.derby.impl.services.stream.RollingFileStream
 
+# This class only exists if compiled using JDK 7 or higher. Will be enabled
+# by the build script if the JDK is recent enough.
+#jdk7#derby.module.permission.service=org.apache.derby.iapi.services.io.FilePermissionServiceImpl
+
 # optional tools
 derby.module.opttrace=org.apache.derby.impl.sql.compile.OptimizerTracer
 derby.module.opttraceviewer=org.apache.derby.impl.sql.compile.OptTraceViewer