📄 locator.java
字号:
/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.tools.ant.launch;import java.net.MalformedURLException;import java.net.URL;import java.io.File;import java.io.FilenameFilter;import java.io.ByteArrayOutputStream;import java.io.UnsupportedEncodingException;import java.text.CharacterIterator;import java.text.StringCharacterIterator;import java.util.Locale;// CheckStyle:LineLengthCheck OFF - urls are long!/** * The Locator is a utility class which is used to find certain items * in the environment. * * It is used at boot time in the launcher, and cannot make use of any of Ant's other classes. * * This is a surprisingly brittle piece of code, and has had lots of bugs filed against it. * {@link <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=42275">running ant off a network share can cause Ant to fail</a>} * {@link <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=8031">use File.toURI().toURL().toExternalForm()</a>} * {@link <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=42222">Locator implementation not encoding URI strings properly: spaces in paths</a>} * It also breaks Eclipse 3.3 Betas * {@link <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=183283">Exception if installation path has spaces</a>} * * Be very careful when making changes to this class, as a break will upset a lot of people. * @since Ant 1.6 */// CheckStyle:LineLengthCheck ON - urls are long!public final class Locator { private static final int NIBBLE = 4; private static final int NIBBLE_MASK = 0xF; private static final int ASCII_SIZE = 128; private static final int BYTE_SIZE = 256; private static final int WORD = 16; private static final int SPACE = 0x20; private static final int DEL = 0x7F; /** * encoding used to represent URIs */ public static final String URI_ENCODING = "UTF-8"; // stolen from org.apache.xerces.impl.XMLEntityManager#getUserDir() // of the Xerces-J team // which ASCII characters need to be escaped private static boolean[] gNeedEscaping = new boolean[ASCII_SIZE]; // the first hex character if a character needs to be escaped private static char[] gAfterEscaping1 = new char[ASCII_SIZE]; // the second hex character if a character needs to be escaped private static char[] gAfterEscaping2 = new char[ASCII_SIZE]; private static char[] gHexChs = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; /** Error string used when an invalid uri is seen */ public static final String ERROR_NOT_FILE_URI = "Can only handle valid file: URIs, not "; // initialize the above 3 arrays static { for (int i = 0; i < SPACE; i++) { gNeedEscaping[i] = true; gAfterEscaping1[i] = gHexChs[i >> NIBBLE]; gAfterEscaping2[i] = gHexChs[i & NIBBLE_MASK]; } gNeedEscaping[DEL] = true; gAfterEscaping1[DEL] = '7'; gAfterEscaping2[DEL] = 'F'; char[] escChs = {' ', '<', '>', '#', '%', '"', '{', '}', '|', '\\', '^', '~', '[', ']', '`'}; int len = escChs.length; char ch; for (int i = 0; i < len; i++) { ch = escChs[i]; gNeedEscaping[ch] = true; gAfterEscaping1[ch] = gHexChs[ch >> NIBBLE]; gAfterEscaping2[ch] = gHexChs[ch & NIBBLE_MASK]; } } /** * Not instantiable */ private Locator() { } /** * Find the directory or jar file the class has been loaded from. * * @param c the class whose location is required. * @return the file or jar with the class or null if we cannot * determine the location. * * @since Ant 1.6 */ public static File getClassSource(Class c) { String classResource = c.getName().replace('.', '/') + ".class"; return getResourceSource(c.getClassLoader(), classResource); } /** * Find the directory or jar a given resource has been loaded from. * * @param c the classloader to be consulted for the source. * @param resource the resource whose location is required. * * @return the file with the resource source or null if * we cannot determine the location. * * @since Ant 1.6 */ public static File getResourceSource(ClassLoader c, String resource) { if (c == null) { c = Locator.class.getClassLoader(); } URL url = null; if (c == null) { url = ClassLoader.getSystemResource(resource); } else { url = c.getResource(resource); } if (url != null) { String u = url.toString(); try { if (u.startsWith("jar:file:")) { int pling = u.indexOf("!"); String jarName = u.substring("jar:".length(), pling); return new File(fromURI(jarName)); } else if (u.startsWith("file:")) { int tail = u.indexOf(resource); String dirName = u.substring(0, tail); return new File(fromURI(dirName)); } } catch (IllegalArgumentException e) { //unable to determine the URI for reasons unknown. return null; } } return null; } /** * Constructs a file path from a <code>file:</code> URI. * * <p>Will be an absolute path if the given URI is absolute.</p> * * <p>Prior to Java 1.4, * swallows '%' that are not followed by two characters.</p> * * See <a href="http://www.w3.org/TR/xml11/#dt-sysid">dt-sysid</a> * which makes some mention of how * characters not supported by URI Reference syntax should be escaped. * * @param uri the URI designating a file in the local filesystem. * @return the local file system path for the file. * @throws IllegalArgumentException if the URI is malformed or not a legal file: URL * @since Ant 1.6 */ public static String fromURI(String uri) { // #buzilla8031: first try Java 1.4. String result = null; //result = fromUriJava14(uri); if (result == null) { result = fromURIJava13(uri); } return result; } /** * Java1.4+ code to extract the path from the URI. * @param uri * @return null if a conversion was not possible */ private static String fromUriJava14(String uri) { Class uriClazz = null; try { uriClazz = Class.forName("java.net.URI"); } catch (ClassNotFoundException cnfe) { // Fine, Java 1.3 or earlier, do it by hand. return null; } // Also check for properly formed URIs. Ant formerly recommended using // nonsense URIs such as "file:./foo.xml" in XML includes. You shouldn't // do that (just "foo.xml" is correct) but for compatibility we special-case // things when the path is not absolute, and fall back to the old parsing behavior. if (uriClazz != null && uri.startsWith("file:/")) { try { java.lang.reflect.Method createMethod = uriClazz.getMethod("create", new Class[]{String.class}); Object uriObj = createMethod.invoke(null, new Object[]{encodeURI(uri)}); java.lang.reflect.Constructor fileConst = File.class.getConstructor(new Class[]{uriClazz}); File f = (File) fileConst.newInstance(new Object[]{uriObj}); //bug #42227 forgot to decode before returning return decodeUri(f.getAbsolutePath()); } catch (java.lang.reflect.InvocationTargetException e) { Throwable e2 = e.getTargetException(); if (e2 instanceof IllegalArgumentException) { // Bad URI, pass this on. // no, this is downgraded to a warning after various // JRE bugs surfaced. Hand off // to our built in code on a failure //throw new IllegalArgumentException( // "Bad URI " + uri + ":" + e2.getMessage(), e2); e2.printStackTrace(); } else { // Unexpected target exception? Should not happen. e2.printStackTrace(); } } catch (Exception e) { // Reflection problems? Should not happen, debug. e.printStackTrace(); } } return null; } /** * package-private for testing in same classloader * @param uri uri to expand * @return the decoded URI * @since Ant1.7.1 */ static String fromURIJava13(String uri) { // Fallback method for Java 1.3 or earlier. URL url = null; try { url = new URL(uri); } catch (MalformedURLException emYouEarlEx) { // Ignore malformed exception } if (url == null || !("file".equals(url.getProtocol()))) { throw new IllegalArgumentException(ERROR_NOT_FILE_URI + uri); } StringBuffer buf = new StringBuffer(url.getHost()); if (buf.length() > 0) { buf.insert(0, File.separatorChar).insert(0, File.separatorChar); } String file = url.getFile(); int queryPos = file.indexOf('?'); buf.append((queryPos < 0) ? file : file.substring(0, queryPos));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -