You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

Length.java 10 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. /*
  2. * Copyright 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. */
  17. package org.apache.tools.ant.taskdefs;
  18. import java.io.File;
  19. import java.io.PrintStream;
  20. import java.io.OutputStream;
  21. import java.io.ByteArrayOutputStream;
  22. import java.util.Vector;
  23. import java.util.Iterator;
  24. import org.apache.tools.ant.Task;
  25. import org.apache.tools.ant.Project;
  26. import org.apache.tools.ant.BuildException;
  27. import org.apache.tools.ant.DirectoryScanner;
  28. import org.apache.tools.ant.taskdefs.condition.Condition;
  29. import org.apache.tools.ant.types.FileSet;
  30. import org.apache.tools.ant.types.Resource;
  31. import org.apache.tools.ant.types.EnumeratedAttribute;
  32. import org.apache.tools.ant.util.FileUtils;
  33. /**
  34. * Gets lengths: of files/resources, byte size; of strings, length (optionally trimmed).
  35. * The task is overloaded in this way for semantic reasons, much like Available.
  36. * @since Ant 1.6.3
  37. */
  38. public class Length extends Task implements Condition {
  39. private static final String ALL = "all";
  40. private static final String EACH = "each";
  41. private static final String STRING = "string";
  42. private static final String LENGTH_REQUIRED
  43. = "Use of the Length condition requires that the length attribute be set.";
  44. private String property;
  45. private String string;
  46. private Boolean trim;
  47. private String mode = ALL;
  48. private When when = When.EQUAL;
  49. private Long length;
  50. private Vector filesets;
  51. /**
  52. * The property in which the length will be stored.
  53. * @param property the <code>String</code> property key.
  54. */
  55. public synchronized void setProperty(String property) {
  56. this.property = property;
  57. }
  58. /**
  59. * Set the single file for this task.
  60. * @param file the <code>File</code> whose length to retrieve.
  61. */
  62. public synchronized void setFile(File file) {
  63. FileSet fs = new FileSet();
  64. fs.setFile(file);
  65. add(fs);
  66. }
  67. /**
  68. * Add a FileSet.
  69. * @param fs the <code>FileSet</code> to add.
  70. */
  71. public synchronized void add(FileSet fs) {
  72. if (fs == null) {
  73. return;
  74. }
  75. filesets = (filesets == null) ? new Vector() : filesets;
  76. filesets.add(fs);
  77. }
  78. /**
  79. * Set the target count number for use as a Condition.
  80. * @param ell the long length to compare with.
  81. */
  82. public synchronized void setLength(long ell) {
  83. length = new Long(ell);
  84. }
  85. /**
  86. * Set the comparison criteria for use as a Condition:
  87. * "equal", "greater", "less". Default is "equal".
  88. * @param w EnumeratedAttribute When.
  89. */
  90. public synchronized void setWhen(When w) {
  91. when = w;
  92. }
  93. /**
  94. * Set the execution mode for working with files.
  95. * @param m the <code>FileMode</code> to use.
  96. */
  97. public synchronized void setMode(FileMode m) {
  98. this.mode = m.getValue();
  99. }
  100. /**
  101. * Set the string whose length to get.
  102. * @param string <code>String</code>.
  103. */
  104. public synchronized void setString(String string) {
  105. this.string = string;
  106. this.mode = STRING;
  107. }
  108. /**
  109. * Set whether to trim in string mode.
  110. * @param trim <code>boolean</code>.
  111. */
  112. public synchronized void setTrim(boolean trim) {
  113. this.trim = trim ? Boolean.TRUE : Boolean.FALSE;
  114. }
  115. /**
  116. * Learn whether strings will be trimmed.
  117. * @return boolean trim setting.
  118. */
  119. public boolean getTrim() {
  120. return trim != null && trim.booleanValue();
  121. }
  122. /**
  123. * Execute the length task.
  124. */
  125. public void execute() {
  126. validate();
  127. PrintStream ps = new PrintStream((property != null)
  128. ? (OutputStream) new PropertyOutputStream()
  129. : (OutputStream) new LogOutputStream(this, Project.MSG_INFO));
  130. if (STRING.equals(mode)) {
  131. ps.print(getLength(string, getTrim()));
  132. ps.close();
  133. } else if (EACH.equals(mode)) {
  134. handleResources(new EachHandler(ps));
  135. } else if (ALL.equals(mode)) {
  136. handleResources(new AllHandler(ps));
  137. }
  138. }
  139. /**
  140. * Fulfill the condition contract.
  141. * @return true if the condition is true.
  142. * @throws BuildException if an error occurs.
  143. */
  144. public boolean eval() {
  145. validate();
  146. if (length == null) {
  147. throw new BuildException(LENGTH_REQUIRED);
  148. }
  149. Long ell = null;
  150. if (STRING.equals(mode)) {
  151. ell = new Long(getLength(string, getTrim()));
  152. } else {
  153. ConditionHandler h = new ConditionHandler();
  154. handleResources(h);
  155. ell = new Long(h.getLength());
  156. }
  157. int w = when.getIndex();
  158. int comp = ell.compareTo(length);
  159. return (w == 0 && comp == 0)
  160. || (w == 1 && comp > 0)
  161. || (w == 2 && comp < 0);
  162. }
  163. private void validate() {
  164. if (string != null) {
  165. if (filesets != null && filesets.size() > 0) {
  166. throw new BuildException("the string length function"
  167. + " is incompatible with the file length function");
  168. }
  169. if (!(STRING.equals(mode))) {
  170. throw new BuildException("the mode attribute is for use"
  171. + " with the file/resource length function");
  172. }
  173. } else if (filesets != null) {
  174. if (!(EACH.equals(mode) || ALL.equals(mode))) {
  175. throw new BuildException("invalid mode setting for"
  176. + " file length function: \"" + mode + "\"");
  177. } else if (trim != null) {
  178. throw new BuildException("the trim attribute is"
  179. + " for use with the string length function only");
  180. }
  181. } else {
  182. throw new BuildException("you must set either the string attribute"
  183. + " or specify one or more files using the file attribute or"
  184. + " nested filesets");
  185. }
  186. }
  187. private void handleResources(Handler h) {
  188. for (Iterator i = filesets.iterator(); i.hasNext();) {
  189. FileSet fs = (FileSet) i.next();
  190. DirectoryScanner ds = fs.getDirectoryScanner(getProject());
  191. String[] f = ds.getIncludedFiles();
  192. for (int j = 0; j < f.length; j++) {
  193. Resource r = ds.getResource(f[j]);
  194. if (!r.isExists()) {
  195. log(r.getName() + " does not exist", Project.MSG_ERR);
  196. } else if (r.isDirectory()) {
  197. log(r.getName() + " is a directory; length unspecified",
  198. Project.MSG_ERR);
  199. } else {
  200. //force a full path:
  201. File basedir = ds.getBasedir();
  202. String s = FileUtils.getFileUtils().resolveFile(
  203. basedir, r.getName()).getAbsolutePath();
  204. h.handle(new Resource(s, true,
  205. r.getLastModified(), false, r.getSize()));
  206. }
  207. }
  208. }
  209. h.complete();
  210. }
  211. private static long getLength(String s, boolean t) {
  212. return (t ? s.trim() : s).length();
  213. }
  214. /** EnumeratedAttribute operation mode */
  215. public static class FileMode extends EnumeratedAttribute {
  216. static final String[] MODES = new String[] {EACH, ALL};
  217. /**
  218. * Return the possible values for FileMode.
  219. * @return <code>String[]</code>.
  220. */
  221. public String[] getValues() {
  222. return MODES;
  223. }
  224. }
  225. /**
  226. * EnumeratedAttribute for the when attribute.
  227. */
  228. public static class When extends EnumeratedAttribute {
  229. private static final String[] VALUES
  230. = new String[] {"equal", "greater", "less"};
  231. private static final When EQUAL = new When("equal");
  232. public When() {
  233. }
  234. public When(String value) {
  235. setValue(value);
  236. }
  237. public String[] getValues() {
  238. return VALUES;
  239. }
  240. }
  241. private class PropertyOutputStream extends ByteArrayOutputStream {
  242. public void close() {
  243. getProject().setNewProperty(
  244. property, new String(toByteArray()).trim());
  245. }
  246. }
  247. private abstract class Handler {
  248. PrintStream ps;
  249. Handler(PrintStream ps) {
  250. this.ps = ps;
  251. }
  252. protected abstract void handle(Resource r);
  253. void complete() {
  254. ps.close();
  255. }
  256. }
  257. private class EachHandler extends Handler {
  258. EachHandler(PrintStream ps) {
  259. super(ps);
  260. }
  261. protected void handle(Resource r) {
  262. ps.print(r.getName());
  263. ps.print(" : ");
  264. //when writing to the log, we'll see what's happening:
  265. long size = r.getSize();
  266. if (size == Resource.UNKNOWN_SIZE) {
  267. ps.println("unknown");
  268. } else {
  269. ps.println(size);
  270. }
  271. }
  272. }
  273. private class AllHandler extends Handler {
  274. long accum = 0L;
  275. AllHandler(PrintStream ps) {
  276. super(ps);
  277. }
  278. protected synchronized void handle(Resource r) {
  279. long size = r.getSize();
  280. if (size == Resource.UNKNOWN_SIZE) {
  281. log("Size unknown for " + r.getName(), Project.MSG_WARN);
  282. } else {
  283. accum += size;
  284. }
  285. }
  286. void complete() {
  287. ps.print(accum);
  288. super.complete();
  289. }
  290. }
  291. private class ConditionHandler extends AllHandler {
  292. ConditionHandler() {
  293. super(null);
  294. }
  295. void complete() {
  296. }
  297. long getLength() {
  298. return accum;
  299. }
  300. }
  301. }