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