1 // © 2016 and later: Unicode, Inc. and others. 2 // License & terms of use: http://www.unicode.org/copyright.html#License 3 /* 4 ****************************************************************************** 5 * Copyright (C) 2005-2015, International Business Machines Corporation and 6 * others. All Rights Reserved. 7 ****************************************************************************** 8 */ 9 10 package com.ibm.icu.impl; 11 12 import java.io.BufferedReader; 13 import java.io.File; 14 import java.io.IOException; 15 import java.io.InputStream; 16 import java.io.InputStreamReader; 17 import java.lang.reflect.InvocationTargetException; 18 import java.lang.reflect.Method; 19 import java.net.JarURLConnection; 20 import java.net.URISyntaxException; 21 import java.net.URL; 22 import java.util.Enumeration; 23 import java.util.HashMap; 24 import java.util.Map; 25 import java.util.jar.JarEntry; 26 import java.util.jar.JarFile; 27 28 public abstract class URLHandler { 29 public static final String PROPNAME = "urlhandler.props"; 30 31 private static final Map<String, Method> handlers; 32 33 private static final boolean DEBUG = ICUDebug.enabled("URLHandler"); 34 35 static { 36 Map<String, Method> h = null; 37 38 BufferedReader br = null; 39 try { 40 @SuppressWarnings("resource") // Closed by BufferedReader. 41 ClassLoader loader = ClassLoaderUtil.getClassLoader(URLHandler.class); 42 InputStream is = loader.getResourceAsStream(PROPNAME); 43 44 if (is != null) { 45 Class<?>[] params = { URL.class }; 46 br = new BufferedReader(new InputStreamReader(is)); 47 48 for (String line = br.readLine(); line != null; line = br.readLine()) { 49 line = line.trim(); 50 51 if (line.length() == 0 || line.charAt(0) == '#') { 52 continue; 53 } 54 55 int ix = line.indexOf('='); 56 57 if (ix == -1) { 58 if (DEBUG) System.err.println("bad urlhandler line: '" + line + "'"); 59 break; 60 } 61 62 String key = line.substring(0, ix).trim(); 63 String value = line.substring(ix+1).trim(); 64 65 try { 66 Class<?> cl = Class.forName(value); 67 Method m = cl.getDeclaredMethod("get", params); 68 69 if (h == null) { 70 h = new HashMap<String, Method>(); 71 } 72 h.put(key, m)73 h.put(key, m); 74 } 75 catch (ClassNotFoundException e) { 76 if (DEBUG) System.err.println(e); 77 } 78 catch(NoSuchMethodException e) { 79 if (DEBUG) System.err.println(e); 80 } 81 catch(SecurityException e) { 82 if (DEBUG) System.err.println(e); 83 } 84 } br.close()85 br.close(); 86 } 87 } catch (Throwable t) { 88 if (DEBUG) System.err.println(t); 89 } finally { 90 if (br != null) { 91 try { br.close()92 br.close(); 93 } catch (IOException ignored) { 94 } 95 } 96 } 97 98 handlers = h; 99 } 100 get(URL url)101 public static URLHandler get(URL url) { 102 if (url == null) { 103 return null; 104 } 105 106 String protocol = url.getProtocol(); 107 108 if (handlers != null) { 109 Method m = handlers.get(protocol); 110 111 if (m != null) { 112 try { 113 URLHandler handler = (URLHandler)m.invoke(null, new Object[] { url }); 114 115 if (handler != null) { 116 return handler; 117 } 118 } 119 catch(IllegalAccessException e) { 120 if (DEBUG) System.err.println(e); 121 } 122 catch(IllegalArgumentException e) { 123 if (DEBUG) System.err.println(e); 124 } 125 catch(InvocationTargetException e) { 126 if (DEBUG) System.err.println(e); 127 } 128 } 129 } 130 131 return getDefault(url); 132 } 133 getDefault(URL url)134 protected static URLHandler getDefault(URL url) { 135 URLHandler handler = null; 136 137 String protocol = url.getProtocol(); 138 try { 139 if (protocol.equals("file")) { 140 handler = new FileURLHandler(url); 141 } else if (protocol.equals("jar") || protocol.equals("wsjar")) { 142 handler = new JarURLHandler(url); 143 } 144 } catch (Exception e) { 145 // ignore - just return null 146 } 147 return handler; 148 } 149 150 private static class FileURLHandler extends URLHandler { 151 File file; 152 FileURLHandler(URL url)153 FileURLHandler(URL url) { 154 try { 155 file = new File(url.toURI()); 156 } catch (URISyntaxException use) { 157 // fall through 158 } 159 if (file == null || !file.exists()) { 160 if (DEBUG) System.err.println("file does not exist - " + url.toString()); 161 throw new IllegalArgumentException(); 162 } 163 } 164 165 @Override guide(URLVisitor v, boolean recurse, boolean strip)166 public void guide(URLVisitor v, boolean recurse, boolean strip) { 167 if (file.isDirectory()) { 168 process(v, recurse, strip, "/", file.listFiles()); 169 } else { 170 v.visit(file.getName()); 171 } 172 } 173 process(URLVisitor v, boolean recurse, boolean strip, String path, File[] files)174 private void process(URLVisitor v, boolean recurse, boolean strip, String path, File[] files) { 175 if (files != null) { 176 for (int i = 0; i < files.length; i++) { 177 File f = files[i]; 178 179 if (f.isDirectory()) { 180 if (recurse) { 181 process(v, recurse, strip, path + f.getName()+ '/', f.listFiles()); 182 } 183 } else { 184 v.visit(strip? f.getName() : path + f.getName()); 185 } 186 } 187 } 188 } 189 } 190 191 private static class JarURLHandler extends URLHandler { 192 JarFile jarFile; 193 String prefix; 194 JarURLHandler(URL url)195 JarURLHandler(URL url) { 196 try { 197 prefix = url.getPath(); 198 199 int ix = prefix.lastIndexOf("!/"); 200 201 if (ix >= 0) { 202 prefix = prefix.substring(ix + 2); // truncate after "!/" 203 } 204 205 String protocol = url.getProtocol(); 206 if (!protocol.equals("jar")) { 207 // change the protocol to "jar" 208 // Note: is this really OK? 209 String urlStr = url.toString(); 210 int idx = urlStr.indexOf(":"); 211 if (idx != -1) { 212 url = new URL("jar" + urlStr.substring(idx)); 213 } 214 } 215 216 JarURLConnection conn = (JarURLConnection)url.openConnection(); 217 jarFile = conn.getJarFile(); 218 } 219 catch (Exception e) { 220 if (DEBUG) System.err.println("icurb jar error: " + e); 221 throw new IllegalArgumentException("jar error: " + e.getMessage()); 222 } 223 } 224 225 @Override guide(URLVisitor v, boolean recurse, boolean strip)226 public void guide(URLVisitor v, boolean recurse, boolean strip) { 227 try { 228 Enumeration<JarEntry> entries = jarFile.entries(); 229 230 while (entries.hasMoreElements()) { 231 JarEntry entry = entries.nextElement(); 232 233 if (!entry.isDirectory()) { // skip just directory paths 234 String name = entry.getName(); 235 236 if (name.startsWith(prefix)) { 237 name = name.substring(prefix.length()); 238 int ix = name.lastIndexOf('/'); 239 if (ix > 0 && !recurse) { 240 continue; 241 } 242 if (strip && ix != -1) { 243 name = name.substring(ix+1); 244 } 245 v.visit(name); 246 } 247 } 248 } 249 } 250 catch (Exception e) { 251 if (DEBUG) System.err.println("icurb jar error: " + e); 252 } 253 } 254 } 255 guide(URLVisitor visitor, boolean recurse)256 public void guide(URLVisitor visitor, boolean recurse) 257 { 258 guide(visitor, recurse, true); 259 } 260 guide(URLVisitor visitor, boolean recurse, boolean strip)261 public abstract void guide(URLVisitor visitor, boolean recurse, boolean strip); 262 263 public interface URLVisitor { visit(String str)264 void visit(String str); 265 } 266 } 267