1 /* 2 * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.tools.javac.file; 27 28 import java.io.File; 29 import java.io.FileInputStream; 30 import java.io.FileOutputStream; 31 import java.io.IOException; 32 import java.io.InputStream; 33 import java.io.OutputStream; 34 import java.io.OutputStreamWriter; 35 import java.io.Writer; 36 import java.lang.ref.Reference; 37 import java.lang.ref.SoftReference; 38 import java.net.URI; 39 import java.nio.ByteBuffer; 40 import java.nio.CharBuffer; 41 import java.nio.charset.CharsetDecoder; 42 import javax.tools.JavaFileObject; 43 44 /** 45 * A subclass of JavaFileObject representing regular files. 46 * 47 * <p><b>This is NOT part of any supported API. 48 * If you write code that depends on this, you do so at your own risk. 49 * This code and its internal interfaces are subject to change or 50 * deletion without notice.</b> 51 */ 52 class RegularFileObject extends BaseFileObject { 53 54 /** Have the parent directories been created? 55 */ 56 private boolean hasParents = false; 57 private String name; 58 final File file; 59 private Reference<File> absFileRef; 60 61 public RegularFileObject(JavacFileManager fileManager, File f) { 62 this(fileManager, f.getName(), f); 63 } 64 65 public RegularFileObject(JavacFileManager fileManager, String name, File f) { 66 super(fileManager); 67 if (f.isDirectory()) { 68 throw new IllegalArgumentException("directories not supported"); 69 } 70 this.name = name; 71 this.file = f; 72 } 73 74 @Override 75 public URI toUri() { 76 return file.toURI().normalize(); 77 } 78 79 @Override 80 public String getName() { 81 return file.getPath(); 82 } 83 84 @Override 85 public String getShortName() { 86 return name; 87 } 88 89 @Override 90 public JavaFileObject.Kind getKind() { 91 return getKind(name); 92 } 93 94 @Override 95 public InputStream openInputStream() throws IOException { 96 return new FileInputStream(file); 97 } 98 99 @Override 100 public OutputStream openOutputStream() throws IOException { 101 ensureParentDirectoriesExist(); 102 return new FileOutputStream(file); 103 } 104 105 @Override 106 public CharBuffer getCharContent(boolean ignoreEncodingErrors) throws IOException { 107 CharBuffer cb = fileManager.getCachedContent(this); 108 if (cb == null) { 109 InputStream in = new FileInputStream(file); 110 try { 111 ByteBuffer bb = fileManager.makeByteBuffer(in); 112 JavaFileObject prev = fileManager.log.useSource(this); 113 try { 114 cb = fileManager.decode(bb, ignoreEncodingErrors); 115 } finally { 116 fileManager.log.useSource(prev); 117 } 118 fileManager.recycleByteBuffer(bb); 119 if (!ignoreEncodingErrors) { 120 fileManager.cache(this, cb); 121 } 122 } finally { 123 in.close(); 124 } 125 } 126 return cb; 127 } 128 129 @Override 130 public Writer openWriter() throws IOException { 131 ensureParentDirectoriesExist(); 132 return new OutputStreamWriter(new FileOutputStream(file), fileManager.getEncodingName()); 133 } 134 135 @Override 136 public long getLastModified() { 137 return file.lastModified(); 138 } 139 140 @Override 141 public boolean delete() { 142 return file.delete(); 143 } 144 145 @Override 146 protected CharsetDecoder getDecoder(boolean ignoreEncodingErrors) { 147 return fileManager.getDecoder(fileManager.getEncodingName(), ignoreEncodingErrors); 148 } 149 150 @Override 151 protected String inferBinaryName(Iterable<? extends File> path) { 152 String fPath = file.getPath(); 153 //System.err.println("RegularFileObject " + file + " " +r.getPath()); 154 for (File dir: path) { 155 //System.err.println("dir: " + dir); 156 String dPath = dir.getPath(); 157 if (dPath.length() == 0) 158 dPath = System.getProperty("user.dir"); 159 if (!dPath.endsWith(File.separator)) 160 dPath += File.separator; 161 if (fPath.regionMatches(true, 0, dPath, 0, dPath.length()) 162 && new File(fPath.substring(0, dPath.length())).equals(new File(dPath))) { 163 String relativeName = fPath.substring(dPath.length()); 164 return removeExtension(relativeName).replace(File.separatorChar, '.'); 165 } 166 } 167 return null; 168 } 169 170 @Override 171 public boolean isNameCompatible(String cn, JavaFileObject.Kind kind) { 172 cn.getClass(); 173 // null check 174 if (kind == Kind.OTHER && getKind() != kind) { 175 return false; 176 } 177 String n = cn + kind.extension; 178 if (name.equals(n)) { 179 return true; 180 } 181 if (name.equalsIgnoreCase(n)) { 182 try { 183 // allow for Windows 184 return file.getCanonicalFile().getName().equals(n); 185 } catch (IOException e) { 186 } 187 } 188 return false; 189 } 190 191 private void ensureParentDirectoriesExist() throws IOException { 192 if (!hasParents) { 193 File parent = file.getParentFile(); 194 if (parent != null && !parent.exists()) { 195 if (!parent.mkdirs()) { 196 if (!parent.exists() || !parent.isDirectory()) { 197 throw new IOException("could not create parent directories"); 198 } 199 } 200 } 201 hasParents = true; 202 } 203 } 204 205 /** 206 * Check if two file objects are equal. 207 * Two RegularFileObjects are equal if the absolute paths of the underlying 208 * files are equal. 209 */ 210 @Override 211 public boolean equals(Object other) { 212 if (this == other) 213 return true; 214 215 if (!(other instanceof RegularFileObject)) 216 return false; 217 218 RegularFileObject o = (RegularFileObject) other; 219 return getAbsoluteFile().equals(o.getAbsoluteFile()); 220 } 221 222 @Override 223 public int hashCode() { 224 return getAbsoluteFile().hashCode(); 225 } 226 227 private File getAbsoluteFile() { 228 File absFile = (absFileRef == null ? null : absFileRef.get()); 229 if (absFile == null) { 230 absFile = file.getAbsoluteFile(); 231 absFileRef = new SoftReference<File>(absFile); 232 } 233 return absFile; 234 } 235 }