.classpath | 2 modules/core/util/src/main/java/org/rhq/core/util/StringUtil.java | 15 modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ASUploadConnection.java | 226 +++++----- 3 files changed, 133 insertions(+), 110 deletions(-)
New commits: commit 456999641d532be8d438ecdb60b2b442c0929874 Author: Thomas Segismont tsegismo@redhat.com Date: Thu Dec 20 15:23:15 2012 +0100
Share first modifications
diff --git a/.classpath b/.classpath index d8e11f6..ab18820 100644 --- a/.classpath +++ b/.classpath @@ -190,7 +190,7 @@ <classpathentry exported="true" kind="var" path="M2_REPO/com/sun/xml/bind/jaxb-impl/2.2.4/jaxb-impl-2.2.4.jar"/> <classpathentry exported="true" kind="var" path="M2_REPO/i18nlog/i18nlog/1.0.10/i18nlog-1.0.10.jar"/> <classpathentry exported="true" kind="var" path="M2_REPO/gnu-getopt/getopt/1.0.13/getopt-1.0.13.jar"/> - <classpathentry exported="true" kind="var" path="M2_REPO/commons-httpclient/commons-httpclient/3.0.1/commons-httpclient-3.0.1.jar"/> + <classpathentry exported="true" kind="var" path="M2_REPO/commons-httpclient/commons-httpclient/3.0.1/commons-httpclient-3.0.1.jar" sourcepath="/M2_REPO/commons-httpclient/commons-httpclient/3.0.1/commons-httpclient-3.0.1-sources.jar"/> <classpathentry exported="true" kind="var" path="M2_REPO/jboss/jboss-remoting/2.2.2.SP8/jboss-remoting-2.2.2.SP8.jar"/> <classpathentry exported="true" kind="var" path="M2_REPO/oswego-concurrent/concurrent/1.3.4/concurrent-1.3.4.jar"/> <classpathentry exported="true" kind="var" path="M2_REPO/rss4j/rss4j/0.92-on.2/rss4j-0.92-on.2.jar"/> diff --git a/modules/core/util/src/main/java/org/rhq/core/util/StringUtil.java b/modules/core/util/src/main/java/org/rhq/core/util/StringUtil.java index bf020ca..59a09f2 100644 --- a/modules/core/util/src/main/java/org/rhq/core/util/StringUtil.java +++ b/modules/core/util/src/main/java/org/rhq/core/util/StringUtil.java @@ -284,7 +284,7 @@ public class StringUtil {
for (int i = 0; i < (size - 1); i++) { buf.append(objs.get(i).toString()); - buf.append( delim); + buf.append(delim); }
if (size != 0) { @@ -553,4 +553,17 @@ public class StringUtil { public static boolean isEmpty(String s) { return s == null || s.length() == 0; } + + public static boolean isNotEmpty(String s) { + return !isEmpty(s); + } + + public static boolean isBlank(String s) { + return s == null || s.trim().length() == 0; + } + + public static boolean isNotBlank(String s) { + return !isBlank(s); + } + } \ No newline at end of file diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ASUploadConnection.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ASUploadConnection.java index a7fe82d..3a3b651 100644 --- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ASUploadConnection.java +++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ASUploadConnection.java @@ -21,99 +21,161 @@ package org.rhq.modules.plugins.jbossas7; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.Closeable; +import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; -import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; -import java.io.UnsupportedEncodingException; -import java.net.Authenticator; -import java.net.HttpURLConnection; -import java.net.URL;
+import org.apache.commons.httpclient.Credentials; +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.UsernamePasswordCredentials; +import org.apache.commons.httpclient.auth.AuthScope; +import org.apache.commons.httpclient.methods.GetMethod; +import org.apache.commons.httpclient.methods.PostMethod; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.codehaus.jackson.JsonNode; import org.codehaus.jackson.map.ObjectMapper;
+import org.rhq.core.util.StringUtil; + /** + * TODO review comments of the class. Add message to say that's it's callers resonsability to call finishUpload or cancelUpload in order to free resources + * * Connection for uploading of content. * Partially taken from https://github.com/jbossas/jboss-as/blob/master/testsuite/smoke/src/test/jav... * * @author Jonathan Pearlin (of the original code) * @author Heiko W. Rupp + * */ public class ASUploadConnection {
- private static final String BOUNDARY_PARAM = "NeAG1QNIHHOyB5joAS7Rox!!"; - - private static final String BOUNDARY = "--" + BOUNDARY_PARAM; + private static final String HTTP_SCHEME = "http";
- private static final String CRLF = "\r\n"; + private static final String UPLOAD_URL_PATH = ASConnection.MANAGEMENT + "/add-content";
- private static final String POST_REQUEST_METHOD = "POST"; + private static final int SOCKET_READ_TIMEOUT = 60 * 1000; // 30sec
- private static final String UPLOAD_URL_PATH = ASConnection.MANAGEMENT + "/add-content"; + private static final int SOCKET_CONNECTION_TIMEOUT = 30 * 1000; // 60sec
private static final Log log = LogFactory.getLog(ASUploadConnection.class);
- Authenticator passwordAuthenticator ; - BufferedOutputStream os = null; - InputStream is = null; - private HttpURLConnection connection; + private String scheme = HTTP_SCHEME; + private String host; + private int port; - private int timeout; - private static final int DEFAULT_TIMEOUT = 60; // 60sec
- public ASUploadConnection(String dcHost, int port, String user, String password) { + private Credentials credentials; + + private String fileName; + + private File cacheFile; + + private BufferedOutputStream cacheOutputStream; + + private boolean credentialsProvided() { + // If null user or password is given to the constructor + // no credentials instance is created + return credentials != null; + } + + public ASUploadConnection(String dcHost, int port, String user, String password, String fileName) { if (dcHost == null) { throw new IllegalArgumentException("Management host cannot be null."); } if (port <= 0 || port > 65535) { throw new IllegalArgumentException("Invalid port: " + port); } + if (StringUtil.isBlank(fileName)) { + throw new IllegalArgumentException("Filename cannot be blank"); + } this.host = dcHost; this.port = port; - if (user != null) { - passwordAuthenticator = new AS7Authenticator(user,password); - Authenticator.setDefault(passwordAuthenticator); + if (user != null && password != null) { + credentials = new UsernamePasswordCredentials(user, password); } - timeout = DEFAULT_TIMEOUT; + this.fileName = fileName; }
- public ASUploadConnection(ASConnection asConnection) { - this.host=asConnection.getHost(); - this.port=asConnection.getPort(); - this.timeout = DEFAULT_TIMEOUT; + /** + * TODO : more + * Gives an outpustream where callers should write the content that will be uploaded to AS7 when {@link #finishUpload()} will be called. + * + * @return an outputstream or null if it could not be created. + */ + public OutputStream getOutputStream() { + try { + cacheFile = File.createTempFile("as7upload-" + fileName, "cache"); + cacheOutputStream = new BufferedOutputStream(new FileOutputStream(cacheFile)); + return cacheOutputStream; + } catch (IOException e) { + log.error("Could not create outputstream for " + fileName, e); + } + return null; + + // String url = "http://" + host + ":" + port + UPLOAD_URL_PATH; + // try { + // // Create the HTTP connection to the upload URL + // connection = (HttpURLConnection) new URL(url).openConnection(); + // connection.setConnectTimeout(30 * 1000); // 30s + // connection.setReadTimeout(timeout * 1000); // default 60s + // connection.setDoInput(true); + // connection.setDoOutput(true); + // connection.setRequestMethod(POST_REQUEST_METHOD); + // connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY_PARAM); + // + // // Grab the test WAR file and get a stream to its contents to be included in the POST. + // os = new BufferedOutputStream(connection.getOutputStream()); + // os.write(buildPostRequestHeader(fileName)); + // + // return os; + // } + // catch (Exception e) { + // log.error("Failed to open output stream to URL [" + url + "]: " + e, e); + // } + // + // return null; }
+ /** + * TODO + */ + public void cancelUpload() { + closeQuietly(cacheOutputStream); + cacheFile.delete(); + }
- public OutputStream getOutputStream(String fileName) { - String url = "http://" + host + ":" + port + UPLOAD_URL_PATH; - try { - // Create the HTTP connection to the upload URL - connection = (HttpURLConnection) new URL(url).openConnection(); - connection.setConnectTimeout(30 * 1000); // 30s - connection.setReadTimeout(timeout * 1000); // default 60s - connection.setDoInput(true); - connection.setDoOutput(true); - connection.setRequestMethod(POST_REQUEST_METHOD); - connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY_PARAM); - - // Grab the test WAR file and get a stream to its contents to be included in the POST. - os = new BufferedOutputStream(connection.getOutputStream()); - os.write(buildPostRequestHeader(fileName)); - - return os; - } - catch (Exception e) { - log.error("Failed to open output stream to URL [" + url + "]: " + e, e); - } + /** + * TODO + * @return + */ + public JsonNode finishUpload() {
- return null; - } + closeQuietly(cacheOutputStream); + + String targetURL = scheme + "://" + host + ":" + port + UPLOAD_URL_PATH; + + // TODO : we use the same url for the hack but there maybe is a management endpoint with very little response + // We will issue a simple get request in order to trigger authentication challenge. + // This allows to send the potentially big file only once to the server + // The typical resulting http exchange would be: + // GET without auth <- 401 (start auth challenge : the server will name the realm and the scheme) + // GET with auth <- 200 + // POST big file + GetMethod triggerAuthGET = new GetMethod(targetURL); + + PostMethod filePOST = new PostMethod(targetURL); + + HttpClient client = new HttpClient(); + if (credentialsProvided()) { + client.getState().setCredentials(new AuthScope(host, port, AuthScope.ANY_REALM), credentials); + } + client.getHttpConnectionManager().getParams().setConnectionTimeout(SOCKET_CONNECTION_TIMEOUT); + client.getHttpConnectionManager().getParams().setSoTimeout(SOCKET_READ_TIMEOUT);
- public JsonNode finishUpload() { JsonNode tree = null; try { os.write(buildPostRequestFooter()); @@ -139,18 +201,16 @@ public class ASUploadConnection { ObjectMapper mapper = new ObjectMapper();
String s = builder.toString(); - if (s!=null) + if (s != null) tree = mapper.readTree(s); else log.warn("- no result received from InputStream -"); - } - else + } else log.warn("- no InputStream available -");
} catch (IOException e) { log.error(e); - } - finally { + } finally { closeQuietly(is); closeQuietly(os); } @@ -158,43 +218,8 @@ public class ASUploadConnection { return tree; }
- - private byte[] buildPostRequestHeader(String fileName) throws UnsupportedEncodingException { - final StringBuilder builder = new StringBuilder(); - builder.append(buildPostRequestHeaderSection("form-data; name="file"; filename=""+fileName+""", "application/octet-stream", "")); - return builder.toString().getBytes("US-ASCII"); - } - - private StringBuilder buildPostRequestHeaderSection(final String contentDisposition, final String contentType, final String content) { - final StringBuilder builder = new StringBuilder(); - builder.append(BOUNDARY); - builder.append(CRLF); - if(contentDisposition != null && contentDisposition.length() > 0) { - builder.append(String.format("Content-Disposition: %s", contentDisposition)); - } - builder.append(CRLF); - if(contentType != null && contentType.length() > 0) { - builder.append(String.format("Content-Type: %s", contentType)); - } - builder.append(CRLF); - if(content != null && content.length() > 0) { - builder.append(content); - } - builder.append(CRLF); - return builder; - } - - private byte[] buildPostRequestFooter() throws UnsupportedEncodingException{ - final StringBuilder builder = new StringBuilder(); - builder.append(CRLF); - builder.append(BOUNDARY); - builder.append("--"); - builder.append(CRLF); - return builder.toString().getBytes("US-ASCII"); - } - public static String getFailureDescription(JsonNode jsonNode) { - if (jsonNode==null) + if (jsonNode == null) return "getFailureDescription: -input was null-"; JsonNode node = jsonNode.findValue("failure-description"); return node.getValueAsText(); @@ -212,7 +237,7 @@ public class ASUploadConnection { if (outcome.equals("failed")) { JsonNode reasonNode = in.findValue("failure-description");
- String reason = reasonNode.getTextValue(); + reasonNode.getTextValue(); return true; } } catch (Exception e) { @@ -224,7 +249,7 @@ public class ASUploadConnection { }
private void closeQuietly(final Closeable closeable) { - if(closeable != null) { + if (closeable != null) { try { closeable.close(); } catch (final IOException ignore) { @@ -232,19 +257,4 @@ public class ASUploadConnection { } }
- /** - * Get the currently active upload timeout - * @return timeout in seconds - */ - public int getTimeout() { - return timeout; - } - - /** - * Set upload timeout in seconds. - * @param timeout upload timeout in seconds - */ - public void setTimeout(int timeout) { - this.timeout = timeout; - } }
rhq-commits@lists.fedorahosted.org