All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.odftoolkit.odfdom.pkg.OdfPackageDocument Maven / Gradle / Ivy

/**
 * **********************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
 *
 * Copyright 2008, 2010 Oracle and/or its affiliates. All rights reserved.
 *
 * Use is subject to license terms.
 *
 * Licensed 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. You can also
 * obtain a copy of the License at http://odftoolkit.org/docs/license.txt
 *
 * 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.odftoolkit.odfdom.pkg;

import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory;
import org.apache.jena.util.ResourceUtils;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URI;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.transform.Templates;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.URIResolver;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamResult;
import org.odftoolkit.odfdom.pkg.rdfa.Util;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;

/**
 *
 * The package layer described by the ODF 1.2 Package specification is
 * independent of the above ODF XML layer described by the ODF 1.2 XML Schema
 * specification.
 *
 * Still the abstract concept of documents exist in the ODF Package layer.
 */
public class OdfPackageDocument implements Closeable {

	private static final String TWO_DOTS = "..";
	private static final String SLASH = "/";
	private static final String COLON = ":";
	private static final String EMPTY_STRING = "";
	/**
	 * The path of the root document
	 */
	protected static final String ROOT_DOCUMENT_PATH = EMPTY_STRING;
	private Resolver mResolver;
	/**
	 * The ODF package containing the document
	 */
	protected OdfPackage mPackage;
	/**
	 * The internal path to the document relative to the ODF package
	 */
	protected String mDocumentPathInPackage;
	/**
	 * The mediatype of the ODF package document. Note: Not necessarily an ODF
	 * XML mediatype as specified in ODF 1.2 part1
	 */
	protected String mDocumentMediaType;
	private static Templates mRdfFileExtractionTemplate;

	/**
	 * Creates a new OdfPackageDocument.
	 *
	 * @param pkg - the ODF Package that contains the document. A baseURL is
	 * being generated based on its location.
	 * @param internalPath - the directory path within the package from where
	 * the document should be loaded.
	 * @param mediaTypeString - media type of stream. If unknown null can be
	 * used.
	 */
	protected OdfPackageDocument(OdfPackage pkg, String internalPath, String mediaTypeString) {
		if (pkg != null) {
			mPackage = pkg;
			mDocumentPathInPackage = internalPath;
			this.setMediaTypeString(mediaTypeString);
			pkg.cacheDocument(this, internalPath);
		} else {
			throw new IllegalArgumentException("No Package provided for new document!");
		}
	}

	/**
	 * Loads an OdfPackageDocument from the provided path.
	 *
	 * 

OdfPackageDocument relies on the file being available for read access * over the whole lifecycle of OdfDocument.

* * @param documentPath - the path from where the document can be loaded * @return the OpenDocument from the given path or NULL if the media type is * not supported by ODFDOM. * @throws java.lang.Exception - if the document could not be created. */ public static OdfPackageDocument loadDocument(String documentPath) throws Exception { OdfPackage pkg = OdfPackage.loadPackage(documentPath); return pkg.loadDocument(ROOT_DOCUMENT_PATH); } /** * Returns an embedded OdfPackageDocument from the given package path. * * @param documentPath to the document within the package. The path is * relative the current document path. * @return an embedded OdfPackageDocument */ public OdfPackageDocument loadSubDocument(String documentPath) { String internalPath = this.getDocumentPath() + documentPath; internalPath = OdfPackage.normalizeDirectoryPath(internalPath); return mPackage.loadDocument(internalPath); } /** * @return the mediatype of this document */ public String getMediaTypeString() { return mDocumentMediaType; } /** * @param mediaTypeString for the mediatype of this document */ protected final void setMediaTypeString(String mediaTypeString) { mDocumentMediaType = mediaTypeString; if (isRootDocument()) { mPackage.setMediaTypeString(mediaTypeString); } } /** * Sets the OdfPackage that contains this OdfPackageDocument. * * @param pkg the OdfPackage that contains this OdfPackageDocument */ void setPackage(OdfPackage pkg) { mPackage = pkg; } /** * Retreives the OdfPackage for this OdfPackageDocument. * * @return the OdfPackage that contains this OdfPackageDocument. */ public OdfPackage getPackage() { return mPackage; } /** * Set the relative path for an embedded ODF document. * * @param path to directory of the embedded ODF document (relative to ODF * package root). */ String setDocumentPath(String path) { mDocumentPathInPackage = normalizeDocumentPath(path); return mDocumentPathInPackage; } /** * Get the relative path for an embedded ODF document. * * @return path to the directory of the embedded ODF document (relative to * ODF package root). */ public String getDocumentPath() { return mDocumentPathInPackage; } /** * Removes an embedded ODF document from the ODF Package. All files within * the embedded document directory will be removed. * * @param internDocumentPath path to the directory of the embedded ODF * document (always relative to the package path of the current document). */ public void removeDocument(String internDocumentPath) { mPackage.removeDocument(mDocumentPathInPackage + internDocumentPath); } /** * @return true if the document is at the root level of the package */ public boolean isRootDocument() { if (getDocumentPath().equals(ROOT_DOCUMENT_PATH)) { return true; } else { return false; } } /** * Checks if the given reference is a reference, which points outside the * ODF package Only relative path are allowed with the exception of a single * slash '/' representing the root document. * * @param ref the file reference to be checked * @return true if the reference is an package external reference */ protected static boolean isExternalReference(String ref) { boolean isExternalReference = false; // if the reference is a external relative filePath.. if (ref.startsWith(TWO_DOTS) || // or absolute filePath AND not root document) ref.startsWith(SLASH) && !ref.equals(SLASH) || // or absolute IRI ref.contains(COLON)) { isExternalReference = true; } return isExternalReference; } /** * Ensure the document path for is valid and gurantee unique encoding by * normalizing the path. * * @see OdfPackage#normalizeDirectoryPath(java.lang.String) * @param documentPath the destination directory of the document. The path * should end with a '/'. * @return the documentPath after normalization. */ protected static String normalizeDocumentPath(String documentPath) { String dirPath = OdfPackage.normalizeDirectoryPath(documentPath); //package path should not start with '/'. if (dirPath.startsWith(SLASH) && !dirPath.equals(SLASH)) { dirPath = dirPath.substring(1); } return dirPath; } /** * Save the document to given path. * *

When save the embedded document to a stand alone document, all the * file entries of the embedded document will be copied to a new document * package. If the embedded document is outside of the current document * directory, you have to embed it to the sub directory and refresh the link * of the embedded document. You should reload it from the given path to get * the saved embedded document. * * @param documentPath - the path to the package document * @throws java.lang.Exception if the document could not be saved */ public void save(String documentPath) throws Exception { File f = new File(documentPath); save(f); } /** * Save the document to a given file. * *

If the input file has been cached (this is the case when loading from * an InputStream), the input file can be overwritten.

* *

Otherwise it's allowed to overwrite the input file as long as the same * path name is used that was used for loading (no symbolic link foo2.odt * pointing to the loaded file foo1.odt, no network path X:\foo.odt pointing * to the loaded file D:\foo.odt).

* *

When saving the embedded document to a stand alone document, all files * of the embedded document will be copied to a new document package. If the * embedded document is outside of the current document directory, you have * to embed it to the sub directory and refresh the link of the embedded * document. You should reload it from the given file to get the saved * embedded document. * * @param file - the file to save the document * @throws java.lang.Exception if the document could not be saved */ public void save(File file) throws Exception { mPackage.save(file); } /** * Flush the existing DOM to the document to get in advantage of the recent * changes from the DOM */ protected void flushDoms() { mPackage.flushDoms(this); } /** * Embed an OdfPackageDocument to the current OdfPackageDocument. All the * file entries of child document will be embedded as well to the current * document package. * * @param newDocument the OdfPackageDocument to be embedded. * @param documentPath to the directory the ODF document should be inserted * (relative to the root of this document). */ public void insertDocument(OdfPackageDocument newDocument, String documentPath) { newDocument.flushDoms(); // if the existing document already has a subdirtory if had to be added to the absolute mPackage.insertDocument(newDocument, mDocumentPathInPackage + documentPath); } /** * @param internalPath path to the XML file relative to package root * @return the typed DOM of the given file */ public OdfFileDom getFileDom(String internalPath) throws Exception { String normalizeDocumentPath = getDocumentPath(); if (!isRootDocument()) { normalizeDocumentPath = normalizeDocumentPath(normalizeDocumentPath); } return OdfFileDom.newFileDom(this, normalizeDocumentPath + internalPath); } /** * Get EntityResolver to be used in XML Parsers which can resolve content * inside the OdfPackage */ EntityResolver getEntityResolver() { if (mResolver == null) { mResolver = new Resolver(mPackage); } return mResolver; } /** * Get URIResolver to be used in XSL Transformations which can resolve * content inside the OdfPackage */ URIResolver getURIResolver() { if (mResolver == null) { mResolver = new Resolver(mPackage); } return mResolver; } /** * Close the OdfPackageDocument, its OdfPackage and release all temporary * created data. Acter execution of this method, this class is no longer * usable. Do this as the last action to free resources. Closing an already * closed document has no effect. */ public void close() { mPackage.close(); // set all member variables explicit to null mPackage = null; } /** * Helper class to receive an ODF document template for new documents from * the environment (ie. from the JAR via classloader) */ protected static class Resource { private String name; public Resource(String name) { this.name = name; } public InputStream createInputStream() { InputStream in = OdfPackageDocument.class.getResourceAsStream(this.name); if (in == null) { Logger.getLogger(OdfPackageDocument.class.getName()).log(Level.SEVERE, "Could not find resource: {0}", this.name); } return in; } } /** * Extracts RDF Metadata triple from XML files * * @param internalPath path to the XML file relative to package root * @return RDF Metadata through GRDDL XSLT of given XML file */ public Model getXMLFileMetadata(String internalPath) { Model rdfModel = null; try { ByteArrayOutputStream out = new ByteArrayOutputStream(); OdfXMLHelper helper = new OdfXMLHelper(); if (mRdfFileExtractionTemplate == null) { String filePath = "file:" + OdfPackageDocument.class.getClassLoader().getResource("grddl/odf2rdf.xsl").getPath(); URI uri = new URI(filePath); InputSource inputSource = new InputSource(uri.toString()); mRdfFileExtractionTemplate = TransformerFactory.newInstance().newTemplates(new SAXSource(inputSource)); } helper.transform(this.getPackage(), internalPath, mRdfFileExtractionTemplate, new StreamResult(out)); String RDFBaseUri = Util.getRDFBaseUri(this.getPackage().getBaseURI(), internalPath); rdfModel = ModelFactory.createDefaultModel(); rdfModel.read(new InputStreamReader(new ByteArrayInputStream(out.toByteArray()), "utf-8"), RDFBaseUri); // remove the last SLASH at the end of the RDFBaseUri: // test_rdfmeta.odt/ --> test_rdfmeta.odt ResourceUtils.renameResource(rdfModel.getResource(RDFBaseUri), RDFBaseUri.substring(0, RDFBaseUri.length() - 1)); } catch (Exception ex) { Logger.getLogger(OdfPackageDocument.class.getName()).log(Level.SEVERE, null, ex); } return rdfModel; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy