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: /*
019: * BiffViewer.java
020: *
021: * Created on November 13, 2001, 9:23 AM
022: */
023: package org.apache.poi.hssf.dev;
024:
025: import org.apache.poi.hssf.record.*;
026: import org.apache.poi.poifs.filesystem.POIFSFileSystem;
027: import org.apache.poi.util.HexDump;
028:
029: import java.io.FileInputStream;
030: import java.io.IOException;
031: import java.io.InputStream;
032: import java.util.ArrayList;
033:
034: /**
035: * Utillity for reading in BIFF8 records and displaying data from them.
036: *
037: *@author Andrew C. Oliver (acoliver at apache dot org)
038: *@author Glen Stampoultzis (glens at apache.org)
039: *@see #main
040: */
041:
042: public class BiffViewer {
043: String filename;
044: private boolean dump;
045:
046: /**
047: * Creates new BiffViewer
048: *
049: *@param args
050: */
051:
052: public BiffViewer(String[] args) {
053: if (args.length > 0) {
054: filename = args[0];
055: } else {
056: System.out.println("BIFFVIEWER REQUIRES A FILENAME***");
057: }
058: }
059:
060: /**
061: * Method run starts up BiffViewer...
062: */
063:
064: public void run() {
065: try {
066: POIFSFileSystem fs = new POIFSFileSystem(
067: new FileInputStream(filename));
068: InputStream stream = fs
069: .createDocumentInputStream("Workbook");
070: createRecords(stream, dump);
071: } catch (Exception e) {
072: e.printStackTrace();
073: }
074: }
075:
076: /**
077: * Create an array of records from an input stream
078: *
079: *@param in the InputStream from which the records
080: * will be obtained
081: *@param dump
082: *@return an array of Records created from the
083: * InputStream
084: *@exception RecordFormatException on error processing the InputStream
085: */
086:
087: public static Record[] createRecords(InputStream in, boolean dump)
088: throws RecordFormatException {
089: ArrayList records = new ArrayList();
090: RecordDetails activeRecord = null;
091:
092: try {
093: BiffviewRecordInputStream recStream = new BiffviewRecordInputStream(
094: in);
095: while (recStream.hasNextRecord()) {
096: recStream.nextRecord();
097: if (recStream.getSid() != 0) {
098: Record record = createRecord(recStream);
099: if (record.getSid() != ContinueRecord.sid) {
100: records.add(record);
101: if (activeRecord != null)
102: activeRecord.dump();
103: activeRecord = new RecordDetails(recStream
104: .getSid(), recStream.getLength(),
105: (int) recStream.getPos(), record);
106: }
107: if (dump) {
108: recStream.dumpBytes();
109: }
110: }
111: }
112: activeRecord.dump();
113: } catch (IOException e) {
114: throw new RecordFormatException("Error reading bytes", e);
115: }
116: Record[] retval = new Record[records.size()];
117:
118: retval = (Record[]) records.toArray(retval);
119: return retval;
120: }
121:
122: private static void dumpNormal(Record record, int startloc,
123: short rectype, short recsize) {
124: System.out.println("Offset 0x" + Integer.toHexString(startloc)
125: + " (" + startloc + ")");
126: System.out.println("recordid = 0x"
127: + Integer.toHexString(rectype) + ", size = " + recsize);
128: System.out.println(record.toString());
129:
130: }
131:
132: /**
133: * Essentially a duplicate of RecordFactory. Kept seperate as not to screw
134: * up non-debug operations.
135: *
136: */
137: private static Record createRecord(RecordInputStream in) {
138: Record retval = null;
139:
140: switch (in.getSid()) {
141:
142: case ChartRecord.sid:
143: retval = new ChartRecord(in);
144: break;
145: case ChartFormatRecord.sid:
146: retval = new ChartFormatRecord(in);
147: break;
148: case SeriesRecord.sid:
149: retval = new SeriesRecord(in);
150: break;
151: case BeginRecord.sid:
152: retval = new BeginRecord(in);
153: break;
154: case EndRecord.sid:
155: retval = new EndRecord(in);
156: break;
157: case BOFRecord.sid:
158: retval = new BOFRecord(in);
159: break;
160: case InterfaceHdrRecord.sid:
161: retval = new InterfaceHdrRecord(in);
162: break;
163: case MMSRecord.sid:
164: retval = new MMSRecord(in);
165: break;
166: case InterfaceEndRecord.sid:
167: retval = new InterfaceEndRecord(in);
168: break;
169: case WriteAccessRecord.sid:
170: retval = new WriteAccessRecord(in);
171: break;
172: case CodepageRecord.sid:
173: retval = new CodepageRecord(in);
174: break;
175: case DSFRecord.sid:
176: retval = new DSFRecord(in);
177: break;
178: case TabIdRecord.sid:
179: retval = new TabIdRecord(in);
180: break;
181: case FnGroupCountRecord.sid:
182: retval = new FnGroupCountRecord(in);
183: break;
184: case WindowProtectRecord.sid:
185: retval = new WindowProtectRecord(in);
186: break;
187: case ProtectRecord.sid:
188: retval = new ProtectRecord(in);
189: break;
190: case PasswordRecord.sid:
191: retval = new PasswordRecord(in);
192: break;
193: case ProtectionRev4Record.sid:
194: retval = new ProtectionRev4Record(in);
195: break;
196: case PasswordRev4Record.sid:
197: retval = new PasswordRev4Record(in);
198: break;
199: case WindowOneRecord.sid:
200: retval = new WindowOneRecord(in);
201: break;
202: case BackupRecord.sid:
203: retval = new BackupRecord(in);
204: break;
205: case HideObjRecord.sid:
206: retval = new HideObjRecord(in);
207: break;
208: case DateWindow1904Record.sid:
209: retval = new DateWindow1904Record(in);
210: break;
211: case PrecisionRecord.sid:
212: retval = new PrecisionRecord(in);
213: break;
214: case RefreshAllRecord.sid:
215: retval = new RefreshAllRecord(in);
216: break;
217: case BookBoolRecord.sid:
218: retval = new BookBoolRecord(in);
219: break;
220: case FontRecord.sid:
221: retval = new FontRecord(in);
222: break;
223: case FormatRecord.sid:
224: retval = new FormatRecord(in);
225: break;
226: case ExtendedFormatRecord.sid:
227: retval = new ExtendedFormatRecord(in);
228: break;
229: case StyleRecord.sid:
230: retval = new StyleRecord(in);
231: break;
232: case UseSelFSRecord.sid:
233: retval = new UseSelFSRecord(in);
234: break;
235: case BoundSheetRecord.sid:
236: retval = new BoundSheetRecord(in);
237: break;
238: case CountryRecord.sid:
239: retval = new CountryRecord(in);
240: break;
241: case SSTRecord.sid:
242: retval = new SSTRecord(in);
243: break;
244: case ExtSSTRecord.sid:
245: retval = new ExtSSTRecord(in);
246: break;
247: case EOFRecord.sid:
248: retval = new EOFRecord(in);
249: break;
250: case IndexRecord.sid:
251: retval = new IndexRecord(in);
252: break;
253: case CalcModeRecord.sid:
254: retval = new CalcModeRecord(in);
255: break;
256: case CalcCountRecord.sid:
257: retval = new CalcCountRecord(in);
258: break;
259: case RefModeRecord.sid:
260: retval = new RefModeRecord(in);
261: break;
262: case IterationRecord.sid:
263: retval = new IterationRecord(in);
264: break;
265: case DeltaRecord.sid:
266: retval = new DeltaRecord(in);
267: break;
268: case SaveRecalcRecord.sid:
269: retval = new SaveRecalcRecord(in);
270: break;
271: case PrintHeadersRecord.sid:
272: retval = new PrintHeadersRecord(in);
273: break;
274: case PrintGridlinesRecord.sid:
275: retval = new PrintGridlinesRecord(in);
276: break;
277: case GridsetRecord.sid:
278: retval = new GridsetRecord(in);
279: break;
280: case DrawingGroupRecord.sid:
281: retval = new DrawingGroupRecord(in);
282: break;
283: case DrawingRecordForBiffViewer.sid:
284: retval = new DrawingRecordForBiffViewer(in);
285: break;
286: case DrawingSelectionRecord.sid:
287: retval = new DrawingSelectionRecord(in);
288: break;
289: case GutsRecord.sid:
290: retval = new GutsRecord(in);
291: break;
292: case DefaultRowHeightRecord.sid:
293: retval = new DefaultRowHeightRecord(in);
294: break;
295: case WSBoolRecord.sid:
296: retval = new WSBoolRecord(in);
297: break;
298: case HeaderRecord.sid:
299: retval = new HeaderRecord(in);
300: break;
301: case FooterRecord.sid:
302: retval = new FooterRecord(in);
303: break;
304: case HCenterRecord.sid:
305: retval = new HCenterRecord(in);
306: break;
307: case VCenterRecord.sid:
308: retval = new VCenterRecord(in);
309: break;
310: case PrintSetupRecord.sid:
311: retval = new PrintSetupRecord(in);
312: break;
313: case DefaultColWidthRecord.sid:
314: retval = new DefaultColWidthRecord(in);
315: break;
316: case DimensionsRecord.sid:
317: retval = new DimensionsRecord(in);
318: break;
319: case RowRecord.sid:
320: retval = new RowRecord(in);
321: break;
322: case LabelSSTRecord.sid:
323: retval = new LabelSSTRecord(in);
324: break;
325: case RKRecord.sid:
326: retval = new RKRecord(in);
327: break;
328: case NumberRecord.sid:
329: retval = new NumberRecord(in);
330: break;
331: case DBCellRecord.sid:
332: retval = new DBCellRecord(in);
333: break;
334: case WindowTwoRecord.sid:
335: retval = new WindowTwoRecord(in);
336: break;
337: case SelectionRecord.sid:
338: retval = new SelectionRecord(in);
339: break;
340: case ContinueRecord.sid:
341: retval = new ContinueRecord(in);
342: break;
343: case LabelRecord.sid:
344: retval = new LabelRecord(in);
345: break;
346: case MulRKRecord.sid:
347: retval = new MulRKRecord(in);
348: break;
349: case MulBlankRecord.sid:
350: retval = new MulBlankRecord(in);
351: break;
352: case BlankRecord.sid:
353: retval = new BlankRecord(in);
354: break;
355: case BoolErrRecord.sid:
356: retval = new BoolErrRecord(in);
357: break;
358: case ColumnInfoRecord.sid:
359: retval = new ColumnInfoRecord(in);
360: break;
361: case MergeCellsRecord.sid:
362: retval = new MergeCellsRecord(in);
363: break;
364: case AreaRecord.sid:
365: retval = new AreaRecord(in);
366: break;
367: case DataFormatRecord.sid:
368: retval = new DataFormatRecord(in);
369: break;
370: case BarRecord.sid:
371: retval = new BarRecord(in);
372: break;
373: case DatRecord.sid:
374: retval = new DatRecord(in);
375: break;
376: case PlotGrowthRecord.sid:
377: retval = new PlotGrowthRecord(in);
378: break;
379: case UnitsRecord.sid:
380: retval = new UnitsRecord(in);
381: break;
382: case FrameRecord.sid:
383: retval = new FrameRecord(in);
384: break;
385: case ValueRangeRecord.sid:
386: retval = new ValueRangeRecord(in);
387: break;
388: case SeriesListRecord.sid:
389: retval = new SeriesListRecord(in);
390: break;
391: case FontBasisRecord.sid:
392: retval = new FontBasisRecord(in);
393: break;
394: case FontIndexRecord.sid:
395: retval = new FontIndexRecord(in);
396: break;
397: case LineFormatRecord.sid:
398: retval = new LineFormatRecord(in);
399: break;
400: case AreaFormatRecord.sid:
401: retval = new AreaFormatRecord(in);
402: break;
403: case LinkedDataRecord.sid:
404: retval = new LinkedDataRecord(in);
405: break;
406: case FormulaRecord.sid:
407: retval = new FormulaRecord(in);
408: break;
409: case SheetPropertiesRecord.sid:
410: retval = new SheetPropertiesRecord(in);
411: break;
412: case DefaultDataLabelTextPropertiesRecord.sid:
413: retval = new DefaultDataLabelTextPropertiesRecord(in);
414: break;
415: case TextRecord.sid:
416: retval = new TextRecord(in);
417: break;
418: case AxisParentRecord.sid:
419: retval = new AxisParentRecord(in);
420: break;
421: case AxisLineFormatRecord.sid:
422: retval = new AxisLineFormatRecord(in);
423: break;
424: case SupBookRecord.sid:
425: retval = new SupBookRecord(in);
426: break;
427: case ExternSheetRecord.sid:
428: retval = new ExternSheetRecord(in);
429: break;
430: case SCLRecord.sid:
431: retval = new SCLRecord(in);
432: break;
433: case SeriesToChartGroupRecord.sid:
434: retval = new SeriesToChartGroupRecord(in);
435: break;
436: case AxisUsedRecord.sid:
437: retval = new AxisUsedRecord(in);
438: break;
439: case AxisRecord.sid:
440: retval = new AxisRecord(in);
441: break;
442: case CategorySeriesAxisRecord.sid:
443: retval = new CategorySeriesAxisRecord(in);
444: break;
445: case AxisOptionsRecord.sid:
446: retval = new AxisOptionsRecord(in);
447: break;
448: case TickRecord.sid:
449: retval = new TickRecord(in);
450: break;
451: case SeriesTextRecord.sid:
452: retval = new SeriesTextRecord(in);
453: break;
454: case ObjectLinkRecord.sid:
455: retval = new ObjectLinkRecord(in);
456: break;
457: case PlotAreaRecord.sid:
458: retval = new PlotAreaRecord(in);
459: break;
460: case SeriesIndexRecord.sid:
461: retval = new SeriesIndexRecord(in);
462: break;
463: case LegendRecord.sid:
464: retval = new LegendRecord(in);
465: break;
466: case LeftMarginRecord.sid:
467: retval = new LeftMarginRecord(in);
468: break;
469: case RightMarginRecord.sid:
470: retval = new RightMarginRecord(in);
471: break;
472: case TopMarginRecord.sid:
473: retval = new TopMarginRecord(in);
474: break;
475: case BottomMarginRecord.sid:
476: retval = new BottomMarginRecord(in);
477: break;
478: case PaletteRecord.sid:
479: retval = new PaletteRecord(in);
480: break;
481: case StringRecord.sid:
482: retval = new StringRecord(in);
483: break;
484: case NameRecord.sid:
485: retval = new NameRecord(in);
486: break;
487: case PaneRecord.sid:
488: retval = new PaneRecord(in);
489: break;
490: case SharedFormulaRecord.sid:
491: retval = new SharedFormulaRecord(in);
492: break;
493: case ObjRecord.sid:
494: retval = new ObjRecord(in);
495: break;
496: case TextObjectRecord.sid:
497: retval = new TextObjectRecord(in);
498: break;
499: case HorizontalPageBreakRecord.sid:
500: retval = new HorizontalPageBreakRecord(in);
501: break;
502: case VerticalPageBreakRecord.sid:
503: retval = new VerticalPageBreakRecord(in);
504: break;
505: case WriteProtectRecord.sid:
506: retval = new WriteProtectRecord(in);
507: break;
508: case FilePassRecord.sid:
509: retval = new FilePassRecord(in);
510: break;
511: case NoteRecord.sid:
512: retval = new NoteRecord(in);
513: break;
514: case FileSharingRecord.sid:
515: retval = new FileSharingRecord(in);
516: break;
517: default:
518: retval = new UnknownRecord(in);
519: }
520: return retval;
521: }
522:
523: /**
524: * Method setDump - hex dump out data or not.
525: *
526: *@param dump
527: */
528:
529: public void setDump(boolean dump) {
530: this .dump = dump;
531: }
532:
533: /**
534: * Method main with 1 argument just run straight biffview against given
535: * file<P>
536: *
537: * with 2 arguments where the second argument is "on" - run biffviewer<P>
538: *
539: * with hex dumps of records <P>
540: *
541: * with 2 arguments where the second argument is "bfd" just run a big fat
542: * hex dump of the file...don't worry about biffviewing it at all
543: * <p>
544: * Define the system property <code>poi.deserialize.escher</code> to turn on
545: * deserialization of escher records.
546: *
547: */
548: public static void main(String[] args) {
549: try {
550: System.setProperty("poi.deserialize.escher", "true");
551:
552: if (args.length == 0) {
553: System.out.println("Biff viewer needs a filename");
554: } else {
555: BiffViewer viewer = new BiffViewer(args);
556: if ((args.length > 1) && args[1].equals("on")) {
557: viewer.setDump(true);
558: }
559: if ((args.length > 1) && args[1].equals("bfd")) {
560: POIFSFileSystem fs = new POIFSFileSystem(
561: new FileInputStream(args[0]));
562: InputStream stream = fs
563: .createDocumentInputStream("Workbook");
564: int size = stream.available();
565: byte[] data = new byte[size];
566:
567: stream.read(data);
568: HexDump.dump(data, 0, System.out, 0);
569: } else {
570: viewer.run();
571: }
572: }
573: } catch (Exception e) {
574: e.printStackTrace();
575: }
576: }
577:
578: /**
579: * This record supports dumping of completed continue records.
580: */
581: static class RecordDetails {
582: short rectype, recsize;
583: int startloc;
584: Record record;
585:
586: public RecordDetails(short rectype, short recsize,
587: int startloc, Record record) {
588: this .rectype = rectype;
589: this .recsize = recsize;
590: this .startloc = startloc;
591: this .record = record;
592: }
593:
594: public short getRectype() {
595: return rectype;
596: }
597:
598: public short getRecsize() {
599: return recsize;
600: }
601:
602: public Record getRecord() {
603: return record;
604: }
605:
606: public void dump() throws IOException {
607: dumpNormal(record, startloc, rectype, recsize);
608: }
609: }
610:
611: static class BiffviewRecordInputStream extends RecordInputStream {
612: public BiffviewRecordInputStream(InputStream in) {
613: super (in);
614: }
615:
616: public void dumpBytes() {
617: HexDump.dump(this .data, 0, this.currentLength);
618: }
619: }
620:
621: }
|