org.dita.dost.util.FileUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.dita.dost.util.FileUtils.java

Source

/*
 * This file is part of the DITA Open Toolkit project.
 * See the accompanying license.txt file for applicable licenses.
 */

/*
 * (c) Copyright IBM Corp. 2005 All Rights Reserved.
 */
package org.dita.dost.util;

import static org.apache.commons.io.FilenameUtils.*;
import static org.dita.dost.util.Constants.*;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.util.*;

import org.dita.dost.log.DITAOTJavaLogger;

/**
 * Static file utilities.
 * 
 * @author Wu, Zhi Qiang
 */
public final class FileUtils {

    /**
     * Private default constructor to make class uninstantiable.
     */
    private FileUtils() {
    }

    private static final DITAOTJavaLogger logger = new DITAOTJavaLogger();

    /**
     * Supported image extensions. File extensions contain a leading dot.
     */
    @Deprecated
    private final static List<String> supportedImageExtensions;
    static {
        final List<String> sie = new ArrayList<>();
        final String imageExtensions = Configuration.configuration.get(CONF_SUPPORTED_IMAGE_EXTENSIONS);
        if (imageExtensions != null && imageExtensions.length() > 0) {
            Collections.addAll(sie, imageExtensions.split(CONF_LIST_SEPARATOR));
        } else {
            logger.error("Failed to read supported image extensions from configuration, using defaults.");
            sie.add(FILE_EXTENSION_JPG);
            sie.add(FILE_EXTENSION_GIF);
            sie.add(FILE_EXTENSION_EPS);
            sie.add(FILE_EXTENSION_JPEG);
            sie.add(FILE_EXTENSION_PNG);
            sie.add(FILE_EXTENSION_SVG);
            sie.add(FILE_EXTENSION_TIFF);
            sie.add(FILE_EXTENSION_TIF);
        }
        supportedImageExtensions = Collections.unmodifiableList(sie);
    }

    /**
     * Supported HTML extensions. File extensions contain a leading dot.
     */
    @Deprecated
    private final static List<String> supportedHTMLExtensions;
    static {
        final List<String> she = new ArrayList<>();
        final String extensions = Configuration.configuration.get(CONF_SUPPORTED_HTML_EXTENSIONS);
        if (extensions != null && extensions.length() > 0) {
            Collections.addAll(she, extensions.split(CONF_LIST_SEPARATOR));
        } else {
            logger.error("Failed to read supported HTML extensions from configuration, using defaults.");
            she.add(FILE_EXTENSION_HTML);
            she.add(FILE_EXTENSION_HTM);
        }
        supportedHTMLExtensions = Collections.unmodifiableList(she);
    }

    /**
     * Supported resource file extensions. File extensions contain a leading dot.
     */
    @Deprecated
    private final static List<String> supportedResourceExtensions;
    static {
        final List<String> sre = new ArrayList<>();
        final String extensions = Configuration.configuration.get(CONF_SUPPORTED_RESOURCE_EXTENSIONS);
        if (extensions != null && extensions.length() > 0) {
            Collections.addAll(sre, extensions.split(CONF_LIST_SEPARATOR));
        } else {
            logger.error("Failed to read supported resource file extensions from configuration, using defaults.");
            sre.add(FILE_EXTENSION_SWF);
            sre.add(FILE_EXTENSION_PDF);
        }
        supportedResourceExtensions = Collections.unmodifiableList(sre);
    }

    /**
     * Return if the file is a html file by extension.
     * @param lcasefn file name
     * @return true if is html file and false otherwise
     */
    @Deprecated
    public static boolean isHTMLFile(final String lcasefn) {
        for (final String ext : supportedHTMLExtensions) {
            if (lcasefn.endsWith(ext)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Return if the file is a hhp file by extension.
     * @param lcasefn file name
     * @return true if is hhp file and false otherwise
     */
    public static boolean isHHPFile(final String lcasefn) {
        return (lcasefn.endsWith(FILE_EXTENSION_HHP));
    }

    /**
     * Return if the file is a hhc file by extension.
     * @param lcasefn file name
     * @return true if is hhc file and false otherwise
     */
    public static boolean isHHCFile(final String lcasefn) {
        return (lcasefn.endsWith(FILE_EXTENSION_HHC));
    }

    /**
     * Return if the file is a hhk file by extension.
     * @param lcasefn file name
     * @return true if is hhk file and false otherwise
     */
    public static boolean isHHKFile(final String lcasefn) {
        return (lcasefn.endsWith(FILE_EXTENSION_HHK));
    }

    /**
     * Return if the file is a resource file by its extension.
     * 
     * @param lcasefn file name in lower case.
     * @return {@code true} if file is a resource file, otherwise {@code false}
     */
    @Deprecated
    public static boolean isResourceFile(final String lcasefn) {
        for (final String ext : supportedResourceExtensions) {
            if (lcasefn.endsWith(ext)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Return if the file is a supported image file by extension.
     * @param lcasefn filename
     * @return true if is supported image and false otherwise
     */
    @Deprecated
    public static boolean isSupportedImageFile(final String lcasefn) {
        for (final String ext : supportedImageExtensions) {
            if (lcasefn.endsWith(ext)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Resolves a path reference against a base path.
     * 
     * @param basePath base path
     * @param refPath reference path
     * @return relative path using {@link Constants#UNIX_SEPARATOR} path separator
     */
    @Deprecated
    public static String getRelativeUnixPath(final File basePath, final String refPath) {
        return getRelativePath(basePath.getPath(), refPath, UNIX_SEPARATOR);
    }

    /**
     * Resolves a path reference against a base path.
     * 
     * @param basePath base path
     * @param refPath reference path
     * @return relative path
     */
    public static File getRelativePath(final File basePath, final File refPath) {
        return new File(getRelativePath(basePath.getPath(), refPath.getPath(), File.separator));
    }

    /**
     * Resolves a path reference against a base path.
     * 
     * @param basePath base path
     * @param refPath reference path
     * @return relative path using {@link Constants#UNIX_SEPARATOR} path separator
     */
    @Deprecated
    public static String getRelativeUnixPath(final String basePath, final String refPath) {
        return getRelativePath(basePath, refPath, UNIX_SEPARATOR);
    }

    /**
     * Resolves a path reference against a base path.
     * 
     * @param basePath base path
     * @param refPath reference path
     * @param sep path separator
     * @return relative path using {@link Constants#UNIX_SEPARATOR} path separator
     */
    private static String getRelativePath(final String basePath, final String refPath, final String sep) {
        final StringBuilder upPathBuffer = new StringBuilder(128);
        final StringBuilder downPathBuffer = new StringBuilder(128);
        final StringTokenizer mapTokenizer = new StringTokenizer(normalizePath(basePath, File.separator),
                File.separator);
        final StringTokenizer topicTokenizer = new StringTokenizer(normalizePath(refPath, File.separator),
                File.separator);

        while (mapTokenizer.countTokens() > 1 && topicTokenizer.countTokens() > 1) {
            final String mapToken = mapTokenizer.nextToken();
            final String topicToken = topicTokenizer.nextToken();
            boolean equals = false;
            if (OS_NAME.toLowerCase().contains(OS_NAME_WINDOWS)) {
                //if OS is Windows, we need to ignore case when comparing path names.
                equals = mapToken.equalsIgnoreCase(topicToken);
            } else {
                equals = mapToken.equals(topicToken);
            }

            if (!equals) {
                if (mapToken.endsWith(COLON) || topicToken.endsWith(COLON)) {
                    //the two files are in different disks under Windows
                    return refPath;
                }
                upPathBuffer.append("..");
                upPathBuffer.append(sep);
                downPathBuffer.append(topicToken);
                downPathBuffer.append(sep);
                break;
            }
        }

        while (mapTokenizer.countTokens() > 1) {
            mapTokenizer.nextToken();

            upPathBuffer.append("..");
            upPathBuffer.append(sep);
        }

        while (topicTokenizer.hasMoreTokens()) {
            downPathBuffer.append(topicTokenizer.nextToken());
            if (topicTokenizer.hasMoreTokens()) {
                downPathBuffer.append(sep);
            }
        }

        return upPathBuffer.append(downPathBuffer).toString();
    }

    /**
     * Get relative path to base path.
     * 
     * <p>For {@code foo/bar/baz.txt} return {@code ../../}</p>
     * 
     * @param relativePath relative UNIX path
     * @return relative UNIX path to base path, {@code null} if reference path was a single file
     */
    @Deprecated
    public static String getRelativeUnixPath(final String relativePath) {
        return getRelativePathForPath(relativePath, UNIX_SEPARATOR);
    }

    /**
     * Get relative path to base path.
     * 
     * <p>For {@code foo/bar/baz.txt} return {@code ../../}</p>
     * 
     * @param relativePath relative path
     * @return relative path to base path, {@code null} if reference path was a single file
     */
    public static File getRelativePath(final File relativePath) {
        final String p = getRelativePathForPath(relativePath.getPath(), File.separator);
        return p != null ? new File(p) : null;
    }

    /**
     * Get relative path to base path.
     * 
     * <p>For {@code foo/bar/baz.txt} return {@code ../../}</p>
     * 
     * @param relativePath relative path
     * @param sep path separator
     * @return relative path to base path, {@code null} if reference path was a single file
     */
    private static String getRelativePathForPath(final String relativePath, final String sep) {
        final StringTokenizer tokenizer = new StringTokenizer(
                relativePath.replace(WINDOWS_SEPARATOR, UNIX_SEPARATOR), UNIX_SEPARATOR);
        final StringBuilder buffer = new StringBuilder();
        if (tokenizer.countTokens() == 1) {
            return null;
        } else {
            while (tokenizer.countTokens() > 1) {
                tokenizer.nextToken();
                buffer.append("..");
                buffer.append(sep);
            }
            return buffer.toString();
        }
    }

    /**
     * Normalize topic path base on current directory and href value, by
     * replacing "\\" and "\" with {@link File#separator}, and removing ".", ".."
     * from the file path, with no change to substring behind "#".
     * 
     * @param rootPath root directory path
     * @param relativePath relative path
     * @return resolved topic file
     */
    @Deprecated
    public static String resolveTopic(final File rootPath, final String relativePath) {
        return setFragment(resolve(rootPath, stripFragment(relativePath)).getPath(), getFragment(relativePath));
    }

    /**
     * Normalize topic path base on current directory and href value, by
     * replacing "\\" and "\" with {@link File#separator}, and removing ".", ".."
     * from the file path, with no change to substring behind "#".
     * 
     * @param rootPath root directory path
     * @param relativePath relative path
     * @return resolved topic file
     */
    @Deprecated
    public static String resolveTopic(final String rootPath, final String relativePath) {
        return setFragment(resolve(rootPath, stripFragment(relativePath)).getPath(), getFragment(relativePath));
    }

    @Deprecated
    public static URI resolve(final File rootPath, final URI relativePath) {
        return URLUtils.toURI(resolve(rootPath != null ? rootPath.getPath() : null, relativePath.getPath()));
    }

    /**
     * Resolve file path against a base directory path. Normalize the input file path, by replacing all the '\\', '/' with
     * File.seperator, and removing '..' from the directory.
     * 
     * <p>Note: the substring behind "#" will be removed.</p>
     *  
     * @param basedir base dir, may be {@code null}
     * @param filepath file path
     * @return normalized path
     */
    @Deprecated
    public static File resolve(final String basedir, final String filepath) {
        final File pathname = new File(normalizePath(stripFragment(filepath), File.separator));
        if (basedir == null || basedir.length() == 0) {
            return pathname;
        }
        final String normilizedPath = new File(basedir, pathname.getPath()).getPath();
        return new File(normalizePath(normilizedPath, File.separator));
    }

    @Deprecated
    public static File resolve(final File basedir, final String filepath) {
        return resolve(basedir != null ? basedir.getPath() : null, filepath);
    }

    public static File resolve(final File basedir, final File filepath) {
        return resolve(basedir != null ? basedir.getPath() : null, filepath.getPath());
    }

    /**
     * Remove redundant names ".." and "." from the given path and replace directory separators.
     * 
     * @param path input path
     * @param separator directory separator
     * @return processed path
     */
    private static String normalizePath(final String path, final String separator) {
        final String p = path.replace(WINDOWS_SEPARATOR, separator).replace(UNIX_SEPARATOR, separator);
        // remove "." from the directory.
        final List<String> dirs = new LinkedList<>();
        final StringTokenizer tokenizer = new StringTokenizer(p, separator);
        while (tokenizer.hasMoreTokens()) {
            final String token = tokenizer.nextToken();
            if (!(".".equals(token))) {
                dirs.add(token);
            }
        }

        // remove ".." and the dir name before it.
        int dirNum = dirs.size();
        int i = 0;
        while (i < dirNum) {
            if (i > 0) {
                final String lastDir = dirs.get(i - 1);
                final String dir = dirs.get(i);
                if ("..".equals(dir) && !("..".equals(lastDir))) {
                    dirs.remove(i);
                    dirs.remove(i - 1);
                    dirNum = dirs.size();
                    i = i - 1;
                    continue;
                }
            }

            i++;
        }

        // restore the directory.
        final StringBuilder buff = new StringBuilder(p.length());
        if (p.startsWith(separator + separator)) {
            buff.append(separator).append(separator);
        } else if (p.startsWith(separator)) {
            buff.append(separator);
        }
        final Iterator<String> iter = dirs.iterator();
        while (iter.hasNext()) {
            buff.append(iter.next());
            if (iter.hasNext()) {
                buff.append(separator);
            }
        }
        if (p.endsWith(separator)) {
            buff.append(separator);
        }

        return buff.toString();
    }

    /**
     * Return if the path is absolute.
     * @param path test path
     * @return true if path is absolute and false otherwise.
     */
    public static boolean isAbsolutePath(final String path) {
        if (path == null || path.trim().length() == 0) {
            return false;
        }

        if (File.separator.equals(UNIX_SEPARATOR)) {
            return path.startsWith(UNIX_SEPARATOR);
        } else

        if (File.separator.equals(WINDOWS_SEPARATOR) && path.length() > 2) {
            return path.matches("([a-zA-Z]:|\\\\)\\\\.*");
        }

        return false;
    }

    /**
     * Replace the file extension.
     * @param attValue value to be replaced
     * @param extName value used to replace with
     * @return replaced value
     */
    public static String replaceExtension(final String attValue, final String extName) {
        String fileName;
        int fileExtIndex;
        int index;

        index = attValue.indexOf(SHARP);

        if (attValue.startsWith(SHARP)) {
            return attValue;
        } else if (index != -1) {
            fileName = attValue.substring(0, index);
            fileExtIndex = fileName.lastIndexOf(DOT);
            return (fileExtIndex != -1) ? fileName.substring(0, fileExtIndex) + extName + attValue.substring(index)
                    : attValue;
        } else {
            fileExtIndex = attValue.lastIndexOf(DOT);
            return (fileExtIndex != -1) ? (attValue.substring(0, fileExtIndex) + extName) : attValue;
        }
    }

    /**
     * Get file extension
     * 
     * @param file filename, may contain a URL fragment
     * @return file extensions, {@code null} if no extension was found
     */
    public static String getExtension(final String file) {
        final int index = file.indexOf(SHARP);

        if (file.startsWith(SHARP)) {
            return null;
        } else if (index != -1) {
            final String fileName = file.substring(0, index);
            final int fileExtIndex = fileName.lastIndexOf(DOT);
            return (fileExtIndex != -1) ? fileName.substring(fileExtIndex + 1, fileName.length()) : null;
        } else {
            final int fileExtIndex = file.lastIndexOf(DOT);
            return (fileExtIndex != -1) ? file.substring(fileExtIndex + 1, file.length()) : null;
        }
    }

    /**
     * Get filename from a path.
     * 
     * @param aURLString Windows, UNIX, or URI path, may contain hash fragment
     * @return filename without path or hash fragment
     */
    public static String getName(final String aURLString) {
        int pathnameEndIndex;
        if (isWindows()) {
            if (aURLString.contains(SHARP)) {
                pathnameEndIndex = aURLString.lastIndexOf(SHARP);
            } else {
                pathnameEndIndex = aURLString.lastIndexOf(WINDOWS_SEPARATOR);
                if (pathnameEndIndex == -1) {
                    pathnameEndIndex = aURLString.lastIndexOf(UNIX_SEPARATOR);
                }
            }
        } else {
            if (aURLString.contains(SHARP)) {
                pathnameEndIndex = aURLString.lastIndexOf(SHARP);
            }
            pathnameEndIndex = aURLString.lastIndexOf(UNIX_SEPARATOR);
        }

        String schemaLocation = null;
        if (aURLString.contains(SHARP)) {
            schemaLocation = aURLString.substring(0, pathnameEndIndex);
        } else {
            schemaLocation = aURLString.substring(pathnameEndIndex + 1);
        }

        return schemaLocation;
    }

    /**
     * Test if current platform is Windows
     * 
     * @return {@code true} if platform is Windows, otherwise {@code fasel}
     */
    private static boolean isWindows() {
        final String osName = System.getProperty("os.name");
        return osName.startsWith("Win");

    }

    /**
     * Get base path from a path.
     * 
     * @param aURLString UNIX or URI path
     * @return base path
     */
    public static String getFullPathNoEndSeparator(final String aURLString) {
        final int pathnameStartIndex = aURLString.indexOf(UNIX_SEPARATOR);
        final int pathnameEndIndex = aURLString.lastIndexOf(UNIX_SEPARATOR);
        String aPath = aURLString.substring(pathnameStartIndex, pathnameEndIndex);
        aPath = aURLString.substring(0, pathnameEndIndex);
        return aPath;
    }

    /**
     * Strip fragment part from path.
     * 
     * @param path path
     * @return path without path
     */
    @Deprecated
    public static String stripFragment(final String path) {
        final int i = path.indexOf(SHARP);
        if (i != -1) {
            return path.substring(0, i);
        } else {
            return path;
        }
    }

    /**
     * Set fragment
     * @param path path
     * @param fragment new fragment, may be {@code null}
     * @return path with new fragment
     */
    @Deprecated
    public static String setFragment(final String path, final String fragment) {
        final int i = path.indexOf(SHARP);
        final String p = i != -1 ? path.substring(0, i) : path;
        return p + (fragment != null ? (SHARP + fragment) : "");
    }

    /**
     * Get fragment part from path.
     * 
     * @param path path
     * @return fragment without {@link Constants#SHARP}, {@code null} if no fragment exists
     */
    @Deprecated
    public static String getFragment(final String path) {
        return getFragment(path, null);
    }

    /**
     * Retrieve the topic ID from the path
     * 
     * @param relativePath
     * @return topic ID, may be {@code null}
     */
    @Deprecated
    public static String getTopicID(final String relativePath) {
        final String fragment = getFragment(relativePath);
        if (fragment != null) {
            final String id = fragment.lastIndexOf(SLASH) != -1 ? fragment.substring(0, fragment.lastIndexOf(SLASH))
                    : fragment;
            return id.isEmpty() ? null : id;
        }
        return null;
    }

    /**
     * Retrieve the element ID from the path
     * 
     * @param relativePath
     * @return element ID, may be {@code null}
     */
    @Deprecated
    public static String getElementID(final String relativePath) {
        final String fragment = getFragment(relativePath);
        if (fragment != null) {
            if (fragment.lastIndexOf(SLASH) != -1) {
                final String id = fragment.substring(fragment.lastIndexOf(SLASH) + 1);
                return id.isEmpty() ? null : id;
            }
        }
        return null;
    }

    /**
     * Set the element ID from the path
     * 
     * @param relativePath
     * @param id element ID
     * @return element ID, may be {@code null}
     */
    @Deprecated
    public static String setElementID(final String relativePath, final String id) {
        String topic = getTopicID(relativePath);
        if (topic != null) {
            return setFragment(relativePath, topic + (id != null ? SLASH + id : ""));
        } else if (id == null) {
            return stripFragment(relativePath);
        } else {
            throw new IllegalArgumentException(relativePath);
        }
    }

    /**
     * Get fragment part from path or return default fragment.
     * 
     * @param path path
     * @param defaultValue default fragment value
     * @return fragment without {@link Constants#SHARP}, default value if no fragment exists
     */
    @Deprecated
    public static String getFragment(final String path, final String defaultValue) {
        final int i = path.indexOf(SHARP);
        if (i != -1) {
            return path.substring(i + 1);
        } else {
            return defaultValue;
        }
    }

    /**
     * Determines whether the parent directory contains the child element (a file or directory)
     * 
     * @param directory the file to consider as the parent
     * @param child the file to consider as the child
     * @return true is the candidate leaf is under by the specified composite, otherwise false
     * @throws IOException
     */
    public static boolean directoryContains(final File directory, final File child) {
        final File d = new File(normalize(directory.getAbsolutePath()));
        final File c = new File(normalize(child.getAbsolutePath()));
        if (d.equals(c)) {
            return false;
        } else {
            return c.getPath().startsWith(d.getPath());
        }
    }

}