azkaban-aplcache
Changes
src/java/azkaban/project/Project.java 30(+11 -19)
src/java/azkaban/project/ProjectManager.java 32(+16 -16)
src/java/azkaban/user/XmlUserManager.java 95(+53 -42)
src/java/azkaban/utils/JSONUtils.java 54(+23 -31)
src/java/azkaban/utils/Pair.java 6(+3 -3)
src/java/azkaban/utils/Props.java 1847(+920 -927)
src/java/azkaban/utils/Utils.java 268(+137 -131)
src/java/azkaban/webapp/servlet/AbstractAzkabanServlet.java 576(+301 -275)
src/java/azkaban/webapp/servlet/Page.java 101(+50 -51)
Details
src/java/azkaban/project/Project.java 30(+11 -19)
diff --git a/src/java/azkaban/project/Project.java b/src/java/azkaban/project/Project.java
index 316b11b..e17720a 100644
--- a/src/java/azkaban/project/Project.java
+++ b/src/java/azkaban/project/Project.java
@@ -136,12 +136,9 @@ public class Project {
Map<String, Object> projectObject = (Map<String, Object>) object;
String name = (String) projectObject.get("name");
String description = (String) projectObject.get("description");
- String lastModifiedUser = (String) projectObject
- .get("lastModifiedUser");
- long createTimestamp = coerceToLong(projectObject
- .get("createTimestamp"));
- long lastModifiedTimestamp = coerceToLong(projectObject
- .get("lastModifiedTimestamp"));
+ String lastModifiedUser = (String) projectObject.get("lastModifiedUser");
+ long createTimestamp = coerceToLong(projectObject.get("createTimestamp"));
+ long lastModifiedTimestamp = coerceToLong(projectObject.get("lastModifiedTimestamp"));
String source = (String)projectObject.get("source");
Project project = new Project(name);
@@ -191,20 +188,12 @@ public class Project {
public int hashCode() {
final int prime = 31;
int result = 1;
- result = prime * result
- + (int) (createTimestamp ^ (createTimestamp >>> 32));
- result = prime * result
- + ((description == null) ? 0 : description.hashCode());
- result = prime
- * result
- + (int) (lastModifiedTimestamp ^ (lastModifiedTimestamp >>> 32));
- result = prime
- * result
- + ((lastModifiedUser == null) ? 0 : lastModifiedUser.hashCode());
+ result = prime * result + (int) (createTimestamp ^ (createTimestamp >>> 32));
+ result = prime * result + ((description == null) ? 0 : description.hashCode());
+ result = prime * result + (int) (lastModifiedTimestamp ^ (lastModifiedTimestamp >>> 32));
+ result = prime * result + ((lastModifiedUser == null) ? 0 : lastModifiedUser.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
- result = prime
- * result
- + ((userToPermission == null) ? 0 : userToPermission.hashCode());
+ result = prime * result + ((userToPermission == null) ? 0 : userToPermission.hashCode());
return result;
}
@@ -216,14 +205,17 @@ public class Project {
return false;
if (getClass() != obj.getClass())
return false;
+
Project other = (Project) obj;
if (createTimestamp != other.createTimestamp)
return false;
+
if (description == null) {
if (other.description != null)
return false;
} else if (!description.equals(other.description))
return false;
+
if (lastModifiedTimestamp != other.lastModifiedTimestamp)
return false;
if (lastModifiedUser == null) {
src/java/azkaban/project/ProjectManager.java 32(+16 -16)
diff --git a/src/java/azkaban/project/ProjectManager.java b/src/java/azkaban/project/ProjectManager.java
index d135d94..43f654c 100644
--- a/src/java/azkaban/project/ProjectManager.java
+++ b/src/java/azkaban/project/ProjectManager.java
@@ -7,20 +7,20 @@ import azkaban.user.User;
import azkaban.utils.Props;
public interface ProjectManager {
-
- public List<String> getProjectNames();
-
- public List<Project> getProjects(User user);
-
- public void commitProject(String name) throws ProjectManagerException;
-
- public Project getProject(String name, User user);
-
- public void uploadProject(String projectName, File projectDir, User uploader, boolean force) throws ProjectManagerException;
-
- public Project createProject(String projectName, String description, User creator) throws ProjectManagerException;
-
- public Project removeProject(String projectName, User user) throws ProjectManagerException;
-
- public Props getProperties(String projectName, String source, User user) throws ProjectManagerException;
+
+ public List<String> getProjectNames();
+
+ public List<Project> getProjects(User user);
+
+ public void commitProject(String name) throws ProjectManagerException;
+
+ public Project getProject(String name, User user);
+
+ public void uploadProject(String projectName, File projectDir, User uploader, boolean force) throws ProjectManagerException;
+
+ public Project createProject(String projectName, String description, User creator) throws ProjectManagerException;
+
+ public Project removeProject(String projectName, User user) throws ProjectManagerException;
+
+ public Props getProperties(String projectName, String source, User user) throws ProjectManagerException;
}
\ No newline at end of file
src/java/azkaban/user/XmlUserManager.java 95(+53 -42)
diff --git a/src/java/azkaban/user/XmlUserManager.java b/src/java/azkaban/user/XmlUserManager.java
index 8e0b30e..21968a4 100644
--- a/src/java/azkaban/user/XmlUserManager.java
+++ b/src/java/azkaban/user/XmlUserManager.java
@@ -18,20 +18,19 @@ import org.xml.sax.SAXException;
import azkaban.utils.Props;
/**
- * Xml implementation of the UserManager.
- * Looks for the property user.manager.xml.file in the azkaban properties.
+ * Xml implementation of the UserManager. Looks for the property
+ * user.manager.xml.file in the azkaban properties.
*
- * The xml to be in the following form:
- * <azkaban-users>
- * <user username="username" password="azkaban" roles="admin" groups="azkaban"/>
+ * The xml to be in the following form: <azkaban-users> <user
+ * username="username" password="azkaban" roles="admin" groups="azkaban"/>
* </azkaban-users>
*
* @author rpark
- *
+ *
*/
public class XmlUserManager implements UserManager {
- private static final Logger logger = Logger.getLogger(XmlUserManager.class.getName());
-
+ private static final Logger logger = Logger.getLogger(XmlUserManager.class.getName());
+
public static final String XML_FILE_PARAM = "user.manager.xml.file";
public static final String AZKABAN_USERS_TAG = "azkaban-users";
public static final String USER_TAG = "user";
@@ -43,10 +42,10 @@ public class XmlUserManager implements UserManager {
public static final String GROUPS_ATTR = "groups";
private String xmlPath;
-
+
private HashMap<String, User> users;
private HashMap<String, String> userPassword;
-
+
/**
* The constructor.
*
@@ -54,41 +53,48 @@ public class XmlUserManager implements UserManager {
*/
public XmlUserManager(Props props) {
xmlPath = props.getString(XML_FILE_PARAM);
-
+
parseXMLFile();
}
-
+
private void parseXMLFile() {
File file = new File(xmlPath);
if (!file.exists()) {
- throw new IllegalArgumentException("User xml file " + xmlPath + " doesn't exist.");
+ throw new IllegalArgumentException("User xml file " + xmlPath
+ + " doesn't exist.");
}
-
+
HashMap<String, User> users = new HashMap<String, User>();
HashMap<String, String> userPassword = new HashMap<String, String>();
-
+
// Creating the document builder to parse xml.
- DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
+ DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory
+ .newInstance();
DocumentBuilder builder = null;
try {
builder = docBuilderFactory.newDocumentBuilder();
} catch (ParserConfigurationException e) {
- throw new IllegalArgumentException("Exception while parsing user xml. Document builder not created.", e);
+ throw new IllegalArgumentException(
+ "Exception while parsing user xml. Document builder not created.",
+ e);
}
-
+
Document doc = null;
try {
doc = builder.parse(file);
} catch (SAXException e) {
- throw new IllegalArgumentException("Exception while parsing " + xmlPath + ". Invalid XML.", e);
+ throw new IllegalArgumentException("Exception while parsing "
+ + xmlPath + ". Invalid XML.", e);
} catch (IOException e) {
- throw new IllegalArgumentException("Exception while parsing " + xmlPath + ". Error reading file.", e);
+ throw new IllegalArgumentException("Exception while parsing "
+ + xmlPath + ". Error reading file.", e);
}
-
- // Only look at first item, because we should only be seeing azkaban-users tag.
+
+ // Only look at first item, because we should only be seeing
+ // azkaban-users tag.
NodeList tagList = doc.getChildNodes();
Node azkabanUsers = tagList.item(0);
-
+
NodeList azkabanUsersList = azkabanUsers.getChildNodes();
for (int i = 0; i < azkabanUsersList.getLength(); ++i) {
Node node = azkabanUsersList.item(i);
@@ -98,25 +104,28 @@ public class XmlUserManager implements UserManager {
}
}
}
-
+
// Synchronize the swap. Similarly, the gets are synchronized to this.
- synchronized(this) {
+ synchronized (this) {
this.users = users;
this.userPassword = userPassword;
}
}
-
+
private void parseUserTag(Node node, HashMap<String, User> users, HashMap<String, String> userPassword) {
NamedNodeMap userAttrMap = node.getAttributes();
Node userNameAttr = userAttrMap.getNamedItem(USERNAME_ATTR);
if (userNameAttr == null) {
- throw new RuntimeException("Error loading user. The username doesn't exist");
+ throw new RuntimeException(
+ "Error loading user. The username doesn't exist");
}
Node passwordAttr = userAttrMap.getNamedItem(PASSWORD_ATTR);
if (passwordAttr == null) {
- throw new RuntimeException("Error loading user. The password doesn't exist for " + passwordAttr);
+ throw new RuntimeException(
+ "Error loading user. The password doesn't exist for "
+ + passwordAttr);
}
-
+
// Add user to the user/password map
String username = userNameAttr.getNodeValue();
String password = passwordAttr.getNodeValue();
@@ -125,50 +134,52 @@ public class XmlUserManager implements UserManager {
User user = new User(userNameAttr.getNodeValue());
users.put(username, user);
logger.info("Loading user " + user.getUserId());
-
+
Node roles = userAttrMap.getNamedItem(ROLES_ATTR);
if (roles != null) {
String value = roles.getNodeValue();
String[] roleSplit = value.split("\\s*,\\s*");
- for (String role: roleSplit) {
+ for (String role : roleSplit) {
user.addRole(role);
}
}
-
+
Node groups = userAttrMap.getNamedItem(GROUPS_ATTR);
if (groups != null) {
String value = groups.getNodeValue();
String[] groupSplit = value.split("\\s*,\\s*");
- for (String group: groupSplit) {
+ for (String group : groupSplit) {
user.addGroup(group);
}
}
}
-
+
@Override
public User getUser(String username, String password) throws UserManagerException {
if (username == null || username.trim().isEmpty()) {
throw new UserManagerException("Username is empty.");
- }
- else if (password == null || password.trim().isEmpty()) {
+ } else if (password == null || password.trim().isEmpty()) {
throw new UserManagerException("Password is empty.");
}
-
- // Minimize the synchronization of the get. Shouldn't matter if it doesn't exist.
+
+ // Minimize the synchronization of the get. Shouldn't matter if it
+ // doesn't exist.
String foundPassword = null;
User user = null;
- synchronized(this) {
+ synchronized (this) {
foundPassword = userPassword.get(username);
if (foundPassword != null) {
user = users.get(username);
}
}
-
+
if (foundPassword == null || !foundPassword.equals(password)) {
throw new UserManagerException("Username/Password not found.");
}
- // Once it gets to this point, no exception has been thrown. User shoudn't be
- // null, but adding this check for if user and user/password hash tables go
+ // Once it gets to this point, no exception has been thrown. User
+ // shoudn't be
+ // null, but adding this check for if user and user/password hash tables
+ // go
// out of sync.
if (user == null) {
throw new UserManagerException("Internal error: User not found.");
src/java/azkaban/utils/JSONUtils.java 54(+23 -31)
diff --git a/src/java/azkaban/utils/JSONUtils.java b/src/java/azkaban/utils/JSONUtils.java
index b99a5a4..80ebde6 100644
--- a/src/java/azkaban/utils/JSONUtils.java
+++ b/src/java/azkaban/utils/JSONUtils.java
@@ -1,6 +1,5 @@
package azkaban.utils;
-
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
@@ -19,11 +18,11 @@ public class JSONUtils {
*/
private JSONUtils() {
}
-
+
public static String toJSON(Object obj) {
return toJSON(obj, false);
}
-
+
public static String toJSON(Object obj, boolean prettyPrint) {
ObjectMapper mapper = new ObjectMapper();
@@ -37,28 +36,28 @@ public class JSONUtils {
throw new RuntimeException(e);
}
}
-
+
public static Object parseJSONFromString(String json) throws IOException {
ObjectMapper mapper = new ObjectMapper();
- JsonFactory factory = new JsonFactory();
- JsonParser parser = factory.createJsonParser(json);
+ JsonFactory factory = new JsonFactory();
+ JsonParser parser = factory.createJsonParser(json);
JsonNode node = mapper.readTree(parser);
-
+
return toObjectFromJSONNode(node);
}
-
+
public static Object parseJSONFromFile(File file) throws IOException {
ObjectMapper mapper = new ObjectMapper();
- JsonFactory factory = new JsonFactory();
- JsonParser parser = factory.createJsonParser(file);
+ JsonFactory factory = new JsonFactory();
+ JsonParser parser = factory.createJsonParser(file);
JsonNode node = mapper.readTree(parser);
-
+
return toObjectFromJSONNode(node);
}
-
+
private static Object toObjectFromJSONNode(JsonNode node) {
if (node.isObject()) {
- HashMap<String, Object> obj = new HashMap<String,Object>();
+ HashMap<String, Object> obj = new HashMap<String, Object>();
Iterator<String> iter = node.getFieldNames();
while (iter.hasNext()) {
String fieldName = iter.next();
@@ -66,10 +65,9 @@ public class JSONUtils {
Object subObj = toObjectFromJSONNode(subNode);
obj.put(fieldName, subObj);
}
-
+
return obj;
- }
- else if (node.isArray()) {
+ } else if (node.isArray()) {
ArrayList<Object> array = new ArrayList<Object>();
Iterator<JsonNode> iter = node.getElements();
while (iter.hasNext()) {
@@ -78,29 +76,23 @@ public class JSONUtils {
array.add(subObject);
}
return array;
- }
- else if (node.isTextual()) {
+ } else if (node.isTextual()) {
return node.asText();
- }
- else if (node.isNumber()) {
+ } else if (node.isNumber()) {
if (node.isInt()) {
return node.asInt();
- }
- else if (node.isLong()) {
+ } else if (node.isLong()) {
return node.asLong();
- }
- else if (node.isDouble()) {
+ } else if (node.isDouble()) {
return node.asDouble();
- }
- else {
- System.err.println("ERROR What is this!? " + node.getNumberType());
+ } else {
+ System.err.println("ERROR What is this!? "
+ + node.getNumberType());
return null;
}
- }
- else if (node.isBoolean()) {
+ } else if (node.isBoolean()) {
return node.asBoolean();
- }
- else {
+ } else {
return null;
}
}
src/java/azkaban/utils/Pair.java 6(+3 -3)
diff --git a/src/java/azkaban/utils/Pair.java b/src/java/azkaban/utils/Pair.java
index 867f845..0d85d02 100644
--- a/src/java/azkaban/utils/Pair.java
+++ b/src/java/azkaban/utils/Pair.java
@@ -3,16 +3,16 @@ package azkaban.utils;
public class Pair<F, S> {
private final F first;
private final S second;
-
+
public Pair(F first, S second) {
this.first = first;
this.second = second;
}
-
+
public F getFirst() {
return first;
}
-
+
public S getSecond() {
return second;
}
src/java/azkaban/utils/Props.java 1847(+920 -927)
diff --git a/src/java/azkaban/utils/Props.java b/src/java/azkaban/utils/Props.java
index dad659b..6dd0a5e 100644
--- a/src/java/azkaban/utils/Props.java
+++ b/src/java/azkaban/utils/Props.java
@@ -42,931 +42,924 @@ import org.apache.log4j.Logger;
* functions and Exception throwing. This class is not threadsafe.
*/
public class Props {
- private final Map<String, String> _current;
- private Props _parent;
- private String source = null;
-
- /**
- * Constructor for empty props with empty parent.
- */
- public Props() {
- this(null);
- }
-
- /**
- * Constructor for empty Props with parent override.
- *
- * @param parent
- */
- public Props(Props parent) {
- this._current = new HashMap<String, String>();
- this._parent = parent;
- }
-
- /**
- * Load props from a file.
- *
- * @param parent
- * @param file
- * @throws IOException
- */
- public Props(Props parent, String filepath) throws IOException {
- this(parent, new File(filepath));
- }
-
- /**
- * Load props from a file.
- *
- * @param parent
- * @param file
- * @throws IOException
- */
- public Props(Props parent, File file) throws IOException {
- this(parent);
- setSource(file.getPath());
-
- InputStream input = new BufferedInputStream(new FileInputStream(file));
- try {
- loadFrom(input);
- }
- catch (IOException e) {
- input.close();
- throw e;
- }
- input.close();
- }
-
- /**
- * Create props from property input streams
- *
- * @param parent
- * @param inputStreams
- * @throws IOException
- */
- public Props(Props parent, InputStream inputStream) throws IOException {
- this(parent);
- loadFrom(inputStream);
- }
-
- /**
- *
- * @param inputStream
- * @throws IOException
- */
- private void loadFrom(InputStream inputStream) throws IOException {
- Properties properties = new Properties();
- properties.load(inputStream);
- this.put(properties);
- }
-
- /**
- * Create properties from maps of properties
- *
- * @param parent
- * @param props
- */
- public Props(Props parent, Map<String, String>... props) {
- this(parent);
- for (int i = props.length - 1; i >= 0; i--) {
- this.putAll(props[i]);
- }
- }
-
- /**
- * Create properties from Properties objects
- *
- * @param parent
- * @param properties
- */
- public Props(Props parent, Properties... properties) {
- this(parent);
- for (int i = properties.length - 1; i >= 0; i--) {
- this.put(properties[i]);
- }
- }
-
- /**
- * Create a Props object with the contents set to that of props.
- *
- * @param parent
- * @param props
- */
- public Props(Props parent, Props props) {
- this(parent);
- if (props != null) {
- putAll(props);
- }
- }
-
- /**
- * Create a Props with a null parent from a list of key value pairing. i.e.
- * [key1, value1, key2, value2 ...]
- *
- * @param args
- * @return
- */
- public static Props of(String... args) {
- return of((Props) null, args);
- }
-
- /**
- * Create a Props from a list of key value pairing. i.e. [key1, value1,
- * key2, value2 ...]
- *
- * @param args
- * @return
- */
- @SuppressWarnings("unchecked")
- public static Props of(Props parent, String... args) {
- if (args.length % 2 != 0) {
- throw new IllegalArgumentException("Must have an equal number of keys and values.");
- }
-
- Map<String, String> vals = new HashMap<String, String>(args.length / 2);
-
- for (int i = 0; i < args.length; i += 2) {
- vals.put(args[i], args[i + 1]);
- }
- return new Props(parent, vals);
- }
-
- /**
- * Clear the current Props, but leaves the parent untouched.
- */
- public void clearLocal() {
- _current.clear();
- }
-
- /**
- * Check key in current Props then search in parent
- *
- * @param k
- * @return
- */
- public boolean containsKey(Object k) {
- return _current.containsKey(k) || (_parent != null && _parent.containsKey(k));
- }
-
- /**
- * Check value in current Props then search in parent
- *
- * @param value
- * @return
- */
- public boolean containsValue(Object value) {
- return _current.containsValue(value) || (_parent != null && _parent.containsValue(value));
- }
-
- /**
- * Return value if available in current Props otherwise return from parent
- *
- * @param key
- * @return
- */
- public String get(Object key) {
- if (_current.containsKey(key)) {
- return _current.get(key);
- }
- else if (_parent != null) {
- return _parent.get(key);
- }
- else {
- return null;
- }
- }
-
- /**
- * Get the key set from the current Props
- *
- * @return
- */
- public Set<String> localKeySet() {
- return _current.keySet();
- }
-
- /**
- * Get parent Props
- *
- * @return
- */
- public Props getParent() {
- return _parent;
- }
-
- /**
- * Put the given string value for the string key. This method performs any
- * variable substitution in the value replacing any occurance of ${name}
- * with the value of get("name").
- *
- * @param key
- * The key to put the value to
- * @param value
- * The value to do substitution on and store
- *
- * @throws IllegalArgumentException
- * If the variable given for substitution is not a valid key in
- * this Props.
- */
- public String put(String key, String value) {
- return _current.put(key, value);
- }
-
- /**
- * Put the given Properties into the Props. This method performs any
- * variable substitution in the value replacing any occurrence of ${name}
- * with the value of get("name"). get() is called first on the Props and
- * next on the Properties object.
- *
- * @param properties
- * The properties to put
- *
- * @throws IllegalArgumentException
- * If the variable given for substitution is not a valid key in
- * this Props.
- */
- public void put(Properties properties) {
- for (String propName : properties.stringPropertyNames()) {
- _current.put(propName, properties.getProperty(propName));
- }
- }
-
- /**
- * Put integer
- *
- * @param key
- * @param value
- * @return
- */
- public String put(String key, Integer value) {
- return _current.put(key, value.toString());
- }
-
- /**
- * Put Long. Stores as String.
- *
- * @param key
- * @param value
- * @return
- */
- public String put(String key, Long value) {
- return _current.put(key, value.toString());
- }
-
- /**
- * Put Double. Stores as String.
- *
- * @param key
- * @param value
- * @return
- */
- public String put(String key, Double value) {
- return _current.put(key, value.toString());
- }
-
- /**
- * Put everything in the map into the props.
- *
- * @param m
- */
- public void putAll(Map<? extends String, ? extends String> m) {
- if (m == null) {
- return;
- }
-
- for (Map.Entry<? extends String, ? extends String> entry : m.entrySet())
- {
- this.put(entry.getKey(), entry.getValue());
- }
- }
-
- /**
- * Put all properties in the props into the current props. Will handle null
- * p.
- *
- * @param p
- */
- public void putAll(Props p) {
- if (p == null) {
- return;
- }
-
- for (String key : p.getKeySet()) {
- this.put(key, p.get(key));
- }
- }
-
- /**
- * Puts only the local props from p into the current properties
- *
- * @param p
- */
- public void putLocal(Props p) {
- for (String key : p.localKeySet()) {
- this.put(key, p.get(key));
- }
- }
-
- /**
- * Remove only the local value of key s, and not the parents.
- *
- * @param s
- * @return
- */
- public String removeLocal(Object s) {
- return _current.remove(s);
- }
-
- /**
- * The number of unique keys defined by this Props and all parent Props
- */
- public int size() {
- return getKeySet().size();
- }
-
- /**
- * The number of unique keys defined by this Props (keys defined only in
- * parent Props are not counted)
- */
- public int localSize() {
- return _current.size();
- }
-
- /**
- * Attempts to return the Class that corresponds to the Props value. If the
- * class doesn't exit, an IllegalArgumentException will be thrown.
- *
- * @param key
- * @return
- */
- public Class<?> getClass(String key) {
- try {
- if (containsKey(key)) {
- return Class.forName(get(key));
- }
- else {
- throw new UndefinedPropertyException("Missing required property '" + key + "'");
- }
- }
- catch (ClassNotFoundException e) {
- throw new IllegalArgumentException(e);
- }
- }
-
- /**
- * Gets the class from the Props. If it doesn't exist, it will return the
- * defaultClass
- *
- * @param key
- * @param c
- * @return
- */
- public Class<?> getClass(String key, Class<?> defaultClass) {
- if (containsKey(key)) {
- return getClass(key);
- }
- else {
- return defaultClass;
- }
- }
-
- /**
- * Gets the string from the Props. If it doesn't exist, it will return the
- * defaultValue
- *
- * @param key
- * @param defaultValue
- * @return
- */
- public String getString(String key, String defaultValue) {
- if (containsKey(key)) {
- return get(key);
- }
- else {
- return defaultValue;
- }
- }
-
- /**
- * Gets the string from the Props. If it doesn't exist, throw and
- * UndefinedPropertiesException
- *
- * @param key
- * @param defaultValue
- * @return
- */
- public String getString(String key) {
- if (containsKey(key)) {
- return get(key);
- }
- else {
- throw new UndefinedPropertyException("Missing required property '" + key + "'");
- }
- }
-
- /**
- * Returns a list of strings with the comma as the separator of the value
- *
- * @param key
- * @return
- */
- public List<String> getStringList(String key) {
- return getStringList(key, "\\s*,\\s*");
- }
-
- /**
- * Returns a list of strings with the sep as the separator of the value
- *
- * @param key
- * @param sep
- * @return
- */
- public List<String> getStringList(String key, String sep) {
- String val = get(key);
- if (val == null || val.trim().length() == 0) {
- return Collections.emptyList();
- }
-
- if (containsKey(key)) {
- return Arrays.asList(val.split(sep));
- }
- else {
- throw new UndefinedPropertyException("Missing required property '" + key + "'");
- }
- }
-
- /**
- * Returns a list of strings with the comma as the separator of the value.
- * If the value is null, it'll return the defaultValue.
- *
- * @param key
- * @return
- */
- public List<String> getStringList(String key, List<String> defaultValue) {
- if (containsKey(key)) {
- return getStringList(key);
- }
- else {
- return defaultValue;
- }
- }
-
- /**
- * Returns a list of strings with the sep as the separator of the value. If
- * the value is null, it'll return the defaultValue.
- *
- * @param key
- * @return
- */
- public List<String> getStringList(String key, List<String> defaultValue, String sep) {
- if (containsKey(key)) {
- return getStringList(key, sep);
- }
- else {
- return defaultValue;
- }
- }
-
- /**
- * Returns true if the value equals "true". If the value is null, then the
- * default value is returned.
- *
- * @param key
- * @param defaultValue
- * @return
- */
- public boolean getBoolean(String key, boolean defaultValue) {
- if (containsKey(key)) {
- return "true".equalsIgnoreCase(get(key).trim());
- }
- else {
- return defaultValue;
- }
- }
-
- /**
- * Returns true if the value equals "true". If the value is null, then an
- * UndefinedPropertyException is thrown.
- *
- * @param key
- * @return
- */
- public boolean getBoolean(String key) {
- if (containsKey(key)) return "true".equalsIgnoreCase(get(key));
- else throw new UndefinedPropertyException("Missing required property '" + key + "'");
- }
-
- /**
- * Returns the long representation of the value. If the value is null, then
- * the default value is returned. If the value isn't a long, then a parse
- * exception will be thrown.
- *
- * @param key
- * @param defaultValue
- * @return
- */
- public long getLong(String name, long defaultValue) {
- if (containsKey(name)) {
- return Long.parseLong(get(name));
- }
- else {
- return defaultValue;
- }
- }
-
- /**
- * Returns the long representation of the value. If the value is null, then
- * a UndefinedPropertyException will be thrown. If the value isn't a long,
- * then a parse exception will be thrown.
- *
- * @param key
- * @return
- */
- public long getLong(String name) {
- if (containsKey(name)) {
- return Long.parseLong(get(name));
- }
- else {
- throw new UndefinedPropertyException("Missing required property '" + name + "'");
- }
- }
-
- /**
- * Returns the int representation of the value. If the value is null, then
- * the default value is returned. If the value isn't a int, then a parse
- * exception will be thrown.
- *
- * @param key
- * @param defaultValue
- * @return
- */
- public int getInt(String name, int defaultValue) {
- if (containsKey(name)) {
- return Integer.parseInt(get(name).trim());
- }
- else {
- return defaultValue;
- }
- }
-
- /**
- * Returns the int representation of the value. If the value is null, then a
- * UndefinedPropertyException will be thrown. If the value isn't a int, then
- * a parse exception will be thrown.
- *
- * @param key
- * @return
- */
- public int getInt(String name) {
- if (containsKey(name)) {
- return Integer.parseInt(get(name).trim());
- }
- else {
- throw new UndefinedPropertyException("Missing required property '" + name + "'");
- }
- }
-
- /**
- * Returns the double representation of the value. If the value is null,
- * then the default value is returned. If the value isn't a double, then a
- * parse exception will be thrown.
- *
- * @param key
- * @param defaultValue
- * @return
- */
- public double getDouble(String name, double defaultValue) {
- if (containsKey(name)) {
- return Double.parseDouble(get(name).trim());
- }
- else {
- return defaultValue;
- }
- }
-
- /**
- * Returns the double representation of the value. If the value is null,
- * then a UndefinedPropertyException will be thrown. If the value isn't a
- * double, then a parse exception will be thrown.
- *
- * @param key
- * @return
- */
- public double getDouble(String name) {
- if (containsKey(name)) {
- return Double.parseDouble(get(name).trim());
- }
- else {
- throw new UndefinedPropertyException("Missing required property '" + name + "'");
- }
- }
-
- /**
- * Returns the uri representation of the value. If the value is null, then
- * the default value is returned. If the value isn't a uri, then a
- * IllegalArgumentException will be thrown.
- *
- * @param key
- * @param defaultValue
- * @return
- */
- public URI getUri(String name) {
- if (containsKey(name)) {
- try {
- return new URI(get(name));
- }
- catch (URISyntaxException e) {
- throw new IllegalArgumentException(e.getMessage());
- }
- }
- else {
- throw new UndefinedPropertyException("Missing required property '" + name + "'");
- }
- }
-
- /**
- * Returns the double representation of the value. If the value is null,
- * then the default value is returned. If the value isn't a uri, then a
- * IllegalArgumentException will be thrown.
- *
- * @param key
- * @param defaultValue
- * @return
- */
- public URI getUri(String name, URI defaultValue) {
- if (containsKey(name)) {
- return getUri(name);
- }
- else {
- return defaultValue;
- }
- }
-
- public URI getUri(String name, String defaultValue) {
- try {
- return getUri(name, new URI(defaultValue));
- }
- catch (URISyntaxException e) {
- throw new IllegalArgumentException(e.getMessage());
- }
- }
-
- /**
- * Store only those properties defined at this local level
- *
- * @param file
- * The file to write to
- * @throws IOException
- * If the file can't be found or there is an io error
- */
- public void storeLocal(File file) throws IOException {
- BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file));
- try {
- storeLocal(out);
- }
- finally {
- out.close();
- }
- }
-
- /**
- * Returns a copy of only the local values of this props
- *
- * @return
- */
- @SuppressWarnings("unchecked")
- public Props local() {
- return new Props(null, _current);
- }
-
- /**
- * Store only those properties defined at this local level
- *
- * @param out
- * The output stream to write to
- * @throws IOException
- * If the file can't be found or there is an io error
- */
- public void storeLocal(OutputStream out) throws IOException {
- Properties p = new Properties();
- for (String key : _current.keySet()) {
- p.setProperty(key, get(key));
- }
- p.store(out, null);
- }
-
- /**
- * Returns a java.util.Properties file populated with the stuff in here.
- *
- * @return
- */
- public Properties toProperties() {
- Properties p = new Properties();
- for (String key : _current.keySet()) {
- p.setProperty(key, get(key));
- }
-
- return p;
- }
-
- /**
- * Store all properties, those local and also those in parent props
- *
- * @param file
- * The file to store to
- * @throws IOException
- * If there is an error writing
- */
- public void storeFlattened(File file) throws IOException {
- BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file));
- try {
- storeFlattened(out);
- }
- finally {
- out.close();
- }
- }
-
- /**
- * Store all properties, those local and also those in parent props
- *
- * @param out
- * The stream to write to
- * @throws IOException
- * If there is an error writing
- */
- public void storeFlattened(OutputStream out) throws IOException {
- Properties p = new Properties();
- for (Props curr = this; curr != null; curr = curr.getParent()) {
- for (String key : curr.localKeySet()) {
- if (!p.containsKey(key)) {
- p.setProperty(key, get(key));
- }
- }
- }
-
- p.store(out, null);
- }
-
- /**
- * Get a map of all properties by string prefix
- *
- * @param prefix
- * The string prefix
- */
- public Map<String, String> getMapByPrefix(String prefix) {
- Map<String, String> values = new HashMap<String, String>();
-
- if (_parent != null) {
- for (Map.Entry<String, String> entry : _parent.getMapByPrefix(prefix).entrySet())
- {
- values.put(entry.getKey(), entry.getValue());
- }
- }
-
- for (String key : this.localKeySet()) {
- if (key.startsWith(prefix)) {
- values.put(key.substring(prefix.length()), get(key));
- }
- }
- return values;
- }
-
- /**
- * Returns a set of all keys, including the parents
- * @return
- */
- public Set<String> getKeySet() {
- HashSet<String> keySet = new HashSet<String>();
-
- keySet.addAll(localKeySet());
-
- if (_parent != null) {
- keySet.addAll(_parent.getKeySet());
- }
-
- return keySet;
- }
-
- /**
- * Logs the property in the given logger
- *
- * @param logger
- * @param comment
- */
- public void logProperties(Logger logger, String comment) {
- logger.info(comment);
-
- for (String key : getKeySet()) {
- logger.info(" key=" + key + " value=" + get(key));
- }
- }
-
- /**
- * Clones the Props p object and all of its parents.
- *
- * @param p
- * @return
- */
- public static Props clone(Props p) {
- return copyNext(p);
- }
-
- /**
- *
- * @param source
- * @return
- */
- private static Props copyNext(Props source) {
- Props priorNodeCopy = null;
- if (source.getParent() != null) {
- priorNodeCopy = copyNext(source.getParent());
- }
- Props dest = new Props(priorNodeCopy);
- for (String key : source.localKeySet()) {
- dest.put(key, source.get(key));
- }
-
- return dest;
- }
-
- /**
- */
- @Override
- public boolean equals(Object o) {
- if (o == this) {
- return true;
- }
- else if (o == null) {
- return false;
- }
- else if (o.getClass() != Props.class) {
- return false;
- }
-
- Props p = (Props) o;
- return _current.equals(p._current) && Utils.equals(this._parent, p._parent);
- }
-
- /**
- * Returns true if the properties are equivalent, regardless of the hierarchy.
- *
- * @param p
- * @return
- */
- public boolean equalsProps(Props p) {
- if (p == null) {
- return false;
- }
-
- final Set<String> myKeySet = getKeySet();
- for (String s : myKeySet) {
- if (!get(s).equals(p.get(s))) {
- return false;
- }
- }
-
- return myKeySet.size() == p.getKeySet().size();
- }
-
- /**
- *
- */
- @Override
- public int hashCode() {
- int code = this._current.hashCode();
- if (_parent != null) code += _parent.hashCode();
- return code;
- }
-
- /**
- *
- */
- @Override
- public String toString() {
- StringBuilder builder = new StringBuilder("{");
- for (Map.Entry<String, String> entry : this._current.entrySet()) {
- builder.append(entry.getKey());
- builder.append(": ");
- builder.append(entry.getValue());
- builder.append(", ");
- }
- if (_parent != null) {
- builder.append(" parent = ");
- builder.append(_parent.toString());
- }
- builder.append("}");
- return builder.toString();
- }
-
- public String getSource() {
- return source;
- }
-
- public void setSource(String source) {
- this.source = source;
- }
-
- public void setParent(Props prop) {
- this._parent = prop;
- }
+ private final Map<String, String> _current;
+ private Props _parent;
+ private String source = null;
+
+ /**
+ * Constructor for empty props with empty parent.
+ */
+ public Props() {
+ this(null);
+ }
+
+ /**
+ * Constructor for empty Props with parent override.
+ *
+ * @param parent
+ */
+ public Props(Props parent) {
+ this._current = new HashMap<String, String>();
+ this._parent = parent;
+ }
+
+ /**
+ * Load props from a file.
+ *
+ * @param parent
+ * @param file
+ * @throws IOException
+ */
+ public Props(Props parent, String filepath) throws IOException {
+ this(parent, new File(filepath));
+ }
+
+ /**
+ * Load props from a file.
+ *
+ * @param parent
+ * @param file
+ * @throws IOException
+ */
+ public Props(Props parent, File file) throws IOException {
+ this(parent);
+ setSource(file.getPath());
+
+ InputStream input = new BufferedInputStream(new FileInputStream(file));
+ try {
+ loadFrom(input);
+ } catch (IOException e) {
+ input.close();
+ throw e;
+ }
+ input.close();
+ }
+
+ /**
+ * Create props from property input streams
+ *
+ * @param parent
+ * @param inputStreams
+ * @throws IOException
+ */
+ public Props(Props parent, InputStream inputStream) throws IOException {
+ this(parent);
+ loadFrom(inputStream);
+ }
+
+ /**
+ *
+ * @param inputStream
+ * @throws IOException
+ */
+ private void loadFrom(InputStream inputStream) throws IOException {
+ Properties properties = new Properties();
+ properties.load(inputStream);
+ this.put(properties);
+ }
+
+ /**
+ * Create properties from maps of properties
+ *
+ * @param parent
+ * @param props
+ */
+ public Props(Props parent, Map<String, String>... props) {
+ this(parent);
+ for (int i = props.length - 1; i >= 0; i--) {
+ this.putAll(props[i]);
+ }
+ }
+
+ /**
+ * Create properties from Properties objects
+ *
+ * @param parent
+ * @param properties
+ */
+ public Props(Props parent, Properties... properties) {
+ this(parent);
+ for (int i = properties.length - 1; i >= 0; i--) {
+ this.put(properties[i]);
+ }
+ }
+
+ /**
+ * Create a Props object with the contents set to that of props.
+ *
+ * @param parent
+ * @param props
+ */
+ public Props(Props parent, Props props) {
+ this(parent);
+ if (props != null) {
+ putAll(props);
+ }
+ }
+
+ /**
+ * Create a Props with a null parent from a list of key value pairing. i.e.
+ * [key1, value1, key2, value2 ...]
+ *
+ * @param args
+ * @return
+ */
+ public static Props of(String... args) {
+ return of((Props) null, args);
+ }
+
+ /**
+ * Create a Props from a list of key value pairing. i.e. [key1, value1,
+ * key2, value2 ...]
+ *
+ * @param args
+ * @return
+ */
+ @SuppressWarnings("unchecked")
+ public static Props of(Props parent, String... args) {
+ if (args.length % 2 != 0) {
+ throw new IllegalArgumentException(
+ "Must have an equal number of keys and values.");
+ }
+
+ Map<String, String> vals = new HashMap<String, String>(args.length / 2);
+
+ for (int i = 0; i < args.length; i += 2) {
+ vals.put(args[i], args[i + 1]);
+ }
+ return new Props(parent, vals);
+ }
+
+ /**
+ * Clear the current Props, but leaves the parent untouched.
+ */
+ public void clearLocal() {
+ _current.clear();
+ }
+
+ /**
+ * Check key in current Props then search in parent
+ *
+ * @param k
+ * @return
+ */
+ public boolean containsKey(Object k) {
+ return _current.containsKey(k)
+ || (_parent != null && _parent.containsKey(k));
+ }
+
+ /**
+ * Check value in current Props then search in parent
+ *
+ * @param value
+ * @return
+ */
+ public boolean containsValue(Object value) {
+ return _current.containsValue(value)
+ || (_parent != null && _parent.containsValue(value));
+ }
+
+ /**
+ * Return value if available in current Props otherwise return from parent
+ *
+ * @param key
+ * @return
+ */
+ public String get(Object key) {
+ if (_current.containsKey(key)) {
+ return _current.get(key);
+ } else if (_parent != null) {
+ return _parent.get(key);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Get the key set from the current Props
+ *
+ * @return
+ */
+ public Set<String> localKeySet() {
+ return _current.keySet();
+ }
+
+ /**
+ * Get parent Props
+ *
+ * @return
+ */
+ public Props getParent() {
+ return _parent;
+ }
+
+ /**
+ * Put the given string value for the string key. This method performs any
+ * variable substitution in the value replacing any occurance of ${name}
+ * with the value of get("name").
+ *
+ * @param key
+ * The key to put the value to
+ * @param value
+ * The value to do substitution on and store
+ *
+ * @throws IllegalArgumentException
+ * If the variable given for substitution is not a valid key in
+ * this Props.
+ */
+ public String put(String key, String value) {
+ return _current.put(key, value);
+ }
+
+ /**
+ * Put the given Properties into the Props. This method performs any
+ * variable substitution in the value replacing any occurrence of ${name}
+ * with the value of get("name"). get() is called first on the Props and
+ * next on the Properties object.
+ *
+ * @param properties
+ * The properties to put
+ *
+ * @throws IllegalArgumentException
+ * If the variable given for substitution is not a valid key in
+ * this Props.
+ */
+ public void put(Properties properties) {
+ for (String propName : properties.stringPropertyNames()) {
+ _current.put(propName, properties.getProperty(propName));
+ }
+ }
+
+ /**
+ * Put integer
+ *
+ * @param key
+ * @param value
+ * @return
+ */
+ public String put(String key, Integer value) {
+ return _current.put(key, value.toString());
+ }
+
+ /**
+ * Put Long. Stores as String.
+ *
+ * @param key
+ * @param value
+ * @return
+ */
+ public String put(String key, Long value) {
+ return _current.put(key, value.toString());
+ }
+
+ /**
+ * Put Double. Stores as String.
+ *
+ * @param key
+ * @param value
+ * @return
+ */
+ public String put(String key, Double value) {
+ return _current.put(key, value.toString());
+ }
+
+ /**
+ * Put everything in the map into the props.
+ *
+ * @param m
+ */
+ public void putAll(Map<? extends String, ? extends String> m) {
+ if (m == null) {
+ return;
+ }
+
+ for (Map.Entry<? extends String, ? extends String> entry : m.entrySet()) {
+ this.put(entry.getKey(), entry.getValue());
+ }
+ }
+
+ /**
+ * Put all properties in the props into the current props. Will handle null
+ * p.
+ *
+ * @param p
+ */
+ public void putAll(Props p) {
+ if (p == null) {
+ return;
+ }
+
+ for (String key : p.getKeySet()) {
+ this.put(key, p.get(key));
+ }
+ }
+
+ /**
+ * Puts only the local props from p into the current properties
+ *
+ * @param p
+ */
+ public void putLocal(Props p) {
+ for (String key : p.localKeySet()) {
+ this.put(key, p.get(key));
+ }
+ }
+
+ /**
+ * Remove only the local value of key s, and not the parents.
+ *
+ * @param s
+ * @return
+ */
+ public String removeLocal(Object s) {
+ return _current.remove(s);
+ }
+
+ /**
+ * The number of unique keys defined by this Props and all parent Props
+ */
+ public int size() {
+ return getKeySet().size();
+ }
+
+ /**
+ * The number of unique keys defined by this Props (keys defined only in
+ * parent Props are not counted)
+ */
+ public int localSize() {
+ return _current.size();
+ }
+
+ /**
+ * Attempts to return the Class that corresponds to the Props value. If the
+ * class doesn't exit, an IllegalArgumentException will be thrown.
+ *
+ * @param key
+ * @return
+ */
+ public Class<?> getClass(String key) {
+ try {
+ if (containsKey(key)) {
+ return Class.forName(get(key));
+ } else {
+ throw new UndefinedPropertyException(
+ "Missing required property '" + key + "'");
+ }
+ } catch (ClassNotFoundException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ /**
+ * Gets the class from the Props. If it doesn't exist, it will return the
+ * defaultClass
+ *
+ * @param key
+ * @param c
+ * @return
+ */
+ public Class<?> getClass(String key, Class<?> defaultClass) {
+ if (containsKey(key)) {
+ return getClass(key);
+ } else {
+ return defaultClass;
+ }
+ }
+
+ /**
+ * Gets the string from the Props. If it doesn't exist, it will return the
+ * defaultValue
+ *
+ * @param key
+ * @param defaultValue
+ * @return
+ */
+ public String getString(String key, String defaultValue) {
+ if (containsKey(key)) {
+ return get(key);
+ } else {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * Gets the string from the Props. If it doesn't exist, throw and
+ * UndefinedPropertiesException
+ *
+ * @param key
+ * @param defaultValue
+ * @return
+ */
+ public String getString(String key) {
+ if (containsKey(key)) {
+ return get(key);
+ } else {
+ throw new UndefinedPropertyException("Missing required property '"
+ + key + "'");
+ }
+ }
+
+ /**
+ * Returns a list of strings with the comma as the separator of the value
+ *
+ * @param key
+ * @return
+ */
+ public List<String> getStringList(String key) {
+ return getStringList(key, "\\s*,\\s*");
+ }
+
+ /**
+ * Returns a list of strings with the sep as the separator of the value
+ *
+ * @param key
+ * @param sep
+ * @return
+ */
+ public List<String> getStringList(String key, String sep) {
+ String val = get(key);
+ if (val == null || val.trim().length() == 0) {
+ return Collections.emptyList();
+ }
+
+ if (containsKey(key)) {
+ return Arrays.asList(val.split(sep));
+ } else {
+ throw new UndefinedPropertyException("Missing required property '"
+ + key + "'");
+ }
+ }
+
+ /**
+ * Returns a list of strings with the comma as the separator of the value.
+ * If the value is null, it'll return the defaultValue.
+ *
+ * @param key
+ * @return
+ */
+ public List<String> getStringList(String key, List<String> defaultValue) {
+ if (containsKey(key)) {
+ return getStringList(key);
+ } else {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * Returns a list of strings with the sep as the separator of the value. If
+ * the value is null, it'll return the defaultValue.
+ *
+ * @param key
+ * @return
+ */
+ public List<String> getStringList(String key, List<String> defaultValue,
+ String sep) {
+ if (containsKey(key)) {
+ return getStringList(key, sep);
+ } else {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * Returns true if the value equals "true". If the value is null, then the
+ * default value is returned.
+ *
+ * @param key
+ * @param defaultValue
+ * @return
+ */
+ public boolean getBoolean(String key, boolean defaultValue) {
+ if (containsKey(key)) {
+ return "true".equalsIgnoreCase(get(key).trim());
+ } else {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * Returns true if the value equals "true". If the value is null, then an
+ * UndefinedPropertyException is thrown.
+ *
+ * @param key
+ * @return
+ */
+ public boolean getBoolean(String key) {
+ if (containsKey(key))
+ return "true".equalsIgnoreCase(get(key));
+ else
+ throw new UndefinedPropertyException("Missing required property '"
+ + key + "'");
+ }
+
+ /**
+ * Returns the long representation of the value. If the value is null, then
+ * the default value is returned. If the value isn't a long, then a parse
+ * exception will be thrown.
+ *
+ * @param key
+ * @param defaultValue
+ * @return
+ */
+ public long getLong(String name, long defaultValue) {
+ if (containsKey(name)) {
+ return Long.parseLong(get(name));
+ } else {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * Returns the long representation of the value. If the value is null, then
+ * a UndefinedPropertyException will be thrown. If the value isn't a long,
+ * then a parse exception will be thrown.
+ *
+ * @param key
+ * @return
+ */
+ public long getLong(String name) {
+ if (containsKey(name)) {
+ return Long.parseLong(get(name));
+ } else {
+ throw new UndefinedPropertyException("Missing required property '"
+ + name + "'");
+ }
+ }
+
+ /**
+ * Returns the int representation of the value. If the value is null, then
+ * the default value is returned. If the value isn't a int, then a parse
+ * exception will be thrown.
+ *
+ * @param key
+ * @param defaultValue
+ * @return
+ */
+ public int getInt(String name, int defaultValue) {
+ if (containsKey(name)) {
+ return Integer.parseInt(get(name).trim());
+ } else {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * Returns the int representation of the value. If the value is null, then a
+ * UndefinedPropertyException will be thrown. If the value isn't a int, then
+ * a parse exception will be thrown.
+ *
+ * @param key
+ * @return
+ */
+ public int getInt(String name) {
+ if (containsKey(name)) {
+ return Integer.parseInt(get(name).trim());
+ } else {
+ throw new UndefinedPropertyException("Missing required property '"
+ + name + "'");
+ }
+ }
+
+ /**
+ * Returns the double representation of the value. If the value is null,
+ * then the default value is returned. If the value isn't a double, then a
+ * parse exception will be thrown.
+ *
+ * @param key
+ * @param defaultValue
+ * @return
+ */
+ public double getDouble(String name, double defaultValue) {
+ if (containsKey(name)) {
+ return Double.parseDouble(get(name).trim());
+ } else {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * Returns the double representation of the value. If the value is null,
+ * then a UndefinedPropertyException will be thrown. If the value isn't a
+ * double, then a parse exception will be thrown.
+ *
+ * @param key
+ * @return
+ */
+ public double getDouble(String name) {
+ if (containsKey(name)) {
+ return Double.parseDouble(get(name).trim());
+ } else {
+ throw new UndefinedPropertyException("Missing required property '"
+ + name + "'");
+ }
+ }
+
+ /**
+ * Returns the uri representation of the value. If the value is null, then
+ * the default value is returned. If the value isn't a uri, then a
+ * IllegalArgumentException will be thrown.
+ *
+ * @param key
+ * @param defaultValue
+ * @return
+ */
+ public URI getUri(String name) {
+ if (containsKey(name)) {
+ try {
+ return new URI(get(name));
+ } catch (URISyntaxException e) {
+ throw new IllegalArgumentException(e.getMessage());
+ }
+ } else {
+ throw new UndefinedPropertyException("Missing required property '"
+ + name + "'");
+ }
+ }
+
+ /**
+ * Returns the double representation of the value. If the value is null,
+ * then the default value is returned. If the value isn't a uri, then a
+ * IllegalArgumentException will be thrown.
+ *
+ * @param key
+ * @param defaultValue
+ * @return
+ */
+ public URI getUri(String name, URI defaultValue) {
+ if (containsKey(name)) {
+ return getUri(name);
+ } else {
+ return defaultValue;
+ }
+ }
+
+ public URI getUri(String name, String defaultValue) {
+ try {
+ return getUri(name, new URI(defaultValue));
+ } catch (URISyntaxException e) {
+ throw new IllegalArgumentException(e.getMessage());
+ }
+ }
+
+ /**
+ * Store only those properties defined at this local level
+ *
+ * @param file
+ * The file to write to
+ * @throws IOException
+ * If the file can't be found or there is an io error
+ */
+ public void storeLocal(File file) throws IOException {
+ BufferedOutputStream out = new BufferedOutputStream(
+ new FileOutputStream(file));
+ try {
+ storeLocal(out);
+ } finally {
+ out.close();
+ }
+ }
+
+ /**
+ * Returns a copy of only the local values of this props
+ *
+ * @return
+ */
+ @SuppressWarnings("unchecked")
+ public Props local() {
+ return new Props(null, _current);
+ }
+
+ /**
+ * Store only those properties defined at this local level
+ *
+ * @param out
+ * The output stream to write to
+ * @throws IOException
+ * If the file can't be found or there is an io error
+ */
+ public void storeLocal(OutputStream out) throws IOException {
+ Properties p = new Properties();
+ for (String key : _current.keySet()) {
+ p.setProperty(key, get(key));
+ }
+ p.store(out, null);
+ }
+
+ /**
+ * Returns a java.util.Properties file populated with the stuff in here.
+ *
+ * @return
+ */
+ public Properties toProperties() {
+ Properties p = new Properties();
+ for (String key : _current.keySet()) {
+ p.setProperty(key, get(key));
+ }
+
+ return p;
+ }
+
+ /**
+ * Store all properties, those local and also those in parent props
+ *
+ * @param file
+ * The file to store to
+ * @throws IOException
+ * If there is an error writing
+ */
+ public void storeFlattened(File file) throws IOException {
+ BufferedOutputStream out = new BufferedOutputStream(
+ new FileOutputStream(file));
+ try {
+ storeFlattened(out);
+ } finally {
+ out.close();
+ }
+ }
+
+ /**
+ * Store all properties, those local and also those in parent props
+ *
+ * @param out
+ * The stream to write to
+ * @throws IOException
+ * If there is an error writing
+ */
+ public void storeFlattened(OutputStream out) throws IOException {
+ Properties p = new Properties();
+ for (Props curr = this; curr != null; curr = curr.getParent()) {
+ for (String key : curr.localKeySet()) {
+ if (!p.containsKey(key)) {
+ p.setProperty(key, get(key));
+ }
+ }
+ }
+
+ p.store(out, null);
+ }
+
+ /**
+ * Get a map of all properties by string prefix
+ *
+ * @param prefix
+ * The string prefix
+ */
+ public Map<String, String> getMapByPrefix(String prefix) {
+ Map<String, String> values = new HashMap<String, String>();
+
+ if (_parent != null) {
+ for (Map.Entry<String, String> entry : _parent.getMapByPrefix(
+ prefix).entrySet()) {
+ values.put(entry.getKey(), entry.getValue());
+ }
+ }
+
+ for (String key : this.localKeySet()) {
+ if (key.startsWith(prefix)) {
+ values.put(key.substring(prefix.length()), get(key));
+ }
+ }
+ return values;
+ }
+
+ /**
+ * Returns a set of all keys, including the parents
+ *
+ * @return
+ */
+ public Set<String> getKeySet() {
+ HashSet<String> keySet = new HashSet<String>();
+
+ keySet.addAll(localKeySet());
+
+ if (_parent != null) {
+ keySet.addAll(_parent.getKeySet());
+ }
+
+ return keySet;
+ }
+
+ /**
+ * Logs the property in the given logger
+ *
+ * @param logger
+ * @param comment
+ */
+ public void logProperties(Logger logger, String comment) {
+ logger.info(comment);
+
+ for (String key : getKeySet()) {
+ logger.info(" key=" + key + " value=" + get(key));
+ }
+ }
+
+ /**
+ * Clones the Props p object and all of its parents.
+ *
+ * @param p
+ * @return
+ */
+ public static Props clone(Props p) {
+ return copyNext(p);
+ }
+
+ /**
+ *
+ * @param source
+ * @return
+ */
+ private static Props copyNext(Props source) {
+ Props priorNodeCopy = null;
+ if (source.getParent() != null) {
+ priorNodeCopy = copyNext(source.getParent());
+ }
+ Props dest = new Props(priorNodeCopy);
+ for (String key : source.localKeySet()) {
+ dest.put(key, source.get(key));
+ }
+
+ return dest;
+ }
+
+ /**
+ */
+ @Override
+ public boolean equals(Object o) {
+ if (o == this) {
+ return true;
+ } else if (o == null) {
+ return false;
+ } else if (o.getClass() != Props.class) {
+ return false;
+ }
+
+ Props p = (Props) o;
+ return _current.equals(p._current)
+ && Utils.equals(this._parent, p._parent);
+ }
+
+ /**
+ * Returns true if the properties are equivalent, regardless of the
+ * hierarchy.
+ *
+ * @param p
+ * @return
+ */
+ public boolean equalsProps(Props p) {
+ if (p == null) {
+ return false;
+ }
+
+ final Set<String> myKeySet = getKeySet();
+ for (String s : myKeySet) {
+ if (!get(s).equals(p.get(s))) {
+ return false;
+ }
+ }
+
+ return myKeySet.size() == p.getKeySet().size();
+ }
+
+ /**
+ *
+ */
+ @Override
+ public int hashCode() {
+ int code = this._current.hashCode();
+ if (_parent != null)
+ code += _parent.hashCode();
+ return code;
+ }
+
+ /**
+ *
+ */
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder("{");
+ for (Map.Entry<String, String> entry : this._current.entrySet()) {
+ builder.append(entry.getKey());
+ builder.append(": ");
+ builder.append(entry.getValue());
+ builder.append(", ");
+ }
+ if (_parent != null) {
+ builder.append(" parent = ");
+ builder.append(_parent.toString());
+ }
+ builder.append("}");
+ return builder.toString();
+ }
+
+ public String getSource() {
+ return source;
+ }
+
+ public void setSource(String source) {
+ this.source = source;
+ }
+
+ public void setParent(Props prop) {
+ this._parent = prop;
+ }
}
diff --git a/src/java/azkaban/utils/UndefinedPropertyException.java b/src/java/azkaban/utils/UndefinedPropertyException.java
index 758f4b1..a63aabb 100644
--- a/src/java/azkaban/utils/UndefinedPropertyException.java
+++ b/src/java/azkaban/utils/UndefinedPropertyException.java
@@ -17,14 +17,14 @@
package azkaban.utils;
/**
- * Indicates that a required property is missing from the Props
+ * Indicates that a required property is missing from the Props
*/
public class UndefinedPropertyException extends RuntimeException {
- private static final long serialVersionUID = 1;
+ private static final long serialVersionUID = 1;
- public UndefinedPropertyException(String message) {
- super(message);
- }
+ public UndefinedPropertyException(String message) {
+ super(message);
+ }
}
src/java/azkaban/utils/Utils.java 268(+137 -131)
diff --git a/src/java/azkaban/utils/Utils.java b/src/java/azkaban/utils/Utils.java
index 5d95084..c00951a 100644
--- a/src/java/azkaban/utils/Utils.java
+++ b/src/java/azkaban/utils/Utils.java
@@ -37,135 +37,141 @@ import org.apache.commons.io.IOUtils;
* A util helper class full of static methods that are commonly used.
*/
public class Utils {
- public static final Random RANDOM = new Random();
-
- /**
- * Private constructor.
- */
- private Utils() {
- }
-
- /**
- * Equivalent to Object.equals except that it handles nulls. If a and b are
- * both null, true is returned.
- *
- * @param a
- * @param b
- * @return
- */
- public static boolean equals(Object a, Object b) {
- if (a == null || b == null) {
- return a == b;
- }
-
- return a.equals(b);
- }
-
- /**
- * Return the object if it is non-null, otherwise throw an exception
- *
- * @param <T>
- * The type of the object
- * @param t
- * The object
- * @return The object if it is not null
- * @throws IllegalArgumentException
- * if the object is null
- */
- public static <T> T nonNull(T t) {
- if (t == null) {
- throw new IllegalArgumentException("Null value not allowed.");
- }
- else {
- return t;
- }
- }
-
- /**
- * Print the message and then exit with the given exit code
- *
- * @param message The message to print
- * @param exitCode The exit code
- */
- public static void croak(String message, int exitCode) {
- System.err.println(message);
- System.exit(exitCode);
- }
-
- public static File createTempDir() {
- return createTempDir(new File(System.getProperty("java.io.tmpdir")));
- }
-
- public static File createTempDir(File parent) {
- File temp = new File(parent, Integer.toString(Math.abs(RANDOM.nextInt()) % 100000000));
- temp.delete();
- temp.mkdir();
- temp.deleteOnExit();
- return temp;
- }
-
- public static void zip(File input, File output) throws IOException {
- FileOutputStream out = new FileOutputStream(output);
- ZipOutputStream zOut = new ZipOutputStream(out);
- zipFile("", input, zOut);
- zOut.close();
- }
-
- private static void zipFile(String path, File input, ZipOutputStream zOut) throws IOException {
- if(input.isDirectory()) {
- File[] files = input.listFiles();
- if(files != null) {
- for(File f: files) {
- String childPath = path + input.getName() + (f.isDirectory() ? "/" : "");
- zipFile(childPath, f, zOut);
- }
- }
- } else {
- String childPath = path + (path.length() > 0 ? "/" : "") + input.getName();
- ZipEntry entry = new ZipEntry(childPath);
- zOut.putNextEntry(entry);
- InputStream fileInputStream = new BufferedInputStream(new FileInputStream(input));
- IOUtils.copy(fileInputStream, zOut);
- fileInputStream.close();
- }
- }
-
- public static void unzip(ZipFile source, File dest) throws IOException {
- Enumeration<?> entries = source.entries();
- while(entries.hasMoreElements()) {
- ZipEntry entry = (ZipEntry) entries.nextElement();
- File newFile = new File(dest, entry.getName());
- if(entry.isDirectory()) {
- newFile.mkdirs();
- } else {
- newFile.getParentFile().mkdirs();
- InputStream src = source.getInputStream(entry);
- OutputStream output = new BufferedOutputStream(new FileOutputStream(newFile));
- IOUtils.copy(src, output);
- src.close();
- output.close();
- }
- }
- }
-
- public static String flattenToString(Collection<?> collection, String delimiter) {
- StringBuffer buffer = new StringBuffer();
- for (Object obj: collection) {
- buffer.append(obj.toString());
- buffer.append(',');
- }
-
- if (buffer.length() > 0) {
- buffer.setLength(buffer.length() - 1);
- }
- return buffer.toString();
- }
-
- public static Double convertToDouble(Object obj) {
- if (obj instanceof String) {
- return Double.parseDouble((String)obj);
- }
-
- return (Double)obj;
- }
+ public static final Random RANDOM = new Random();
+
+ /**
+ * Private constructor.
+ */
+ private Utils() {
+ }
+
+ /**
+ * Equivalent to Object.equals except that it handles nulls. If a and b are
+ * both null, true is returned.
+ *
+ * @param a
+ * @param b
+ * @return
+ */
+ public static boolean equals(Object a, Object b) {
+ if (a == null || b == null) {
+ return a == b;
+ }
+
+ return a.equals(b);
+ }
+
+ /**
+ * Return the object if it is non-null, otherwise throw an exception
+ *
+ * @param <T>
+ * The type of the object
+ * @param t
+ * The object
+ * @return The object if it is not null
+ * @throws IllegalArgumentException
+ * if the object is null
+ */
+ public static <T> T nonNull(T t) {
+ if (t == null) {
+ throw new IllegalArgumentException("Null value not allowed.");
+ } else {
+ return t;
+ }
+ }
+
+ /**
+ * Print the message and then exit with the given exit code
+ *
+ * @param message
+ * The message to print
+ * @param exitCode
+ * The exit code
+ */
+ public static void croak(String message, int exitCode) {
+ System.err.println(message);
+ System.exit(exitCode);
+ }
+
+ public static File createTempDir() {
+ return createTempDir(new File(System.getProperty("java.io.tmpdir")));
+ }
+
+ public static File createTempDir(File parent) {
+ File temp = new File(parent,
+ Integer.toString(Math.abs(RANDOM.nextInt()) % 100000000));
+ temp.delete();
+ temp.mkdir();
+ temp.deleteOnExit();
+ return temp;
+ }
+
+ public static void zip(File input, File output) throws IOException {
+ FileOutputStream out = new FileOutputStream(output);
+ ZipOutputStream zOut = new ZipOutputStream(out);
+ zipFile("", input, zOut);
+ zOut.close();
+ }
+
+ private static void zipFile(String path, File input, ZipOutputStream zOut) throws IOException {
+ if (input.isDirectory()) {
+ File[] files = input.listFiles();
+ if (files != null) {
+ for (File f : files) {
+ String childPath = path + input.getName()
+ + (f.isDirectory() ? "/" : "");
+ zipFile(childPath, f, zOut);
+ }
+ }
+ } else {
+ String childPath = path + (path.length() > 0 ? "/" : "")
+ + input.getName();
+ ZipEntry entry = new ZipEntry(childPath);
+ zOut.putNextEntry(entry);
+ InputStream fileInputStream = new BufferedInputStream(
+ new FileInputStream(input));
+ IOUtils.copy(fileInputStream, zOut);
+ fileInputStream.close();
+ }
+ }
+
+ public static void unzip(ZipFile source, File dest) throws IOException {
+ Enumeration<?> entries = source.entries();
+ while (entries.hasMoreElements()) {
+ ZipEntry entry = (ZipEntry) entries.nextElement();
+ File newFile = new File(dest, entry.getName());
+ if (entry.isDirectory()) {
+ newFile.mkdirs();
+ } else {
+ newFile.getParentFile().mkdirs();
+ InputStream src = source.getInputStream(entry);
+ OutputStream output = new BufferedOutputStream(
+ new FileOutputStream(newFile));
+ IOUtils.copy(src, output);
+ src.close();
+ output.close();
+ }
+ }
+ }
+
+ public static String flattenToString(Collection<?> collection, String delimiter) {
+ StringBuffer buffer = new StringBuffer();
+ for (Object obj : collection) {
+ buffer.append(obj.toString());
+ buffer.append(',');
+ }
+
+ if (buffer.length() > 0) {
+ buffer.setLength(buffer.length() - 1);
+ }
+ return buffer.toString();
+ }
+
+ public static Double convertToDouble(Object obj) {
+ if (obj instanceof String) {
+ return Double.parseDouble((String) obj);
+ }
+
+ return (Double) obj;
+ }
}
\ No newline at end of file
src/java/azkaban/webapp/servlet/AbstractAzkabanServlet.java 576(+301 -275)
diff --git a/src/java/azkaban/webapp/servlet/AbstractAzkabanServlet.java b/src/java/azkaban/webapp/servlet/AbstractAzkabanServlet.java
index c57fd8b..139b1e8 100644
--- a/src/java/azkaban/webapp/servlet/AbstractAzkabanServlet.java
+++ b/src/java/azkaban/webapp/servlet/AbstractAzkabanServlet.java
@@ -43,279 +43,305 @@ import azkaban.webapp.session.Session;
* Base Servlet for pages
*/
public abstract class AbstractAzkabanServlet extends HttpServlet {
- private static final DateTimeFormatter ZONE_FORMATTER = DateTimeFormat.forPattern("z");
- private static final String AZKABAN_SUCCESS_MESSAGE = "azkaban.success.message";
- private static final String AZKABAN_FAILURE_MESSAGE = "azkaban.failure.message";
-
- private static final long serialVersionUID = -1;
- public static final String DEFAULT_LOG_URL_PREFIX = "predefined_log_url_prefix";
- public static final String LOG_URL_PREFIX = "log_url_prefix";
- public static final String HTML_TYPE = "text/html";
- public static final String XML_MIME_TYPE = "application/xhtml+xml";
- public static final String JSON_MIME_TYPE = "application/json";
-
- private AzkabanWebServer application;
- private String name;
- private String label;
- private String color;
-
- /**
- * To retrieve the application for the servlet
- * @return
- */
- public AzkabanWebServer getApplication() {
- return application;
- }
-
- @Override
- public void init(ServletConfig config) throws ServletException {
- application = (AzkabanWebServer) config.getServletContext().getAttribute(
- AzkabanServletContextListener.AZKABAN_SERVLET_CONTEXT_KEY);
-
- if (application == null) {
- throw new IllegalStateException("No batch application is defined in the servlet context!");
- }
-
- Props props = application.getAzkabanProps();
- name = props.getString("azkaban.name", "");
- label = props.getString("azkaban.label", "");
- color = props.getString("azkaban.color", "#FF0000");
- }
-
- /**
- * Checks for the existance of the parameter in the request
- *
- * @param request
- * @param param
- * @return
- */
- public boolean hasParam(HttpServletRequest request, String param) {
- return request.getParameter(param) != null;
- }
-
- /**
- * Retrieves the param from the http servlet request. Will throw an exception if not
- * found
- *
- * @param request
- * @param name
- * @return
- * @throws ServletException
- */
- public String getParam(HttpServletRequest request, String name) throws ServletException {
- String p = request.getParameter(name);
- if (p == null) throw new ServletException("Missing required parameter '" + name + "'.");
- else return p;
- }
-
- /**
- * Returns the param and parses it into an int. Will throw an exception if not found, or
- * a parse error if the type is incorrect.
- *
- * @param request
- * @param name
- * @return
- * @throws ServletException
- */
- public int getIntParam(HttpServletRequest request, String name) throws ServletException {
- String p = getParam(request, name);
- return Integer.parseInt(p);
- }
-
- /**
- * Returns the session value of the request.
- *
- * @param request
- * @param key
- * @param value
- */
- protected void setSessionValue(HttpServletRequest request, String key, Object value) {
- request.getSession(true).setAttribute(key, value);
- }
-
- /**
- * Adds a session value to the request
- *
- * @param request
- * @param key
- * @param value
- */
- @SuppressWarnings({ "unchecked", "rawtypes" })
- protected void addSessionValue(HttpServletRequest request, String key, Object value) {
- List l = (List) request.getSession(true).getAttribute(key);
- if (l == null) l = new ArrayList();
- l.add(value);
- request.getSession(true).setAttribute(key, l);
- }
-
- /**
- * Sets an error message in azkaban.failure.message in the cookie. This will be used by the
- * web client javascript to somehow display the message
- *
- * @param response
- * @param errorMsg
- */
- protected void setErrorMessageInCookie(HttpServletResponse response, String errorMsg) {
- Cookie cookie = new Cookie(AZKABAN_FAILURE_MESSAGE, errorMsg);
- response.addCookie(cookie);
- }
-
- /**
- * Sets a message in azkaban.success.message in the cookie. This will be used by the
- * web client javascript to somehow display the message
- *
- * @param response
- * @param errorMsg
- */
- protected void setSuccessMessageInCookie(HttpServletResponse response, String message) {
- Cookie cookie = new Cookie(AZKABAN_SUCCESS_MESSAGE, message);
- response.addCookie(cookie);
- }
-
- /**
- * Retrieves a success message from a cookie. azkaban.success.message
- * @param request
- * @return
- */
- protected String getSuccessMessageFromCookie(HttpServletRequest request) {
- Cookie cookie = getCookieByName(request, AZKABAN_SUCCESS_MESSAGE);
-
- if (cookie == null) {
- return null;
- }
- return cookie.getValue();
- }
-
- /**
- * Retrieves a success message from a cookie. azkaban.failure.message
- * @param request
- * @return
- */
- protected String getErrorMessageFromCookie(HttpServletRequest request) {
- Cookie cookie = getCookieByName(request, AZKABAN_FAILURE_MESSAGE);
- if (cookie == null) {
- return null;
- }
-
- return cookie.getValue();
- }
-
- /**
- * Retrieves a cookie by name. Potential issue in performance if a lot of cookie
- * variables are used.
- *
- * @param request
- * @return
- */
- protected Cookie getCookieByName(HttpServletRequest request, String name) {
- Cookie[] cookies = request.getCookies();
- if (cookies != null) {
- for(Cookie cookie : cookies) {
- if (name.equals(cookie.getName())) {
- return cookie;
- }
- }
- }
-
- return null;
- }
-
- /**
- * Creates a new velocity page to use. With session.
- *
- * @param req
- * @param resp
- * @param template
- * @return
- */
- protected Page newPage(HttpServletRequest req, HttpServletResponse resp, Session session, String template) {
- Page page = new Page(req, resp, application.getVelocityEngine(), template);
- page.add("azkaban_name", name);
- page.add("azkaban_label", label);
- page.add("azkaban_color", color);
- page.add("timezone", ZONE_FORMATTER.print(System.currentTimeMillis()));
- page.add("currentTime",(new DateTime()).getMillis());
- if (session != null && session.getUser() != null) {
- page.add("user_id", session.getUser().getUserId());
- }
- page.add("context", req.getContextPath());
-
- String errorMsg = getErrorMessageFromCookie(req);
- page.add("error_message", errorMsg == null || errorMsg.isEmpty()? "null": errorMsg);
- setErrorMessageInCookie(resp, null);
-
- String successMsg = getSuccessMessageFromCookie(req);
- page.add("success_message", successMsg == null || successMsg.isEmpty()? "null": successMsg);
- setSuccessMessageInCookie(resp, null);
-
-
- return page;
- }
-
- /**
- * Creates a new velocity page to use.
- *
- * @param req
- * @param resp
- * @param template
- * @return
- */
- protected Page newPage(HttpServletRequest req, HttpServletResponse resp, String template) {
- Page page = new Page(req, resp, application.getVelocityEngine(), template);
- page.add("azkaban_name", name);
- page.add("azkaban_label", label);
- page.add("azkaban_color", color);
- page.add("timezone", ZONE_FORMATTER.print(System.currentTimeMillis()));
- page.add("currentTime",(new DateTime()).getMillis());
- page.add("context", req.getContextPath());
- return page;
- }
-
- /**
- * Writes json out to the stream.
- *
- * @param resp
- * @param obj
- * @throws IOException
- */
- protected void writeJSON(HttpServletResponse resp, Object obj) throws IOException {
- resp.setContentType(JSON_MIME_TYPE);
- ObjectMapper mapper = new ObjectMapper();
- mapper.writeValue(resp.getOutputStream(), obj);
- }
-
- /**
- * Retrieve the Azkaban application
- * @param config
- * @return
- */
- public static AzkabanWebServer getApp(ServletConfig config) {
- AzkabanWebServer app = (AzkabanWebServer) config
- .getServletContext()
- .getAttribute(
- AzkabanServletContextListener.AZKABAN_SERVLET_CONTEXT_KEY);
-
- if (app == null) {
- throw new IllegalStateException("No batch application is defined in the servlet context!");
- }
- else {
- return app;
- }
- }
-
- public static String createJsonResponse(String status, String message, String action, Map<String, Object> params) {
- HashMap<String,Object> response = new HashMap<String,Object>();
- response.put("status", status);
- if (message != null) {
- response.put("message", message);
- }
- if (action != null) {
- response.put("action", action);
- }
- if (params != null) {
- response.putAll(params);
- }
-
- return JSONUtils.toJSON(response);
- }
+ private static final DateTimeFormatter ZONE_FORMATTER = DateTimeFormat
+ .forPattern("z");
+ private static final String AZKABAN_SUCCESS_MESSAGE = "azkaban.success.message";
+ private static final String AZKABAN_FAILURE_MESSAGE = "azkaban.failure.message";
+
+ private static final long serialVersionUID = -1;
+ public static final String DEFAULT_LOG_URL_PREFIX = "predefined_log_url_prefix";
+ public static final String LOG_URL_PREFIX = "log_url_prefix";
+ public static final String HTML_TYPE = "text/html";
+ public static final String XML_MIME_TYPE = "application/xhtml+xml";
+ public static final String JSON_MIME_TYPE = "application/json";
+
+ private AzkabanWebServer application;
+ private String name;
+ private String label;
+ private String color;
+
+ /**
+ * To retrieve the application for the servlet
+ *
+ * @return
+ */
+ public AzkabanWebServer getApplication() {
+ return application;
+ }
+
+ @Override
+ public void init(ServletConfig config) throws ServletException {
+ application = (AzkabanWebServer) config
+ .getServletContext()
+ .getAttribute(
+ AzkabanServletContextListener.AZKABAN_SERVLET_CONTEXT_KEY);
+
+ if (application == null) {
+ throw new IllegalStateException(
+ "No batch application is defined in the servlet context!");
+ }
+
+ Props props = application.getAzkabanProps();
+ name = props.getString("azkaban.name", "");
+ label = props.getString("azkaban.label", "");
+ color = props.getString("azkaban.color", "#FF0000");
+ }
+
+ /**
+ * Checks for the existance of the parameter in the request
+ *
+ * @param request
+ * @param param
+ * @return
+ */
+ public boolean hasParam(HttpServletRequest request, String param) {
+ return request.getParameter(param) != null;
+ }
+
+ /**
+ * Retrieves the param from the http servlet request. Will throw an
+ * exception if not found
+ *
+ * @param request
+ * @param name
+ * @return
+ * @throws ServletException
+ */
+ public String getParam(HttpServletRequest request, String name)
+ throws ServletException {
+ String p = request.getParameter(name);
+ if (p == null)
+ throw new ServletException("Missing required parameter '" + name
+ + "'.");
+ else
+ return p;
+ }
+
+ /**
+ * Returns the param and parses it into an int. Will throw an exception if
+ * not found, or a parse error if the type is incorrect.
+ *
+ * @param request
+ * @param name
+ * @return
+ * @throws ServletException
+ */
+ public int getIntParam(HttpServletRequest request, String name)
+ throws ServletException {
+ String p = getParam(request, name);
+ return Integer.parseInt(p);
+ }
+
+ /**
+ * Returns the session value of the request.
+ *
+ * @param request
+ * @param key
+ * @param value
+ */
+ protected void setSessionValue(HttpServletRequest request, String key,
+ Object value) {
+ request.getSession(true).setAttribute(key, value);
+ }
+
+ /**
+ * Adds a session value to the request
+ *
+ * @param request
+ * @param key
+ * @param value
+ */
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ protected void addSessionValue(HttpServletRequest request, String key,
+ Object value) {
+ List l = (List) request.getSession(true).getAttribute(key);
+ if (l == null)
+ l = new ArrayList();
+ l.add(value);
+ request.getSession(true).setAttribute(key, l);
+ }
+
+ /**
+ * Sets an error message in azkaban.failure.message in the cookie. This will
+ * be used by the web client javascript to somehow display the message
+ *
+ * @param response
+ * @param errorMsg
+ */
+ protected void setErrorMessageInCookie(HttpServletResponse response,
+ String errorMsg) {
+ Cookie cookie = new Cookie(AZKABAN_FAILURE_MESSAGE, errorMsg);
+ response.addCookie(cookie);
+ }
+
+ /**
+ * Sets a message in azkaban.success.message in the cookie. This will be
+ * used by the web client javascript to somehow display the message
+ *
+ * @param response
+ * @param errorMsg
+ */
+ protected void setSuccessMessageInCookie(HttpServletResponse response,
+ String message) {
+ Cookie cookie = new Cookie(AZKABAN_SUCCESS_MESSAGE, message);
+ response.addCookie(cookie);
+ }
+
+ /**
+ * Retrieves a success message from a cookie. azkaban.success.message
+ *
+ * @param request
+ * @return
+ */
+ protected String getSuccessMessageFromCookie(HttpServletRequest request) {
+ Cookie cookie = getCookieByName(request, AZKABAN_SUCCESS_MESSAGE);
+
+ if (cookie == null) {
+ return null;
+ }
+ return cookie.getValue();
+ }
+
+ /**
+ * Retrieves a success message from a cookie. azkaban.failure.message
+ *
+ * @param request
+ * @return
+ */
+ protected String getErrorMessageFromCookie(HttpServletRequest request) {
+ Cookie cookie = getCookieByName(request, AZKABAN_FAILURE_MESSAGE);
+ if (cookie == null) {
+ return null;
+ }
+
+ return cookie.getValue();
+ }
+
+ /**
+ * Retrieves a cookie by name. Potential issue in performance if a lot of
+ * cookie variables are used.
+ *
+ * @param request
+ * @return
+ */
+ protected Cookie getCookieByName(HttpServletRequest request, String name) {
+ Cookie[] cookies = request.getCookies();
+ if (cookies != null) {
+ for (Cookie cookie : cookies) {
+ if (name.equals(cookie.getName())) {
+ return cookie;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Creates a new velocity page to use. With session.
+ *
+ * @param req
+ * @param resp
+ * @param template
+ * @return
+ */
+ protected Page newPage(HttpServletRequest req, HttpServletResponse resp,
+ Session session, String template) {
+ Page page = new Page(req, resp, application.getVelocityEngine(),
+ template);
+ page.add("azkaban_name", name);
+ page.add("azkaban_label", label);
+ page.add("azkaban_color", color);
+ page.add("timezone", ZONE_FORMATTER.print(System.currentTimeMillis()));
+ page.add("currentTime", (new DateTime()).getMillis());
+ if (session != null && session.getUser() != null) {
+ page.add("user_id", session.getUser().getUserId());
+ }
+ page.add("context", req.getContextPath());
+
+ String errorMsg = getErrorMessageFromCookie(req);
+ page.add("error_message",
+ errorMsg == null || errorMsg.isEmpty() ? "null" : errorMsg);
+ setErrorMessageInCookie(resp, null);
+
+ String successMsg = getSuccessMessageFromCookie(req);
+ page.add("success_message",
+ successMsg == null || successMsg.isEmpty() ? "null"
+ : successMsg);
+ setSuccessMessageInCookie(resp, null);
+
+ return page;
+ }
+
+ /**
+ * Creates a new velocity page to use.
+ *
+ * @param req
+ * @param resp
+ * @param template
+ * @return
+ */
+ protected Page newPage(HttpServletRequest req, HttpServletResponse resp,
+ String template) {
+ Page page = new Page(req, resp, application.getVelocityEngine(),
+ template);
+ page.add("azkaban_name", name);
+ page.add("azkaban_label", label);
+ page.add("azkaban_color", color);
+ page.add("timezone", ZONE_FORMATTER.print(System.currentTimeMillis()));
+ page.add("currentTime", (new DateTime()).getMillis());
+ page.add("context", req.getContextPath());
+ return page;
+ }
+
+ /**
+ * Writes json out to the stream.
+ *
+ * @param resp
+ * @param obj
+ * @throws IOException
+ */
+ protected void writeJSON(HttpServletResponse resp, Object obj)
+ throws IOException {
+ resp.setContentType(JSON_MIME_TYPE);
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.writeValue(resp.getOutputStream(), obj);
+ }
+
+ /**
+ * Retrieve the Azkaban application
+ *
+ * @param config
+ * @return
+ */
+ public static AzkabanWebServer getApp(ServletConfig config) {
+ AzkabanWebServer app = (AzkabanWebServer) config
+ .getServletContext()
+ .getAttribute(
+ AzkabanServletContextListener.AZKABAN_SERVLET_CONTEXT_KEY);
+
+ if (app == null) {
+ throw new IllegalStateException(
+ "No batch application is defined in the servlet context!");
+ } else {
+ return app;
+ }
+ }
+
+ public static String createJsonResponse(String status, String message,
+ String action, Map<String, Object> params) {
+ HashMap<String, Object> response = new HashMap<String, Object>();
+ response.put("status", status);
+ if (message != null) {
+ response.put("message", message);
+ }
+ if (action != null) {
+ response.put("action", action);
+ }
+ if (params != null) {
+ response.putAll(params);
+ }
+
+ return JSONUtils.toJSON(response);
+ }
}
diff --git a/src/java/azkaban/webapp/servlet/AzkabanServletContextListener.java b/src/java/azkaban/webapp/servlet/AzkabanServletContextListener.java
index e1e99f7..f4a755b 100644
--- a/src/java/azkaban/webapp/servlet/AzkabanServletContextListener.java
+++ b/src/java/azkaban/webapp/servlet/AzkabanServletContextListener.java
@@ -25,23 +25,24 @@ import azkaban.webapp.AzkabanWebServer;
* A ServletContextListener that loads the batch application
*/
public class AzkabanServletContextListener implements ServletContextListener {
- public static final String AZKABAN_SERVLET_CONTEXT_KEY = "azkaban_app";
-
- private AzkabanWebServer app;
-
- /**
- * Delete the app
- */
- public void contextDestroyed(ServletContextEvent event) {
- this.app = null;
- }
-
- /**
- * Load the app
- */
- public void contextInitialized(ServletContextEvent event) {
- this.app = new AzkabanWebServer();
-
- event.getServletContext().setAttribute(AZKABAN_SERVLET_CONTEXT_KEY, this.app);
- }
+ public static final String AZKABAN_SERVLET_CONTEXT_KEY = "azkaban_app";
+
+ private AzkabanWebServer app;
+
+ /**
+ * Delete the app
+ */
+ public void contextDestroyed(ServletContextEvent event) {
+ this.app = null;
+ }
+
+ /**
+ * Load the app
+ */
+ public void contextInitialized(ServletContextEvent event) {
+ this.app = new AzkabanWebServer();
+
+ event.getServletContext().setAttribute(AZKABAN_SERVLET_CONTEXT_KEY,
+ this.app);
+ }
}
diff --git a/src/java/azkaban/webapp/servlet/IndexServlet.java b/src/java/azkaban/webapp/servlet/IndexServlet.java
index 0af2f2f..91ab4ba 100644
--- a/src/java/azkaban/webapp/servlet/IndexServlet.java
+++ b/src/java/azkaban/webapp/servlet/IndexServlet.java
@@ -34,33 +34,34 @@ import azkaban.webapp.session.Session;
* The main page
*/
public class IndexServlet extends LoginAbstractAzkabanServlet {
- //private static final Logger logger = Logger.getLogger(IndexServlet.class.getName());
+ // private static final Logger logger =
+ // Logger.getLogger(IndexServlet.class.getName());
- private static final long serialVersionUID = -1;
+ private static final long serialVersionUID = -1;
- @Override
- protected void handleGet(HttpServletRequest req, HttpServletResponse resp, Session session) throws ServletException,
- IOException {
- User user = session.getUser();
-
- ProjectManager manager = this.getApplication().getProjectManager();
- List<Project> projects = manager.getProjects(user);
- Page page = newPage(req, resp, session, "azkaban/webapp/servlet/velocity/index.vm");
- page.add("projects", projects);
- page.render();
- }
+ @Override
+ protected void handleGet(HttpServletRequest req, HttpServletResponse resp,
+ Session session) throws ServletException, IOException {
+ User user = session.getUser();
- @Override
- protected void handlePost(HttpServletRequest req, HttpServletResponse resp, Session session)
- throws ServletException, IOException {
- if(hasParam(req, "action")) {
- String action = getParam(req, "action");
- if (action.equals("create")) {
-
- }
- }
- else {
- resp.sendRedirect(req.getContextPath());
- }
- }
+ ProjectManager manager = this.getApplication().getProjectManager();
+ List<Project> projects = manager.getProjects(user);
+ Page page = newPage(req, resp, session,
+ "azkaban/webapp/servlet/velocity/index.vm");
+ page.add("projects", projects);
+ page.render();
+ }
+
+ @Override
+ protected void handlePost(HttpServletRequest req, HttpServletResponse resp,
+ Session session) throws ServletException, IOException {
+ if (hasParam(req, "action")) {
+ String action = getParam(req, "action");
+ if (action.equals("create")) {
+
+ }
+ } else {
+ resp.sendRedirect(req.getContextPath());
+ }
+ }
}
diff --git a/src/java/azkaban/webapp/servlet/LoginAbstractAzkabanServlet.java b/src/java/azkaban/webapp/servlet/LoginAbstractAzkabanServlet.java
index 76ec115..f568ca3 100644
--- a/src/java/azkaban/webapp/servlet/LoginAbstractAzkabanServlet.java
+++ b/src/java/azkaban/webapp/servlet/LoginAbstractAzkabanServlet.java
@@ -21,81 +21,82 @@ import azkaban.webapp.session.Session;
* verified.
*/
public abstract class LoginAbstractAzkabanServlet extends
- AbstractAzkabanServlet {
-
- private static final long serialVersionUID = 1L;
-
- private static final Logger logger = Logger
- .getLogger(LoginAbstractAzkabanServlet.class.getName());
- private static final String SESSION_ID_NAME = "azkaban.session.id";
-
- @Override
- protected void doGet(HttpServletRequest req, HttpServletResponse resp)
- throws ServletException, IOException {
-
- // Set session id
- Session session = getSessionFromRequest(req);
- if (hasParam(req, "logout")) {
- resp.sendRedirect(req.getContextPath());
- if (session != null) {
- getApplication().getSessionCache().removeSession(
- session.getSessionId());
- }
- return;
- }
-
- if (session != null) {
- logger.info("Found session " + session.getUser());
- handleGet(req, resp, session);
- } else {
- handleLogin(req, resp);
- }
- }
-
- private Session getSessionFromRequest(HttpServletRequest req) {
- Cookie cookie = getCookieByName(req, SESSION_ID_NAME);
- String sessionId = null;
-
- if (cookie != null) {
- sessionId = cookie.getValue();
- logger.info("Session id " + sessionId);
- }
- if (sessionId == null) {
- return null;
- } else {
- return getApplication().getSessionCache().getSession(sessionId);
- }
- }
-
- private void handleLogin(HttpServletRequest req, HttpServletResponse resp)
- throws ServletException, IOException {
- handleLogin(req, resp, null);
- }
-
- private void handleLogin(HttpServletRequest req, HttpServletResponse resp,
- String errorMsg) throws ServletException, IOException {
-
- Page page = newPage(req, resp, "azkaban/webapp/servlet/velocity/login.vm");
- if (errorMsg != null) {
- page.add("errorMsg", errorMsg);
- }
-
- page.render();
- }
-
- @Override
- protected void doPost(HttpServletRequest req, HttpServletResponse resp)
- throws ServletException, IOException {
- if (hasParam(req, "action")) {
- String action = getParam(req, "action");
- if (action.equals("login")) {
- if (hasParam(req, "username") && hasParam(req, "password")) {
- String username = getParam(req, "username");
- String password = getParam(req, "password");
-
- UserManager manager = getApplication().getUserManager();
-
- User user = null;
+ AbstractAzkabanServlet {
+
+ private static final long serialVersionUID = 1L;
+
+ private static final Logger logger = Logger
+ .getLogger(LoginAbstractAzkabanServlet.class.getName());
+ private static final String SESSION_ID_NAME = "azkaban.session.id";
+
+ @Override
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp)
+ throws ServletException, IOException {
+
+ // Set session id
+ Session session = getSessionFromRequest(req);
+ if (hasParam(req, "logout")) {
+ resp.sendRedirect(req.getContextPath());
+ if (session != null) {
+ getApplication().getSessionCache().removeSession(
+ session.getSessionId());
+ }
+ return;
+ }
+
+ if (session != null) {
+ logger.info("Found session " + session.getUser());
+ handleGet(req, resp, session);
+ } else {
+ handleLogin(req, resp);
+ }
+ }
+
+ private Session getSessionFromRequest(HttpServletRequest req) {
+ Cookie cookie = getCookieByName(req, SESSION_ID_NAME);
+ String sessionId = null;
+
+ if (cookie != null) {
+ sessionId = cookie.getValue();
+ logger.info("Session id " + sessionId);
+ }
+ if (sessionId == null) {
+ return null;
+ } else {
+ return getApplication().getSessionCache().getSession(sessionId);
+ }
+ }
+
+ private void handleLogin(HttpServletRequest req, HttpServletResponse resp)
+ throws ServletException, IOException {
+ handleLogin(req, resp, null);
+ }
+
+ private void handleLogin(HttpServletRequest req, HttpServletResponse resp,
+ String errorMsg) throws ServletException, IOException {
+
+ Page page = newPage(req, resp,
+ "azkaban/webapp/servlet/velocity/login.vm");
+ if (errorMsg != null) {
+ page.add("errorMsg", errorMsg);
+ }
+
+ page.render();
+ }
+
+ @Override
+ protected void doPost(HttpServletRequest req, HttpServletResponse resp)
+ throws ServletException, IOException {
+ if (hasParam(req, "action")) {
+ String action = getParam(req, "action");
+ if (action.equals("login")) {
+ if (hasParam(req, "username") && hasParam(req, "password")) {
+ String username = getParam(req, "username");
+ String password = getParam(req, "password");
+
+ UserManager manager = getApplication().getUserManager();
+
+ User user = null;
try {
user = manager.getUser(username, password);
} catch (UserManagerException e) {
@@ -103,89 +104,94 @@ public abstract class LoginAbstractAzkabanServlet extends
return;
}
- String randomUID = UUID.randomUUID().toString();
- Session session = new Session(randomUID, user);
- resp.addCookie(new Cookie(SESSION_ID_NAME, randomUID));
- getApplication().getSessionCache().addSession(session);
- handleGet(req, resp, session);
- } else {
- if (isAjaxCall(req)) {
- String response = createJsonResponse("error", "Incorrect Login.", "login", null);
- writeResponse(resp, response);
- }
- else {
- handleLogin(req, resp, "Enter username and password");
- }
- }
- } else {
- Session session = getSessionFromRequest(req);
- if (session == null) {
- if (isAjaxCall(req)) {
- String response = createJsonResponse("error", "Invalid Session. Need to re-login", "login", null);
- writeResponse(resp, response);
- }
- else {
- handleLogin(req, resp, "Enter username and password");
- }
- } else {
- handlePost(req, resp, session);
- }
- }
- } else {
- Session session = getSessionFromRequest(req);
- if (session == null) {
- if (isAjaxCall(req)) {
- String response = createJsonResponse("error", "Invalid Session. Need to re-login", "login", null);
- writeResponse(resp, response);
- }
- else {
- handleLogin(req, resp, "Enter username and password");
- }
- } else {
- handlePost(req, resp, session);
- }
- }
- }
-
- protected void writeResponse(HttpServletResponse resp, String response) throws IOException {
- Writer writer = resp.getWriter();
- writer.append(response);
- writer.flush();
- }
-
- protected boolean isAjaxCall(HttpServletRequest req) throws ServletException {
- String value = req.getHeader("X-Requested-With");
- if (value != null) {
- logger.info("has X-Requested-With " + value);
- return value.equals("XMLHttpRequest");
- }
-
- return false;
- }
-
- /**
- * The get request is handed off to the implementor after the user is logged in.
- *
- * @param req
- * @param resp
- * @param session
- * @throws ServletException
- * @throws IOException
- */
- protected abstract void handleGet(HttpServletRequest req,
- HttpServletResponse resp, Session session) throws ServletException,
- IOException;
-
- /**
- * The post request is handed off to the implementor after the user is logged in.
- *
- * @param req
- * @param resp
- * @param session
- * @throws ServletException
- * @throws IOException
- */
- protected abstract void handlePost(HttpServletRequest req,
- HttpServletResponse resp, Session session) throws ServletException,
- IOException;
+ String randomUID = UUID.randomUUID().toString();
+ Session session = new Session(randomUID, user);
+ resp.addCookie(new Cookie(SESSION_ID_NAME, randomUID));
+ getApplication().getSessionCache().addSession(session);
+ handleGet(req, resp, session);
+ } else {
+ if (isAjaxCall(req)) {
+ String response = createJsonResponse("error",
+ "Incorrect Login.", "login", null);
+ writeResponse(resp, response);
+ } else {
+ handleLogin(req, resp, "Enter username and password");
+ }
+ }
+ } else {
+ Session session = getSessionFromRequest(req);
+ if (session == null) {
+ if (isAjaxCall(req)) {
+ String response = createJsonResponse("error",
+ "Invalid Session. Need to re-login", "login",
+ null);
+ writeResponse(resp, response);
+ } else {
+ handleLogin(req, resp, "Enter username and password");
+ }
+ } else {
+ handlePost(req, resp, session);
+ }
+ }
+ } else {
+ Session session = getSessionFromRequest(req);
+ if (session == null) {
+ if (isAjaxCall(req)) {
+ String response = createJsonResponse("error",
+ "Invalid Session. Need to re-login", "login", null);
+ writeResponse(resp, response);
+ } else {
+ handleLogin(req, resp, "Enter username and password");
+ }
+ } else {
+ handlePost(req, resp, session);
+ }
+ }
+ }
+
+ protected void writeResponse(HttpServletResponse resp, String response)
+ throws IOException {
+ Writer writer = resp.getWriter();
+ writer.append(response);
+ writer.flush();
+ }
+
+ protected boolean isAjaxCall(HttpServletRequest req)
+ throws ServletException {
+ String value = req.getHeader("X-Requested-With");
+ if (value != null) {
+ logger.info("has X-Requested-With " + value);
+ return value.equals("XMLHttpRequest");
+ }
+
+ return false;
+ }
+
+ /**
+ * The get request is handed off to the implementor after the user is logged
+ * in.
+ *
+ * @param req
+ * @param resp
+ * @param session
+ * @throws ServletException
+ * @throws IOException
+ */
+ protected abstract void handleGet(HttpServletRequest req,
+ HttpServletResponse resp, Session session) throws ServletException,
+ IOException;
+
+ /**
+ * The post request is handed off to the implementor after the user is
+ * logged in.
+ *
+ * @param req
+ * @param resp
+ * @param session
+ * @throws ServletException
+ * @throws IOException
+ */
+ protected abstract void handlePost(HttpServletRequest req,
+ HttpServletResponse resp, Session session) throws ServletException,
+ IOException;
}
\ No newline at end of file
diff --git a/src/java/azkaban/webapp/servlet/MultipartParser.java b/src/java/azkaban/webapp/servlet/MultipartParser.java
index 66fb88f..234f986 100644
--- a/src/java/azkaban/webapp/servlet/MultipartParser.java
+++ b/src/java/azkaban/webapp/servlet/MultipartParser.java
@@ -31,32 +31,32 @@ import org.apache.commons.fileupload.servlet.ServletFileUpload;
public class MultipartParser {
- private DiskFileItemFactory _uploadItemFactory;
-
- public MultipartParser(int spillToDiskSize) {
- _uploadItemFactory = new DiskFileItemFactory();
- _uploadItemFactory.setSizeThreshold(spillToDiskSize);
- }
-
- @SuppressWarnings("unchecked")
- public Map<String, Object> parseMultipart(HttpServletRequest request) throws IOException,
- ServletException {
- ServletFileUpload upload = new ServletFileUpload(_uploadItemFactory);
- List<FileItem> items = null;
- try {
- items = upload.parseRequest(request);
- } catch(FileUploadException e) {
- throw new ServletException(e);
- }
-
- Map<String, Object> params = new HashMap<String, Object>();
- for(FileItem item: items) {
- if(item.isFormField())
- params.put(item.getFieldName(), item.getString());
- else
- params.put(item.getFieldName(), item);
- }
- return params;
- }
+ private DiskFileItemFactory _uploadItemFactory;
+
+ public MultipartParser(int spillToDiskSize) {
+ _uploadItemFactory = new DiskFileItemFactory();
+ _uploadItemFactory.setSizeThreshold(spillToDiskSize);
+ }
+
+ @SuppressWarnings("unchecked")
+ public Map<String, Object> parseMultipart(HttpServletRequest request)
+ throws IOException, ServletException {
+ ServletFileUpload upload = new ServletFileUpload(_uploadItemFactory);
+ List<FileItem> items = null;
+ try {
+ items = upload.parseRequest(request);
+ } catch (FileUploadException e) {
+ throw new ServletException(e);
+ }
+
+ Map<String, Object> params = new HashMap<String, Object>();
+ for (FileItem item : items) {
+ if (item.isFormField())
+ params.put(item.getFieldName(), item.getString());
+ else
+ params.put(item.getFieldName(), item);
+ }
+ return params;
+ }
}
src/java/azkaban/webapp/servlet/Page.java 101(+50 -51)
diff --git a/src/java/azkaban/webapp/servlet/Page.java b/src/java/azkaban/webapp/servlet/Page.java
index 3f0029a..1c52bab 100644
--- a/src/java/azkaban/webapp/servlet/Page.java
+++ b/src/java/azkaban/webapp/servlet/Page.java
@@ -28,58 +28,57 @@ import azkaban.utils.Utils;
* A page to display
*/
public class Page {
- private static final String DEFAULT_MIME_TYPE = "text/html";
- @SuppressWarnings("unused")
+ private static final String DEFAULT_MIME_TYPE = "text/html";
+ @SuppressWarnings("unused")
private final HttpServletRequest request;
- private final HttpServletResponse response;
- private final VelocityEngine engine;
- private final VelocityContext context;
- private final String template;
- private String mimeType = DEFAULT_MIME_TYPE;
- private VelocityUtils utils = new VelocityUtils();
-
- /**
- * Creates a page and sets up the velocity engine to render
- *
- * @param request
- * @param response
- * @param engine
- * @param template
- */
- public Page(HttpServletRequest request,
- HttpServletResponse response,
- VelocityEngine engine,
- String template) {
- this.request = Utils.nonNull(request);
- this.response = Utils.nonNull(response);
- this.engine = Utils.nonNull(engine);
- this.template = Utils.nonNull(template);
- this.context = new VelocityContext();
- this.context.put("utils", utils);
- this.context.put("session", request.getSession(true));
- this.context.put("context", request.getContextPath());
- }
+ private final HttpServletResponse response;
+ private final VelocityEngine engine;
+ private final VelocityContext context;
+ private final String template;
+ private String mimeType = DEFAULT_MIME_TYPE;
+ private VelocityUtils utils = new VelocityUtils();
- /**
- * Renders the page in UTF-8
- */
- public void render() {
- try {
- response.setContentType(mimeType);
- engine.mergeTemplate(template, "UTF-8", context, response.getWriter());
- } catch(Exception e) {
- throw new PageRenderException(e);
- }
- }
+ /**
+ * Creates a page and sets up the velocity engine to render
+ *
+ * @param request
+ * @param response
+ * @param engine
+ * @param template
+ */
+ public Page(HttpServletRequest request, HttpServletResponse response,
+ VelocityEngine engine, String template) {
+ this.request = Utils.nonNull(request);
+ this.response = Utils.nonNull(response);
+ this.engine = Utils.nonNull(engine);
+ this.template = Utils.nonNull(template);
+ this.context = new VelocityContext();
+ this.context.put("utils", utils);
+ this.context.put("session", request.getSession(true));
+ this.context.put("context", request.getContextPath());
+ }
- /**
- * Adds variables to the velocity context.
- */
- public void add(String name, Object value) {
- context.put(name, value);
- }
-
- public void setMimeType(String type) {
- mimeType = type;
- }
+ /**
+ * Renders the page in UTF-8
+ */
+ public void render() {
+ try {
+ response.setContentType(mimeType);
+ engine.mergeTemplate(template, "UTF-8", context,
+ response.getWriter());
+ } catch (Exception e) {
+ throw new PageRenderException(e);
+ }
+ }
+
+ /**
+ * Adds variables to the velocity context.
+ */
+ public void add(String name, Object value) {
+ context.put(name, value);
+ }
+
+ public void setMimeType(String type) {
+ mimeType = type;
+ }
}
diff --git a/src/java/azkaban/webapp/servlet/PageRenderException.java b/src/java/azkaban/webapp/servlet/PageRenderException.java
index 26a4c06..dd63b5f 100644
--- a/src/java/azkaban/webapp/servlet/PageRenderException.java
+++ b/src/java/azkaban/webapp/servlet/PageRenderException.java
@@ -20,9 +20,9 @@ package azkaban.webapp.servlet;
* Thrown if there is an error rendering the page
*/
public class PageRenderException extends RuntimeException {
- private static final long serialVersionUID = -1;
+ private static final long serialVersionUID = -1;
- public PageRenderException(Throwable cause) {
- super(cause);
- }
+ public PageRenderException(Throwable cause) {
+ super(cause);
+ }
}
diff --git a/src/java/azkaban/webapp/servlet/VelocityUtils.java b/src/java/azkaban/webapp/servlet/VelocityUtils.java
index 5430988..00825e4 100644
--- a/src/java/azkaban/webapp/servlet/VelocityUtils.java
+++ b/src/java/azkaban/webapp/servlet/VelocityUtils.java
@@ -5,21 +5,21 @@ import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
public class VelocityUtils {
- public String formatDate(long timestamp) {
- return formatDate(timestamp, "yyyy-MM-dd HH:mm:ss");
- }
-
- public String formatDate(DateTime date) {
- return formatDate(date, "yyyy-MM-dd HH:mm:ss");
- }
-
- public String formatDate(long timestamp, String format) {
- DateTimeFormatter f = DateTimeFormat.forPattern(format);
- return f.print(timestamp);
- }
-
- public String formatDate(DateTime date, String format) {
- DateTimeFormatter f = DateTimeFormat.forPattern(format);
- return f.print(date);
- }
+ public String formatDate(long timestamp) {
+ return formatDate(timestamp, "yyyy-MM-dd HH:mm:ss");
+ }
+
+ public String formatDate(DateTime date) {
+ return formatDate(date, "yyyy-MM-dd HH:mm:ss");
+ }
+
+ public String formatDate(long timestamp, String format) {
+ DateTimeFormatter f = DateTimeFormat.forPattern(format);
+ return f.print(timestamp);
+ }
+
+ public String formatDate(DateTime date, String format) {
+ DateTimeFormatter f = DateTimeFormat.forPattern(format);
+ return f.print(date);
+ }
}
\ No newline at end of file