source: release-kits/lirk3/resources/gs3-release-maker/apache-ant-1.6.5/src/main/org/apache/tools/ant/taskdefs/PathConvert.java@ 14982

Last change on this file since 14982 was 14982, checked in by oranfry, 16 years ago

initial import of LiRK3

File size: 15.1 KB
Line 
1/*
2 * Copyright 2001-2005 The Apache Software Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17package org.apache.tools.ant.taskdefs;
18
19import java.io.File;
20import java.util.StringTokenizer;
21import java.util.Vector;
22import java.util.List;
23import java.util.ArrayList;
24import org.apache.tools.ant.BuildException;
25import org.apache.tools.ant.Project;
26import org.apache.tools.ant.Task;
27import org.apache.tools.ant.taskdefs.condition.Os;
28import org.apache.tools.ant.types.DirSet;
29import org.apache.tools.ant.types.EnumeratedAttribute;
30import org.apache.tools.ant.types.FileList;
31import org.apache.tools.ant.types.FileSet;
32import org.apache.tools.ant.types.Path;
33import org.apache.tools.ant.types.Reference;
34import org.apache.tools.ant.types.Mapper;
35import org.apache.tools.ant.util.FileNameMapper;
36
37/**
38 * Converts path and classpath information to a specific target OS
39 * format. The resulting formatted path is placed into the specified property.
40 *
41 * @since Ant 1.4
42 * @ant.task category="utility"
43 */
44public class PathConvert extends Task {
45
46 // Members
47 /**
48 * Path to be converted
49 */
50 private Path path = null;
51 /**
52 * Reference to path/fileset to convert
53 */
54 private Reference refid = null;
55 /**
56 * The target OS type
57 */
58 private String targetOS = null;
59 /**
60 * Set when targetOS is set to windows
61 */
62 private boolean targetWindows = false;
63 /**
64 * Set if we're running on windows
65 */
66 private boolean onWindows = false;
67 /**
68 * Set if we should create a new property even if the result is empty
69 */
70 private boolean setonempty = true;
71 /**
72 * The property to receive the conversion
73 */
74 private String property = null;
75 /**
76 * Path prefix map
77 */
78 private Vector prefixMap = new Vector();
79 /**
80 * User override on path sep char
81 */
82 private String pathSep = null;
83 /**
84 * User override on directory sep char
85 */
86 private String dirSep = null;
87
88 /** Filename mapper */
89 private Mapper mapper = null;
90
91 /**
92 * Construct a new instance of the PathConvert task.
93 */
94 public PathConvert() {
95 onWindows = Os.isFamily("dos");
96 }
97
98 /**
99 * Helper class, holds the nested <map> values. Elements will look like
100 * this: <map from="d:" to="/foo"/>
101 *
102 * When running on windows, the prefix comparison will be case
103 * insensitive.
104 */
105 public class MapEntry {
106
107 // Members
108 private String from = null;
109 private String to = null;
110
111 /**
112 * Set the "from" attribute of the map entry.
113 * @param from the prefix string to search for; required.
114 * Note that this value is case-insensitive when the build is
115 * running on a Windows platform and case-sensitive when running on
116 * a Unix platform.
117 */
118 public void setFrom(String from) {
119 this.from = from;
120 }
121
122 /**
123 * Set the replacement text to use when from is matched; required.
124 * @param to new prefix.
125 */
126 public void setTo(String to) {
127 this.to = to;
128 }
129
130 /**
131 * Apply this map entry to a given path element.
132 *
133 * @param elem Path element to process.
134 * @return String Updated path element after mapping.
135 */
136 public String apply(String elem) {
137 if (from == null || to == null) {
138 throw new BuildException("Both 'from' and 'to' must be set "
139 + "in a map entry");
140 }
141 // If we're on windows, then do the comparison ignoring case
142 String cmpElem = onWindows ? elem.toLowerCase() : elem;
143 String cmpFrom = onWindows ? from.toLowerCase() : from;
144
145 // If the element starts with the configured prefix, then
146 // convert the prefix to the configured 'to' value.
147
148 return cmpElem.startsWith(cmpFrom)
149 ? to + elem.substring(from.length()) : elem;
150 }
151 }
152
153 /**
154 * An enumeration of supported targets:
155 * "windows", "unix", "netware", and "os/2".
156 */
157 public static class TargetOs extends EnumeratedAttribute {
158 /**
159 * @return the list of values for this enumerated attribute.
160 */
161 public String[] getValues() {
162 return new String[]{"windows", "unix", "netware", "os/2", "tandem"};
163 }
164 }
165
166 /**
167 * Create a nested PATH element.
168 * @return a Path to be used by Ant reflection.
169 */
170 public Path createPath() {
171 if (isReference()) {
172 throw noChildrenAllowed();
173 }
174 if (path == null) {
175 path = new Path(getProject());
176 }
177 return path.createPath();
178 }
179
180 /**
181 * Create a nested MAP element.
182 * @return a Map to configure.
183 */
184 public MapEntry createMap() {
185 MapEntry entry = new MapEntry();
186 prefixMap.addElement(entry);
187 return entry;
188 }
189
190 /**
191 * Set targetos to a platform to one of
192 * "windows", "unix", "netware", or "os/2";
193 * current platform settings are used by default.
194 * @deprecated use the method taking a TargetOs argument instead.
195 * @see #setTargetos(PathConvert.TargetOs)
196 */
197 public void setTargetos(String target) {
198 TargetOs to = new TargetOs();
199 to.setValue(target);
200 setTargetos(to);
201 }
202
203 /**
204 * Set targetos to a platform to one of
205 * "windows", "unix", "netware", or "os/2";
206 * current platform settings are used by default.
207 * @param target the target os
208 *
209 * @since Ant 1.5
210 */
211 public void setTargetos(TargetOs target) {
212 targetOS = target.getValue();
213
214 // Currently, we deal with only two path formats: Unix and Windows
215 // And Unix is everything that is not Windows
216
217 // for NetWare and OS/2, piggy-back on Windows, since in the
218 // validateSetup code, the same assumptions can be made as
219 // with windows - that ; is the path separator
220
221 targetWindows = !targetOS.equals("unix") && !targetOS.equals("tandem");
222 }
223
224 /**
225 * Set whether the specified property will be set if the result
226 * is the empty string.
227 * @param setonempty true or false.
228 *
229 * @since Ant 1.5
230 */
231 public void setSetonempty(boolean setonempty) {
232 this.setonempty = setonempty;
233 }
234
235 /**
236 * Set the name of the property into which the converted path will be placed.
237 * @param p the property name.
238 */
239 public void setProperty(String p) {
240 property = p;
241 }
242
243 /**
244 * Add a reference to a Path, FileSet, DirSet, or FileList defined elsewhere.
245 * @param r the reference to a path, fileset, dirset or filelist.
246 */
247 public void setRefid(Reference r) {
248 if (path != null) {
249 throw noChildrenAllowed();
250 }
251 refid = r;
252 }
253
254 /**
255 * Set the default path separator string; defaults to current JVM
256 * {@link java.io.File#pathSeparator File.pathSeparator}.
257 * @param sep path separator string.
258 */
259 public void setPathSep(String sep) {
260 pathSep = sep;
261 }
262
263
264 /**
265 * Set the default directory separator string;
266 * defaults to current JVM {@link java.io.File#separator File.separator}.
267 * @param sep directory separator string.
268 */
269 public void setDirSep(String sep) {
270 dirSep = sep;
271 }
272
273 /**
274 * Learn whether the refid attribute of this element been set.
275 * @return true if refid is valid.
276 */
277 public boolean isReference() {
278 return refid != null;
279 }
280
281 /**
282 * Do the execution.
283 * @throws BuildException if something is invalid.
284 */
285 public void execute() throws BuildException {
286 Path savedPath = path;
287 String savedPathSep = pathSep; // may be altered in validateSetup
288 String savedDirSep = dirSep; // may be altered in validateSetup
289
290 try {
291 // If we are a reference, create a Path from the reference
292 if (isReference()) {
293 path = new Path(getProject()).createPath();
294 Object obj = refid.getReferencedObject(getProject());
295
296 if (obj instanceof Path) {
297 path.setRefid(refid);
298 } else if (obj instanceof FileSet) {
299 path.addFileset((FileSet) obj);
300 } else if (obj instanceof DirSet) {
301 path.addDirset((DirSet) obj);
302 } else if (obj instanceof FileList) {
303 path.addFilelist((FileList) obj);
304 } else {
305 throw new BuildException("'refid' does not refer to a "
306 + "path, fileset, dirset, or filelist.");
307 }
308 }
309 validateSetup(); // validate our setup
310
311 // Currently, we deal with only two path formats: Unix and Windows
312 // And Unix is everything that is not Windows
313 // (with the exception for NetWare and OS/2 below)
314
315 // for NetWare and OS/2, piggy-back on Windows, since here and
316 // in the apply code, the same assumptions can be made as with
317 // windows - that \\ is an OK separator, and do comparisons
318 // case-insensitive.
319 String fromDirSep = onWindows ? "\\" : "/";
320
321 StringBuffer rslt = new StringBuffer();
322
323 // Get the list of path components in canonical form
324 String[] elems = path.list();
325
326 if (mapper != null) {
327 FileNameMapper impl = mapper.getImplementation();
328 List ret = new ArrayList();
329 for (int i = 0; i < elems.length; ++i) {
330 String[] mapped = impl.mapFileName(elems[i]);
331 for (int m = 0; mapped != null && m < mapped.length; ++m) {
332 ret.add(mapped[m]);
333 }
334 }
335 elems = (String[]) ret.toArray(new String[] {});
336 }
337 for (int i = 0; i < elems.length; i++) {
338 String elem = mapElement(elems[i]); // Apply the path prefix map
339
340 // Now convert the path and file separator characters from the
341 // current os to the target os.
342
343 if (i != 0) {
344 rslt.append(pathSep);
345 }
346 StringTokenizer stDirectory =
347 new StringTokenizer(elem, fromDirSep, true);
348
349 while (stDirectory.hasMoreTokens()) {
350 String token = stDirectory.nextToken();
351 rslt.append(fromDirSep.equals(token) ? dirSep : token);
352 }
353 }
354 // Place the result into the specified property,
355 // unless setonempty == false
356 if (setonempty || rslt.length() > 0) {
357 String value = rslt.toString();
358 log("Set property " + property + " = " + value,
359 Project.MSG_VERBOSE);
360 getProject().setNewProperty(property, value);
361 }
362 } finally {
363 path = savedPath;
364 dirSep = savedDirSep;
365 pathSep = savedPathSep;
366 }
367 }
368
369 /**
370 * Apply the configured map to a path element. The map is used to convert
371 * between Windows drive letters and Unix paths. If no map is configured,
372 * then the input string is returned unchanged.
373 *
374 * @param elem The path element to apply the map to.
375 * @return String Updated element.
376 */
377 private String mapElement(String elem) {
378
379 int size = prefixMap.size();
380
381 if (size != 0) {
382
383 // Iterate over the map entries and apply each one.
384 // Stop when one of the entries actually changes the element.
385
386 for (int i = 0; i < size; i++) {
387 MapEntry entry = (MapEntry) prefixMap.elementAt(i);
388 String newElem = entry.apply(elem);
389
390 // Note I'm using "!=" to see if we got a new object back from
391 // the apply method.
392
393 if (newElem != elem) {
394 elem = newElem;
395 break; // We applied one, so we're done
396 }
397 }
398 }
399 return elem;
400 }
401
402 /**
403 * Add a mapper to convert the file names.
404 *
405 * @param mapper a <code>Mapper</code> value.
406 */
407 public void addMapper(Mapper mapper) {
408 if (this.mapper != null) {
409 throw new BuildException(
410 "Cannot define more than one mapper");
411 }
412 this.mapper = mapper;
413 }
414
415 /**
416 * Add a nested filenamemapper.
417 * @param fileNameMapper the mapper to add.
418 * @since Ant 1.6.3
419 */
420 public void add(FileNameMapper fileNameMapper) {
421 Mapper m = new Mapper(getProject());
422 m.add(fileNameMapper);
423 addMapper(m);
424 }
425
426
427 /**
428 * Validate that all our parameters have been properly initialized.
429 *
430 * @throws BuildException if something is not set up properly.
431 */
432 private void validateSetup() throws BuildException {
433
434 if (path == null) {
435 throw new BuildException("You must specify a path to convert");
436 }
437 if (property == null) {
438 throw new BuildException("You must specify a property");
439 }
440 // Determine the separator strings. The dirsep and pathsep attributes
441 // override the targetOS settings.
442 String dsep = File.separator;
443 String psep = File.pathSeparator;
444
445 if (targetOS != null) {
446 psep = targetWindows ? ";" : ":";
447 dsep = targetWindows ? "\\" : "/";
448 }
449 if (pathSep != null) {
450 // override with pathsep=
451 psep = pathSep;
452 }
453 if (dirSep != null) {
454 // override with dirsep=
455 dsep = dirSep;
456 }
457 pathSep = psep;
458 dirSep = dsep;
459 }
460
461 /**
462 * Creates an exception that indicates that this XML element must not have
463 * child elements if the refid attribute is set.
464 * @return BuildException.
465 */
466 private BuildException noChildrenAllowed() {
467 return new BuildException("You must not specify nested <path> "
468 + "elements when using the refid attribute.");
469 }
470
471}
472
Note: See TracBrowser for help on using the repository browser.