Coverage Report - org.owasp.dependencycheck.org.apache.tools.ant.launch.Locator
 
Classes in this File Line Coverage Branch Coverage Complexity
Locator
0%
0/168
0%
0/88
5.846
Locator$1
0%
0/6
0%
0/4
5.846
 
 1  
 /*
 2  
  *  Licensed to the Apache Software Foundation (ASF) under one or more
 3  
  *  contributor license agreements.  See the NOTICE file distributed with
 4  
  *  this work for additional information regarding copyright ownership.
 5  
  *  The ASF licenses this file to You under the Apache License, Version 2.0
 6  
  *  (the "License"); you may not use this file except in compliance with
 7  
  *  the License.  You may obtain a copy of the License at
 8  
  *
 9  
  *      http://www.apache.org/licenses/LICENSE-2.0
 10  
  *
 11  
  *  Unless required by applicable law or agreed to in writing, software
 12  
  *  distributed under the License is distributed on an "AS IS" BASIS,
 13  
  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  *  See the License for the specific language governing permissions and
 15  
  *  limitations under the License.
 16  
  *
 17  
  */
 18  
 package org.owasp.dependencycheck.org.apache.tools.ant.launch;
 19  
 
 20  
 import java.net.MalformedURLException;
 21  
 import java.net.URL;
 22  
 import java.io.File;
 23  
 import java.io.FilenameFilter;
 24  
 import java.io.ByteArrayOutputStream;
 25  
 import java.io.UnsupportedEncodingException;
 26  
 import java.text.CharacterIterator;
 27  
 import java.text.StringCharacterIterator;
 28  
 import java.util.Locale;
 29  
 
 30  
 import org.owasp.dependencycheck.org.apache.tools.ant.util.FileUtils;
 31  
 
 32  
 // CheckStyle:LineLengthCheck OFF - urls are long!
 33  
 /**
 34  
  * The Locator is a utility class which is used to find certain items
 35  
  * in the environment.
 36  
  *
 37  
  * It is used at boot time in the launcher, and cannot make use of any of Ant's other classes.
 38  
  *
 39  
  * This is a surprisingly brittle piece of code, and has had lots of bugs filed against it.
 40  
  * {@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>}
 41  
  * {@link <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=8031">use File.toURI().toURL().toExternalForm()</a>}
 42  
  * {@link <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=42222">Locator implementation not encoding URI strings properly: spaces in paths</a>}
 43  
  * It also breaks Eclipse 3.3 Betas
 44  
  * {@link <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=183283">Exception if installation path has spaces</a>}
 45  
  *
 46  
  * Be very careful when making changes to this class, as a break will upset a lot of people.
 47  
  * @since Ant 1.6
 48  
  */
 49  
 // CheckStyle:LineLengthCheck ON - urls are long!
 50  
 public final class Locator {
 51  
 
 52  
     private static final int NIBBLE = 4;
 53  
     private static final int NIBBLE_MASK   = 0xF;
 54  
 
 55  
     private static final int ASCII_SIZE = 128;
 56  
 
 57  
     private static final int BYTE_SIZE = 256;
 58  
 
 59  
     private static final int WORD = 16;
 60  
 
 61  
     private static final int SPACE = 0x20;
 62  
     private static final int DEL = 0x7F;
 63  
 
 64  
     /**
 65  
      * encoding used to represent URIs
 66  
      */
 67  
     public static final String URI_ENCODING = "UTF-8";
 68  
     // stolen from org.apache.xerces.impl.XMLEntityManager#getUserDir()
 69  
     // of the Xerces-J team
 70  
     // which ASCII characters need to be escaped
 71  0
     private static boolean[] gNeedEscaping = new boolean[ASCII_SIZE];
 72  
     // the first hex character if a character needs to be escaped
 73  0
     private static char[] gAfterEscaping1 = new char[ASCII_SIZE];
 74  
     // the second hex character if a character needs to be escaped
 75  0
     private static char[] gAfterEscaping2 = new char[ASCII_SIZE];
 76  0
     private static char[] gHexChs = {'0', '1', '2', '3', '4', '5', '6', '7',
 77  
                                      '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
 78  
     /** Error string used when an invalid uri is seen */
 79  
     public static final String ERROR_NOT_FILE_URI
 80  
         = "Can only handle valid file: URIs, not ";
 81  
 
 82  
     // initialize the above 3 arrays
 83  
     static {
 84  0
         for (int i = 0; i < SPACE; i++) {
 85  0
             gNeedEscaping[i] = true;
 86  0
             gAfterEscaping1[i] = gHexChs[i >> NIBBLE];
 87  0
             gAfterEscaping2[i] = gHexChs[i & NIBBLE_MASK];
 88  
         }
 89  0
         gNeedEscaping[DEL] = true;
 90  0
         gAfterEscaping1[DEL] = '7';
 91  0
         gAfterEscaping2[DEL] = 'F';
 92  0
         char[] escChs = {' ', '<', '>', '#', '%', '"', '{', '}',
 93  
                          '|', '\\', '^', '~', '[', ']', '`'};
 94  0
         int len = escChs.length;
 95  
         char ch;
 96  0
         for (int i = 0; i < len; i++) {
 97  0
             ch = escChs[i];
 98  0
             gNeedEscaping[ch] = true;
 99  0
             gAfterEscaping1[ch] = gHexChs[ch >> NIBBLE];
 100  0
             gAfterEscaping2[ch] = gHexChs[ch & NIBBLE_MASK];
 101  
         }
 102  0
     }
 103  
     /**
 104  
      * Not instantiable
 105  
      */
 106  0
     private Locator() {
 107  0
     }
 108  
 
 109  
     /**
 110  
      * Find the directory or jar file the class has been loaded from.
 111  
      *
 112  
      * @param c the class whose location is required.
 113  
      * @return the file or jar with the class or null if we cannot
 114  
      *         determine the location.
 115  
      *
 116  
      * @since Ant 1.6
 117  
      */
 118  
     public static File getClassSource(Class<?> c) {
 119  0
         String classResource = c.getName().replace('.', '/') + ".class";
 120  0
         return getResourceSource(c.getClassLoader(), classResource);
 121  
     }
 122  
 
 123  
     /**
 124  
      * Find the directory or jar a given resource has been loaded from.
 125  
      *
 126  
      * @param c the classloader to be consulted for the source.
 127  
      * @param resource the resource whose location is required.
 128  
      *
 129  
      * @return the file with the resource source or null if
 130  
      *         we cannot determine the location.
 131  
      *
 132  
      * @since Ant 1.6
 133  
      */
 134  
     public static File getResourceSource(ClassLoader c, String resource) {
 135  0
         if (c == null) {
 136  0
             c = Locator.class.getClassLoader();
 137  
         }
 138  0
         URL url = null;
 139  0
         if (c == null) {
 140  0
             url = ClassLoader.getSystemResource(resource);
 141  
         } else {
 142  0
             url = c.getResource(resource);
 143  
         }
 144  0
         if (url != null) {
 145  0
             String u = url.toString();
 146  
             try {
 147  0
                 if (u.startsWith("jar:file:")) {
 148  0
                     return new File(fromJarURI(u));
 149  0
                 } else if (u.startsWith("file:")) {
 150  0
                     int tail = u.indexOf(resource);
 151  0
                     String dirName = u.substring(0, tail);
 152  0
                     return new File(fromURI(dirName));
 153  
                 }
 154  0
             } catch (IllegalArgumentException e) {
 155  
                 //unable to determine the URI for reasons unknown.
 156  0
                 return null;
 157  0
             }
 158  
         }
 159  0
         return null;
 160  
     }
 161  
 
 162  
 
 163  
 
 164  
     /**
 165  
      * Constructs a file path from a <code>file:</code> URI.
 166  
      *
 167  
      * <p>Will be an absolute path if the given URI is absolute.</p>
 168  
      *
 169  
      * <p>Prior to Java 1.4,<!-- TODO is JDK version actually relevant? -->
 170  
      * swallows '%' that are not followed by two characters.</p>
 171  
      *
 172  
      * See <a href="http://www.w3.org/TR/xml11/#dt-sysid">dt-sysid</a>
 173  
      * which makes some mention of how
 174  
      * characters not supported by URI Reference syntax should be escaped.
 175  
      *
 176  
      * @param uri the URI designating a file in the local filesystem.
 177  
      * @return the local file system path for the file.
 178  
      * @throws IllegalArgumentException if the URI is malformed or not a legal file: URL
 179  
      * @since Ant 1.6
 180  
      */
 181  
     public static String fromURI(String uri) {
 182  0
         return fromURIJava13(uri);
 183  
         // #buzilla8031: first try Java 1.4.
 184  
         // TODO should use java.net.URI now that we can rely on 1.4...
 185  
         // but check for UNC-related regressions, e.g. #42275
 186  
         // (and remember that \\server\share\file -> file:////server/share/file
 187  
         // rather than -> file://server/share/file as it should;
 188  
         // fixed only in JDK 7's java.nio.file.Path.toUri)
 189  
         // return fromUriJava14(uri);
 190  
     }
 191  
 
 192  
     /**
 193  
      * Java1.4+ code to extract the path from the URI.
 194  
      * @param uri
 195  
      * @return null if a conversion was not possible
 196  
      */
 197  
     /* currently unused:
 198  
     private static String fromUriJava14(String uri) {
 199  
         // Also check for properly formed URIs. Ant formerly recommended using
 200  
         // nonsense URIs such as "file:./foo.xml" in XML includes. You shouldn't
 201  
         // do that (just "foo.xml" is correct) but for compatibility we special-case
 202  
         // things when the path is not absolute, and fall back to the old parsing behavior.
 203  
         if (uri.startsWith("file:/")) {
 204  
             try {
 205  
                 File f = new File(URI.create(encodeURI(uri)));
 206  
                 //bug #42227 forgot to decode before returning
 207  
                 return decodeUri(f.getAbsolutePath());
 208  
             } catch (IllegalArgumentException e) {
 209  
                 // Bad URI, pass this on.
 210  
                 // no, this is downgraded to a warning after various
 211  
                 // JRE bugs surfaced. Hand off
 212  
                 // to our built in code on a failure
 213  
                 //throw new IllegalArgumentException(
 214  
                 //   "Bad URI " + uri + ":" + e.getMessage(), e);
 215  
                 e.printStackTrace();
 216  
             } catch (Exception e) {
 217  
                 // Unexpected exception? Should not happen.
 218  
                 e.printStackTrace();
 219  
             }
 220  
         }
 221  
         return null;
 222  
     }
 223  
      */
 224  
 
 225  
     /**
 226  
      * @param uri uri to expand
 227  
      * @return the decoded URI
 228  
      * @since Ant1.7.1
 229  
      */
 230  
     private static String fromURIJava13(String uri) {
 231  
         // Fallback method for Java 1.3 or earlier.
 232  
 
 233  0
         URL url = null;
 234  
         try {
 235  0
             url = new URL(uri);
 236  0
         } catch (MalformedURLException emYouEarlEx) {
 237  
             // Ignore malformed exception
 238  0
         }
 239  0
         if (url == null || !("file".equals(url.getProtocol()))) {
 240  0
             throw new IllegalArgumentException(ERROR_NOT_FILE_URI + uri);
 241  
         }
 242  0
         StringBuffer buf = new StringBuffer(url.getHost());
 243  0
         if (buf.length() > 0) {
 244  0
             buf.insert(0, File.separatorChar).insert(0, File.separatorChar);
 245  
         }
 246  0
         String file = url.getFile();
 247  0
         int queryPos = file.indexOf('?');
 248  0
         buf.append((queryPos < 0) ? file : file.substring(0, queryPos));
 249  
 
 250  0
         uri = buf.toString().replace('/', File.separatorChar);
 251  
 
 252  0
         if (File.pathSeparatorChar == ';' && uri.startsWith("\\") && uri.length() > 2
 253  
             && Character.isLetter(uri.charAt(1)) && uri.lastIndexOf(':') > -1) {
 254  0
             uri = uri.substring(1);
 255  
         }
 256  0
         String path = null;
 257  
         try {
 258  0
             path = decodeUri(uri);
 259  
             //consider adding the current directory. This is not done when
 260  
             //the path is a UNC name
 261  0
             String cwd = System.getProperty("user.dir");
 262  0
             int posi = cwd.indexOf(':');
 263  0
             boolean pathStartsWithFileSeparator = path.startsWith(File.separator);
 264  0
             boolean pathStartsWithUNC = path.startsWith("" + File.separator + File.separator);
 265  0
             if ((posi > 0) && pathStartsWithFileSeparator && !pathStartsWithUNC) {
 266  0
                 path = cwd.substring(0, posi + 1) + path;
 267  
             }
 268  0
         } catch (UnsupportedEncodingException exc) {
 269  
             // not sure whether this is clean, but this method is
 270  
             // declared not to throw exceptions.
 271  0
             throw new IllegalStateException(
 272  
                 "Could not convert URI " + uri + " to path: "
 273  
                 + exc.getMessage());
 274  0
         }
 275  0
         return path;
 276  
     }
 277  
 
 278  
     /**
 279  
      * Crack a JAR URI.
 280  
      * This method is public for testing; we may delete it without any warning -it is not part of Ant's stable API.
 281  
      * @param uri uri to expand; contains jar: somewhere in it
 282  
      * @return the decoded URI
 283  
      * @since Ant1.7.1
 284  
      */
 285  
     public static String fromJarURI(String uri) {
 286  0
         int pling = uri.indexOf("!/");
 287  0
         String jarName = uri.substring("jar:".length(), pling);
 288  0
         return fromURI(jarName);
 289  
     }
 290  
 
 291  
     /**
 292  
      * Decodes an Uri with % characters.
 293  
      * The URI is escaped
 294  
      * @param uri String with the uri possibly containing % characters.
 295  
      * @return The decoded Uri
 296  
      * @throws UnsupportedEncodingException if UTF-8 is not available
 297  
      * @since Ant 1.7
 298  
      */
 299  
     public static String decodeUri(String uri) throws UnsupportedEncodingException {
 300  0
         if (uri.indexOf('%') == -1) {
 301  0
             return uri;
 302  
         }
 303  0
         ByteArrayOutputStream sb = new ByteArrayOutputStream(uri.length());
 304  0
         CharacterIterator iter = new StringCharacterIterator(uri);
 305  0
         for (char c = iter.first(); c != CharacterIterator.DONE;
 306  0
              c = iter.next()) {
 307  0
             if (c == '%') {
 308  0
                 char c1 = iter.next();
 309  0
                 if (c1 != CharacterIterator.DONE) {
 310  0
                     int i1 = Character.digit(c1, WORD);
 311  0
                     char c2 = iter.next();
 312  0
                     if (c2 != CharacterIterator.DONE) {
 313  0
                         int i2 = Character.digit(c2, WORD);
 314  0
                         sb.write((char) ((i1 << NIBBLE) + i2));
 315  
                     }
 316  
                 }
 317  0
             } else if (c >= 0x0000 && c < 0x0080) {
 318  0
                 sb.write(c);
 319  
             } else { // #50543
 320  0
                 byte[] bytes = String.valueOf(c).getBytes(URI_ENCODING);
 321  0
                 sb.write(bytes, 0, bytes.length);
 322  
             }
 323  
         }
 324  0
         return sb.toString(URI_ENCODING);
 325  
     }
 326  
 
 327  
     /**
 328  
      * Encodes an Uri with % characters.
 329  
      * The URI is escaped
 330  
      * @param path String to encode.
 331  
      * @return The encoded string, according to URI norms
 332  
      * @throws UnsupportedEncodingException if UTF-8 is not available
 333  
      * @since Ant 1.7
 334  
      */
 335  
     public static String encodeURI(String path) throws UnsupportedEncodingException {
 336  0
         int i = 0;
 337  0
         int len = path.length();
 338  0
         int ch = 0;
 339  0
         StringBuffer sb = null;
 340  0
         for (; i < len; i++) {
 341  0
             ch = path.charAt(i);
 342  
             // if it's not an ASCII character, break here, and use UTF-8 encoding
 343  0
             if (ch >= ASCII_SIZE) {
 344  0
                 break;
 345  
             }
 346  0
             if (gNeedEscaping[ch]) {
 347  0
                 if (sb == null) {
 348  0
                     sb = new StringBuffer(path.substring(0, i));
 349  
                 }
 350  0
                 sb.append('%');
 351  0
                 sb.append(gAfterEscaping1[ch]);
 352  0
                 sb.append(gAfterEscaping2[ch]);
 353  
                 // record the fact that it's escaped
 354  0
             } else if (sb != null) {
 355  0
                 sb.append((char) ch);
 356  
             }
 357  
         }
 358  
 
 359  
         // we saw some non-ascii character
 360  0
         if (i < len) {
 361  0
             if (sb == null) {
 362  0
                 sb = new StringBuffer(path.substring(0, i));
 363  
             }
 364  
             // get UTF-8 bytes for the remaining sub-string
 365  0
             byte[] bytes = null;
 366  
             byte b;
 367  0
             bytes = path.substring(i).getBytes(URI_ENCODING);
 368  0
             len = bytes.length;
 369  
 
 370  
             // for each byte
 371  0
             for (i = 0; i < len; i++) {
 372  0
                 b = bytes[i];
 373  
                 // for non-ascii character: make it positive, then escape
 374  0
                 if (b < 0) {
 375  0
                     ch = b + BYTE_SIZE;
 376  0
                     sb.append('%');
 377  0
                     sb.append(gHexChs[ch >> NIBBLE]);
 378  0
                     sb.append(gHexChs[ch & NIBBLE_MASK]);
 379  0
                 } else if (gNeedEscaping[b]) {
 380  0
                     sb.append('%');
 381  0
                     sb.append(gAfterEscaping1[b]);
 382  0
                     sb.append(gAfterEscaping2[b]);
 383  
                 } else {
 384  0
                     sb.append((char) b);
 385  
                 }
 386  
             }
 387  
         }
 388  0
         return sb == null ? path : sb.toString();
 389  
     }
 390  
 
 391  
     /**
 392  
      * Convert a File to a URL.
 393  
      * File.toURL() does not encode characters like #.
 394  
      * File.toURI() has been introduced in java 1.4, so
 395  
      * Ant cannot use it (except by reflection) <!-- TODO no longer true -->
 396  
      * FileUtils.toURI() cannot be used by Locator.java
 397  
      * Implemented this way.
 398  
      * File.toURL() adds file: and changes '\' to '/' for dos OSes
 399  
      * encodeURI converts characters like ' ' and '#' to %DD
 400  
      * @param file the file to convert
 401  
      * @return URL the converted File
 402  
      * @throws MalformedURLException on error
 403  
      * @deprecated since 1.9, use {@link FileUtils#getFileURL(File)}
 404  
      */
 405  
     @Deprecated
 406  
     public static URL fileToURL(File file)
 407  
         throws MalformedURLException {
 408  0
         return new URL(file.toURI().toASCIIString());
 409  
     }
 410  
 
 411  
     /**
 412  
      * Get the File necessary to load the Sun compiler tools. If the classes
 413  
      * are available to this class, then no additional URL is required and
 414  
      * null is returned. This may be because the classes are explicitly in the
 415  
      * class path or provided by the JVM directly.
 416  
      *
 417  
      * @return the tools jar as a File if required, null otherwise.
 418  
      */
 419  
     public static File getToolsJar() {
 420  
         // firstly check if the tools jar is already in the classpath
 421  0
         boolean toolsJarAvailable = false;
 422  
         try {
 423  
             // just check whether this throws an exception
 424  0
             Class.forName("com.sun.tools.javac.Main");
 425  0
             toolsJarAvailable = true;
 426  0
         } catch (Exception e) {
 427  
             try {
 428  0
                 Class.forName("sun.tools.javac.Main");
 429  0
                 toolsJarAvailable = true;
 430  0
             } catch (Exception e2) {
 431  
                 // ignore
 432  0
             }
 433  0
         }
 434  0
         if (toolsJarAvailable) {
 435  0
             return null;
 436  
         }
 437  
         // couldn't find compiler - try to find tools.jar
 438  
         // based on java.home setting
 439  0
         String libToolsJar
 440  
             = File.separator + "lib" + File.separator + "tools.jar";
 441  0
         String javaHome = System.getProperty("java.home");
 442  0
         File toolsJar = new File(javaHome + libToolsJar);
 443  0
         if (toolsJar.exists()) {
 444  
             // Found in java.home as given
 445  0
             return toolsJar;
 446  
         }
 447  0
         if (javaHome.toLowerCase(Locale.ENGLISH).endsWith(File.separator + "jre")) {
 448  0
             javaHome = javaHome.substring(
 449  
                 0, javaHome.length() - "/jre".length());
 450  0
             toolsJar = new File(javaHome + libToolsJar);
 451  
         }
 452  0
         if (!toolsJar.exists()) {
 453  0
             System.out.println("Unable to locate tools.jar. "
 454  
                  + "Expected to find it in " + toolsJar.getPath());
 455  0
             return null;
 456  
         }
 457  0
         return toolsJar;
 458  
     }
 459  
 
 460  
     /**
 461  
      * Get an array of URLs representing all of the jar files in the
 462  
      * given location. If the location is a file, it is returned as the only
 463  
      * element of the array. If the location is a directory, it is scanned for
 464  
      * jar files.
 465  
      *
 466  
      * @param location the location to scan for Jars.
 467  
      *
 468  
      * @return an array of URLs for all jars in the given location.
 469  
      *
 470  
      * @exception MalformedURLException if the URLs for the jars cannot be
 471  
      *            formed.
 472  
      */
 473  
     public static URL[] getLocationURLs(File location)
 474  
          throws MalformedURLException {
 475  0
         return getLocationURLs(location, new String[]{".jar"});
 476  
     }
 477  
 
 478  
     /**
 479  
      * Get an array of URLs representing all of the files of a given set of
 480  
      * extensions in the given location. If the location is a file, it is
 481  
      * returned as the only element of the array. If the location is a
 482  
      * directory, it is scanned for matching files.
 483  
      *
 484  
      * @param location the location to scan for files.
 485  
      * @param extensions an array of extension that are to match in the
 486  
      *        directory search.
 487  
      *
 488  
      * @return an array of URLs of matching files.
 489  
      * @exception MalformedURLException if the URLs for the files cannot be
 490  
      *            formed.
 491  
      */
 492  
     public static URL[] getLocationURLs(File location,
 493  
                                         final String[] extensions)
 494  
          throws MalformedURLException {
 495  0
         URL[] urls = new URL[0];
 496  
 
 497  0
         if (!location.exists()) {
 498  0
             return urls;
 499  
         }
 500  0
         if (!location.isDirectory()) {
 501  0
             urls = new URL[1];
 502  0
             String path = location.getPath();
 503  0
             String littlePath = path.toLowerCase(Locale.ENGLISH);
 504  0
             for (int i = 0; i < extensions.length; ++i) {
 505  0
                 if (littlePath.endsWith(extensions[i])) {
 506  0
                     urls[0] = fileToURL(location);
 507  0
                     break;
 508  
                 }
 509  
             }
 510  0
             return urls;
 511  
         }
 512  0
         File[] matches = location.listFiles(
 513  0
             new FilenameFilter() {
 514  
                 public boolean accept(File dir, String name) {
 515  0
                     String littleName = name.toLowerCase(Locale.ENGLISH);
 516  0
                     for (int i = 0; i < extensions.length; ++i) {
 517  0
                         if (littleName.endsWith(extensions[i])) {
 518  0
                             return true;
 519  
                         }
 520  
                     }
 521  0
                     return false;
 522  
                 }
 523  
             });
 524  0
         urls = new URL[matches.length];
 525  0
         for (int i = 0; i < matches.length; ++i) {
 526  0
             urls[i] = fileToURL(matches[i]);
 527  
         }
 528  0
         return urls;
 529  
     }
 530  
 }