/** * VMware Continuent Tungsten Replicator * Copyright (C) 2015 VMware, Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Initial developer(s): Robert Hodges * Contributor(s): */ package com.continuent.tungsten.common.file; import java.util.LinkedList; import java.util.List; /** * Implements a class to manipulate generic file system path structures that can * apply to any type of file system-like structure including Linux, Hadoop, and * Zookeeper. */ public class FilePath { private LinkedList<String> elements = new LinkedList<String>(); private boolean absolute; /** Construct a path with no arguments, which creates a root path. */ public FilePath() { this("/"); } /** Constructs a path from a string, which may be a full or partial path. */ public FilePath(String path) { path = path.trim(); if (path.startsWith("/")) absolute = true; else absolute = false; append(path); } /** * Constructs a path from a list of elements and a flag to indicate whether * it is absolute. */ public FilePath(List<String> base, boolean absolute) { this.elements = new LinkedList<String>(base); this.absolute = absolute; } /** Constructs a path from an existing path. */ public FilePath(FilePath base) { this(base.elements, base.isAbsolute()); } /** Constructs a path constructed from an existing path plus a string. */ public FilePath(FilePath base, String subpath) { this(base); append(subpath); } /** Returns the elements that compose the path. */ public List<String> elements() { return elements; } /** Returns the i'th element in the path. */ public String element(int i) { return elements.get(i); } /** * Returns true if this is an absolute path. */ public boolean isAbsolute() { return absolute; } /** * Appends a string, which may consist of one or more elements. */ public FilePath append(String subPath) { String[] subElements = subPath.trim().split("\\/"); for (String subElement : subElements) { appendSub(subElement); } return this; } /** Appends another path to end of this one. */ public FilePath append(FilePath subPath) { return append(subPath.elements()); } /** Appends 0 or more path elements to the end. */ public FilePath append(List<String> subElements) { for (String subElement : subElements) { appendSub(subElement); } return this; } // Append a subsequent single element to an existing path. private void appendSub(String subElement) { if ("".equals(subElement) || ".".equals(subElement)) { // Empty elements and "." add nothing to path. } else if ("..".equals(subElement)) { // A .. moves us up a level by removing the last element on an // absolute path. For relative paths we just add it. if (absolute) { if (elements.size() > 0) { elements.removeLast(); } else throw new IllegalArgumentException( "The .. operator may not step past top element in a absolute path"); } else { elements.add(subElement); } } else { // Anything else gets added to the end. elements.add(subElement); } } /** * Returns a full path with leading "/" if absolute. * * @see java.lang.Object#toString() */ public String toString() { StringBuffer path = new StringBuffer(); if (absolute) path.append("/"); for (int i = 0; i < elements.size(); i++) { if (i > 0) path.append("/"); path.append(elements.get(i)); } return path.toString(); } /** * Returns true if the argument is a FilePath instance and denotes the same * location. {@inheritDoc} * * @see java.lang.Object#equals(java.lang.Object) */ public boolean equals(Object other) { // Return false for obvious cases that cannot be true. if (other == null) return false; else if (!(other instanceof FilePath)) return false; // Convert and test properties carefully. FilePath otherPath = (FilePath) other; if (absolute != otherPath.isAbsolute()) return false; else if (elements.size() != otherPath.elements().size()) return false; for (int i = 0; i < elements.size(); i++) { String myElement = elements.get(i); String otherElement = otherPath.element(i); if (!myElement.equals(otherElement)) return false; } // If we got here we must be equal. return true; } }