JarUtils.java revision 465a2ac534bf5c0dea38608dbe713ed3a9dc84eb
12be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka/* 22be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka * Copyright (C) 2012 The Android Open Source Project 32be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka * 42be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka * Licensed under the Apache License, Version 2.0 (the "License"); 52be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka * you may not use this file except in compliance with the License. 62be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka * You may obtain a copy of the License at 72be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka * 82be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka * http://www.apache.org/licenses/LICENSE-2.0 92be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka * 102be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka * Unless required by applicable law or agreed to in writing, software 112be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka * distributed under the License is distributed on an "AS IS" BASIS, 122be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka * See the License for the specific language governing permissions and 142be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka * limitations under the License. 152be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka */ 162be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka 17ca6acfdd6b3400ad6e29d45c29b0ec40ea92a968Tadashi G. Takaokapackage com.android.inputmethod.keyboard.tools; 182be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka 19465a2ac534bf5c0dea38608dbe713ed3a9dc84ebTadashi G. Takaokaimport java.io.Closeable; 202be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaokaimport java.io.IOException; 212be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaokaimport java.io.InputStream; 222be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaokaimport java.io.UnsupportedEncodingException; 232be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaokaimport java.net.URL; 242be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaokaimport java.net.URLDecoder; 252be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaokaimport java.util.ArrayList; 262be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaokaimport java.util.Enumeration; 272be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaokaimport java.util.jar.JarEntry; 282be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaokaimport java.util.jar.JarFile; 292be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka 301e11c44d1b5f9ddf593c5407cb14c458be0056f2Tadashi G. Takaokapublic final class JarUtils { 312be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka private JarUtils() { 322be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka // This utility class is not publicly instantiable. 332be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 342be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka 359c9802e6473e5e2e2b792d5f14502139feb49637Tadashi G. Takaoka public static JarFile getJarFile(final Class<?> mainClass) { 369c9802e6473e5e2e2b792d5f14502139feb49637Tadashi G. Takaoka final String mainClassPath = "/" + mainClass.getName().replace('.', '/') + ".class"; 379c9802e6473e5e2e2b792d5f14502139feb49637Tadashi G. Takaoka final URL resUrl = mainClass.getResource(mainClassPath); 382be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka if (!resUrl.getProtocol().equals("jar")) { 392be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka throw new RuntimeException("Should run as jar"); 402be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 412be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka final String path = resUrl.getPath(); 422be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka if (!path.startsWith("file:")) { 432be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka throw new RuntimeException("Unknown jar path: " + path); 442be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 452be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka final String jarPath = path.substring("file:".length(), path.indexOf('!')); 462be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka try { 472be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka return new JarFile(URLDecoder.decode(jarPath, "UTF-8")); 482be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } catch (UnsupportedEncodingException e) { 492be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } catch (IOException e) { 502be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 512be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka return null; 522be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 532be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka 542be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka public static InputStream openResource(final String name) { 552be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka return JarUtils.class.getResourceAsStream("/" + name); 562be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 572be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka 582be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka public interface JarFilter { 592be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka public boolean accept(String dirName, String name); 602be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 612be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka 62465a2ac534bf5c0dea38608dbe713ed3a9dc84ebTadashi G. Takaoka public static ArrayList<String> getEntryNameListing(final JarFile jar, final JarFilter filter) { 632be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka final ArrayList<String> result = new ArrayList<String>(); 642be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka final Enumeration<JarEntry> entries = jar.entries(); 652be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka while (entries.hasMoreElements()) { 662be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka final JarEntry entry = entries.nextElement(); 672be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka final String path = entry.getName(); 682be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka final int pos = path.lastIndexOf('/'); 692be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka final String dirName = (pos >= 0) ? path.substring(0, pos) : ""; 702be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka final String name = (pos >= 0) ? path.substring(pos + 1) : path; 712be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka if (filter.accept(dirName, name)) { 722be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka result.add(path); 732be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 742be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 752be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka return result; 762be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 772be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka 78465a2ac534bf5c0dea38608dbe713ed3a9dc84ebTadashi G. Takaoka public static ArrayList<String> getEntryNameListing(final JarFile jar, 79465a2ac534bf5c0dea38608dbe713ed3a9dc84ebTadashi G. Takaoka final String filterName) { 80465a2ac534bf5c0dea38608dbe713ed3a9dc84ebTadashi G. Takaoka return getEntryNameListing(jar, new JarFilter() { 812be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka @Override 822be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka public boolean accept(final String dirName, final String name) { 832be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka return name.equals(filterName); 842be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 852be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka }); 862be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 87465a2ac534bf5c0dea38608dbe713ed3a9dc84ebTadashi G. Takaoka 88465a2ac534bf5c0dea38608dbe713ed3a9dc84ebTadashi G. Takaoka // The language is taken from string resource jar entry name (values-<language>/) 89465a2ac534bf5c0dea38608dbe713ed3a9dc84ebTadashi G. Takaoka // or {@link LocaleUtils#DEFAULT_LANGUAGE_NAME} for the default string resource 90465a2ac534bf5c0dea38608dbe713ed3a9dc84ebTadashi G. Takaoka // directory (values/). 91465a2ac534bf5c0dea38608dbe713ed3a9dc84ebTadashi G. Takaoka public static String getLanguageFromEntryName(final String jarEntryName) { 92465a2ac534bf5c0dea38608dbe713ed3a9dc84ebTadashi G. Takaoka final String dirName = jarEntryName.substring(0, jarEntryName.lastIndexOf('/')); 93465a2ac534bf5c0dea38608dbe713ed3a9dc84ebTadashi G. Takaoka final int pos = dirName.lastIndexOf('/'); 94465a2ac534bf5c0dea38608dbe713ed3a9dc84ebTadashi G. Takaoka final String parentName = (pos >= 0) ? dirName.substring(pos + 1) : dirName; 95465a2ac534bf5c0dea38608dbe713ed3a9dc84ebTadashi G. Takaoka final int languagePos = parentName.indexOf('-'); 96465a2ac534bf5c0dea38608dbe713ed3a9dc84ebTadashi G. Takaoka if (languagePos < 0) { 97465a2ac534bf5c0dea38608dbe713ed3a9dc84ebTadashi G. Takaoka // Default resource name. 98465a2ac534bf5c0dea38608dbe713ed3a9dc84ebTadashi G. Takaoka return LocaleUtils.DEFAULT_LANGUAGE_NAME; 99465a2ac534bf5c0dea38608dbe713ed3a9dc84ebTadashi G. Takaoka } 100465a2ac534bf5c0dea38608dbe713ed3a9dc84ebTadashi G. Takaoka final String language = parentName.substring(languagePos + 1); 101465a2ac534bf5c0dea38608dbe713ed3a9dc84ebTadashi G. Takaoka final int countryPos = language.indexOf("-r"); 102465a2ac534bf5c0dea38608dbe713ed3a9dc84ebTadashi G. Takaoka if (countryPos < 0) { 103465a2ac534bf5c0dea38608dbe713ed3a9dc84ebTadashi G. Takaoka return language; 104465a2ac534bf5c0dea38608dbe713ed3a9dc84ebTadashi G. Takaoka } 105465a2ac534bf5c0dea38608dbe713ed3a9dc84ebTadashi G. Takaoka return language.replace("-r", "_"); 106465a2ac534bf5c0dea38608dbe713ed3a9dc84ebTadashi G. Takaoka } 107465a2ac534bf5c0dea38608dbe713ed3a9dc84ebTadashi G. Takaoka 108465a2ac534bf5c0dea38608dbe713ed3a9dc84ebTadashi G. Takaoka public static void close(final Closeable stream) { 109465a2ac534bf5c0dea38608dbe713ed3a9dc84ebTadashi G. Takaoka try { 110465a2ac534bf5c0dea38608dbe713ed3a9dc84ebTadashi G. Takaoka if (stream != null) { 111465a2ac534bf5c0dea38608dbe713ed3a9dc84ebTadashi G. Takaoka stream.close(); 112465a2ac534bf5c0dea38608dbe713ed3a9dc84ebTadashi G. Takaoka } 113465a2ac534bf5c0dea38608dbe713ed3a9dc84ebTadashi G. Takaoka } catch (IOException e) { 114465a2ac534bf5c0dea38608dbe713ed3a9dc84ebTadashi G. Takaoka } 115465a2ac534bf5c0dea38608dbe713ed3a9dc84ebTadashi G. Takaoka } 1162be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka} 117