blob: db7d62ff46a1b67799f0160448f36b75c5283e61 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.hadoop.fs.shell.find;
import java.io.IOException;
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
import org.apache.hadoop.conf.Configurable;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.shell.PathData;
/**
* Abstract expression for use in the
* {@link org.apache.hadoop.fs.shell.find.Find} command. Provides default
* behavior for a no-argument primary expression.
*/
public abstract class BaseExpression implements Expression, Configurable {
private String[] usage = { "Not yet implemented" };
private String[] help = { "Not yet implemented" };
/** Sets the usage text for this {@link Expression} */
protected void setUsage(String[] usage) {
this.usage = usage;
}
/** Sets the help text for this {@link Expression} */
protected void setHelp(String[] help) {
this.help = help;
}
@Override
public String[] getUsage() {
return this.usage;
}
@Override
public String[] getHelp() {
return this.help;
}
@Override
public void setOptions(FindOptions options) throws IOException {
this.options = options;
for (Expression child : getChildren()) {
child.setOptions(options);
}
}
@Override
public void prepare() throws IOException {
for (Expression child : getChildren()) {
child.prepare();
}
}
@Override
public void finish() throws IOException {
for (Expression child : getChildren()) {
child.finish();
}
}
/** Options passed in from the {@link Find} command. */
private FindOptions options;
/** Hadoop configuration. */
private Configuration conf;
/** Arguments for this expression. */
private LinkedList<String> arguments = new LinkedList<String>();
/** Children of this expression. */
private LinkedList<Expression> children = new LinkedList<Expression>();
/** Return the options to be used by this expression. */
protected FindOptions getOptions() {
return (this.options == null) ? new FindOptions() : this.options;
}
@Override
public void setConf(Configuration conf) {
this.conf = conf;
}
@Override
public Configuration getConf() {
return this.conf;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(getClass().getSimpleName());
sb.append("(");
boolean firstArg = true;
for (String arg : getArguments()) {
if (!firstArg) {
sb.append(",");
} else {
firstArg = false;
}
sb.append(arg);
}
sb.append(";");
firstArg = true;
for (Expression child : getChildren()) {
if (!firstArg) {
sb.append(",");
} else {
firstArg = false;
}
sb.append(child.toString());
}
sb.append(")");
return sb.toString();
}
@Override
public boolean isAction() {
for (Expression child : getChildren()) {
if (child.isAction()) {
return true;
}
}
return false;
}
@Override
public boolean isOperator() {
return false;
}
/**
* Returns the arguments of this expression
*
* @return list of argument strings
*/
protected List<String> getArguments() {
return this.arguments;
}
/**
* Returns the argument at the given position (starting from 1).
*
* @param position
* argument to be returned
* @return requested argument
* @throws IOException
* if the argument doesn't exist or is null
*/
protected String getArgument(int position) throws IOException {
if (position > this.arguments.size()) {
throw new IOException("Missing argument at " + position);
}
String argument = this.arguments.get(position - 1);
if (argument == null) {
throw new IOException("Null argument at position " + position);
}
return argument;
}
/**
* Returns the children of this expression.
*
* @return list of child expressions
*/
protected List<Expression> getChildren() {
return this.children;
}
@Override
public int getPrecedence() {
return 0;
}
@Override
public void addChildren(Deque<Expression> exprs) {
// no children by default, will be overridden by specific expressions.
}
/**
* Add a specific number of children to this expression. The children are
* popped off the head of the expressions.
*
* @param exprs
* deque of expressions from which to take the children
* @param count
* number of children to be added
*/
protected void addChildren(Deque<Expression> exprs, int count) {
for (int i = 0; i < count; i++) {
addChild(exprs.pop());
}
}
/**
* Add a single argument to this expression. The argument is popped off the
* head of the expressions.
*
* @param expr
* child to add to the expression
*/
private void addChild(Expression expr) {
children.push(expr);
}
@Override
public void addArguments(Deque<String> args) {
// no children by default, will be overridden by specific expressions.
}
/**
* Add a specific number of arguments to this expression. The children are
* popped off the head of the expressions.
*
* @param args
* deque of arguments from which to take the argument
* @param count
* number of children to be added
*/
protected void addArguments(Deque<String> args, int count) {
for (int i = 0; i < count; i++) {
addArgument(args.pop());
}
}
/**
* Add a single argument to this expression. The argument is popped off the
* head of the expressions.
*
* @param arg
* argument to add to the expression
*/
protected void addArgument(String arg) {
arguments.add(arg);
}
/**
* Returns the {@link FileStatus} from the {@link PathData} item. If the
* current options require links to be followed then the returned file status
* is that of the linked file.
*
* @param item
* PathData
* @param depth
* current depth in the process directories
* @return FileStatus
*/
protected FileStatus getFileStatus(PathData item, int depth)
throws IOException {
FileStatus fileStatus = item.stat;
if (fileStatus.isSymlink()) {
if (options.isFollowLink() || (options.isFollowArgLink() &&
(depth == 0))) {
Path linkedFile = item.fs.resolvePath(fileStatus.getSymlink());
fileStatus = getFileSystem(item).getFileStatus(linkedFile);
}
}
return fileStatus;
}
/**
* Returns the {@link Path} from the {@link PathData} item.
*
* @param item
* PathData
* @return Path
*/
protected Path getPath(PathData item) throws IOException {
return item.path;
}
/**
* Returns the {@link FileSystem} associated with the {@link PathData} item.
*
* @param item PathData
* @return FileSystem
*/
protected FileSystem getFileSystem(PathData item) throws IOException {
return item.fs;
}
}