sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
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 GMT
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 <var>n</var> 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, <i>etc</i>).
+     * @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<Feature> getFeatures();
+    public abstract Stream<Feature> 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.
  *
  * <div class="note"><b>Use case:</b>
  * 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, <i>etc</i>).
+     * @param  connector information about the storage (URL, stream, reader instance, <i>etc</i>).
+     * @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<Feature> getFeatures() {
-        return StreamSupport.stream(reader, false);
-    }
-
-    final GPXReader reader() throws DataStoreException, XMLStreamException {
-        return reader = new GPXReader(this);
+    public synchronized Stream<Feature> 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<Feature> 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}, <i>etc.</i>).
- *
- * <p>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.</p>
+ * {@link XMLStreamWriter} interface before to test for {@link OutputStream}, {@link Writer}, <i>etc.</i>).
  *
  * @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, <i>etc</i>).
-     * @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, <i>etc</i>).
+     * @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, <i>etc</i>).
+     * @param  type  the type of the output stream or storage object (URL, <i>etc</i>).
      * @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.
      *
      * <p>A {@code null} value means that this datastore has been {@linkplain #close() closed}.</p>
      *
@@ -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, <i>etc</i>).
@@ -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}.
+     *
+     * <p>This method is indirectly invoked by {@link #createReader(StaxStreamReader)},
+     * through a call to {@link InputType#create(StaxDataStore, Object)}.</p>
      */
-    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.
+     *
+     * <p>This method is indirectly invoked by {@link #createWriter(StaxStreamWriter)},
+     * through a call to {@link OutputType#create(StaxDataStore, Object)}.</p>
      */
-    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<Feature> {
+public abstract class StaxStreamReader extends StaxStreamIO implements XMLStreamConstants, Spliterator<Feature>, 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();
     }
 }



Mime
View raw message