From commits-return-8553-apmail-sis-commits-archive=sis.apache.org@sis.apache.org Sun Dec 25 10:54:43 2016 Return-Path: X-Original-To: apmail-sis-commits-archive@www.apache.org Delivered-To: apmail-sis-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 5868A199BB for ; Sun, 25 Dec 2016 10:54:43 +0000 (UTC) Received: (qmail 55136 invoked by uid 500); 25 Dec 2016 10:54:43 -0000 Delivered-To: apmail-sis-commits-archive@sis.apache.org Received: (qmail 55126 invoked by uid 500); 25 Dec 2016 10:54:42 -0000 Mailing-List: contact commits-help@sis.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: sis-dev@sis.apache.org Delivered-To: mailing list commits@sis.apache.org Received: (qmail 55117 invoked by uid 99); 25 Dec 2016 10:54:42 -0000 Received: from Unknown (HELO svn01-us-west.apache.org) (209.188.14.144) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 25 Dec 2016 10:54:42 +0000 Received: from svn01-us-west.apache.org (localhost [127.0.0.1]) by svn01-us-west.apache.org (ASF Mail Server at svn01-us-west.apache.org) with ESMTP id 37E6C3A0252 for ; Sun, 25 Dec 2016 10:54:42 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1776002 [1/2] - in /sis/branches/JDK8/storage: sis-storage/src/main/java/org/apache/sis/internal/storage/ sis-storage/src/main/java/org/apache/sis/storage/ sis-xmlstore/src/main/java/org/apache/sis/internal/gpx/ sis-xmlstore/src/main/java/... Date: Sun, 25 Dec 2016 10:54:41 -0000 To: commits@sis.apache.org From: desruisseaux@apache.org X-Mailer: svnmailer-1.0.9 Message-Id: <20161225105442.37E6C3A0252@svn01-us-west.apache.org> Author: desruisseaux Date: Sun Dec 25 10:54:40 2016 New Revision: 1776002 URL: http://svn.apache.org/viewvc?rev=1776002&view=rev Log: Complete the revision of GPXReader for most parts except having 2 or more stream opened concurrently. Added: sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Markable.java - copied, changed from r1776001, sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Trackable.java sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/OutputType.java - copied, changed from r1775863, sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/InputType.java Removed: sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Trackable.java Modified: sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelData.java sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelDataInput.java sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelImageInputStream.java sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/FeatureStore.java sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStore.java sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/storage/InputStreamAdapter.java sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/gpx/GPXReader.java sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/gpx/GPXStore.java sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/StaxDataStore.java sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/StaxStreamIO.java sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/StaxStreamReader.java sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/StaxStreamWriter.java sis/branches/JDK8/storage/sis-xmlstore/src/test/java/org/apache/sis/internal/gpx/GPXReaderTest.java sis/branches/JDK8/storage/sis-xmlstore/src/test/java/org/apache/sis/internal/gpx/GPXWriterTest.java sis/branches/JDK8/storage/sis-xmlstore/src/test/resources/org/apache/sis/internal/gpx/1.0/metadata.xml sis/branches/JDK8/storage/sis-xmlstore/src/test/resources/org/apache/sis/internal/gpx/1.0/route.xml sis/branches/JDK8/storage/sis-xmlstore/src/test/resources/org/apache/sis/internal/gpx/1.0/track.xml sis/branches/JDK8/storage/sis-xmlstore/src/test/resources/org/apache/sis/internal/gpx/1.0/waypoint.xml sis/branches/JDK8/storage/sis-xmlstore/src/test/resources/org/apache/sis/internal/gpx/1.1/metadata.xml sis/branches/JDK8/storage/sis-xmlstore/src/test/resources/org/apache/sis/internal/gpx/1.1/route.xml sis/branches/JDK8/storage/sis-xmlstore/src/test/resources/org/apache/sis/internal/gpx/1.1/track.xml sis/branches/JDK8/storage/sis-xmlstore/src/test/resources/org/apache/sis/internal/gpx/1.1/waypoint.xml Modified: sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelData.java URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelData.java?rev=1776002&r1=1776001&r2=1776002&view=diff ============================================================================== --- sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelData.java [UTF-8] (original) +++ sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelData.java [UTF-8] Sun Dec 25 10:54:40 2016 @@ -37,7 +37,7 @@ import static org.apache.sis.util.Argume * @version 0.5 * @module */ -public abstract class ChannelData implements Trackable { +public abstract class ChannelData implements Markable { /** * Number of bits needed for storing the bit offset in {@link #bitPosition}. * The following condition must hold: Modified: sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelDataInput.java URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelDataInput.java?rev=1776002&r1=1776001&r2=1776002&view=diff ============================================================================== --- sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelDataInput.java [UTF-8] (original) +++ sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelDataInput.java [UTF-8] Sun Dec 25 10:54:40 2016 @@ -27,14 +27,12 @@ import java.nio.LongBuffer; import java.nio.FloatBuffer; import java.nio.DoubleBuffer; import java.nio.channels.ReadableByteChannel; +import java.nio.channels.SeekableByteChannel; import org.apache.sis.util.resources.Errors; import org.apache.sis.util.Debug; import static org.apache.sis.util.ArgumentChecks.ensureBetween; -// Branch-dependent imports -import java.nio.channels.SeekableByteChannel; - /** * Provides convenience methods for working with a ({@link ReadableByteChannel}, {@link ByteBuffer}) pair. Modified: sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelImageInputStream.java URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelImageInputStream.java?rev=1776002&r1=1776001&r2=1776002&view=diff ============================================================================== --- sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelImageInputStream.java [UTF-8] (original) +++ sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelImageInputStream.java [UTF-8] Sun Dec 25 10:54:40 2016 @@ -21,12 +21,10 @@ import java.io.IOException; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.channels.ReadableByteChannel; +import java.nio.channels.SeekableByteChannel; import javax.imageio.stream.IIOByteBuffer; import javax.imageio.stream.ImageInputStream; -// Branch-dependent imports -import java.nio.channels.SeekableByteChannel; - /** * Adds the missing methods in {@code ChannelDataInput} for implementing the {@code ImageInputStream} interface. @@ -57,12 +55,12 @@ public class ChannelImageInputStream ext /** * Creates a new input stream for the given channel and using the given buffer. * - * @param filename A file identifier used only for formatting error message. - * @param channel The channel from where data are read. - * @param buffer The buffer where to copy the data. - * @param filled {@code true} if the buffer already contains data, or {@code false} if it needs - * to be initially filled with some content read from the channel. - * @throws IOException If an error occurred while reading the channel. + * @param filename a file identifier used only for formatting error message. + * @param channel the channel from where data are read. + * @param buffer the buffer where to copy the data. + * @param filled {@code true} if the buffer already contains data, or {@code false} if it needs + * to be initially filled with some content read from the channel. + * @throws IOException if an error occurred while reading the channel. */ public ChannelImageInputStream(final String filename, final ReadableByteChannel channel, final ByteBuffer buffer, final boolean filled) throws IOException @@ -75,8 +73,8 @@ public class ChannelImageInputStream ext * This constructor is invoked when we need to change the implementation class * from {@code ChannelDataInput} to {@code ChannelImageInputStream}. * - * @param input The existing instance from which to takes the channel and buffer. - * @throws IOException If an error occurred while reading the channel. + * @param input the existing instance from which to takes the channel and buffer. + * @throws IOException if an error occurred while reading the channel. */ public ChannelImageInputStream(final ChannelDataInput input) throws IOException { super(input.filename, input.channel, input.buffer, true); @@ -86,7 +84,7 @@ public class ChannelImageInputStream ext * Sets the desired byte order for future reads of data values from this stream. * The default value is {@link ByteOrder#BIG_ENDIAN}. * - * @param byteOrder The new {@linkplain #buffer buffer} byte order. + * @param byteOrder the new {@linkplain #buffer buffer} byte order. */ @Override public final void setByteOrder(final ByteOrder byteOrder) { @@ -97,7 +95,7 @@ public class ChannelImageInputStream ext * Returns the byte order with which data values will be read from this stream. * This is the {@linkplain #buffer buffer} byte order. * - * @return The {@linkplain #buffer buffer} byte order. + * @return the {@linkplain #buffer buffer} byte order. */ @Override public final ByteOrder getByteOrder() { @@ -107,8 +105,8 @@ public class ChannelImageInputStream ext /** * Returns the length of the stream (in bytes), or -1 if unknown. * - * @return The length of the stream (in bytes), or -1 if unknown. - * @throws IOException If an error occurred while fetching the stream length. + * @return the length of the stream (in bytes), or -1 if unknown. + * @throws IOException if an error occurred while fetching the stream length. */ @Override public final long length() throws IOException { @@ -126,8 +124,8 @@ public class ChannelImageInputStream ext * return readByte() != 0; * } * - * @return The value of the next boolean from the stream. - * @throws IOException If an error (including EOF) occurred while reading the stream. + * @return the value of the next boolean from the stream. + * @throws IOException if an error (including EOF) occurred while reading the stream. */ @Override public final boolean readBoolean() throws IOException { @@ -137,8 +135,8 @@ public class ChannelImageInputStream ext /** * Reads in a string that has been encoded using a UTF-8 string. * - * @return The string reads from the stream. - * @throws IOException If an error (including EOF) occurred while reading the stream. + * @return the string reads from the stream. + * @throws IOException if an error (including EOF) occurred while reading the stream. */ @Override public final String readUTF() throws IOException { @@ -156,8 +154,8 @@ public class ChannelImageInputStream ext * This method is provided for compliance with the {@link java.io.DataInput} interface, * but is generally not recommended. * - * @return The next line, or {@code null} if the EOF has been reached. - * @throws IOException If an error occurred while reading. + * @return the next line, or {@code null} if the EOF has been reached. + * @throws IOException if an error occurred while reading. */ @Override public final String readLine() throws IOException { @@ -189,8 +187,8 @@ loop: while ((c = read()) >= 0) { * Returns the next byte from the stream as an unsigned integer between 0 and 255, * or -1 if we reached the end of stream. * - * @return The next byte as an unsigned integer, or -1 on end of stream. - * @throws IOException If an error occurred while reading the stream. + * @return the next byte as an unsigned integer, or -1 on end of stream. + * @throws IOException if an error occurred while reading the stream. */ @Override public final int read() throws IOException { @@ -205,9 +203,9 @@ loop: while ((c = read()) >= 0) { * return read(dest, 0, dest.length); * } * - * @param dest An array of bytes to be written to. - * @return The number of bytes actually read, or -1 on EOF. - * @throws IOException If an error occurred while reading. + * @param dest an array of bytes to be written to. + * @return the number of bytes actually read, or -1 on EOF. + * @throws IOException if an error occurred while reading. */ @Override public final int read(final byte[] dest) throws IOException { @@ -219,11 +217,11 @@ loop: while ((c = read()) >= 0) { * starting at index {@code offset}. If no bytes can be read because the end of the stream * has been reached, -1 is returned. * - * @param dest An array of bytes to be written to. - * @param offset The starting position within {@code dest} to write. - * @param length The maximum number of bytes to read. - * @return The number of bytes actually read, or -1 on EOF. - * @throws IOException If an error occurred while reading. + * @param dest an array of bytes to be written to. + * @param offset the starting position within {@code dest} to write. + * @param length the maximum number of bytes to read. + * @return the number of bytes actually read, or -1 on EOF. + * @throws IOException if an error occurred while reading. */ @Override public final int read(final byte[] dest, int offset, int length) throws IOException { @@ -245,9 +243,9 @@ loop: while ((c = read()) >= 0) { * {@code IIOByteBuffer} to indicate the byte array, offset, and length where * the data may be found. * - * @param dest The buffer to be written to. - * @param length The maximum number of bytes to read. - * @throws IOException If an error occurred while reading. + * @param dest the buffer to be written to. + * @param length the maximum number of bytes to read. + * @throws IOException if an error occurred while reading. */ @Override public final void readBytes(final IIOByteBuffer dest, int length) throws IOException { @@ -262,9 +260,9 @@ loop: while ((c = read()) >= 0) { * Skips over n bytes of data from the input stream. * This implementation does not skip more bytes than the buffer capacity. * - * @param n Maximal number of bytes to skip. - * @return Number of bytes actually skipped. - * @throws IOException If an error occurred while reading. + * @param n maximal number of bytes to skip. + * @return number of bytes actually skipped. + * @throws IOException if an error occurred while reading. */ @Override public final int skipBytes(int n) throws IOException { @@ -283,9 +281,9 @@ loop: while ((c = read()) >= 0) { * Advances the current stream position by the given amount of bytes. * The bit offset is reset to 0 by this method. * - * @param n The number of bytes to seek forward. - * @return The number of bytes skipped. - * @throws IOException If an error occurred while skipping. + * @param n the number of bytes to seek forward. + * @return the number of bytes skipped. + * @throws IOException if an error occurred while skipping. */ @Override public final long skipBytes(final long n) throws IOException { @@ -300,7 +298,7 @@ loop: while ((c = read()) >= 0) { * flushBefore(getStreamPosition()); * } * - * @throws IOException If an I/O error occurred. + * @throws IOException if an I/O error occurred. */ @Override public final void flush() throws IOException { @@ -346,7 +344,7 @@ loop: while ((c = read()) >= 0) { /** * Closes the {@linkplain #channel}. * - * @throws IOException If an error occurred while closing the channel. + * @throws IOException if an error occurred while closing the channel. */ @Override public final void close() throws IOException { Modified: sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/FeatureStore.java URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/FeatureStore.java?rev=1776002&r1=1776001&r2=1776002&view=diff ============================================================================== --- sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/FeatureStore.java [UTF-8] (original) +++ sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/FeatureStore.java [UTF-8] Sun Dec 25 10:54:40 2016 @@ -17,6 +17,7 @@ package org.apache.sis.internal.storage; import org.apache.sis.storage.DataStore; import org.apache.sis.storage.StorageConnector; +import org.apache.sis.storage.DataStoreException; // Branch-dependent imports import java.util.stream.Stream; @@ -39,8 +40,9 @@ public abstract class FeatureStore exten * Creates a new instance for the given storage (typically file or database). * * @param connector information about the storage (URL, stream, reader instance, etc). + * @throws DataStoreException if an error occurred while creating the data store for the given storage. */ - protected FeatureStore(final StorageConnector connector) { + protected FeatureStore(final StorageConnector connector) throws DataStoreException { super(connector); } @@ -48,6 +50,7 @@ public abstract class FeatureStore exten * Returns the stream of features. * * @return a stream over all features in the file. + * @throws DataStoreException if an error occurred while creating the feature stream. */ - public abstract Stream getFeatures(); + public abstract Stream getFeatures() throws DataStoreException; } Copied: sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Markable.java (from r1776001, sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Trackable.java) URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Markable.java?p2=sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Markable.java&p1=sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Trackable.java&r1=1776001&r2=1776002&rev=1776002&view=diff ============================================================================== --- sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Trackable.java [UTF-8] (original) +++ sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Markable.java [UTF-8] Sun Dec 25 10:54:40 2016 @@ -21,9 +21,8 @@ import java.nio.InvalidMarkException; /** - * Stream reader or writer capable to keep trace of its position. - * The stream does not need to be able to seek at arbitrary positions. - * However it may support nested marks. + * Stream reader or writer capable to mark its current position and reset to that position later. + * The stream shall support nested marks. * *
Use case: * this interface can be used when we need to move to a previously marked position, but we do not know how many nested @@ -41,7 +40,7 @@ import java.nio.InvalidMarkException; * @version 0.8 * @module */ -public interface Trackable { +public interface Markable { /** * Returns the current byte position of the stream. * Modified: sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStore.java URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStore.java?rev=1776002&r1=1776001&r2=1776002&view=diff ============================================================================== --- sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStore.java [UTF-8] (original) +++ sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStore.java [UTF-8] Sun Dec 25 10:54:40 2016 @@ -66,11 +66,12 @@ public abstract class DataStore implemen /** * Creates a new instance for the given storage (typically file or database). * - * @param connector information about the storage (URL, stream, reader instance, etc). + * @param connector information about the storage (URL, stream, reader instance, etc). + * @throws DataStoreException if an error occurred while creating the data store for the given storage. * * @since 0.8 */ - protected DataStore(final StorageConnector connector) { + protected DataStore(final StorageConnector connector) throws DataStoreException { ArgumentChecks.ensureNonNull("connector", connector); locale = Locale.getDefault(Locale.Category.DISPLAY); listeners = new WarningListeners<>(this); Modified: sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/storage/InputStreamAdapter.java URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/storage/InputStreamAdapter.java?rev=1776002&r1=1776001&r2=1776002&view=diff ============================================================================== --- sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/storage/InputStreamAdapter.java [UTF-8] (original) +++ sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/storage/InputStreamAdapter.java [UTF-8] Sun Dec 25 10:54:40 2016 @@ -19,18 +19,18 @@ package org.apache.sis.storage; import java.io.InputStream; import java.io.IOException; import javax.imageio.stream.ImageInputStream; -import org.apache.sis.internal.storage.Trackable; +import org.apache.sis.internal.storage.Markable; /** - * Wraps a {@link ImageInputStream} as a standard {@link InputStream}. + * Wraps an {@link ImageInputStream} as a standard {@link InputStream}. * * @author Martin Desruisseaux (IRD) * @since 0.4 * @version 0.8 * @module */ -final class InputStreamAdapter extends InputStream implements Trackable { +final class InputStreamAdapter extends InputStream implements Markable { /** * The data input stream. */ Modified: sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/gpx/GPXReader.java URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/gpx/GPXReader.java?rev=1776002&r1=1776001&r2=1776002&view=diff ============================================================================== --- sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/gpx/GPXReader.java [UTF-8] (original) +++ sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/gpx/GPXReader.java [UTF-8] Sun Dec 25 10:54:40 2016 @@ -101,11 +101,12 @@ public class GPXReader extends StaxStrea * Creates a new GPX reader for the given data store. * The {@link #initialize(boolean)} method must be invoked after this constructor. * - * @param owner the data store for which this reader is created. + * @param owner the data store for which this reader is created. * @throws DataStoreException if the input type is not recognized. * @throws XMLStreamException if an error occurred while opening the XML file. + * @throws IOException if an error occurred while preparing the input stream. */ - public GPXReader(final GPXStore owner) throws DataStoreException, XMLStreamException { + public GPXReader(final GPXStore owner) throws DataStoreException, XMLStreamException, IOException { super(owner); types = Types.DEFAULT; } Modified: sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/gpx/GPXStore.java URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/gpx/GPXStore.java?rev=1776002&r1=1776001&r2=1776002&view=diff ============================================================================== --- sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/gpx/GPXStore.java [UTF-8] (original) +++ sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/gpx/GPXStore.java [UTF-8] Sun Dec 25 10:54:40 2016 @@ -16,14 +16,14 @@ */ package org.apache.sis.internal.gpx; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; +import java.io.IOException; +import java.net.URISyntaxException; +import javax.xml.bind.JAXBException; import javax.xml.stream.XMLStreamException; import org.apache.sis.internal.xml.StaxDataStore; -import org.apache.sis.setup.OptionKey; -import org.apache.sis.storage.DataStoreException; import org.apache.sis.storage.StorageConnector; -import org.apache.sis.util.ArgumentChecks; +import org.apache.sis.storage.DataStoreException; +import org.apache.sis.storage.DataStoreContentException; import org.apache.sis.util.Version; import org.opengis.metadata.Metadata; @@ -54,17 +54,24 @@ public class GPXStore extends StaxDataSt static final Version V1_1 = new Version("1.1"); /** - * The file encoding. Actually used only by the writer; ignored by the reader. + * Version of the GPX file, or {@code null} if unknown. + */ + private Version version; + + /** + * {@code true} if the {@linkplain #metadata} field has been initialized. + * Note that metadata after initialization may still be {@code null}. */ - final Charset encoding; + private boolean initialized; /** * The metadata, or {@code null} if not yet parsed. */ - private transient Metadata metadata; + private Metadata metadata; /** - * Iterator over the features. + * If a reader has been created for parsing the {@linkplain #metadata} and has not yet been used + * for iterating over the features, that reader. Otherwise {@code null}. */ private GPXReader reader; @@ -78,9 +85,6 @@ public class GPXStore extends StaxDataSt */ public GPXStore(final StorageConnector connector) throws DataStoreException { super(connector); - ArgumentChecks.ensureNonNull("connector", connector); - final Charset encoding = connector.getOption(OptionKey.ENCODING); - this.encoding = (encoding != null) ? encoding : StandardCharsets.UTF_8; } /** @@ -93,25 +97,60 @@ public class GPXStore extends StaxDataSt return "GPX"; } + /** + * Returns the GPX file version. + * + * @return the GPX file version, or {@code null} if none. + * @throws DataStoreException if an error occurred while reading the metadata. + */ + public synchronized Version getVersion() throws DataStoreException { + if (version == null) { + getMetadata(); + } + return version; + } + + /** + * Returns information about the dataset as a whole. + * + * @return information about the dataset, or {@code null} if none. + * @throws DataStoreException if an error occurred while reading the metadata. + */ @Override - public Metadata getMetadata() throws DataStoreException { - return null; // TODO + public synchronized Metadata getMetadata() throws DataStoreException { + if (!initialized) try { + initialized = true; + reader = new GPXReader(this); + version = reader.initialize(true); + metadata = reader.getMetadata(); + } catch (XMLStreamException | IOException | JAXBException e) { + throw new DataStoreException(e); + } catch (URISyntaxException | RuntimeException e) { + throw new DataStoreContentException(e); + } + return metadata; } /** * Returns the stream of features. * * @return a stream over all features in the CSV file. - * - * @todo Needs to reset the position when doing another pass on the features. + * @throws DataStoreException if an error occurred while creating the feature stream. */ @Override - public Stream getFeatures() { - return StreamSupport.stream(reader, false); - } - - final GPXReader reader() throws DataStoreException, XMLStreamException { - return reader = new GPXReader(this); + public synchronized Stream getFeatures() throws DataStoreException { + GPXReader r = reader; + reader = null; + if (r == null) try { + r = new GPXReader(this); + version = r.initialize(false); + } catch (XMLStreamException | IOException | JAXBException e) { + throw new DataStoreException(e); + } catch (URISyntaxException | RuntimeException e) { + throw new DataStoreContentException(e); + } + final Stream features = StreamSupport.stream(r, false); + return features.onClose(r); } /** @@ -125,7 +164,7 @@ public class GPXStore extends StaxDataSt reader = null; if (r != null) try { r.close(); - } catch (XMLStreamException e) { + } catch (Exception e) { final DataStoreException ds = new DataStoreException(e); try { super.close(); Copied: sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/OutputType.java (from r1775863, sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/InputType.java) URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/OutputType.java?p2=sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/OutputType.java&p1=sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/InputType.java&r1=1775863&r2=1776002&rev=1776002&view=diff ============================================================================== --- sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/InputType.java [UTF-8] (original) +++ sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/OutputType.java [UTF-8] Sun Dec 25 10:54:40 2016 @@ -16,135 +16,131 @@ */ package org.apache.sis.internal.xml; -import java.io.Reader; -import java.io.InputStream; -import javax.xml.stream.XMLEventReader; -import javax.xml.stream.XMLInputFactory; -import javax.xml.stream.XMLStreamReader; +import java.io.Writer; +import java.io.OutputStream; +import javax.xml.stream.XMLEventWriter; +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamWriter; import javax.xml.stream.XMLStreamException; -import javax.xml.transform.Source; -import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.sax.SAXSource; -import javax.xml.transform.stax.StAXSource; -import org.xml.sax.InputSource; +import javax.xml.transform.Result; +import javax.xml.transform.dom.DOMResult; +import javax.xml.transform.sax.SAXResult; +import javax.xml.transform.stax.StAXResult; +import org.xml.sax.ContentHandler; import org.w3c.dom.Node; /** - * Creates {@link XMLStreamReader} from a given input. This enumeration allows to analyze the input type - * only once before to create as many instances of {@link XMLStreamReader} as needed for that input. + * Creates {@link XMLStreamWriter} from a given output. This enumeration allows to analyze the output type + * only once before to create as many instances of {@link XMLStreamWriter} as needed for that output. * The enumeration order is the preference order (i.e. we will test if the object already implements the - * {@link XMLStreamReader} interface before to test for {@link InputStream}, {@link Reader}, etc.). - * - *

Some kinds of inputs can be used many time (for example {@link Node}). - * Other inputs can be used only once (for example {@link XMLEventReader}). - * For some inputs, it depends on whether the stream support marks.

+ * {@link XMLStreamWriter} interface before to test for {@link OutputStream}, {@link Writer}, etc.). * * @author Martin Desruisseaux (Geomatys) * @since 0.8 * @version 0.8 * @module */ -enum InputType { +enum OutputType { /** - * The input is already an instance of {@link XMLStreamReader}. - * That input is returned directly and can be used only once. + * The output is already an instance of {@link XMLStreamWriter}. + * That output is returned directly. */ - STAX(XMLStreamReader.class) { - @Override XMLStreamReader create(StaxDataStore ds, Object s) { - return (XMLStreamReader) s; + STAX(XMLStreamWriter.class) { + @Override XMLStreamWriter create(StaxDataStore ds, Object s) { + return (XMLStreamWriter) s; } }, /** - * The input is an instance of Java I/O {@link InputStream}. - * Decoding may depend on the {@linkplain StaxDataStore#encoding data store character encoding}. + * The output is an instance of Java I/O {@link OutputStream}. + * Encoding depends on the {@linkplain StaxDataStore#encoding data store character encoding}. */ - STREAM(InputStream.class) { - @Override XMLStreamReader create(StaxDataStore ds, Object s) throws XMLStreamException { - final XMLInputFactory f = ds.inputFactory(); - return (ds.encoding != null) ? f.createXMLStreamReader((InputStream) s, ds.encoding.name()) - : f.createXMLStreamReader((InputStream) s); + STREAM(OutputStream.class) { + @Override XMLStreamWriter create(StaxDataStore ds, Object s) throws XMLStreamException { + final XMLOutputFactory f = ds.outputFactory(); + return (ds.encoding != null) ? f.createXMLStreamWriter((OutputStream) s, ds.encoding.name()) + : f.createXMLStreamWriter((OutputStream) s); } }, /** - * The input is an instance of Java I/O {@link Reader}. + * The output is an instance of Java I/O {@link Writer}. */ - CHARACTERS(Reader.class) { - @Override XMLStreamReader create(StaxDataStore ds, Object s) throws XMLStreamException { - return ds.inputFactory().createXMLStreamReader((Reader) s); + CHARACTERS(Writer.class) { + @Override XMLStreamWriter create(StaxDataStore ds, Object s) throws XMLStreamException { + return ds.outputFactory().createXMLStreamWriter((Writer) s); } }, /** - * The input is an instance of XML {@link Source}, which is itself a wrapper around another kind of source. + * The output is an instance of XML {@link Result}, which is itself a wrapper around another kind of result. */ - SOURCE(Source.class) { - @Override XMLStreamReader create(StaxDataStore ds, Object s) throws XMLStreamException { - return ds.inputFactory().createXMLStreamReader((Source) s); + SOURCE(Result.class) { + @Override XMLStreamWriter create(StaxDataStore ds, Object s) throws XMLStreamException { + return ds.outputFactory().createXMLStreamWriter((Result) s); } }, /** - * The input is an instance of DOM {@link Node}. + * The output is an instance of DOM {@link Node}. */ NODE(Node.class) { - @Override XMLStreamReader create(StaxDataStore ds, Object s) throws XMLStreamException { - return ds.inputFactory().createXMLStreamReader(new DOMSource((Node) s)); + @Override XMLStreamWriter create(StaxDataStore ds, Object s) throws XMLStreamException { + return ds.outputFactory().createXMLStreamWriter(new DOMResult((Node) s)); } }, /** - * The input is an instance of SAX {@link InputSource}. + * The output is an instance of SAX {@link ContentHandler}. */ - SAX(InputSource.class) { - @Override XMLStreamReader create(StaxDataStore ds, Object s) throws XMLStreamException { - return ds.inputFactory().createXMLStreamReader(new SAXSource((InputSource) s)); + SAX(ContentHandler.class) { + @Override XMLStreamWriter create(StaxDataStore ds, Object s) throws XMLStreamException { + return ds.outputFactory().createXMLStreamWriter(new SAXResult((ContentHandler) s)); } }, /** - * The input is an instance of STAX {@link XMLEventReader}. + * The output is an instance of STAX {@link XMLEventWriter}. */ - EVENT(XMLEventReader.class) { - @Override XMLStreamReader create(StaxDataStore ds, Object s) throws XMLStreamException { - return ds.inputFactory().createXMLStreamReader(new StAXSource((XMLEventReader) s)); + EVENT(XMLEventWriter.class) { + @Override XMLStreamWriter create(StaxDataStore ds, Object s) throws XMLStreamException { + return ds.outputFactory().createXMLStreamWriter(new StAXResult((XMLEventWriter) s)); } }; /** - * The kind of input that this enumeration can handle. + * The kind of output that this enumeration can handle. */ - private final Class inputType; + private final Class outputType; /** - * Creates a new enumeration for the given type of input. + * Creates a new enumeration for the given type of output. */ - private InputType(final Class inputType) { - this.inputType = inputType; + private OutputType(final Class outputType) { + this.outputType = outputType; } /** - * Creates a XML reader for the given input. + * Creates a XML writer for the given output. * - * @param ds the data store for which to create reader instances. - * @param s the input stream or the storage object (URL, etc). - * @return the XML reader. - * @throws XMLStreamException if the XML reader creation failed. + * @param ds the data store for which to create writer instances. + * @param s the output stream or the storage object (URL, etc). + * @return the XML writer. + * @throws XMLStreamException if the XML writer creation failed. */ - abstract XMLStreamReader create(StaxDataStore ds, Object s) throws XMLStreamException; + abstract XMLStreamWriter create(StaxDataStore ds, Object s) throws XMLStreamException; /** - * Returns a {@code ReaderFactory} for the given input type. The {@code type} argument given to this method + * Returns a {@code WriterFactory} for the given output type. The {@code type} argument given to this method * shall be the class of the {@code s} argument to be given in {@link #create(StaxDataStore, Object)} calls. * - * @param type the type of the input stream or storage object (URL, etc). + * @param type the type of the output stream or storage object (URL, etc). * @return a factory for the given stream or storage type, or {@code null} if the given type is not recognized. */ - static InputType forType(final Class type) { - for (final InputType c : values()) { - if (c.inputType.isAssignableFrom(type)) { + static OutputType forType(final Class type) { + for (final OutputType c : values()) { + if (c.outputType.isAssignableFrom(type)) { return c; } } Modified: sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/StaxDataStore.java URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/StaxDataStore.java?rev=1776002&r1=1776001&r2=1776002&view=diff ============================================================================== --- sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/StaxDataStore.java [UTF-8] (original) +++ sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/StaxDataStore.java [UTF-8] Sun Dec 25 10:54:40 2016 @@ -20,15 +20,16 @@ import java.util.Locale; import java.util.TimeZone; import java.util.logging.Level; import java.util.logging.LogRecord; -import java.io.Closeable; import java.io.IOException; import java.io.InputStream; +import java.nio.file.Path; import java.nio.charset.Charset; import javax.xml.stream.Location; import javax.xml.stream.XMLReporter; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLOutputFactory; import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; import javax.xml.stream.XMLStreamException; import org.apache.sis.xml.XML; import org.apache.sis.setup.OptionKey; @@ -36,7 +37,9 @@ import org.apache.sis.storage.DataStore; import org.apache.sis.storage.StorageConnector; import org.apache.sis.storage.DataStoreException; import org.apache.sis.internal.storage.FeatureStore; +import org.apache.sis.internal.storage.Markable; import org.apache.sis.internal.util.AbstractMap; +import org.apache.sis.storage.DataStoreClosedException; import org.apache.sis.storage.UnsupportedStorageException; import org.apache.sis.util.logging.WarningListener; import org.apache.sis.util.resources.Errors; @@ -76,15 +79,15 @@ public abstract class StaxDataStore exte final Config configuration; /** - * The character encoding, or {@code null} if unspecified. + * The character encoding of the file content, or {@code null} if unspecified. * This is often (but not always) ignored at reading time, but taken in account at writing time. */ final Charset encoding; /** - * The storage object has given by the user. Can be {@link java.nio.file.Path}, {@link java.net.URL}, - * {@link java.io.InputStream}, {@link java.io.Reader}, {@link javax.xml.stream.XMLStreamReader}, - * {@link org.w3c.dom.Node} or some other types including the writer variants of above list. + * The storage object given by the user. May be {@link Path}, {@link java.net.URL}, {@link InputStream}, + * {@link java.io.OutputStream}, {@link java.io.Reader}, {@link java.io.Writer}, {@link XMLStreamReader}, + * {@link XMLStreamWriter}, {@link org.w3c.dom.Node} or some other types that the STAX framework can handle. * *

A {@code null} value means that this datastore has been {@linkplain #close() closed}.

* @@ -100,15 +103,28 @@ public abstract class StaxDataStore exte * * @see #close() */ - private Closeable stream; + private AutoCloseable stream; + + /** + * Position of the first byte to read in the {@linkplain #stream}, or a negative value if unknown. + * If the position is positive, then the stream should have been {@linkplain Markable#mark() marked} + * at that position by the constructor. + */ + private final long streamPosition; /** * The function in charge of producing a {@link XMLStreamReader} from the {@link #storage} or {@link #stream}. - * This field is {@code null} if the XML file is write only. + * This field is {@code null} if the XML file is write-only or if {@link #storage} is a {@link Path}. */ private final InputType storageToReader; /** + * The function in charge of producing a {@link XMLStreamWriter} for the {@link #storage} or {@link #stream}. + * This field is {@code null} if the XML file is read-only or if {@link #storage} is a {@link Path}. + */ + private final OutputType storageToWriter; + + /** * The STAX readers factory, created when first needed. * * @see #inputFactory() @@ -123,6 +139,17 @@ public abstract class StaxDataStore exte private XMLOutputFactory outputFactory; /** + * Whether the {@linkplain #stream} is currently in use by a {@link StaxStreamReader}. + * Value can be one of {@link #READY}, {@link #IN_USE} or {@link #FINISHED} constants. + */ + private byte state; + + /** + * Possible states for the {@link #state} field. + */ + private static final byte READY = 0, IN_USE = 1, FINISHED = 2; + + /** * Creates a new data store. * * @param connector information about the storage (URL, stream, etc). @@ -130,21 +157,45 @@ public abstract class StaxDataStore exte */ protected StaxDataStore(final StorageConnector connector) throws DataStoreException { super(connector); - name = connector.getStorageName(); - storage = connector.getStorage(); - encoding = connector.getOption(OptionKey.ENCODING); - configuration = new Config(connector); - InputType storageToReader = InputType.forType(storage.getClass()); + name = connector.getStorageName(); + storage = connector.getStorage(); + encoding = connector.getOption(OptionKey.ENCODING); + configuration = new Config(connector); + storageToWriter = OutputType.forType(storage.getClass()); + storageToReader = InputType.forType(storage.getClass()); if (storageToReader == null) { + /* + * We enter in this block if the storage type is not an input stream, DOM node, etc. + * It may be a file name, a URL, etc. Those types are not handled by InputType in + * order to give us a chance to use the existing InputStream instead than closing + * the connection and reopening a new one on the same URL. Another reason is that + * we will need to remember the stream created from the Path in order to close it. + * + * We ask for an InputStream, but StorageConnector implementation actually tries to create + * a ChannelDataInput if possible, which will allow us to create a ChannelDataOutput later + * if needed (and if the underlying channel is writable). + */ stream = connector.getStorageAs(InputStream.class); - if (stream != null) { - storageToReader = InputType.STREAM; - } - } else if (storage instanceof Closeable) { - stream = (Closeable) storage; + } else if (storage instanceof AutoCloseable) { + stream = (AutoCloseable) storage; } - this.storageToReader = storageToReader; connector.closeAllExcept(stream); + /* + * If possible, remember the position where data begin in the stream in order to allow reading + * the same data many time. We do not use the InputStream.mark(int) and reset() methods because + * we do not know which "read ahead limit" to use, and we do not know if the XMLStreamReader or + * other code will set their own mark (which could cause our reset() call to move to the wrong + * position). + */ + if (stream instanceof Markable) try { + final Markable m = (Markable) stream; + streamPosition = m.getStreamPosition(); + m.mark(); + } catch (IOException e) { + throw new DataStoreException(e); + } else { + streamPosition = -1; + } } /** @@ -249,10 +300,14 @@ public abstract class StaxDataStore exte public abstract String getFormatName(); /** - * Returns the factory for STAX readers. - * This method is invoked by {@link InputType#create(StaxDataStore, Object)}. + * Returns the factory for STAX readers. The same instance is returned for all {@code StaxDataStore} lifetime. + * Warnings emitted by readers created by this factory will be forwarded to the {@link #listeners}. + * + *

This method is indirectly invoked by {@link #createReader(StaxStreamReader)}, + * through a call to {@link InputType#create(StaxDataStore, Object)}.

*/ - final synchronized XMLInputFactory inputFactory() { + final XMLInputFactory inputFactory() { + assert Thread.holdsLock(this); if (inputFactory == null) { inputFactory = XMLInputFactory.newInstance(); inputFactory.setXMLReporter(configuration); @@ -261,10 +316,13 @@ public abstract class StaxDataStore exte } /** - * Returns the factory for STAX writers. - * This method is invoked by {@link OutputType#create(StaxDataStore, Object)}. + * Returns the factory for STAX writers. The same instance is returned for all {@code StaxDataStore} lifetime. + * + *

This method is indirectly invoked by {@link #createWriter(StaxStreamWriter)}, + * through a call to {@link OutputType#create(StaxDataStore, Object)}.

*/ - final synchronized XMLOutputFactory outputFactory() { + final XMLOutputFactory outputFactory() { + assert Thread.holdsLock(this); if (outputFactory == null) { outputFactory = XMLOutputFactory.newInstance(); outputFactory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, Boolean.TRUE); @@ -272,13 +330,87 @@ public abstract class StaxDataStore exte return outputFactory; } - protected final XMLStreamReader createReader() throws DataStoreException, XMLStreamException { - if (storageToReader == null) { - throw new UnsupportedStorageException(errors().getString(Errors.Keys.IllegalInputTypeForReader_2, - getFormatName(), Classes.getClass(storage))); + /** + * Creates a new XML stream reader for reading the document from its position at {@code StaxDataStore} + * creation time. If another {@code XMLStreamReader} has already been created before this method call, + * whether this method will succeed in creating a new reader depends on the storage type (e.g. file or + * input stream) or on whether the previous reader has been closed. + * + * @param target the reader which will store the {@code XMLStreamReader} reference. + * @return a new reader for reading the same XML data. + * @throws DataStoreException if the input type is not recognized or the data store is closed. + * @throws XMLStreamException if an error occurred while opening the XML file. + * @throws IOException if an error occurred while preparing the input stream. + */ + @SuppressWarnings("fallthrough") + final synchronized XMLStreamReader createReader(final StaxStreamReader target) + throws DataStoreException, XMLStreamException, IOException + { + Object input = storage; + if (input == null) { + throw new DataStoreClosedException(errors().getString(Errors.Keys.ClosedReader_1, getFormatName())); + } + /* + * If the storage given by the user was not one of InputStream, Reader or other type recognized + * by InputType, then maybe that storage was a Path, File or URL, in which case the constructor + * should have opened an InputStream for it. If not, then this was an unsupported storage type. + */ + InputType type = storageToReader; + if (type == null) { + type = InputType.STREAM; + if ((input = stream) == null) { + throw new UnsupportedStorageException(errors().getString(Errors.Keys.IllegalInputTypeForReader_2, + getFormatName(), Classes.getClass(storage))); + } } - // TODO: mark the stream - return storageToReader.create(this, stream != null ? stream : storage); + /* + * If the stream has already been used by a previous read operation, then we need to rewind + * it to the start position determined at construction time. It the stream does not support + * mark, then we can not re-read the data. + */ +reset: switch (state) { + default: { + throw new AssertionError(state); + } + case FINISHED: { + if (streamPosition >= 0) { + final Markable m = (Markable) input; + long p; + while ((p = m.getStreamPosition()) >= streamPosition) { + if (p == streamPosition) { + break reset; + } + m.reset(); + } + } + // Failed to reset the stream - fallthrough. + } + case IN_USE: { + // TODO: create a new stream here if we can. + throw new DataStoreException("Can not read twice."); + } + case READY: break; // Stream already at the data start; nothing to do. + } + final XMLStreamReader reader = type.create(this, input); + target.stream = stream; + state = IN_USE; + return reader; + } + + /** + * Invoked when {@link StaxStreamReader} finished to read XML document from the given stream. + * This method returns {@code true} if the caller should invoke {@link AutoCloseable#close()}, + * or {@code false} if this {@code StaxDataStore} may reuse that stream. + * + * @param finished the stream that has been used for reading XML document. + * @return whether the caller should invoke {@code finished.close()}. + */ + final synchronized boolean canClose(final AutoCloseable finished) { + if (finished != null && stream == finished) { + state = FINISHED; + return false; + } + return true; } /** @@ -296,14 +428,14 @@ public abstract class StaxDataStore exte */ @Override public synchronized void close() throws DataStoreException { - final Closeable s = stream; + final AutoCloseable s = stream; stream = null; storage = null; inputFactory = null; outputFactory = null; if (s != null) try { s.close(); - } catch (IOException e) { + } catch (Exception e) { throw new DataStoreException(e); } } Modified: sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/StaxStreamIO.java URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/StaxStreamIO.java?rev=1776002&r1=1776001&r2=1776002&view=diff ============================================================================== --- sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/StaxStreamIO.java [UTF-8] (original) +++ sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/StaxStreamIO.java [UTF-8] Sun Dec 25 10:54:40 2016 @@ -16,6 +16,8 @@ */ package org.apache.sis.internal.xml; +import java.io.IOException; +import javax.xml.stream.XMLStreamException; import org.apache.sis.util.ArgumentChecks; import org.apache.sis.util.resources.Errors; @@ -44,6 +46,13 @@ abstract class StaxStreamIO implements A protected final StaxDataStore owner; /** + * The underlying stream to close when this {@code StaxStreamIO} reader or writer is closed, + * or {@code null} if none. This may be the same reference than {@link StaxDataStore#stream}, + * but not necessarily if we had to create a new stream for reading the data one more time. + */ + AutoCloseable stream; + + /** * For sub-classes constructors. * * @param owner the data store for which this reader or writer is created. @@ -54,6 +63,22 @@ abstract class StaxStreamIO implements A } /** + * Closes the input or output stream and releases any resources used by this XML reader or writer. + * This reader or writer can not be used anymore after this method has been invoked. + * + * @throws XMLStreamException if an error occurred while releasing XML reader/writer resources. + * @throws IOException if an error occurred while closing the input or output stream. + */ + @Override + public void close() throws Exception { + final AutoCloseable s = stream; + stream = null; + if (owner.canClose(s)) { + s.close(); + } + } + + /** * Returns the error resources in the current locale. */ protected final Errors errors() { Modified: sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/StaxStreamReader.java URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/StaxStreamReader.java?rev=1776002&r1=1776001&r2=1776002&view=diff ============================================================================== --- sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/StaxStreamReader.java [UTF-8] (original) +++ sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/StaxStreamReader.java [UTF-8] Sun Dec 25 10:54:40 2016 @@ -100,7 +100,7 @@ import org.opengis.feature.Feature; * @version 0.8 * @module */ -public abstract class StaxStreamReader extends StaxStreamIO implements XMLStreamConstants, Spliterator { +public abstract class StaxStreamReader extends StaxStreamIO implements XMLStreamConstants, Spliterator, Runnable { /** * The XML stream reader. */ @@ -110,12 +110,14 @@ public abstract class StaxStreamReader e * Creates a new XML reader for the given data store. * * @param owner the data store for which this reader is created. - * @throws DataStoreException if the input type is not recognized. + * @throws DataStoreException if the input type is not recognized or the data store is closed. * @throws XMLStreamException if an error occurred while opening the XML file. + * @throws IOException if an error occurred while preparing the input stream. */ - protected StaxStreamReader(final StaxDataStore owner) throws DataStoreException, XMLStreamException { + @SuppressWarnings("ThisEscapedInObjectConstruction") + protected StaxStreamReader(final StaxDataStore owner) throws DataStoreException, XMLStreamException, IOException { super(owner); - reader = owner.createReader(); + reader = owner.createReader(this); // Okay because will not store the 'this' reference. } /** @@ -399,11 +401,29 @@ public abstract class StaxStreamReader e * Closes the input stream and releases any resources used by this XML reader. * This reader can not be used anymore after this method has been invoked. * - * @throws XMLStreamException if an error occurred while releasing XML reader/writer resources. + * @throws XMLStreamException if an error occurred while releasing XML reader resources. + * @throws IOException if an error occurred while closing the input stream. */ @Override - public void close() throws XMLStreamException { + public void close() throws Exception { reader.close(); + super.close(); + } + + /** + * Invokes {@link #close()} and wraps checked exceptions in a {@link BackingStoreException}. + * This method is defined for allowing this {@code StaxStreamReader} to be given to + * {@link java.util.stream.Stream#onClose(Runnable)}. + */ + @Override + public final void run() throws BackingStoreException { + try { + close(); + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + throw new BackingStoreException(e); + } } /** Modified: sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/StaxStreamWriter.java URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/StaxStreamWriter.java?rev=1776002&r1=1776001&r2=1776002&view=diff ============================================================================== --- sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/StaxStreamWriter.java [UTF-8] (original) +++ sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/StaxStreamWriter.java [UTF-8] Sun Dec 25 10:54:40 2016 @@ -187,12 +187,14 @@ public abstract class StaxStreamWriter e * This writer can not be used anymore after this method has been invoked. * * @throws XMLStreamException if an error occurred while releasing XML writer resources. + * @throws IOException if an error occurred while closing the output stream. */ @Override - public void close() throws XMLStreamException { + public void close() throws Exception { if (writer != null) { writer.close(); writer = null; } + super.close(); } }