You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ant.apache.org by Phil Hanna <au...@philhanna.com> on 2000/05/14 03:52:26 UTC
Fixes for org.apache.tools.ant.taskdefs.Javac and org.apache.tools.ant.Project
Appended to this note are fixes for two related Ant bugs:
BUG 1 - Project.translatePath()
1. org.apache.tools.ant.taskdefs.Javac uses Project.translatePath() to convert various paths to native format (i.e., Unix to Win32, etc.). But Project.translatePath() does not always correctly handle Win32 paths with forward slashes, converting for example
d:/jdk1.3/jre/lib/ext
to
d;\jdk1.3\jre\lib\ext
which is interpreted as two directories instead of one.
Here is what happens (I added the DEBUG messages to the source code):
--- CUT HERE ---
D:\jspcr\docs>ant
Buildfile: build.xml
Project base dir set to: D:\jspcr\docs
DEBUG: Javac: setExtdirs: entry
DEBUG: Javac: setExtdirs: extdirs=d:/jdk1.3/jre/lib/ext
DEBUG: Javac: setExtdirs: after project.translatePath()
DEBUG: Javac: setExtdirs: this.extdirs=d;\jdk1.3\jre\lib\ext
DEBUG: Javac: setExtdirs: exit
Executing Target: init
Executing Target: compile
Compiling 1 source files to D:\jspcr\docs
DEBUG: addExtdirsToClasspath: entry
DEBUG: addExtdirsToClasspath: classpath=D:\jspcr\docs;D:\ant\lib\ant.jar;D:\jdk1.3\lib\tools.jar
DEBUG: addExtdirsToClasspath: extdirs=d;\jdk1.3\jre\lib\ext
DEBUG: addExtdirsToClasspath: dir=D:\jspcr\docs\d
Exception in thread "main" java.lang.NullPointerException
at org.apache.tools.ant.taskdefs.Javac.addExtdirsToClasspath(Javac.java:605)
at org.apache.tools.ant.taskdefs.Javac.doJikesCompile(Javac.java:466)
at org.apache.tools.ant.taskdefs.Javac.execute(Javac.java:227)
at org.apache.tools.ant.Target.execute(Target.java:122)
at org.apache.tools.ant.Project.runTarget(Project.java:675)
at org.apache.tools.ant.Project.executeTarget(Project.java:422)
at org.apache.tools.ant.Main.runBuild(Main.java:248)
at org.apache.tools.ant.Main.main(Main.java:191)
D:\jspcr\docs>
--- END CUT ---
Here is the build.xml file:
--- CUT HERE ---
<project default="compile" basedir="." >
<target name="init">
<tstamp/>
<property name="java_home" value="d:/jdk1.3"/>
<property name="extdirs" value="${java_home}/jre/lib/ext" />
<property name="build.compiler" value="jikes" />
</target>
<target name="compile" depends="init">
<javac srcdir="." destdir="." extdirs="${extdirs}" />
</target>
</project>
--- END CUT ---
Unfortunately, the translatePath() problem is not always possible to solve because the Unix and Win32 path formats do not map completely. For example, what should we make of c:/test? It could be a single Win32 directory or two Unix directories. (Forward slashes should be treated as valid, even on Win32).
The best we can do is employ a heuristic to determine what platform the string is coded for, and then apply the following decision table:
String Runtime
Platform Platform Action
-------- -------- ------
Unix Unix No change required
Unix Win32 Change ":" to ";", "/" to "\\"
Win32 Unix Remove "<driveletter>:",
then change ";" to ":", "\\" to "/"
Win32 Win32 No change required
A string is considered to be a Win32 path if
1. It contains any ";" characters, OR
2. It contains any "\\" characters, OR
3. It begins with a letter followed by a ":"
I fiddled with Project.translatePath() but ended up writing a replacement. Here is the patch:
--- CUT HERE ---
--- Project.java Wed May 10 16:20:34 2000
+++ Project.java.new Sat May 13 15:15:03 2000
@@ -482,43 +482,127 @@
}
/**
- Translate a path into its native (platform specific)
- path. This should be extremely fast, code is
- borrowed from ECS project.
- <p>
- All it does is translate the : into ; and / into \
- if needed. In other words, it isn't perfect.
-
- @returns translated string or empty string if to_process is null or empty
- @author Jon S. Stevens <a href="mailto:jon@clearink.com">jon@clearink.com</a>
+ * Translates a path into its native (platform specific)
+ * path.
+ * <P>
+ * This is not always possible because the
+ * Unix and Win32 path formats do not map completely.
+ * For example, what should we make of <CODE>c:/test</CODE>?
+ * It could be a single Win32 directory or two Unix
+ * directories. (Forward slashes should be treated
+ * as valid, even on Win32).
+ * <P>
+ * The best we can do is employ a heuristic to determine
+ * what platform the string is coded for, and then apply
+ * the following decision table:
+ * <PRE>
+ * String Runtime
+ * Platform Platform Action
+ * -------- -------- ------
+ * Unix Unix No change required
+ *
+ * Unix Win32 Change ":" to ";", "/" to "\\"
+ *
+ * Win32 Unix Remove "<driveletter>:",
+ * then change ";" to ":", "\\" to "/"
+ *
+ * Win32 Win32 No change required
+ * </PRE>
+ * A string is considered to be a Win32 path if
+ * <OL>
+ * <LI>It contains any ";" characters, <B>OR</B>
+ * <LI>It contains any "\\" characters, <B>OR</B>
+ * <LI>It begins with a letter followed by a ":"
+ * </OL>
+ *
+ * @param pathString a path string
+ * @return translated string
+ * or empty string if pathString is null or empty
*/
- public String translatePath(String to_process) {
- if ( to_process == null || to_process.length() == 0 ) return "";
+ public String translatePath(String pathString) {
+
+ // Simple cases first
+
+ if (pathString == null)
+ return "";
+ int length = pathString.length();
+ if (length == 0)
+ return null;
+
+ // The string to process is considered a Win32 path if
+ // it contains any semicolons, backslashes, or if it
+ // begins with a drive letter + ":"
+
+ boolean string_is_win32 =
+ (pathString.indexOf(";") != -1) ||
+ (pathString.indexOf("\\") != -1) ||
+ ((length > 1)
+ && (Character.isLetter(pathString.charAt(0)))
+ && (pathString.charAt(1) == ':'));
+
+ // The runtime platform is considered to be Win32
+ // if the path separator is ";"
+
+ boolean platform_is_win32 =
+ System.getProperty("path.separator").equals(";");
+
+ // No change is required if the platforms are the same
+
+ if (string_is_win32 == platform_is_win32)
+ return pathString;
+
+ // Win32 to Unix translation:
- StringBuffer bs = new StringBuffer(to_process.length() + 50);
- StringCharacterIterator sci = new StringCharacterIterator(to_process);
- String path = System.getProperty("path.separator");
- String file = System.getProperty("file.separator");
- String tmp = null;
- for (char c = sci.first(); c != CharacterIterator.DONE; c = sci.next()) {
- tmp = String.valueOf(c);
-
- if (tmp.equals(":")) {
- // could be a DOS drive or a Unix path separator...
- // if followed by a backslash, assume it is a drive
- c = sci.next();
- tmp = String.valueOf(c);
- bs.append( tmp.equals("\\") ? ":" : path );
- if (c == CharacterIterator.DONE) break;
+ if (string_is_win32) {
+
+ // Ugly problem: There is no completely correct
+ // way to translate drive letters, since Unix
+ // does not use them. Moreover, if an absolute
+ // path is intended, it probably does not make
+ // sense to convert it to "/" - it is more likely
+ // to be "~/" or something.
+ //
+ // Solution: Remove drive letters and the colons
+ // that follow them altogether. If the user has
+ // a mix of "C:" and "D:" designations in the
+ // path and wants to run it on Unix, the user must
+ // untangle it first.
+
+ int p = pathString.indexOf(":");
+ if (p != -1) {
+ StringBuffer sb = new StringBuffer();
+ int goodLength = 0; // Last known good length
+ for (int i = 0; i < length; i++) {
+ char c = pathString.charAt(i);
+ if (c == ':') {
+ sb.setLength(goodLength);
+ }
+ else {
+ sb.append(c);
+ if (c == ';')
+ goodLength = sb.length();
+ }
+ }
+ pathString = sb.toString();
}
- if (tmp.equals(":") || tmp.equals(";"))
- tmp = path;
- else if (tmp.equals("/") || tmp.equals ("\\"))
- tmp = file;
- bs.append(tmp);
+ // Now translate ";" to ":" and "\\" to "/"
+
+ pathString = pathString.replace(';', ':');
+ pathString = pathString.replace('\\', '/');
}
- return(bs.toString());
+
+ // Unix to Win32 translation:
+
+ else {
+
+ // Translate ":" to ";" and "/" to "\\"
+
+ pathString = pathString.replace(':', ';');
+ pathString = pathString.replace('/', '\\');
+ }
+
+ return pathString;
}
/**
--- END CUT ---
BUG 2 - Javac.addExtdirsToClasspath()
2. org.apache.tools.ant.taskdefs.Javac gets a null pointer exception in addExtdirsToClasspath() if any element of the path refers to a directory which does not exist. The fix consists of testing the file list for null before entering the loop. Here is the patch:
--- CUT HERE ---
--- Javac.java Wed May 10 16:20:34 2000
+++ Javac.java.new Sat May 13 15:45:58 2000
@@ -593,6 +593,7 @@
while (tok.hasMoreTokens()) {
File dir = project.resolveFile(tok.nextToken());
String[] files = dir.list(new JarFilenameFilter());
+ if (files == null) continue;
for (int i=0 ; i < files.length ; i++) {
File f = new File(dir,files[i]);
if (f.exists() && f.isFile()) {
--- END CUT ---
Thanks,
Phil Hanna
Re: Beginner questions for setting up build environment
Posted by Stefan Bodewig <bo...@bost.de>.
Hi Tom,
>>>>> "tg" == tom goodman <to...@bigfoot.com> writes:
tg> 1) I've have the java files in a hierarchy and want to compile
tg> the entire tree into a single jar file containing .class files.
tg> Is there a simple way to do that?
Sure, look at Ant's own build.xml which does exactly what you want for
Ant itself.
tg> 2) The files need to compile in the right order to satisfy the
tg> include dependencies in the .java files.
All files are compiled at the same time which is guaranteed to be the
right order 8^).
tg> I know this must be simple stuff written up in a doc somewhere
tg> but I can't find it.
See docs/index.html in Ant's CVS repository and take a look at
spec/core.html to get a feeling for things to come.
HTH
Stefan
Beginner questions for setting up build environment
Posted by tom goodman <to...@bigfoot.com>.
I'm trying to set up an JSP, servlet, bean, apache, jakarta-tomcat, java 1.2
environment. and would like to use ant to manage the compile dependencies.
I have all the pieces installed.
Can someone tell me where I might find a good running demo of this that I
can start with? Or a good tutorial? I dowloaded Sun's JavaPetStore code
demo (which uses ant, etc) but it looks like that requires the J2EE sdk
which doesn't seem to be available on Linux yet.
Two basic questions:
1) I've have the java files in a hierarchy and want to compile the entire
tree into a single jar file containing .class files. Is there a simple way
to do that?
2) The files need to compile in the right order to satisfy the include
dependencies in the .java files.
I know this must be simple stuff written up in a doc somewhere but I can't
find it.
If ant (or something simpler) helps, I'll gladly use it.
Thanks any help.
tom
Re: Fixes for org.apache.tools.ant.taskdefs.Javac and
org.apache.tools.ant.Project
Posted by Tom Cook <tc...@ardec.com.au>.
A few comments:
On Sat, 13 May 2000, Phil Hanna wrote:
> Unfortunately, the translatePath() problem is not always possible to solve because the Unix and Win32 path formats do not map completely.
True.
> For example, what should we make of c:/test? It could be a single Win32
> directory or two Unix directories.
Mmmmm, how likely is it that absolute paths will map from a win32 to UNIX
environment? To take your example, it seems very unlikely to me that a
'C:\test' on one system will map to '/test' on another system. Things get
more complicated as the paths get deeper - different conventions are used
on each system. For instance, applications are in "C:\Program Files" on
Win32, and are smattered over /usr, /usr/local, /opt and /mnt/* on UNIX
systems. None of these are restrictive, but they clearly don't map well. I
wonder, then, how valuable mapping absolute paths from Win32 to UNIX and
back again is. Clearly relative paths within a project are likely to
remain consistent, but absolute paths I feel need more thought.
> (Forward slashes should be treated as valid, even on Win32).
Do M$ Win32 systems recognize them?
Cheerio
--
Tom Cook - Software Engineer
"The brain is a wonderful organ. It starts functioning the moment you get
up in the morning, and does not stop until you get into the office."
- Robert Frost
LISAcorp - www.lisa.com.au
--------------------------------------------------
38 Greenhill Rd. Level 3, 228 Pitt Street
Wayville, SA, 5034 Sydney, NSW, 2000
Phone: +61 8 8272 1555 Phone: +61 2 9283 0877
Fax: +61 8 8271 1199 Fax: +61 2 9283 0866
--------------------------------------------------