All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.sommeri.less4j.utils.URIUtils Maven / Gradle / Ivy

Go to download

Less language is an extension of css and less4j compiles it into regular css. It adds several dynamic features into css: variables, expressions, nested rules. Less4j is a port. The original compiler was written in JavaScript and is called less.js. The less language is mostly defined in less.js documentation/issues and by what less.js actually do. Links to less.js: * home page: http://lesscss.org/ * source code & issues: https://github.com/cloudhead/less.js

There is a newer version: 1.17.2
Show newest version
package com.github.sommeri.less4j.utils;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.regex.Pattern;

import org.apache.commons.io.FilenameUtils;

import com.github.sommeri.less4j.LessSource;
import com.github.sommeri.less4j.LessSource.FileSource;
import com.github.sommeri.less4j.platform.Constants;

public class URIUtils {

  public static final String URI_FILE_SEPARATOR = "/";

  public static URL toParentURL(URL url) {
    String path = url.getPath();
    int i = path.lastIndexOf(URI_FILE_SEPARATOR);
    if (i != -1) {
      path = path.substring(0, i + 1);
    }
    try {
      return new URL(url, path + url.getQuery());
    } catch (MalformedURLException ex) {
      throw new RuntimeException(ex);
    }
  }

  public static String relativize(File from, File to) {
    URI fromURI = from.toURI();
    URI toURI = to.toURI();

    String relative = getRelativePath(fromURI.toString(), toURI.toString(), URIUtils.URI_FILE_SEPARATOR);
    relative = convertUriToPlatformSeparator(relative);

    return relative;
  }

  public static String relativizeSourceURIs(LessSource from, LessSource to) {
    if (to == null)
      return "";

    if (to.getURI() == null)
      return to.getName() == null ? "" : to.getName();

    if (from == null || from.getURI() == null)
      return to.getURI().toString();

    String fromURI = from.getURI().toString();
    String toURI = to.getURI().toString();

    return getRelativePath(fromURI, toURI, URIUtils.URI_FILE_SEPARATOR);
  }

  public static String convertUriToPlatformSeparator(String relative) {
    return relative.replace(URI_FILE_SEPARATOR, Constants.FILE_SEPARATOR);
  }

  public static String convertPlatformSeparatorToUri(String relative) {
    return relative.replace(Constants.FILE_SEPARATOR, URI_FILE_SEPARATOR);
  }

  /**
   * taken from stackoverflow:
   * http://stackoverflow.com/questions/204784/how-to-construct
   * -a-relative-path-in-java-from-two-absolute-paths-or-urls
   * 
   * Get the relative path from one file to another, specifying the directory
   * separator. If one of the provided resources does not exist, it is assumed
   * to be a file unless it ends with '/' or '\'.
   * 
   * @param basePath
   *          basePath is calculated from this file
   * @param targetPath
   *          targetPath is calculated to this file
   * @param pathSeparator
   *          directory separator. The platform default is not assumed so that
   *          we can test Unix behaviour when running on Windows (for example)
   * 
   * @return
   */
  public static String getRelativePath(String basePath, String targetPath, String pathSeparator) {

    // Normalize the paths
    String normalizedTargetPath = normalizeNoEndSeparator(targetPath, pathSeparator);
    String normalizedBasePath = normalizeNoEndSeparator(basePath, pathSeparator);
    
    if (normalizedTargetPath==null)
      return "";
    
    if (normalizedBasePath==null)
      return targetPath;

    String[] base = normalizedBasePath.split(Pattern.quote(pathSeparator));
    String[] target = normalizedTargetPath.split(Pattern.quote(pathSeparator));

    // First get all the common elements. Store them as a string,
    // and also count how many of them there are.
    StringBuffer common = new StringBuffer();

    int commonIndex = 0;
    while (commonIndex < target.length && commonIndex < base.length && target[commonIndex].equals(base[commonIndex])) {
      common.append(target[commonIndex] + pathSeparator);
      commonIndex++;
    }

    if (commonIndex == 0) {
      // No single common path element. This most
      // likely indicates differing drive letters, like C: and D:.
      // These paths cannot be relativized.
      return normalizedTargetPath;
      //      throw new PathResolutionException("No common path element found for '" + normalizedTargetPath + "' and '" + normalizedBasePath + "'");
    }

    // The number of directories we have to backtrack depends on whether the base is a file or a dir
    // For example, the relative path from
    //
    // /foo/bar/baz/gg/ff to /foo/bar/baz
    // 
    // ".." if ff is a file
    // "../.." if ff is a directory
    //
    // The following is a heuristic to figure out if the base refers to a file or dir. It's not perfect, because
    // the resource referred to by this path may not actually exist, but it's the best I can do
    boolean baseIsFile = true;

    File baseResource = new File(normalizedBasePath);

    if (baseResource.exists()) {
      baseIsFile = baseResource.isFile();

    } else if (basePath.endsWith(pathSeparator)) {
      baseIsFile = false;
    }

    StringBuffer relative = new StringBuffer();

    if (base.length != commonIndex) {
      int numDirsUp = baseIsFile ? base.length - commonIndex - 1 : base.length - commonIndex;

      for (int i = 0; i < numDirsUp; i++) {
        relative.append(".." + pathSeparator);
      }
    }
    relative.append(safeSubstring(normalizedTargetPath, common.length()));
    return relative.toString();
  }

  public static String normalizeNoEndSeparator(String path, String separator) {
    String result = RelativeFilenameUtils.normalizeNoEndSeparator(path);

    // Undo the changes to the separators made by normalization
    if (separator.equals("/")) {
      result = FilenameUtils.separatorsToUnix(result);

    } else if (separator.equals("\\")) {
      result = FilenameUtils.separatorsToWindows(result);
    } else {
      throw new IllegalArgumentException("Unrecognised dir separator '" + separator + "'");
    }

    return result;
  }

  private static String safeSubstring(String string, int beginIndex) {
    if (beginIndex > string.length())
      return "";

    return string.substring(beginIndex);
  }

  public static String addPLatformSlashIfNeeded(String directory) {
    if (directory.endsWith(Constants.FILE_SEPARATOR))
      return directory;

    return directory + Constants.FILE_SEPARATOR;
  }

  public static URI changeSuffix(URI uri, String dottedSuffix) {
    if (uri==null)
      return null;
    
    String newPath = changeSuffix(uri.getPath(), dottedSuffix);
    try {
      URI result = new URI(uri.getScheme(),uri.getUserInfo(), uri.getHost(), uri.getPort(), newPath, null, null);
      return result;
    } catch (URISyntaxException ex) {
      //TODO do something more reasonable, maybe return null?
      throw new IllegalStateException(ex);
    }
  }

  public static String changeSuffix(String filename, String dottedSuffix) {
    if (filename == null)
      return null;

    int lastIndexOf = filename.lastIndexOf('.');
    if (lastIndexOf == -1)
      return filename + dottedSuffix;

    return filename.substring(0, lastIndexOf) + dottedSuffix;
  }

  public static String addSuffix(String filename, String dottedSuffix) {
    if (filename == null)
      return null;

    return filename + dottedSuffix;
  }

  public static File changeSuffix(File file, String dottedSuffix) {
    if (file == null)
      return null;

    String filename = changeSuffix(file.toString(), dottedSuffix);
    return new File(filename);
  }

  public static FileSource changeSuffix(FileSource source, String dottedSuffix) {
    if (source == null)
      return null;

    return new LessSource.FileSource(changeSuffix(source.getInputFile(), dottedSuffix));
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy