This is an automated email from the ASF dual-hosted git repository. desruisseaux pushed a commit to branch 1.4.1 in repository https://gitbox.apache.org/repos/asf/sis.git
commit 1b00da34f0e41afd85a346ae0a25a3ef86d4f20e Author: Martin Desruisseaux <[email protected]> AuthorDate: Wed Jul 2 13:29:12 2025 +0200 Make the build compatible with Java 22. https://issues.apache.org/jira/browse/SIS-602 --- .../sis/storage/sql/postgis/RasterReader.java | 12 +- .../org/apache/sis/io/stream/ChannelDataInput.java | 3 - .../sis/io/stream/InputStreamArrayGetter.java | 133 --------------------- .../sis/io/stream/InputStreamArrayGetterTest.java | 68 ----------- .../sis/util/collection/FrequencySortedSet.java | 17 ++- .../apache/sis/util/collection/IntegerList.java | 50 +++++++- 6 files changed, 59 insertions(+), 224 deletions(-) diff --git a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/postgis/RasterReader.java b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/postgis/RasterReader.java index f71e3718db..ed27411c16 100644 --- a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/postgis/RasterReader.java +++ b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/postgis/RasterReader.java @@ -20,6 +20,7 @@ import java.util.List; import java.util.Arrays; import java.nio.ByteOrder; import java.nio.ByteBuffer; +import java.nio.channels.Channels; import java.io.InputStream; import java.io.IOException; import java.lang.reflect.Array; @@ -47,7 +48,6 @@ import org.apache.sis.coverage.grid.j2d.ColorModelFactory; import org.apache.sis.coverage.grid.j2d.ObservableImage; import org.apache.sis.referencing.CRS; import org.apache.sis.referencing.util.j2d.AffineTransform2D; -import org.apache.sis.io.stream.InputStreamArrayGetter; import org.apache.sis.io.stream.ChannelDataInput; import org.apache.sis.storage.sql.feature.InfoStatements; import org.apache.sis.util.internal.Constants; @@ -397,11 +397,9 @@ public final class RasterReader extends RasterFormat { * @throws IOException if an error occurred while reading data from the input stream. */ public ChannelDataInput channel(final InputStream input) throws IOException { - return InputStreamArrayGetter.channel("raster", input, () -> { - if (buffer == null) { - buffer = ByteBuffer.allocate(8192); - } - return buffer; - }); + if (buffer == null) { + buffer = ByteBuffer.allocate(8192); + } + return new ChannelDataInput("raster", Channels.newChannel(input), buffer, false); } } diff --git a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/io/stream/ChannelDataInput.java b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/io/stream/ChannelDataInput.java index 5f0c4c5c9e..d2b6e7a6fe 100644 --- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/io/stream/ChannelDataInput.java +++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/io/stream/ChannelDataInput.java @@ -84,9 +84,6 @@ public class ChannelDataInput extends ChannelData { * If the buffer already contains some data, then the {@code filled} argument shall be {@code true}. * Otherwise (e.g. if it is a newly created buffer), then {@code filled} shall be {@code false}. * - * <p><b>Tip:</b> - * for building a data input from an input stream, see {@link InputStreamArrayGetter}.</p> - * * @param filename a short identifier (typically a filename without path) used for formatting error message. * @param channel the channel from where data are read. * @param buffer the buffer where to copy the data. diff --git a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/io/stream/InputStreamArrayGetter.java b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/io/stream/InputStreamArrayGetter.java deleted file mode 100644 index 14287edf72..0000000000 --- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/io/stream/InputStreamArrayGetter.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.sis.io.stream; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.ByteArrayInputStream; -import java.nio.ByteBuffer; -import java.nio.channels.Channels; -import java.nio.channels.ReadableByteChannel; -import java.util.function.Supplier; -import org.apache.sis.util.logging.Logging; -import org.apache.sis.storage.base.StoreUtilities; - - -/** - * A hack for getting the backing array of an input stream if that array exists. - * This class searches the array in the following locations: - * - * <ul> - * <li>{@link ByteArrayInputStream#buf} together with offset and length. - * Those fields have {@code protected} access, so they are committed Java API. - * However as of Java 19, there is no public accessor for them.</li> - * </ul> - * - * @author Martin Desruisseaux (Geomatys) - */ -public final class InputStreamArrayGetter extends OutputStream { - /** - * The buffer wrapping the array, or {@code null} if unknown. - * This buffer is not read-only, but nevertheless should not be modified. - */ - private ByteBuffer buffer; - - /** - * Creates a pseudo output stream to use as a trick for getting the backing array. - */ - private InputStreamArrayGetter() { - } - - /** - * Whether it is hopefully safe to apply the trick used by this class for getting the backing array. - * The trick is that the {@link ByteArrayInputStream#transferTo(OutputStream)} implementation gives - * the backing array in argument in a call to {@link InputStream#write(byte[], int, int)} method. - * This is verified by looking at the OpenJDK source code, and presumed relatively stable because - * the code uses only protected fields and public methods, which are committed API. - * But because users could override the {@code transferTo(…)} method in a subclass, - * we rely on this strick only if the method implementation is the one provided by - * the standard {@link ByteArrayInputStream} class. - * - * @param input the input stream for which to verify the implementation class. - * @return whether the implementation is the OpenJDK one. - */ - private static boolean isKnownImplementation(final InputStream input) { - try { - return input.getClass().getMethod("transferTo", OutputStream.class).getDeclaringClass() == ByteArrayInputStream.class; - } catch (NoSuchMethodException e) { - // Should not happen because we requested a method which should exist. - Logging.unexpectedException(StoreUtilities.LOGGER, InputStreamArrayGetter.class, "isKnownImplementation", e); - return false; - } - } - - /** - * Creates a new data input for the given input stream. - * If the input stream is backed by an array, the array will be wrapped in a read-only mode. - * - * @param filename a short identifier (typically a filename without path) used for formatting error message. - * @param input the input stream from where data are read. - * @param bs supplier of the buffer where to copy the data. - * @return the data input using a readable channel. - * @throws IOException if an error occurred while reading the input stream. - */ - public static ChannelDataInput channel(final String filename, final InputStream input, final Supplier<ByteBuffer> bs) - throws IOException - { - if (isKnownImplementation(input)) { - final InputStreamArrayGetter getter = new InputStreamArrayGetter(); - input.transferTo(getter); - if (getter.buffer != null) { - return new ChannelDataInput(filename, getter.buffer); - } - } - final ReadableByteChannel channel = Channels.newChannel(input); - return new ChannelDataInput(filename, channel, bs.get(), false); - } - - /** - * Invoked by {@link ByteArrayInputStream#transferTo(OutputStream)}. - * We use this method as a callback for getting the underlying array. - * - * @param array the data. - * @param offset the start offset in the array. - * @param length the number of valid bytes in the array. - * @throws IOException if this method is invoked more than once. - */ - @Override - public void write(final byte[] array, final int offset, final int length) throws IOException { - if (buffer == null) { - buffer = ByteBuffer.wrap(array, offset, length); - } else { - super.write(array, offset, length); - } - } - - /** - * Should never be invoked. If this method is nevertheless invoked, - * then the {@link ByteArrayInputStream#transferTo(OutputStream)} - * implementation is not what we expected. - * - * @param b ignored. - * @throws IOException always thrown. - */ - @Override - public void write(int b) throws IOException { - throw new IOException("Unexpected implementation."); - } -} diff --git a/endorsed/src/org.apache.sis.storage/test/org/apache/sis/io/stream/InputStreamArrayGetterTest.java b/endorsed/src/org.apache.sis.storage/test/org/apache/sis/io/stream/InputStreamArrayGetterTest.java deleted file mode 100644 index 53d94125fc..0000000000 --- a/endorsed/src/org.apache.sis.storage/test/org/apache/sis/io/stream/InputStreamArrayGetterTest.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.sis.io.stream; - -import java.io.IOException; -import java.io.ByteArrayInputStream; - -// Test dependencies -import org.junit.Test; -import org.apache.sis.test.TestCase; - -import static org.junit.Assert.*; - - -/** - * Tests the {@link InputStreamArrayGetter} class. - * - * @author Martin Desruisseaux (Geomatys) - */ -public final class InputStreamArrayGetterTest extends TestCase { - /** - * Creates a new test case. - */ - public InputStreamArrayGetterTest() { - } - - /** - * Tests the creation of a channel data input which uses directly the array. - * - * @throws IOException if an error occurred while creating the channel data input. - */ - @Test - public void testDirectChannel() throws IOException { - final var array = new byte[20]; - for (int i=0; i<array.length; i++) { - array[i] = (byte) ((i ^ 5772) * 37); - } - final int offset = 7; - final var input = new ByteArrayInputStream(array, offset, 9); - final ChannelDataInput data = InputStreamArrayGetter.channel("Test", input, () -> { - throw new AssertionError("Should not create new buffer."); - }); - /* - * Replace a few values in the backing array AFTER the `ChannelDataInput` creation. - * If the data input does not wrap the array, the changes below would be unnoticed. - */ - array[offset + 1] = 99; // Replace 20. - array[offset + 4] = 100; // Replace -125. - final byte[] expected = {23, 99, 57, 94, 100, -128}; - for (int i=0; i<expected.length; i++) { - assertEquals(expected[i], data.readByte()); - } - } -} diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/collection/FrequencySortedSet.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/collection/FrequencySortedSet.java index 4e8a86aaa0..763d7b429a 100644 --- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/collection/FrequencySortedSet.java +++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/collection/FrequencySortedSet.java @@ -30,12 +30,12 @@ import org.apache.sis.util.ArgumentChecks; /** - * A set with elements ordered by the amount of time they were {@linkplain #add added}. + * A set with elements ordered by the amount of time they were added. * By default, less frequently added elements are first and most frequently added elements are last. * If some elements were added the same amount of time, then the iterator will traverse them in their * insertion order. * - * <p>An optional boolean argument in the constructor allows the construction of set in reversed order + * <p>An optional Boolean argument in the constructor allows the construction of set in reversed order * (most frequently added elements first, less frequently added last). This is similar but not identical * to creating a default {@code FrequencySortedSet} and iterating through it in reverse order. * The difference is that elements added the same amount of time will still be traversed in their insertion order.</p> @@ -50,7 +50,7 @@ import org.apache.sis.util.ArgumentChecks; * * @since 0.8 */ -public class FrequencySortedSet<E> extends AbstractSet<E> implements SortedSet<E>, Comparator<E>, Serializable { +public class FrequencySortedSet<E> extends AbstractSet<E> implements SortedSet<E>, Serializable { /** * For cross-version compatibility. */ @@ -336,7 +336,7 @@ public class FrequencySortedSet<E> extends AbstractSet<E> implements SortedSet<E */ @Override public Comparator<E> comparator() { - return FrequencySortedSet.this; + return FrequencySortedSet.this.comparator(); } /** @@ -347,11 +347,11 @@ public class FrequencySortedSet<E> extends AbstractSet<E> implements SortedSet<E ensureSorted(); elements = sorted; if (hasFrom) { - lower = Arrays.binarySearch(elements, fromElement, FrequencySortedSet.this); + lower = Arrays.binarySearch(elements, fromElement, comparator()); if (lower < 0) lower = ~lower; } if (hasTo) { - upper = Arrays.binarySearch(elements, toElement, FrequencySortedSet.this); + upper = Arrays.binarySearch(elements, toElement, comparator()); if (upper < 0) upper = ~upper; if (upper < lower) upper = lower; } else { @@ -576,15 +576,13 @@ public class FrequencySortedSet<E> extends AbstractSet<E> implements SortedSet<E /** * Returns the comparator used to order the elements in this set. - * For a {@code FrequencySortedSet}, the comparator is always {@code this}. * * <p>This method is final because the {@code FrequencySortedSet} implementation makes * assumptions on the comparator that would not hold if this method were overridden.</p> */ @Override - @SuppressWarnings("ReturnOfCollectionOrArrayField") public final Comparator<E> comparator() { - return this; + return this::compare; } /** @@ -596,7 +594,6 @@ public class FrequencySortedSet<E> extends AbstractSet<E> implements SortedSet<E * <p>This method is final because the {@code FrequencySortedSet} implementation makes * assumptions on the comparator that would not hold if this method were overridden.</p> */ - @Override public final int compare(final E o1, final E o2) { return signedFrequency(o1) - signedFrequency(o2); } diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/collection/IntegerList.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/collection/IntegerList.java index 9f526bc0b4..6031f276c5 100644 --- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/collection/IntegerList.java +++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/collection/IntegerList.java @@ -43,7 +43,7 @@ import org.apache.sis.util.internal.Numerics; * * @author Martin Desruisseaux (Geomatys) * @author Alexis Manin (Geomatys) - * @version 1.1 + * @version 1.5 * * @see org.apache.sis.math.Vector * @@ -273,6 +273,34 @@ public class IntegerList extends AbstractList<Integer> implements RandomAccess, return getInt(index); } + /** + * Gets the first element. + * + * @return the first element. + * @throws NoSuchElementException if this collection is empty. + * @since 1.4.1 + */ + public Integer getFirst() { + if (size != 0) { + return getUnchecked(0); + } + throw new NoSuchElementException(); + } + + /** + * Gets the last element. + * + * @return the last element. + * @throws NoSuchElementException if this collection is empty. + * @since 1.4.1 + */ + public Integer getLast() { + if (size != 0) { + return getUnchecked(size - 1); + } + throw new NoSuchElementException(); + } + /** * Returns the element at the given index as the {@code int} primitive type. * @@ -377,12 +405,28 @@ public class IntegerList extends AbstractList<Integer> implements RandomAccess, } /** - * Retrieves and remove the last element of this list. + * Retrieves and removes the first element of this list. + * + * @return the head of this list. + * @throws NoSuchElementException if this list is empty. + * + * @since 1.4.1 + */ + public Integer removeFirst() throws NoSuchElementException { + if (size != 0) { + modCount++; + return getUnchecked(0); + } + throw new NoSuchElementException(); + } + + /** + * Retrieves and removes the last element of this list. * * @return the tail of this list. * @throws NoSuchElementException if this list is empty. */ - public int removeLast() throws NoSuchElementException { + public Integer removeLast() throws NoSuchElementException { if (size != 0) { modCount++; return getUnchecked(--size);
