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  * @key randomness
  29  */
  30 
  31 import java.nio.ByteBuffer;
  32 import java.nio.charset.Charset;
  33 import java.nio.file.*;
  34 import static java.nio.file.LinkOption.*;
  35 import java.nio.file.attribute.*;
  36 import java.util.Arrays;
  37 import java.util.Map;
  38 import java.util.Random;
  39 import java.io.IOException;
  40 
  41 public class Basic {
  42 
  43     private static Random rand = new Random();
  44 
  45     private static final String ATTR_NAME = "mime_type";
  46     private static final String ATTR_VALUE = "text/plain";
  47     private static final String ATTR_VALUE2 = "text/html";
  48 
  49     static interface Task {
  50         void run() throws Exception;
  51     }
  52 
  53     static void tryCatch(Class<? extends Throwable> ex, Task task) {
  54         boolean caught = false;
  55         try {
  56             task.run();
  57         } catch (Throwable x) {
  58             if (ex.isAssignableFrom(x.getClass())) {
  59                 caught = true;
  60             } else {
  61                 throw new RuntimeException(x);
  62             }
  63         }
  64         if (!caught)
  65             throw new RuntimeException(ex.getName() + " expected");
  66     }
  67 
  68     static void expectNullPointerException(Task task) {
  69         tryCatch(NullPointerException.class, task);
  70     }
  71 
  72     static boolean hasAttribute(UserDefinedFileAttributeView view, String attr)
  73         throws IOException
  74     {
  75         for (String name: view.list()) {
  76             if (name.equals(ATTR_NAME))
  77                 return true;
  78         }
  79         return false;
  80     }
  81 
  82     static void test(Path file, LinkOption... options) throws IOException {
  83         final UserDefinedFileAttributeView view =
  84             Files.getFileAttributeView(file, UserDefinedFileAttributeView.class, options);
  85         ByteBuffer buf = rand.nextBoolean() ?
  86             ByteBuffer.allocate(100) : ByteBuffer.allocateDirect(100);
  87 
  88         // Test: write
  89         buf.put(ATTR_VALUE.getBytes()).flip();
  90         int size = buf.remaining();
  91         int nwrote = view.write(ATTR_NAME, buf);
  92         if (nwrote != size)
  93             throw new RuntimeException("Unexpected number of bytes written");
  94 
  95         // Test: size
  96         if (view.size(ATTR_NAME) != size)
  97             throw new RuntimeException("Unexpected size");
  98 
  99         // Test: read
 100         buf.clear();
 101         int nread = view.read(ATTR_NAME, buf);
 102         if (nread != size)
 103             throw new RuntimeException("Unexpected number of bytes read");
 104         buf.flip();
 105         String value = Charset.defaultCharset().decode(buf).toString();
 106         if (!value.equals(ATTR_VALUE))
 107             throw new RuntimeException("Unexpected attribute value");
 108 
 109         // Test: read with insufficient space
 110         tryCatch(IOException.class, new Task() {
 111             public void run() throws IOException {
 112                 view.read(ATTR_NAME, ByteBuffer.allocateDirect(1));
 113             }});
 114 
 115         // Test: replace value
 116         buf.clear();
 117         buf.put(ATTR_VALUE2.getBytes()).flip();
 118         size = buf.remaining();
 119         view.write(ATTR_NAME, buf);
 120         if (view.size(ATTR_NAME) != size)
 121             throw new RuntimeException("Unexpected size");
 122 
 123         // Test: list
 124         if (!hasAttribute(view, ATTR_NAME))
 125             throw new RuntimeException("Attribute name not in list");
 126 
 127         // Test: delete
 128         view.delete(ATTR_NAME);
 129         if (hasAttribute(view, ATTR_NAME))
 130             throw new RuntimeException("Attribute name in list");
 131 
 132         // Test: dynamic access
 133         String name = "user:" + ATTR_NAME;
 134         byte[] valueAsBytes = ATTR_VALUE.getBytes();
 135         Files.setAttribute(file, name, valueAsBytes);
 136         byte[] actualAsBytes = (byte[])Files.getAttribute(file, name);
 137         if (!Arrays.equals(valueAsBytes, actualAsBytes))
 138             throw new RuntimeException("Unexpected attribute value");
 139         Map<String,?> map = Files.readAttributes(file, name);
 140         if (!Arrays.equals(valueAsBytes, (byte[])map.get(ATTR_NAME)))
 141             throw new RuntimeException("Unexpected attribute value");
 142         map = Files.readAttributes(file, "user:*");
 143         if (!Arrays.equals(valueAsBytes, (byte[])map.get(ATTR_NAME)))
 144             throw new RuntimeException("Unexpected attribute value");
 145     }
 146 
 147     static void miscTests(final Path file) throws IOException {
 148         final UserDefinedFileAttributeView view =
 149             Files.getFileAttributeView(file, UserDefinedFileAttributeView.class);
 150         view.write(ATTR_NAME, ByteBuffer.wrap(ATTR_VALUE.getBytes()));
 151 
 152         // NullPointerException
 153         final ByteBuffer buf = ByteBuffer.allocate(100);
 154 
 155         expectNullPointerException(new Task() {
 156             public void run() throws IOException {
 157                 view.read(null, buf);
 158             }});
 159         expectNullPointerException(new Task() {
 160             public void run() throws IOException {
 161                 view.read(ATTR_NAME, null);
 162             }});
 163         expectNullPointerException(new Task() {
 164             public void run() throws IOException {
 165                 view.write(null, buf);
 166             }});
 167         expectNullPointerException(new Task() {
 168             public void run() throws IOException {
 169                view.write(ATTR_NAME, null);
 170             }});
 171         expectNullPointerException(new Task() {
 172             public void run() throws IOException {
 173                 view.size(null);
 174             }});
 175         expectNullPointerException(new Task() {
 176             public void run() throws IOException {
 177                 view.delete(null);
 178             }});
 179         expectNullPointerException(new Task() {
 180             public void run() throws IOException {
 181                 Files.getAttribute(file, null);
 182             }});
 183         expectNullPointerException(new Task() {
 184             public void run() throws IOException {
 185                 Files.getAttribute(file, "user:" + ATTR_NAME, (LinkOption[])null);
 186             }});
 187         expectNullPointerException(new Task() {
 188             public void run() throws IOException {
 189                 Files.setAttribute(file, "user:" + ATTR_NAME, null);
 190             }});
 191         expectNullPointerException(new Task() {
 192             public void run() throws IOException {
 193                 Files.setAttribute(file, null, new byte[0]);
 194             }});
 195         expectNullPointerException(new Task() {
 196             public void run() throws IOException {
 197                 Files.setAttribute(file, "user: " + ATTR_NAME, new byte[0], (LinkOption[])null);
 198             }});
 199         expectNullPointerException(new Task() {
 200             public void run() throws IOException {
 201                 Files.readAttributes(file, (String)null);
 202             }});
 203         expectNullPointerException(new Task() {
 204             public void run() throws IOException {
 205                 Files.readAttributes(file, "*", (LinkOption[])null);
 206             }});
 207 
 208         // Read-only buffer
 209         tryCatch(IllegalArgumentException.class, new Task() {
 210             public void run() throws IOException {
 211                 ByteBuffer buf = ByteBuffer.wrap(ATTR_VALUE.getBytes()).asReadOnlyBuffer();
 212                 view.write(ATTR_NAME, buf);
 213                 buf.flip();
 214                 view.read(ATTR_NAME, buf);
 215             }});
 216 
 217         // Zero bytes remaining
 218         tryCatch(IOException.class, new Task() {
 219             public void run() throws IOException {
 220                 ByteBuffer buf = buf = ByteBuffer.allocateDirect(100);
 221                 buf.position(buf.capacity());
 222                 view.read(ATTR_NAME, buf);
 223             }});
 224     }
 225 
 226     public static void main(String[] args) throws IOException {
 227         // create temporary directory to run tests
 228         Path dir = TestUtil.createTemporaryDirectory();
 229         try {
 230             if (!Files.getFileStore(dir).supportsFileAttributeView("user")) {
 231                 System.out.println("UserDefinedFileAttributeView not supported - skip test");
 232                 return;
 233             }
 234 
 235             // test access to user defined attributes of regular file
 236             Path file = dir.resolve("foo.html");
 237             Files.createFile(file);
 238             try {
 239                 test(file);
 240             } finally {
 241                 Files.delete(file);
 242             }
 243 
 244             // test access to user defined attributes of directory
 245             Path subdir = dir.resolve("foo");
 246             Files.createDirectory(subdir);
 247             try {
 248                 test(subdir);
 249             } finally {
 250                 Files.delete(subdir);
 251             }
 252 
 253             // test access to user defined attributes of sym link
 254             if (TestUtil.supportsLinks(dir)) {
 255                 Path target = dir.resolve("doesnotexist");
 256                 Path link = dir.resolve("link");
 257                 Files.createSymbolicLink(link, target);
 258                 try {
 259                     test(link, NOFOLLOW_LINKS);
 260                 } catch (IOException x) {
 261                     // access to attributes of sym link may not be supported
 262                 } finally {
 263                     Files.delete(link);
 264                 }
 265             }
 266 
 267             // misc. tests
 268             try {
 269                 file = dir.resolve("foo.txt");
 270                 Files.createFile(file);
 271                 miscTests(dir);
 272             } finally {
 273                 Files.delete(file);
 274             }
 275 
 276         } finally {
 277             TestUtil.removeAll(dir);
 278         }
 279     }
 280  }