TempFileHelper.java revision 10767:eaa52ce531c3
1/* 2 * Copyright (c) 2009, 2013, 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 26package java.nio.file; 27 28import java.util.Set; 29import java.util.EnumSet; 30import java.security.SecureRandom; 31import static java.security.AccessController.*; 32import java.io.IOException; 33import java.nio.file.attribute.FileAttribute; 34import java.nio.file.attribute.PosixFilePermission; 35import java.nio.file.attribute.PosixFilePermissions; 36import static java.nio.file.attribute.PosixFilePermission.*; 37import sun.security.action.GetPropertyAction; 38 39 40/** 41 * Helper class to support creation of temporary files and directories with 42 * initial attributes. 43 */ 44 45class TempFileHelper { 46 private TempFileHelper() { } 47 48 // temporary directory location 49 private static final Path tmpdir = 50 Paths.get(doPrivileged(new GetPropertyAction("java.io.tmpdir"))); 51 52 private static final boolean isPosix = 53 FileSystems.getDefault().supportedFileAttributeViews().contains("posix"); 54 55 // file name generation, same as java.io.File for now 56 private static final SecureRandom random = new SecureRandom(); 57 private static Path generatePath(String prefix, String suffix, Path dir) { 58 long n = random.nextLong(); 59 n = (n == Long.MIN_VALUE) ? 0 : Math.abs(n); 60 Path name = dir.getFileSystem().getPath(prefix + Long.toString(n) + suffix); 61 // the generated name should be a simple file name 62 if (name.getParent() != null) 63 throw new IllegalArgumentException("Invalid prefix or suffix"); 64 return dir.resolve(name); 65 } 66 67 // default file and directory permissions (lazily initialized) 68 private static class PosixPermissions { 69 static final FileAttribute<Set<PosixFilePermission>> filePermissions = 70 PosixFilePermissions.asFileAttribute(EnumSet.of(OWNER_READ, OWNER_WRITE)); 71 static final FileAttribute<Set<PosixFilePermission>> dirPermissions = 72 PosixFilePermissions.asFileAttribute(EnumSet 73 .of(OWNER_READ, OWNER_WRITE, OWNER_EXECUTE)); 74 } 75 76 /** 77 * Creates a file or directory in the given directory (or in the 78 * temporary directory if dir is {@code null}). 79 */ 80 private static Path create(Path dir, 81 String prefix, 82 String suffix, 83 boolean createDirectory, 84 FileAttribute<?>[] attrs) 85 throws IOException 86 { 87 if (prefix == null) 88 prefix = ""; 89 if (suffix == null) 90 suffix = (createDirectory) ? "" : ".tmp"; 91 if (dir == null) 92 dir = tmpdir; 93 94 // in POSIX environments use default file and directory permissions 95 // if initial permissions not given by caller. 96 if (isPosix && (dir.getFileSystem() == FileSystems.getDefault())) { 97 if (attrs.length == 0) { 98 // no attributes so use default permissions 99 attrs = new FileAttribute<?>[1]; 100 attrs[0] = (createDirectory) ? PosixPermissions.dirPermissions : 101 PosixPermissions.filePermissions; 102 } else { 103 // check if posix permissions given; if not use default 104 boolean hasPermissions = false; 105 for (int i=0; i<attrs.length; i++) { 106 if (attrs[i].name().equals("posix:permissions")) { 107 hasPermissions = true; 108 break; 109 } 110 } 111 if (!hasPermissions) { 112 FileAttribute<?>[] copy = new FileAttribute<?>[attrs.length+1]; 113 System.arraycopy(attrs, 0, copy, 0, attrs.length); 114 attrs = copy; 115 attrs[attrs.length-1] = (createDirectory) ? 116 PosixPermissions.dirPermissions : 117 PosixPermissions.filePermissions; 118 } 119 } 120 } 121 122 // loop generating random names until file or directory can be created 123 SecurityManager sm = System.getSecurityManager(); 124 for (;;) { 125 Path f; 126 try { 127 f = generatePath(prefix, suffix, dir); 128 } catch (InvalidPathException e) { 129 // don't reveal temporary directory location 130 if (sm != null) 131 throw new IllegalArgumentException("Invalid prefix or suffix"); 132 throw e; 133 } 134 try { 135 if (createDirectory) { 136 return Files.createDirectory(f, attrs); 137 } else { 138 return Files.createFile(f, attrs); 139 } 140 } catch (SecurityException e) { 141 // don't reveal temporary directory location 142 if (dir == tmpdir && sm != null) 143 throw new SecurityException("Unable to create temporary file or directory"); 144 throw e; 145 } catch (FileAlreadyExistsException e) { 146 // ignore 147 } 148 } 149 } 150 151 /** 152 * Creates a temporary file in the given directory, or in the 153 * temporary directory if dir is {@code null}. 154 */ 155 static Path createTempFile(Path dir, 156 String prefix, 157 String suffix, 158 FileAttribute<?>[] attrs) 159 throws IOException 160 { 161 return create(dir, prefix, suffix, false, attrs); 162 } 163 164 /** 165 * Creates a temporary directory in the given directory, or in the 166 * temporary directory if dir is {@code null}. 167 */ 168 static Path createTempDirectory(Path dir, 169 String prefix, 170 FileAttribute<?>[] attrs) 171 throws IOException 172 { 173 return create(dir, prefix, null, true, attrs); 174 } 175} 176