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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. */
  18. package org.apache.tools.ant.taskdefs;
  19. import java.io.File;
  20. import java.io.PrintStream;
  21. import java.io.OutputStream;
  22. import java.util.Iterator;
  23. import org.apache.tools.ant.Task;
  24. import org.apache.tools.ant.Project;
  25. import org.apache.tools.ant.BuildException;
  26. import org.apache.tools.ant.taskdefs.condition.Condition;
  27. import org.apache.tools.ant.types.FileSet;
  28. import org.apache.tools.ant.types.Resource;
  29. import org.apache.tools.ant.types.Comparison;
  30. import org.apache.tools.ant.types.ResourceCollection;
  31. import org.apache.tools.ant.types.EnumeratedAttribute;
  32. import org.apache.tools.ant.types.resources.Resources;
  33. import org.apache.tools.ant.types.resources.FileResource;
  34. import org.apache.tools.ant.util.FileUtils;
  35. import org.apache.tools.ant.util.PropertyOutputStream;
  36. /**
  37. * Gets lengths: of files/resources, byte size; of strings, length (optionally trimmed).
  38. * The task is overloaded in this way for semantic reasons, much like Available.
  39. * @since Ant 1.6.3
  40. */
  41. public class Length extends Task implements Condition {
  42. private static final String ALL = "all";
  43. private static final String EACH = "each";
  44. private static final String STRING = "string";
  45. private static final String LENGTH_REQUIRED
  46. = "Use of the Length condition requires that the length attribute be set.";
  47. private String property;
  48. private String string;
  49. private Boolean trim;
  50. private String mode = ALL;
  51. private Comparison when = Comparison.EQUAL;
  52. private Long length;
  53. private Resources resources;
  54. /**
  55. * The property in which the length will be stored.
  56. * @param property the <code>String</code> property key.
  57. */
  58. public synchronized void setProperty(String property) {
  59. this.property = property;
  60. }
  61. /**
  62. * Set the single file for this task.
  63. * @param file the <code>File</code> whose length to retrieve.
  64. */
  65. public synchronized void setFile(File file) {
  66. add(new FileResource(file));
  67. }
  68. /**
  69. * Add a FileSet.
  70. * @param fs the <code>FileSet</code> to add.
  71. */
  72. public synchronized void add(FileSet fs) {
  73. add((ResourceCollection) fs);
  74. }
  75. /**
  76. * Add a ResourceCollection.
  77. * @param c the <code>ResourceCollection</code> to add.
  78. * @since Ant 1.7
  79. */
  80. public synchronized void add(ResourceCollection c) {
  81. if (c == null) {
  82. return;
  83. }
  84. resources = (resources == null) ? new Resources() : resources;
  85. resources.add(c);
  86. }
  87. /**
  88. * Set the target count number for use as a Condition.
  89. * @param ell the long length to compare with.
  90. */
  91. public synchronized void setLength(long ell) {
  92. length = new Long(ell);
  93. }
  94. /**
  95. * Set the comparison for use as a Condition.
  96. * @param w EnumeratedAttribute When.
  97. * @see org.apache.tools.ant.types.Comparison
  98. */
  99. public synchronized void setWhen(When w) {
  100. setWhen((Comparison) w);
  101. }
  102. /**
  103. * Set the comparison for use as a Condition.
  104. * @param c Comparison.
  105. * @see org.apache.tools.ant.types.Comparison
  106. * @since Ant 1.7
  107. */
  108. public synchronized void setWhen(Comparison c) {
  109. when = c;
  110. }
  111. /**
  112. * Set the execution mode for working with files.
  113. * @param m the <code>FileMode</code> to use.
  114. */
  115. public synchronized void setMode(FileMode m) {
  116. this.mode = m.getValue();
  117. }
  118. /**
  119. * Set the string whose length to get.
  120. * @param string <code>String</code>.
  121. */
  122. public synchronized void setString(String string) {
  123. this.string = string;
  124. this.mode = STRING;
  125. }
  126. /**
  127. * Set whether to trim in string mode.
  128. * @param trim <code>boolean</code>.
  129. */
  130. public synchronized void setTrim(boolean trim) {
  131. this.trim = trim ? Boolean.TRUE : Boolean.FALSE;
  132. }
  133. /**
  134. * Learn whether strings will be trimmed.
  135. * @return boolean trim setting.
  136. */
  137. public boolean getTrim() {
  138. return trim != null && trim.booleanValue();
  139. }
  140. /**
  141. * Execute the length task.
  142. */
  143. public void execute() {
  144. validate();
  145. PrintStream ps = new PrintStream((property != null)
  146. ? (OutputStream) new PropertyOutputStream(getProject(), property)
  147. : (OutputStream) new LogOutputStream(this, Project.MSG_INFO));
  148. if (STRING.equals(mode)) {
  149. ps.print(getLength(string, getTrim()));
  150. ps.close();
  151. } else if (EACH.equals(mode)) {
  152. handleResources(new EachHandler(ps));
  153. } else if (ALL.equals(mode)) {
  154. handleResources(new AllHandler(ps));
  155. }
  156. }
  157. /**
  158. * Fulfill the condition contract.
  159. * @return true if the condition is true.
  160. * @throws BuildException if an error occurs.
  161. */
  162. public boolean eval() {
  163. validate();
  164. if (length == null) {
  165. throw new BuildException(LENGTH_REQUIRED);
  166. }
  167. Long ell;
  168. if (STRING.equals(mode)) {
  169. ell = new Long(getLength(string, getTrim()));
  170. } else {
  171. AccumHandler h = new AccumHandler();
  172. handleResources(h);
  173. ell = new Long(h.getAccum());
  174. }
  175. return when.evaluate(ell.compareTo(length));
  176. }
  177. private void validate() {
  178. if (string != null) {
  179. if (resources != null) {
  180. throw new BuildException("the string length function"
  181. + " is incompatible with the file/resource length function");
  182. }
  183. if (!(STRING.equals(mode))) {
  184. throw new BuildException("the mode attribute is for use"
  185. + " with the file/resource length function");
  186. }
  187. } else if (resources != null) {
  188. if (!(EACH.equals(mode) || ALL.equals(mode))) {
  189. throw new BuildException("invalid mode setting for"
  190. + " file/resource length function: \"" + mode + "\"");
  191. } else if (trim != null) {
  192. throw new BuildException("the trim attribute is"
  193. + " for use with the string length function only");
  194. }
  195. } else {
  196. throw new BuildException("you must set either the string attribute"
  197. + " or specify one or more files using the file attribute or"
  198. + " nested resource collections");
  199. }
  200. }
  201. private void handleResources(Handler h) {
  202. for (Iterator i = resources.iterator(); i.hasNext();) {
  203. Resource r = (Resource) i.next();
  204. if (!r.isExists()) {
  205. log(r + " does not exist", Project.MSG_ERR);
  206. } else if (r.isDirectory()) {
  207. log(r + " is a directory; length unspecified",
  208. Project.MSG_ERR);
  209. } else {
  210. h.handle(r);
  211. }
  212. }
  213. h.complete();
  214. }
  215. private static long getLength(String s, boolean t) {
  216. return (t ? s.trim() : s).length();
  217. }
  218. /** EnumeratedAttribute operation mode */
  219. public static class FileMode extends EnumeratedAttribute {
  220. static final String[] MODES = new String[] {EACH, ALL};
  221. /**
  222. * Return the possible values for FileMode.
  223. * @return <code>String[]</code>.
  224. */
  225. public String[] getValues() {
  226. return MODES;
  227. }
  228. }
  229. /**
  230. * EnumeratedAttribute for the when attribute.
  231. */
  232. public static class When extends Comparison {
  233. //extend Comparison; retain for BC only
  234. }
  235. private abstract class Handler {
  236. private PrintStream ps;
  237. Handler(PrintStream ps) {
  238. this.ps = ps;
  239. }
  240. protected PrintStream getPs() {
  241. return ps;
  242. }
  243. protected abstract void handle(Resource r);
  244. void complete() {
  245. FileUtils.close(ps);
  246. }
  247. }
  248. private class EachHandler extends Handler {
  249. EachHandler(PrintStream ps) {
  250. super(ps);
  251. }
  252. protected void handle(Resource r) {
  253. getPs().print(r.toString());
  254. getPs().print(" : ");
  255. //when writing to the log, we'll see what's happening:
  256. long size = r.getSize();
  257. if (size == Resource.UNKNOWN_SIZE) {
  258. getPs().println("unknown");
  259. } else {
  260. getPs().println(size);
  261. }
  262. }
  263. }
  264. private class AccumHandler extends Handler {
  265. private long accum = 0L;
  266. AccumHandler() {
  267. super(null);
  268. }
  269. protected AccumHandler(PrintStream ps) {
  270. super(ps);
  271. }
  272. protected long getAccum() {
  273. return accum;
  274. }
  275. protected synchronized void handle(Resource r) {
  276. long size = r.getSize();
  277. if (size == Resource.UNKNOWN_SIZE) {
  278. log("Size unknown for " + r.toString(), Project.MSG_WARN);
  279. } else {
  280. accum += size;
  281. }
  282. }
  283. }
  284. private class AllHandler extends AccumHandler {
  285. AllHandler(PrintStream ps) {
  286. super(ps);
  287. }
  288. void complete() {
  289. getPs().print(getAccum());
  290. super.complete();
  291. }
  292. }
  293. }