blob: b922a9ed8eca8b000605274215987adb409b1782 [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.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.util.ReflectionUtils;
import org.apache.hadoop.util.StringUtils;
/**
* Factory class for registering and searching for expressions for use in the
* {@link org.apache.hadoop.fs.shell.find.Find} command.
*/
final class ExpressionFactory {
private static final String REGISTER_EXPRESSION_METHOD = "registerExpression";
private Map<String, Class<? extends Expression>> expressionMap =
new HashMap<String, Class<? extends Expression>>();
private static final ExpressionFactory INSTANCE = new ExpressionFactory();
static ExpressionFactory getExpressionFactory() {
return INSTANCE;
}
/**
* Private constructor to ensure singleton.
*/
private ExpressionFactory() {
}
/**
* Invokes "static void registerExpression(FindExpressionFactory)" on the
* given class. This method abstracts the contract between the factory and the
* expression class. Do not assume that directly invoking registerExpression
* on the given class will have the same effect.
*
* @param expressionClass
* class to allow an opportunity to register
*/
void registerExpression(Class<? extends Expression> expressionClass) {
try {
Method register = expressionClass.getMethod(REGISTER_EXPRESSION_METHOD,
ExpressionFactory.class);
if (register != null) {
register.invoke(null, this);
}
} catch (Exception e) {
throw new RuntimeException(StringUtils.stringifyException(e));
}
}
/**
* Register the given class as handling the given list of expression names.
*
* @param expressionClass
* the class implementing the expression names
* @param names
* one or more command names that will invoke this class
* @throws IOException
* if the expression is not of an expected type
*/
void addClass(Class<? extends Expression> expressionClass,
String... names) throws IOException {
for (String name : names)
expressionMap.put(name, expressionClass);
}
/**
* Determines whether the given expression name represents and actual
* expression.
*
* @param expressionName
* name of the expression
* @return true if expressionName represents an expression
*/
boolean isExpression(String expressionName) {
return expressionMap.containsKey(expressionName);
}
/**
* Get an instance of the requested expression
*
* @param expressionName
* name of the command to lookup
* @param conf
* the Hadoop configuration
* @return the {@link Expression} or null if the expression is unknown
*/
Expression getExpression(String expressionName, Configuration conf) {
if (conf == null)
throw new NullPointerException("configuration is null");
Class<? extends Expression> expressionClass = expressionMap
.get(expressionName);
Expression instance = createExpression(expressionClass, conf);
return instance;
}
/**
* Creates an instance of the requested {@link Expression} class.
*
* @param expressionClass
* {@link Expression} class to be instantiated
* @param conf
* the Hadoop configuration
* @return a new instance of the requested {@link Expression} class
*/
Expression createExpression(
Class<? extends Expression> expressionClass, Configuration conf) {
Expression instance = null;
if (expressionClass != null) {
instance = ReflectionUtils.newInstance(expressionClass, conf);
}
return instance;
}
/**
* Creates an instance of the requested {@link Expression} class.
*
* @param expressionClassname
* name of the {@link Expression} class to be instantiated
* @param conf
* the Hadoop configuration
* @return a new instance of the requested {@link Expression} class
*/
Expression createExpression(String expressionClassname,
Configuration conf) {
try {
Class<? extends Expression> expressionClass = Class.forName(
expressionClassname).asSubclass(Expression.class);
return createExpression(expressionClass, conf);
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException("Invalid classname "
+ expressionClassname);
}
}
}