1 /*
   2  * Copyright (c) 2008, 2011, 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.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /* @test
  25  * @bug 4313887 6838333
  26  * @summary Unit test for java.nio.file.attribute.UserDefinedFileAttributeView
  27  * @library ../..
  28  */
  29 
  30 import java.nio.ByteBuffer;
  31 import java.nio.charset.Charset;
  32 import java.nio.file.*;
  33 import static java.nio.file.LinkOption.*;
  34 import java.nio.file.attribute.*;
  35 import java.util.Arrays;
  36 import java.util.Map;
  37 import java.util.Random;
  38 import java.io.IOException;
  39 
  40 public class Basic {
  41 
  42     private static Random rand = new Random();
  43 
  44     private static final String ATTR_NAME = "mime_type";
  45     private static final String ATTR_VALUE = "text/plain";
  46     private static final String ATTR_VALUE2 = "text/html";
  47 
  48     static interface Task {
  49         void run() throws Exception;
  50     }
  51 
  52     static void tryCatch(Class<? extends Throwable> ex, Task task) {
  53         boolean caught = false;
  54         try {
  55             task.run();
  56         } catch (Throwable x) {
  57             if (ex.isAssignableFrom(x.getClass())) {
  58                 caught = true;
  59             } else {
  60                 throw new RuntimeException(x);
  61             }
  62         }
  63         if (!caught)
  64             throw new RuntimeException(ex.getName() + " expected");
  65     }
  66 
  67     static void expectNullPointerException(Task task) {
  68         tryCatch(NullPointerException.class, task);
  69     }
  70 
  71     static boolean hasAttribute(UserDefinedFileAttributeView view, String attr)
  72         throws IOException
  73     {
  74         for (String name: view.list()) {
  75             if (name.equals(ATTR_NAME))
  76                 return true;
  77         }
  78         return false;
  79     }
  80 
  81     static void test(Path file, LinkOption... options) throws IOException {
  82         final UserDefinedFileAttributeView view =
  83             Files.getFileAttributeView(file, UserDefinedFileAttributeView.class, options);
  84         ByteBuffer buf = rand.nextBoolean() ?
  85             ByteBuffer.allocate(100) : ByteBuffer.allocateDirect(100);
  86 
  87         // Test: write
  88         buf.put(ATTR_VALUE.getBytes()).flip();
  89         int size = buf.remaining();
  90         int nwrote = view.write(ATTR_NAME, buf);
  91         if (nwrote != size)
  92             throw new RuntimeException("Unexpected number of bytes written");
  93 
  94         // Test: size
  95         if (view.size(ATTR_NAME) != size)
  96             throw new RuntimeException("Unexpected size");
  97 
  98         // Test: read
  99         buf.clear();
 100         int nread = view.read(ATTR_NAME, buf);
 101         if (nread != size)
 102             throw new RuntimeException("Unexpected number of bytes read");
 103         buf.flip();
 104         String value = Charset.defaultCharset().decode(buf).toString();
 105         if (!value.equals(ATTR_VALUE))
 106             throw new RuntimeException("Unexpected attribute value");
 107 
 108         // Test: read with insufficient space
 109         tryCatch(IOException.class, new Task() {
 110             public void run() throws IOException {
 111                 view.read(ATTR_NAME, ByteBuffer.allocateDirect(1));
 112             }});
 113 
 114         // Test: replace value
 115         buf.clear();
 116         buf.put(ATTR_VALUE2.getBytes()).flip();
 117         size = buf.remaining();
 118         view.write(ATTR_NAME, buf);
 119         if (view.size(ATTR_NAME) != size)
 120             throw new RuntimeException("Unexpected size");
 121 
 122         // Test: list
 123         if (!hasAttribute(view, ATTR_NAME))
 124             throw new RuntimeException("Attribute name not in list");
 125 
 126         // Test: delete
 127         view.delete(ATTR_NAME);
 128         if (hasAttribute(view, ATTR_NAME))
 129             throw new RuntimeException("Attribute name in list");
 130 
 131         // Test: dynamic access
 132         String name = "user:" + ATTR_NAME;
 133         byte[] valueAsBytes = ATTR_VALUE.getBytes();
 134         Files.setAttribute(file, name, valueAsBytes);
 135         byte[] actualAsBytes = (byte[])Files.getAttribute(file, name);
 136         if (!Arrays.equals(valueAsBytes, actualAsBytes))
 137             throw new RuntimeException("Unexpected attribute value");
 138         Map<String,?> map = Files.readAttributes(file, name);
 139         if (!Arrays.equals(valueAsBytes, (byte[])map.get(ATTR_NAME)))
 140             throw new RuntimeException("Unexpected attribute value");
 141         map = Files.readAttributes(file, "user:*");
 142         if (!Arrays.equals(valueAsBytes, (byte[])map.get(ATTR_NAME)))
 143             throw new RuntimeException("Unexpected attribute value");
 144     }
 145 
 146     static void miscTests(final Path file) throws IOException {
 147         final UserDefinedFileAttributeView view =
 148             Files.getFileAttributeView(file, UserDefinedFileAttributeView.class);
 149         view.write(ATTR_NAME, ByteBuffer.wrap(ATTR_VALUE.getBytes()));
 150 
 151         // NullPointerException
 152         final ByteBuffer buf = ByteBuffer.allocate(100);
 153 
 154         expectNullPointerException(new Task() {
 155             public void run() throws IOException {
 156                 view.read(null, buf);
 157             }});
 158         expectNullPointerException(new Task() {
 159             public void run() throws IOException {
 160                 view.read(ATTR_NAME, null);
 161             }});
 162         expectNullPointerException(new Task() {
 163             public void run() throws IOException {
 164                 view.write(null, buf);
 165             }});
 166         expectNullPointerException(new Task() {
 167             public void run() throws IOException {
 168                view.write(ATTR_NAME, null);
 169             }});
 170         expectNullPointerException(new Task() {
 171             public void run() throws IOException {
 172                 view.size(null);
 173             }});
 174         expectNullPointerException(new Task() {
 175             public void run() throws IOException {
 176                 view.delete(null);
 177             }});
 178         expectNullPointerException(new Task() {
 179             public void run() throws IOException {
 180                 Files.getAttribute(file, null);
 181             }});
 182         expectNullPointerException(new Task() {
 183             public void run() throws IOException {
 184                 Files.getAttribute(file, "user:" + ATTR_NAME, (LinkOption[])null);
 185             }});
 186         expectNullPointerException(new Task() {
 187             public void run() throws IOException {
 188                 Files.setAttribute(file, "user:" + ATTR_NAME, null);
 189             }});
 190         expectNullPointerException(new Task() {
 191             public void run() throws IOException {
 192                 Files.setAttribute(file, null, new byte[0]);
 193             }});
 194         expectNullPointerException(new Task() {
 195             public void run() throws IOException {
 196                 Files.setAttribute(file, "user: " + ATTR_NAME, new byte[0], (LinkOption[])null);
 197             }});
 198         expectNullPointerException(new Task() {
 199             public void run() throws IOException {
 200                 Files.readAttributes(file, (String)null);
 201             }});
 202         expectNullPointerException(new Task() {
 203             public void run() throws IOException {
 204                 Files.readAttributes(file, "*", (LinkOption[])null);
 205             }});
 206 
 207         // Read-only buffer
 208         tryCatch(IllegalArgumentException.class, new Task() {
 209             public void run() throws IOException {
 210                 ByteBuffer buf = ByteBuffer.wrap(ATTR_VALUE.getBytes()).asReadOnlyBuffer();
 211                 view.write(ATTR_NAME, buf);
 212                 buf.flip();
 213                 view.read(ATTR_NAME, buf);
 214             }});
 215 
 216         // Zero bytes remaining
 217         tryCatch(IOException.class, new Task() {
 218             public void run() throws IOException {
 219                 ByteBuffer buf = buf = ByteBuffer.allocateDirect(100);
 220                 buf.position(buf.capacity());
 221                 view.read(ATTR_NAME, buf);
 222             }});
 223     }
 224 
 225     public static void main(String[] args) throws IOException {
 226         // create temporary directory to run tests
 227         Path dir = TestUtil.createTemporaryDirectory();
 228         try {
 229             if (!Files.getFileStore(dir).supportsFileAttributeView("user")) {
 230                 System.out.println("UserDefinedFileAttributeView not supported - skip test");
 231                 return;
 232             }
 233 
 234             // test access to user defined attributes of regular file
 235             Path file = dir.resolve("foo.html");
 236             Files.createFile(file);
 237             try {
 238                 test(file);
 239             } finally {
 240                 Files.delete(file);
 241             }
 242 
 243             // test access to user defined attributes of directory
 244             Path subdir = dir.resolve("foo");
 245             Files.createDirectory(subdir);
 246             try {
 247                 test(subdir);
 248             } finally {
 249                 Files.delete(subdir);
 250             }
 251 
 252             // test access to user defined attributes of sym link
 253             if (TestUtil.supportsLinks(dir)) {
 254                 Path target = dir.resolve("doesnotexist");
 255                 Path link = dir.resolve("link");
 256                 Files.createSymbolicLink(link, target);
 257                 try {
 258                     test(link, NOFOLLOW_LINKS);
 259                 } catch (IOException x) {
 260                     // access to attributes of sym link may not be supported
 261                 } finally {
 262                     Files.delete(link);
 263                 }
 264             }
 265 
 266             // misc. tests
 267             try {
 268                 file = dir.resolve("foo.txt");
 269                 Files.createFile(file);
 270                 miscTests(dir);
 271             } finally {
 272                 Files.delete(file);
 273             }
 274 
 275         } finally {
 276             TestUtil.removeAll(dir);
 277         }
 278     }
 279  }