/* * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package libcore.io; import junit.framework.TestCase; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.net.JarURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import java.net.URLStreamHandler; import java.net.UnknownServiceException; import java.util.Arrays; import tests.support.resource.Support_Resources; public class ClassPathURLStreamHandlerTest extends TestCase { // A well formed jar file with 6 entries. private static final String JAR = "ClassPathURLStreamHandlerTest.jar"; private static final String ENTRY_IN_ROOT = "root.txt"; private static final String DIR_ENTRY_WITHOUT_SLASH = "foo"; private static final String DIR_ENTRY_WITH_SLASH = DIR_ENTRY_WITHOUT_SLASH + "/"; private static final String ENTRY_IN_SUBDIR = "foo/bar/baz.txt"; private static final String ENTRY_STORED = "stored_file.txt"; private static final String ENTRY_WITH_SPACES_ENCODED = "file%20with%20spaces.txt"; private static final String ENTRY_WITH_SPACES_UNENCODED = "file with spaces.txt"; private static final String ENTRY_THAT_NEEDS_ESCAPING = "file_with_percent20_%20.txt"; private static final String ENTRY_THAT_NEEDS_ESCAPING_ENCODED = "file_with_percent20_%2520.txt"; private static final String ENTRY_WITH_RELATIVE_PATH = "foo/../foo/bar/baz.txt"; private static final String MISSING_ENTRY = "Wrong.resource"; private File jarFile; @Override protected void setUp() throws Exception { File resources = Support_Resources.createTempFolder().getCanonicalFile(); Support_Resources.copyFile(resources, null, JAR); jarFile = new File(resources, JAR); } public void testConstructor() throws Exception { try { ClassPathURLStreamHandler streamHandler = new ClassPathURLStreamHandler("Missing.file"); fail("Should throw IOException"); } catch (IOException expected) { } String fileName = jarFile.getPath(); ClassPathURLStreamHandler streamHandler = new ClassPathURLStreamHandler(fileName); streamHandler.close(); } public void testGetEntryOrNull() throws Exception { String fileName = jarFile.getPath(); ClassPathURLStreamHandler streamHandler = new ClassPathURLStreamHandler(fileName); checkGetEntryUrlOrNull(streamHandler, ENTRY_IN_ROOT, ENTRY_IN_ROOT); checkGetEntryUrlOrNull(streamHandler, ENTRY_IN_SUBDIR, ENTRY_IN_SUBDIR); checkGetEntryUrlOrNull(streamHandler, ENTRY_WITH_SPACES_UNENCODED, ENTRY_WITH_SPACES_ENCODED); checkGetEntryUrlOrNull(streamHandler, ENTRY_THAT_NEEDS_ESCAPING, ENTRY_THAT_NEEDS_ESCAPING_ENCODED); // getEntryOrNull() performs a lookup with and without trailing slash to handle directories. // http://b/22527772 checkGetEntryUrlOrNull(streamHandler, DIR_ENTRY_WITHOUT_SLASH, DIR_ENTRY_WITHOUT_SLASH); checkGetEntryUrlOrNull(streamHandler, DIR_ENTRY_WITH_SLASH, DIR_ENTRY_WITH_SLASH); assertNull(streamHandler.getEntryUrlOrNull(MISSING_ENTRY)); assertNull(streamHandler.getEntryUrlOrNull("/" + ENTRY_IN_ROOT)); assertNull(streamHandler.getEntryUrlOrNull("/" + ENTRY_IN_SUBDIR)); assertNull(streamHandler.getEntryUrlOrNull(ENTRY_WITH_SPACES_ENCODED)); assertNull(streamHandler.getEntryUrlOrNull(ENTRY_WITH_RELATIVE_PATH)); assertNull(streamHandler.getEntryUrlOrNull("/" + DIR_ENTRY_WITHOUT_SLASH)); assertNull(streamHandler.getEntryUrlOrNull("/" + DIR_ENTRY_WITH_SLASH)); streamHandler.close(); } /** * Check that the call to {@link ClassPathURLStreamHandler#getEntryUrlOrNull(String)} works as * expected. */ private void checkGetEntryUrlOrNull(ClassPathURLStreamHandler streamHandler, String entryName, String expectedJarRelativeURI) throws IOException { String fileName = jarFile.getPath(); URL urlOrNull = streamHandler.getEntryUrlOrNull(entryName); assertNotNull("URL was unexpectedly null for " + entryName, urlOrNull); assertEquals("jar:file:" + fileName + "!/" + expectedJarRelativeURI, urlOrNull.toExternalForm()); // Make sure that the resource could be opened and the correct contents returned, i.e. the // same as those read from the jar file directly. assertOpenConnectionOk(jarFile, expectedJarRelativeURI, streamHandler); } public void testIsEntryStored() throws IOException { String fileName = jarFile.getPath(); ClassPathURLStreamHandler streamHandler = new ClassPathURLStreamHandler(fileName); assertFalse(streamHandler.isEntryStored("this/file/does/not/exist.txt")); // This one is compressed assertFalse(streamHandler.isEntryStored(ENTRY_IN_SUBDIR)); assertTrue(streamHandler.isEntryStored(ENTRY_STORED)); assertTrue(streamHandler.isEntryStored(DIR_ENTRY_WITHOUT_SLASH)); // Directory entries are just stored, empty entries with "/" on the end of the name, so // "true". assertTrue(streamHandler.isEntryStored(DIR_ENTRY_WITH_SLASH)); } public void testOpenConnection() throws Exception { String fileName = jarFile.getPath(); ClassPathURLStreamHandler streamHandler = new ClassPathURLStreamHandler(fileName); assertOpenConnectionOk(jarFile, ENTRY_IN_ROOT, streamHandler); assertOpenConnectionOk(jarFile, ENTRY_IN_SUBDIR, streamHandler); assertOpenConnectionOk(jarFile, ENTRY_WITH_SPACES_ENCODED, streamHandler); assertOpenConnectionOk(jarFile, ENTRY_WITH_SPACES_UNENCODED, streamHandler); assertOpenConnectionOk(jarFile, DIR_ENTRY_WITH_SLASH, streamHandler); assertOpenConnectionOk(jarFile, DIR_ENTRY_WITHOUT_SLASH, streamHandler); assertOpenConnectionConnectFails(jarFile, ENTRY_WITH_RELATIVE_PATH, streamHandler); assertOpenConnectionConnectFails(jarFile, MISSING_ENTRY, streamHandler); assertOpenConnectionConnectFails(jarFile, ENTRY_THAT_NEEDS_ESCAPING, streamHandler); streamHandler.close(); } private void assertOpenConnectionConnectFails( File jarFile, String entryName, URLStreamHandler streamHandler) throws IOException { URL standardUrl = createJarUrl(jarFile, entryName, null /* use default stream handler */); try { standardUrl.openConnection().connect(); fail(); } catch (FileNotFoundException expected) { } URL actualUrl = createJarUrl(jarFile, entryName, streamHandler); try { actualUrl.openConnection().connect(); fail(); } catch (FileNotFoundException expected) { } } private static void assertOpenConnectionOk(File jarFile, String entryName, ClassPathURLStreamHandler streamHandler) throws IOException { URL standardUrl = createJarUrl(jarFile, entryName, null /* use default stream handler */); URLConnection standardUrlConnection = standardUrl.openConnection(); assertNotNull(standardUrlConnection); URL actualUrl = createJarUrl(jarFile, entryName, streamHandler); URLConnection actualUrlConnection = actualUrl.openConnection(); assertNotNull(actualUrlConnection); assertBehaviorSame(standardUrlConnection, actualUrlConnection); } private static void assertBehaviorSame(URLConnection standardURLConnection, URLConnection actualUrlConnection) throws IOException { JarURLConnection standardJarUrlConnection = (JarURLConnection) standardURLConnection; JarURLConnection actualJarUrlConnection = (JarURLConnection) actualUrlConnection; byte[] actualBytes = Streams.readFully(actualJarUrlConnection.getInputStream()); byte[] standardBytes = Streams.readFully(standardJarUrlConnection.getInputStream()); assertEquals(Arrays.toString(standardBytes), Arrays.toString(actualBytes)); try { actualJarUrlConnection.getOutputStream(); fail(); } catch (UnknownServiceException expected) { } assertEquals( standardJarUrlConnection.getJarFile().getName(), actualJarUrlConnection.getJarFile().getName()); assertEquals( standardJarUrlConnection.getJarEntry().getName(), actualJarUrlConnection.getJarEntry().getName()); assertEquals( standardJarUrlConnection.getJarFileURL(), actualJarUrlConnection.getJarFileURL()); assertEquals( standardJarUrlConnection.getContentType(), actualJarUrlConnection.getContentType()); assertEquals( standardJarUrlConnection.getContentLength(), actualJarUrlConnection.getContentLength()); } private static URL createJarUrl(File jarFile, String entryName, URLStreamHandler streamHandler) throws MalformedURLException { return new URL("jar", null, -1, jarFile.toURI() + "!/" + entryName, streamHandler); } }