United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: 4787260 (spec) File.equals() spec suggests canonicalization but implemention does not canonicalize
4787260 : (spec) File.equals() spec suggests canonicalization but implemention does not canonicalize

Details
Type:
Bug
Submit Date:
2002-12-03
Status:
Open
Updated Date:
2012-01-08
Project Name:
JDK
Resolved Date:
Component:
core-libs
OS:
solaris_8,generic
Sub-Component:
java.io
CPU:
sparc,generic
Priority:
P4
Resolution:
Unresolved
Affected Versions:
1.3.0,1.4.1
Targeted Versions:
tbd_major

Related Reports

Sub Tasks

Description
Name: nt126004			Date: 12/02/2002


FULL PRODUCT VERSION :
java version "1.4.1"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1-b21)
Java HotSpot(TM) Client VM (build 1.4.1-b21, mixed mode)

FULL OPERATING SYSTEM VERSION :
SunOS mammoth 5.8 Generic_108528-15 sun4u sparc SUNW,Ultra-80


A DESCRIPTION OF THE PROBLEM :
The documentation for java.io.File.equals() states that the
method "Returns true if and only if the argument is not null
and is an abstract pathname that denotes the same file or
directory as this abstract pathname." However, a look at the
source reveals that it delegates to the FileSystem class (same
package), whose compare() method states "Compare two abstract
pathnames lexicographically." These two contracts contradict
one another.

Refer to the sample program below and its output.
On UNIX, at least, /dir1/dir2/../dir3/myfile and
/dir1/dir3/myfile "denote the same file or directory."
However, the strings are not lexicographically equal and
File.equals() returns false.

Either File.equals() should be changed to use canonical files
to meet the contract set out in its documentation or the
documentation should be changed to state explicitly that
the files are compared using their path strings without
reference to whether or not they refer to the same physical
file.

This bug is similar to a general case of bug #4143695. That
bug's author asked for a change to File to assist with a
permissions issue. I am not interested in permissions or in
the specific case he mentions, however; I am concerned with
the misleading inconsistency between what is implied in the
method's documentation and what its implementation in fact
does.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile and run the sample code below.

EXPECTED VERSUS ACTUAL BEHAVIOR :
The sample program outputs:

File #1: /dir1/dir2/../dir3/myfile
File #2: /dir1/dir3/myfile
Equals:  false

Based on the File.equals() docs, I expected:

File #1: /dir1/dir2/../dir3/myfile
File #2: /dir1/dir3/myfile
Equals:  true

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.io.File;

public class FileTest {
    public static void main(String[] args) {
        File f1 = new File("/dir1/dir2/../dir3/myfile");
        File f2 = new File("/dir1/dir3/myfile");
        System.out.println("File #1: " + f1);
        System.out.println("File #2: " + f2);
        System.out.println("Equals:  " + f1.equals(f2));
    }
}

---------- END SOURCE ----------

CUSTOMER WORKAROUND :
Always compare canonical files:

public static boolean equals(File f1, File f2) {
    File canonical1;
    try {
        canonical1 = f1.getCanonicalFile();
    } catch (IOException iox) {
        canonical1 = f1.getAbsoluteFile();
    }
    File canonical2;
    try {
        canonical2 = f2.getCanonicalFile();
    } catch (IOException iox) {
        canonical2 = f2.getAbsoluteFile();
    }
    return canonical1.equals(canonical2);
}

There are a couple of issues with the above:
1.) It involves a couple object instatiations, and is hence
    relatively slow, and
2.) In the event that an IOException occurs in
    getCanonicalFile(), the output is not guaranteed to be
    correct. However, it is *more likely* to be correct than
    the current code.
(Review ID: 165782) 
======================================================================

                                    

Comments



Hardware and Software, Engineered to Work Together