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

gov.nasa.worldwind.ogc.kml.io.KMZInputStream Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2012 United States Government as represented by the Administrator of the
 * National Aeronautics and Space Administration.
 * All Rights Reserved.
 */

package gov.nasa.worldwind.ogc.kml.io;

import gov.nasa.worldwind.util.*;

import java.io.*;
import java.util.*;
import java.util.zip.*;

/**
 * Implements the {@link KMLDoc} interface for KMZ files read from a stream.
 *
 * @author tag
 * @version $Id: KMZInputStream.java 1171 2013-02-11 21:45:02Z dcollins $
 */
public class KMZInputStream implements KMLDoc
{
    /** The zip stream created for the specified input stream. */
    protected ZipInputStream zipStream;

    /**
     * The next entry to read from the input stream. This field refers to the first entry in the stream when the
     * constructor returns, and after each entry is copied to the temp dir it is updated to point to the subsequent
     * entry. If null, the stream contains no more entries.
     */
    protected ZipEntry currentEntry;

    /** A mapping of the files in the KMZ stream to their location in the temporary directory. */
    protected Map files;

    /** The directory to hold files copied from the stream. Both the directory and the files copied there are temporary. */
    protected File tempDir;

    /**
     * Constructs a KMZInputStream instance. Upon return, the new instance's current-entry field refers to the first
     * entry in the stream.
     *
     * @param sourceStream the input stream to read from.
     *
     * @throws IllegalArgumentException if the specified stream is null.
     * @throws java.io.IOException      if an error occurs while accessing the stream.
     */
    public KMZInputStream(InputStream sourceStream) throws IOException
    {
        if (sourceStream == null)
        {
            String message = Logging.getMessage("nullValue.InputStreamIsNull");
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }

        this.zipStream = new ZipInputStream(sourceStream);
        this.files = new HashMap();
        this.moveToNextEntry();
    }

    /**
     * Moves this stream to its next zip entry and updates this stream's current-entry field.
     *
     * @throws IOException if an exception occurs while attempting to more the stream to the next entry.
     */
    protected void moveToNextEntry() throws IOException
    {
        ZipEntry nextEntry = this.zipStream.getNextEntry();

        // Close the stream if there's nothing more to read from it.
        if (nextEntry == null && this.currentEntry != null)
            this.zipStream.close();

        this.currentEntry = nextEntry;
    }

    /**
     * Returns an {@link java.io.InputStream} to the first KML file within the stream.
     *
     * @return an input stream positioned to the first KML file in the stream, or null if the stream does not contain a
     *         KML file.
     *
     * @throws IOException if an error occurs while reading the stream.
     */
    public synchronized InputStream getKMLStream() throws IOException
    {
        // Iterate through the stream's entries to find the KML file. It will normally be the first entry, but there's
        // no guarantee of that. If another file is encountered before the KML file, copy it to temp dir created to
        // capture the KMZ document's directory hierarchy.

        while (this.currentEntry != null)
        {
            if (this.currentEntry.getName().toLowerCase().endsWith(".kml"))
            {
                String kmlEntryName = this.currentEntry.getName();
                this.copyCurrentEntryToTempDir(); // copies the current entry to a temp file and adds it to this.files
                File file = this.files.get(kmlEntryName);
                return file != null ? new FileInputStream(file) : null;
            }
            else
            {
                this.copyCurrentEntryToTempDir();
            }
        }

        return null;
    }

    /**
     * Returns an {@link InputStream} to a specified file within the KMZ stream. The file's path is resolved relative to
     * the internal root of the KMZ file represented by the stream.
     * 

* Note: Since relative references to files outside the stream have no meaning, this class does not resolve relative * references to files in other KMZ archives. For example, it does not resolve references like this: * ../other.kmz/file.png. * * @param path the path of the requested file. * * @return an input stream positioned to the start of the requested file, or null if the file does not exist or the * specified path is absolute. * * @throws IllegalArgumentException if the path is null. * @throws IOException if an error occurs while attempting to read the input stream. */ public synchronized InputStream getSupportFileStream(String path) throws IOException { // This method is called by the native WebView implementation to resolve resources in KMZ balloons. It may // not perform any synchronization with the EDT (such as calling invokeAndWait), or it will introduce a // potential deadlock when called by the WebView's native UI thread. if (path == null) { String message = Logging.getMessage("nullValue.FilePathIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } // Regardless of whether the next entry in the stream is the requested file, copy each entry encountered to // the temporary directory created to represent the directory hierarchy in the KMZ document. If the most // recently copied file is the requested file, return it and suspend reading and copying until it's again // necessary. This prevents bogging down performance until everything is copied. File file = files.get(path); if (file != null) return new FileInputStream(file); if (this.currentEntry == null) // no more entries in the zip stream return null; this.copyCurrentEntryToTempDir(); // If the file just copied is the one requested, a recursive call will pick it up immediately. return this.getSupportFileStream(path); } /** * Returns an absolute path to a specified file within the KMZ stream. The file's path is resolved relative to the * internal root of the KMZ file represented by the stream. *

* Note: Since relative references to files outside the stream have no meaning, this class does not resolve relative * references to files in other KMZ archives. For example, it does not resolve references like this: * ../other.kmz/file.png. * * @param path the path of the requested file. * * @return an absolute path for the requested file, or null if the file does not exist or the specified path is * absolute. * * @throws IllegalArgumentException if the path is null. * @throws IOException if an error occurs while attempting to create a temporary file. */ public synchronized String getSupportFilePath(String path) throws IOException { // This method is called by the native WebView implementation to resolve resources in KMZ balloons. It may // not perform any synchronization with the EDT (such as calling invokeAndWait), or it will introduce a // potential deadlock when called by the WebView's native UI thread. if (path == null) { String message = Logging.getMessage("nullValue.FilePathIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } // Regardless of whether the next entry in the stream is the requested file, copy each entry encountered to // the temporary directory created to represent the directory hierarchy in the KMZ document. If the most // recently copied file is the requested file, return it and suspend reading and copying until it's again // necessary. This prevents bogging down performance until everything is copied. File file = files.get(path); if (file != null) return file.getPath(); if (this.currentEntry == null) // no more entries in the zip stream return null; this.copyCurrentEntryToTempDir(); // If the file just copied is the one requested, a recursive call will pick it up immediately. If not, the next // entry will be retrieved. return this.getSupportFilePath(path); } /** * Copies a file from the input stream to the temporary area created to represent the KMZ contents. If that area * does not yet exists, it is created. *

* Note: This method should be called only by another synchronized method of this instance. * * @throws IOException if an error occurs during the copy. */ protected void copyCurrentEntryToTempDir() throws IOException { if (this.currentEntry == null) // no more entries in the zip stream return; if (this.currentEntry.isDirectory()) { this.moveToNextEntry(); return; } if (this.tempDir == null) this.tempDir = WWIO.makeTempDir(); if (this.tempDir == null) // unlikely to occur, but define a reaction { String message = Logging.getMessage("generic.UnableToCreateTempDir", this.tempDir); Logging.logger().warning(message); return; } // Create the path for the temp file and ensure all directories leading to it exist. String tempFileName = this.tempDir + File.separator + this.currentEntry.getName(); WWIO.makeParentDirs(tempFileName); // Copy the entry. File outFile = new File(tempFileName); outFile.deleteOnExit(); WWIO.saveBuffer(WWIO.readStreamToBuffer(this.zipStream), outFile); this.files.put(this.currentEntry.getName(), outFile); // Increment the stream to the next entry. this.moveToNextEntry(); } // // public static void main(String[] args) // { // try // { // InputStream is = new FileInputStream(new File("/Users/tag/NoBackup/kml/ocean_model_locations.kmz")); // KMZInputStream zStream = new KMZInputStream(is); // InputStream kmlStream = zStream.getKMLStream(); // is = zStream.getSupportFileStream("files/camera_mode.png"); // is = zStream.getSupportFileStream("files/3DBuildingsLayer3.png"); // is = zStream.getSupportFileStream("files/camera_mode.png"); // if (kmlStream != null) // { // KMLRoot root = KMLRoot.create(kmlStream); // root.parse(); // } // } // catch (IOException e) // { // e.printStackTrace(); // } // catch (XMLStreamException e) // { // e.printStackTrace(); // } // } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy