001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018:
019: package org.apache.tools.ant.taskdefs.optional;
020:
021: import java.io.File;
022: import org.apache.tools.ant.BuildException;
023: import org.apache.tools.ant.DirectoryScanner;
024: import org.apache.tools.ant.Project;
025: import org.apache.tools.ant.taskdefs.MatchingTask;
026: import org.apache.tools.ant.taskdefs.optional.native2ascii.Native2AsciiAdapter;
027: import org.apache.tools.ant.taskdefs.optional.native2ascii.Native2AsciiAdapterFactory;
028: import org.apache.tools.ant.types.Mapper;
029: import org.apache.tools.ant.util.FileNameMapper;
030: import org.apache.tools.ant.util.IdentityMapper;
031: import org.apache.tools.ant.util.SourceFileScanner;
032: import org.apache.tools.ant.util.facade.FacadeTaskHelper;
033: import org.apache.tools.ant.util.facade.ImplementationSpecificArgument;
034:
035: /**
036: * Converts files from native encodings to ASCII.
037: *
038: * @since Ant 1.2
039: */
040: public class Native2Ascii extends MatchingTask {
041:
042: private boolean reverse = false; // convert from ascii back to native
043: private String encoding = null; // encoding to convert to/from
044: private File srcDir = null; // Where to find input files
045: private File destDir = null; // Where to put output files
046: private String extension = null; // Extension of output files if different
047:
048: private Mapper mapper;
049: private FacadeTaskHelper facade = null;
050:
051: /** No args constructor */
052: public Native2Ascii() {
053: facade = new FacadeTaskHelper(Native2AsciiAdapterFactory
054: .getDefault());
055: }
056:
057: /**
058: * Flag the conversion to run in the reverse sense,
059: * that is Ascii to Native encoding.
060: *
061: * @param reverse True if the conversion is to be reversed,
062: * otherwise false;
063: */
064: public void setReverse(boolean reverse) {
065: this .reverse = reverse;
066: }
067:
068: /**
069: * The value of the reverse attribute.
070: * @return the reverse attribute.
071: * @since Ant 1.6.3
072: */
073: public boolean getReverse() {
074: return reverse;
075: }
076:
077: /**
078: * Set the encoding to translate to/from.
079: * If unset, the default encoding for the JVM is used.
080: *
081: * @param encoding String containing the name of the Native
082: * encoding to convert from or to.
083: */
084: public void setEncoding(String encoding) {
085: this .encoding = encoding;
086: }
087:
088: /**
089: * The value of the encoding attribute.
090: * @return the encoding attribute.
091: * @since Ant 1.6.3
092: */
093: public String getEncoding() {
094: return encoding;
095: }
096:
097: /**
098: * Set the source directory in which to find files to convert.
099: *
100: * @param srcDir directory to find input file in.
101: */
102: public void setSrc(File srcDir) {
103: this .srcDir = srcDir;
104: }
105:
106: /**
107: * Set the destination directory to place converted files into.
108: *
109: * @param destDir directory to place output file into.
110: */
111: public void setDest(File destDir) {
112: this .destDir = destDir;
113: }
114:
115: /**
116: * Set the extension which converted files should have.
117: * If unset, files will not be renamed.
118: *
119: * @param ext File extension to use for converted files.
120: */
121: public void setExt(String ext) {
122: this .extension = ext;
123: }
124:
125: /**
126: * Choose the implementation for this particular task.
127: * @param impl the name of the implemenation
128: * @since Ant 1.6.3
129: */
130: public void setImplementation(String impl) {
131: if ("default".equals(impl)) {
132: facade.setImplementation(Native2AsciiAdapterFactory
133: .getDefault());
134: } else {
135: facade.setImplementation(impl);
136: }
137: }
138:
139: /**
140: * Defines the FileNameMapper to use (nested mapper element).
141: *
142: * @return the mapper to use for file name translations.
143: *
144: * @throws BuildException if more than one mapper is defined.
145: */
146: public Mapper createMapper() throws BuildException {
147: if (mapper != null) {
148: throw new BuildException(
149: "Cannot define more than one mapper", getLocation());
150: }
151: mapper = new Mapper(getProject());
152: return mapper;
153: }
154:
155: /**
156: * A nested filenamemapper
157: * @param fileNameMapper the mapper to add
158: * @since Ant 1.6.3
159: */
160: public void add(FileNameMapper fileNameMapper) {
161: createMapper().add(fileNameMapper);
162: }
163:
164: /**
165: * Adds an implementation specific command-line argument.
166: * @return a ImplementationSpecificArgument to be configured
167: *
168: * @since Ant 1.6.3
169: */
170: public ImplementationSpecificArgument createArg() {
171: ImplementationSpecificArgument arg = new ImplementationSpecificArgument();
172: facade.addImplementationArgument(arg);
173: return arg;
174: }
175:
176: /**
177: * Execute the task
178: *
179: * @throws BuildException is there is a problem in the task execution.
180: */
181: public void execute() throws BuildException {
182:
183: DirectoryScanner scanner = null; // Scanner to find our inputs
184: String[] files; // list of files to process
185:
186: // default srcDir to basedir
187: if (srcDir == null) {
188: srcDir = getProject().resolveFile(".");
189: }
190:
191: // Require destDir
192: if (destDir == null) {
193: throw new BuildException("The dest attribute must be set.");
194: }
195:
196: // if src and dest dirs are the same, require the extension
197: // to be set, so we don't stomp every file. One could still
198: // include a file with the same extension, but ....
199: if (srcDir.equals(destDir) && extension == null
200: && mapper == null) {
201: throw new BuildException(
202: "The ext attribute or a mapper must be set if"
203: + " src and dest dirs are the same.");
204: }
205:
206: FileNameMapper m = null;
207: if (mapper == null) {
208: if (extension == null) {
209: m = new IdentityMapper();
210: } else {
211: m = new ExtMapper();
212: }
213: } else {
214: m = mapper.getImplementation();
215: }
216:
217: scanner = getDirectoryScanner(srcDir);
218: files = scanner.getIncludedFiles();
219: SourceFileScanner sfs = new SourceFileScanner(this );
220: files = sfs.restrict(files, srcDir, destDir, m);
221: int count = files.length;
222: if (count == 0) {
223: return;
224: }
225: String message = "Converting " + count + " file"
226: + (count != 1 ? "s" : "") + " from ";
227: log(message + srcDir + " to " + destDir);
228: for (int i = 0; i < files.length; i++) {
229: convert(files[i], m.mapFileName(files[i])[0]);
230: }
231: }
232:
233: /**
234: * Convert a single file.
235: *
236: * @param srcName name of the input file.
237: * @param destName name of the input file.
238: */
239: private void convert(String srcName, String destName)
240: throws BuildException {
241: File srcFile; // File to convert
242: File destFile; // where to put the results
243:
244: // Build the full file names
245: srcFile = new File(srcDir, srcName);
246: destFile = new File(destDir, destName);
247:
248: // Make sure we're not about to clobber something
249: if (srcFile.equals(destFile)) {
250: throw new BuildException("file " + srcFile
251: + " would overwrite its self");
252: }
253:
254: // Make intermediate directories if needed
255: // XXX JDK 1.1 doesn't have File.getParentFile,
256: String parentName = destFile.getParent();
257: if (parentName != null) {
258: File parentFile = new File(parentName);
259:
260: if ((!parentFile.exists()) && (!parentFile.mkdirs())) {
261: throw new BuildException(
262: "cannot create parent directory " + parentName);
263: }
264: }
265:
266: log("converting " + srcName, Project.MSG_VERBOSE);
267: Native2AsciiAdapter ad = Native2AsciiAdapterFactory.getAdapter(
268: facade.getImplementation(), this );
269: if (!ad.convert(this , srcFile, destFile)) {
270: throw new BuildException("conversion failed");
271: }
272: }
273:
274: /**
275: * Returns the (implementation specific) settings given as nested
276: * arg elements.
277: * @return the arguments.
278: * @since Ant 1.6.3
279: */
280: public String[] getCurrentArgs() {
281: return facade.getArgs();
282: }
283:
284: private class ExtMapper implements FileNameMapper {
285:
286: public void setFrom(String s) {
287: }
288:
289: public void setTo(String s) {
290: }
291:
292: public String[] mapFileName(String fileName) {
293: int lastDot = fileName.lastIndexOf('.');
294: if (lastDot >= 0) {
295: return new String[] { fileName.substring(0, lastDot)
296: + extension };
297: } else {
298: return new String[] { fileName + extension };
299: }
300: }
301: }
302: }
|