committed changes submitted by dto client

This commit is contained in:
connaryscott 2012-08-18 10:35:26 -07:00
parent 985474989b
commit 4d8959a0fa
7 changed files with 789 additions and 28 deletions

View file

@ -29,12 +29,15 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map.Entry;
import org.apache.commons.lang.StringUtils;
import org.apache.http.cookie.Cookie;
import org.apache.http.Header;
import org.apache.http.HttpException;
import org.apache.http.HttpRequest;
import org.apache.http.HttpRequestInterceptor;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.client.CookieStore;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpDelete;
@ -71,9 +74,12 @@ class ApiCall {
/** RunDeck HTTP header for the auth-token (in case of token-based authentication) */
private static final transient String AUTH_TOKEN_HEADER = "X-RunDeck-Auth-Token";
/** RunDeck HTTP header for the setting session cookie (in case of session-based authentication) */
private static final transient String COOKIE_HEADER = "Cookie";
/** {@link RundeckClient} instance holding the RunDeck url and the credentials */
private final RundeckClient client;
/**
* Build a new instance, linked to the given RunDeck client
*
@ -115,12 +121,14 @@ class ApiCall {
* @see #testLoginAuth()
* @see #testTokenAuth()
*/
public void testAuth() throws RundeckApiLoginException, RundeckApiTokenException {
if (client.getToken() != null) {
public String testAuth() throws RundeckApiLoginException, RundeckApiTokenException {
String sessionID = null;
if (client.getToken() != null || client.getSessionID() != null) {
testTokenAuth();
} else {
testLoginAuth();
sessionID = testLoginAuth();
}
return sessionID;
}
/**
@ -129,13 +137,15 @@ class ApiCall {
* @throws RundeckApiLoginException if the login fails
* @see #testAuth()
*/
public void testLoginAuth() throws RundeckApiLoginException {
public String testLoginAuth() throws RundeckApiLoginException {
String sessionID = null;
HttpClient httpClient = instantiateHttpClient();
try {
login(httpClient);
sessionID = login(httpClient);
} finally {
httpClient.getConnectionManager().shutdown();
}
return sessionID;
}
/**
@ -191,6 +201,24 @@ class ApiCall {
return response;
}
/**
* Execute an HTTP GET request to the RunDeck instance, on the given path. We will login first, and then execute the
* API call without appending the API_ENDPOINT to the URL.
*
* @param apiPath on which we will make the HTTP request - see {@link ApiPathBuilder}
* @return a new {@link InputStream} instance, not linked with network resources
* @throws RundeckApiException in case of error when calling the API
* @throws RundeckApiLoginException if the login fails (in case of login-based authentication)
* @throws RundeckApiTokenException if the token is invalid (in case of token-based authentication)
*/
public InputStream getNonApi(ApiPathBuilder apiPath) throws RundeckApiException, RundeckApiLoginException,
RundeckApiTokenException {
ByteArrayInputStream response = execute(new HttpGet(client.getUrl() + apiPath));
response.reset();
return response;
}
/**
* Execute an HTTP POST request to the RunDeck instance, on the given path. We will login first, and then execute
* the API call. At the end, the given parser will be used to convert the response to a more useful result object.
@ -268,7 +296,7 @@ class ApiCall {
try {
// we only need to manually login in case of login-based authentication
// note that in case of token-based auth, the auth (via an HTTP header) is managed by an interceptor.
if (client.getToken() == null) {
if (client.getToken() == null && client.getSessionID() == null) {
login(httpClient);
}
@ -300,8 +328,9 @@ class ApiCall {
// check the response code (should be 2xx, even in case of error : error message is in the XML result)
if (response.getStatusLine().getStatusCode() / 100 != 2) {
if (response.getStatusLine().getStatusCode() == 403 && client.getToken() != null) {
throw new RundeckApiTokenException("Invalid Token ! Got HTTP response '" + response.getStatusLine()
if (response.getStatusLine().getStatusCode() == 403 &&
(client.getToken() != null || client.getSessionID() != null)) {
throw new RundeckApiTokenException("Invalid Token or sessionID ! Got HTTP response '" + response.getStatusLine()
+ "' for " + request.getURI());
} else {
throw new RundeckApiException("Invalid HTTP response '" + response.getStatusLine() + "' for "
@ -331,9 +360,9 @@ class ApiCall {
* @param httpClient pre-instantiated
* @throws RundeckApiLoginException if the login failed
*/
private void login(HttpClient httpClient) throws RundeckApiLoginException {
private String login(HttpClient httpClient) throws RundeckApiLoginException {
String location = client.getUrl() + "/j_security_check";
String sessionID = null;
while (true) {
HttpPost postLogin = new HttpPost(location);
List<NameValuePair> params = new ArrayList<NameValuePair>();
@ -345,6 +374,20 @@ class ApiCall {
try {
postLogin.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));
response = httpClient.execute(postLogin);
Header cookieHeader = response.getFirstHeader("Set-Cookie");
if(cookieHeader != null){
String cookieStr = cookieHeader.getValue();
if(cookieStr != null){
int i1 = cookieStr.indexOf("JSESSIONID=");
if(i1 >= 0){
cookieStr = cookieStr.substring(i1 + "JSESSIONID=".length());
int i2 = cookieStr.indexOf(";");
if(i2 >= 0){
sessionID = cookieStr.substring(0, i2);
}
}
}
}
} catch (IOException e) {
throw new RundeckApiLoginException("Failed to post login form on " + location, e);
}
@ -380,6 +423,7 @@ class ApiCall {
}
break;
}
return sessionID;
}
/**
@ -426,6 +470,11 @@ class ApiCall {
public void process(HttpRequest request, HttpContext context) throws HttpException, IOException {
if (client.getToken() != null) {
request.addHeader(AUTH_TOKEN_HEADER, client.getToken());
//System.out.println("httpClient adding token header");
}
else if(client.getSessionID() != null) {
request.addHeader(COOKIE_HEADER, "JSESSIONID="+client.getSessionID());
//System.out.println("httpClient adding session header, sessionID="+client.getSessionID());
}
}
});

View file

@ -40,6 +40,7 @@ import org.rundeck.api.domain.RundeckNode;
import org.rundeck.api.domain.RundeckProject;
import org.rundeck.api.domain.RundeckSystemInfo;
import org.rundeck.api.domain.RundeckExecution.ExecutionStatus;
import org.rundeck.api.domain.RundeckOutput;
import org.rundeck.api.parser.AbortParser;
import org.rundeck.api.parser.ExecutionParser;
import org.rundeck.api.parser.HistoryParser;
@ -50,6 +51,7 @@ import org.rundeck.api.parser.NodeParser;
import org.rundeck.api.parser.ProjectParser;
import org.rundeck.api.parser.StringParser;
import org.rundeck.api.parser.SystemInfoParser;
import org.rundeck.api.parser.OutputParser;
import org.rundeck.api.util.AssertUtil;
import org.rundeck.api.util.ParametersUtil;
@ -61,7 +63,7 @@ import org.rundeck.api.util.ParametersUtil;
* <br>
* Usage : <br>
* <code>
* <pre class="prettyprint">
* <pre>
* // using login-based authentication :
* RundeckClient rundeck = new RundeckClient("http://localhost:4440", "admin", "admin");
* // or for a token-based authentication :
@ -87,7 +89,7 @@ public class RundeckClient implements Serializable {
private static final long serialVersionUID = 1L;
/** Version of the API supported */
public static final transient int API_VERSION = 2;
public static final transient int API_VERSION = 5;
/** End-point of the API */
public static final transient String API_ENDPOINT = "/api/" + API_VERSION;
@ -109,6 +111,8 @@ public class RundeckClient implements Serializable {
/** Password to use for authentication on the RunDeck instance (if not using token-based auth) */
private final String password;
private String sessionID;
/**
* Instantiate a new {@link RundeckClient} for the RunDeck instance at the given url, using login-based
@ -131,23 +135,39 @@ public class RundeckClient implements Serializable {
}
/**
* Instantiate a new {@link RundeckClient} for the RunDeck instance at the given url, using token-based
* authentication.
* Instantiate a new {@link RundeckClient} for the RunDeck instance at the given url,
* using token-based or session-based authentication. Either token or sessionID must be valid
*
* @param url of the RunDeck instance ("http://localhost:4440", "http://rundeck.your-compagny.com/", etc)
* @param token to use for authentication on the RunDeck instance
* @param sessionID to use for session authentication on the RunDeck instance
* @param useToken should be true if using token, false if using sessionID
* @throws IllegalArgumentException if the url or token is blank (null, empty or whitespace)
*/
public RundeckClient(String url, String token) throws IllegalArgumentException {
public RundeckClient(String url, String token, String sessionID, boolean useToken) throws IllegalArgumentException {
super();
AssertUtil.notBlank(url, "The RunDeck URL is mandatory !");
AssertUtil.notBlank(token, "The RunDeck auth-token is mandatory !");
AssertUtil.notBlank(url, "The RunDeck URL is mandatory !");
if(useToken){
AssertUtil.notBlank(token, "Token is mandatory!");
this.token = token;
this.sessionID = null;
}
else {
AssertUtil.notBlank(sessionID, "sessionID is mandatory!");
this.sessionID = sessionID;
this.token = null;
}
this.url = url;
this.token = token;
this.login = null;
this.password = null;
}
public RundeckClient(String url, String token) throws IllegalArgumentException {
this(url, token, null, true);
}
/**
* Try to "ping" the RunDeck instance to see if it is alive
*
@ -160,11 +180,12 @@ public class RundeckClient implements Serializable {
/**
* Test the authentication on the RunDeck instance.
*
* @return sessionID if doing username+password login and it succeeded
* @throws RundeckApiLoginException if the login fails (in case of login-based authentication)
* @throws RundeckApiTokenException if the token is invalid (in case of token-based authentication)
*/
public void testAuth() throws RundeckApiLoginException, RundeckApiTokenException {
new ApiCall(this).testAuth();
public String testAuth() throws RundeckApiLoginException, RundeckApiTokenException {
return (new ApiCall(this)).testAuth();
}
/**
@ -366,7 +387,7 @@ public class RundeckClient implements Serializable {
AssertUtil.notBlank(filename, "filename is mandatory to export a job !");
InputStream inputStream = exportJobs(format, project, jobFilter, groupPath, jobIds);
FileUtils.writeByteArrayToFile(new File(filename), IOUtils.toByteArray(inputStream));
}
}
/**
* Export the definitions of all jobs that belongs to the given project
@ -2293,6 +2314,104 @@ public class RundeckClient implements Serializable {
new NodeParser("project/node"));
}
/**
* Get the output of a job execution
*
* @param id of the execution - mandatory
* @return an {@link InputStream} instance, not linked to any network resources - won't be null
* @throws RundeckApiException in case of error when calling the API (non-existent name or project with this name)
* @throws RundeckApiLoginException if the login fails (in case of login-based authentication)
* @throws RundeckApiTokenException if the token is invalid (in case of token-based authentication)
* @throws IllegalArgumentException if the name or project is blank (null, empty or whitespace)
*/
public InputStream getOutput(String executionId) throws RundeckApiException, RundeckApiLoginException,
RundeckApiTokenException, IllegalArgumentException {
AssertUtil.notBlank(executionId, "the execution id is mandatory to get execution output !");
return new ApiCall(this).getNonApi(new ApiPathBuilder("/execution/downloadOutput/", executionId));
}
/**
* Get the html page of the user's profile
*
* @param username - mandatory
* @return an {@link InputStream} instance, not linked to any network resources - won't be null
* @throws RundeckApiException in case of error when calling the API (non-existent name or project with this name)
* @throws RundeckApiLoginException if the login fails (in case of login-based authentication)
* @throws RundeckApiTokenException if the token is invalid (in case of token-based authentication)
* @throws IllegalArgumentException if the name or project is blank (null, empty or whitespace)
*/
public InputStream getProfilePage(String username) throws RundeckApiException, RundeckApiLoginException,
RundeckApiTokenException, IllegalArgumentException {
AssertUtil.notBlank(username, "the username is mandatory to get profile page !");
return new ApiCall(this).getNonApi(new ApiPathBuilder("/user/profile?login=", username));
}
/**
* Generate a new token and get the result page (which is the html page of the user's profile)
*
* @param username - mandatory
* @return an {@link InputStream} instance, not linked to any network resources - won't be null
* @throws RundeckApiException in case of error when calling the API (non-existent name or project with this name)
* @throws RundeckApiLoginException if the login fails (in case of login-based authentication)
* @throws RundeckApiTokenException if the token is invalid (in case of token-based authentication)
* @throws IllegalArgumentException if the name or project is blank (null, empty or whitespace)
*/
public InputStream generateToken(String username) throws RundeckApiException, RundeckApiLoginException,
RundeckApiTokenException, IllegalArgumentException {
AssertUtil.notBlank(username, "the username is mandatory to generate the token");
return new ApiCall(this).getNonApi(new ApiPathBuilder("/user/generateApiToken?login=", username));
}
/**
* Get the execution output of the given job
*
* @param executionId identifier of the execution - mandatory
* @param offset byte offset to read from in the file. 0 indicates the beginning.
* @param lastlines nnumber of lines to retrieve from the end of the available output. If specified it will override the offset value and return only the specified number of lines at the end of the log.
* @param lastmod epoch datestamp in milliseconds, return results only if modification changed since the specified date OR if more data is available at the given offset
* @param maxlines maximum number of lines to retrieve forward from the specified offset.
* @return {@link RundeckOutput}
* @throws RundeckApiException in case of error when calling the API (non-existent job with this ID)
* @throws RundeckApiLoginException if the login fails (in case of login-based authentication)
* @throws RundeckApiTokenException if the token is invalid (in case of token-based authentication)
* @throws IllegalArgumentException if the jobId is blank (null, empty or whitespace)
*/
public RundeckOutput getJobExecutionOutput(Long executionId, int offset, int lastlines, long lastmod, int maxlines)
throws RundeckApiException, RundeckApiLoginException, RundeckApiTokenException, IllegalArgumentException {
AssertUtil.notNull(executionId, "executionId is mandatory to get the output of a job execution!");
return new ApiCall(this).get(new ApiPathBuilder("/execution/", executionId.toString(), "/output.xml").param("offset", offset)
.param("lastlines", lastlines)
.param("lastmod", lastmod)
.param("maxlines", maxlines),
new OutputParser("result/output"));
}
/**
* Get the execution output of the given job
*
* @param jobId identifier of the job - mandatory
* @param offset byte offset to read from in the file. 0 indicates the beginning.
* @param lastmod epoch datestamp in milliseconds, return results only if modification changed since the specified date OR if more data is available at the given offset
* @param maxlines maximum number of lines to retrieve forward from the specified offset.
* @return {@link RundeckOutput}
* @throws RundeckApiException in case of error when calling the API (non-existent job with this ID)
* @throws RundeckApiLoginException if the login fails (in case of login-based authentication)
* @throws RundeckApiTokenException if the token is invalid (in case of token-based authentication)
* @throws IllegalArgumentException if the jobId is blank (null, empty or whitespace)
*/
public RundeckOutput getJobExecutionOutput(Long executionId, int offset, long lastmod, int maxlines)
throws RundeckApiException, RundeckApiLoginException, RundeckApiTokenException, IllegalArgumentException {
AssertUtil.notNull(executionId, "executionId is mandatory to get the output of a job execution!");
return new ApiCall(this).get(new ApiPathBuilder("/execution/", executionId.toString(), "/output.xml").param("offset", offset)
.param("lastmod", lastmod)
.param("maxlines", maxlines),
new OutputParser("result/output"));
}
/*
* System Info
*/
@ -2318,26 +2437,33 @@ public class RundeckClient implements Serializable {
}
/**
* @return the auth-token used for authentication on the RunDeck instance (null if using login-based auth)
* @return the auth-token used for authentication on the RunDeck instance (null if using login-based or session-based auth)
*/
public String getToken() {
return token;
}
/**
* @return the login used for authentication on the RunDeck instance (null if using token-based auth)
* @return the login used for authentication on the RunDeck instance (null if using token-based or session-based auth)
*/
public String getLogin() {
return login;
}
/**
* @return the password used for authentication on the RunDeck instance (null if using token-based auth)
* @return the password used for authentication on the RunDeck instance (null if using token-based or session-based auth)
*/
public String getPassword() {
return password;
}
/**
* @return the sessionID used for authentication on the RunDeck instance (null if using login-based or token-based auth)
*/
public String getSessionID() {
return sessionID;
}
@Override
public String toString() {
StringBuilder str = new StringBuilder();

View file

@ -0,0 +1,292 @@
package org.rundeck.api.domain;
import java.util.List;
import java.util.ArrayList;
import java.io.Serializable;
import org.rundeck.api.domain.RundeckExecution.ExecutionStatus;
/**
* Represents a RunDeck output
*
*/
public class RundeckOutput implements Serializable {
private static final long serialVersionUID = 1L;
private Long executionId;
//private String message = null;
//private String error = null;
private Boolean unmodified;
private Boolean empty;
private int offset;
private Boolean completed = false;
private Boolean execCompleted = false;
private Boolean hasFailedNodes = false;
private RundeckExecution.ExecutionStatus status = null;
private Long lastModified;
private Long execDuration;
private Float percentLoaded;
private int totalSize;
List<RundeckOutputEntry> logEntries = null;
public Long getExecutionId() {
return executionId;
}
public void setExecutionId(Long executionId) {
this.executionId = executionId;
}
/*public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getError() {
return error;
}
public void setError(String error) {
this.error = error;
}*/
public Boolean isUnmodified() {
return unmodified;
}
public void setUnmodified(Boolean unmodified) {
this.unmodified = unmodified;
}
public Boolean isEmpty() {
return empty;
}
public void setEmpty(Boolean empty) {
this.empty = empty;
}
public int getOffset() {
return offset;
}
public void setOffset(int offset) {
this.offset = offset;
}
public Boolean isCompleted() {
return completed;
}
public void setCompleted(Boolean completed) {
this.completed = completed;
}
public Boolean isExecCompleted() {
return execCompleted;
}
public void setExecCompleted(Boolean execCompleted) {
this.execCompleted = execCompleted;
}
public Boolean isHasFailedNodes() {
return hasFailedNodes;
}
public void setHasFailedNodes(Boolean hasFailedNodes) {
this.hasFailedNodes = hasFailedNodes;
}
public RundeckExecution.ExecutionStatus getStatus() {
return status;
}
public void setStatus(RundeckExecution.ExecutionStatus status) {
this.status = status;
}
public Long getLastModified() {
return lastModified;
}
public void setLastModified(Long lastModified) {
this.lastModified = lastModified;
}
public Long getExecDuration() {
return execDuration;
}
public void setExecDuration(Long execDuration) {
this.execDuration = execDuration;
}
public Float getPercentLoaded() {
return percentLoaded;
}
public void setPercentLoaded(Float percentLoaded) {
this.percentLoaded = percentLoaded;
}
public int getTotalSize() {
return totalSize;
}
public void setTotalSize(int totalSize) {
this.totalSize = totalSize;
}
public List<RundeckOutputEntry> getLogEntries() {
return logEntries;
}
public void setLogEntries(List<RundeckOutputEntry> logEntries) {
this.logEntries = logEntries;
}
public void addLogEntry(RundeckOutputEntry entry){
if(logEntries == null){
logEntries = new ArrayList<RundeckOutputEntry>();
}
logEntries.add(entry);
}
@Override
public String toString() {
return "RundeckOutput [executionId=" + executionId + /*", message=" + message +
", error=" + error +*/ ", unmodified=" + unmodified + ", empty=" + empty +
", offset=" + offset + ", completed=" + completed +
", execCompleted=" + execCompleted + ", hasFailedNodes=" + hasFailedNodes +
", status=" + status + ", lastModified=" + lastModified +
", execDuration=" + execDuration + ", percentLoaded=" + percentLoaded +
", totalSize=" + totalSize + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((executionId == null) ? 0 : executionId.hashCode());
// result = prime * result + ((message == null) ? 0 : message.hashCode());
// result = prime * result + ((error == null) ? 0 : error.hashCode());
result = prime * result + ((unmodified == null) ? 0 : unmodified.hashCode());
result = prime * result + ((empty == null) ? 0 : empty.hashCode());
result = prime * result + offset;
result = prime * result + ((completed == null) ? 0 : completed.hashCode());
result = prime * result + ((execCompleted == null) ? 0 : execCompleted.hashCode());
result = prime * result + ((hasFailedNodes == null) ? 0 : hasFailedNodes.hashCode());
result = prime * result + ((status == null) ? 0 : status.hashCode());
result = prime * result + ((lastModified == null) ? 0 : lastModified.hashCode());
result = prime * result + ((execDuration == null) ? 0 : execDuration.hashCode());
result = prime * result + ((percentLoaded == null) ? 0 : percentLoaded.hashCode());
result = prime * result + totalSize;
result = prime * result + ((logEntries == null) ? 0 : logEntries.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
RundeckOutput other = (RundeckOutput) obj;
if (executionId == null) {
if (other.executionId != null)
return false;
} else if (!executionId.equals(other.executionId))
return false;
/* if (message == null) {
if (other.message != null)
return false;
} else if (!message.equals(other.message))
return false;
if (error == null) {
if (other.error != null)
return false;
} else if (!error.equals(other.error))
return false;
*/
if (unmodified == null) {
if (other.unmodified != null)
return false;
} else if (!unmodified.equals(other.unmodified))
return false;
if (empty == null) {
if (other.empty != null)
return false;
} else if (!empty.equals(other.empty))
return false;
if (offset != other.offset)
return false;
if (completed == null) {
if (other.completed != null)
return false;
} else if (!completed.equals(other.completed))
return false;
if (execCompleted == null) {
if (other.execCompleted != null)
return false;
} else if (!execCompleted.equals(other.execCompleted))
return false;
if (hasFailedNodes == null) {
if (other.hasFailedNodes != null)
return false;
} else if (!hasFailedNodes.equals(other.hasFailedNodes))
return false;
if (status == null) {
if (other.status != null)
return false;
} else if (!status.equals(other.status))
return false;
if (lastModified == null) {
if (other.lastModified != null)
return false;
} else if (!lastModified.equals(other.lastModified))
return false;
if (execDuration == null) {
if (other.execDuration != null)
return false;
} else if (!execDuration.equals(other.execDuration))
return false;
if (percentLoaded == null) {
if (other.percentLoaded != null)
return false;
} else if (!percentLoaded.equals(other.percentLoaded))
return false;
if (totalSize != other.totalSize)
return false;
if (logEntries == null) {
if (other.logEntries != null)
return false;
} else if (!logEntries.equals(other.logEntries))
return false;
return true;
}
}

View file

@ -0,0 +1,146 @@
package org.rundeck.api.domain;
import java.io.Serializable;
/**
* Represents a RunDeck output entry
*
*/
public class RundeckOutputEntry implements Serializable {
private static final long serialVersionUID = 1L;
private String time = null;
private RundeckLogLevel level = null;
private String message = null;
private String user = null;
private String command = null;
private String node = null;
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
public RundeckLogLevel getLevel() {
return level;
}
public void setLevel(RundeckLogLevel level) {
this.level = level;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public String getCommand() {
return command;
}
public void setCommand(String command) {
this.command = command;
}
public String getNode() {
return node;
}
public void setNode(String node) {
this.node = node;
}
@Override
public String toString() {
return "RundeckOutputEntry [time=" + time + ", level=" + level +
", message=" + message + ", user=" + user + ", command=" +
command + ", node=" + node + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((time == null) ? 0 : time.hashCode());
result = prime * result + ((level == null) ? 0 : level.hashCode());
result = prime * result + ((message == null) ? 0 : message.hashCode());
result = prime * result + ((user == null) ? 0 : user.hashCode());
result = prime * result + ((command == null) ? 0 : command.hashCode());
result = prime * result + ((node == null) ? 0 : node.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
RundeckOutputEntry other = (RundeckOutputEntry) obj;
if (time == null) {
if (other.time != null)
return false;
} else if (!time.equals(other.time))
return false;
if (level == null) {
if (other.level != null)
return false;
} else if (!level.equals(other.level))
return false;
if (message == null) {
if (other.message != null)
return false;
} else if (!message.equals(other.message))
return false;
if (user == null) {
if (other.user != null)
return false;
} else if (!user.equals(other.user))
return false;
if (command == null) {
if (other.command != null)
return false;
} else if (!command.equals(other.command))
return false;
if (node == null) {
if (other.node != null)
return false;
} else if (!node.equals(other.node))
return false;
return true;
}
public static enum RundeckLogLevel {
SEVERE, WARNING, INFO, CONFIG, FINEST;
}
}

View file

@ -0,0 +1,47 @@
package org.rundeck.api.parser;
import org.apache.commons.lang.StringUtils;
import org.dom4j.Node;
import org.rundeck.api.domain.RundeckOutputEntry;
import org.rundeck.api.domain.RundeckOutputEntry.RundeckLogLevel;
public class OutputEntryParser implements XmlNodeParser<RundeckOutputEntry> {
private String xpath;
public OutputEntryParser() {
super();
}
/**
* @param xpath of the event element if it is not the root node
*/
public OutputEntryParser(String xpath) {
super();
this.xpath = xpath;
}
@Override
public RundeckOutputEntry parseXmlNode(Node node) {
Node entryNode = xpath != null ? node.selectSingleNode(xpath) : node;
RundeckOutputEntry outputEntry = new RundeckOutputEntry();
outputEntry.setTime(StringUtils.trimToNull(entryNode.valueOf("@time")));
try {
outputEntry.setLevel(RundeckLogLevel.valueOf(StringUtils.upperCase(entryNode.valueOf("@level"))));
} catch (IllegalArgumentException e) {
outputEntry.setLevel(null);
}
outputEntry.setUser(StringUtils.trimToNull(entryNode.valueOf("@user")));
outputEntry.setCommand(StringUtils.trimToNull(entryNode.valueOf("@command")));
outputEntry.setNode(StringUtils.trimToNull(entryNode.valueOf("@node")));
outputEntry.setMessage(StringUtils.trimToNull(entryNode.getStringValue()));
return outputEntry;
}
}

View file

@ -0,0 +1,101 @@
package org.rundeck.api.parser;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.dom4j.Node;
import org.rundeck.api.domain.RundeckOutput;
import org.rundeck.api.domain.RundeckOutputEntry;
import org.rundeck.api.domain.RundeckExecution;
import org.rundeck.api.domain.RundeckExecution.ExecutionStatus;
public class OutputParser implements XmlNodeParser<RundeckOutput> {
private String xpath;
public OutputParser() {
super();
}
/**
* @param xpath of the event element if it is not the root node
*/
public OutputParser(String xpath) {
super();
this.xpath = xpath;
}
@Override
public RundeckOutput parseXmlNode(Node node) {
Node entryNode = xpath != null ? node.selectSingleNode(xpath) : node;
RundeckOutput output = new RundeckOutput();
//output.setMessage(StringUtils.trimToNull(entryNode.valueOf("message")));
//output.setError(StringUtils.trimToNull(entryNode.valueOf("error")));
try{
output.setExecutionId(Long.valueOf(entryNode.valueOf("id")));
} catch (NumberFormatException e) {
output.setExecutionId(null);
}
try{
output.setOffset(Integer.valueOf(entryNode.valueOf("offset")));
} catch (NumberFormatException e) {
output.setOffset(-1);
}
output.setCompleted(Boolean.valueOf(entryNode.valueOf("completed")));
output.setExecCompleted(Boolean.valueOf(entryNode.valueOf("execCompleted")));
output.setHasFailedNodes(Boolean.valueOf(entryNode.valueOf("hasFailedNodes")));
try {
output.setStatus(RundeckExecution.ExecutionStatus.valueOf(StringUtils.upperCase(entryNode.valueOf("execState"))));
} catch (IllegalArgumentException e) {
output.setStatus(null);
}
try{
output.setLastModified(Long.valueOf(entryNode.valueOf("lastModified")));
} catch (NumberFormatException e) {
output.setLastModified(null);
}
try{
output.setExecDuration(Long.valueOf(entryNode.valueOf("execDuration")));
} catch (NumberFormatException e) {
output.setExecDuration(null);
}
try{
output.setPercentLoaded(Float.valueOf(entryNode.valueOf("percentLoaded")));
} catch (NumberFormatException e) {
output.setPercentLoaded(null);
}
try{
output.setTotalSize(Integer.valueOf(entryNode.valueOf("totalSize")));
} catch (NumberFormatException e) {
output.setTotalSize(-1);
}
Node entriesListNode = entryNode.selectSingleNode("entries");
if(entriesListNode != null){
@SuppressWarnings("unchecked")
List<Node> entries = entriesListNode.selectNodes("entry");
OutputEntryParser entryParser = new OutputEntryParser();
for (Node logEntryNode : entries) {
RundeckOutputEntry outputEntry = entryParser.parseXmlNode(logEntryNode);
output.addLogEntry(outputEntry);
}
}
return output;
}
}

View file

@ -4,11 +4,11 @@ interactions:
- recorded: 2011-09-18T16:04:45.973Z
request:
method: GET
uri: http://rundeck.local:4440/api/2/projects
uri: http://rundeck.local:4440/api/5/projects
headers:
Host: rundeck.local:4440
Proxy-Connection: Keep-Alive
User-Agent: RunDeck API Java Client 2
User-Agent: RunDeck API Java Client 5
X-RunDeck-Auth-Token: PVnN5K3OPc5vduS3uVuVnEsD57pDC5pd
response:
status: 200
@ -17,4 +17,4 @@ interactions:
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Server: Jetty(6.1.21)
Set-Cookie: JSESSIONID=mxrbh6byhvxt;Path=/
body: <result success='true' apiversion='2'><projects count='1'><project><name>test</name><description></description></project></projects></result>
body: <result success='true' apiversion='5'><projects count='1'><project><name>test</name><description></description></project></projects></result>