001: /* ====================================================================
002: Licensed to the Apache Software Foundation (ASF) under one or more
003: contributor license agreements. See the NOTICE file distributed with
004: this work for additional information regarding copyright ownership.
005: The ASF licenses this file to You under the Apache License, Version 2.0
006: (the "License"); you may not use this file except in compliance with
007: the License. You may obtain a copy of the License at
008:
009: http://www.apache.org/licenses/LICENSE-2.0
010:
011: Unless required by applicable law or agreed to in writing, software
012: distributed under the License is distributed on an "AS IS" BASIS,
013: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: See the License for the specific language governing permissions and
015: limitations under the License.
016: ==================================================================== */
017:
018: package org.apache.poi.hpsf;
019:
020: import java.io.IOException;
021: import java.io.PrintWriter;
022: import java.io.StringWriter;
023: import java.util.Collection;
024: import java.util.Date;
025:
026: /**
027: * <p>Provides various static utility methods.</p>
028: *
029: * @author Rainer Klute (klute@rainer-klute.de)
030: * @version $Id: Util.java 550886 2007-06-26 17:58:28Z klute $
031: * @since 2002-02-09
032: */
033: public class Util {
034:
035: /**
036: * <p>Checks whether two byte arrays <var>a</var> and <var>b</var>
037: * are equal. They are equal</p>
038: *
039: * <ul>
040: *
041: * <li><p>if they have the same length and</p></li>
042: *
043: * <li><p>if for each <var>i</var> with
044: * <var>i</var> >= 0 and
045: * <var>i</var> < <var>a.length</var> holds
046: * <var>a</var>[<var>i</var>] == <var>b</var>[<var>i</var>].</p></li>
047: *
048: * </ul>
049: *
050: * @param a The first byte array
051: * @param b The first byte array
052: * @return <code>true</code> if the byte arrays are equal, else
053: * <code>false</code>
054: */
055: public static boolean equal(final byte[] a, final byte[] b) {
056: if (a.length != b.length)
057: return false;
058: for (int i = 0; i < a.length; i++)
059: if (a[i] != b[i])
060: return false;
061: return true;
062: }
063:
064: /**
065: * <p>Copies a part of a byte array into another byte array.</p>
066: *
067: * @param src The source byte array.
068: * @param srcOffset Offset in the source byte array.
069: * @param length The number of bytes to copy.
070: * @param dst The destination byte array.
071: * @param dstOffset Offset in the destination byte array.
072: */
073: public static void copy(final byte[] src, final int srcOffset,
074: final int length, final byte[] dst, final int dstOffset) {
075: for (int i = 0; i < length; i++)
076: dst[dstOffset + i] = src[srcOffset + i];
077: }
078:
079: /**
080: * <p>Concatenates the contents of several byte arrays into a
081: * single one.</p>
082: *
083: * @param byteArrays The byte arrays to be concatened.
084: * @return A new byte array containing the concatenated byte
085: * arrays.
086: */
087: public static byte[] cat(final byte[][] byteArrays) {
088: int capacity = 0;
089: for (int i = 0; i < byteArrays.length; i++)
090: capacity += byteArrays[i].length;
091: final byte[] result = new byte[capacity];
092: int r = 0;
093: for (int i = 0; i < byteArrays.length; i++)
094: for (int j = 0; j < byteArrays[i].length; j++)
095: result[r++] = byteArrays[i][j];
096: return result;
097: }
098:
099: /**
100: * <p>Copies bytes from a source byte array into a new byte
101: * array.</p>
102: *
103: * @param src Copy from this byte array.
104: * @param offset Start copying here.
105: * @param length Copy this many bytes.
106: * @return The new byte array. Its length is number of copied bytes.
107: */
108: public static byte[] copy(final byte[] src, final int offset,
109: final int length) {
110: final byte[] result = new byte[length];
111: copy(src, offset, length, result, 0);
112: return result;
113: }
114:
115: /**
116: * <p>The difference between the Windows epoch (1601-01-01
117: * 00:00:00) and the Unix epoch (1970-01-01 00:00:00) in
118: * milliseconds: 11644473600000L. (Use your favorite spreadsheet
119: * program to verify the correctness of this value. By the way,
120: * did you notice that you can tell from the epochs which
121: * operating system is the modern one? :-))</p>
122: */
123: public static final long EPOCH_DIFF = 11644473600000L;
124:
125: /**
126: * <p>Converts a Windows FILETIME into a {@link Date}. The Windows
127: * FILETIME structure holds a date and time associated with a
128: * file. The structure identifies a 64-bit integer specifying the
129: * number of 100-nanosecond intervals which have passed since
130: * January 1, 1601. This 64-bit value is split into the two double
131: * words stored in the structure.</p>
132: *
133: * @param high The higher double word of the FILETIME structure.
134: * @param low The lower double word of the FILETIME structure.
135: * @return The Windows FILETIME as a {@link Date}.
136: */
137: public static Date filetimeToDate(final int high, final int low) {
138: final long filetime = ((long) high) << 32 | (low & 0xffffffffL);
139: return filetimeToDate(filetime);
140: }
141:
142: /**
143: * <p>Converts a Windows FILETIME into a {@link Date}. The Windows
144: * FILETIME structure holds a date and time associated with a
145: * file. The structure identifies a 64-bit integer specifying the
146: * number of 100-nanosecond intervals which have passed since
147: * January 1, 1601.</p>
148: *
149: * @param filetime The filetime to convert.
150: * @return The Windows FILETIME as a {@link Date}.
151: */
152: public static Date filetimeToDate(final long filetime) {
153: final long ms_since_16010101 = filetime / (1000 * 10);
154: final long ms_since_19700101 = ms_since_16010101 - EPOCH_DIFF;
155: return new Date(ms_since_19700101);
156: }
157:
158: /**
159: * <p>Converts a {@link Date} into a filetime.</p>
160: *
161: * @param date The date to be converted
162: * @return The filetime
163: *
164: * @see #filetimeToDate(long)
165: * @see #filetimeToDate(int, int)
166: */
167: public static long dateToFileTime(final Date date) {
168: long ms_since_19700101 = date.getTime();
169: long ms_since_16010101 = ms_since_19700101 + EPOCH_DIFF;
170: return ms_since_16010101 * (1000 * 10);
171: }
172:
173: /**
174: * <p>Checks whether two collections are equal. Two collections
175: * C<sub>1</sub> and C<sub>2</sub> are equal, if the following conditions
176: * are true:</p>
177: *
178: * <ul>
179: *
180: * <li><p>For each c<sub>1<em>i</em></sub> (element of C<sub>1</sub>) there
181: * is a c<sub>2<em>j</em></sub> (element of C<sub>2</sub>), and
182: * c<sub>1<em>i</em></sub> equals c<sub>2<em>j</em></sub>.</p></li>
183: *
184: * <li><p>For each c<sub>2<em>i</em></sub> (element of C<sub>2</sub>) there
185: * is a c<sub>1<em>j</em></sub> (element of C<sub>1</sub>) and
186: * c<sub>2<em>i</em></sub> equals c<sub>1<em>j</em></sub>.</p></li>
187: *
188: * </ul>
189: *
190: * @param c1 the first collection
191: * @param c2 the second collection
192: * @return <code>true</code> if the collections are equal, else
193: * <code>false</code>.
194: */
195: public static boolean equals(final Collection c1,
196: final Collection c2) {
197: final Object[] o1 = c1.toArray();
198: final Object[] o2 = c2.toArray();
199: return internalEquals(o1, o2);
200: }
201:
202: /**
203: * <p>Compares to object arrays with regarding the objects' order. For
204: * example, [1, 2, 3] and [2, 1, 3] are equal.</p>
205: *
206: * @param c1 The first object array.
207: * @param c2 The second object array.
208: * @return <code>true</code> if the object arrays are equal,
209: * <code>false</code> if they are not.
210: */
211: public static boolean equals(final Object[] c1, final Object[] c2) {
212: final Object[] o1 = (Object[]) c1.clone();
213: final Object[] o2 = (Object[]) c2.clone();
214: return internalEquals(o1, o2);
215: }
216:
217: private static boolean internalEquals(final Object[] o1,
218: final Object[] o2) {
219: for (int i1 = 0; i1 < o1.length; i1++) {
220: final Object obj1 = o1[i1];
221: boolean matchFound = false;
222: for (int i2 = 0; !matchFound && i2 < o1.length; i2++) {
223: final Object obj2 = o2[i2];
224: if (obj1.equals(obj2)) {
225: matchFound = true;
226: o2[i2] = null;
227: }
228: }
229: if (!matchFound)
230: return false;
231: }
232: return true;
233: }
234:
235: /**
236: * <p>Pads a byte array with 0x00 bytes so that its length is a multiple of
237: * 4.</p>
238: *
239: * @param ba The byte array to pad.
240: * @return The padded byte array.
241: */
242: public static byte[] pad4(final byte[] ba) {
243: final int PAD = 4;
244: final byte[] result;
245: int l = ba.length % PAD;
246: if (l == 0)
247: result = ba;
248: else {
249: l = PAD - l;
250: result = new byte[ba.length + l];
251: System.arraycopy(ba, 0, result, 0, ba.length);
252: }
253: return result;
254: }
255:
256: /**
257: * <p>Pads a character array with 0x0000 characters so that its length is a
258: * multiple of 4.</p>
259: *
260: * @param ca The character array to pad.
261: * @return The padded character array.
262: */
263: public static char[] pad4(final char[] ca) {
264: final int PAD = 4;
265: final char[] result;
266: int l = ca.length % PAD;
267: if (l == 0)
268: result = ca;
269: else {
270: l = PAD - l;
271: result = new char[ca.length + l];
272: System.arraycopy(ca, 0, result, 0, ca.length);
273: }
274: return result;
275: }
276:
277: /**
278: * <p>Pads a string with 0x0000 characters so that its length is a
279: * multiple of 4.</p>
280: *
281: * @param s The string to pad.
282: * @return The padded string as a character array.
283: */
284: public static char[] pad4(final String s) {
285: return pad4(s.toCharArray());
286: }
287:
288: /**
289: * <p>Returns a textual representation of a {@link Throwable}, including a
290: * stacktrace.</p>
291: *
292: * @param t The {@link Throwable}
293: *
294: * @return a string containing the output of a call to
295: * <code>t.printStacktrace()</code>.
296: */
297: public static String toString(final Throwable t) {
298: final StringWriter sw = new StringWriter();
299: final PrintWriter pw = new PrintWriter(sw);
300: t.printStackTrace(pw);
301: pw.close();
302: try {
303: sw.close();
304: return sw.toString();
305: } catch (IOException e) {
306: final StringBuffer b = new StringBuffer(t.getMessage());
307: b.append("\n");
308: b.append("Could not create a stacktrace. Reason: ");
309: b.append(e.getMessage());
310: return b.toString();
311: }
312: }
313:
314: }
|