From afca241f1fc0d6b2e1ea49c6996107c5a2b89862 Mon Sep 17 00:00:00 2001 From: Steve Loughran Date: Mon, 22 Aug 2005 16:49:44 +0000 Subject: [PATCH] This is an official contrib of the smartfrog tourl task to the apache codebase; its aim has been to set up rmic classpaths, but it turns out to use maven2 its kind of convenient to be able to turn any location into a file: url. That is only, what, 3 lines of code, but what this task does is bulk conversion and a set of unit tests that work. Docs are to be xdoc generated git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@278531 13f79535-47bb-0310-9956-ffa450edef68 --- src/etc/testcases/taskdefs/makeurl.xml | 63 ++++ .../apache/tools/ant/taskdefs/MakeUrl.java | 295 ++++++++++++++++++ .../tools/ant/taskdefs/defaults.properties | 1 + .../tools/ant/taskdefs/MakeUrlTest.java | 136 ++++++++ 4 files changed, 495 insertions(+) create mode 100644 src/etc/testcases/taskdefs/makeurl.xml create mode 100644 src/main/org/apache/tools/ant/taskdefs/MakeUrl.java create mode 100644 src/testcases/org/apache/tools/ant/taskdefs/MakeUrlTest.java diff --git a/src/etc/testcases/taskdefs/makeurl.xml b/src/etc/testcases/taskdefs/makeurl.xml new file mode 100644 index 000000000..7bb16941a --- /dev/null +++ b/src/etc/testcases/taskdefs/makeurl.xml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/org/apache/tools/ant/taskdefs/MakeUrl.java b/src/main/org/apache/tools/ant/taskdefs/MakeUrl.java new file mode 100644 index 000000000..edbf84402 --- /dev/null +++ b/src/main/org/apache/tools/ant/taskdefs/MakeUrl.java @@ -0,0 +1,295 @@ +/* + * Copyright 2005 The Apache Software Foundation + * + * Licensed 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.tools.ant.taskdefs; + + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.Task; +import org.apache.tools.ant.DirectoryScanner; +import org.apache.tools.ant.types.FileSet; +import org.apache.tools.ant.types.Path; + +import java.io.File; +import java.net.MalformedURLException; +import java.util.List; +import java.util.LinkedList; +import java.util.ListIterator; + +/** + * This task takes file and turns them into a URL, which it then assigns + * to a property. Use when for setting up RMI codebases. + *

+ * nested filesets are supported; if present, these are turned into the + * url with the given separator between them (default = " "). + * + * @ant.task category="core" name="tourl" + */ + +public class MakeUrl extends Task { + + /** + * name of the property to set + */ + private String property; + + /** + * name of a file to turn into a URL + */ + private File file; + + /** + * separator char + */ + private String separator = " "; + + /** + * filesets of nested files to add to this url + */ + private List filesets = new LinkedList(); + + /** + * paths to add + */ + private List paths = new LinkedList(); + + /** + * validation flag + */ + private boolean validate = true; + + /** + * error message + */ + public static final String ERROR_MISSING_FILE = "A source file is missing :"; + public static final String ERROR_NO_PROPERTY = "No property defined"; + public static final String ERROR_NO_FILES = "No files defined"; + + /** + * set the name of a property to fill with the URL + * + * @param property + */ + public void setProperty(String property) { + this.property = property; + } + + /** + * the name of a file to be converted into a URL + * + * @param file + */ + public void setFile(File file) { + this.file = file; + } + + /** + * a fileset of jar files to include in the URL, each + * separated by the separator + * + * @param fileset + */ + public void addFileSet(FileSet fileset) { + filesets.add(fileset); + } + + /** + * set the separator for the multi-url option. + * + * @param separator + */ + public void setSeparator(String separator) { + this.separator = separator; + } + + /** + * set this flag to trigger validation that every named file exists. + * Optional: default=true + * + * @param validate + */ + public void setValidate(boolean validate) { + this.validate = validate; + } + + /** + * add a path to the URL. All elements in the path + * will be converted to individual URL entries + * + * @param path + */ + public void addPath(Path path) { + paths.add(path); + } + + /** + * convert the filesets to urls. + * + * @return null for no files + */ + private String filesetsToURL() { + if (filesets.isEmpty()) { + return ""; + } + int count = 0; + StringBuffer urls = new StringBuffer(); + ListIterator list = filesets.listIterator(); + while (list.hasNext()) { + FileSet set = (FileSet) list.next(); + DirectoryScanner scanner = set.getDirectoryScanner(getProject()); + String[] files = scanner.getIncludedFiles(); + for (int i = 0; i < files.length; i++) { + File f = new File(scanner.getBasedir(), files[i]); + validateFile(f); + String asUrl = toURL(f); + urls.append(asUrl); + log(asUrl, Project.MSG_DEBUG); + urls.append(separator); + count++; + } + } + //at this point there is one trailing space to remove, if the list is not empty. + return stripTrailingSeparator(urls, count); + } + + /** + * convert the string buffer to a string, potentially stripping + * out any trailing separator + * + * @param urls URL buffer + * @param count number of URL entries + * @return trimmed string, or empty string + */ + private String stripTrailingSeparator(StringBuffer urls, + int count) { + if (count > 0) { + urls.delete(urls.length() - separator.length(), urls.length()); + return new String(urls); + } else { + return ""; + } + } + + + /** + * convert all paths to URLs + * + * @return the paths as a separated list of URLs + */ + private String pathsToURL() { + if (paths.isEmpty()) { + return ""; + } + int count = 0; + StringBuffer urls = new StringBuffer(); + ListIterator list = paths.listIterator(); + while (list.hasNext()) { + Path path = (Path) list.next(); + String[] elements = path.list(); + for (int i = 0; i < elements.length; i++) { + File f = new File(elements[i]); + validateFile(f); + String asUrl = toURL(f); + urls.append(asUrl); + log(asUrl, Project.MSG_DEBUG); + urls.append(separator); + count++; + } + } + //at this point there is one trailing space to remove, if the list is not empty. + return stripTrailingSeparator(urls, count); + } + + /** + * verify that the file exists, if {@link #validate} is set + * + * @param fileToCheck file that may need to exist + * @throws BuildException with text beginning {@link #ERROR_MISSING_FILE} + */ + private void validateFile(File fileToCheck) { + if (validate && !fileToCheck.exists()) { + throw new BuildException(ERROR_MISSING_FILE + fileToCheck.toString()); + } + } + + /** + * Create the url + * + * @throws org.apache.tools.ant.BuildException + * if something goes wrong with the build + */ + public void execute() throws BuildException { + validate(); + //now exit here if the property is already set + if (getProject().getProperty(property) != null) { + return; + } + String url; + String filesetURL = filesetsToURL(); + if (file != null) { + validateFile(file); + url = toURL(file); + //and add any files if also defined + if (filesetURL.length() > 0) { + url = url + separator + filesetURL; + } + } else { + url = filesetURL; + } + //add path URLs + String pathURL = pathsToURL(); + if (pathURL.length() > 0) { + if (url.length() > 0) { + url = url + separator + pathURL; + } else { + url = pathURL; + } + } + log("Setting " + property + " to URL " + url, Project.MSG_VERBOSE); + getProject().setNewProperty(property, url); + } + + private void validate() { + //validation + if (property == null) { + throw new BuildException(ERROR_NO_PROPERTY); + } + if (file == null && filesets.isEmpty() && paths.isEmpty()) { + throw new BuildException(ERROR_NO_FILES); + } + } + + /** + * convert a file to a URL; + * + * @param fileToConvert + * @return the file converted to a URL + * @throws BuildException if the file would not convert + */ + private String toURL(File fileToConvert) { + String url; + try { + //create the URL + url = fileToConvert.toURI().toURL().toExternalForm(); + //set the property + } catch (MalformedURLException e) { + throw new BuildException("Could not convert " + fileToConvert, e); + } + return url; + } + +} diff --git a/src/main/org/apache/tools/ant/taskdefs/defaults.properties b/src/main/org/apache/tools/ant/taskdefs/defaults.properties index a4b403387..6eaaead3d 100644 --- a/src/main/org/apache/tools/ant/taskdefs/defaults.properties +++ b/src/main/org/apache/tools/ant/taskdefs/defaults.properties @@ -208,6 +208,7 @@ schemavalidate=org.apache.tools.ant.taskdefs.optional.SchemaValidate verifyjar=org.apache.tools.ant.taskdefs.VerifyJar resourcecount=org.apache.tools.ant.taskdefs.ResourceCount echoxml=org.apache.tools.ant.taskdefs.EchoXML +makeurl=org.apache.tools.ant.taskdefs.MakeUrl # deprecated ant tasks (kept for back compatibility) starteam=org.apache.tools.ant.taskdefs.optional.scm.AntStarTeamCheckOut diff --git a/src/testcases/org/apache/tools/ant/taskdefs/MakeUrlTest.java b/src/testcases/org/apache/tools/ant/taskdefs/MakeUrlTest.java new file mode 100644 index 000000000..a2048c584 --- /dev/null +++ b/src/testcases/org/apache/tools/ant/taskdefs/MakeUrlTest.java @@ -0,0 +1,136 @@ +/* + * Copyright 2005 The Apache Software Foundation + * + * Licensed 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.tools.ant.taskdefs; + +import org.apache.tools.ant.BuildFileTest; + +import java.io.InputStream; +import java.io.IOException; +import java.net.URL; + + +public class MakeUrlTest extends BuildFileTest { + + public MakeUrlTest(String s) { + super(s); + } + + public void setUp() { + configureProject("src/etc/testcases/taskdefs/makeurl.xml"); + } + + public void testEmpty() { + expectBuildExceptionContaining("testEmpty", "missing property", "property"); + } + + public void testNoProperty() { + expectBuildExceptionContaining("testNoProperty", "missing property", "property"); + } + + public void testNoFile() { + expectBuildExceptionContaining("testNoFile", "missing file", "file"); + } + + public void testValidation() { + expectBuildExceptionContaining("testValidation", MakeUrl.ERROR_MISSING_FILE, "file"); + } + + public void testWorks() { + executeTarget("testWorks"); + assertPropertyContains("testWorks", "file:"); + assertPropertyContains("testWorks", "/foo"); + } + + public void testIllegalChars() { + executeTarget("testIllegalChars"); + assertPropertyContains("testIllegalChars", "file:"); + assertPropertyContains("testIllegalChars", "fo%20o%25"); + } + + /** + * test that we can round trip by opening a url that exists + * + * @throws IOException + */ + public void testRoundTrip() throws IOException { + executeTarget("testRoundTrip"); + assertPropertyContains("testRoundTrip", "file:"); + String property = getProperty("testRoundTrip"); + URL url = new URL(property); + InputStream instream = url.openStream(); + instream.close(); + } + + public void testIllegalCombinations() { + executeTarget("testIllegalCombinations"); + assertPropertyContains("testIllegalCombinations", "/foo"); + assertPropertyContains("testIllegalCombinations", ".xml"); + } + + public void testFileset() { + executeTarget("testFileset"); + assertPropertyContains("testFileset", ".xml "); + String result = getProperty("testFileset"); + assertPropertyEndsWith("testFileset", ".xml"); + } + + public void testFilesetSeparator() { + executeTarget("testFilesetSeparator"); + assertPropertyContains("testFilesetSeparator", ".xml\",\""); + assertPropertyEndsWith("testFilesetSeparator", ".xml"); + } + + public void testPath() { + executeTarget("testPath"); + assertPropertyContains("testPath", "to-url.xml"); + } + + /** + * assert that a property ends with + * + * @param property + * @param ending + */ + private void assertPropertyEndsWith(String property, String ending) { + String result = getProperty(property); + String substring = result.substring(result.length() - ending.length()); + assertEquals(ending, substring); + } + + /** + * assert that a property contains a string + * + * @param property name of property to look for + * @param contains what to search for in the string + */ + protected void assertPropertyContains(String property, String contains) { + String result = getProperty(property); + + assertTrue("expected " + contains + " in " + result, + result != null && result.indexOf(contains) >= 0); + } + + /** + * get a property from the project + * + * @param property + * @return + */ + protected String getProperty(String property) { + return project.getProperty(property); + } +}