ClassFileNameHandler.java revision bbf4dbba6127ef96e316060b2b4ec292627a4078
1f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com/* 2f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com * [The "BSD licence"] 3f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com * Copyright (c) 2010 Ben Gruver 4f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com * All rights reserved. 5f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com * 6f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com * Redistribution and use in source and binary forms, with or without 7f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com * modification, are permitted provided that the following conditions 8f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com * are met: 9f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com * 1. Redistributions of source code must retain the above copyright 10f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com * notice, this list of conditions and the following disclaimer. 11f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com * 2. Redistributions in binary form must reproduce the above copyright 12f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com * notice, this list of conditions and the following disclaimer in the 13f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com * documentation and/or other materials provided with the distribution. 14f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com * 3. The name of the author may not be used to endorse or promote products 15f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com * derived from this software without specific prior written permission. 16f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com * 17f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com * INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com */ 28f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com 29f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.compackage org.jf.util; 30f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com 31f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.comimport ds.tree.RadixTree; 32f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.comimport ds.tree.RadixTreeImpl; 33f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com 34f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.comimport java.io.*; 35f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.comimport java.nio.CharBuffer; 36f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com 37f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com/** 38f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com * This class checks for case-insensitive file systems, and generates file names based on a given class name, that are 39f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com * guaranteed to be unique. When "colliding" class names are found, it appends a numeric identifier to the end of the 40f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com * class name to distinguish it from another class with a name that differes only by case. i.e. a.smali and a_2.smali 41f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com */ 42f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.compublic class ClassFileNameHandler { 43f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com private PackageNameEntry top; 44f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com private String fileExtension; 45f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com 46f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com public ClassFileNameHandler(File path, String fileExtension) { 47f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com this.top = new PackageNameEntry(path); 48f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com this.fileExtension = fileExtension; 49f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com } 50f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com 51f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com public File getUniqueFilenameForClass(String className) { 52f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com //class names should be passed in the normal dalvik style, with a leading L, a trailing ;, and using 53f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com //'/' as a separator. 54f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com if (className.charAt(0) != 'L' || className.charAt(className.length()-1) != ';') { 55f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com throw new RuntimeException("Not a valid dalvik class name"); 56f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com } 57f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com 58f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com String blah; 59f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com int packageElementCount = 1; 60f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com for (int i=1; i<className.length()-1; i++) { 61f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com if (className.charAt(i) == '/') { 62f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com packageElementCount++; 63f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com } 64f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com } 65f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com 66f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com String[] packageElements = new String[packageElementCount]; 67f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com int elementIndex = 0; 68f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com int elementStart = 1; 69f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com for (int i=1; i<className.length()-1; i++) { 70f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com if (className.charAt(i) == '/') { 71f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com //if the first char after the initial L is a '/', or if there are 72f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com //two consecutive '/' 73f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com if (i-elementStart==0) { 74f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com throw new RuntimeException("Not a valid dalvik class name"); 75f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com } 76f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com 77f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com packageElements[elementIndex++] = className.substring(elementStart, i); 78f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com elementStart = ++i; 79f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com } 80f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com } 81f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com 82f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com //at this point, we have added all the package elements to packageElements, but still need to add 83f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com //the final class name. elementStart should point to the beginning of the class name 84f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com 85f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com //this will be true if the class ends in a '/', i.e. Lsome/package/className/; 86f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com if (elementStart >= className.length()-1) { 87f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com throw new RuntimeException("Not a valid dalvik class name"); 88f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com } 89f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com packageElements[elementIndex] = className.substring(elementStart, className.length()-1); 90f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com 91f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com return top.addUniqueChild(packageElements, 0); 92f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com } 93f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com 94f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com private abstract class FileSystemEntry { 95f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com public final File file; 96f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com 97f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com public FileSystemEntry(File file) { 98f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com this.file = file; 99f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com } 100f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com 101f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com public abstract File addUniqueChild(String[] pathElements, int pathElementsIndex); 102f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com 103f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com public FileSystemEntry makeVirtual(File parent) { 104f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com return new VirtualGroupEntry(this, parent); 105f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com } 106f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com } 107f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com 108f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com private class PackageNameEntry extends FileSystemEntry { 109f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com //this contains the FileSystemEntries for all of this package's children 110f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com //the associated keys are all lowercase 111f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com private RadixTree<FileSystemEntry> children = new RadixTreeImpl<FileSystemEntry>(); 112f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com 113f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com public PackageNameEntry(File parent, String name) { 114f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com super(new File(parent, name)); 115f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com } 116f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com 117f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com public PackageNameEntry(File path) { 118f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com super(path); 119f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com } 120f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com 121f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com @Override 122f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com public File addUniqueChild(String[] pathElements, int pathElementsIndex) { 123f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com String elementName; 124f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com String elementNameLower; 125f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com 126f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com if (pathElementsIndex == pathElements.length - 1) { 127f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com elementName = pathElements[pathElementsIndex] + fileExtension; 128f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com } else { 129f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com elementName = pathElements[pathElementsIndex]; 130f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com } 131f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com elementNameLower = elementName.toLowerCase(); 132f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com 133f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com FileSystemEntry existingEntry = children.find(elementNameLower); 134f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com if (existingEntry != null) { 135f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com FileSystemEntry virtualEntry = existingEntry; 136f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com //if there is already another entry with the same name but different case, we need to 137f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com //add a virtual group, and then add the existing entry and the new entry to that group 138f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com if (!(existingEntry instanceof VirtualGroupEntry)) { 139f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com if (existingEntry.file.getName().equals(elementName)) { 140f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com if (pathElementsIndex == pathElements.length - 1) { 141f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com return existingEntry.file; 142f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com } else { 143f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com return existingEntry.addUniqueChild(pathElements, pathElementsIndex + 1); 144f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com } 145f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com } else { 146f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com virtualEntry = existingEntry.makeVirtual(file); 147f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com children.replace(elementNameLower, virtualEntry); 148f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com } 149f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com } 150f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com 151f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com return virtualEntry.addUniqueChild(pathElements, pathElementsIndex); 152f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com } 153f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com 154f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com if (pathElementsIndex == pathElements.length - 1) { 155f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com ClassNameEntry classNameEntry = new ClassNameEntry(file, elementName); 156f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com children.insert(elementNameLower, classNameEntry); 157f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com return classNameEntry.file; 158f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com } else { 159f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com PackageNameEntry packageNameEntry = new PackageNameEntry(file, elementName); 160f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com children.insert(elementNameLower, packageNameEntry); 161f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com return packageNameEntry.addUniqueChild(pathElements, pathElementsIndex + 1); 162f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com } 163f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com } 164f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com } 165f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com 166f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com /** 167f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com * A virtual group that groups together file system entries with the same name, differing only in case 168f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com */ 169f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com private class VirtualGroupEntry extends FileSystemEntry { 170f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com //this contains the FileSystemEntries for all of the files/directories in this group 171f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com //the key is the unmodified name of the entry, before it is modified to be made unique (if needed). 172f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com private RadixTree<FileSystemEntry> groupEntries = new RadixTreeImpl<FileSystemEntry>(); 173f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com 174f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com //whether the containing directory is case sensitive or not. 175 //-1 = unset 176 //0 = false; 177 //1 = true; 178 private int isCaseSensitive = -1; 179 180 public VirtualGroupEntry(FileSystemEntry firstChild, File parent) { 181 super(parent); 182 183 //use the name of the first child in the group as-is 184 groupEntries.insert(firstChild.file.getName(), firstChild); 185 } 186 187 @Override 188 public File addUniqueChild(String[] pathElements, int pathElementsIndex) { 189 String elementName = pathElements[pathElementsIndex]; 190 191 if (pathElementsIndex == pathElements.length - 1) { 192 elementName = elementName + fileExtension; 193 } 194 195 FileSystemEntry existingEntry = groupEntries.find(elementName); 196 if (existingEntry != null) { 197 if (pathElementsIndex == pathElements.length - 1) { 198 return existingEntry.file; 199 } else { 200 return existingEntry.addUniqueChild(pathElements, pathElementsIndex+1); 201 } 202 } 203 204 205 if (pathElementsIndex == pathElements.length - 1) { 206 String fileName; 207 if (!isCaseSensitive()) { 208 fileName = pathElements[pathElementsIndex] + "." + (groupEntries.getSize()+1) + fileExtension; 209 } else { 210 fileName = elementName; 211 } 212 213 ClassNameEntry classNameEntry = new ClassNameEntry(file, fileName); 214 groupEntries.insert(elementName, classNameEntry); 215 return classNameEntry.file; 216 } else { 217 String fileName; 218 if (!isCaseSensitive()) { 219 fileName = pathElements[pathElementsIndex] + "." + (groupEntries.getSize()+1); 220 } else { 221 fileName = elementName; 222 } 223 224 PackageNameEntry packageNameEntry = new PackageNameEntry(file, fileName); 225 groupEntries.insert(elementName, packageNameEntry); 226 return packageNameEntry.addUniqueChild(pathElements, pathElementsIndex + 1); 227 } 228 } 229 230 private boolean isCaseSensitive() { 231 if (isCaseSensitive != -1) { 232 return isCaseSensitive == 1; 233 } 234 235 File path = file; 236 237 if (path.exists() && path.isFile()) { 238 path = path.getParentFile(); 239 } 240 241 if ((!file.exists() && !file.mkdirs())) { 242 return false; 243 } 244 245 try { 246 boolean result = testCaseSensitivity(path); 247 isCaseSensitive = result?1:0; 248 return result; 249 } catch (IOException ex) { 250 return false; 251 } 252 } 253 254 private boolean testCaseSensitivity(File path) throws IOException { 255 int num = 1; 256 File f, f2; 257 do { 258 f = new File(path, "test." + num); 259 f2 = new File(path, "TEST." + num++); 260 } while(f.exists() || f2.exists()); 261 262 try { 263 try { 264 FileWriter writer = new FileWriter(f); 265 writer.write("test"); 266 writer.flush(); 267 writer.close(); 268 } catch (IOException ex) { 269 try {f.delete();} catch (Exception ex2) {} 270 throw ex; 271 } 272 273 if (f2.exists()) { 274 return false; 275 } 276 277 if (f2.createNewFile()) { 278 return true; 279 } 280 281 //the above 2 tests should catch almost all cases. But maybe there was a failure while creating f2 282 //that isn't related to case sensitivity. Let's see if we can open the file we just created using 283 //f2 284 try { 285 CharBuffer buf = CharBuffer.allocate(32); 286 FileReader reader = new FileReader(f2); 287 288 while (reader.read(buf) != -1 && buf.length() < 4); 289 if (buf.length() == 4 && buf.toString().equals("test")) { 290 return false; 291 } else { 292 //we probably shouldn't get here. If the filesystem was case-sensetive, creating a new 293 //FileReader should have thrown a FileNotFoundException. Otherwise, we should have opened 294 //the file and read in the string "test". It's remotely possible that someone else modified 295 //the file after we created it. Let's be safe and return false here as well 296 assert(false); 297 return false; 298 } 299 } catch (FileNotFoundException ex) { 300 return true; 301 } 302 } finally { 303 try { f.delete(); } catch (Exception ex) {} 304 try { f2.delete(); } catch (Exception ex) {} 305 } 306 } 307 308 @Override 309 public FileSystemEntry makeVirtual(File parent) { 310 return this; 311 } 312 } 313 314 private class ClassNameEntry extends FileSystemEntry { 315 public ClassNameEntry(File parent, String name) { 316 super(new File(parent, name)); 317 } 318 319 @Override 320 public File addUniqueChild(String[] pathElements, int pathElementsIndex) { 321 assert false; 322 return file; 323 } 324 } 325} 326