You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ace.apache.org by ja...@apache.org on 2012/08/03 13:39:20 UTC
svn commit: r1368896 - in
/ace/sandbox/marrs/org.apache.ace.client.repository.helper.base/src/org/apache/ace/client/repository/helper/base:
ArtifactPreprocessorBase.java VelocityArtifactPreprocessor.java
Author: jawi
Date: Fri Aug 3 11:39:20 2012
New Revision: 1368896
URL: http://svn.apache.org/viewvc?rev=1368896&view=rev
Log:
- Simplified the uploading of preprocessed artifacts to use
only a single thread, instead of two. Also make use of a
ThreadPool in order to be more efficiently with available
resources;
- Added means to test whether the to-be-uploaded artifact
not already exists. This way, some pointless exception
traces can be avoided.
Modified:
ace/sandbox/marrs/org.apache.ace.client.repository.helper.base/src/org/apache/ace/client/repository/helper/base/ArtifactPreprocessorBase.java
ace/sandbox/marrs/org.apache.ace.client.repository.helper.base/src/org/apache/ace/client/repository/helper/base/VelocityArtifactPreprocessor.java
Modified: ace/sandbox/marrs/org.apache.ace.client.repository.helper.base/src/org/apache/ace/client/repository/helper/base/ArtifactPreprocessorBase.java
URL: http://svn.apache.org/viewvc/ace/sandbox/marrs/org.apache.ace.client.repository.helper.base/src/org/apache/ace/client/repository/helper/base/ArtifactPreprocessorBase.java?rev=1368896&r1=1368895&r2=1368896&view=diff
==============================================================================
--- ace/sandbox/marrs/org.apache.ace.client.repository.helper.base/src/org/apache/ace/client/repository/helper/base/ArtifactPreprocessorBase.java (original)
+++ ace/sandbox/marrs/org.apache.ace.client.repository.helper.base/src/org/apache/ace/client/repository/helper/base/ArtifactPreprocessorBase.java Fri Aug 3 11:39:20 2012
@@ -24,16 +24,17 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.io.PipedInputStream;
-import java.io.PipedOutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
import org.apache.ace.client.repository.helper.ArtifactPreprocessor;
-import org.apache.ace.client.repository.helper.PropertyResolver;
import org.apache.ace.connectionfactory.ConnectionFactory;
/**
@@ -42,19 +43,84 @@ import org.apache.ace.connectionfactory.
*/
public abstract class ArtifactPreprocessorBase implements ArtifactPreprocessor {
- protected static final int BUFFER_SIZE = 4 * 1024;
+ /** 64k buffers should be enough for everybody... */
+ protected static final int BUFFER_SIZE = 64 * 1024;
protected final ConnectionFactory m_connectionFactory;
+ private final ExecutorService m_executor;
/**
- * @param connectionFactory
+ * Creates a new {@link ArtifactPreprocessorBase} instance.
+ *
+ * @param connectionFactory the connection factory to use, cannot be <code>null</code>.
*/
protected ArtifactPreprocessorBase(ConnectionFactory connectionFactory) {
m_connectionFactory = connectionFactory;
+ m_executor = Executors.newCachedThreadPool();
+ }
+
+ /**
+ * Creates a new URL for given (file) name and OBR base URL.
+ *
+ * @param name the name of the file to create the URL for;
+ * @param obrBase the OBR base URL to use.
+ * @return a new URL for the file, never <code>null</code>.
+ * @throws MalformedURLException in case of invalid characters in the given name.
+ */
+ protected URL determineNewUrl(String name, URL obrBase) throws MalformedURLException {
+ return new URL(obrBase, name);
+ }
+
+ /**
+ * Silently closes the given {@link Closeable} instance.
+ *
+ * @param closable the closeable to close, may be <code>null</code>.
+ */
+ protected final void silentlyClose(Closeable closable) {
+ if (closable != null) {
+ try {
+ closable.close();
+ }
+ catch (IOException e) {
+ // Ignore; nothing we can/will do about here...
+ }
+ }
}
/**
- * Uploads an artifact to an OBR.
+ * Gets a stream to write an artifact to, which will be uploaded asynchronously to the OBR.
+ *
+ * @param name The name of the artifact.
+ * @param obrBase The base URL of the obr to which this artifact should be written.
+ * @param inputStream the input stream with data to upload.
+ */
+ protected final Future<URL> uploadAsynchronously(final String name, final URL obrBase, final InputStream inputStream) {
+ return m_executor.submit(new Callable<URL>() {
+ public URL call() throws IOException {
+ return upload(inputStream, name, obrBase);
+ }
+ });
+ }
+
+ /**
+ * Converts a given URL to a {@link File} object.
+ *
+ * @param url the URL to convert, cannot be <code>null</code>.
+ * @return a {@link File} object, never <code>null</code>.
+ */
+ protected final File urlToFile(URL url) {
+ File file;
+ try {
+ file = new File(url.toURI());
+ }
+ catch (URISyntaxException e) {
+ file = new File(url.getPath());
+ }
+ return file;
+ }
+
+ /**
+ * Uploads an artifact synchronously to an OBR.
*
* @param input A inputstream from which the artifact can be read.
* @param name The name of the artifact. If the name is not unique, an IOException will be thrown.
@@ -63,7 +129,7 @@ public abstract class ArtifactPreprocess
* @throws IOException If there was an error reading from <code>input</code>, or if there was a problem communicating
* with the OBR.
*/
- protected URL upload(InputStream input, String name, URL obrBase) throws IOException {
+ private URL upload(InputStream input, String name, URL obrBase) throws IOException {
if (obrBase == null) {
throw new IOException("There is no storage available for this artifact.");
}
@@ -75,11 +141,13 @@ public abstract class ArtifactPreprocess
try {
url = determineNewUrl(name, obrBase);
- if ("file".equals(url.getProtocol())) {
- uploadToFile(input, url);
- }
- else {
- uploadToRemote(input, url);
+ if (!urlPointsToExistingFile(url)) {
+ if ("file".equals(url.getProtocol())) {
+ uploadToFile(input, url);
+ }
+ else {
+ uploadToRemote(input, url);
+ }
}
}
catch (IOException ioe) {
@@ -93,88 +161,6 @@ public abstract class ArtifactPreprocess
}
/**
- * Gets a stream to write an artifact to, which will be uploaded to the OBR.
- *
- * @param name The name of the artifact.
- * @param obrBase The base URL of the obr to which this artifact should be written.
- * @return An outputstream, to which the artifact can be written.
- * @throws IOException If there is a problem setting up the outputstream.
- */
- protected OutputStream upload(final String name, final URL obrBase) throws IOException {
- /*
- * This function works by starting a thread which reads from the outputstream which is passed out,
- * and writing it to another stream, which is read by a thread that does the Upload.
- */
- final PipedOutputStream externalOutput = new PipedOutputStream();
- final PipedInputStream externalInput = new PipedInputStream(externalOutput);
-
- final PipedOutputStream internalOutput = new PipedOutputStream();
- final PipedInputStream internalInput = new PipedInputStream(internalOutput);
-
- new Thread(new Runnable() {
- public void run() {
- try {
- byte[] buffer = new byte[BUFFER_SIZE];
- for (int count = externalInput.read(buffer); count != -1; count = externalInput.read(buffer)) {
- internalOutput.write(buffer, 0, count);
- }
- }
- catch (IOException e) {
- // We cannot signal this to the user, but he will notice (in the original thread)
- // that the pipe has been broken.
- e.printStackTrace();
- }
- finally {
- silentlyClose(internalOutput);
- silentlyClose(externalInput);
- }
- }
- }, "upload-Outputstream(" + name + ")").start();
-
- new Thread(new Runnable() {
- public void run() {
- try {
- upload(internalInput, name, obrBase);
- }
- catch (IOException e) {
- // We cannot signal this to the user, but he will notice (in the original thread)
- // that the pipe has been broken.
- e.printStackTrace();
- }
- finally {
- silentlyClose(internalInput);
- silentlyClose(externalOutput);
- }
- }
- }, "upload-Inputstream(" + name + ")").start();
-
- return externalOutput;
- }
-
- protected URL determineNewUrl(String name, URL obrBase) throws MalformedURLException {
- return new URL(obrBase, name);
- }
-
- public abstract String preprocess(String url, PropertyResolver props, String targetID, String version, URL obrBase) throws IOException;
-
- public abstract boolean needsNewVersion(String url, PropertyResolver props, String targetID, String fromVersion);
-
- /**
- * @param closable
- * @throws IOException
- */
- protected final void silentlyClose(Closeable closable) {
- if (closable != null) {
- try {
- closable.close();
- }
- catch (IOException e) {
- // Ignore; nothing we can/will do about here...
- }
- }
- }
-
- /**
* Uploads an artifact to a local file location.
*
* @param input the input stream of the (local) artifact to upload.
@@ -182,13 +168,7 @@ public abstract class ArtifactPreprocess
* @throws IOException in case of I/O problems.
*/
private void uploadToFile(InputStream input, URL url) throws IOException {
- File file;
- try {
- file = new File(url.toURI());
- }
- catch (URISyntaxException e) {
- file = new File(url.getPath());
- }
+ File file = urlToFile(url);
OutputStream output = null;
@@ -217,9 +197,8 @@ public abstract class ArtifactPreprocess
try {
URLConnection connection = m_connectionFactory.createConnection(url);
-
connection.setDoOutput(true);
- connection.setDoInput(true);
+
output = connection.getOutputStream();
byte[] buffer = new byte[BUFFER_SIZE];
@@ -247,4 +226,48 @@ public abstract class ArtifactPreprocess
silentlyClose(output);
}
}
+
+ /**
+ * Determines whether the given URL points to an existing file.
+ *
+ * @param url the URL to test, cannot be <code>null</code>.
+ * @return <code>true</code> if the given URL points to an existing file, <code>false</code> otherwise.
+ */
+ private boolean urlPointsToExistingFile(URL url) {
+ boolean result = false;
+
+ if ("file".equals(url.getProtocol())) {
+ result = urlToFile(url).exists();
+ } else {
+ try {
+ URLConnection connection = m_connectionFactory.createConnection(url);
+
+ if (connection instanceof HttpURLConnection) {
+ HttpURLConnection hc = (HttpURLConnection) connection;
+
+ // Perform a HEAD on the file, to see whether it exists...
+ hc.setRequestMethod("HEAD");
+ try {
+ int responseCode = hc.getResponseCode();
+ result = (responseCode == HttpURLConnection.HTTP_OK);
+ } finally {
+ hc.disconnect();
+ }
+ } else {
+ // In all other scenario's: try to read a single byte from the input
+ // stream, if this succeeds, we can assume the file exists...
+ InputStream is = connection.getInputStream();
+ try {
+ is.read();
+ } finally {
+ silentlyClose(is);
+ }
+ }
+ } catch (IOException e) {
+ // Ignore; assume file does not exist...
+ }
+ }
+
+ return result;
+ }
}
Modified: ace/sandbox/marrs/org.apache.ace.client.repository.helper.base/src/org/apache/ace/client/repository/helper/base/VelocityArtifactPreprocessor.java
URL: http://svn.apache.org/viewvc/ace/sandbox/marrs/org.apache.ace.client.repository.helper.base/src/org/apache/ace/client/repository/helper/base/VelocityArtifactPreprocessor.java?rev=1368896&r1=1368895&r2=1368896&view=diff
==============================================================================
--- ace/sandbox/marrs/org.apache.ace.client.repository.helper.base/src/org/apache/ace/client/repository/helper/base/VelocityArtifactPreprocessor.java (original)
+++ ace/sandbox/marrs/org.apache.ace.client.repository.helper.base/src/org/apache/ace/client/repository/helper/base/VelocityArtifactPreprocessor.java Fri Aug 3 11:39:20 2012
@@ -20,11 +20,9 @@ package org.apache.ace.client.repository
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
-import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
-import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.lang.ref.Reference;
@@ -127,9 +125,7 @@ public class VelocityArtifactPreprocesso
String name = getFilename(url, targetID, version);
- OutputStream output = upload(name, obrBase);
- output.write(result);
- output.close();
+ uploadAsynchronously(name, obrBase, new ByteArrayInputStream(result));
return determineNewUrl(name, obrBase).toString();
}
@@ -168,7 +164,7 @@ public class VelocityArtifactPreprocesso
* @throws MalformedURLException
*/
private String getFilename(String url, String targetID, String version) throws MalformedURLException {
- return new File(new URL(url).getFile()).getName() + "-" + targetID + "-" + version;
+ return urlToFile(new URL(url)).getName() + "-" + targetID + "-" + version;
}
/**