/**** UrlHexDump.java ****/ package urlhexdump; import java.net.*; import java.io.*; import java.awt.*; import java.awt.event.*; public class UrlHexDump implements Serializable { private static final String BAD_URL_MSG = "Can't open URL."; private static final String SEPARATOR_STR = "\n"; private static final int SEG_SIZE = 16; // // instance variables ... // // formatSegment() requires some value for this variable. // Depending on how use use it, you must decide how to // initialize it here, for example, as "\n" (for use in // TextArea instances) or the system property that reflects // the current environment's newline sequence // private String separatorStr = SEPARATOR_STR; // // The next three variables are required for stream processing. // Also, 'eof' and 'offset' are instance-level because the // participate in the 'toString()' functionality. // private boolean eof; private int offset; private int segment[] = new int[SEG_SIZE]; public UrlHexDump() { } public UrlHexDump(String urlStr) { this.urlStr = urlStr; openUrl(); } public static void main(String args[]) { if (usageOnly(args)) System.exit(0); UrlHexDump url = new UrlHexDump(args[0]); if (url == null) System.exit(-1); // System.out.println(url.retrieveUrlContent()); url.retrieveUrlContentGraphicalApplication(); } private static boolean usageOnly(String args[]) { if (args.length == 0 || args.length > 1 || ((args.length == 1) && (args[0].equalsIgnoreCase("-usage") || args[0].equalsIgnoreCase("-help") || args[0].equalsIgnoreCase("-h")))) { System.out.println(""); System.out.println( "UrlHexDump opens a URL as an input stream and dumps an ASCII"); System.out.println( "interpretation of the data stream to standard output."); System.out.println(""); System.out.println("Usage: java UrlHexDump "); System.out.println(""); return true; } else return false; } private void openUrl() { url = null; // // attempt to establish a URL connection ... // } private void handleMessage(String msg, Exception e) { if (debug) { System.out.println(msg); System.out.println(e); } message = msg; } // // retrieveUrlContent() opens a data stream to the URL, reads fixed- // size data segments, and returns the result. // synchronized public String retrieveUrlContent() { if (url == null) { openUrl(); if (url == null) return BAD_URL_MSG; } DataInputStream in = null; /// // other initializations ... /// eof = false; offset = 0; try { in = new DataInputStream(url.openStream()); try { while (!eof) { readSegment(in); /* collect content ... */ = formatSegment(); } } catch (Exception e) { handleMessage("retrieveUrlContent: unknown general exception.", e); } } catch (Exception e) { handleMessage( "retrieveUrlContent: general exception opening data stream.", e); } return /* the collected content */; } public String toString() { return "[" + "URL string = " + urlStr + ", eof = " + eof + ", offset = " + offset + "]"; } //////////////////////////////////////////////////////////////////////// // Private, you-don't-want-to-know stuff follows //////////////////////////////////////////////////////////////////////// // // readSegment() reads the data stream as unsigned bytes. This strategy // is NOT 100-percent reliable, because servers don't always close the // connection. // private void readSegment(DataInputStream in) { int i = 0; try { for ( ; i < SEG_SIZE; i++) segment[i] = in.readUnsignedByte(); } catch (EOFException e) { eof = true; for (int j = i; i < SEG_SIZE; i++) segment[i] = 0; } catch (IOException e) { handleMessage("I/O error reading from URL: " + urlStr, e); } } // // formatSegment() builds each fixed segment of the data stream, // one per line, e.g.: // // 00000 54 68 ... 73 20--74 65 ... 30 31 |This is -text..01| // 00010 32 33 ... 38 39--0a 01 ... 64 0a |23456789-....end.| // 00020 00 00 ... 00 00--00 00 ... 00 00 |........-........| // private String formatSegment() { int i; String str = ""; // // build the offset in the data stream: // str += rightJustify(Integer.toHexString(offset * 16), 5) + " "; // // build the data as hex values: // for (i = 0; i < (SEG_SIZE / 2) - 1; i++) str += rightJustify(Integer.toHexString(segment[i]), 2) + " "; str += rightJustify(Integer.toHexString(segment[i++]), 2); str += "--"; for ( ; i < SEG_SIZE; i++) str += rightJustify(Integer.toHexString(segment[i]), 2) + " "; // // build the data as a (forced) ASCII interpretation: // str += " |"; for (i = 0; i < (SEG_SIZE / 2); i++) { char c = (char) segment[i]; if (!isPrintableAscii(c)) c = '.'; str += c; } urlContent += "-"; for ( ; i < SEG_SIZE; i++) { char c = (char) segment[i]; if (!isPrintableAscii(c)) c = '.'; str += c; } str += "|" + separatorStr; offset++; return str; } private void printSegment() { System.out.print(formatSegment()); } // // isPrintableAscii() indicates the type of data NOT to print. // private boolean isPrintableAscii(char c) { return !(Character.isISOControl(c)); } // // rightJustify() right justifies hex data in a 0-padded field // of arbitrary size. // private String rightJustify(String str, int width) { for (int i = width - str.length(); i > 0; i--) str = "0" + str; return str; } }