CodeLocations.java

  1. package org.jbehave.core.io;

  2. import static org.apache.commons.lang3.StringUtils.removeEnd;
  3. import static org.apache.commons.lang3.StringUtils.removeStart;

  4. import java.io.File;
  5. import java.net.URI;
  6. import java.net.URISyntaxException;
  7. import java.net.URL;

  8. /**
  9.  * Collection of utility methods to create code location URLs
  10.  */
  11. public class CodeLocations {

  12.     /**
  13.      * Creates a code location URL from a class
  14.      *
  15.      * @param codeLocationClass the class
  16.      * @return A URL created from Class
  17.      * @throws InvalidCodeLocation if URL creation fails
  18.      */
  19.     public static URL codeLocationFromClass(Class<?> codeLocationClass) {
  20.         String pathOfClass = codeLocationClass.getName().replace(".", "/") + ".class";
  21.         URL classResource = codeLocationClass.getClassLoader().getResource(pathOfClass);
  22.         String codeLocationPath = removeEnd(getPathFromURL(classResource), pathOfClass);
  23.         if (codeLocationPath.endsWith(".jar!/")) {
  24.             codeLocationPath = removeEnd(codeLocationPath, "!/");
  25.         }
  26.         return codeLocationFromPath(codeLocationPath);
  27.     }

  28.     /**
  29.      * Creates a code location URL from a file path
  30.      *
  31.      * @param filePath the file path
  32.      * @return A URL created from File
  33.      * @throws InvalidCodeLocation if URL creation fails
  34.      */
  35.     public static URL codeLocationFromPath(String filePath) {
  36.         try {
  37.             return new File(filePath).toURI().toURL();
  38.         } catch (Exception e) {
  39.             throw new InvalidCodeLocation(filePath);
  40.         }
  41.     }

  42.     /**
  43.      * Creates a code location URL from a URL
  44.      *
  45.      * @param url the URL external form
  46.      * @return A URL created from URL
  47.      * @throws InvalidCodeLocation if URL creation fails
  48.      */
  49.     public static URL codeLocationFromURL(String url) {
  50.         try {
  51.             return new URL(url);
  52.         } catch (Exception e) {
  53.             throw new InvalidCodeLocation(url);
  54.         }
  55.     }

  56.     @SuppressWarnings("serial")
  57.     public static class InvalidCodeLocation extends RuntimeException {

  58.         public InvalidCodeLocation(String path) {
  59.             super(path);
  60.         }

  61.     }

  62.     /**
  63.      * Get absolute path from URL objects starting with file:
  64.      * This method takes care of decoding %-encoded chars, e.g. %20 -> space etc
  65.      * Since we do not use a File object, the system specific path encoding
  66.      * is not used (e.g. C:\ on Windows). This is necessary to facilitate
  67.      * the removal of a class file with path in codeLocationFromClass
  68.      *
  69.      * @param url the file-URL
  70.      * @return String absolute decoded path
  71.      * @throws InvalidCodeLocation if URL contains format errors
  72.      */
  73.     public static String getPathFromURL(URL url) {
  74.         URI uri;
  75.         try {
  76.             uri = url.toURI();
  77.         } catch (URISyntaxException e) {
  78.             // this will probably not happen since the url was created
  79.             // from a filename beforehand
  80.             throw new InvalidCodeLocation(e.toString());
  81.         }

  82.         if (uri.toString().startsWith("file:") || uri.toString().startsWith("jar:")) {
  83.             return removeStart(uri.getSchemeSpecificPart(),"file:");
  84.         } else {
  85.             // this is wrong, but should at least give a
  86.             // helpful error when trying to open the file later
  87.             return uri.toString();
  88.         }
  89.     }

  90. }