001: /*
002: * Copyright (c) xsocket.org, 2006 - 2008. All rights reserved.
003: *
004: * This library is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License as published by the Free Software Foundation; either
007: * version 2.1 of the License, or (at your option) any later version.
008: *
009: * This library is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public
015: * License along with this library; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: *
018: * Please refer to the LGPL license at: http://www.gnu.org/copyleft/lesser.txt
019: * The latest copy of this software may be found on http://www.xsocket.org/
020: */
021: package org.xsocket;
022:
023: import java.io.UnsupportedEncodingException;
024: import java.nio.ByteBuffer;
025: import java.nio.charset.CharacterCodingException;
026: import java.nio.charset.Charset;
027: import java.nio.charset.CharsetDecoder;
028: import java.nio.charset.CharsetEncoder;
029: import java.text.SimpleDateFormat;
030: import java.util.ArrayList;
031: import java.util.Date;
032: import java.util.HashMap;
033: import java.util.List;
034: import java.util.Map;
035:
036: /**
037: * a data converter utilities class
038: *
039: * @author grro@xsocket.org
040: */
041: public final class DataConverter {
042:
043: private static final Map<String, CharsetEncoder> encoders = new HashMap<String, CharsetEncoder>();
044: private static final Map<String, CharsetDecoder> decoders = new HashMap<String, CharsetDecoder>();
045:
046: /**
047: * converts a unsigned long to a integer by considering the overflow
048: *
049: * @param l the long value
050: * @return the int value
051: */
052: public static int unsignedLongToInt(Long l) {
053: if (l <= 0) {
054: return 0;
055:
056: } else {
057: int sec = (int) (l * 1000);
058:
059: // overflow?
060: if (sec <= 0) {
061: return Integer.MAX_VALUE;
062:
063: } else {
064: return sec;
065: }
066: }
067: }
068:
069: /**
070: * converts a unsigned int to a long by considering the overflow
071: *
072: * @param i the integer value
073: * @return the long value
074: */
075: public static long unsignedIntToLong(int i) {
076: if (i <= 0) {
077: return 0;
078: } else {
079: return ((long) i) * 1000;
080: }
081: }
082:
083: /**
084: * converts the given byte size in a textual representation
085: *
086: * @param bytes the bytes to convert
087: * @return the formated String representation of the bytes
088: */
089: public static String toFormatedBytesSize(long bytes) {
090: if (bytes > (5 * 1000 * 1000)) {
091: return (bytes / 1000000) + " mb";
092:
093: } else if (bytes > (10 * 1000)) {
094: return (bytes / 1000) + " kb";
095:
096: } else {
097: return bytes + " bytes";
098: }
099: }
100:
101: /**
102: * converts the given time in a textual representation
103: *
104: * @param time the time to convert
105: * @return the formated String representation of the date
106: */
107: public static String toFormatedDate(long time) {
108: return new SimpleDateFormat("MMM.dd HH:mm").format(new Date(
109: time));
110: }
111:
112: /**
113: * converts the given duration in a textual representation
114: *
115: * @param duration the duration to convert
116: * @return the formated String representation of the duration
117: */
118: public static String toFormatedDuration(long duration) {
119:
120: if (duration < 5 * 1000) {
121: return duration + " millis";
122:
123: } else if (duration < (60 * 1000)) {
124: return ((int) (duration / 1000)) + " sec";
125:
126: } else if (duration < (60 * 60 * 1000)) {
127: return ((int) (duration / (60 * 1000))) + " min";
128: } else {
129: return ((int) (duration / (60 * 60 * 1000))) + " h";
130: }
131: }
132:
133: /**
134: * converts the given String into a ByteBuffer
135: *
136: * @param s the String to convert
137: * @param encoding the encoding to use
138: * @return the String as ByteBuffer
139: */
140: public static ByteBuffer toByteBuffer(String s, String encoding) {
141: try {
142: return ByteBuffer.wrap(s.getBytes(encoding));
143: } catch (UnsupportedEncodingException uee) {
144: throw new RuntimeException(uee);
145: }
146: }
147:
148: /**
149: * converts the given ByteBuffer into String by using
150: * UTF-8 encoding
151: *
152: * @param buffer the ByteBuffer to convert
153: * @return the ByteByuffer as String
154: */
155: public static String toString(ByteBuffer buffer)
156: throws UnsupportedEncodingException {
157: return toString(buffer, "UTF-8");
158: }
159:
160: /**
161: * converts the given ByteBuffer array into String by using
162: * UTF-8 encoding
163: *
164: * @param buffer the ByteBuffer arrayto convert
165: * @return the ByteByuffer as String
166: */
167: public static String toString(ByteBuffer[] buffer)
168: throws UnsupportedEncodingException {
169: return toString(buffer, "UTF-8");
170: }
171:
172: /**
173: * converts the given ByteBuffer into String repesentation
174: *
175: * @param buffer the ByteBuffer to convert
176: * @param encoding the encoding to use
177: * @return the ByteByuffer as String
178: */
179: public static String toString(ByteBuffer buffer, String encoding)
180: throws UnsupportedEncodingException {
181: try {
182: CharsetDecoder decoder = decoders.get(encoding);
183: if (decoder == null) {
184: Charset charset = Charset.forName(encoding);
185: if (charset != null) {
186: decoder = charset.newDecoder();
187: decoders.put(encoding, decoder);
188: encoders.put(encoding, charset.newEncoder());
189: } else {
190: throw new UnsupportedEncodingException("charset `"
191: + encoding + "` has not been found");
192: }
193: }
194:
195: return decoder.decode(buffer).toString();
196:
197: } catch (CharacterCodingException cce) {
198: RuntimeException re = new RuntimeException(
199: "coding exception for `" + encoding + "` occured: "
200: + cce.toString(), cce);
201: throw re;
202: }
203: }
204:
205: /**
206: * converts the given ByteBuffer into a hex string
207: *
208: * @param buffer the ByteBuffer to convert
209: * @return the hex string
210: */
211: public static String toHexString(ByteBuffer buffer) {
212:
213: if (buffer == null) {
214: return "";
215: }
216:
217: StringBuilder sb = new StringBuilder();
218:
219: while (buffer.hasRemaining()) {
220: String hex = Integer.toHexString(
221: 0x0100 + (buffer.get() & 0x00FF)).substring(1);
222: sb.append((hex.length() < 2 ? "0" : "") + hex + " ");
223: }
224:
225: return sb.toString();
226: }
227:
228: /**
229: * converts the given list of ByteBuffers into a String by using UTF-8 encoding
230: *
231: * @param buffers the list of ByteBuffer to convert
232: * @return the ByteByuffer as String
233: */
234: public static String toString(List<ByteBuffer> buffers)
235: throws UnsupportedEncodingException {
236: return toString(
237: buffers.toArray(new ByteBuffer[buffers.size()]),
238: "UTF-8");
239: }
240:
241: /**
242: * converts the given list of ByteBuffers into a String
243: *
244: * @param buffers the list of ByteBuffer to convert
245: * @param encoding the encoding to use
246: * @return the ByteByuffer as String
247: */
248: public static String toString(List<ByteBuffer> buffers,
249: String encoding) throws UnsupportedEncodingException {
250: return toString(
251: buffers.toArray(new ByteBuffer[buffers.size()]),
252: encoding);
253: }
254:
255: /**
256: * converts the given array of ByteBuffers into String
257: *
258: * @param buffers the array of ByteBuffer to convert
259: * @param encoding the encoding to use
260: * @return the ByteByuffer as String
261: */
262: public static String toString(ByteBuffer[] buffers, String encoding)
263: throws UnsupportedEncodingException {
264: byte[] bytes = toBytes(buffers);
265: if (bytes != null) {
266: return new String(bytes, encoding);
267: } else {
268: return "";
269: }
270: }
271:
272: /**
273: * print the bytebuffer as limited string
274: *
275: * @param buffers the buffers to print
276: * @param encoding the encoding to use
277: * @param maxOutSize the max size to print
278: *
279: * @return the ByteBuffers as string representation
280: */
281: public static String toString(ByteBuffer[] buffers,
282: String encoding, int maxOutSize)
283: throws UnsupportedEncodingException {
284: String s = toString(buffers, encoding);
285: if (s.length() > maxOutSize) {
286: s = s.substring(0, maxOutSize) + " [output has been cut]";
287: }
288: return s;
289: }
290:
291: /**
292: * merges a ByteBuffer array into a (direct) ByteBuffer
293: *
294: * @param buffers the ByteBuffer array to merge
295: * @return the single ByteBuffer
296: */
297: public static ByteBuffer toByteBuffer(ByteBuffer[] buffers) {
298: byte[] bytes = toBytes(buffers);
299: return ByteBuffer.wrap(bytes);
300: }
301:
302: /**
303: * converts a single byte to a byte buffer
304: *
305: * @param b the byte
306: * @return the ByteBuffer which contains the single byte
307: */
308: public static ByteBuffer toByteBuffer(byte b) {
309: ByteBuffer buffer = ByteBuffer.allocate(1).put(b);
310: buffer.flip();
311:
312: return buffer;
313: }
314:
315: /**
316: * converts a byte array to a byte buffer
317: *
318: * @param bytes the byte array
319: * @return the ByteBuffer which contains the bytes
320: */
321: public static ByteBuffer toByteBuffer(byte[] bytes) {
322: return ByteBuffer.wrap(bytes);
323: }
324:
325: /**
326: * converts a byte array to a byte buffer
327: *
328: * @param bytes the bytes
329: * @param offset the offset
330: * @param length the length
331: * @return the ByteBuffer which contains the single byte
332: */
333: public static ByteBuffer toByteBuffer(byte[] bytes, int offset,
334: int length) {
335: return ByteBuffer.wrap(bytes, offset, length);
336: }
337:
338: /**
339: * converts a double to a byte buffer
340: *
341: * @param d the double
342: * @return the ByteBuffer which contains the double
343: */
344: public static ByteBuffer toByteBuffer(double d) {
345: ByteBuffer buffer = ByteBuffer.allocate(8).putDouble(d);
346: buffer.flip();
347:
348: return buffer;
349: }
350:
351: /**
352: * converts a long to a byte buffer
353: *
354: * @param l the long
355: * @return the ByteBuffer which contains the long
356: */
357: public static ByteBuffer toByteBuffer(long l) {
358: ByteBuffer buffer = ByteBuffer.allocate(8).putLong(l);
359: buffer.flip();
360:
361: return buffer;
362: }
363:
364: /**
365: * converts a short to a byte buffer
366: *
367: * @param s the short
368: * @return the ByteBuffer which contains the short
369: */
370: public static ByteBuffer toByteBuffer(short s) {
371: ByteBuffer buffer = ByteBuffer.allocate(2).putShort(s);
372: buffer.flip();
373:
374: return buffer;
375: }
376:
377: /**
378: * converts a integer to a byte buffer
379: *
380: * @param i the int
381: * @return the ByteBuffer which contains the int
382: */
383: public static ByteBuffer toByteBuffer(int i) {
384: ByteBuffer buffer = ByteBuffer.allocate(4).putInt(i);
385: buffer.flip();
386:
387: return buffer;
388: }
389:
390: /**
391: * copies a array of ByteBuffer based on offset length to a byte buffer array
392: *
393: * @param srcs the buffers
394: * @param offset the offset
395: * @param length the length
396: * @return the ByteBuffer
397: */
398: public static ByteBuffer[] toByteBuffers(ByteBuffer[] srcs,
399: int offset, int length) {
400: ByteBuffer[] bufs = new ByteBuffer[length];
401: System.arraycopy(srcs, offset, bufs, 0, length);
402:
403: return bufs;
404: }
405:
406: /**
407: * converts a list of ByteBuffer to a byte array
408: *
409: * @param buffers the ByteBuffer list to convert
410: * @return the byte array
411: */
412: public static byte[] toBytes(List<ByteBuffer> buffers) {
413: return toBytes(buffers.toArray(new ByteBuffer[buffers.size()]));
414: }
415:
416: /**
417: * converts a ByteBuffer array to a byte array
418: *
419: * @param buffers the ByteBuffer array to convert
420: * @return the byte array
421: */
422: public static byte[] toBytes(ByteBuffer[] buffers) {
423: byte[] result = null;
424:
425: if (buffers == null) {
426: return null;
427: }
428:
429: if (buffers.length == 0) {
430: return new byte[0];
431: }
432:
433: int size = 0;
434: for (int i = 0; i < buffers.length; i++) {
435: if (buffers[i] == null) {
436: continue;
437: }
438:
439: size += buffers[i].remaining();
440: if (result == null) {
441: byte[] bytes = toBytes(buffers[i]);
442: if (bytes.length > 0) {
443: result = bytes;
444: }
445: } else {
446: byte[] additionalBytes = toBytes(buffers[i]);
447: byte[] newResult = new byte[result.length
448: + additionalBytes.length];
449: System
450: .arraycopy(result, 0, newResult, 0,
451: result.length);
452: System.arraycopy(additionalBytes, 0, newResult,
453: result.length, additionalBytes.length);
454: result = newResult;
455: }
456: }
457:
458: return result;
459: }
460:
461: /**
462: * converts a ByteBuffer into a byte array
463: *
464: * @param buffer the ByteBuffer to convert
465: * @return the byte array
466: */
467: public static byte[] toBytes(ByteBuffer buffer) {
468: if (buffer == null) {
469: return new byte[0];
470: }
471:
472: int savedPos = buffer.position();
473: int savedLimit = buffer.limit();
474:
475: try {
476:
477: byte[] array = new byte[buffer.limit() - buffer.position()];
478:
479: if (buffer.hasArray()) {
480: int offset = buffer.arrayOffset();
481: byte[] bufferArray = buffer.array();
482: System.arraycopy(bufferArray, offset, array, 0,
483: array.length);
484:
485: return array;
486: } else {
487: buffer.get(array);
488: return array;
489: }
490:
491: } finally {
492: buffer.position(savedPos);
493: buffer.limit(savedLimit);
494: }
495: }
496:
497: /**
498: * print the byte array as a hex string
499: *
500: * @param buffers the buffers to print
501: * @param maxOutSize the max size to print
502: *
503: * @return the ByteBuffers as hex representation
504: */
505: public static String toHexString(byte[] buffers, int maxOutSize) {
506: return toHexString(
507: new ByteBuffer[] { ByteBuffer.wrap(buffers) },
508: maxOutSize);
509: }
510:
511: /**
512: * print the byte buffer as a hex string
513: *
514: * @param buffers the buffers to print
515: * @param maxOutSize the max size to print
516: *
517: * @return the ByteBuffers as hex representation
518: */
519: public static String toHexString(List<ByteBuffer> buffers,
520: int maxOutSize) {
521: return toHexString(buffers.toArray(new ByteBuffer[buffers
522: .size()]), maxOutSize);
523: }
524:
525: /**
526: * print the byte buffer as a hex string
527: *
528: * @param buffers the buffers to print
529: * @param maxOutSize the max size to print
530: *
531: * @return the ByteBuffers as hex representation
532: */
533: public static String toHexString(ByteBuffer[] buffers,
534: int maxOutSize) {
535:
536: // first cut output if longer than max limit
537: String postfix = "";
538: int size = 0;
539: List<ByteBuffer> copies = new ArrayList<ByteBuffer>();
540: for (ByteBuffer buffer : buffers) {
541: if (buffer != null) {
542: ByteBuffer copy = buffer.duplicate();
543: if ((size + copy.limit()) > maxOutSize) {
544: copy.limit(maxOutSize - size);
545: copies.add(copy);
546: postfix = " [...output has been cut]";
547: break;
548: } else {
549: copies.add(copy);
550: }
551: }
552: }
553:
554: StringBuilder result = new StringBuilder();
555:
556: for (ByteBuffer buffer : copies) {
557: result.append(toHexString(buffer));
558: }
559:
560: result.append(postfix);
561:
562: return result.toString();
563: }
564:
565: /**
566: * convert the ByteBuffer into a hex or text string (deping on content)
567: *
568: * @param buffer the buffers to print
569: * @param maxOutSize the max size to print
570: * @param encoding the encoding to use
571: * @return the converted ByteBuffer
572: */
573: public static String toTextOrHexString(ByteBuffer buffer,
574: String encoding, int maxOutSize) {
575: return toTextOrHexString(new ByteBuffer[] { buffer }, encoding,
576: maxOutSize);
577: }
578:
579: /**
580: * convert the ByteBuffer array into a hex or text string (deping on content)
581: *
582: * @param buffers the buffers to print
583: * @param maxOutSize the max size to print
584: * @param encoding the encoding to use
585: * @return the converted ByteBuffer
586: */
587: public static String toTextOrHexString(ByteBuffer[] buffers,
588: String encoding, int maxOutSize) {
589: boolean hasNonPrintableChars = false;
590:
591: for (ByteBuffer buffer : buffers) {
592: ByteBuffer copy = buffer.duplicate();
593: while (copy.hasRemaining()) {
594: int i = copy.get();
595: if (i < 10) {
596: hasNonPrintableChars = true;
597: }
598: }
599: }
600:
601: if (hasNonPrintableChars) {
602: return toHexString(buffers, maxOutSize);
603: } else {
604: try {
605: return toString(buffers, encoding, maxOutSize);
606: } catch (UnsupportedEncodingException use) {
607: return toHexString(buffers, maxOutSize);
608: }
609: }
610: }
611:
612: public static String toTextAndHexString(ByteBuffer[] buffers,
613: String encoding, int maxOutSize) {
614: StringBuilder sb = new StringBuilder();
615: sb.append(DataConverter.toHexString(buffers, 500));
616: sb.append("\n");
617: try {
618: sb.append("[txt:] " + toString(buffers, "US-ASCII", 500));
619: } catch (Exception ignore) {
620: sb.append("[txt:] ... content not printable ...");
621: }
622: return sb.toString();
623: }
624: }
|