| /* ==================================================================== |
| Licensed to the Apache Software Foundation (ASF) under one or more |
| contributor license agreements. See the NOTICE file distributed with |
| this work for additional information regarding copyright ownership. |
| The ASF licenses this file to You under the Apache License, Version 2.0 |
| (the "License"); you may not use this file except in compliance with |
| the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| ==================================================================== */ |
| |
| package org.apache.poi.hdgf; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.io.InputStream; |
| |
| import org.apache.poi.POIReadOnlyDocument; |
| import org.apache.poi.hdgf.chunks.ChunkFactory; |
| import org.apache.poi.hdgf.pointers.Pointer; |
| import org.apache.poi.hdgf.pointers.PointerFactory; |
| import org.apache.poi.hdgf.streams.PointerContainingStream; |
| import org.apache.poi.hdgf.streams.Stream; |
| import org.apache.poi.hdgf.streams.StringsStream; |
| import org.apache.poi.hdgf.streams.TrailerStream; |
| import org.apache.poi.poifs.filesystem.DirectoryNode; |
| import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; |
| import org.apache.poi.poifs.filesystem.POIFSFileSystem; |
| import org.apache.poi.util.IOUtils; |
| import org.apache.poi.util.LittleEndian; |
| import org.apache.poi.util.LocaleUtil; |
| |
| /** |
| * See |
| * http://www.redferni.uklinux.net/visio/ |
| * http://www.gnome.ru/projects/docs/vsdocs.html |
| * http://www.gnome.ru/projects/docs/slide1.png |
| * http://www.gnome.ru/projects/docs/slide2.png |
| */ |
| public final class HDGFDiagram extends POIReadOnlyDocument { |
| private static final String VISIO_HEADER = "Visio (TM) Drawing\r\n"; |
| |
| private byte[] _docstream; |
| |
| private short version; |
| private long docSize; |
| |
| private Pointer trailerPointer; |
| private TrailerStream trailer; |
| |
| private ChunkFactory chunkFactory; |
| private PointerFactory ptrFactory; |
| |
| public HDGFDiagram(POIFSFileSystem fs) throws IOException { |
| this(fs.getRoot()); |
| } |
| public HDGFDiagram(NPOIFSFileSystem fs) throws IOException { |
| this(fs.getRoot()); |
| } |
| public HDGFDiagram(DirectoryNode dir) throws IOException { |
| super(dir); |
| |
| // Grab the document stream |
| InputStream is = dir.createDocumentInputStream("VisioDocument"); |
| _docstream = IOUtils.toByteArray(is); |
| is.close(); |
| |
| // Check it's really visio |
| String typeString = new String(_docstream, 0, 20, LocaleUtil.CHARSET_1252 ); |
| if(! typeString.equals(VISIO_HEADER)) { |
| throw new IllegalArgumentException("Wasn't a valid visio document, started with " + typeString); |
| } |
| |
| // Grab the version number, 0x1a -> 0x1b |
| version = LittleEndian.getShort(_docstream, 0x1a); |
| // Grab the document size, 0x1c -> 0x1f |
| docSize = LittleEndian.getUInt(_docstream, 0x1c); |
| // ??? 0x20 -> 0x23 |
| |
| // Create the Chunk+Pointer Factories for the document version |
| ptrFactory = new PointerFactory(version); |
| chunkFactory = new ChunkFactory(version); |
| |
| // Grab the pointer to the trailer |
| trailerPointer = ptrFactory.createPointer(_docstream, 0x24); |
| |
| // Now grab the trailer |
| trailer = (TrailerStream) |
| Stream.createStream(trailerPointer, _docstream, chunkFactory, ptrFactory); |
| |
| // Finally, find all our streams |
| trailer.findChildren(_docstream); |
| } |
| |
| /** |
| * Returns the TrailerStream, which is at the root of the |
| * tree of Streams. |
| */ |
| public TrailerStream getTrailerStream() { return trailer; } |
| /** |
| * Returns all the top level streams, which are the streams |
| * pointed to by the TrailerStream. |
| */ |
| public Stream[] getTopLevelStreams() { return trailer.getPointedToStreams(); } |
| public long getDocumentSize() { return docSize; } |
| |
| /** |
| * Prints out some simple debug on the base contents of the file. |
| * @see org.apache.poi.hdgf.dev.VSDDumper |
| */ |
| public void debug() { |
| System.err.println("Trailer is at " + trailerPointer.getOffset()); |
| System.err.println("Trailer has type " + trailerPointer.getType()); |
| System.err.println("Trailer has length " + trailerPointer.getLength()); |
| System.err.println("Trailer has format " + trailerPointer.getFormat()); |
| |
| for(int i=0; i<trailer.getPointedToStreams().length; i++) { |
| Stream stream = trailer.getPointedToStreams()[i]; |
| Pointer ptr = stream.getPointer(); |
| |
| System.err.println("Looking at pointer " + i); |
| System.err.println("\tType is " + ptr.getType() + "\t\t" + Integer.toHexString(ptr.getType())); |
| System.err.println("\tOffset is " + ptr.getOffset() + "\t\t" + Long.toHexString(ptr.getOffset())); |
| System.err.println("\tAddress is " + ptr.getAddress() + "\t" + Long.toHexString(ptr.getAddress())); |
| System.err.println("\tLength is " + ptr.getLength() + "\t\t" + Long.toHexString(ptr.getLength())); |
| System.err.println("\tFormat is " + ptr.getFormat() + "\t\t" + Long.toHexString(ptr.getFormat())); |
| System.err.println("\tCompressed is " + ptr.destinationCompressed()); |
| System.err.println("\tStream is " + stream.getClass()); |
| |
| if(stream instanceof PointerContainingStream) { |
| PointerContainingStream pcs = (PointerContainingStream)stream; |
| |
| if(pcs.getPointedToStreams() != null && pcs.getPointedToStreams().length > 0) { |
| System.err.println("\tContains " + pcs.getPointedToStreams().length + " other pointers/streams"); |
| for(int j=0; j<pcs.getPointedToStreams().length; j++) { |
| Stream ss = pcs.getPointedToStreams()[j]; |
| Pointer sptr = ss.getPointer(); |
| System.err.println("\t\t" + j + " - Type is " + sptr.getType() + "\t\t" + Integer.toHexString(sptr.getType())); |
| System.err.println("\t\t" + j + " - Length is " + sptr.getLength() + "\t\t" + Long.toHexString(sptr.getLength())); |
| } |
| } |
| } |
| |
| if(stream instanceof StringsStream) { |
| System.err.println("\t\t**strings**"); |
| StringsStream ss = (StringsStream)stream; |
| System.err.println("\t\t" + ss._getContentsLength()); |
| } |
| } |
| } |
| |
| /** |
| * For testing only |
| */ |
| public static void main(String args[]) throws Exception { |
| NPOIFSFileSystem pfs = new NPOIFSFileSystem(new File(args[0])); |
| HDGFDiagram hdgf = new HDGFDiagram(pfs); |
| hdgf.debug(); |
| hdgf.close(); |
| pfs.close(); |
| } |
| } |