/*
 *  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
 *
 *      https://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 java.io.File;
import java.io.OutputStream;
import java.io.PrintStream;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.taskdefs.condition.Condition;
import org.apache.tools.ant.types.Comparison;
import org.apache.tools.ant.types.EnumeratedAttribute;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.types.Resource;
import org.apache.tools.ant.types.ResourceCollection;
import org.apache.tools.ant.types.resources.FileResource;
import org.apache.tools.ant.types.resources.Resources;
import org.apache.tools.ant.util.FileUtils;
import org.apache.tools.ant.util.PropertyOutputStream;

Gets lengths: of files/resources, byte size; of strings, length (optionally trimmed). The task is overloaded in this way for semantic reasons, much like Available.
Since:Ant 1.6.3
/** * Gets lengths: of files/resources, byte size; of strings, length (optionally trimmed). * The task is overloaded in this way for semantic reasons, much like Available. * @since Ant 1.6.3 */
public class Length extends Task implements Condition { private static final String ALL = "all"; private static final String EACH = "each"; private static final String STRING = "string"; private static final String LENGTH_REQUIRED = "Use of the Length condition requires that the length attribute be set."; private String property; private String string; private Boolean trim; private String mode = ALL; private Comparison when = Comparison.EQUAL; private Long length; private Resources resources;
The property in which the length will be stored.
Params:
  • property – the String property key.
/** * The property in which the length will be stored. * @param property the <code>String</code> property key. */
public synchronized void setProperty(String property) { this.property = property; }
Set the single resource for this task.
Params:
  • resource – the Resource whose length to retrieve.
/** * Set the single resource for this task. * @param resource the Resource whose length to retrieve. */
public synchronized void setResource(Resource resource) { add(resource); }
Set the single file for this task.
Params:
  • file – the File whose length to retrieve.
/** * Set the single file for this task. * @param file the <code>File</code> whose length to retrieve. */
public synchronized void setFile(File file) { add(new FileResource(file)); }
Add a FileSet.
Params:
  • fs – the FileSet to add.
/** * Add a FileSet. * @param fs the <code>FileSet</code> to add. */
public synchronized void add(FileSet fs) { add((ResourceCollection) fs); }
Add a ResourceCollection.
Params:
  • c – the ResourceCollection to add.
Since:Ant 1.7
/** * Add a ResourceCollection. * @param c the <code>ResourceCollection</code> to add. * @since Ant 1.7 */
public synchronized void add(ResourceCollection c) { if (c == null) { return; } resources = (resources == null) ? new Resources() : resources; resources.add(c); }
Set the target count number for use as a Condition.
Params:
  • ell – the long length to compare with.
/** * Set the target count number for use as a Condition. * @param ell the long length to compare with. */
public synchronized void setLength(long ell) { length = ell; }
Set the comparison for use as a Condition.
Params:
  • w – EnumeratedAttribute When.
See Also:
/** * Set the comparison for use as a Condition. * @param w EnumeratedAttribute When. * @see org.apache.tools.ant.types.Comparison */
public synchronized void setWhen(When w) { setWhen((Comparison) w); }
Set the comparison for use as a Condition.
Params:
  • c – Comparison.
See Also:
Since:Ant 1.7
/** * Set the comparison for use as a Condition. * @param c Comparison. * @see org.apache.tools.ant.types.Comparison * @since Ant 1.7 */
public synchronized void setWhen(Comparison c) { when = c; }
Set the execution mode for working with files.
Params:
  • m – the FileMode to use.
/** * Set the execution mode for working with files. * @param m the <code>FileMode</code> to use. */
public synchronized void setMode(FileMode m) { this.mode = m.getValue(); }
Set the string whose length to get.
Params:
  • string – String.
/** * Set the string whose length to get. * @param string <code>String</code>. */
public synchronized void setString(String string) { this.string = string; this.mode = STRING; }
Set whether to trim in string mode. Default false.
Params:
  • trim – boolean.
/** * Set whether to trim in string mode. Default false. * @param trim <code>boolean</code>. */
public synchronized void setTrim(boolean trim) { this.trim = trim; }
Learn whether strings will be trimmed. Default false.
Returns:boolean trim setting.
/** * Learn whether strings will be trimmed. Default false. * @return boolean trim setting. */
public boolean getTrim() { return Boolean.TRUE.equals(trim); }
Execute the length task.
/** * Execute the length task. */
@Override public void execute() { validate(); OutputStream out = property == null ? new LogOutputStream(this, Project.MSG_INFO) : new PropertyOutputStream(getProject(), property); PrintStream ps = new PrintStream(out); switch (mode) { case STRING: ps.print(getLength(string, getTrim())); ps.close(); break; case EACH: handleResources(new EachHandler(ps)); break; case ALL: handleResources(new AllHandler(ps)); break; } }
Fulfill the condition contract.
Throws:
Returns:true if the condition is true.
/** * Fulfill the condition contract. * @return true if the condition is true. * @throws BuildException if an error occurs. */
@Override public boolean eval() { validate(); if (length == null) { throw new BuildException(LENGTH_REQUIRED); } Long ell; if (STRING.equals(mode)) { ell = getLength(string, getTrim()); } else { AccumHandler h = new AccumHandler(); handleResources(h); ell = h.getAccum(); } return when.evaluate(ell.compareTo(length)); } private void validate() { if (string != null) { if (resources != null) { throw new BuildException( "the string length function is incompatible with the file/resource length function"); } if (!(STRING.equals(mode))) { throw new BuildException( "the mode attribute is for use with the file/resource length function"); } } else if (resources != null) { if (!EACH.equals(mode) && !ALL.equals(mode)) { throw new BuildException( "invalid mode setting for file/resource length function: \"" + mode + "\""); } if (trim != null) { throw new BuildException( "the trim attribute is for use with the string length function only"); } } else { throw new BuildException( "you must set either the string attribute or specify one or more files using the file attribute or nested resource collections"); } } private void handleResources(Handler h) { for (Resource r : resources) { if (!r.isExists()) { log(r + " does not exist", Project.MSG_WARN); } if (r.isDirectory()) { log(r + " is a directory; length may not be meaningful", Project.MSG_WARN); } h.handle(r); } h.complete(); } private static long getLength(String s, boolean t) { return (t ? s.trim() : s).length(); }
EnumeratedAttribute operation mode
/** EnumeratedAttribute operation mode */
public static class FileMode extends EnumeratedAttribute { static final String[] MODES = new String[] {EACH, ALL}; //NOSONAR
Return the possible values for FileMode.
Returns:String[].
/** * Return the possible values for FileMode. * @return <code>String[]</code>. */
@Override public String[] getValues() { return MODES; } }
EnumeratedAttribute for the when attribute.
/** * EnumeratedAttribute for the when attribute. */
public static class When extends Comparison { //extend Comparison; retain for BC only } private abstract class Handler { private PrintStream ps; Handler(PrintStream ps) { this.ps = ps; } protected PrintStream getPs() { return ps; } protected abstract void handle(Resource r); void complete() { FileUtils.close(ps); } } private class EachHandler extends Handler { EachHandler(PrintStream ps) { super(ps); } @Override protected void handle(Resource r) { getPs().print(r.toString()); getPs().print(" : "); //when writing to the log, we'll see what's happening: long size = r.getSize(); if (size == Resource.UNKNOWN_SIZE) { getPs().println("unknown"); } else { getPs().println(size); } } } private class AccumHandler extends Handler { private long accum = 0L; AccumHandler() { super(null); } protected AccumHandler(PrintStream ps) { super(ps); } protected long getAccum() { return accum; } @Override protected synchronized void handle(Resource r) { long size = r.getSize(); if (size == Resource.UNKNOWN_SIZE) { log("Size unknown for " + r.toString(), Project.MSG_WARN); } else { accum += size; } } } private class AllHandler extends AccumHandler { AllHandler(PrintStream ps) { super(ps); } @Override void complete() { getPs().print(getAccum()); super.complete(); } } }