/* * Copyright © 2012-2014 Cask Data, Inc. * * 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. */ package co.cask.cdap.cli.util; import com.google.common.base.Joiner; import com.google.inject.Inject; import java.io.File; import java.util.LinkedList; import java.util.regex.Pattern; import javax.annotation.Nullable; /** * Utilites for file path input. */ public class FilePathResolver { public static final String CDAP_HOME = "CDAP_HOME"; private final File workingDir; private final File homeDir; @Nullable private final File cdapHomeDir; @Inject public FilePathResolver() { this(new File(System.getProperty("user.home")), new File(System.getProperty("user.dir")), System.getenv(CDAP_HOME) == null ? null : new File(System.getenv(CDAP_HOME))); } FilePathResolver(File homeDir, File workingDir, @Nullable File cdapHomeDir) { this.homeDir = homeDir; this.workingDir = workingDir; this.cdapHomeDir = cdapHomeDir; } /** * Resolves a bash-style file path into a {@link File}. * * Handles ".", "..", and "~". * * @param path bash-style path * @return {@link File} of the resolved path */ public File resolvePathToFile(String path) { path = resolveVariables(path); if (path.contains("/") || path.contains("\\")) { path = path.replace("/", File.separator); path = path.replace("\\", File.separator); } // resolve "~" if (path.startsWith("~" + File.separator)) { path = new File(homeDir, path.substring(2)).getAbsolutePath(); } // turn relative paths into absolute if (!new File(path).isAbsolute()) { path = new File(workingDir, path).getAbsolutePath(); } // resolve the "." and ".." in the path String[] tokens = path.split(Pattern.quote(File.separator)); LinkedList<String> finalTokens = new LinkedList<>(); for (String token : tokens) { if (token.equals("..")) { if (!finalTokens.isEmpty()) { finalTokens.removeLast(); } } else if (!token.equals(".")) { finalTokens.addLast(token); } } return new File(File.separator + Joiner.on(File.separator).join(finalTokens)); } private String resolveVariables(String path) { if (cdapHomeDir != null) { path = path.replaceAll("\\$" + CDAP_HOME + "(?=[^a-zA-Z0-9_])", cdapHomeDir.getAbsolutePath()); } return path; } }