1 | /*
|
---|
2 | * Copyright 2002-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 |
|
---|
18 | package org.apache.tools.ant.types.selectors;
|
---|
19 |
|
---|
20 | import java.io.File;
|
---|
21 |
|
---|
22 | import org.apache.tools.ant.types.EnumeratedAttribute;
|
---|
23 | import org.apache.tools.ant.types.Parameter;
|
---|
24 |
|
---|
25 | /**
|
---|
26 | * Selector that filters files based on their size.
|
---|
27 | *
|
---|
28 | * @since 1.5
|
---|
29 | */
|
---|
30 | public class SizeSelector extends BaseExtendSelector {
|
---|
31 |
|
---|
32 | private long size = -1;
|
---|
33 | private long multiplier = 1;
|
---|
34 | private long sizelimit = -1;
|
---|
35 | private int cmp = 2;
|
---|
36 | /** Used for parameterized custom selector */
|
---|
37 | public static final String SIZE_KEY = "value";
|
---|
38 | /** Used for parameterized custom selector */
|
---|
39 | public static final String UNITS_KEY = "units";
|
---|
40 | /** Used for parameterized custom selector */
|
---|
41 | public static final String WHEN_KEY = "when";
|
---|
42 |
|
---|
43 | /**
|
---|
44 | * Creates a new <code>SizeSelector</code> instance.
|
---|
45 | *
|
---|
46 | */
|
---|
47 | public SizeSelector() {
|
---|
48 | }
|
---|
49 |
|
---|
50 | /**
|
---|
51 | * Returns a <code>String</code> object representing the specified
|
---|
52 | * SizeSelector. This is "{sizeselector value: " + <"compare",
|
---|
53 | * "less", "more", "equal"> + "}".
|
---|
54 | * @return a string describing this object
|
---|
55 | */
|
---|
56 | public String toString() {
|
---|
57 | StringBuffer buf = new StringBuffer("{sizeselector value: ");
|
---|
58 | buf.append(sizelimit);
|
---|
59 | buf.append("compare: ");
|
---|
60 | if (cmp == 0) {
|
---|
61 | buf.append("less");
|
---|
62 | } else if (cmp == 1) {
|
---|
63 | buf.append("more");
|
---|
64 | } else {
|
---|
65 | buf.append("equal");
|
---|
66 | }
|
---|
67 | buf.append("}");
|
---|
68 | return buf.toString();
|
---|
69 | }
|
---|
70 |
|
---|
71 | /**
|
---|
72 | * A size selector needs to know what size to base its selecting on.
|
---|
73 | * This will be further modified by the multiplier to get an
|
---|
74 | * actual size limit.
|
---|
75 | *
|
---|
76 | * @param size the size to select against expressed in units.
|
---|
77 | */
|
---|
78 | public void setValue(long size) {
|
---|
79 | this.size = size;
|
---|
80 | if ((multiplier != 0) && (size > -1)) {
|
---|
81 | sizelimit = size * multiplier;
|
---|
82 | }
|
---|
83 | }
|
---|
84 |
|
---|
85 | /**
|
---|
86 | * Sets the units to use for the comparison. This is a little
|
---|
87 | * complicated because common usage has created standards that
|
---|
88 | * play havoc with capitalization rules. Thus, some people will
|
---|
89 | * use "K" for indicating 1000's, when the SI standard calls for
|
---|
90 | * "k". Others have tried to introduce "K" as a multiple of 1024,
|
---|
91 | * but that falls down when you reach "M", since "m" is already
|
---|
92 | * defined as 0.001.
|
---|
93 | * <p>
|
---|
94 | * To get around this complexity, a number of standards bodies
|
---|
95 | * have proposed the 2^10 standard, and at least one has adopted
|
---|
96 | * it. But we are still left with a populace that isn't clear on
|
---|
97 | * how capitalization should work.
|
---|
98 | * <p>
|
---|
99 | * We therefore ignore capitalization as much as possible.
|
---|
100 | * Completely mixed case is not possible, but all upper and lower
|
---|
101 | * forms are accepted for all long and short forms. Since we have
|
---|
102 | * no need to work with the 0.001 case, this practice works here.
|
---|
103 | * <p>
|
---|
104 | * This function translates all the long and short forms that a
|
---|
105 | * unit prefix can occur in and translates them into a single
|
---|
106 | * multiplier.
|
---|
107 | *
|
---|
108 | * @param units The units to compare the size to, using an
|
---|
109 | * EnumeratedAttribute.
|
---|
110 | */
|
---|
111 | public void setUnits(ByteUnits units) {
|
---|
112 | int i = units.getIndex();
|
---|
113 | multiplier = 0;
|
---|
114 | if ((i > -1) && (i < 4)) {
|
---|
115 | multiplier = 1000;
|
---|
116 | } else if ((i > 3) && (i < 9)) {
|
---|
117 | multiplier = 1024;
|
---|
118 | } else if ((i > 8) && (i < 13)) {
|
---|
119 | multiplier = 1000000;
|
---|
120 | } else if ((i > 12) && (i < 18)) {
|
---|
121 | multiplier = 1048576;
|
---|
122 | } else if ((i > 17) && (i < 22)) {
|
---|
123 | multiplier = 1000000000L;
|
---|
124 | } else if ((i > 21) && (i < 27)) {
|
---|
125 | multiplier = 1073741824L;
|
---|
126 | } else if ((i > 26) && (i < 31)) {
|
---|
127 | multiplier = 1000000000000L;
|
---|
128 | } else if ((i > 30) && (i < 36)) {
|
---|
129 | multiplier = 1099511627776L;
|
---|
130 | }
|
---|
131 | if ((multiplier > 0) && (size > -1)) {
|
---|
132 | sizelimit = size * multiplier;
|
---|
133 | }
|
---|
134 | }
|
---|
135 |
|
---|
136 | /**
|
---|
137 | * This specifies when the file should be selected, whether it be
|
---|
138 | * when the file matches a particular size, when it is smaller,
|
---|
139 | * or whether it is larger.
|
---|
140 | *
|
---|
141 | * @param scmp The comparison to perform, an EnumeratedAttribute.
|
---|
142 | */
|
---|
143 | public void setWhen(SizeComparisons scmp) {
|
---|
144 | this.cmp = scmp.getIndex();
|
---|
145 | }
|
---|
146 |
|
---|
147 | /**
|
---|
148 | * When using this as a custom selector, this method will be called.
|
---|
149 | * It translates each parameter into the appropriate setXXX() call.
|
---|
150 | *
|
---|
151 | * @param parameters the complete set of parameters for this selector.
|
---|
152 | */
|
---|
153 | public void setParameters(Parameter[] parameters) {
|
---|
154 | super.setParameters(parameters);
|
---|
155 | if (parameters != null) {
|
---|
156 | for (int i = 0; i < parameters.length; i++) {
|
---|
157 | String paramname = parameters[i].getName();
|
---|
158 | if (SIZE_KEY.equalsIgnoreCase(paramname)) {
|
---|
159 | try {
|
---|
160 | setValue(new Long(parameters[i].getValue()
|
---|
161 | ).longValue());
|
---|
162 | } catch (NumberFormatException nfe) {
|
---|
163 | setError("Invalid size setting "
|
---|
164 | + parameters[i].getValue());
|
---|
165 | }
|
---|
166 | } else if (UNITS_KEY.equalsIgnoreCase(paramname)) {
|
---|
167 | ByteUnits units = new ByteUnits();
|
---|
168 | units.setValue(parameters[i].getValue());
|
---|
169 | setUnits(units);
|
---|
170 | } else if (WHEN_KEY.equalsIgnoreCase(paramname)) {
|
---|
171 | SizeComparisons scmp = new SizeComparisons();
|
---|
172 | scmp.setValue(parameters[i].getValue());
|
---|
173 | setWhen(scmp);
|
---|
174 | } else {
|
---|
175 | setError("Invalid parameter " + paramname);
|
---|
176 | }
|
---|
177 | }
|
---|
178 | }
|
---|
179 | }
|
---|
180 |
|
---|
181 | /**
|
---|
182 | * <p>Checks to make sure all settings are kosher. In this case, it
|
---|
183 | * means that the size attribute has been set (to a positive value),
|
---|
184 | * that the multiplier has a valid setting, and that the size limit
|
---|
185 | * is valid. Since the latter is a calculated value, this can only
|
---|
186 | * fail due to a programming error.
|
---|
187 | * </p>
|
---|
188 | * <p>If a problem is detected, the setError() method is called.
|
---|
189 | * </p>
|
---|
190 | */
|
---|
191 | public void verifySettings() {
|
---|
192 | if (size < 0) {
|
---|
193 | setError("The value attribute is required, and must be positive");
|
---|
194 | } else if (multiplier < 1) {
|
---|
195 | setError("Invalid Units supplied, must be K,Ki,M,Mi,G,Gi,T,or Ti");
|
---|
196 | } else if (sizelimit < 0) {
|
---|
197 | setError("Internal error: Code is not setting sizelimit correctly");
|
---|
198 | }
|
---|
199 | }
|
---|
200 |
|
---|
201 | /**
|
---|
202 | * The heart of the matter. This is where the selector gets to decide
|
---|
203 | * on the inclusion of a file in a particular fileset.
|
---|
204 | *
|
---|
205 | * @param basedir A java.io.File object for the base directory.
|
---|
206 | * @param filename The name of the file to check.
|
---|
207 | * @param file A File object for this filename.
|
---|
208 | * @return whether the file should be selected or not.
|
---|
209 | */
|
---|
210 | public boolean isSelected(File basedir, String filename, File file) {
|
---|
211 |
|
---|
212 | // throw BuildException on error
|
---|
213 | validate();
|
---|
214 |
|
---|
215 | // Directory size never selected for
|
---|
216 | if (file.isDirectory()) {
|
---|
217 | return true;
|
---|
218 | }
|
---|
219 | if (cmp == 0) {
|
---|
220 | return (file.length() < sizelimit);
|
---|
221 | } else if (cmp == 1) {
|
---|
222 | return (file.length() > sizelimit);
|
---|
223 | } else {
|
---|
224 | return (file.length() == sizelimit);
|
---|
225 | }
|
---|
226 | }
|
---|
227 |
|
---|
228 |
|
---|
229 | /**
|
---|
230 | * Enumerated attribute with the values for units.
|
---|
231 | * <p>
|
---|
232 | * This treats the standard SI units as representing powers of ten,
|
---|
233 | * as they should. If you want the powers of 2 that approximate
|
---|
234 | * the SI units, use the first two characters followed by a
|
---|
235 | * <code>bi</code>. So 1024 (2^10) becomes <code>kibi</code>,
|
---|
236 | * 1048576 (2^20) becomes <code>mebi</code>, 1073741824 (2^30)
|
---|
237 | * becomes <code>gibi</code>, and so on. The symbols are also
|
---|
238 | * accepted, and these are the first letter capitalized followed
|
---|
239 | * by an <code>i</code>. <code>Ki</code>, <code>Mi</code>,
|
---|
240 | * <code>Gi</code>, and so on. Capitalization variations on these
|
---|
241 | * are also accepted.
|
---|
242 | * <p>
|
---|
243 | * This binary prefix system is approved by the IEC and appears on
|
---|
244 | * its way for approval by other agencies, but it is not an SI
|
---|
245 | * standard. It disambiguates things for us, though.
|
---|
246 | */
|
---|
247 | public static class ByteUnits extends EnumeratedAttribute {
|
---|
248 | /**
|
---|
249 | * @return the values as an array of strings
|
---|
250 | */
|
---|
251 | public String[] getValues() {
|
---|
252 | return new String[]{"K", "k", "kilo", "KILO",
|
---|
253 | "Ki", "KI", "ki", "kibi", "KIBI",
|
---|
254 | "M", "m", "mega", "MEGA",
|
---|
255 | "Mi", "MI", "mi", "mebi", "MEBI",
|
---|
256 | "G", "g", "giga", "GIGA",
|
---|
257 | "Gi", "GI", "gi", "gibi", "GIBI",
|
---|
258 | "T", "t", "tera", "TERA",
|
---|
259 | /* You wish! */ "Ti", "TI", "ti", "tebi", "TEBI"
|
---|
260 | };
|
---|
261 | }
|
---|
262 | }
|
---|
263 |
|
---|
264 | /**
|
---|
265 | * Enumerated attribute with the values for size comparison.
|
---|
266 | */
|
---|
267 | public static class SizeComparisons extends EnumeratedAttribute {
|
---|
268 | /**
|
---|
269 | * @return the values as an array of strings
|
---|
270 | */
|
---|
271 | public String[] getValues() {
|
---|
272 | return new String[]{"less", "more", "equal"};
|
---|
273 | }
|
---|
274 | }
|
---|
275 |
|
---|
276 | }
|
---|
277 |
|
---|