/**
  * read an entire PDFObject. The intro line, which looks something like "4 0 obj" has already been
  * read.
  *
  * @param objNum the object number of the object being read, being the first number in the intro
  *     line (4 in "4 0 obj")
  * @param objGen the object generation of the object being read, being the second number in the
  *     intro line (0 in "4 0 obj").
  * @param decrypter the decrypter to use
  */
 private PDFObject readObjectDescription(int objNum, int objGen, PDFDecrypter decrypter)
     throws IOException {
   // we've already read the 4 0 obj bit.  Next thing up is the object.
   // object descriptions end with the keyword endobj
   long debugpos = this.buf.position();
   PDFObject obj = readObject(objNum, objGen, decrypter);
   // see if it's a dictionary.  If so, this could be a stream.
   PDFObject endkey = readObject(objNum, objGen, decrypter);
   if (endkey.getType() != PDFObject.KEYWORD && endkey.getType() != PDFObject.STREAM) {
     PDFDebugger.debug(
         "WARNING: Expected 'stream' or 'endobj' but was "
             + endkey.getType()
             + " "
             + String.valueOf(endkey.getStringValue()));
   }
   if (obj.getType() == PDFObject.DICTIONARY
       && endkey.getStringValue() != null
       && endkey.getStringValue().equals("stream")) {
     // skip until we see \n
     readLine();
     ByteBuffer data = readStream(obj);
     if (data == null) {
       data = ByteBuffer.allocate(0);
     }
     obj.setStream(data);
     endkey = readObject(objNum, objGen, decrypter);
   }
   // at this point, obj is the object, keyword should be "endobj"
   String endcheck = endkey.getStringValue();
   if (endcheck == null || !endcheck.equals("endobj")) {
     PDFDebugger.debug("WARNING: object at " + debugpos + " didn't end with 'endobj'");
   }
   obj.setObjectId(objNum, objGen);
   return obj;
 }
  /**
   * read the stream portion of a PDFObject. Calls decodeStream to un-filter the stream as
   * necessary.
   *
   * @param dict the dictionary associated with this stream.
   * @return a ByteBuffer with the encoded stream data
   */
  private ByteBuffer readStream(PDFObject dict) throws IOException {
    // pointer is at the start of a stream.  read the stream and
    // decode, based on the entries in the dictionary
    PDFObject lengthObj = dict.getDictRef("Length");
    int length = -1;
    if (lengthObj != null) {
      length = lengthObj.getIntValue();
    }
    if (length < 0) {
      throw new PDFParseException("Unknown length for stream");
    }

    // slice the data
    int start = this.buf.position();
    ByteBuffer streamBuf = this.buf.slice();
    streamBuf.limit(length);

    // move the current position to the end of the data
    this.buf.position(this.buf.position() + length);
    int ending = this.buf.position();

    if (!nextItemIs("endstream")) {
      PDFDebugger.debug("read " + length + " chars from " + start + " to " + ending);
      throw new PDFParseException("Stream ended inappropriately");
    }

    return streamBuf;
    // now decode stream
    // return PDFDecoder.decodeStream(dict, streamBuf);
  }
 public static void main(String[] args) {
   if (args.length > 0) {
     String command = args[0];
     String[] arguments = new String[args.length - 1];
     System.arraycopy(args, 1, arguments, 0, arguments.length);
     boolean exitAfterCallingMain = true;
     try {
       if (command.equals("ConvertColorspace")) {
         ConvertColorspace.main(arguments);
       } else if (command.equals("Decrypt")) {
         Decrypt.main(arguments);
       } else if (command.equals("Encrypt")) {
         Encrypt.main(arguments);
       } else if (command.equals("ExtractText")) {
         ExtractText.main(arguments);
       } else if (command.equals("Overlay")) {
         Overlay.main(arguments);
       } else if (command.equals("PrintPDF")) {
         PrintPDF.main(arguments);
       } else if (command.equals("PDFDebugger")) {
         PDFDebugger.main(arguments);
         exitAfterCallingMain = false;
       } else if (command.equals("PDFMerger")) {
         PDFMerger.main(arguments);
       } else if (command.equals("PDFReader")) {
         PDFReader.main(arguments);
         exitAfterCallingMain = false;
       } else if (command.equals("PDFSplit")) {
         PDFSplit.main(arguments);
       } else if (command.equals("PDFToImage")) {
         PDFToImage.main(arguments);
       } else if (command.equals("TextToPDF")) {
         TextToPDF.main(arguments);
       } else if (command.equals("WriteDecodedDoc")) {
         WriteDecodedDoc.main(arguments);
       } else {
         showMessageAndExit();
       }
       if (exitAfterCallingMain) {
         System.exit(0);
       }
     } catch (Exception e) {
       System.err.println(command + " failed with the following exception:");
       e.printStackTrace();
       System.exit(1);
     }
   } else {
     showMessageAndExit();
   }
 }