Author: marrs
Date: Thu Mar 22 21:18:20 2012
New Revision: 1304071
URL: http://svn.apache.org/viewvc?rev=1304071&view=rev
Log:
ACE-174 applied the patch
Added:
ace/trunk/ace-client-repository-helper-base/src/test/
ace/trunk/ace-client-repository-helper-base/src/test/java/
ace/trunk/ace-client-repository-helper-base/src/test/java/org/
ace/trunk/ace-client-repository-helper-base/src/test/java/org/apache/
ace/trunk/ace-client-repository-helper-base/src/test/java/org/apache/ace/
ace/trunk/ace-client-repository-helper-base/src/test/java/org/apache/ace/client/
ace/trunk/ace-client-repository-helper-base/src/test/java/org/apache/ace/client/repository/
ace/trunk/ace-client-repository-helper-base/src/test/java/org/apache/ace/client/repository/helper/
ace/trunk/ace-client-repository-helper-base/src/test/java/org/apache/ace/client/repository/helper/base/
ace/trunk/ace-client-repository-helper-base/src/test/java/org/apache/ace/client/repository/helper/base/VelocityArtifactPreprocessorTest.java
Modified:
ace/trunk/ace-client-repository-helper-base/src/main/java/org/apache/ace/client/repository/helper/base/ArtifactPreprocessorBase.java
ace/trunk/ace-client-repository-helper-base/src/main/java/org/apache/ace/client/repository/helper/base/VelocityArtifactPreprocessor.java
Modified:
ace/trunk/ace-client-repository-helper-base/src/main/java/org/apache/ace/client/repository/helper/base/ArtifactPreprocessorBase.java
URL:
http://svn.apache.org/viewvc/ace/trunk/ace-client-repository-helper-base/src/main/java/org/apache/ace/client/repository/helper/base/ArtifactPreprocessorBase.java?rev=1304071&r1=1304070&r2=1304071&view=diff
==============================================================================
---
ace/trunk/ace-client-repository-helper-base/src/main/java/org/apache/ace/client/repository/helper/base/ArtifactPreprocessorBase.java
(original)
+++
ace/trunk/ace-client-repository-helper-base/src/main/java/org/apache/ace/client/repository/helper/base/ArtifactPreprocessorBase.java
Thu Mar 22 21:18:20 2012
@@ -18,6 +18,7 @@
*/
package org.apache.ace.client.repository.helper.base;
+import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -37,7 +38,7 @@ import org.apache.ace.client.repository.
*/
public abstract class ArtifactPreprocessorBase implements ArtifactPreprocessor
{
- private static final int BUFFER_SIZE = 4 * 1024;
+ protected static final int BUFFER_SIZE = 4 * 1024;
/**
* Uploads an artifact to an OBR.
@@ -87,22 +88,8 @@ public abstract class ArtifactPreprocess
throw new IOException("Error uploading " + name + ": " +
ioe.getMessage());
}
finally {
- if (input != null) {
- try {
- input.close();
- }
- catch (Exception ex) {
- // Not much we can do
- }
- }
- if (output != null) {
- try {
- output.close();
- }
- catch (Exception ex) {
- // Not much we can do
- }
- }
+ silentlyClose(input);
+ silentlyClose(output);
}
return url;
@@ -120,7 +107,7 @@ public abstract class ArtifactPreprocess
* 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.
*/
- PipedOutputStream externalOutput = new PipedOutputStream();
+ final PipedOutputStream externalOutput = new PipedOutputStream();
final PipedInputStream externalInput = new
PipedInputStream(externalOutput);
final PipedOutputStream internalOutput = new PipedOutputStream();
@@ -137,20 +124,11 @@ public abstract class ArtifactPreprocess
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 {
- try {
- internalOutput.close();
- }
- catch (IOException e) {
- // Not much to be done.
- }
- try {
- externalInput.close();
- }
- catch (IOException e) {
- // Not much to be done.
- }
+ silentlyClose(internalOutput);
+ silentlyClose(externalInput);
}
}
}, "upload-Outputstream(" + name + ")").start();
@@ -163,6 +141,10 @@ public abstract class ArtifactPreprocess
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();
@@ -177,4 +159,21 @@ public abstract class ArtifactPreprocess
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...
+ }
+ }
+ }
+
}
Modified:
ace/trunk/ace-client-repository-helper-base/src/main/java/org/apache/ace/client/repository/helper/base/VelocityArtifactPreprocessor.java
URL:
http://svn.apache.org/viewvc/ace/trunk/ace-client-repository-helper-base/src/main/java/org/apache/ace/client/repository/helper/base/VelocityArtifactPreprocessor.java?rev=1304071&r1=1304070&r2=1304071&view=diff
==============================================================================
---
ace/trunk/ace-client-repository-helper-base/src/main/java/org/apache/ace/client/repository/helper/base/VelocityArtifactPreprocessor.java
(original)
+++
ace/trunk/ace-client-repository-helper-base/src/main/java/org/apache/ace/client/repository/helper/base/VelocityArtifactPreprocessor.java
Thu Mar 22 21:18:20 2012
@@ -27,13 +27,14 @@ import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
+import java.lang.ref.WeakReference;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
-import java.util.HashMap;
import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
import org.apache.ace.client.repository.helper.PropertyResolver;
import org.apache.velocity.VelocityContext;
@@ -45,118 +46,187 @@ import org.apache.velocity.app.Velocity;
*/
public class VelocityArtifactPreprocessor extends ArtifactPreprocessorBase {
- private static final int BUFFER_SIZE = 1024;
- private Map<String, byte[]> m_cachedArtifacts = new HashMap<String,
byte[]>();
- private Map<String, String> m_cachedHashes = new HashMap<String, String>();
-
private static Object m_initLock = new Object();
private static boolean m_velocityInitialized = false;
- private void init() throws IOException {
- if (m_velocityInitialized) {
- return;
+ private final Map<String, WeakReference<byte[]>> m_cachedArtifacts;
+ private final Map<String, WeakReference<String>> m_cachedHashes;
+ private final MessageDigest m_md5;
+
+ /**
+ * Creates a new {@link VelocityArtifactPreprocessor} instance.
+ */
+ public VelocityArtifactPreprocessor() {
+ try {
+ m_md5 = MessageDigest.getInstance("MD5");
}
- else {
- synchronized (m_initLock) {
- if (!m_velocityInitialized) {
- try {
- Velocity.init();
- m_velocityInitialized = true;
- }
- catch (Exception e) {
- // Something went seriously bad initializing velocity.
- throw new IOException("Error initializing Velocity: "
+ e.getMessage());
- }
- }
- }
+ catch (NoSuchAlgorithmException e) {
+ throw new RuntimeException("Failed to create
VelocityArtifactPreprocessor instance!", e);
}
+
+ m_cachedArtifacts = new ConcurrentHashMap<String,
WeakReference<byte[]>>();
+ m_cachedHashes = new ConcurrentHashMap<String,
WeakReference<String>>();
}
@Override
- public String preprocess(String url, PropertyResolver props, String
targetID, String version, URL obrBase) throws IOException {
- init();
- // first, get the original data.
+ public boolean needsNewVersion(String url, PropertyResolver props, String
targetID, String fromVersion) {
+ // get the template
byte[] input = null;
+ byte[] result = null;
+
try {
+ init();
+
input = getArtifactAsBytes(url);
+ result = process(input, props);
}
catch (IOException ioe) {
- throw new IOException("Error retrieving the original artifact for
preprocessing: " + ioe.getMessage());
+ // problem initializing velocity, or we cannot retrieve the
+ // original artifact, or process it; we can't say anything now.
+ return true;
}
// process the template
+ // first check: did we need any processing at all?
+ if (Arrays.equals(result, input)) {
+ return false;
+ }
+
+ // hash the processed template
+ String newHash = hash(result);
+
+ // find the hash for the previous version
+ String oldHash = getHashForVersion(url, targetID, fromVersion);
+
+ // Note: we do not cache any previously created processed templates,
since the call that asks us to approve a new version
+ // may cross a pending needsNewVersion call.
+ return !newHash.equals(oldHash);
+ }
+
+ @Override
+ public String preprocess(String url, PropertyResolver props, String
targetID, String version, URL obrBase) throws IOException {
+ init();
+
+ // first, get the original data.
+ byte[] input = getArtifactAsBytes(url);
+ // process the template
byte[] result = process(input, props);
+ // first check: did we need any processing at all?
if (Arrays.equals(result, input)) {
+ // template isn't modified; use direct URL instead...
return url;
}
+
+ setHashForVersion(url, targetID, version, hash(result));
+
+ String name = getFilename(url, targetID, version);
+
+ OutputStream output = upload(name, obrBase);
+ output.write(result);
+ output.close();
+
+ return determineNewUrl(name, obrBase).toString();
+ }
+
+ /**
+ * Initializes this preprocessor by making sure {@link Velocity#init()} is
called.
+ * <p>This method may be called multiple times.</p>
+ *
+ * @throws IOException in case of problems initializing Velocity.
+ */
+ private void init() throws IOException {
+ if (m_velocityInitialized) {
+ return;
+ }
else {
- try {
- String name = getFilename(url, targetID, version);
- OutputStream output = upload(name, obrBase);
- output.write(result);
- output.close();
- setHashForVersion(url, targetID, version, hash(result));
- return determineNewUrl(name, obrBase).toString();
- }
- catch (IOException ioe) {
- throw new IOException("Error storing the processed: " +
ioe.getMessage());
+ synchronized (m_initLock) {
+ if (!m_velocityInitialized) {
+ try {
+ Velocity.init();
+ m_velocityInitialized = true;
+ }
+ catch (Exception e) {
+ // Something went seriously bad initializing velocity.
+ throw new IOException("Error initializing Velocity: "
+ e.getMessage());
+ }
+ }
}
}
}
+ /**
+ * @param url
+ * @param targetID
+ * @param version
+ * @return
+ * @throws MalformedURLException
+ */
private String getFilename(String url, String targetID, String version)
throws MalformedURLException {
return new File(new URL(url).getFile()).getName() + "-" + targetID +
"-" + version;
}
+ /**
+ * @param url
+ * @param targetID
+ * @param version
+ * @return
+ * @throws MalformedURLException
+ */
private String getFullUrl(String url, String targetID, String version)
throws MalformedURLException {
return url + "-" + targetID + "-" + version;
}
+ /**
+ * @param url
+ * @param target
+ * @param version
+ * @return
+ */
private String getHashForVersion(String url, String target, String
version) {
- String key = new StringBuilder().append('[')
- .append(url)
- .append("][")
- .append(target)
- .append("][")
- .append(version)
- .append(']').toString();
+ String key = createHashKey(url, target, version);
+ String result = null;
- if (m_cachedHashes.containsKey(key)) {
- return m_cachedHashes.get(key);
- }
- else {
- byte[] processedTemplate;
+ WeakReference<String> ref = m_cachedHashes.get(key);
+ if (ref == null || ((result = ref.get()) == null)) {
try {
- processedTemplate = getBytesFromUrl(getFullUrl(url, target,
version));
+ result = hash(getBytesFromUrl(getFullUrl(url, target,
version)));
+
+ m_cachedHashes.put(key, new WeakReference<String>(result));
}
catch (IOException e) {
// we cannot retrieve the artifact, so we cannot say anything
about it.
- return null;
}
- String result = hash(processedTemplate);
-
- m_cachedHashes.put(key, result);
- return result;
}
+
+ return result;
}
+ /**
+ * @param url
+ * @param target
+ * @param version
+ * @param hash
+ */
private void setHashForVersion(String url, String target, String version,
String hash) {
- String key = new StringBuilder().append('[')
- .append(url)
- .append("][")
- .append(target)
- .append("][")
- .append(version)
- .append(']').toString();
+ String key = createHashKey(url, target, version);
- m_cachedHashes.put(key, hash);
+ m_cachedHashes.put(key, new WeakReference<String>(hash));
}
+ /**
+ * Applies the template processor to the given byte array.
+ *
+ * @param input the template (as byte array) to process;
+ * @param props the {@link PropertyResolver} to use.
+ * @return the processed template, never <code>null</code>.
+ * @throws IOException in case of I/O problems.
+ */
private byte[] process(byte[] input, PropertyResolver props) throws
IOException {
+ VelocityContext context = new VelocityContext();
+ context.put("context", props);
+
try {
- VelocityContext context = new VelocityContext();
- context.put("context", props);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Writer writer = new OutputStreamWriter(baos);
Velocity.evaluate(context, writer, "", new InputStreamReader(new
ByteArrayInputStream(input)));
@@ -169,77 +239,77 @@ public class VelocityArtifactPreprocesso
}
/**
- * Helper method, which reads all information from a stream, and returns
that as a
- * byte array. The byte array is not to be changed.
+ * Reads all information from a given URL, and returns that as a byte
array. The byte array is not to be changed, and could be potentially come from
a cache.
+ *
+ * @param url the URL to read the artifact from, cannot be
<code>null</code>.
+ * @return the read (or cached) bytes, can be <code>null</code>.
+ * @throws IOException in case of I/O problems.
*/
private byte[] getArtifactAsBytes(String url) throws IOException {
- if (m_cachedArtifacts.containsKey(url)) {
- return m_cachedArtifacts.get(url);
- }
- else {
- return getBytesFromUrl(url);
- }
- }
-
- private byte[] getBytesFromUrl(String url) throws IOException,
MalformedURLException {
- ByteArrayOutputStream found = new ByteArrayOutputStream();
- InputStream in = new URL(url).openStream();
+ byte[] result = null;
- byte[] buf = new byte[BUFFER_SIZE];
- for (int count = in.read(buf); count != -1; count = in.read(buf)) {
- found.write(buf, 0, count);
- }
- in.close();
- byte[] result = found.toByteArray();
- m_cachedArtifacts.put(url, result);
+ WeakReference<byte[]> ref = m_cachedArtifacts.get(url);
+ if (ref == null || ((result = ref.get()) == null)) {
+ result = getBytesFromUrl(url);
+ }
return result;
}
- @Override
- public boolean needsNewVersion(String url, PropertyResolver props, String
targetID, String fromVersion) {
- try {
- init();
- }
- catch (IOException e) {
- // problem initializing velocity... we cannot say anything.
- return true;
- }
- // get the tempate
- byte[] input = null;
+ /**
+ * Reads all bytes from the given URL and caches its result.
+ *
+ * @param url the URL to read the bytes for, cannot be <code>null</code>.
+ * @return the read bytes from the given URL, can be <code>null</code> if
the reading failed.
+ * @throws IOException in case of I/O problems.
+ */
+ private byte[] getBytesFromUrl(String url) throws IOException {
byte[] result = null;
+
+ InputStream in = new URL(url).openStream();
try {
- input = getArtifactAsBytes(url);
- result = process(input, props);
- }
- catch (IOException ioe) {
- // we cannot retrieve the original artifact, or process it; we
can't say anyting now.
- return true;
- }
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
- // process the template
- // first check: did we need any processing at all?
- if (Arrays.equals(result, input)) {
- return false;
- }
+ byte[] buf = new byte[BUFFER_SIZE];
+ for (int count = in.read(buf); count != -1; count = in.read(buf)) {
+ baos.write(buf, 0, count);
- // hash the processed template
- String newHash = hash(result);
+ result = baos.toByteArray();
- // find the hash for the previous version
- String oldHash = getHashForVersion(url, targetID, fromVersion);
+ m_cachedArtifacts.put(url, new WeakReference<byte[]>(result));
+ }
+ }
+ finally {
+ silentlyClose(in);
+ }
- // Note: we do not cache any previously created processed templates,
since the call that asks us to approve a new version
- // may cross a pending needsNewVersion call.
- return !newHash.equals(oldHash);
+ return result;
+ }
+
+ /**
+ * Creates a key for storing/retrieving a hash.
+ *
+ * @param url
+ * @param target
+ * @param version
+ * @return a hash key, never <code>null</code>.
+ */
+ private String createHashKey(String url, String target, String version) {
+ return new StringBuilder().append('[')
+ .append(url)
+ .append("][")
+ .append(target)
+ .append("][")
+ .append(version)
+ .append(']').toString();
}
+ /**
+ * Computes a hash for a given byte array.
+ *
+ * @param input the byte array to compute the hash for.
+ * @return a hash for the given byte array, never <code>null</code>.
+ */
private String hash(byte[] input) {
- try {
- return new String(MessageDigest.getInstance("MD5").digest(input));
- }
- catch (NoSuchAlgorithmException e) {
- // Will not happen: MD5 is a standard algorithm.
- }
- return null;
+ return new String(m_md5.digest(input));
}
}
Added:
ace/trunk/ace-client-repository-helper-base/src/test/java/org/apache/ace/client/repository/helper/base/VelocityArtifactPreprocessorTest.java
URL:
http://svn.apache.org/viewvc/ace/trunk/ace-client-repository-helper-base/src/test/java/org/apache/ace/client/repository/helper/base/VelocityArtifactPreprocessorTest.java?rev=1304071&view=auto
==============================================================================
---
ace/trunk/ace-client-repository-helper-base/src/test/java/org/apache/ace/client/repository/helper/base/VelocityArtifactPreprocessorTest.java
(added)
+++
ace/trunk/ace-client-repository-helper-base/src/test/java/org/apache/ace/client/repository/helper/base/VelocityArtifactPreprocessorTest.java
Thu Mar 22 21:18:20 2012
@@ -0,0 +1,171 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ace.client.repository.helper.base;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.net.URL;
+
+import org.apache.ace.client.repository.helper.PropertyResolver;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Test cases for {@link VelocityArtifactPreprocessor}.
+ */
+public class VelocityArtifactPreprocessorTest {
+
+ private static final String TARGET = "target";
+ private static final String VERSION = "1.0.0";
+
+ private URL m_obrUrl;
+ private PropertyResolver m_resolver;
+
+ @Before
+ public void setUp() throws Exception {
+ m_obrUrl = new URL("file://" + System.getProperty("java.io.tmpdir"));
+
+ m_resolver = new PropertyResolver() {
+ public String get(String key) {
+ return "msg".equals(key) ? "Hello World!" : null;
+ }
+ };
+ }
+
+ /**
+ * Test case for {@link VelocityArtifactPreprocessor#preprocess(String,
PropertyResolver, String, String, java.net.URL)}
+ */
+ @Test(expected = IOException.class)
+ public void testPreprocessNonExistingTemplateOk() throws Exception {
+ // Should be something that really doesn't exist somehow...
+ String url = "file:///path/to/nowhere-" + System.currentTimeMillis();
+
+ new VelocityArtifactPreprocessor().preprocess(url, m_resolver, TARGET,
VERSION, m_obrUrl);
+ }
+
+ /**
+ * Test case for {@link VelocityArtifactPreprocessor#preprocess(String,
PropertyResolver, String, String, java.net.URL)}
+ */
+ @Test
+ public void testPreprocessExistingRealTemplateOk() throws Exception {
+ String url = createArtifact("Message: [$context.msg]");
+
+ String newUrl = new VelocityArtifactPreprocessor().preprocess(url,
m_resolver, TARGET, VERSION, m_obrUrl);
+ assertNotNull(newUrl);
+ // Verify that it is actually uploaded...
+ assertFalse(newUrl.equals(url));
+ // Verify that it is actually uploaded to our (fake) OBR...
+ assertTrue(newUrl.startsWith(m_obrUrl.toExternalForm()));
+ }
+
+ /**
+ * Test case for {@link VelocityArtifactPreprocessor#preprocess(String,
PropertyResolver, String, String, java.net.URL)}
+ */
+ @Test
+ public void testPreprocessExistingNoTemplateOk() throws Exception {
+ String url = createArtifact("Message: [context.msg]");
+
+ String newUrl = new VelocityArtifactPreprocessor().preprocess(url,
m_resolver, TARGET, VERSION, m_obrUrl);
+ assertNotNull(newUrl);
+ // Verify that it is *not* uploaded...
+ assertEquals(url, newUrl);
+ }
+
+ /**
+ * Test case for {@link
VelocityArtifactPreprocessor#needsNewVersion(String, PropertyResolver, String,
String)}
+ */
+ @Test
+ public void testNeedsNewVersionUnchangedTemplateOk() throws Exception {
+ final VelocityArtifactPreprocessor vap = new
VelocityArtifactPreprocessor();
+
+ String url = createArtifact("Message: [$context.msg]");
+
+ boolean result = vap.needsNewVersion(url, m_resolver, TARGET, VERSION);
+ assertTrue(result); // nothing uploaded yet; new version is needed...
+
+ // "upload" a new version...
+ vap.preprocess(url, m_resolver, TARGET, VERSION, m_obrUrl);
+
+ result = vap.needsNewVersion(url, m_resolver, TARGET, VERSION);
+ assertFalse(result); // no new version is needed...
+ }
+
+ /**
+ * Test case for {@link
VelocityArtifactPreprocessor#needsNewVersion(String, PropertyResolver, String,
String)}
+ */
+ @Test
+ public void testNeedsNewVersionChangedTemplateOk() throws Exception {
+ final VelocityArtifactPreprocessor vap = new
VelocityArtifactPreprocessor();
+
+ String url = createArtifact("Message: [$context.msg]");
+
+ // "upload" a new version...
+ vap.preprocess(url, m_resolver, TARGET, VERSION, m_obrUrl);
+
+ boolean result = vap.needsNewVersion(url, m_resolver, TARGET, VERSION);
+ assertFalse(result); // no new version is needed...
+
+ updateArtifact(url, "Another message: [$context.msg2]");
+
+ result = vap.needsNewVersion(url, m_resolver, TARGET, VERSION);
+ assertFalse(result); // no new version is needed; original artifact is
cached indefinitely...
+ }
+
+ /**
+ * Test case for {@link
VelocityArtifactPreprocessor#needsNewVersion(String, PropertyResolver, String,
String)}
+ */
+ @Test
+ public void testNeedsNewVersionNonExistingTemplateOk() throws Exception {
+ final VelocityArtifactPreprocessor vap = new
VelocityArtifactPreprocessor();
+
+ // Should be something that really doesn't exist somehow...
+ String url = "file:///path/to/nowhere-" + System.currentTimeMillis();
+
+ boolean result = vap.needsNewVersion(url, m_resolver, TARGET, VERSION);
+ assertTrue(result); // always true for non-existing templates...
+ }
+
+ private String createArtifact(String string) throws IOException {
+ File tmpFile = File.createTempFile("vap", "vm");
+ tmpFile.delete();
+ tmpFile.deleteOnExit();
+
+ FileWriter writer = new FileWriter(tmpFile);
+ writer.write(string);
+ writer.close();
+
+ return tmpFile.toURI().toURL().toExternalForm();
+ }
+
+ private String updateArtifact(String url, String string) throws
IOException {
+ URL uri = new URL(url);
+
+ FileWriter writer = new FileWriter(uri.getFile());
+ writer.write(string);
+ writer.close();
+
+ return url;
+ }
+}