Package org.pdfclown.files

Source Code of org.pdfclown.files.File$ResolvedObject

/*
  Copyright 2006-2010 Stefano Chizzolini. http://www.pdfclown.org

  Contributors:
    * Stefano Chizzolini (original code developer, http://www.stefanochizzolini.it)

  This file should be part of the source code distribution of "PDF Clown library"
  (the Program): see the accompanying README files for more info.

  This Program is free software; you can redistribute it and/or modify it under the terms
  of the GNU Lesser General Public License as published by the Free Software Foundation;
  either version 3 of the License, or (at your option) any later version.

  This Program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY,
  either expressed or implied; without even the implied warranty of MERCHANTABILITY or
  FITNESS FOR A PARTICULAR PURPOSE. See the License for more details.

  You should have received a copy of the GNU Lesser General Public License along with this
  Program (see README files); if not, go to the GNU website (http://www.gnu.org/licenses/).

  Redistribution and use, with or without modification, are permitted provided that such
  redistributions retain the above copyright notice, license and disclaimer, along with
  this list of conditions.
*/

package org.pdfclown.files;

import java.io.Closeable;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Random;

import org.pdfclown.Version;
import org.pdfclown.VersionEnum;
import org.pdfclown.bytes.FileInputStream;
import org.pdfclown.bytes.IInputStream;
import org.pdfclown.bytes.IOutputStream;
import org.pdfclown.bytes.OutputStream;
import org.pdfclown.documents.Document;
import org.pdfclown.documents.Document.Configuration.XRefModeEnum;
import org.pdfclown.objects.IPdfIndirectObject;
import org.pdfclown.objects.PdfDataObject;
import org.pdfclown.objects.PdfDictionary;
import org.pdfclown.objects.PdfDirectObject;
import org.pdfclown.objects.PdfIndirectObject;
import org.pdfclown.objects.PdfName;
import org.pdfclown.objects.PdfObject;
import org.pdfclown.objects.PdfReference;
import org.pdfclown.tokens.FileFormatException;
import org.pdfclown.tokens.Reader;
import org.pdfclown.tokens.Reader.FileInfo;
import org.pdfclown.tokens.Writer;
import org.pdfclown.util.NotImplementedException;

/**
  PDF file representation.

  @author Stefano Chizzolini (http://www.stefanochizzolini.it)
  @since 0.0.0
  @version 0.1.0
*/
public final class File
  implements Closeable
{
  // <class>
  // <classes>
  public static final class ResolvedObject<T extends PdfDataObject>
  {
    public final T dataObject;
    public final PdfIndirectObject container;

    private ResolvedObject(
      T dataObject,
      PdfIndirectObject container
      )
    {
      this.dataObject = dataObject;
      this.container = container;
    }
  }
  // </classes>

  // <static>
  // <fields>
  private static Random hashCodeGenerator = new Random();
  // </fields>

  // <interface>
  // <public>
  /**
    Forces a generic object to be expressed as its corresponding data object.
  */
  public static PdfDataObject resolve(
    PdfObject object
    )
  {
    if(object instanceof IPdfIndirectObject)
      return ((IPdfIndirectObject)object).getDataObject();
    else
      return (PdfDataObject)object;
  }

  /**
    Resolves a generic object.
  */
  @SuppressWarnings("unchecked")
  public static <T extends PdfDataObject> ResolvedObject<T> resolve(
    PdfObject object,
    IPdfIndirectObject container
    )
  {
    if(object == null)
      return null;
    else if(object instanceof IPdfIndirectObject)
    {
      IPdfIndirectObject indirectObject = (IPdfIndirectObject)object;
      return new ResolvedObject<T>((T)indirectObject.getDataObject(),indirectObject.getIndirectObject());
    }
    else
      return new ResolvedObject<T>((T)object,container.getIndirectObject());
  }

  /**
    Forces a direct object to be updated (whether possible).
  */
  public static boolean update(
    PdfDirectObject object
    )
  {
    /*
      NOTE: Only PDF references are able to be updated. Other direct types
      are dependent on their respective containers for update.
    */
    if(object instanceof PdfReference)
    {
      ((PdfReference)object).getIndirectObject().update();
      return true;
    }
    else
      return false;
  }
  // </public>
  // </interface>
  // </static>

  // <dynamic>
  // <fields>
  private Document document;
  private int hashCode = hashCodeGenerator.nextInt();
  private IndirectObjects indirectObjects;
  private String path;
  private Reader reader;
  private PdfDictionary trailer;
  private Version version;
  // </fields>

  // <constructors>
  public File(
    )
  {
    version = VersionEnum.PDF14.getVersion();
    trailer = new PdfDictionary();
    indirectObjects = new IndirectObjects(this, null);
    document = new Document(this);
  }

  public File(
    String path
    ) throws FileFormatException,
      java.io.FileNotFoundException
  {
    this(
      new FileInputStream(
        new java.io.RandomAccessFile(path,"r")
        )
      );
    this.path = path;
  }

  public File(
    IInputStream stream
    ) throws FileFormatException
  {
    reader = new Reader(stream, this);

    FileInfo info = reader.readInfo();
    version = info.getVersion();
    trailer = info.getTrailer();
    if(trailer.containsKey(PdfName.Encrypt)) // Encrypted file.
      throw new NotImplementedException("Encrypted files are currently not supported.");

    indirectObjects = new IndirectObjects(this, info.getXrefEntries());
    document = new Document(trailer.get(PdfName.Root));
    document.getConfiguration().setXrefMode(PdfName.XRef.equals(trailer.get(PdfName.Type)) ? XRefModeEnum.Compressed : XRefModeEnum.Plain);
  }
  // </constructors>

  // <interface>
  // <public>
  /**
    Gets the high-level representation of the file content.
  */
  public Document getDocument(
    )
  {return document;}

  /**
    Gets the indirect objects collection.
  */
  public IndirectObjects getIndirectObjects(
    )
  {return indirectObjects;}

  /**
    Gets the data reader backing this file.

    @return <code>null</code> in case of newly-created file.
  */
  public Reader getReader(
    )
  {return reader;}

  /**
    Gets the file trailer.
  */
  public PdfDictionary getTrailer(
    )
  {return trailer;}

  /**
    Gets the file header version [PDF:1.6:3.4.1].
    <p>This property represents just the original file version; to get the actual version,
    use the {@link org.pdfclown.documents.Document#getVersion() Document.getVersion} method.</p>
  */
  public Version getVersion(
    )
  {return version;}

  @Override
  public int hashCode(
    )
  {return hashCode;}

  /**
    Registers an <b>internal data object</b>.

    @since 0.0.4
  */
  public PdfReference register(
    PdfDataObject object
    )
  {return indirectObjects.add(object).getReference();}

  /**
    Serializes the file to the current file-system path using the {@link SerializationModeEnum#Standard standard serialization mode}.
  */
  public void save(
    ) throws IOException
  {save(SerializationModeEnum.Standard);}

  /**
    Serializes the file to the current file-system path.

    @param mode Serialization mode.
  */
  public void save(
    SerializationModeEnum mode
    ) throws IOException
  {
    if(!new java.io.File(path).exists())
      throw new FileNotFoundException("No valid source path available.");

    /*
      NOTE: The document file cannot be directly overwritten
      as it's locked for reading by the open stream;
      its update is therefore delayed to its disposal,
      when the temporary file will overwrite it (see close() method).
    */
    save(getTempPath(), mode);
  }

  /**
    Serializes the file to the specified file-system path.

    @param path Target path.
    @param mode Serialization mode.
  */
  public void save(
    String path,
    SerializationModeEnum mode
    ) throws IOException
  {
    save(
      new java.io.File(path),
      mode
      );
  }

  /**
    Serializes the file to the specified file-system file.

    @param file Target file.
    @param mode Serialization mode.
  */
  public void save(
    java.io.File file,
    SerializationModeEnum mode
    ) throws IOException
  {
    OutputStream outputStream;
    java.io.BufferedOutputStream baseOutputStream;
    try
    {
      file.createNewFile();
      baseOutputStream = new java.io.BufferedOutputStream(
        new java.io.FileOutputStream(file)
        );
      outputStream = new OutputStream(baseOutputStream);
    }
    catch(Exception e)
    {throw new IOException(file.getPath() + " file couldn't be created.",e);}
    try
    {
      save(
        outputStream,
        mode
        );
      baseOutputStream.flush();
      baseOutputStream.close();
    }
    catch(Exception e)
    {throw new IOException(file.getPath() + " file writing has failed.",e);}
  }

  /**
    Serializes the file to the specified stream.
    <p>It's caller responsibility to close the stream after this method ends.</p>

    @param stream Target stream.
    @param mode Serialization mode.
  */
  public void save(
    IOutputStream stream,
    SerializationModeEnum mode
    )
  {
    Writer writer = Writer.get(this, stream);
    writer.write(mode);
  }

  /**
    Unregisters an <b>internal object</b>.

    @since 0.0.5
  */
  public void unregister(
    PdfReference reference
    )
  {indirectObjects.remove(reference.getObjectNumber());}

  // <Closeable>
  @Override
  public void close(
    ) throws IOException
  {
    if(reader != null)
    {
      reader.close();
      reader = null;

      /*
        NOTE: If the temporary file exists (see save() method),
        it must overwrite the document file.
      */
      java.io.File sourceFile = new java.io.File(getTempPath());
      if(sourceFile.exists())
      {
        java.io.File targetFile = new java.io.File(path);
        targetFile.delete();
        sourceFile.renameTo(targetFile);
      }
    }
  }
  // </Closeable>
  // </public>

  // <protected>
  @Override
  protected void finalize(
    ) throws Throwable
  {
    try
    {close();}
    finally
    {super.finalize();}
  }
  // </protected>

  // <private>
  private String getTempPath(
    )
  {return (path == null ? null : path + ".tmp");}
  // </private>
  // </interface>
  // </dynamic>
  // </class>
}
TOP

Related Classes of org.pdfclown.files.File$ResolvedObject

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.