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

com.github.sommeri.less4j.utils.RelativeFilenameUtils 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 org.apache.commons.io.FilenameUtils;

//copied from org.apache.commons.io.FilenameUtils.doNormalize and customized
public class RelativeFilenameUtils {

  private static final char SYSTEM_SEPARATOR = File.separatorChar;
  private static final char UNIX_SEPARATOR = '/';
  private static final char WINDOWS_SEPARATOR = '\\';
  private static final char OTHER_SEPARATOR;
  static {
    if (SYSTEM_SEPARATOR == WINDOWS_SEPARATOR) {
      OTHER_SEPARATOR = UNIX_SEPARATOR;
    } else {
      OTHER_SEPARATOR = WINDOWS_SEPARATOR;
    }
  }

  public static String normalizeNoEndSeparator(String filename) {
    return doNormalize(filename, SYSTEM_SEPARATOR, false);
  }

  private static String doNormalize(String filename, char separator, boolean keepSeparator) {
    if (filename == null) {
      return null;
    }
    int size = filename.length();
    if (size == 0) {
      return filename;
    }
    int prefix = FilenameUtils.getPrefixLength(filename);
    if (prefix < 0) {
      return null;
    }

    char[] array = new char[size + 2]; // +1 for possible extra slash, +2 for arraycopy
    filename.getChars(0, filename.length(), array, 0);

    // fix separators throughout
    char otherSeparator = separator == SYSTEM_SEPARATOR ? OTHER_SEPARATOR : SYSTEM_SEPARATOR;
    for (int i = 0; i < array.length; i++) {
      if (array[i] == otherSeparator) {
        array[i] = separator;
      }
    }

    // add extra separator on the end to simplify code below
    boolean lastIsDirectory = true;
    if (array[size - 1] != separator) {
      array[size++] = separator;
      lastIsDirectory = false;
    }

    // adjoining slashes
    for (int i = prefix + 1; i < size; i++) {
      if (array[i] == separator && array[i - 1] == separator) {
        System.arraycopy(array, i, array, i - 1, size - i);
        size--;
        i--;
      }
    }

    // dot slash
    for (int i = prefix + 1; i < size; i++) {
      if (array[i] == separator && array[i - 1] == '.' && (i == prefix + 1 || array[i - 2] == separator)) {
        if (i == size - 1) {
          lastIsDirectory = true;
        }
        System.arraycopy(array, i + 1, array, i - 1, size - i);
        size -= 2;
        i--;
      }
    }

    // double dot slash
    outer: for (int i = prefix + 2; i < size; i++) {
      if (isEndOfClimbUp(array, i, separator) && (i == prefix + 2 || array[i - 3] == separator)) {
        //if (located in the beginning or after drive or server name)
        if (i == prefix + 2) {
          // Modified by SomMeri to allow relative paths
          //return null;
          continue outer;
        }
        if (i == size - 1) {
          lastIsDirectory = true;
        }
        if (isEndOfClimbUp(array, i - 3, separator)) {
          // We reached previous climb up. That can happen only if we are at the 
          // beginning of the path and the path is starting with some climbs. e.g.
          // path looks somewhat like this: ../../something
          //
          // We cannot climb further, so no action is needed.
        } else {
          int j;
          for (j = i - 4; j >= prefix; j--) {
            if (array[j] == separator) {
              // remove b/../ from a/b/../c
              System.arraycopy(array, i + 1, array, j + 1, size - i);
              size -= i - j;
              i = j + 1;
              continue outer;
            }
          }
          // remove a/../ from a/../c
          System.arraycopy(array, i + 1, array, prefix, size - i);
          size -= i + 1 - prefix;
          i = prefix + 1;
        }
      }
    }

    if (size <= 0) { // should never be less than 0
      return "";
    }
    if (size <= prefix) { // should never be less than prefix
      return new String(array, 0, size);
    }
    if (lastIsDirectory && keepSeparator) {
      return new String(array, 0, size); // keep trailing separator
    }
    return new String(array, 0, size - 1); // lose trailing separator
  }

  private static boolean isEndOfClimbUp(char[] array, int position, char separator) {
    return array[position] == separator && array[position - 1] == '.' && array[position - 2] == '.';
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy