/* * 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.tools.ant.taskdefs.optional; import java.io.File; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.DirectoryScanner; import org.apache.tools.ant.Project; import org.apache.tools.ant.taskdefs.MatchingTask; import org.apache.tools.ant.taskdefs.optional.native2ascii.Native2AsciiAdapter; import org.apache.tools.ant.taskdefs.optional.native2ascii.Native2AsciiAdapterFactory; import org.apache.tools.ant.types.Mapper; import org.apache.tools.ant.types.Path; import org.apache.tools.ant.util.FileNameMapper; import org.apache.tools.ant.util.IdentityMapper; import org.apache.tools.ant.util.SourceFileScanner; import org.apache.tools.ant.util.facade.FacadeTaskHelper; import org.apache.tools.ant.util.facade.ImplementationSpecificArgument; /** * Converts files from native encodings to ASCII. * * @since Ant 1.2 */ public class Native2Ascii extends MatchingTask { private boolean reverse = false; // convert from ascii back to native private String encoding = null; // encoding to convert to/from private File srcDir = null; // Where to find input files private File destDir = null; // Where to put output files private String extension = null; // Extension of output files if different private Mapper mapper; private FacadeTaskHelper facade = null; private Native2AsciiAdapter nestedAdapter = null; /** No args constructor */ public Native2Ascii() { facade = new FacadeTaskHelper(Native2AsciiAdapterFactory.getDefault()); } /** * Flag the conversion to run in the reverse sense, * that is Ascii to Native encoding. * * @param reverse True if the conversion is to be reversed, * otherwise false; */ public void setReverse(boolean reverse) { this.reverse = reverse; } /** * The value of the reverse attribute. * @return the reverse attribute. * @since Ant 1.6.3 */ public boolean getReverse() { return reverse; } /** * Set the encoding to translate to/from. * If unset, the default encoding for the JVM is used. * * @param encoding String containing the name of the Native * encoding to convert from or to. */ public void setEncoding(String encoding) { this.encoding = encoding; } /** * The value of the encoding attribute. * @return the encoding attribute. * @since Ant 1.6.3 */ public String getEncoding() { return encoding; } /** * Set the source directory in which to find files to convert. * * @param srcDir directory to find input file in. */ public void setSrc(File srcDir) { this.srcDir = srcDir; } /** * Set the destination directory to place converted files into. * * @param destDir directory to place output file into. */ public void setDest(File destDir) { this.destDir = destDir; } /** * Set the extension which converted files should have. * If unset, files will not be renamed. * * @param ext File extension to use for converted files. */ public void setExt(String ext) { this.extension = ext; } /** * Choose the implementation for this particular task. * @param impl the name of the implementation * @since Ant 1.6.3 */ public void setImplementation(String impl) { if ("default".equals(impl)) { facade.setImplementation(Native2AsciiAdapterFactory.getDefault()); } else { facade.setImplementation(impl); } } /** * Defines the FileNameMapper to use (nested mapper element). * * @return the mapper to use for file name translations. * * @throws BuildException if more than one mapper is defined. */ public Mapper createMapper() throws BuildException { if (mapper != null) { throw new BuildException("Cannot define more than one mapper", getLocation()); } mapper = new Mapper(getProject()); return mapper; } /** * A nested filenamemapper * @param fileNameMapper the mapper to add * @since Ant 1.6.3 */ public void add(FileNameMapper fileNameMapper) { createMapper().add(fileNameMapper); } /** * Adds an implementation specific command-line argument. * @return a ImplementationSpecificArgument to be configured * * @since Ant 1.6.3 */ public ImplementationSpecificArgument createArg() { ImplementationSpecificArgument arg = new ImplementationSpecificArgument(); facade.addImplementationArgument(arg); return arg; } /** * The classpath to use when loading the native2ascii * implementation if it is not a built-in one. * * @since Ant 1.8.0 */ public Path createImplementationClasspath() { return facade.getImplementationClasspath(getProject()); } /** * Set the adapter explicitly. * @since Ant 1.8.0 */ public void add(Native2AsciiAdapter adapter) { if (nestedAdapter != null) { throw new BuildException( "Can't have more than one native2ascii adapter"); } nestedAdapter = adapter; } /** * Execute the task * * @throws BuildException is there is a problem in the task execution. */ @Override public void execute() throws BuildException { DirectoryScanner scanner = null; // Scanner to find our inputs String[] files; // list of files to process // default srcDir to basedir if (srcDir == null) { srcDir = getProject().resolveFile("."); } // Require destDir if (destDir == null) { throw new BuildException("The dest attribute must be set."); } // if src and dest dirs are the same, require the extension // to be set, so we don't stomp every file. One could still // include a file with the same extension, but .... if (srcDir.equals(destDir) && extension == null && mapper == null) { throw new BuildException( "The ext attribute or a mapper must be set if src and dest dirs are the same."); } FileNameMapper m; if (mapper == null) { if (extension == null) { m = new IdentityMapper(); } else { m = new ExtMapper(); } } else { m = mapper.getImplementation(); } scanner = getDirectoryScanner(srcDir); files = scanner.getIncludedFiles(); SourceFileScanner sfs = new SourceFileScanner(this); files = sfs.restrict(files, srcDir, destDir, m); int count = files.length; if (count == 0) { return; } String message = "Converting " + count + " file" + (count != 1 ? "s" : "") + " from "; log(message + srcDir + " to " + destDir); for (int i = 0; i < files.length; i++) { convert(files[i], m.mapFileName(files[i])[0]); } } /** * Convert a single file. * * @param srcName name of the input file. * @param destName name of the input file. */ private void convert(String srcName, String destName) throws BuildException { File srcFile; // File to convert File destFile; // where to put the results // Build the full file names srcFile = new File(srcDir, srcName); destFile = new File(destDir, destName); // Make sure we're not about to clobber something if (srcFile.equals(destFile)) { throw new BuildException("file %s would overwrite itself", srcFile); } // Make intermediate directories if needed // TODO JDK 1.1 doesn't have File.getParentFile, String parentName = destFile.getParent(); if (parentName != null) { File parentFile = new File(parentName); if (!parentFile.exists() && !(parentFile.mkdirs() || parentFile.isDirectory())) { throw new BuildException("cannot create parent directory %s", parentName); } } log("converting " + srcName, Project.MSG_VERBOSE); Native2AsciiAdapter ad = nestedAdapter != null ? nestedAdapter : Native2AsciiAdapterFactory.getAdapter(facade.getImplementation(), this, createImplementationClasspath()); if (!ad.convert(this, srcFile, destFile)) { throw new BuildException("conversion failed"); } } /** * Returns the (implementation specific) settings given as nested * arg elements. * @return the arguments. * @since Ant 1.6.3 */ public String[] getCurrentArgs() { return facade.getArgs(); } private class ExtMapper implements FileNameMapper { @Override public void setFrom(String s) { } @Override public void setTo(String s) { } @Override public String[] mapFileName(String fileName) { int lastDot = fileName.lastIndexOf('.'); if (lastDot >= 0) { return new String[] { fileName.substring(0, lastDot) + extension }; } return new String[] { fileName + extension }; } } }