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.

Truncate.java 6.2 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  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.IOException;
  21. import java.io.RandomAccessFile;
  22. import java.util.Iterator;
  23. import org.apache.tools.ant.BuildException;
  24. import org.apache.tools.ant.Project;
  25. import org.apache.tools.ant.Task;
  26. import org.apache.tools.ant.types.EnumeratedAttribute;
  27. import org.apache.tools.ant.types.Path;
  28. import org.apache.tools.ant.types.ResourceCollection;
  29. import org.apache.tools.ant.types.resources.FileResource;
  30. import org.apache.tools.ant.util.FileUtils;
  31. import org.apache.tools.ant.util.StringUtils;
  32. /**
  33. * Set the length of one or more files, as the intermittently available
  34. * <code>truncate</code> Unix utility/function.
  35. * @since Ant 1.7.1
  36. */
  37. public class Truncate extends Task {
  38. private static final Long ZERO = new Long(0L);
  39. private static final String NO_CHILD = "No files specified.";
  40. private static final String INVALID_LENGTH = "Cannot truncate to length ";
  41. private static final String READ_WRITE = "rw";
  42. private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
  43. private static final byte[] FILL_BUFFER = new byte[1024];
  44. private Path path;
  45. private boolean create = true;
  46. private boolean mkdirs = false;
  47. private Long length;
  48. private Long adjust;
  49. /**
  50. * Set a single target File.
  51. * @param f the single File
  52. */
  53. public void setFile(File f) {
  54. add(new FileResource(f));
  55. }
  56. /**
  57. * Add a nested (filesystem-only) ResourceCollection.
  58. * @param rc the ResourceCollection to add.
  59. */
  60. public void add(ResourceCollection rc) {
  61. getPath().add(rc);
  62. }
  63. /**
  64. * Set the amount by which files' lengths should be adjusted.
  65. * It is permissible to append K / M / G / T / P.
  66. * @param adjust (positive or negative) adjustment amount.
  67. */
  68. public void setAdjust(Long adjust) {
  69. this.adjust = adjust;
  70. }
  71. /**
  72. * Set the length to which files should be set.
  73. * It is permissible to append K / M / G / T / P.
  74. * @param adjust (positive) adjustment amount.
  75. */
  76. public void setLength(Long length) {
  77. this.length = length;
  78. if (length != null && length.longValue() < 0) {
  79. throw new BuildException(INVALID_LENGTH + length);
  80. }
  81. }
  82. /**
  83. * Set whether to create nonexistent files.
  84. * @param create boolean, default <code>true</code>.
  85. */
  86. public void setCreate(boolean create) {
  87. this.create = create;
  88. }
  89. /**
  90. * Set whether, when creating nonexistent files, nonexistent directories
  91. * should also be created.
  92. * @param mkdirs boolean, default <code>false</code>.
  93. */
  94. public void setMkdirs(boolean mkdirs) {
  95. this.mkdirs = mkdirs;
  96. }
  97. /** {@inheritDoc}. */
  98. public void execute() {
  99. if (length != null && adjust != null) {
  100. throw new BuildException(
  101. "length and adjust are mutually exclusive options");
  102. }
  103. if (length == null && adjust == null) {
  104. length = ZERO;
  105. }
  106. if (path == null) {
  107. throw new BuildException(NO_CHILD);
  108. }
  109. for (Iterator it = path.iterator(); it.hasNext();) {
  110. File f = ((FileResource) it.next()).getFile();
  111. if (shouldProcess(f)) {
  112. process(f);
  113. }
  114. }
  115. }
  116. private boolean shouldProcess(File f) {
  117. if (f.isFile()) {
  118. return true;
  119. }
  120. if (!create) {
  121. return false;
  122. }
  123. Exception exception = null;
  124. try {
  125. if (FILE_UTILS.createNewFile(f, mkdirs)) {
  126. return true;
  127. }
  128. } catch (IOException e) {
  129. exception = e;
  130. }
  131. String msg = "Unable to create " + f;
  132. if (exception == null) {
  133. log(msg, Project.MSG_WARN);
  134. return false;
  135. }
  136. throw new BuildException(msg, exception);
  137. }
  138. private void process(File f) {
  139. long len = f.length();
  140. long newLength = length == null
  141. ? len + adjust.longValue() : length.longValue();
  142. if (len == newLength) {
  143. //nothing to do!
  144. return;
  145. }
  146. RandomAccessFile raf = null;
  147. try {
  148. raf = new RandomAccessFile(f, READ_WRITE);
  149. } catch (Exception e) {
  150. throw new BuildException("Could not open " + f + " for writing", e);
  151. }
  152. try {
  153. if (newLength > len) {
  154. long pos = len;
  155. raf.seek(pos);
  156. while (pos < newLength) {
  157. long writeCount = Math.min(FILL_BUFFER.length,
  158. newLength - pos);
  159. raf.write(FILL_BUFFER, 0, (int) writeCount);
  160. pos += writeCount;
  161. }
  162. } else {
  163. raf.setLength(newLength);
  164. }
  165. } catch (IOException e) {
  166. throw new BuildException("Exception working with " + raf, e);
  167. } finally {
  168. try {
  169. raf.close();
  170. } catch (IOException e) {
  171. log("Caught " + e + " closing " + raf, Project.MSG_WARN);
  172. }
  173. }
  174. }
  175. private synchronized Path getPath() {
  176. if (path == null) {
  177. path = new Path(getProject());
  178. }
  179. return path;
  180. }
  181. }