1 /*
   2  * Copyright (c) 2008, 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.
   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 = file
  83             .getFileAttributeView(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         file.setAttribute(name, valueAsBytes);
 135         byte[] actualAsBytes = (byte[])file.getAttribute(name);
 136         if (!Arrays.equals(valueAsBytes, actualAsBytes))
 137             throw new RuntimeException("Unexpected attribute value");
 138         Map<String,?> map = file.readAttributes(name);
 139         if (!Arrays.equals(valueAsBytes, (byte[])map.get(ATTR_NAME)))
 140             throw new RuntimeException("Unexpected attribute value");
 141         map = file.readAttributes("user:*");
 142         if (!Arrays.equals(valueAsBytes, (byte[])map.get(ATTR_NAME)))
 143             throw new RuntimeException("Unexpected attribute value");
 144         map = file.readAttributes("user:DoesNotExist");
 145         if (!map.isEmpty())
 146             throw new RuntimeException("Map expected to be empty");
 147     }
 148 
 149     static void miscTests(final Path file) throws IOException {
 150         final UserDefinedFileAttributeView view = file
 151             .getFileAttributeView(UserDefinedFileAttributeView.class);
 152         view.write(ATTR_NAME, ByteBuffer.wrap(ATTR_VALUE.getBytes()));
 153 
 154         // NullPointerException
 155         final ByteBuffer buf = ByteBuffer.allocate(100);
 156 
 157         expectNullPointerException(new Task() {
 158             public void run() throws IOException {
 159                 view.read(null, buf);
 160             }});
 161         expectNullPointerException(new Task() {
 162             public void run() throws IOException {
 163                 view.read(ATTR_NAME, null);
 164             }});
 165         expectNullPointerException(new Task() {
 166             public void run() throws IOException {
 167                 view.write(null, buf);
 168             }});
 169         expectNullPointerException(new Task() {
 170             public void run() throws IOException {
 171                view.write(ATTR_NAME, null);
 172             }});
 173         expectNullPointerException(new Task() {
 174             public void run() throws IOException {
 175                 view.size(null);
 176             }});
 177         expectNullPointerException(new Task() {
 178             public void run() throws IOException {
 179                 view.delete(null);
 180             }});
 181         expectNullPointerException(new Task() {
 182             public void run() throws IOException {
 183                 file.getAttribute(null);
 184             }});
 185         expectNullPointerException(new Task() {
 186             public void run() throws IOException {
 187                 file.getAttribute("user:" + ATTR_NAME, (LinkOption[])null);
 188             }});
 189         expectNullPointerException(new Task() {
 190             public void run() throws IOException {
 191                 file.setAttribute("user:" + ATTR_NAME, null);
 192             }});
 193         expectNullPointerException(new Task() {
 194             public void run() throws IOException {
 195                 file.setAttribute(null, new byte[0]);
 196             }});
 197         expectNullPointerException(new Task() {
 198             public void run() throws IOException {
 199                 file.setAttribute("user: " + ATTR_NAME, new byte[0], (LinkOption[])null);
 200             }});
 201         expectNullPointerException(new Task() {
 202             public void run() throws IOException {
 203                 file.readAttributes((String)null);
 204             }});
 205         expectNullPointerException(new Task() {
 206             public void run() throws IOException {
 207                 file.readAttributes("*", (LinkOption[])null);
 208             }});
 209 
 210         // Read-only buffer
 211         tryCatch(IllegalArgumentException.class, new Task() {
 212             public void run() throws IOException {
 213                 ByteBuffer buf = ByteBuffer.wrap(ATTR_VALUE.getBytes()).asReadOnlyBuffer();
 214                 view.write(ATTR_NAME, buf);
 215                 buf.flip();
 216                 view.read(ATTR_NAME, buf);
 217             }});
 218 
 219         // Zero bytes remaining
 220         tryCatch(IOException.class, new Task() {
 221             public void run() throws IOException {
 222                 ByteBuffer buf = buf = ByteBuffer.allocateDirect(100);
 223                 buf.position(buf.capacity());
 224                 view.read(ATTR_NAME, buf);
 225             }});
 226     }
 227 
 228     public static void main(String[] args) throws IOException {
 229         // create temporary directory to run tests
 230         Path dir = TestUtil.createTemporaryDirectory();
 231         try {
 232             if (!dir.getFileStore().supportsFileAttributeView("user")) {
 233                 System.out.println("UserDefinedFileAttributeView not supported - skip test");
 234                 return;
 235             }
 236 
 237             // test access to user defined attributes of regular file
 238             Path file = dir.resolve("foo.html").createFile();
 239             try {
 240                 test(file);
 241             } finally {
 242                 file.delete();
 243             }
 244 
 245             // test access to user define attributes of directory
 246             file = dir.resolve("foo").createDirectory();
 247             try {
 248                 test(file);
 249             } finally {
 250                 file.delete();
 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").createSymbolicLink(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                     link.delete();
 263                 }
 264             }
 265 
 266             // misc. tests
 267             try {
 268                 file = dir.resolve("foo.txt").createFile();
 269                 miscTests(dir);
 270             } finally {
 271                 file.delete();
 272             }
 273 
 274         } finally {
 275             TestUtil.removeAll(dir);
 276         }
 277     }
 278  }