View Javadoc
1   package org.djutils.io;
2   
3   import static org.junit.jupiter.api.Assertions.assertEquals;
4   import static org.junit.jupiter.api.Assertions.assertNotNull;
5   import static org.junit.jupiter.api.Assertions.assertNull;
6   
7   import java.io.File;
8   import java.io.FileInputStream;
9   import java.io.FileNotFoundException;
10  import java.io.FileOutputStream;
11  import java.io.IOException;
12  import java.io.InputStream;
13  import java.net.URISyntaxException;
14  import java.net.URL;
15  import java.nio.file.Files;
16  import java.nio.file.Paths;
17  import java.util.ArrayList;
18  import java.util.Arrays;
19  import java.util.List;
20  import java.util.jar.JarEntry;
21  import java.util.jar.JarOutputStream;
22  
23  import org.junit.jupiter.api.Test;
24  
25  /**
26   * URLResourceTest.java.
27   * <p>
28   * Copyright (c) 2002-2024 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved. See
29   * for project information <a href="https://djutils.org" target="_blank"> https://djutils.org</a>. The DJUTILS project is
30   * distributed under a three-clause BSD-style license, which can be found at
31   * <a href="https://djutils.org/docs/license.html" target="_blank"> https://djutils.org/docs/license.html</a>.
32   * </p>
33   * @author <a href="https://www.tudelft.nl/averbraeck" target="_blank">Alexander Verbraeck</a>
34   */
35  public class URLResourceTest
36  {
37  
38      /**
39       * Test whether URLResource retrieves files.
40       * @throws IOException on I/O error
41       */
42      // TODO @Test -- this test does not run on ubuntu
43      public final void fileTest() throws IOException
44      {
45          // create a temporary file.
46          File tempFile = File.createTempFile("filetest-", ".temp");
47          String tempFilePath = tempFile.getAbsolutePath();
48          URL url1 = URLResource.getResource(tempFilePath);
49          assertNotNull(url1);
50          assertEquals(new File(url1.getPath()).getAbsolutePath().replaceAll("\\\\", "/"), tempFilePath.replaceAll("\\\\", "/"));
51  
52          URL url2 = URLResource.getResource("/" + tempFilePath);
53          assertNotNull(url2);
54          assertEquals(new File(url2.getPath()).getAbsolutePath().replaceAll("\\\\", "/"), tempFilePath.replaceAll("\\\\", "/"));
55      }
56  
57      /**
58       * Test whether URLResource retrieves files.
59       * @throws IOException on I/O error
60       * @throws URISyntaxException on URL error
61       */
62      @Test
63      public final void resourceTest() throws IOException, URISyntaxException
64      {
65          URL url = URLResource.getResource("/org/djutils-test-resources/test.txt");
66          String absolutePath = url.toURI().getPath();
67          List<String> lines = Files.readAllLines(Paths.get(url.toURI()));
68          assertEquals(3, lines.size());
69          assertEquals("abc", lines.get(0));
70  
71          url = null;
72          lines = null;
73  
74          url = URLResource.getResource("test.txt", "/org/djutils-test-resources/");
75          lines = Files.readAllLines(Paths.get(url.toURI()));
76          assertEquals(3, lines.size());
77          assertEquals("def", lines.get(1));
78  
79          url = null;
80          lines = null;
81  
82          url = URLResource.getResource("/org/djutils-test-resources/test.txt", "/");
83          lines = Files.readAllLines(Paths.get(url.toURI()));
84          assertEquals(3, lines.size());
85          assertEquals("ghi", lines.get(2));
86  
87          url = null;
88          lines = null;
89  
90          url = URLResource.getResource("file://" + absolutePath);
91          lines = Files.readAllLines(Paths.get(url.toURI()));
92          assertEquals(3, lines.size());
93          assertEquals("abc", lines.get(0));
94      }
95  
96      /**
97       * Test whether URLResource retrieves files.
98       * @throws IOException on I/O error
99       * @throws URISyntaxException on URL error
100      */
101     @Test
102     public final void resourceAsStreamTest() throws IOException, URISyntaxException
103     {
104         InputStream stream = URLResource.getResourceAsStream("/org/djutils-test-resources/test.txt");
105         byte[] barr = readAllBytes(stream);
106         stream.close();
107         assertEquals('a', barr[0]);
108 
109         assertNull(URLResource.getResourceAsStream("xxx:///org::djutils-test-resources<>test.txt"));
110 
111         stream = URLResource.getResourceAsStream("/org/djutils-test-resources/test123.txt");
112         assertNull(stream);
113     }
114 
115     /**
116      * Test whether URLResource retrieves files.
117      * @throws IOException on I/O error
118      * @throws URISyntaxException on error
119      */
120     @Test
121     public final void jarTest() throws IOException, URISyntaxException
122     {
123         // create a temporary jar file.
124         File jarFile = File.createTempFile("filetest-", ".jar");
125         File file1 = File.createTempFile("filetest-", ".f1");
126         File file2 = File.createTempFile("filetest-", ".f2");
127         File file3 = File.createTempFile("filetest-", ".f3");
128 
129         FileOutputStream fos = new FileOutputStream(jarFile.getAbsolutePath());
130         JarOutputStream jos = new JarOutputStream(fos);
131         addToJarFile(file1.getAbsolutePath(), jos);
132         addToJarFile(file2.getAbsolutePath(), jos);
133         addToJarFile(file3.getAbsolutePath(), jos);
134         jos.close();
135         fos.close();
136 
137         String jarFilePath = jarFile.getAbsolutePath();
138         URL jarURL = URLResource.getResource(jarFilePath);
139         assertNotNull(jarURL);
140         // System.out.println(jarFile.getAbsolutePath() + "!" + file1.getName());
141         // URL jar1 = URLResource.getResource(jarFile.getAbsolutePath() + "!" + file1.getName());
142         // System.out.println(jar1.toURI());
143         // assertNotNull(jar1);
144     }
145 
146     /**
147      * Copy a plain file into a jar file.
148      * @param fileName String; name of the file to copy
149      * @param jos JarOutputStream; stream for writing into the jar file
150      * @throws FileNotFoundException when the input file could not be found
151      * @throws IOException when the input file could not be read, or writing to the jar stream fails
152      */
153     public void addToJarFile(final String fileName, final JarOutputStream jos) throws FileNotFoundException, IOException
154     {
155         File file = new File(fileName);
156         FileInputStream fis = new FileInputStream(file);
157         JarEntry zipEntry = new JarEntry(file.getName());
158         jos.putNextEntry(zipEntry);
159         byte[] bytes = new byte[1024];
160         int length;
161         while ((length = fis.read(bytes)) >= 0)
162         {
163             jos.write(bytes, 0, length);
164         }
165         jos.closeEntry();
166         fis.close();
167     }
168 
169     /**
170      * Copied from Java 13 to handle readAllBytes in Java 8.
171      * @param stream the input stream to read the bytes from
172      * @return the byte array
173      * @throws IOException on I/O error
174      */
175     private byte[] readAllBytes(final InputStream stream) throws IOException
176     {
177         List<byte[]> bufs = null;
178         byte[] result = null;
179         int total = 0;
180         int remaining = Integer.MAX_VALUE;
181         int n;
182         do
183         {
184             byte[] buf = new byte[Math.min(remaining, 8192)];
185             int nread = 0;
186 
187             // read to EOF which may read more or less than buffer size
188             while ((n = stream.read(buf, nread, Math.min(buf.length - nread, remaining))) > 0)
189             {
190                 nread += n;
191                 remaining -= n;
192             }
193 
194             if (nread > 0)
195             {
196                 if (Integer.MAX_VALUE - 8 - total < nread)
197                 {
198                     throw new OutOfMemoryError("Required array size too large");
199                 }
200                 total += nread;
201                 if (result == null)
202                 {
203                     result = buf;
204                 }
205                 else
206                 {
207                     if (bufs == null)
208                     {
209                         bufs = new ArrayList<>();
210                         bufs.add(result);
211                     }
212                     bufs.add(buf);
213                 }
214             }
215             // if the last call to read returned -1 or the number of bytes
216             // requested have been read then break
217         }
218         while (n >= 0 && remaining > 0);
219 
220         if (bufs == null)
221         {
222             if (result == null)
223             {
224                 return new byte[0];
225             }
226             return result.length == total ? result : Arrays.copyOf(result, total);
227         }
228 
229         result = new byte[total];
230         int offset = 0;
231         remaining = total;
232         for (byte[] b : bufs)
233         {
234             int count = Math.min(b.length, remaining);
235             System.arraycopy(b, 0, result, offset, count);
236             offset += count;
237             remaining -= count;
238         }
239 
240         return result;
241 
242     }
243 }